From 22e678378fcbca41f752b470c1caf49e16b81a78 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Mon, 20 Jul 2020 12:24:07 -0400 Subject: [PATCH 01/70] temp --- tfjs-backend-wasm/scripts/build-benchmark.sh | 4 ++- tfjs-backend-wasm/scripts/build-wasm.sh | 16 +++++----- tfjs-backend-wasm/scripts/inline-worker.js | 20 +++++++++++++ tfjs-backend-wasm/src/backend_wasm.ts | 30 ++++++++++++++----- tfjs-backend-wasm/src/cc/BUILD | 8 ++++- tfjs-backend-wasm/src/cc/backend.cc | 1 + tfjs-backend-wasm/src/cc/backend.h | 3 ++ .../src/cc/batch_mat_mul_impl.cc | 4 +-- .../wasm-out/tfjs-backend-wasm.d.ts | 1 + .../wasm-out/tfjs-backend-wasm.worker.ts | 1 + 10 files changed, 70 insertions(+), 18 deletions(-) create mode 100644 tfjs-backend-wasm/scripts/inline-worker.js create mode 100644 tfjs-backend-wasm/wasm-out/tfjs-backend-wasm.worker.ts diff --git a/tfjs-backend-wasm/scripts/build-benchmark.sh b/tfjs-backend-wasm/scripts/build-benchmark.sh index 16fca29aa31..a396217cb23 100755 --- a/tfjs-backend-wasm/scripts/build-benchmark.sh +++ b/tfjs-backend-wasm/scripts/build-benchmark.sh @@ -1,6 +1,8 @@ yarn build +node ./scripts/inline-worker.js yarn rollup -c cp dist/tf-backend-wasm.js ../e2e/benchmarks/ +# cp wasm-out/tfjs-backend-wasm-threaded.js ../e2e/benchmarks/tfjs-backend-wasm.js cp wasm-out/tfjs-backend-wasm.wasm ../e2e/benchmarks/ -cp wasm-out/tfjs-backend-wasm-simd.wasm ../e2e/benchmarks/ +# cp wasm-out/tfjs-backend-wasm-simd.wasm ../e2e/benchmarks/ diff --git a/tfjs-backend-wasm/scripts/build-wasm.sh b/tfjs-backend-wasm/scripts/build-wasm.sh index f0d846dceca..a5b776ba0b7 100755 --- a/tfjs-backend-wasm/scripts/build-wasm.sh +++ b/tfjs-backend-wasm/scripts/build-wasm.sh @@ -17,19 +17,21 @@ set -e # Default build. -yarn bazel build -c opt //src/cc:tfjs-backend-wasm.js --config=wasm +yarn bazel build -c opt //src/cc:tfjs-backend-wasm-threaded.js --config=wasm --copt="-pthread" # The typescript code and karma config expect the output of emscripten to be in # wasm-out/ so we copy the bazel output there. -cp -f bazel-bin/src/cc/tfjs-backend-wasm.js \ - bazel-bin/src/cc/tfjs-backend-wasm.wasm \ +cp -f bazel-bin/src/cc/tfjs-backend-wasm-threaded.js \ + bazel-bin/src/cc/tfjs-backend-wasm-threaded.worker.js \ + bazel-bin/src/cc/tfjs-backend-wasm-threaded.wasm \ wasm-out/ # SIMD build. -yarn bazel build -c opt //src/cc:tfjs-backend-wasm-simd.js --config=wasm --copt="-msimd128" -cp -f bazel-bin/src/cc/tfjs-backend-wasm-simd.js \ - bazel-bin/src/cc/tfjs-backend-wasm-simd.wasm \ - wasm-out/ +# yarn bazel build -c opt //src/cc:tfjs-backend-wasm-simd.js --config=wasm --copt="-msimd128" +# cp -f bazel-bin/src/cc/tfjs-backend-wasm-simd.js \ +# bazel-bin/src/cc/tfjs-backend-wasm-simd.wasm \ +# wasm-out/ mkdir -p dist # Only copying binary into dist because the js module gets bundled. cp wasm-out/*.wasm dist/ +cp wasm-out/*.worker.js dist/ diff --git a/tfjs-backend-wasm/scripts/inline-worker.js b/tfjs-backend-wasm/scripts/inline-worker.js new file mode 100644 index 00000000000..eb41f0ea630 --- /dev/null +++ b/tfjs-backend-wasm/scripts/inline-worker.js @@ -0,0 +1,20 @@ +const fs = require('fs'); + +const workerContents = fs.readFileSync('./wasm-out/tfjs-backend-wasm-threaded.worker.js', "utf8"); + +const fileContents = `export const wasmWorkerContents = '${workerContents.trim()}';`; + +fs.writeFile('./wasm-out/tfjs-backend-wasm.worker.ts', fileContents, function(err) { + console.log("dobne"); +}); + + +// const moduleContents = fs.readFileSync('./wasm-out/tfjs-backend-wasm-threaded.js', 'utf-8'); + +// // const moduleFileContents = `export const wasmModuleContents = '${moduleContents.trim().replace(/\r?\n|\r/g, " ")}';`; + +// const moduleFileContents = 'export const wasmModuleContents = `' + moduleContents.trim().replace(/\r?\n|\r/g, " ") + '`;'; + +// fs.writeFile('./wasm-out/tfjs-backend-wasm.ts', moduleFileContents, function(err) { +// console.log("done done"); +// }); diff --git a/tfjs-backend-wasm/src/backend_wasm.ts b/tfjs-backend-wasm/src/backend_wasm.ts index 0299073da66..795d4e19003 100644 --- a/tfjs-backend-wasm/src/backend_wasm.ts +++ b/tfjs-backend-wasm/src/backend_wasm.ts @@ -16,12 +16,14 @@ */ import './flags_wasm'; -import {backend_util, BackendTimingInfo, DataStorage, DataType, engine, env, KernelBackend, registerBackend, TensorInfo, util} from '@tensorflow/tfjs-core'; +import {backend_util, BackendTimingInfo, DataStorage, DataType, engine, KernelBackend, registerBackend, TensorInfo, util} from '@tensorflow/tfjs-core'; import {BackendWasmModule, WasmFactoryConfig} from '../wasm-out/tfjs-backend-wasm'; -import wasmFactorySimd from '../wasm-out/tfjs-backend-wasm-simd.js'; import wasmFactory from '../wasm-out/tfjs-backend-wasm.js'; +// @ts-ignore +import {wasmWorkerContents} from '../wasm-out/tfjs-backend-wasm.worker.js'; + const WASM_PRIORITY = 2; interface TensorData { @@ -203,15 +205,26 @@ function createInstantiateWasmFunc(path: string) { * in Chrome 76). */ export async function init(): Promise<{wasm: BackendWasmModule}> { - const simdSupported = await env().getAsync('WASM_HAS_SIMD_SUPPORT'); + // const simdSupported = await env().getAsync('WASM_HAS_SIMD_SUPPORT'); return new Promise((resolve, reject) => { const factoryConfig: WasmFactoryConfig = {}; + const locateFile = (path: string, prefix: string) => { + if (path.endsWith('.worker.js')) { + const response = wasmWorkerContents; + const blob = new Blob([response], {type: 'application/javascript'}); + return URL.createObjectURL(blob); + } + return prefix + path; + }; + + factoryConfig.locateFile = locateFile; + if (wasmPath != null) { - factoryConfig.locateFile = (path, prefix) => { + factoryConfig.locateFile = (path: string, prefix: string) => { if (path.endsWith('.wasm')) { return wasmPath; } - return prefix + path; + return locateFile(path, prefix); }; // use wasm instantiateWasm override when system fetch is not available. // For detail references @@ -220,9 +233,12 @@ export async function init(): Promise<{wasm: BackendWasmModule}> { factoryConfig.instantiateWasm = createInstantiateWasmFunc(wasmPath); } } - const wasm = simdSupported ? wasmFactorySimd(factoryConfig) : - wasmFactory(factoryConfig); + // const wasm = simdSupported ? wasmFactorySimd(factoryConfig) : + // wasmFactory(factoryConfig); + const wasm = wasmFactory(factoryConfig); const voidReturnType: string = null; + // wasm.mainScriptUrlOrBlob = + // new Blob([emscriptenContents], {type: 'text/javascript'}); // Using the tfjs namespace to avoid conflict with emscripten's API. wasm.tfjs = { init: wasm.cwrap('init', null, []), diff --git a/tfjs-backend-wasm/src/cc/BUILD b/tfjs-backend-wasm/src/cc/BUILD index f1ab1a2101d..f1d1a1f1d46 100644 --- a/tfjs-backend-wasm/src/cc/BUILD +++ b/tfjs-backend-wasm/src/cc/BUILD @@ -8,7 +8,7 @@ KERNELS_WITH_KEEPALIVE = glob( ) cc_binary( - name = "tfjs-backend-wasm.js", + name = "tfjs-backend-wasm-threaded.js", srcs = ["backend.cc"] + KERNELS_WITH_KEEPALIVE, linkopts = [ "-s ALLOW_MEMORY_GROWTH=1", @@ -21,6 +21,12 @@ cc_binary( "-s MODULARIZE=1", "-s EXPORT_NAME=WasmBackendModule", "-s MALLOC=emmalloc", + "-s USE_PTHREADS=1", + "-s PTHREAD_POOL_SIZE=4", + "-s ASSERTIONS=1", + "-s INITIAL_MEMORY=1Gb", + "-s MAXIMUM_MEMORY=1Gb", + "-s PROXY_TO_PTHREAD=1", ], deps = [ ":all_kernels", diff --git a/tfjs-backend-wasm/src/cc/backend.cc b/tfjs-backend-wasm/src/cc/backend.cc index b5037379e2d..18e61790310 100644 --- a/tfjs-backend-wasm/src/cc/backend.cc +++ b/tfjs-backend-wasm/src/cc/backend.cc @@ -48,6 +48,7 @@ TensorInfo &get_tensor_info_out(const size_t tensor_id) { } size_t xnn_operator_count = 0; +pthreadpool *threadpool = pthreadpool_create(4); // Registers a disposal callback for a tensor id with a given callback function. void register_disposal_callback(const size_t tensor_id, diff --git a/tfjs-backend-wasm/src/cc/backend.h b/tfjs-backend-wasm/src/cc/backend.h index d34f55eee08..eb13d124ac9 100644 --- a/tfjs-backend-wasm/src/cc/backend.h +++ b/tfjs-backend-wasm/src/cc/backend.h @@ -15,6 +15,7 @@ #ifndef BACKEND_H_ #define BACKEND_H_ +#include #include #include @@ -81,6 +82,8 @@ const size_t num_tensors(); // The number of instantiated XNN operators. extern size_t xnn_operator_count; + +extern pthreadpool *threadpool; } // namespace backend namespace wasm { diff --git a/tfjs-backend-wasm/src/cc/batch_mat_mul_impl.cc b/tfjs-backend-wasm/src/cc/batch_mat_mul_impl.cc index 3faa4b0f59c..2256d0bb257 100644 --- a/tfjs-backend-wasm/src/cc/batch_mat_mul_impl.cc +++ b/tfjs-backend-wasm/src/cc/batch_mat_mul_impl.cc @@ -150,7 +150,7 @@ void xnn_matmul(const size_t a_id, const size_t* a_shape_ptr, const size_t batch_size = a_shape_ptr[1]; xnn_status status = xnn_setup_fully_connected_nc_f32(fully_connected_op, batch_size, a_buf, - out_buf, nullptr /* thread pool */); + out_buf, tfjs::backend::threadpool); if (status != xnn_status_success) { tfjs::util::warn( "XNN status for xnn_setup_fully_connected_nc_f32 is not successful. " @@ -159,7 +159,7 @@ void xnn_matmul(const size_t a_id, const size_t* a_shape_ptr, return; } - xnn_run_operator(fully_connected_op, nullptr /* thread pool */); + xnn_run_operator(fully_connected_op, tfjs::backend::threadpool); } void slow_batch_matmul(const size_t a_id, const size_t* a_shape_ptr, diff --git a/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm.d.ts b/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm.d.ts index c7254db4a64..f610457b332 100644 --- a/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm.d.ts +++ b/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm.d.ts @@ -16,6 +16,7 @@ */ export interface BackendWasmModule extends EmscriptenModule { + mainScriptUrlOrBlob: string|Blob; onRuntimeInitialized: () => void; onAbort: (msg: string) => void; // Using the tfjs namespace to avoid conflict with emscripten's API. diff --git a/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm.worker.ts b/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm.worker.ts new file mode 100644 index 00000000000..7d1d46c0f0f --- /dev/null +++ b/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm.worker.ts @@ -0,0 +1 @@ +export const wasmWorkerContents = 'var threadInfoStruct=0;var selfThreadId=0;var parentThreadId=0;var Module={};function assert(condition,text){if(!condition)abort("Assertion failed: "+text)}function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:selfThreadId})}var out=function(){throw"out() is not defined in worker.js."};var err=threadPrintErr;this.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);Module["wasmModule"]=null;receiveInstance(instance);return instance.exports};this.onmessage=function(e){try{if(e.data.cmd==="load"){Module["DYNAMIC_BASE"]=e.data.DYNAMIC_BASE;Module["DYNAMICTOP_PTR"]=e.data.DYNAMICTOP_PTR;Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob==="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}Module=WasmBackendModule(Module);postMessage({"cmd":"loaded"})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;threadInfoStruct=e.data.threadInfoStruct;Module["__register_pthread_ptr"](threadInfoStruct,0,0);selfThreadId=e.data.selfThreadId;parentThreadId=e.data.parentThreadId;var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;assert(threadInfoStruct);assert(selfThreadId);assert(parentThreadId);assert(top!=0);assert(max!=0);assert(top>max);Module["establishStackSpace"](top,max);Module["_emscripten_tls_init"]();Module["writeStackCookie"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].setThreadStatus(Module["_pthread_self"](),1);try{var result=Module["dynCall_ii"](e.data.start_routine,e.data.arg);Module["checkStackCookie"]();if(!Module["getNoExitRuntime"]())Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){Atomics.store(Module["HEAPU32"],threadInfoStruct+4>>2,ex instanceof Module["ExitStatus"]?ex.status:-2);Atomics.store(Module["HEAPU32"],threadInfoStruct+0>>2,1);if(typeof Module["_emscripten_futex_wake"]!=="function"){err("Thread Initialisation failed.");throw ex}Module["_emscripten_futex_wake"](threadInfoStruct+0,2147483647);if(!(ex instanceof Module["ExitStatus"]))throw ex}else{err("Pthread 0x"+threadInfoStruct.toString(16)+" completed its pthread main entry point with an unwind, keeping the pthread worker alive for asynchronous operation.")}}}else if(e.data.cmd==="cancel"){if(threadInfoStruct){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(threadInfoStruct){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex.stack)err(ex.stack);throw ex}};if(typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string"){self={location:{href:__filename}};var onmessage=this.onmessage;var nodeWorkerThreads=require("worker_threads");Worker=nodeWorkerThreads.Worker;var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var nodeFS=require("fs");var nodeRead=function(filename){return nodeFS.readFileSync(filename,"utf8")};function globalEval(x){global.require=require;global.Module=Module;eval.call(null,x)}importScripts=function(f){globalEval(nodeRead(f))};postMessage=function(msg){parentPort.postMessage(msg)};if(typeof performance==="undefined"){performance={now:function(){return Date.now()}}}}'; \ No newline at end of file From b6fd69f6100f10ea00f0f787ec66be47861b80ef Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Mon, 20 Jul 2020 12:34:32 -0400 Subject: [PATCH 02/70] updates --- e2e/benchmarks/index.html | 3 +- e2e/benchmarks/tf-backend-wasm.js | 3320 +++++++++++++++++ .../tfjs-backend-wasm-threaded.wasm | Bin 0 -> 175629 bytes e2e/benchmarks/tfjs-backend-wasm.wasm | Bin 0 -> 154589 bytes tfjs-backend-wasm/scripts/build-benchmark.sh | 2 +- tfjs-backend-wasm/src/backend_wasm.ts | 2 +- .../wasm-out/tfjs-backend-wasm-threaded.d.ts | 39 + 7 files changed, 3363 insertions(+), 3 deletions(-) create mode 100644 e2e/benchmarks/tf-backend-wasm.js create mode 100644 e2e/benchmarks/tfjs-backend-wasm-threaded.wasm create mode 100644 e2e/benchmarks/tfjs-backend-wasm.wasm create mode 100644 tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-threaded.d.ts diff --git a/e2e/benchmarks/index.html b/e2e/benchmarks/index.html index 61f314f203a..98710181447 100644 --- a/e2e/benchmarks/index.html +++ b/e2e/benchmarks/index.html @@ -90,7 +90,8 @@

TensorFlow.js Model Benchmark

- + + diff --git a/e2e/benchmarks/tf-backend-wasm.js b/e2e/benchmarks/tf-backend-wasm.js new file mode 100644 index 00000000000..818167900a8 --- /dev/null +++ b/e2e/benchmarks/tf-backend-wasm.js @@ -0,0 +1,3320 @@ +/** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tensorflow/tfjs-core'), require('path'), require('fs'), require('worker_threads'), require('perf_hooks')) : + typeof define === 'function' && define.amd ? define(['exports', '@tensorflow/tfjs-core', 'path', 'fs', 'worker_threads', 'perf_hooks'], factory) : + (global = global || self, factory((global.tf = global.tf || {}, global.tf.wasm = global.tf.wasm || {}), global.tf, global.path, global.fs, global.worker_threads, global.perf_hooks)); +}(this, (function (exports, tfjsCore, path, fs, worker_threads, perf_hooks) { 'use strict'; + + path = path && path.hasOwnProperty('default') ? path['default'] : path; + fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; + worker_threads = worker_threads && worker_threads.hasOwnProperty('default') ? worker_threads['default'] : worker_threads; + perf_hooks = perf_hooks && perf_hooks.hasOwnProperty('default') ? perf_hooks['default'] : perf_hooks; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // This enum must align with the enum defined in cc/backend.h. + var CppDType; + (function (CppDType) { + CppDType[CppDType["float32"] = 0] = "float32"; + CppDType[CppDType["int32"] = 1] = "int32"; + CppDType[CppDType["bool"] = 2] = "bool"; + CppDType[CppDType["string"] = 3] = "string"; + CppDType[CppDType["complex64"] = 4] = "complex64"; + })(CppDType || (CppDType = {})); + // Must match enum in cc/fusable_activations.h. + var FusableActivation; + (function (FusableActivation) { + FusableActivation[FusableActivation["linear"] = 0] = "linear"; + FusableActivation[FusableActivation["relu"] = 1] = "relu"; + FusableActivation[FusableActivation["relu6"] = 2] = "relu6"; + FusableActivation[FusableActivation["prelu"] = 3] = "prelu"; + })(FusableActivation || (FusableActivation = {})); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFusedMatMul; + function setup(backend) { + wasmFusedMatMul = backend.wasm.cwrap('_FusedMatMul', null /* void */, [ + 'number', + 'array', + 'number', + 'number', + 'array', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number' // out_id + ]); + } + function fusedBatchMatMul(args) { + const { inputs, backend, attrs } = args; + const { a, b, bias, preluActivationWeights } = inputs; + if (a.dtype !== 'float32' || b.dtype !== 'float32') { + throw new Error(`_FusedMatMul for non non-float32 tensors not yet supported.`); + } + const { transposeA, transposeB, activation } = attrs; + const aId = backend.dataIdMap.get(a.dataId).id; + const bId = backend.dataIdMap.get(b.dataId).id; + let biasId = 0; + if (bias != null) { + const biasData = backend.dataIdMap.get(bias.dataId); + if (biasData.shape.length !== 1) { + throw new Error(`_FusedMatMul only supports rank-1 bias but got ` + + `rank ${biasData.shape.length}.`); + } + biasId = biasData.id; + } + const preluActivationWeightsId = preluActivationWeights == null ? + 0 : + backend.dataIdMap.get(preluActivationWeights.dataId).id; + const fusedActivation = FusableActivation[activation]; + if (fusedActivation == null) { + throw new Error(`${activation} activation not yet supported for FusedConv2D ` + + `in the wasm backend.`); + } + const leftDim = transposeA ? a.shape[2] : a.shape[1]; + const rightDim = transposeB ? b.shape[1] : b.shape[2]; + const batchDim = a.shape[0]; + const out = backend.makeOutput([batchDim, leftDim, rightDim], a.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); + const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); + wasmFusedMatMul(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, transposeA, transposeB, fusedActivation, biasId, preluActivationWeightsId, outId); + return out; + } + const fusedMatMulConfig = { + kernelName: '_FusedMatMul', + backendName: 'wasm', + setupFunc: setup, + kernelFunc: fusedBatchMatMul + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function createUnaryKernelConfig(kernelName) { + let wasmFunc; + function setupFunc(backend) { + wasmFunc = + backend.wasm.cwrap(kernelName, null /* void */, ['number', 'number']); + } + function kernelFunc(args) { + const { backend, inputs: { x } } = args; + const xId = backend.dataIdMap.get(x.dataId).id; + const out = backend.makeOutput(x.shape, x.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(out.shape) === 0) { + return out; + } + wasmFunc(xId, outId); + return out; + } + return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; + } + + const absConfig = createUnaryKernelConfig('Abs'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function createBinaryKernelConfig(kernelName, supportsFullBroadcast, dtype) { + let wasmFunc; + function setupFunc(backend) { + wasmFunc = backend.wasm.cwrap(kernelName, null /* void */, [ + 'number', + 'array', + 'number', + 'number', + 'array', + 'number', + 'number', + 'number' // out_id + ]); + } + function kernelFunc(args) { + const { backend, inputs } = args; + const { a, b } = inputs; + const aId = backend.dataIdMap.get(a.dataId).id; + const bId = backend.dataIdMap.get(b.dataId).id; + const outputType = dtype != null ? dtype : a.dtype; + const newShape = tfjsCore.backend_util.assertAndGetBroadcastShape(a.shape, b.shape); + const out = backend.makeOutput(newShape, outputType); + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(newShape) === 0) { + return out; + } + const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); + const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); + const outId = backend.dataIdMap.get(out.dataId).id; + const kernelFunc = () => wasmFunc(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, CppDType[a.dtype], outId); + // Currently only some float operations support full broadcast. + if (supportsFullBroadcast && a.dtype === 'float32') { + kernelFunc(); + return out; + } + const aBroadcastDims = tfjsCore.backend_util.getBroadcastDims(a.shape, newShape); + const bBroadcastDims = tfjsCore.backend_util.getBroadcastDims(b.shape, newShape); + const loopsOverAllOfA = aBroadcastDims.every((v, i) => v === i); + const loopsOverAllOfB = bBroadcastDims.every((v, i) => v === i); + if (loopsOverAllOfA && loopsOverAllOfB) { + kernelFunc(); + return out; + } + else { + throw new Error(`Broadcasting along outer dims is not yet ` + + `supported for ${a.dtype} ${kernelName}.`); + } + } + return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast = true; + const addConfig = createBinaryKernelConfig('Add', supportsFullBroadcast); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc; + function setupFunc(backend) { + wasmFunc = backend.wasm.cwrap('AddN', null /* void */, [ + 'array', + 'number', + 'number', + 'number', + ]); + } + function addn(args) { + const { inputs, backend } = args; + const out = backend.makeOutput(inputs[0].shape, inputs[0].dtype); + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(out.shape) === 0) { + return out; + } + const inputIds = inputs.map(x => backend.dataIdMap.get(x.dataId).id); + const inputIdsBytes = new Uint8Array(new Int32Array(inputIds).buffer); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmFunc(inputIdsBytes, inputIds.length, CppDType[out.dtype], outId); + return out; + } + const addNConfig = { + kernelName: 'AddN', + backendName: 'wasm', + setupFunc, + kernelFunc: addn, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function identity(args) { + const { inputs: { x }, backend } = args; + const out = backend.makeOutput(x.shape, x.dtype); + const inVals = backend.typedArrayFromHeap(x); + const outVals = backend.typedArrayFromHeap(out); + outVals.set(inVals); + return out; + } + const identityConfig = { + kernelName: tfjsCore.Identity, + backendName: 'wasm', + kernelFunc: identity, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmTranspose; + function setup$1(backend) { + wasmTranspose = backend.wasm.cwrap('Transpose', null /* void */, [ + 'number', + 'array', + 'number', + 'number', + 'number', + 'array', + 'number', + ]); + } + function transpose(args) { + const { inputs, backend, attrs } = args; + // Reduce any dimensions with size one. Lower-rank transpose kernel performs + // better due to simpler memory access pattern. + const [reducedShape, perm] = removeOneSizeDims(inputs.x.shape, attrs.perm); + let permIsNoOp = true; + for (let i = 0; i < perm.length; i++) { + if (perm[i] !== i) { + permIsNoOp = false; + } + } + const outShape = computeOutShape(inputs.x.shape, attrs.perm); + const x = { + dataId: inputs.x.dataId, + shape: reducedShape, + dtype: inputs.x.dtype + }; + if (permIsNoOp) { + const cloned = identity({ inputs, backend }); + cloned.shape = outShape; + return cloned; + } + const out = backend.makeOutput(outShape, x.dtype); + const xId = backend.dataIdMap.get(x.dataId).id; + const outId = backend.dataIdMap.get(out.dataId).id; + const permBytes = new Uint8Array(new Int32Array(perm).buffer); + const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); + wasmTranspose(xId, xShapeBytes, x.shape.length, CppDType[x.dtype], outId, permBytes, perm.length); + return out; + } + function computeOutShape(inShape, perm) { + const outShape = new Array(inShape.length); + for (let i = 0; i < outShape.length; i++) { + outShape[i] = inShape[perm[i]]; + } + return outShape; + } + function removeOneSizeDims(shape, perm) { + const newShape = []; + const newPerm = []; + for (let i = 0; i < shape.length; ++i) { + if (shape[i] !== 1) { + newShape.push(shape[i]); + } + if (shape[perm[i]] !== 1) { + newPerm.push(perm[i]); + } + } + for (let i = 0; i < newPerm.length; ++i) { + let minValIdx = -1; + for (let j = 0; j < newPerm.length; ++j) { + if (newPerm[j] >= i && + (minValIdx === -1 || newPerm[minValIdx] > newPerm[j])) { + minValIdx = j; + } + } + newPerm[minValIdx] = i; + } + return [newShape, newPerm]; + } + const transposeConfig = { + kernelName: 'Transpose', + backendName: 'wasm', + kernelFunc: transpose, + setupFunc: setup$1, + }; + + /** + * @license + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Compute permutation axes and do a transpose if necessary. + * + * Used by reduction ops. + * @param x input TensorInfo + * @param axis reduction axes + * @param backend wasm backend instance + */ + function permuteAxesAndTranspose(x, axis, backend) { + const xShape = x.shape; + const xRank = x.shape.length; + const originalAxes = tfjsCore.util.parseAxisParam(axis, xShape); + let axes = originalAxes; + const permutedAxes = tfjsCore.backend_util.getAxesPermutation(axes, xRank); + let xTransposed = null; + let inputWasTransposed = false; + if (permutedAxes != null) { + const newShape = new Array(xRank); + for (let i = 0; i < newShape.length; i++) { + newShape[i] = xShape[permutedAxes[i]]; + } + axes = tfjsCore.backend_util.getInnerMostAxes(axes.length, xRank); + xTransposed = + transpose({ inputs: { x }, attrs: { perm: permutedAxes }, backend }); + const xId = backend.dataIdMap.get(x.dataId).id; + const transposedId = backend.dataIdMap.get(xTransposed.dataId).id; + if (transposedId !== xId) { + inputWasTransposed = true; + } + } + return { transposed: xTransposed, originalAxes, axes, inputWasTransposed }; + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$1; + function setup$2(backend) { + wasmFunc$1 = backend.wasm.cwrap('ArgMax', null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number' // out_id + ]); + } + function argmax(args) { + const { backend, inputs, attrs } = args; + const { axis } = attrs; + const { x } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + let inputId = xId; + let input = x; + const { transposed, axes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); + if (inputWasTransposed) { + const transposedId = backend.dataIdMap.get(transposed.dataId).id; + if (transposedId !== xId) { + // transpose was not a no-op. We will need to dispose of this + // once we are done. + input = transposed; + inputId = transposedId; + } + } + const outShape = input.shape.slice(0, -1); + const out = backend.makeOutput(outShape, 'int32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const outerSize = tfjsCore.util.sizeFromShape(out.shape); + const innerSize = input.shape[axes[0]]; + wasmFunc$1(inputId, CppDType[input.dtype], outerSize, innerSize, outId); + if (inputWasTransposed) { + // dispose of the transposed tensor. + backend.disposeData(transposed.dataId); + } + return out; + } + const argMaxConfig = { + kernelName: tfjsCore.ArgMax, + backendName: 'wasm', + kernelFunc: argmax, + setupFunc: setup$2 + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmAvgPool; + function setup$3(backend) { + wasmAvgPool = backend.wasm.cwrap('AvgPool', null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function avgPool(args) { + const { inputs, attrs, backend } = args; + const x = inputs.x; + const xId = backend.dataIdMap.get(x.dataId).id; + const { filterSize, strides, pad, dimRoundingMode } = attrs; + const convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const channels = convInfo.inChannels; + if (convInfo.dataFormat !== 'channelsLast') { + throw new Error(`wasm backend does not support dataFormat:'` + + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + } + if (convInfo.dilationWidth !== 1 || convInfo.dilationHeight !== 1) { + throw new Error(`was backend only supports average pooling with dilation = [1, 1], ` + + `got [${convInfo.dilationHeight}, ${convInfo.dilationWidth}].`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmAvgPool(xId, x.shape[0], x.shape[1], x.shape[2], filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, strideHeight, strideWidth, channels, outId); + return out; + } + const avgPoolConfig = { + kernelName: 'AvgPool', + backendName: 'wasm', + setupFunc: setup$3, + kernelFunc: avgPool + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmBatchMatMul; + function setup$4(backend) { + wasmBatchMatMul = backend.wasm.cwrap('BatchMatMul', null /* void */, [ + 'number', + 'array', + 'number', + 'number', + 'array', + 'number', + 'number', + 'number', + 'number' // out_id + ]); + } + function batchMatMul(args) { + const { inputs, backend, attrs } = args; + const { a, b } = inputs; + if (a.dtype !== 'float32' || b.dtype !== 'float32') { + throw new Error(`BatchMatMul for non non-float32 tensors not yet supported.`); + } + const { transposeA, transposeB } = attrs; + const aId = backend.dataIdMap.get(a.dataId).id; + const bId = backend.dataIdMap.get(b.dataId).id; + const leftDim = transposeA ? a.shape[2] : a.shape[1]; + const rightDim = transposeB ? b.shape[1] : b.shape[2]; + const batchDim = a.shape[0]; + const out = backend.makeOutput([batchDim, leftDim, rightDim], a.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); + const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); + wasmBatchMatMul(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, transposeA, transposeB, outId); + return out; + } + const batchMatMulConfig = { + kernelName: 'BatchMatMul', + backendName: 'wasm', + setupFunc: setup$4, + kernelFunc: batchMatMul + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function cast(args) { + const { inputs: { x }, attrs: { dtype }, backend } = args; + const out = backend.makeOutput(x.shape, dtype); + const inVals = backend.typedArrayFromHeap(x); + const outVals = backend.typedArrayFromHeap(out); + outVals.set(inVals); + return out; + } + const castConfig = { + kernelName: 'Cast', + backendName: 'wasm', + kernelFunc: cast, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmClip; + function setup$5(backend) { + wasmClip = backend.wasm.cwrap(tfjsCore.ClipByValue, null /* void */, [ + 'number', + 'number', + 'number', + 'number' // out_id + ]); + } + function clip(args) { + const { inputs, backend, attrs } = args; + const { x } = inputs; + const { clipValueMin, clipValueMax } = attrs; + const xId = backend.dataIdMap.get(x.dataId).id; + const out = backend.makeOutput(x.shape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmClip(xId, clipValueMin, clipValueMax, outId); + return out; + } + const clipByValueConfig = { + kernelName: tfjsCore.ClipByValue, + backendName: 'wasm', + setupFunc: setup$5, + kernelFunc: clip + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function concat(args) { + const { inputs, backend } = args; + const axis = tfjsCore.util.parseAxisParam(args.attrs.axis, inputs[0].shape)[0]; + const outShape = tfjsCore.backend_util.computeOutShape(inputs.map(t => t.shape), axis); + const out = backend.makeOutput(outShape, inputs[0].dtype); + const batchDim = tfjsCore.util.sizeFromShape(inputs[0].shape.slice(0, axis)); + let sumInnerDims = 0; + const innerDims = inputs.map(input => { + const innerDim = tfjsCore.util.sizeFromShape(input.shape.slice(axis)); + sumInnerDims += innerDim; + return innerDim; + }); + const inVals = inputs.map(input => backend.typedArrayFromHeap(input)); + const outVals = backend.typedArrayFromHeap(out); + for (let b = 0; b < batchDim; b++) { + let outOffset = b * sumInnerDims; + for (let i = 0; i < inVals.length; i++) { + const innerDim = innerDims[i]; + const inOffset = b * innerDim; + const vals = inVals[i].subarray(inOffset, inOffset + innerDim); + outVals.set(vals, outOffset); + outOffset += innerDim; + } + } + return out; + } + const concatConfig = { + kernelName: 'Concat', + backendName: 'wasm', + kernelFunc: concat, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmConv2d; + function setup$6(backend) { + wasmConv2d = backend.wasm.cwrap('Conv2D', null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function conv2d(args) { + const { inputs, attrs, backend } = args; + const { x, filter } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const filterId = backend.dataIdMap.get(filter.dataId).id; + const { strides, dilations, pad, dimRoundingMode, dataFormat } = attrs; + const $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat); + const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const dilationHeight = convInfo.dilationHeight; + const dilationWidth = convInfo.dilationWidth; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const inputChannels = convInfo.inChannels; + const outputChannels = convInfo.outChannels; + const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; + if (convInfo.dataFormat !== 'channelsLast') { + throw new Error(`wasm backend Conv2D does not support dataFormat:'` + + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmConv2d(xId, x.shape[0], x.shape[1], x.shape[2], filterId, filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); + return out; + } + const conv2DConfig = { + kernelName: 'Conv2D', + backendName: 'wasm', + setupFunc: setup$6, + kernelFunc: conv2d + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmConv2DBackpropInput; + function setup$7(backend) { + wasmConv2DBackpropInput = backend.wasm.cwrap(tfjsCore.Conv2DBackpropInput, null, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function conv2DBackpropInput(args) { + const { backend, inputs, attrs } = args; + const { dy, filter } = inputs; + const { strides, pad, dataFormat, dimRoundingMode, inputShape } = attrs; + const dilations = 1; + const $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat); + const convInfo = tfjsCore.backend_util.computeConv2DInfo(inputShape, filter.shape, strides, dilations, pad, dimRoundingMode, false /* depthwise */, $dataFormat); + const { batchSize, filterHeight, filterWidth, inChannels, inHeight, inWidth, outChannels, outHeight, outWidth, strideHeight, strideWidth } = convInfo; + const topPad = filterHeight - 1 - convInfo.padInfo.top; + const leftPad = filterWidth - 1 - convInfo.padInfo.left; + const isChannelsLast = convInfo.dataFormat === 'channelsLast'; + const dxStrides = tfjsCore.util.computeStrides(convInfo.inShape); + const dyStrides = tfjsCore.util.computeStrides(dy.shape); + const [fltS0, fltS1, fltS2] = tfjsCore.util.computeStrides(filter.shape); + const xBatchStride = dxStrides[0]; + const xRowStride = isChannelsLast ? dxStrides[1] : dxStrides[2]; + const xColStride = isChannelsLast ? dxStrides[2] : 1; + const xChannelStride = isChannelsLast ? 1 : dxStrides[1]; + const yBatchStride = dyStrides[0]; + const yRowStride = isChannelsLast ? dyStrides[1] : dyStrides[2]; + const yColStride = isChannelsLast ? dyStrides[2] : 1; + const yChannelStride = isChannelsLast ? 1 : dyStrides[1]; + const out = backend.makeOutput(convInfo.inShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const dyId = backend.dataIdMap.get(dy.dataId).id; + const filterId = backend.dataIdMap.get(filter.dataId).id; + wasmConv2DBackpropInput(dyId, filterId, batchSize, filterHeight, filterWidth, inHeight, inWidth, inChannels, outHeight, outWidth, outChannels, strideHeight, strideWidth, topPad, leftPad, fltS0, fltS1, fltS2, xBatchStride, xRowStride, xColStride, xChannelStride, yBatchStride, yRowStride, yColStride, yChannelStride, outId); + return out; + } + const conv2DBackpropInputConfig = { + kernelName: tfjsCore.Conv2DBackpropInput, + backendName: 'wasm', + setupFunc: setup$7, + kernelFunc: conv2DBackpropInput + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const cosConfig = createUnaryKernelConfig('Cos'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // Must match enum in CropAndResize.cc + var InterpolationMethod; + (function (InterpolationMethod) { + InterpolationMethod[InterpolationMethod["bilinear"] = 0] = "bilinear"; + InterpolationMethod[InterpolationMethod["nearest"] = 1] = "nearest"; + })(InterpolationMethod || (InterpolationMethod = {})); + let wasmCropAndResize; + function setup$8(backend) { + wasmCropAndResize = backend.wasm.cwrap('CropAndResize', null /*void*/, [ + 'number', + 'number', + 'number', + 'number', + 'array', + 'number', + 'number', + 'number', + 'number', + 'number' // out id + ]); + } + function cropAndResize(args) { + const { backend, inputs, attrs } = args; + const { method, extrapolationValue, cropSize } = attrs; + const { image, boxes, boxInd } = inputs; + const numBoxes = boxes.shape[0]; + const [cropHeight, cropWidth] = cropSize; + const outShape = [numBoxes, cropHeight, cropWidth, image.shape[3]]; + let imagesData = backend.dataIdMap.get(image.dataId); + let castedData; + if (image.dtype !== 'float32') { + castedData = cast({ backend, inputs: { x: image }, attrs: { dtype: 'float32' } }); + imagesData = backend.dataIdMap.get(castedData.dataId); + } + const imagesId = imagesData.id; + const boxesId = backend.dataIdMap.get(boxes.dataId).id; + const boxIndId = backend.dataIdMap.get(boxInd.dataId).id; + const out = backend.makeOutput(outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const imagesShapeBytes = new Uint8Array(new Int32Array(image.shape).buffer); + wasmCropAndResize(imagesId, boxesId, boxIndId, numBoxes, imagesShapeBytes, cropHeight, cropWidth, InterpolationMethod[method], extrapolationValue, outId); + if (castedData != null) { + backend.disposeData(castedData.dataId); + } + return out; + } + const cropAndResizeConfig = { + kernelName: tfjsCore.CropAndResize, + backendName: 'wasm', + setupFunc: setup$8, + kernelFunc: cropAndResize + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmDepthwiseConv2d; + function setup$9(backend) { + wasmDepthwiseConv2d = + backend.wasm.cwrap('DepthwiseConv2dNative', null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function depthwiseConv2d(args) { + const { inputs, attrs, backend } = args; + const { x, filter } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const filterId = backend.dataIdMap.get(filter.dataId).id; + const { strides, dilations, pad, dimRoundingMode } = attrs; + const $dilations = dilations == null ? [1, 1] : dilations; + const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, $dilations, pad, dimRoundingMode, true /* depthwise */); + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const dilationHeight = convInfo.dilationHeight; + const dilationWidth = convInfo.dilationWidth; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const inputChannels = convInfo.inChannels; + const outputChannels = convInfo.outChannels; + const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; + if (convInfo.dataFormat !== 'channelsLast') { + throw new Error(`wasm backend DepthwiseConv2dNative does not support dataFormat:'` + + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmDepthwiseConv2d(xId, x.shape[0], x.shape[1], x.shape[2], filterId, filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); + return out; + } + const depthwiseConv2DNativeConfig = { + kernelName: 'DepthwiseConv2dNative', + backendName: 'wasm', + setupFunc: setup$9, + kernelFunc: depthwiseConv2d + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$1 = true; + const divConfig = createBinaryKernelConfig('Div', supportsFullBroadcast$1); + + const supportsFullBroadcast$2 = false; + const equalConfig = createBinaryKernelConfig('Equal', supportsFullBroadcast$2, 'bool'); + + const expConfig = createUnaryKernelConfig('Exp'); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function fill(args) { + const { attrs: { shape, value, dtype }, backend } = args; + const out = backend.makeOutput(shape, dtype); + const outVals = backend.typedArrayFromHeap(out); + outVals.fill(value); + return out; + } + const fillConfig = { + kernelName: tfjsCore.Fill, + backendName: 'wasm', + kernelFunc: fill, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$3 = false; + const floorDivConfig = createBinaryKernelConfig('FloorDiv', supportsFullBroadcast$3); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmBatchNorm; + function setup$a(backend) { + wasmBatchNorm = backend.wasm.cwrap('FusedBatchNorm', null /* void */, ['number', 'number', 'number', 'number', 'number', 'number', 'number']); + } + function fusedBatchNorm(args) { + const { backend, inputs, attrs } = args; + const { varianceEpsilon } = attrs; + const { x, mean, variance, offset, scale } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const meanId = backend.dataIdMap.get(mean.dataId).id; + const varianceId = backend.dataIdMap.get(variance.dataId).id; + const offsetId = offset != null ? backend.dataIdMap.get(offset.dataId).id : 0; + const scaleId = scale != null ? backend.dataIdMap.get(scale.dataId).id : 0; + const out = backend.makeOutput(x.shape, x.dtype); + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(x.shape) === 0) { + return out; + } + const outId = backend.dataIdMap.get(out.dataId).id; + wasmBatchNorm(xId, meanId, varianceId, offsetId, scaleId, varianceEpsilon, outId); + return out; + } + const fusedBatchNormConfig = { + kernelName: 'FusedBatchNorm', + backendName: 'wasm', + setupFunc: setup$a, + kernelFunc: fusedBatchNorm + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFusedConv2d; + function setup$b(backend) { + wasmFusedConv2d = backend.wasm.cwrap('FusedConv2D', null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function fusedConv2d(args) { + const { inputs, attrs, backend } = args; + const { convInfo, activation } = attrs; + const fusedActivation = FusableActivation[activation]; + if (fusedActivation == null) { + throw new Error(`${activation} activation not yet supported for FusedConv2D ` + + `in the wasm backend.`); + } + const { x, filter, bias, preluActivationWeights } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const filterId = backend.dataIdMap.get(filter.dataId).id; + const outputChannels = convInfo.outChannels; + let biasId = 0; + if (bias != null) { + const biasData = backend.dataIdMap.get(bias.dataId); + if (biasData.shape.length !== 1) { + throw new Error(`FusedConv2D only supports rank-1 bias but got ` + + `rank ${biasData.shape.length}.`); + } + if (biasData.shape[0] !== outputChannels) { + throw new Error(`FusedConv2D bias shape (${biasData.shape}) does not ` + + `match the number of output channels (${outputChannels})`); + } + biasId = biasData.id; + } + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const dilationHeight = convInfo.dilationHeight; + const dilationWidth = convInfo.dilationWidth; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const inputChannels = convInfo.inChannels; + const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; + const batchSize = convInfo.batchSize; + const inHeight = convInfo.inHeight; + const inWidth = convInfo.inWidth; + if (convInfo.dataFormat !== 'channelsLast') { + throw new Error(`wasm backend FusedConv2D does not support dataFormat:'` + + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const preluActivationWeightsId = preluActivationWeights == null ? + 0 : + backend.dataIdMap.get(preluActivationWeights.dataId).id; + wasmFusedConv2d(xId, batchSize, inHeight, inWidth, filterId, filterHeight, filterWidth, biasId, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, fusedActivation, preluActivationWeightsId, outId); + return out; + } + const fusedConv2DConfig = { + kernelName: 'FusedConv2D', + backendName: 'wasm', + setupFunc: setup$b, + kernelFunc: fusedConv2d + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFusedDepthwiseConv2d; + function setup$c(backend) { + wasmFusedDepthwiseConv2d = + backend.wasm.cwrap('FusedDepthwiseConv2D', null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function fusedDepthwiseConv2d(args) { + const { inputs, attrs, backend } = args; + const { convInfo, activation } = attrs; + const fusedActivation = FusableActivation[activation]; + if (fusedActivation == null) { + throw new Error(`${activation} activation not yet supported for FusedDepthwiseConv2D ` + + `in the wasm backend.`); + } + const { x, filter, bias, preluActivationWeights } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const filterId = backend.dataIdMap.get(filter.dataId).id; + const outputChannels = convInfo.outChannels; + let biasId = 0; + if (bias != null) { + const biasData = backend.dataIdMap.get(bias.dataId); + if (biasData.shape.length !== 1) { + throw new Error(`FusedDepthwiseConv2D only supports rank-1 bias but got ` + + `rank ${biasData.shape.length}.`); + } + if (biasData.shape[0] !== outputChannels) { + throw new Error(`FusedDepthwiseConv2D bias shape (${biasData.shape}) does not ` + + `match the number of output channels (${outputChannels})`); + } + biasId = biasData.id; + } + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const dilationHeight = convInfo.dilationHeight; + const dilationWidth = convInfo.dilationWidth; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const inputChannels = convInfo.inChannels; + const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; + const batchSize = convInfo.batchSize; + const inHeight = convInfo.inHeight; + const inWidth = convInfo.inWidth; + if (convInfo.dataFormat !== 'channelsLast') { + throw new Error(`wasm backend FusedDepthwiseConv2D does not support dataFormat:'` + + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const preluActivationWeightsId = preluActivationWeights == null ? + 0 : + backend.dataIdMap.get(preluActivationWeights.dataId).id; + wasmFusedDepthwiseConv2d(xId, batchSize, inHeight, inWidth, filterId, filterHeight, filterWidth, biasId, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, fusedActivation, preluActivationWeightsId, outId); + return out; + } + const fusedDepthwiseConv2DConfig = { + kernelName: 'FusedDepthwiseConv2D', + backendName: 'wasm', + setupFunc: setup$c, + kernelFunc: fusedDepthwiseConv2d + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmGatherNd; + function setup$d(backend) { + wasmGatherNd = backend.wasm.cwrap('GatherNd', null /*void*/, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'array', + 'number' // outId + ]); + } + function gatherNd(args) { + const { backend, inputs } = args; + const { params, indices } = inputs; + const [resultShape, numSlices, sliceSize, strides] = tfjsCore.gather_util.prepareAndValidate(params, indices); + const out = backend.makeOutput(resultShape, params.dtype); + if (numSlices === 0) { + return out; + } + const indicesShape = indices.shape; + const sliceRank = indicesShape[indicesShape.length - 1]; + const xData = backend.dataIdMap.get(params.dataId); + const xId = xData.id; + const indicesData = backend.dataIdMap.get(indices.dataId); + const indicesId = indicesData.id; + const stridesBytes = new Uint8Array(new Int32Array(strides).buffer); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmGatherNd(xId, CppDType[params.dtype], indicesId, numSlices, sliceRank, sliceSize, stridesBytes, outId); + return out; + } + const gatherNdConfig = { + kernelName: tfjsCore.GatherNd, + backendName: 'wasm', + setupFunc: setup$d, + kernelFunc: gatherNd + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmGather; + function setup$e(backend) { + wasmGather = backend.wasm.cwrap('Gather', null /*void*/, [ + 'number', + 'number', + 'array', + 'number', + 'number', + 'number', + 'array', + 'number' // outId + ]); + } + function gatherV2(args) { + const { backend, inputs, attrs } = args; + const { x, indices } = inputs; + const { axis } = attrs; + const newShape = x.shape.slice(); + newShape[axis] = tfjsCore.util.sizeFromShape(indices.shape); + const stridesSize = x.shape.length - 1; + const out = backend.makeOutput(newShape, x.dtype); + if (tfjsCore.util.sizeFromShape(x.shape) === 0) { + return out; + } + const xData = backend.dataIdMap.get(x.dataId); + const xId = xData.id; + const indicesData = backend.dataIdMap.get(indices.dataId); + const indicesId = indicesData.id; + const outId = backend.dataIdMap.get(out.dataId).id; + const xStridesBytes = new Uint8Array(new Int32Array(tfjsCore.util.computeStrides(x.shape)).buffer); + const outStridesBytes = new Uint8Array(new Int32Array(tfjsCore.util.computeStrides(newShape)).buffer); + wasmGather(xId, CppDType[x.dtype], xStridesBytes, stridesSize, indicesId, axis, outStridesBytes, outId); + // reshape + const parsedAxis = tfjsCore.util.parseAxisParam(axis, x.shape)[0]; + const shapeInfo = tfjsCore.backend_util.segment_util.collectGatherOpShapeInfo(x, indices, parsedAxis); + out.shape = shapeInfo.outputShape; + return out; + } + const gatherV2Config = { + kernelName: tfjsCore.GatherV2, + backendName: 'wasm', + setupFunc: setup$e, + kernelFunc: gatherV2 + }; + + const supportsFullBroadcast$4 = false; + const greaterConfig = createBinaryKernelConfig('Greater', supportsFullBroadcast$4, 'bool'); + + const supportsFullBroadcast$5 = false; + const greaterEqualConfig = createBinaryKernelConfig('GreaterEqual', supportsFullBroadcast$5, 'bool'); + + const supportsFullBroadcast$6 = false; + const lessConfig = createBinaryKernelConfig('Less', supportsFullBroadcast$6, 'bool'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$7 = false; + const lessEqualConfig = createBinaryKernelConfig('LessEqual', supportsFullBroadcast$7, 'bool'); + + const logConfig = createUnaryKernelConfig('Log'); + + const supportsFullBroadcast$8 = false; + const logicalAndConfig = createBinaryKernelConfig('LogicalAnd', supportsFullBroadcast$8, 'bool'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmMax; + function setup$f(backend) { + wasmMax = + backend.wasm.cwrap('Max', null /*void*/, ['number, number, number']); + } + function max(args) { + const { backend, inputs, attrs } = args; + const { reductionIndices: axis, keepDims } = attrs; + const { x } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + let inputId = xId; + let input = x; + const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); + if (inputWasTransposed) { + const transposedId = backend.dataIdMap.get(transposed.dataId).id; + input = transposed; + inputId = transposedId; + } + const inputRank = input.shape.length; + tfjsCore.backend_util.assertAxesAreInnerMostDims('max', axes, inputRank); + const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, axes); + const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); + const out = backend.makeOutput(outShape, x.dtype); + if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { + const outId = backend.dataIdMap.get(out.dataId).id; + wasmMax(inputId, reduceSize, outId); + } + if (inputWasTransposed) { + // dispose of the transposed tensor. + backend.disposeData(transposed.dataId); + } + if (keepDims) { + // reshape + const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); + out.shape = newShape; + } + return out; + } + const maxConfig = { + kernelName: tfjsCore.Max, + backendName: 'wasm', + setupFunc: setup$f, + kernelFunc: max + }; + + const supportsFullBroadcast$9 = false; + const maximumConfig = createBinaryKernelConfig('Maximum', supportsFullBroadcast$9); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmMaxPool; + function setup$g(backend) { + wasmMaxPool = backend.wasm.cwrap('MaxPool', null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function maxPool(args) { + const { inputs, attrs, backend } = args; + const x = inputs.x; + const xId = backend.dataIdMap.get(x.dataId).id; + const { filterSize, strides, pad, dimRoundingMode } = attrs; + const convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const dilationHeight = convInfo.dilationHeight; + const dilationWidth = convInfo.dilationWidth; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const inputChannels = convInfo.inChannels; + const outputChannels = convInfo.outChannels; + if (convInfo.dataFormat !== 'channelsLast') { + throw new Error(`wasm backend does not support dataFormat:'` + + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmMaxPool(xId, x.shape[0], x.shape[1], x.shape[2], filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); + return out; + } + const maxPoolConfig = { + kernelName: 'MaxPool', + backendName: 'wasm', + setupFunc: setup$g, + kernelFunc: maxPool + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmMin; + function setup$h(backend) { + wasmMin = + backend.wasm.cwrap('Min', null /*void*/, ['number, number, number']); + } + function min(args) { + const { backend, inputs, attrs } = args; + const { axis, keepDims } = attrs; + const { x } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + let inputId = xId; + let input = x; + const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); + if (inputWasTransposed) { + const transposedId = backend.dataIdMap.get(transposed.dataId).id; + if (transposedId !== xId) { + // transpose was not a no-op. We will need to dispose of this + // once we are done. + input = transposed; + inputId = transposedId; + } + } + const inputRank = input.shape.length; + tfjsCore.backend_util.assertAxesAreInnerMostDims('min', axes, inputRank); + const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, axes); + const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); + const out = backend.makeOutput(outShape, input.dtype); + if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { + const outId = backend.dataIdMap.get(out.dataId).id; + wasmMin(inputId, reduceSize, outId); + } + if (inputWasTransposed) { + // dispose of the transposed tensor. + backend.disposeData(transposed.dataId); + } + if (keepDims) { + // reshape + const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); + out.shape = newShape; + } + return out; + } + const minConfig = { + kernelName: tfjsCore.Min, + backendName: 'wasm', + setupFunc: setup$h, + kernelFunc: min + }; + + const supportsFullBroadcast$a = false; + const minimumConfig = createBinaryKernelConfig('Minimum', supportsFullBroadcast$a); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$b = true; + const multiplyConfig = createBinaryKernelConfig(tfjsCore.Multiply, supportsFullBroadcast$b); + + const negateConfig = createUnaryKernelConfig('Negate'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Parse the result of the c++ method, which has the shape equivalent to + * `Result`. + */ + function parseResultStruct(backend, resOffset) { + const result = new Int32Array(backend.wasm.HEAPU8.buffer, resOffset, 4); + const pSelectedIndices = result[0]; + const selectedSize = result[1]; + const pSelectedScores = result[2]; + const pValidOutputs = result[3]; + // Since the result was allocated on the heap, we have to delete it. + backend.wasm._free(resOffset); + return { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs }; + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$2; + function setup$i(backend) { + wasmFunc$2 = backend.wasm.cwrap('NonMaxSuppressionV3', 'number', // Result* + [ + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function kernelFunc(args) { + const { backend, inputs, attrs } = args; + const { iouThreshold, maxOutputSize, scoreThreshold } = attrs; + const { boxes, scores } = inputs; + const boxesId = backend.dataIdMap.get(boxes.dataId).id; + const scoresId = backend.dataIdMap.get(scores.dataId).id; + const resOffset = wasmFunc$2(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold); + const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); + // Since we are not using scores for V3, we have to delete it from the heap. + backend.wasm._free(pSelectedScores); + backend.wasm._free(pValidOutputs); + const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); + return selectedIndicesTensor; + } + const nonMaxSuppressionV3Config = { + kernelName: 'NonMaxSuppressionV3', + backendName: 'wasm', + setupFunc: setup$i, + kernelFunc, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$3; + function setup$j(backend) { + wasmFunc$3 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV4, 'number', // Result* + [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'bool', + ]); + } + function nonMaxSuppressionV4(args) { + const { backend, inputs, attrs } = args; + const { iouThreshold, maxOutputSize, scoreThreshold, padToMaxOutputSize } = attrs; + const { boxes, scores } = inputs; + const boxesId = backend.dataIdMap.get(boxes.dataId).id; + const scoresId = backend.dataIdMap.get(scores.dataId).id; + const resOffset = wasmFunc$3(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize); + const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); + // Since we are not using scores for V4, we have to delete it from the heap. + backend.wasm._free(pSelectedScores); + const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); + const validOutputsTensor = backend.makeOutput([], 'int32', pValidOutputs); + return [selectedIndicesTensor, validOutputsTensor]; + } + const nonMaxSuppressionV4Config = { + kernelName: tfjsCore.NonMaxSuppressionV4, + backendName: 'wasm', + setupFunc: setup$j, + kernelFunc: nonMaxSuppressionV4, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$4; + function setup$k(backend) { + wasmFunc$4 = backend.wasm.cwrap('NonMaxSuppressionV5', 'number', // Result* + [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function kernelFunc$1(args) { + const { backend, inputs, attrs } = args; + const { iouThreshold, maxOutputSize, scoreThreshold, softNmsSigma } = attrs; + const { boxes, scores } = inputs; + const boxesId = backend.dataIdMap.get(boxes.dataId).id; + const scoresId = backend.dataIdMap.get(scores.dataId).id; + const resOffset = wasmFunc$4(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma); + const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); + // Since we are not using validOutputs for V5, we have to delete it from the + // heap. + backend.wasm._free(pValidOutputs); + const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); + const selectedScoresTensor = backend.makeOutput([selectedSize], 'float32', pSelectedScores); + return [selectedIndicesTensor, selectedScoresTensor]; + } + const nonMaxSuppressionV5Config = { + kernelName: 'NonMaxSuppressionV5', + backendName: 'wasm', + setupFunc: setup$k, + kernelFunc: kernelFunc$1, + }; + + const supportsFullBroadcast$c = false; + const notEqualConfig = createBinaryKernelConfig('NotEqual', supportsFullBroadcast$c, 'bool'); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmOneHot; + function setup$l(backend) { + wasmOneHot = backend.wasm.cwrap('OneHot', null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number' // out_id + ]); + } + function oneHot(args) { + const { inputs, backend, attrs } = args; + const { indices } = inputs; + const { depth, onValue, offValue } = attrs; + const out = backend.makeOutput([...indices.shape, depth], 'int32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const indicesData = backend.dataIdMap.get(indices.dataId); + const indicesId = indicesData.id; + wasmOneHot(indicesId, depth, onValue, offValue, outId); + return out; + } + const oneHotConfig = { + kernelName: tfjsCore.OneHot, + backendName: 'wasm', + setupFunc: setup$l, + kernelFunc: oneHot, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function onesLike(args) { + const { inputs: { x }, backend } = args; + const out = backend.makeOutput(x.shape, x.dtype); + const outVals = backend.typedArrayFromHeap(out); + outVals.fill(1); + return out; + } + const onesLikeConfig = { + kernelName: 'OnesLike', + backendName: 'wasm', + kernelFunc: onesLike, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmPadV2; + function setup$m(backend) { + wasmPadV2 = backend.wasm.cwrap(tfjsCore.PadV2, null /* void */, [ + 'number', + 'array', + 'number', + 'number', + 'array', + 'array', + 'number', + 'number', + ]); + } + function pad(args) { + const { inputs: { x }, backend, attrs: { paddings, constantValue } } = args; + const outShape = paddings.map((p, i) => p[0] /* beforePad */ + x.shape[i] + p[1] /* afterPad */); + const xId = backend.dataIdMap.get(x.dataId).id; + const out = backend.makeOutput(outShape, x.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); + const prePaddingsFlat = paddings.map(padTuple => padTuple[0]); + const postPaddingsFlat = paddings.map(padTuple => padTuple[1]); + const prePaddingsBytes = new Uint8Array(new Int32Array(prePaddingsFlat).buffer); + const postPaddingsBytes = new Uint8Array(new Int32Array(postPaddingsFlat).buffer); + wasmPadV2(xId, xShapeBytes, x.shape.length, CppDType[x.dtype], prePaddingsBytes, postPaddingsBytes, constantValue, outId); + return out; + } + const padV2Config = { + kernelName: tfjsCore.PadV2, + backendName: 'wasm', + kernelFunc: pad, + setupFunc: setup$m + }; + + const supportsFullBroadcast$d = false; + const powConfig = createBinaryKernelConfig('Pow', supportsFullBroadcast$d); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmPrelu; + function setup$n(backend) { + wasmPrelu = backend.wasm.cwrap('Prelu', null /* void */, [ + 'number', + 'number', + 'number' // out_id + ]); + } + function prelu(args) { + const { inputs, backend } = args; + const { x, alpha } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const weightsId = backend.dataIdMap.get(alpha.dataId).id; + const out = backend.makeOutput(x.shape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmPrelu(xId, weightsId, outId); + return out; + } + const preluConfig = { + kernelName: 'Prelu', + backendName: 'wasm', + setupFunc: setup$n, + kernelFunc: prelu + }; + + const reluConfig = createUnaryKernelConfig('Relu'); + + const relu6Config = createUnaryKernelConfig('Relu6'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function reshape(args) { + const { inputs, attrs } = args; + const { x } = inputs; + const { shape } = attrs; + return { dataId: x.dataId, shape, dtype: x.dtype }; + } + const reshapeConfig = { + kernelName: tfjsCore.Reshape, + backendName: 'wasm', + kernelFunc: reshape, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmResizeBilinear; + function setup$o(backend) { + wasmResizeBilinear = backend.wasm.cwrap('ResizeBilinear', null /*void*/, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number' // outId + ]); + } + function resizeBilinear(args) { + const { backend, inputs, attrs } = args; + const { images } = inputs; + const { alignCorners, size } = attrs; + const [newHeight, newWidth] = size; + const [batch, oldHeight, oldWidth, numChannels] = images.shape; + const outShape = [batch, newHeight, newWidth, numChannels]; + let xData = backend.dataIdMap.get(images.dataId); + let castedData; + if (xData.dtype !== 'float32') { + castedData = + cast({ backend, inputs: { x: images }, attrs: { dtype: 'float32' } }); + xData = backend.dataIdMap.get(castedData.dataId); + } + const xId = xData.id; + const out = backend.makeOutput(outShape, 'float32'); + if (tfjsCore.util.sizeFromShape(images.shape) === 0) { + return out; + } + const outId = backend.dataIdMap.get(out.dataId).id; + wasmResizeBilinear(xId, batch, oldHeight, oldWidth, numChannels, newHeight, newWidth, alignCorners ? 1 : 0, outId); + if (castedData != null) { + backend.disposeData(castedData.dataId); + } + return out; + } + const resizeBilinearConfig = { + kernelName: tfjsCore.ResizeBilinear, + backendName: 'wasm', + setupFunc: setup$o, + kernelFunc: resizeBilinear + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmReverse; + function setup$p(backend) { + wasmReverse = backend.wasm.cwrap(tfjsCore.Reverse, null, [ + 'number', + 'array', + 'number', + 'array', + 'number', + 'number' // out_id + ]); + } + function reverse(args) { + const { inputs, backend, attrs } = args; + const { x } = inputs; + const { dims } = attrs; + const axes = tfjsCore.util.parseAxisParam(dims, x.shape); + if (x.shape.length === 0) { + return identity({ inputs: { x }, backend }); + } + const out = backend.makeOutput(x.shape, x.dtype); + const xId = backend.dataIdMap.get(x.dataId).id; + const outId = backend.dataIdMap.get(out.dataId).id; + const axesBytes = new Uint8Array(new Int32Array(axes).buffer); + const outShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); + wasmReverse(xId, axesBytes, axes.length, outShapeBytes, x.shape.length, outId); + return reshape({ inputs: { x: out }, attrs: { shape: x.shape }, backend }); + } + const reverseConfig = { + kernelName: tfjsCore.Reverse, + backendName: 'wasm', + kernelFunc: reverse, + setupFunc: setup$p + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmRotate; + function setup$q(backend) { + wasmRotate = backend.wasm.cwrap(tfjsCore.RotateWithOffset, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'array', + 'number', + 'number', + ]); + } + function rotateWithOffset(args) { + const { inputs, backend, attrs } = args; + const { image } = inputs; + const { radians, fillValue, center } = attrs; + const out = backend.makeOutput(image.shape, image.dtype); + const imageId = backend.dataIdMap.get(image.dataId).id; + const outId = backend.dataIdMap.get(out.dataId).id; + const [batch, imageHeight, imageWidth, numChannels] = image.shape; + const [centerX, centerY] = tfjsCore.backend_util.getImageCenter(center, imageHeight, imageWidth); + const fillIsBlack = fillValue === 0; + const fullOpacityValue = 255; + const fillValues = typeof fillValue === 'number' ? + [fillValue, fillValue, fillValue, fillIsBlack ? 0 : fullOpacityValue] : + [...fillValue, fullOpacityValue]; + const fillBytes = new Uint8Array(new Int32Array(fillValues).buffer); + wasmRotate(imageId, batch, imageHeight, imageWidth, numChannels, radians, centerX, centerY, fillBytes, fillValues.length, outId); + return out; + } + const rotateWithOffsetConfig = { + kernelName: tfjsCore.RotateWithOffset, + backendName: 'wasm', + kernelFunc: rotateWithOffset, + setupFunc: setup$q + }; + + const rsqrtConfig = createUnaryKernelConfig('Rsqrt'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmScatterNd; + function setup$r(backend) { + wasmScatterNd = backend.wasm.cwrap('ScatterNd', null /*void*/, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'array', + 'number', + 'number' // outId + ]); + } + function scatterNd(args) { + const { backend, inputs, attrs } = args; + const { indices, updates } = inputs; + const { shape } = attrs; + const out = backend.makeOutput(shape, updates.dtype); + if (tfjsCore.util.sizeFromShape(shape) === 0) { + return out; + } + const { sliceRank, numUpdates, sliceSize, strides, outputSize } = tfjsCore.scatter_util.calculateShapes(updates, indices, shape); + const indicesData = backend.dataIdMap.get(indices.dataId); + const indicesId = indicesData.id; + const updatesData = backend.dataIdMap.get(updates.dataId); + const updatesId = updatesData.id; + const stridesBytes = new Uint8Array(new Int32Array(strides).buffer); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmScatterNd(indicesId, updatesId, CppDType[updates.dtype], sliceRank, numUpdates, sliceSize, stridesBytes, outputSize, outId); + return out; + } + const scatterNdConfig = { + kernelName: tfjsCore.ScatterNd, + backendName: 'wasm', + setupFunc: setup$r, + kernelFunc: scatterNd + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmSelect; + function setup$s(backend) { + wasmSelect = backend.wasm.cwrap(tfjsCore.SelectV2, null, [ + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function select(args) { + const { inputs, backend } = args; + const { condition, t, e } = inputs; + const conditionId = backend.dataIdMap.get(condition.dataId).id; + const tId = backend.dataIdMap.get(t.dataId).id; + const eId = backend.dataIdMap.get(e.dataId).id; + const out = backend.makeOutput(t.shape, t.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + const cRank = condition.shape.length; + const tRank = t.shape.length; + const offset = cRank === 0 || cRank > 1 || tRank === 1 ? + 1 : + tfjsCore.util.sizeFromShape(t.shape.slice(1)); + wasmSelect(conditionId, tId, eId, offset, outId); + return out; + } + const selectV2Config = { + kernelName: tfjsCore.SelectV2, + backendName: 'wasm', + kernelFunc: select, + setupFunc: setup$s + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$5; + function setup$t(backend) { + wasmFunc$5 = + backend.wasm.cwrap('Sigmoid', null /* void */, ['number', 'number']); + } + function sigmoid(args) { + const { backend, inputs: { x } } = args; + const xId = backend.dataIdMap.get(x.dataId).id; + const out = backend.makeOutput(x.shape, x.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(out.shape) === 0) { + return out; + } + wasmFunc$5(xId, outId); + return out; + } + const sigmoidConfig = { + kernelName: 'Sigmoid', + backendName: 'wasm', + setupFunc: setup$t, + kernelFunc: sigmoid + }; + + const sinConfig = createUnaryKernelConfig('Sin'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function slice(args) { + const { inputs: { x }, attrs: { begin, size }, backend } = args; + const [begin_, size_] = tfjsCore.slice_util.parseSliceParams(x, begin, size); + const isContinous = tfjsCore.slice_util.isSliceContinous(x.shape, begin_, size_); + const xVals = backend.typedArrayFromHeap(x); + const out = backend.makeOutput(size_, x.dtype); + const outVals = backend.typedArrayFromHeap(out); + const xStrides = tfjsCore.util.computeStrides(x.shape); + if (isContinous) { + const flatOffset = tfjsCore.slice_util.computeFlatOffset(begin_, xStrides); + outVals.set(xVals.subarray(flatOffset, flatOffset + tfjsCore.util.sizeFromShape(size_))); + return out; + } + const rank = x.shape.length; + if (rank === 2) { + slice2d(xVals, xStrides[0], outVals, begin_, size_); + } + else if (rank === 3) { + slice3d(xVals, xStrides[0], xStrides[1], outVals, begin_, size_); + } + else if (rank === 4) { + slice4d(xVals, xStrides[0], xStrides[1], xStrides[2], outVals, begin_, size_); + } + else { + genericSliceSlow(xVals, x, outVals, begin_, size_); + } + return out; + } + function slice2d(xVals, xStride, outVals, begin, size) { + let outOffset = 0; + const beginI = begin[0]; + const beginJ = begin[1]; + const endI = beginI + size[0]; + for (let i = beginI; i < endI; i++) { + const xOffset = i * xStride + beginJ; + outVals.set(xVals.subarray(xOffset, xOffset + size[1]), outOffset); + outOffset += size[1]; + } + } + function slice3d(xVals, xStride1, xStride2, outVals, begin, size) { + let outOffset = 0; + const beginI = begin[0]; + const beginJ = begin[1]; + const beginK = begin[2]; + const endI = beginI + size[0]; + const endJ = beginJ + size[1]; + for (let i = beginI; i < endI; i++) { + for (let j = beginJ; j < endJ; j++) { + const xOffset = i * xStride1 + j * xStride2 + beginK; + outVals.set(xVals.subarray(xOffset, xOffset + size[2]), outOffset); + outOffset += size[2]; + } + } + } + function slice4d(xVals, xStride1, xStride2, xStride3, outVals, begin, size) { + let outOffset = 0; + const beginI = begin[0]; + const beginJ = begin[1]; + const beginK = begin[2]; + const endI = beginI + size[0]; + const endJ = beginJ + size[1]; + const endK = beginK + size[2]; + const beginL = begin[3]; + for (let i = beginI; i < endI; i++) { + for (let j = beginJ; j < endJ; j++) { + for (let k = beginK; k < endK; k++) { + const xOffset = i * xStride1 + j * xStride2 + k * xStride3 + beginL; + outVals.set(xVals.subarray(xOffset, xOffset + size[3]), outOffset); + outOffset += size[3]; + } + } + } + } + function genericSliceSlow(xVals, xInfo, outVals, begin, size) { + const outBuf = tfjsCore.buffer(size, xInfo.dtype, outVals); + const xBuf = tfjsCore.buffer(xInfo.shape, xInfo.dtype, xVals); + for (let i = 0; i < outBuf.size; ++i) { + const loc = outBuf.indexToLoc(i); + const xLoc = loc.map((idx, j) => idx + begin[j]); + outVals[i] = xBuf.get(...xLoc); + } + } + const sliceConfig = { + kernelName: 'Slice', + backendName: 'wasm', + kernelFunc: slice, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$6; + function setup$u(backend) { + wasmFunc$6 = backend.wasm.cwrap('Softmax', null /* void */, [ + 'number', + 'number', + 'number', + 'number' // batch + ]); + } + function softmax(args) { + const { backend, inputs: { logits }, attrs: { dim } } = args; + const xId = backend.dataIdMap.get(logits.dataId).id; + const out = backend.makeOutput(logits.shape, logits.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + const channels = logits.shape[dim]; + const batch = tfjsCore.util.sizeFromShape(logits.shape) / channels; + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(out.shape) === 0) { + return out; + } + wasmFunc$6(xId, outId, channels, batch); + return out; + } + const softmaxConfig = { + kernelName: 'Softmax', + backendName: 'wasm', + setupFunc: setup$u, + kernelFunc: softmax + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function split(args) { + const { inputs, attrs, backend } = args; + const { x } = inputs; + const { numOrSizeSplits, axis } = attrs; + const $axis = tfjsCore.util.parseAxisParam(axis, x.shape)[0]; + const splitSizes = tfjsCore.backend_util.prepareSplitSize(x, numOrSizeSplits, axis); + const begin = new Array(x.shape.length).fill(0); + const size = x.shape.slice(); + return splitSizes.map(s => { + const xSliceSize = [...size]; + xSliceSize[$axis] = s; + const xSlice = slice({ inputs: { x }, attrs: { begin, size: xSliceSize }, backend }); + begin[$axis] += s; + return xSlice; + }); + } + const splitVConfig = { + kernelName: tfjsCore.SplitV, + backendName: 'wasm', + kernelFunc: split + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const sqrtConfig = createUnaryKernelConfig('Sqrt'); + + const squareConfig = createUnaryKernelConfig('Square'); + + const supportsFullBroadcast$e = true; + const subConfig = createBinaryKernelConfig('Sub', supportsFullBroadcast$e); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmSum; + function setup$v(backend) { + wasmSum = + backend.wasm.cwrap('Sum', null /*void*/, ['number, number, number']); + } + function sum(args) { + const { backend, inputs, attrs } = args; + const { axis, keepDims } = attrs; + const { x } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + let inputId = xId; + let input = x; + const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); + let reductionAxes = axes; + if (inputWasTransposed) { + const transposedId = backend.dataIdMap.get(transposed.dataId).id; + if (transposedId !== xId) { + // transpose was not a no-op. We will need to dispose of this + // once we are done. + input = transposed; + inputId = transposedId; + reductionAxes = tfjsCore.backend_util.getInnerMostAxes(reductionAxes.length, input.shape.length); + } + } + tfjsCore.backend_util.assertAxesAreInnerMostDims('sum', reductionAxes, input.shape.length); + const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, reductionAxes); + const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); + const out = backend.makeOutput(outShape, input.dtype); + if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { + const outId = backend.dataIdMap.get(out.dataId).id; + wasmSum(inputId, reduceSize, outId); + } + if (inputWasTransposed) { + // dispose of the transposed tensor. + backend.disposeData(transposed.dataId); + } + if (keepDims) { + // reshape + const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); + out.shape = newShape; + } + return out; + } + const sumConfig = { + kernelName: tfjsCore.Sum, + backendName: 'wasm', + setupFunc: setup$v, + kernelFunc: sum + }; + + const tanhConfig = createUnaryKernelConfig('Tanh'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmTile; + function setup$w(backend) { + wasmTile = backend.wasm.cwrap('Tile', null /* void */, [ + 'number', + 'array', + 'number', + 'array', + 'number', + 'number' // out_id + ]); + } + function tile(args) { + const { inputs, backend, attrs } = args; + const { x } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const { reps } = attrs; + const newShape = new Array(x.shape.length); + for (let i = 0; i < newShape.length; i++) { + newShape[i] = x.shape[i] * reps[i]; + } + const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); + const newShapeBytes = new Uint8Array(new Int32Array(newShape).buffer); + const out = backend.makeOutput(newShape, x.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmTile(xId, xShapeBytes, x.shape.length, newShapeBytes, newShape.length, CppDType[out.dtype], outId); + return out; + } + const tileConfig = { + kernelName: 'Tile', + backendName: 'wasm', + setupFunc: setup$w, + kernelFunc: tile + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function unpack(args) { + const { inputs, backend, attrs } = args; + const { value } = inputs; + const { axis } = attrs; + const numOutputs = value.shape[axis]; + const rank = value.shape.length; + const outShape = new Array(rank - 1); + let outIndex = 0; + for (let i = 0; i < rank; i++) { + if (i !== axis) { + outShape[outIndex++] = value.shape[i]; + } + } + const outs = new Array(numOutputs); + const begin = new Array(rank).fill(0); + const size = value.shape.slice(); + size[axis] = 1; + for (let i = 0; i < outs.length; i++) { + begin[axis] = i; + outs[i] = slice({ inputs: { x: value }, attrs: { begin, size }, backend }); + } + return outs.map(({ dataId, dtype }) => ({ dataId, dtype, shape: outShape })); + } + const unpackConfig = { + kernelName: tfjsCore.Unpack, + backendName: 'wasm', + kernelFunc: unpack, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function zerosLike(args) { + const { inputs: { x }, backend } = args; + const out = backend.makeOutput(x.shape, x.dtype); + const outVals = backend.typedArrayFromHeap(out); + outVals.fill(0); + return out; + } + const zerosLikeConfig = { + kernelName: 'ZerosLike', + backendName: 'wasm', + kernelFunc: zerosLike, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // List all kernel configs here + const kernelConfigs = [ + absConfig, + addConfig, + addNConfig, + argMaxConfig, + avgPoolConfig, + batchMatMulConfig, + castConfig, + clipByValueConfig, + concatConfig, + conv2DConfig, + conv2DBackpropInputConfig, + cosConfig, + cropAndResizeConfig, + depthwiseConv2DNativeConfig, + divConfig, + equalConfig, + expConfig, + fillConfig, + floorDivConfig, + fusedMatMulConfig, + fusedBatchNormConfig, + fusedConv2DConfig, + fusedDepthwiseConv2DConfig, + gatherNdConfig, + gatherV2Config, + greaterConfig, + greaterEqualConfig, + identityConfig, + lessConfig, + lessEqualConfig, + logConfig, + logicalAndConfig, + maxConfig, + maximumConfig, + maxPoolConfig, + minConfig, + minimumConfig, + multiplyConfig, + negateConfig, + nonMaxSuppressionV3Config, + nonMaxSuppressionV4Config, + nonMaxSuppressionV5Config, + notEqualConfig, + oneHotConfig, + onesLikeConfig, + padV2Config, + powConfig, + preluConfig, + reluConfig, + relu6Config, + reshapeConfig, + resizeBilinearConfig, + reverseConfig, + rotateWithOffsetConfig, + rsqrtConfig, + scatterNdConfig, + selectV2Config, + sigmoidConfig, + sinConfig, + sliceConfig, + softmaxConfig, + splitVConfig, + sqrtConfig, + squareConfig, + subConfig, + sumConfig, + tanhConfig, + tileConfig, + transposeConfig, + unpackConfig, + zerosLikeConfig + ]; + for (const kernelConfig of kernelConfigs) { + tfjsCore.registerKernel(kernelConfig); + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const ENV = tfjsCore.env(); + /** + * True if SIMD is supported. + */ + // From: https://github.com/GoogleChromeLabs/wasm-feature-detect + ENV.registerFlag('WASM_HAS_SIMD_SUPPORT', async () => WebAssembly.validate(new Uint8Array([ + 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, + 2, 1, 0, 10, 9, 1, 7, 0, 65, 0, 253, 15, 26, 11 + ]))); + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var tfjsBackendWasmThreaded = createCommonjsModule(function (module, exports) { + var WasmBackendModule = (function() { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( + function(WasmBackendModule) { + WasmBackendModule = WasmBackendModule || {}; + + function GROWABLE_HEAP_I8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP8}function GROWABLE_HEAP_U8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU8}function GROWABLE_HEAP_I32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP32}function GROWABLE_HEAP_U32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPF64}var Module=typeof WasmBackendModule!=="undefined"?WasmBackendModule:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(Module["ENVIRONMENT"]){throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -s ENVIRONMENT=web or -s ENVIRONMENT=node)")}var ENVIRONMENT_IS_PTHREAD=Module["ENVIRONMENT_IS_PTHREAD"]||false;if(ENVIRONMENT_IS_PTHREAD){buffer=Module["buffer"];DYNAMIC_BASE=Module["DYNAMIC_BASE"];DYNAMICTOP_PTR=Module["DYNAMICTOP_PTR"];}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};var nodeWorkerThreads;try{nodeWorkerThreads=worker_threads;}catch(e){console.error('The "worker_threads" module is not supported in this node.js build - perhaps a newer version is needed?');throw e}Worker=nodeWorkerThreads.Worker;}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}if(ENVIRONMENT_IS_NODE){read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};}else{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}else{throw new Error("environment detection error")}if(ENVIRONMENT_IS_NODE){if(typeof performance==="undefined"){performance=perf_hooks.performance;}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(!Object.getOwnPropertyDescriptor(Module,"arguments"))Object.defineProperty(Module,"arguments",{configurable:true,get:function(){abort("Module.arguments has been replaced with plain arguments_");}});if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(!Object.getOwnPropertyDescriptor(Module,"thisProgram"))Object.defineProperty(Module,"thisProgram",{configurable:true,get:function(){abort("Module.thisProgram has been replaced with plain thisProgram");}});if(Module["quit"])quit_=Module["quit"];if(!Object.getOwnPropertyDescriptor(Module,"quit"))Object.defineProperty(Module,"quit",{configurable:true,get:function(){abort("Module.quit has been replaced with plain quit_");}});assert(typeof Module["memoryInitializerPrefixURL"]==="undefined","Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["pthreadMainPrefixURL"]==="undefined","Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["cdInitializerPrefixURL"]==="undefined","Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["filePackagePrefixURL"]==="undefined","Module.filePackagePrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["read"]==="undefined","Module.read option was removed (modify read_ in JS)");assert(typeof Module["readAsync"]==="undefined","Module.readAsync option was removed (modify readAsync in JS)");assert(typeof Module["readBinary"]==="undefined","Module.readBinary option was removed (modify readBinary in JS)");assert(typeof Module["setWindowTitle"]==="undefined","Module.setWindowTitle option was removed (modify setWindowTitle in JS)");assert(typeof Module["TOTAL_MEMORY"]==="undefined","Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");if(!Object.getOwnPropertyDescriptor(Module,"read"))Object.defineProperty(Module,"read",{configurable:true,get:function(){abort("Module.read has been replaced with plain read_");}});if(!Object.getOwnPropertyDescriptor(Module,"readAsync"))Object.defineProperty(Module,"readAsync",{configurable:true,get:function(){abort("Module.readAsync has been replaced with plain readAsync");}});if(!Object.getOwnPropertyDescriptor(Module,"readBinary"))Object.defineProperty(Module,"readBinary",{configurable:true,get:function(){abort("Module.readBinary has been replaced with plain readBinary");}});if(!Object.getOwnPropertyDescriptor(Module,"setWindowTitle"))Object.defineProperty(Module,"setWindowTitle",{configurable:true,get:function(){abort("Module.setWindowTitle has been replaced with plain setWindowTitle");}});assert(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER||ENVIRONMENT_IS_NODE,"Pthreads do not work in this environment yet (need Web Workers, or an alternative to them)");var stackSave;var stackRestore;var stackAlloc;stackSave=stackRestore=stackAlloc=function(){abort("cannot use the stack before compiled code is ready to run, and has provided stack access");};function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text);}}var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(!Object.getOwnPropertyDescriptor(Module,"wasmBinary"))Object.defineProperty(Module,"wasmBinary",{configurable:true,get:function(){abort("Module.wasmBinary has been replaced with plain wasmBinary");}});var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(!Object.getOwnPropertyDescriptor(Module,"noExitRuntime"))Object.defineProperty(Module,"noExitRuntime",{configurable:true,get:function(){abort("Module.noExitRuntime has been replaced with plain noExitRuntime");}});if(typeof WebAssembly!=="object"){abort("No WebAssembly support found. Build with -s WASM=0 to target JavaScript instead.");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":160,"maximum":160+0,"element":"anyfunc"});var wasmModule;var threadInfoStruct=0;var selfThreadId=0;var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;assert(returnType!=="array",'Return type should not be "array".');if(args){for(var i=0;i=endIdx)){var u0=heap[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heap[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heap[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2;}else{if((u0&248)!=240)warnOnce("Invalid UTF-8 leading byte 0x"+u0.toString(16)+" encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!");u0=(u0&7)<<18|u1<<12|u2<<6|heap[idx++]&63;}if(u0<65536){str+=String.fromCharCode(u0);}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023);}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;if(u>=2097152)warnOnce("Invalid Unicode code point 0x"+u.toString(16)+" encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).");heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){assert(typeof maxBytesToWrite=="number","stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");return stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4;}return len}function writeArrayToMemory(array,buffer){assert(array.length>=0,"writeArrayToMemory array must have a length (should be an array or typed array)");GROWABLE_HEAP_I8().set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var STACK_BASE=5256544,STACKTOP=STACK_BASE,STACK_MAX=13664,DYNAMIC_BASE=5256544,DYNAMICTOP_PTR=12736;assert(STACK_BASE%16===0,"stack must start aligned");assert(DYNAMIC_BASE%16===0,"heap must start aligned");if(ENVIRONMENT_IS_PTHREAD){STACK_MAX=STACKTOP=STACK_MAX=2147483647;}var TOTAL_STACK=5242880;if(Module["TOTAL_STACK"])assert(TOTAL_STACK===Module["TOTAL_STACK"],"the stack size can no longer be determined at runtime");var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||1073741824;if(!Object.getOwnPropertyDescriptor(Module,"INITIAL_MEMORY"))Object.defineProperty(Module,"INITIAL_MEMORY",{configurable:true,get:function(){abort("Module.INITIAL_MEMORY has been replaced with plain INITIAL_INITIAL_MEMORY");}});assert(INITIAL_INITIAL_MEMORY>=TOTAL_STACK,"INITIAL_MEMORY should be larger than TOTAL_STACK, was "+INITIAL_INITIAL_MEMORY+"! (TOTAL_STACK="+TOTAL_STACK+")");assert(typeof Int32Array!=="undefined"&&typeof Float64Array!=="undefined"&&Int32Array.prototype.subarray!==undefined&&Int32Array.prototype.set!==undefined,"JS engine does not provide full typed array support");if(ENVIRONMENT_IS_PTHREAD){wasmMemory=Module["wasmMemory"];buffer=Module["buffer"];}else{if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":1073741824/WASM_PAGE_SIZE,"shared":true});if(!(wasmMemory.buffer instanceof SharedArrayBuffer)){err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");if(ENVIRONMENT_IS_NODE){console.log("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)");}throw Error("bad memory")}}}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;assert(INITIAL_INITIAL_MEMORY%WASM_PAGE_SIZE===0);assert(65536%WASM_PAGE_SIZE===0);updateGlobalBufferAndViews(buffer);if(!ENVIRONMENT_IS_PTHREAD){GROWABLE_HEAP_I32()[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;}function writeStackCookie(){assert((STACK_MAX&3)==0);GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1]=34821223;GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2]=2310721022;GROWABLE_HEAP_I32()[0]=1668509029;}function checkStackCookie(){var cookie1=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1];var cookie2=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2];if(cookie1!=34821223||cookie2!=2310721022){abort("Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x"+cookie2.toString(16)+" "+cookie1.toString(16));}if(GROWABLE_HEAP_I32()[0]!==1668509029)abort("Runtime error: The application has corrupted its heap memory area (address zero)!");}function abortStackOverflow(allocSize){abort("Stack overflow! Attempted to allocate "+allocSize+" bytes on the stack, but stack has only "+(STACK_MAX-stackSave()+allocSize)+" bytes available!");}(function(){var h16=new Int16Array(1);var h8=new Int8Array(h16.buffer);h16[0]=25459;if(h8[0]!==115||h8[1]!==99)throw "Runtime error: expected the system to be little-endian!"})();function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;if(ENVIRONMENT_IS_PTHREAD)runtimeInitialized=true;function preRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){checkStackCookie();assert(!runtimeInitialized);runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__);}function preMain(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;callRuntimeCallbacks(__ATMAIN__);}function postRun(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}assert(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;var runDependencyTracking={};function addRunDependency(id){assert(!ENVIRONMENT_IS_PTHREAD,"addRunDependency cannot be used in a pthread worker");runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(!runDependencyTracking[id]);runDependencyTracking[id]=1;if(runDependencyWatcher===null&&typeof setInterval!=="undefined"){runDependencyWatcher=setInterval(function(){if(ABORT){clearInterval(runDependencyWatcher);runDependencyWatcher=null;return}var shown=false;for(var dep in runDependencyTracking){if(!shown){shown=true;err("still waiting on run dependencies:");}err("dependency: "+dep);}if(shown){err("(end of list)");}},1e4);}}else{err("warning: run dependency added without ID");}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(runDependencyTracking[id]);delete runDependencyTracking[id];}else{err("warning: run dependency removed without ID");}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}if(ENVIRONMENT_IS_PTHREAD)console.error("Pthread aborting at "+(new Error).stack);what+="";out(what);err(what);ABORT=true;var output="abort("+what+") at "+stackTrace();what=output;throw new WebAssembly.RuntimeError(what)}var FS={error:function(){abort("Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -s FORCE_FILESYSTEM=1");},init:function(){FS.error();},createDataFile:function(){FS.error();},createPreloadedFile:function(){FS.error();},createLazyFile:function(){FS.error();},open:function(){FS.error();},mkdev:function(){FS.error();},registerDevice:function(){FS.error();},analyzePath:function(){FS.error();},loadFilesFromDB:function(){FS.error();},ErrnoError:function ErrnoError(){FS.error();}};Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm-threaded.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmModule=module;if(!ENVIRONMENT_IS_PTHREAD){var numWorkersToLoad=PThread.unusedWorkers.length;PThread.unusedWorkers.forEach(function(w){PThread.loadWasmModuleToWorker(w,function(){if(!--numWorkersToLoad)removeRunDependency("wasm-instantiate");});});}}if(!ENVIRONMENT_IS_PTHREAD){addRunDependency("wasm-instantiate");}var trueModule=Module;function receiveInstantiatedSource(output){assert(Module===trueModule,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");trueModule=null;receiveInstance(output["instance"],output["module"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}var ASM_CONSTS={};function initPthreadsJS(){PThread.initRuntime();}if(!ENVIRONMENT_IS_PTHREAD)__ATINIT__.push({func:function(){___wasm_call_ctors();}});function demangle(func){warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling");return func}function demangleAll(text){var regex=/\b_Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}var __pthread_ptr=0;var __pthread_is_main_runtime_thread=0;var __pthread_is_main_browser_thread=0;function __register_pthread_ptr(pthreadPtr,isMainBrowserThread,isMainRuntimeThread){pthreadPtr=pthreadPtr|0;isMainBrowserThread=isMainBrowserThread|0;isMainRuntimeThread=isMainRuntimeThread|0;__pthread_ptr=pthreadPtr;__pthread_is_main_browser_thread=isMainBrowserThread;__pthread_is_main_runtime_thread=isMainRuntimeThread;}Module["__register_pthread_ptr"]=__register_pthread_ptr;var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var __main_thread_futex_wait_address=13648;function _emscripten_futex_wake(addr,count){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0||count<0)return -28;if(count==0)return 0;if(count>=2147483647)count=Infinity;var mainThreadWaitAddress=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);var mainThreadWoken=0;if(mainThreadWaitAddress==addr){var loadedAddr=Atomics.compareExchange(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,mainThreadWaitAddress,0);if(loadedAddr==mainThreadWaitAddress){--count;mainThreadWoken=1;if(count<=0)return 1}}var ret=Atomics.notify(GROWABLE_HEAP_I32(),addr>>2,count);if(ret>=0)return ret+mainThreadWoken;throw "Atomics.notify returned an unexpected value "+ret}Module["_emscripten_futex_wake"]=_emscripten_futex_wake;function __kill_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _kill_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _kill_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];pthread.worker.terminate();PThread.freeThreadData(pthread);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(pthread.worker),1);pthread.worker.pthread=undefined;}function __cancel_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cancel_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cancel_thread!";var pthread=PThread.pthreads[pthread_ptr];pthread.worker.postMessage({"cmd":"cancel"});}function __cleanup_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cleanup_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cleanup_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];if(pthread){var worker=pthread.worker;PThread.returnWorkerToPool(worker);}}var PThread={MAIN_THREAD_ID:1,mainThreadInfo:{schedPolicy:0,schedPrio:0},unusedWorkers:[],runningWorkers:[],initRuntime:function(){__register_pthread_ptr(PThread.mainThreadBlock,!ENVIRONMENT_IS_WORKER,1);_emscripten_register_main_browser_thread_id(PThread.mainThreadBlock);},initMainThreadBlock:function(){assert(!ENVIRONMENT_IS_PTHREAD);var pthreadPoolSize=8;for(var i=0;i>2]=PThread.mainThreadBlock;var headPtr=PThread.mainThreadBlock+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var tlsMemory=13136;for(var i=0;i<128;++i)GROWABLE_HEAP_U32()[tlsMemory/4+i]=0;Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+104>>2,tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+40>>2,PThread.mainThreadBlock);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+44>>2,42);},initWorker:function(){},pthreads:{},exitHandlers:null,setThreadStatus:function(){},runExitHandlers:function(){if(PThread.exitHandlers!==null){while(PThread.exitHandlers.length>0){PThread.exitHandlers.pop()();}PThread.exitHandlers=null;}if(ENVIRONMENT_IS_PTHREAD&&threadInfoStruct)___pthread_tsd_run_dtors();},threadExit:function(exitCode){var tb=_pthread_self();if(tb){err("Pthread 0x"+tb.toString(16)+" exited.");Atomics.store(GROWABLE_HEAP_U32(),tb+4>>2,exitCode);Atomics.store(GROWABLE_HEAP_U32(),tb+0>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+60>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+64>>2,0);PThread.runExitHandlers();_emscripten_futex_wake(tb+0,2147483647);__register_pthread_ptr(0,0,0);threadInfoStruct=0;if(ENVIRONMENT_IS_PTHREAD){postMessage({"cmd":"exit"});}}},threadCancel:function(){PThread.runExitHandlers();Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+4>>2,-1);Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+0>>2,1);_emscripten_futex_wake(threadInfoStruct+0,2147483647);threadInfoStruct=selfThreadId=0;__register_pthread_ptr(0,0,0);postMessage({"cmd":"cancelDone"});},terminateAllThreads:function(){for(var t in PThread.pthreads){var pthread=PThread.pthreads[t];if(pthread&&pthread.worker){PThread.returnWorkerToPool(pthread.worker);}}PThread.pthreads={};for(var i=0;i>2];GROWABLE_HEAP_I32()[pthread.threadInfoStruct+104>>2]=0;_free(tlsMemory);_free(pthread.threadInfoStruct);}pthread.threadInfoStruct=0;if(pthread.allocatedOwnStack&&pthread.stackBase)_free(pthread.stackBase);pthread.stackBase=0;if(pthread.worker)pthread.worker.pthread=null;},returnWorkerToPool:function(worker){delete PThread.pthreads[worker.pthread.thread];PThread.unusedWorkers.push(worker);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);PThread.freeThreadData(worker.pthread);worker.pthread=undefined;},receiveObjectTransfer:function(data){},loadWasmModuleToWorker:function(worker,onFinishedLoading){worker.onmessage=function(e){var d=e["data"];var cmd=d["cmd"];if(worker.pthread)PThread.currentProxiedOperationCallerThread=worker.pthread.threadInfoStruct;if(d["targetThread"]&&d["targetThread"]!=_pthread_self()){var thread=PThread.pthreads[d.targetThread];if(thread){thread.worker.postMessage(e.data,d["transferList"]);}else{console.error('Internal error! Worker sent a message "'+cmd+'" to target pthread '+d["targetThread"]+", but that thread no longer exists!");}PThread.currentProxiedOperationCallerThread=undefined;return}if(cmd==="processQueuedMainThreadWork"){_emscripten_main_thread_process_queued_calls();}else if(cmd==="spawnThread"){__spawn_thread(e.data);}else if(cmd==="cleanupThread"){__cleanup_thread(d["thread"]);}else if(cmd==="killThread"){__kill_thread(d["thread"]);}else if(cmd==="cancelThread"){__cancel_thread(d["thread"]);}else if(cmd==="loaded"){worker.loaded=true;if(onFinishedLoading)onFinishedLoading(worker);if(worker.runPthread){worker.runPthread();delete worker.runPthread;}}else if(cmd==="print"){out("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="printErr"){err("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="alert"){alert("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="exit"){var detached=worker.pthread&&Atomics.load(GROWABLE_HEAP_U32(),worker.pthread.thread+68>>2);if(detached){PThread.returnWorkerToPool(worker);}}else if(cmd==="cancelDone"){PThread.returnWorkerToPool(worker);}else if(cmd==="objectTransfer"){PThread.receiveObjectTransfer(e.data);}else if(e.data.target==="setimmediate"){worker.postMessage(e.data);}else{err("worker sent an unknown command "+cmd);}PThread.currentProxiedOperationCallerThread=undefined;};worker.onerror=function(e){err("pthread sent an error! "+e.filename+":"+e.lineno+": "+e.message);};if(ENVIRONMENT_IS_NODE){worker.on("message",function(data){worker.onmessage({data:data});});worker.on("error",function(data){worker.onerror(data);});worker.on("exit",function(data){console.log("worker exited - TODO: update the worker queue?");});}assert(wasmMemory instanceof WebAssembly.Memory,"WebAssembly memory should have been loaded by now!");assert(wasmModule instanceof WebAssembly.Module,"WebAssembly Module should have been loaded by now!");worker.postMessage({"cmd":"load","urlOrBlob":Module["mainScriptUrlOrBlob"]||_scriptDir,"wasmMemory":wasmMemory,"wasmModule":wasmModule,"DYNAMIC_BASE":DYNAMIC_BASE,"DYNAMICTOP_PTR":DYNAMICTOP_PTR});},allocateUnusedWorker:function(){var pthreadMainJs=locateFile("tfjs-backend-wasm-threaded.worker.js");PThread.unusedWorkers.push(new Worker(pthreadMainJs));},getNewWorker:function(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]);}if(PThread.unusedWorkers.length>0)return PThread.unusedWorkers.pop();else return null},busySpinWait:function(msecs){var t=performance.now()+msecs;while(performance.now()>2]=value;return value}function _atexit(func,arg){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(1,1,func,arg);warnOnce("atexit() called, but EXIT_RUNTIME is not set, so atexits() will not be called. set EXIT_RUNTIME to 1 (see the FAQ)");}function ___handle_stack_overflow(){abort("stack overflow");}function __emscripten_notify_thread_queue(targetThreadId,mainThreadId){if(targetThreadId==mainThreadId){postMessage({"cmd":"processQueuedMainThreadWork"});}else if(ENVIRONMENT_IS_PTHREAD){postMessage({"targetThread":targetThreadId,"cmd":"processThreadQueue"});}else{var pthread=PThread.pthreads[targetThreadId];var worker=pthread&&pthread.worker;if(!worker){err("Cannot send message to thread with ID "+targetThreadId+", unknown thread ID!");return}worker.postMessage({"cmd":"processThreadQueue"});}return 1}function _abort(){abort();}function _emscripten_conditional_set_current_thread_status(expectedStatus,newStatus){}function _emscripten_futex_wait(addr,val,timeout){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0)return -28;if(ENVIRONMENT_IS_WORKER){var ret=Atomics.wait(GROWABLE_HEAP_I32(),addr>>2,val,timeout);if(ret==="timed-out")return -73;if(ret==="not-equal")return -6;if(ret==="ok")return 0;throw "Atomics.wait returned an unexpected value "+ret}else{var loadedVal=Atomics.load(GROWABLE_HEAP_I32(),addr>>2);if(val!=loadedVal)return -6;var tNow=performance.now();var tEnd=tNow+timeout;Atomics.store(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,addr);var ourWaitAddress=addr;while(addr==ourWaitAddress){tNow=performance.now();if(tNow>tEnd){return -73}_emscripten_main_thread_process_queued_calls();addr=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);}return 0}}function _emscripten_is_main_browser_thread(){return __pthread_is_main_browser_thread|0}function _emscripten_is_main_runtime_thread(){return __pthread_is_main_runtime_thread|0}function _emscripten_memcpy_big(dest,src,num){GROWABLE_HEAP_U8().copyWithin(dest,src,src+num);}function _emscripten_proxy_to_main_thread_js(index,sync){var numCallArgs=arguments.length-2;if(numCallArgs>20-1)throw "emscripten_proxy_to_main_thread_js: Too many arguments "+numCallArgs+" to proxied function idx="+index+", maximum supported is "+(20-1)+"!";var stack=stackSave();var args=stackAlloc(numCallArgs*8);var b=args>>3;for(var i=0;i>3]);buf+=8;}else if(ch===105){buf=buf+3&~3;args.push(GROWABLE_HEAP_I32()[buf>>2]);buf+=4;}else abort("unexpected char in asm const signature "+ch);}return args}function _emscripten_receive_on_main_thread_js(index,numCallArgs,args){_emscripten_receive_on_main_thread_js_callArgs.length=numCallArgs;var b=args>>3;for(var i=0;i>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){console.error("emscripten_realloc_buffer: Attempted to grow heap from "+buffer.byteLength+" bytes to "+size+" bytes, but got error: "+e);}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();if(requestedSize<=oldSize){return false}var PAGE_MULTIPLE=65536;var maxHeapSize=1073741824;if(requestedSize>maxHeapSize){err("Cannot enlarge memory, asked to go up to "+requestedSize+" bytes, but the limit is "+maxHeapSize+" bytes!");return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}err("Failed to grow the heap from "+oldSize+" bytes to "+newSize+" bytes, not enough memory!");return false}var JSEvents={keyEvent:0,mouseEvent:0,wheelEvent:0,uiEvent:0,focusEvent:0,deviceOrientationEvent:0,deviceMotionEvent:0,fullscreenChangeEvent:0,pointerlockChangeEvent:0,visibilityChangeEvent:0,touchEvent:0,previousFullscreenElement:null,previousScreenX:null,previousScreenY:null,removeEventListenersRegistered:false,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i);}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[];},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){JSEvents.removeEventListenersRegistered=true;}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence>2]=eventTypeId;GROWABLE_HEAP_I32()[varargs+4>>2]=eventData;GROWABLE_HEAP_I32()[varargs+8>>2]=userData;_emscripten_async_queue_on_thread_(targetThread,637534208,eventHandlerFunc,eventData,varargs);stackRestore(stackTop);},getTargetThreadForEventCallback:function(targetThread){switch(targetThread){case 1:return 0;case 2:return PThread.currentProxiedOperationCallerThread;default:return targetThread}},getNodeNameForTarget:function(target){if(!target)return "";if(target==window)return "#window";if(target==screen)return "#screen";return target&&target.nodeName?target.nodeName:""},fullscreenEnabled:function(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+1;var cString=_malloc(length);stringToUTF8(jsString,cString,length);return cString}function _emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height){var stackTop=stackSave();var varargs=stackAlloc(12);var targetCanvasPtr=0;if(targetCanvas){targetCanvasPtr=stringToNewUTF8(targetCanvas);}GROWABLE_HEAP_I32()[varargs>>2]=targetCanvasPtr;GROWABLE_HEAP_I32()[varargs+4>>2]=width;GROWABLE_HEAP_I32()[varargs+8>>2]=height;_emscripten_async_queue_on_thread_(targetThread,657457152,0,targetCanvasPtr,varargs);stackRestore(stackTop);}function _emscripten_set_offscreencanvas_size_on_target_thread(targetThread,targetCanvas,width,height){targetCanvas=targetCanvas?UTF8ToString(targetCanvas):"";_emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height);}function __maybeCStringToJsString(cString){return cString>2?UTF8ToString(cString):cString}var specialHTMLTargets=[0,typeof document!=="undefined"?document:0,typeof window!=="undefined"?window:0];function __findEventTarget(target){target=__maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!=="undefined"?document.querySelector(target):undefined);return domElement}function __findCanvasEventTarget(target){return __findEventTarget(target)}function _emscripten_set_canvas_element_size_calling_thread(target,width,height){var canvas=__findCanvasEventTarget(target);if(!canvas)return -4;if(canvas.canvasSharedPtr){GROWABLE_HEAP_I32()[canvas.canvasSharedPtr>>2]=width;GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+4>>2]=height;}if(canvas.offscreenCanvas||!canvas.controlTransferredOffscreen){if(canvas.offscreenCanvas)canvas=canvas.offscreenCanvas;var autoResizeViewport=false;if(canvas.GLctxObject&&canvas.GLctxObject.GLctx){var prevViewport=canvas.GLctxObject.GLctx.getParameter(2978);autoResizeViewport=prevViewport[0]===0&&prevViewport[1]===0&&prevViewport[2]===canvas.width&&prevViewport[3]===canvas.height;}canvas.width=width;canvas.height=height;if(autoResizeViewport){canvas.GLctxObject.GLctx.viewport(0,0,width,height);}}else if(canvas.canvasSharedPtr){var targetThread=GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+8>>2];_emscripten_set_offscreencanvas_size_on_target_thread(targetThread,target,width,height);return 1}else{return -4}return 0}function _emscripten_set_canvas_element_size_main_thread(target,width,height){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(2,1,target,width,height);return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}function _emscripten_set_canvas_element_size(target,width,height){var canvas=__findCanvasEventTarget(target);if(canvas){return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}else{return _emscripten_set_canvas_element_size_main_thread(target,width,height)}}function _emscripten_set_current_thread_status(newStatus){}function _emscripten_set_thread_name(threadId,name){}function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=function(index,divisor){ext["vertexAttribDivisorANGLE"](index,divisor);};ctx["drawArraysInstanced"]=function(mode,first,count,primcount){ext["drawArraysInstancedANGLE"](mode,first,count,primcount);};ctx["drawElementsInstanced"]=function(mode,count,type,indices,primcount){ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);};return 1}}function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=function(){return ext["createVertexArrayOES"]()};ctx["deleteVertexArray"]=function(vao){ext["deleteVertexArrayOES"](vao);};ctx["bindVertexArray"]=function(vao){ext["bindVertexArrayOES"](vao);};ctx["isVertexArray"]=function(vao){return ext["isVertexArrayOES"](vao)};return 1}}function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=function(n,bufs){ext["drawBuffersWEBGL"](n,bufs);};return 1}}var GL={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:{},currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],programInfos:{},stringCache:{},unpackAlignment:4,init:function(){var miniTempFloatBuffer=new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);for(var i=0;i>2]:-1;source+=UTF8ToString(GROWABLE_HEAP_I32()[string+i*4>>2],len<0?undefined:len);}return source},createContext:function(canvas,webGLContextAttributes){var ctx=canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=_malloc(8);GROWABLE_HEAP_I32()[handle+4>>2]=_pthread_self();var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context);}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return !(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;_free(GL.contexts[contextHandle].handle);GL.contexts[contextHandle]=null;},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;__webgl_enable_ANGLE_instanced_arrays(GLctx);__webgl_enable_OES_vertex_array_object(GLctx);__webgl_enable_WEBGL_draw_buffers(GLctx);GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query");var automaticallyEnabledExtensions=["OES_texture_float","OES_texture_half_float","OES_standard_derivatives","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBGL_depth_texture","OES_element_index_uint","EXT_texture_filter_anisotropic","EXT_frag_depth","WEBGL_draw_buffers","ANGLE_instanced_arrays","OES_texture_float_linear","OES_texture_half_float_linear","EXT_blend_minmax","EXT_shader_texture_lod","EXT_texture_norm16","WEBGL_compressed_texture_pvrtc","EXT_color_buffer_half_float","WEBGL_color_buffer_float","EXT_sRGB","WEBGL_compressed_texture_etc1","EXT_disjoint_timer_query","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_astc","EXT_color_buffer_float","WEBGL_compressed_texture_s3tc_srgb","EXT_disjoint_timer_query_webgl2","WEBKIT_WEBGL_compressed_texture_pvrtc"];var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext);}});},populateUniformTable:function(program){var p=GL.programs[program];var ptable=GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,35718);for(var i=0;i>2;contextAttributes["alpha"]=!!GROWABLE_HEAP_I32()[a+(0>>2)];contextAttributes["depth"]=!!GROWABLE_HEAP_I32()[a+(4>>2)];contextAttributes["stencil"]=!!GROWABLE_HEAP_I32()[a+(8>>2)];contextAttributes["antialias"]=!!GROWABLE_HEAP_I32()[a+(12>>2)];contextAttributes["premultipliedAlpha"]=!!GROWABLE_HEAP_I32()[a+(16>>2)];contextAttributes["preserveDrawingBuffer"]=!!GROWABLE_HEAP_I32()[a+(20>>2)];var powerPreference=GROWABLE_HEAP_I32()[a+(24>>2)];contextAttributes["powerPreference"]=__emscripten_webgl_power_preferences[powerPreference];contextAttributes["failIfMajorPerformanceCaveat"]=!!GROWABLE_HEAP_I32()[a+(28>>2)];contextAttributes.majorVersion=GROWABLE_HEAP_I32()[a+(32>>2)];contextAttributes.minorVersion=GROWABLE_HEAP_I32()[a+(36>>2)];contextAttributes.enableExtensionsByDefault=GROWABLE_HEAP_I32()[a+(40>>2)];contextAttributes.explicitSwapControl=GROWABLE_HEAP_I32()[a+(44>>2)];contextAttributes.proxyContextToMainThread=GROWABLE_HEAP_I32()[a+(48>>2)];contextAttributes.renderViaOffscreenBackBuffer=GROWABLE_HEAP_I32()[a+(52>>2)];var canvas=__findCanvasEventTarget(target);if(!canvas){return -4}if(contextAttributes.explicitSwapControl){return -1}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}function _emscripten_webgl_create_context(a0,a1){return _emscripten_webgl_do_create_context(a0,a1)}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];assert(buffer);if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){assert(SYSCALLS.varargs!=undefined);SYSCALLS.varargs+=4;var ret=GROWABLE_HEAP_I32()[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){if(low>=0)assert(high===0);else assert(high===-1);return low}};function _fd_close(fd){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(3,1,fd);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(4,1,fd,offset_low,offset_high,whence,newOffset);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");}function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(5,1,fd,iov,iovcnt,pnum);var num=0;for(var i=0;i>2];var len=GROWABLE_HEAP_I32()[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _pthread_cleanup_pop(execute){var routine=PThread.exitHandlers.pop();if(execute)routine();}function _pthread_cleanup_push(routine,arg){if(PThread.exitHandlers===null){PThread.exitHandlers=[];}PThread.exitHandlers.push(function(){dynCall_vi(routine,arg);});}function __spawn_thread(threadParams){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _spawn_thread() can only ever be called from main application thread!";var worker=PThread.getNewWorker();if(worker.pthread!==undefined)throw "Internal error!";if(!threadParams.pthread_ptr)throw "Internal error, no pthread ptr!";PThread.runningWorkers.push(worker);var tlsMemory=_malloc(128*4);for(var i=0;i<128;++i){GROWABLE_HEAP_I32()[tlsMemory+i*4>>2]=0;}var stackHigh=threadParams.stackBase+threadParams.stackSize;var pthread=PThread.pthreads[threadParams.pthread_ptr]={worker:worker,stackBase:threadParams.stackBase,stackSize:threadParams.stackSize,allocatedOwnStack:threadParams.allocatedOwnStack,thread:threadParams.pthread_ptr,threadInfoStruct:threadParams.pthread_ptr};var tis=pthread.threadInfoStruct>>2;Atomics.store(GROWABLE_HEAP_U32(),tis+(0>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(4>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(8>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(68>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(104>>2),tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),tis+(48>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(40>>2),pthread.threadInfoStruct);Atomics.store(GROWABLE_HEAP_U32(),tis+(44>>2),42);Atomics.store(GROWABLE_HEAP_U32(),tis+(108>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(84>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(80>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+8>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+12>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+20>>2),threadParams.schedPolicy);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+24>>2),threadParams.schedPrio);var global_libc=_emscripten_get_global_libc();var global_locale=global_libc+40;Atomics.store(GROWABLE_HEAP_U32(),tis+(176>>2),global_locale);worker.pthread=pthread;var msg={"cmd":"run","start_routine":threadParams.startRoutine,"arg":threadParams.arg,"threadInfoStruct":threadParams.pthread_ptr,"selfThreadId":threadParams.pthread_ptr,"parentThreadId":threadParams.parent_pthread_ptr,"stackBase":threadParams.stackBase,"stackSize":threadParams.stackSize};worker.runPthread=function(){msg.time=performance.now();worker.postMessage(msg,threadParams.transferList);};if(worker.loaded){worker.runPthread();delete worker.runPthread;}}function _pthread_getschedparam(thread,policy,schedparam){if(!policy&&!schedparam)return ERRNO_CODES.EINVAL;if(!thread){err("pthread_getschedparam called with a null thread pointer!");return ERRNO_CODES.ESRCH}var self=GROWABLE_HEAP_I32()[thread+12>>2];if(self!==thread){err("pthread_getschedparam attempted on thread "+thread+", which does not point to a valid thread, or does not exist anymore!");return ERRNO_CODES.ESRCH}var schedPolicy=Atomics.load(GROWABLE_HEAP_U32(),thread+108+20>>2);var schedPrio=Atomics.load(GROWABLE_HEAP_U32(),thread+108+24>>2);if(policy)GROWABLE_HEAP_I32()[policy>>2]=schedPolicy;if(schedparam)GROWABLE_HEAP_I32()[schedparam>>2]=schedPrio;return 0}function _pthread_self(){return __pthread_ptr|0}Module["_pthread_self"]=_pthread_self;function _pthread_create(pthread_ptr,attr,start_routine,arg){if(typeof SharedArrayBuffer==="undefined"){err("Current environment does not support SharedArrayBuffer, pthreads are not available!");return 6}if(!pthread_ptr){err("pthread_create called with a null thread pointer!");return 28}var transferList=[];var error=0;if(ENVIRONMENT_IS_PTHREAD&&(transferList.length===0||error)){return _emscripten_sync_run_in_main_thread_4(687865856,pthread_ptr,attr,start_routine,arg)}var stackSize=0;var stackBase=0;var detached=0;var schedPolicy=0;var schedPrio=0;if(attr){stackSize=GROWABLE_HEAP_I32()[attr>>2];stackSize+=81920;stackBase=GROWABLE_HEAP_I32()[attr+8>>2];detached=GROWABLE_HEAP_I32()[attr+12>>2]!==0;var inheritSched=GROWABLE_HEAP_I32()[attr+16>>2]===0;if(inheritSched){var prevSchedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];var prevSchedPrio=GROWABLE_HEAP_I32()[attr+24>>2];var parentThreadPtr=PThread.currentProxiedOperationCallerThread?PThread.currentProxiedOperationCallerThread:_pthread_self();_pthread_getschedparam(parentThreadPtr,attr+20,attr+24);schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];GROWABLE_HEAP_I32()[attr+20>>2]=prevSchedPolicy;GROWABLE_HEAP_I32()[attr+24>>2]=prevSchedPrio;}else{schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];}}else{stackSize=2097152;}var allocatedOwnStack=stackBase==0;if(allocatedOwnStack){stackBase=_memalign(16,stackSize);}else{stackBase-=stackSize;assert(stackBase>0);}var threadInfoStruct=_malloc(232);for(var i=0;i<232>>2;++i)GROWABLE_HEAP_U32()[(threadInfoStruct>>2)+i]=0;GROWABLE_HEAP_I32()[pthread_ptr>>2]=threadInfoStruct;GROWABLE_HEAP_I32()[threadInfoStruct+12>>2]=threadInfoStruct;var headPtr=threadInfoStruct+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var threadParams={stackBase:stackBase,stackSize:stackSize,allocatedOwnStack:allocatedOwnStack,schedPolicy:schedPolicy,schedPrio:schedPrio,detached:detached,startRoutine:start_routine,pthread_ptr:threadInfoStruct,parent_pthread_ptr:_pthread_self(),arg:arg,transferList:transferList};if(ENVIRONMENT_IS_PTHREAD){threadParams.cmd="spawnThread";postMessage(threadParams,transferList);}else{__spawn_thread(threadParams);}return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}function _sysconf(name){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(6,1,name);switch(name){case 30:return 16384;case 85:var maxHeapSize=1073741824;return maxHeapSize/16384;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:case 79:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return -1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}setErrNo(28);return -1}if(!ENVIRONMENT_IS_PTHREAD)PThread.initMainThreadBlock();else PThread.initWorker();var GLctx;GL.init();var proxiedFunctionTable=[null,_atexit,_emscripten_set_canvas_element_size_main_thread,_fd_close,_fd_seek,_fd_write,_sysconf];var asmLibraryArg={"__assert_fail":___assert_fail,"__call_main":___call_main,"__handle_stack_overflow":___handle_stack_overflow,"_emscripten_notify_thread_queue":__emscripten_notify_thread_queue,"abort":_abort,"emscripten_conditional_set_current_thread_status":_emscripten_conditional_set_current_thread_status,"emscripten_futex_wait":_emscripten_futex_wait,"emscripten_futex_wake":_emscripten_futex_wake,"emscripten_get_now":_emscripten_get_now,"emscripten_is_main_browser_thread":_emscripten_is_main_browser_thread,"emscripten_is_main_runtime_thread":_emscripten_is_main_runtime_thread,"emscripten_memcpy_big":_emscripten_memcpy_big,"emscripten_receive_on_main_thread_js":_emscripten_receive_on_main_thread_js,"emscripten_resize_heap":_emscripten_resize_heap,"emscripten_set_canvas_element_size":_emscripten_set_canvas_element_size,"emscripten_set_current_thread_status":_emscripten_set_current_thread_status,"emscripten_set_thread_name":_emscripten_set_thread_name,"emscripten_webgl_create_context":_emscripten_webgl_create_context,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"initPthreadsJS":initPthreadsJS,"memory":wasmMemory||Module["wasmMemory"],"pthread_cleanup_pop":_pthread_cleanup_pop,"pthread_cleanup_push":_pthread_cleanup_push,"pthread_create":_pthread_create,"pthread_self":_pthread_self,"roundf":_roundf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__wasm_call_ctors"].apply(null,arguments)};var _init=Module["_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["init"].apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["register_tensor"].apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose_data"].apply(null,arguments)};var _dispose=Module["_dispose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose"].apply(null,arguments)};var _Abs=Module["_Abs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Abs"].apply(null,arguments)};var _Add=Module["_Add"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Add"].apply(null,arguments)};var _AddN=Module["_AddN"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AddN"].apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ArgMax"].apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AvgPool"].apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["BatchMatMul"].apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ClipByValue"].apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2D"].apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2DBackpropInput"].apply(null,arguments)};var _Cos=Module["_Cos"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Cos"].apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["CropAndResize"].apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["DepthwiseConv2dNative"].apply(null,arguments)};var _Div=Module["_Div"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Div"].apply(null,arguments)};var _Equal=Module["_Equal"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Equal"].apply(null,arguments)};var _Exp=Module["_Exp"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Exp"].apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FloorDiv"].apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedBatchNorm"].apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedConv2D"].apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedDepthwiseConv2D"].apply(null,arguments)};var _Gather=Module["_Gather"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Gather"].apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GatherNd"].apply(null,arguments)};var _Greater=Module["_Greater"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Greater"].apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GreaterEqual"].apply(null,arguments)};var _Less=Module["_Less"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Less"].apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LessEqual"].apply(null,arguments)};var _Log=Module["_Log"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Log"].apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LogicalAnd"].apply(null,arguments)};var _Max=Module["_Max"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Max"].apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["MaxPool"].apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Maximum"].apply(null,arguments)};var _Min=Module["_Min"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Min"].apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Minimum"].apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Multiply"].apply(null,arguments)};var _Negate=Module["_Negate"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Negate"].apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV3"].apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV4"].apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV5"].apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NotEqual"].apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["OneHot"].apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["PadV2"].apply(null,arguments)};var _Pow=Module["_Pow"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Pow"].apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Prelu"].apply(null,arguments)};var _Relu=Module["_Relu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu"].apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu6"].apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ResizeBilinear"].apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Reverse"].apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["RotateWithOffset"].apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Rsqrt"].apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ScatterNd"].apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["SelectV2"].apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sigmoid"].apply(null,arguments)};var _Sin=Module["_Sin"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sin"].apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Softmax"].apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sqrt"].apply(null,arguments)};var _Square=Module["_Square"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Square"].apply(null,arguments)};var _Sub=Module["_Sub"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sub"].apply(null,arguments)};var _Sum=Module["_Sum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sum"].apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tanh"].apply(null,arguments)};var _Tile=Module["_Tile"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tile"].apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Transpose"].apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["_FusedMatMul"].apply(null,arguments)};var _malloc=Module["_malloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["malloc"].apply(null,arguments)};var _free=Module["_free"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["free"].apply(null,arguments)};var ___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__em_js__initPthreadsJS"].apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__errno_location"].apply(null,arguments)};var _emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_get_global_libc"].apply(null,arguments)};var _memalign=Module["_memalign"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["memalign"].apply(null,arguments)};var ___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__pthread_tsd_run_dtors"].apply(null,arguments)};var _emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_current_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_register_main_browser_thread_id"].apply(null,arguments)};var _emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_browser_thread_id"].apply(null,arguments)};var _emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_0"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_1"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_2"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_xprintf_varargs"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_3"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_4"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_5"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_6"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_7"].apply(null,arguments)};var _emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_run_in_main_runtime_thread_js"].apply(null,arguments)};var _emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_queue_on_thread_"].apply(null,arguments)};var _emscripten_tls_init=Module["_emscripten_tls_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_tls_init"].apply(null,arguments)};var ___set_stack_limit=Module["___set_stack_limit"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__set_stack_limit"].apply(null,arguments)};var stackSave=Module["stackSave"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackSave"].apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackAlloc"].apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackRestore"].apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_vi"].apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_v"].apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_ii"].apply(null,arguments)};Module["asm"]=asm;if(!Object.getOwnPropertyDescriptor(Module,"intArrayFromString"))Module["intArrayFromString"]=function(){abort("'intArrayFromString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"intArrayToString"))Module["intArrayToString"]=function(){abort("'intArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ccall"))Module["ccall"]=function(){abort("'ccall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["cwrap"]=cwrap;if(!Object.getOwnPropertyDescriptor(Module,"setValue"))Module["setValue"]=function(){abort("'setValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getValue"))Module["getValue"]=function(){abort("'getValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocate"))Module["allocate"]=function(){abort("'allocate' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getMemory"))Module["getMemory"]=function(){abort("'getMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ArrayToString"))Module["UTF8ArrayToString"]=function(){abort("'UTF8ArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ToString"))Module["UTF8ToString"]=function(){abort("'UTF8ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8Array"))Module["stringToUTF8Array"]=function(){abort("'stringToUTF8Array' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8"))Module["stringToUTF8"]=function(){abort("'stringToUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF8"))Module["lengthBytesUTF8"]=function(){abort("'lengthBytesUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreRun"))Module["addOnPreRun"]=function(){abort("'addOnPreRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnInit"))Module["addOnInit"]=function(){abort("'addOnInit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreMain"))Module["addOnPreMain"]=function(){abort("'addOnPreMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnExit"))Module["addOnExit"]=function(){abort("'addOnExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPostRun"))Module["addOnPostRun"]=function(){abort("'addOnPostRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeStringToMemory"))Module["writeStringToMemory"]=function(){abort("'writeStringToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeArrayToMemory"))Module["writeArrayToMemory"]=function(){abort("'writeArrayToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeAsciiToMemory"))Module["writeAsciiToMemory"]=function(){abort("'writeAsciiToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addRunDependency"))Module["addRunDependency"]=function(){abort("'addRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"removeRunDependency"))Module["removeRunDependency"]=function(){abort("'removeRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createFolder"))Module["FS_createFolder"]=function(){abort("'FS_createFolder' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPath"))Module["FS_createPath"]=function(){abort("'FS_createPath' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDataFile"))Module["FS_createDataFile"]=function(){abort("'FS_createDataFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPreloadedFile"))Module["FS_createPreloadedFile"]=function(){abort("'FS_createPreloadedFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLazyFile"))Module["FS_createLazyFile"]=function(){abort("'FS_createLazyFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLink"))Module["FS_createLink"]=function(){abort("'FS_createLink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDevice"))Module["FS_createDevice"]=function(){abort("'FS_createDevice' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_unlink"))Module["FS_unlink"]=function(){abort("'FS_unlink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"dynamicAlloc"))Module["dynamicAlloc"]=function(){abort("'dynamicAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadDynamicLibrary"))Module["loadDynamicLibrary"]=function(){abort("'loadDynamicLibrary' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadWebAssemblyModule"))Module["loadWebAssemblyModule"]=function(){abort("'loadWebAssemblyModule' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getLEB"))Module["getLEB"]=function(){abort("'getLEB' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFunctionTables"))Module["getFunctionTables"]=function(){abort("'getFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"alignFunctionTables"))Module["alignFunctionTables"]=function(){abort("'alignFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"registerFunctions"))Module["registerFunctions"]=function(){abort("'registerFunctions' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addFunction"))Module["addFunction"]=function(){abort("'addFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"removeFunction"))Module["removeFunction"]=function(){abort("'removeFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFuncWrapper"))Module["getFuncWrapper"]=function(){abort("'getFuncWrapper' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"prettyPrint"))Module["prettyPrint"]=function(){abort("'prettyPrint' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"makeBigInt"))Module["makeBigInt"]=function(){abort("'makeBigInt' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"dynCall"))Module["dynCall"]=function(){abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getCompilerSetting"))Module["getCompilerSetting"]=function(){abort("'getCompilerSetting' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"print"))Module["print"]=function(){abort("'print' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"printErr"))Module["printErr"]=function(){abort("'printErr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getTempRet0"))Module["getTempRet0"]=function(){abort("'getTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setTempRet0"))Module["setTempRet0"]=function(){abort("'setTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"callMain"))Module["callMain"]=function(){abort("'callMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"abort"))Module["abort"]=function(){abort("'abort' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToNewUTF8"))Module["stringToNewUTF8"]=function(){abort("'stringToNewUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscripten_realloc_buffer"))Module["emscripten_realloc_buffer"]=function(){abort("'emscripten_realloc_buffer' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ENV"))Module["ENV"]=function(){abort("'ENV' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setjmpId"))Module["setjmpId"]=function(){abort("'setjmpId' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_CODES"))Module["ERRNO_CODES"]=function(){abort("'ERRNO_CODES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_MESSAGES"))Module["ERRNO_MESSAGES"]=function(){abort("'ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setErrNo"))Module["setErrNo"]=function(){abort("'setErrNo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"DNS"))Module["DNS"]=function(){abort("'DNS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GAI_ERRNO_MESSAGES"))Module["GAI_ERRNO_MESSAGES"]=function(){abort("'GAI_ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Protocols"))Module["Protocols"]=function(){abort("'Protocols' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Sockets"))Module["Sockets"]=function(){abort("'Sockets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UNWIND_CACHE"))Module["UNWIND_CACHE"]=function(){abort("'UNWIND_CACHE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readAsmConstArgs"))Module["readAsmConstArgs"]=function(){abort("'readAsmConstArgs' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_q"))Module["jstoi_q"]=function(){abort("'jstoi_q' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_s"))Module["jstoi_s"]=function(){abort("'jstoi_s' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"reallyNegative"))Module["reallyNegative"]=function(){abort("'reallyNegative' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"formatString"))Module["formatString"]=function(){abort("'formatString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH"))Module["PATH"]=function(){abort("'PATH' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH_FS"))Module["PATH_FS"]=function(){abort("'PATH_FS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SYSCALLS"))Module["SYSCALLS"]=function(){abort("'SYSCALLS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMmap2"))Module["syscallMmap2"]=function(){abort("'syscallMmap2' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMunmap"))Module["syscallMunmap"]=function(){abort("'syscallMunmap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"flush_NO_FILESYSTEM"))Module["flush_NO_FILESYSTEM"]=function(){abort("'flush_NO_FILESYSTEM' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"JSEvents"))Module["JSEvents"]=function(){abort("'JSEvents' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"specialHTMLTargets"))Module["specialHTMLTargets"]=function(){abort("'specialHTMLTargets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangle"))Module["demangle"]=function(){abort("'demangle' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangleAll"))Module["demangleAll"]=function(){abort("'demangleAll' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jsStackTrace"))Module["jsStackTrace"]=function(){abort("'jsStackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getEnvStrings"))Module["getEnvStrings"]=function(){abort("'getEnvStrings' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64"))Module["writeI53ToI64"]=function(){abort("'writeI53ToI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Clamped"))Module["writeI53ToI64Clamped"]=function(){abort("'writeI53ToI64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Signaling"))Module["writeI53ToI64Signaling"]=function(){abort("'writeI53ToI64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Clamped"))Module["writeI53ToU64Clamped"]=function(){abort("'writeI53ToU64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Signaling"))Module["writeI53ToU64Signaling"]=function(){abort("'writeI53ToU64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromI64"))Module["readI53FromI64"]=function(){abort("'readI53FromI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromU64"))Module["readI53FromU64"]=function(){abort("'readI53FromU64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertI32PairToI53"))Module["convertI32PairToI53"]=function(){abort("'convertI32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertU32PairToI53"))Module["convertU32PairToI53"]=function(){abort("'convertU32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Browser"))Module["Browser"]=function(){abort("'Browser' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GL"))Module["GL"]=function(){abort("'GL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGet"))Module["emscriptenWebGLGet"]=function(){abort("'emscriptenWebGLGet' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetTexPixelData"))Module["emscriptenWebGLGetTexPixelData"]=function(){abort("'emscriptenWebGLGetTexPixelData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetUniform"))Module["emscriptenWebGLGetUniform"]=function(){abort("'emscriptenWebGLGetUniform' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetVertexAttrib"))Module["emscriptenWebGLGetVertexAttrib"]=function(){abort("'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AL"))Module["AL"]=function(){abort("'AL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_unicode"))Module["SDL_unicode"]=function(){abort("'SDL_unicode' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_ttfContext"))Module["SDL_ttfContext"]=function(){abort("'SDL_ttfContext' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_audio"))Module["SDL_audio"]=function(){abort("'SDL_audio' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL"))Module["SDL"]=function(){abort("'SDL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_gfx"))Module["SDL_gfx"]=function(){abort("'SDL_gfx' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLUT"))Module["GLUT"]=function(){abort("'GLUT' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"EGL"))Module["EGL"]=function(){abort("'EGL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW_Window"))Module["GLFW_Window"]=function(){abort("'GLFW_Window' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW"))Module["GLFW"]=function(){abort("'GLFW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLEW"))Module["GLEW"]=function(){abort("'GLEW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"IDBStore"))Module["IDBStore"]=function(){abort("'IDBStore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"runAndAbortIfError"))Module["runAndAbortIfError"]=function(){abort("'runAndAbortIfError' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["PThread"]=PThread;if(!Object.getOwnPropertyDescriptor(Module,"establishStackSpace"))Module["establishStackSpace"]=function(){abort("'establishStackSpace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getNoExitRuntime"))Module["getNoExitRuntime"]=function(){abort("'getNoExitRuntime' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"resetPrototype"))Module["resetPrototype"]=function(){abort("'resetPrototype' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"warnOnce"))Module["warnOnce"]=function(){abort("'warnOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackSave"))Module["stackSave"]=function(){abort("'stackSave' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackRestore"))Module["stackRestore"]=function(){abort("'stackRestore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackAlloc"))Module["stackAlloc"]=function(){abort("'stackAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AsciiToString"))Module["AsciiToString"]=function(){abort("'AsciiToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToAscii"))Module["stringToAscii"]=function(){abort("'stringToAscii' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF16ToString"))Module["UTF16ToString"]=function(){abort("'UTF16ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF16"))Module["stringToUTF16"]=function(){abort("'stringToUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF16"))Module["lengthBytesUTF16"]=function(){abort("'lengthBytesUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF32ToString"))Module["UTF32ToString"]=function(){abort("'UTF32ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF32"))Module["stringToUTF32"]=function(){abort("'stringToUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF32"))Module["lengthBytesUTF32"]=function(){abort("'lengthBytesUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8"))Module["allocateUTF8"]=function(){abort("'allocateUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8OnStack"))Module["allocateUTF8OnStack"]=function(){abort("'allocateUTF8OnStack' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["writeStackCookie"]=writeStackCookie;Module["checkStackCookie"]=checkStackCookie;Module["abortStackOverflow"]=abortStackOverflow;Module["PThread"]=PThread;Module["_pthread_self"]=_pthread_self;Module["wasmMemory"]=wasmMemory;Module["ExitStatus"]=ExitStatus;if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NORMAL"))Object.defineProperty(Module,"ALLOC_NORMAL",{configurable:true,get:function(){abort("'ALLOC_NORMAL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_STACK"))Object.defineProperty(Module,"ALLOC_STACK",{configurable:true,get:function(){abort("'ALLOC_STACK' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_DYNAMIC"))Object.defineProperty(Module,"ALLOC_DYNAMIC",{configurable:true,get:function(){abort("'ALLOC_DYNAMIC' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NONE"))Object.defineProperty(Module,"ALLOC_NONE",{configurable:true,get:function(){abort("'ALLOC_NONE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}writeStackCookie();preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();assert(!Module["_main"],'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}checkStackCookie();}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}if(!ENVIRONMENT_IS_PTHREAD)noExitRuntime=true;if(!ENVIRONMENT_IS_PTHREAD)run(); + + + return WasmBackendModule + } + ); + })(); + module.exports = WasmBackendModule; + }); + + const wasmWorkerContents = 'var threadInfoStruct=0;var selfThreadId=0;var parentThreadId=0;var Module={};function assert(condition,text){if(!condition)abort("Assertion failed: "+text)}function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:selfThreadId})}var out=function(){throw"out() is not defined in worker.js."};var err=threadPrintErr;this.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);Module["wasmModule"]=null;receiveInstance(instance);return instance.exports};this.onmessage=function(e){try{if(e.data.cmd==="load"){console.log("LOADING");console.log(e.data);Module["DYNAMIC_BASE"]=e.data.DYNAMIC_BASE;Module["DYNAMICTOP_PTR"]=e.data.DYNAMICTOP_PTR;Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob==="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}Module=WasmBackendModule(Module);postMessage({"cmd":"loaded"})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;threadInfoStruct=e.data.threadInfoStruct;Module["__register_pthread_ptr"](threadInfoStruct,0,0);selfThreadId=e.data.selfThreadId;parentThreadId=e.data.parentThreadId;var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;assert(threadInfoStruct);assert(selfThreadId);assert(parentThreadId);assert(top!=0);assert(max!=0);assert(top>max);Module["establishStackSpace"](top,max);Module["_emscripten_tls_init"]();Module["writeStackCookie"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].setThreadStatus(Module["_pthread_self"](),1);try{var result=Module["dynCall_ii"](e.data.start_routine,e.data.arg);Module["checkStackCookie"]();if(!Module["getNoExitRuntime"]())Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){Atomics.store(Module["HEAPU32"],threadInfoStruct+4>>2,ex instanceof Module["ExitStatus"]?ex.status:-2);Atomics.store(Module["HEAPU32"],threadInfoStruct+0>>2,1);if(typeof Module["_emscripten_futex_wake"]!=="function"){err("Thread Initialisation failed.");throw ex}Module["_emscripten_futex_wake"](threadInfoStruct+0,2147483647);if(!(ex instanceof Module["ExitStatus"]))throw ex}else{err("Pthread 0x"+threadInfoStruct.toString(16)+" completed its pthread main entry point with an unwind, keeping the pthread worker alive for asynchronous operation.")}}}else if(e.data.cmd==="cancel"){if(threadInfoStruct){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(threadInfoStruct){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex.stack)err(ex.stack);throw ex}};if(typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string"){self={location:{href:__filename}};var onmessage=this.onmessage;var nodeWorkerThreads=require("worker_threads");Worker=nodeWorkerThreads.Worker;var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var nodeFS=require("fs");var nodeRead=function(filename){return nodeFS.readFileSync(filename,"utf8")};function globalEval(x){global.require=require;global.Module=Module;eval.call(null,x)}importScripts=function(f){globalEval(nodeRead(f))};postMessage=function(msg){parentPort.postMessage(msg)};if(typeof performance==="undefined"){performance={now:function(){return Date.now()}}}}'; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const WASM_PRIORITY = 2; + class BackendWasm extends tfjsCore.KernelBackend { + constructor(wasm) { + super(); + this.wasm = wasm; + // 0 is reserved for null data ids. + this.dataIdNextNumber = 1; + this.wasm.tfjs.init(); + this.dataIdMap = new tfjsCore.DataStorage(this, tfjsCore.engine()); + } + write(values, shape, dtype) { + const dataId = {}; + this.move(dataId, values, shape, dtype); + return dataId; + } + numDataIds() { + return this.dataIdMap.numDataIds(); + } + async time(f) { + const start = tfjsCore.util.now(); + f(); + const kernelMs = tfjsCore.util.now() - start; + return { kernelMs }; + } + move(dataId, values, shape, dtype) { + const id = this.dataIdNextNumber++; + if (dtype === 'string') { + const stringBytes = values; + this.dataIdMap.set(dataId, { id, stringBytes, shape, dtype, memoryOffset: null }); + return; + } + const size = tfjsCore.util.sizeFromShape(shape); + const numBytes = size * tfjsCore.util.bytesPerElement(dtype); + const memoryOffset = this.wasm._malloc(numBytes); + this.dataIdMap.set(dataId, { id, memoryOffset, shape, dtype }); + this.wasm.tfjs.registerTensor(id, size, memoryOffset); + if (values != null) { + this.wasm.HEAPU8.set(new Uint8Array(values.buffer, values.byteOffset, numBytes), memoryOffset); + } + } + async read(dataId) { + return this.readSync(dataId); + } + readSync(dataId) { + const { memoryOffset, dtype, shape, stringBytes } = this.dataIdMap.get(dataId); + if (dtype === 'string') { + return stringBytes; + } + const bytes = this.wasm.HEAPU8.slice(memoryOffset, memoryOffset + tfjsCore.util.sizeFromShape(shape) * tfjsCore.util.bytesPerElement(dtype)); + return typedArrayFromBuffer(bytes.buffer, dtype); + } + disposeData(dataId) { + const data = this.dataIdMap.get(dataId); + this.wasm._free(data.memoryOffset); + this.wasm.tfjs.disposeData(data.id); + this.dataIdMap.delete(dataId); + } + floatPrecision() { + return 32; + } + // Returns the memory offset of a tensor. Useful for debugging and unit + // testing. + getMemoryOffset(dataId) { + return this.dataIdMap.get(dataId).memoryOffset; + } + dispose() { + this.wasm.tfjs.dispose(); + this.wasm = null; + } + memory() { + return { unreliable: false }; + } + /** + * Make a tensor info for the output of an op. If `memoryOffset` is not + * present, this method allocates memory on the WASM heap. If `memoryOffset` + * is present, the memory was allocated elsewhere (in c++) and we just record + * the pointer where that memory lives. + */ + makeOutput(shape, dtype, memoryOffset) { + let dataId; + if (memoryOffset == null) { + dataId = this.write(null /* values */, shape, dtype); + } + else { + dataId = {}; + const id = this.dataIdNextNumber++; + this.dataIdMap.set(dataId, { id, memoryOffset, shape, dtype }); + const size = tfjsCore.util.sizeFromShape(shape); + this.wasm.tfjs.registerTensor(id, size, memoryOffset); + } + return { dataId, shape, dtype }; + } + typedArrayFromHeap({ shape, dtype, dataId }) { + const buffer = this.wasm.HEAPU8.buffer; + const { memoryOffset } = this.dataIdMap.get(dataId); + const size = tfjsCore.util.sizeFromShape(shape); + switch (dtype) { + case 'float32': + return new Float32Array(buffer, memoryOffset, size); + case 'int32': + return new Int32Array(buffer, memoryOffset, size); + case 'bool': + return new Uint8Array(buffer, memoryOffset, size); + default: + throw new Error(`Uknown dtype ${dtype}`); + } + } + } + tfjsCore.registerBackend('wasm', async () => { + const { wasm } = await init(); + return new BackendWasm(wasm); + }, WASM_PRIORITY); + function createInstantiateWasmFunc(path) { + // tslint:disable-next-line:no-any + return (imports, callback) => { + tfjsCore.util.fetch(path, { credentials: 'same-origin' }).then((response) => { + if (!response['ok']) { + imports.env.a(`failed to load wasm binary file at '${path}'`); + } + response.arrayBuffer().then(binary => { + WebAssembly.instantiate(binary, imports).then(output => { + callback(output.instance); + }); + }); + }); + return {}; + }; + } + /** + * Initializes the wasm module and creates the js <--> wasm bridge. + * + * NOTE: We wrap the wasm module in a object with property 'wasm' instead of + * returning Promise to avoid freezing Chrome (last tested + * in Chrome 76). + */ + async function init() { + // const simdSupported = await env().getAsync('WASM_HAS_SIMD_SUPPORT'); + return new Promise((resolve, reject) => { + const factoryConfig = {}; + const locateFile = (path, prefix) => { + if (path.endsWith('.worker.js')) { + const response = wasmWorkerContents; + const blob = new Blob([response], { type: 'application/javascript' }); + return URL.createObjectURL(blob); + } + return prefix + path; + }; + factoryConfig.locateFile = locateFile; + if (wasmPath != null) { + factoryConfig.locateFile = (path, prefix) => { + if (path.endsWith('.wasm')) { + return wasmPath; + } + return locateFile(path, prefix); + }; + // use wasm instantiateWasm override when system fetch is not available. + // For detail references + // https://github.com/emscripten-core/emscripten/blob/2bca083cbbd5a4133db61fbd74d04f7feecfa907/tests/manual_wasm_instantiate.html#L170 + if (customFetch) { + factoryConfig.instantiateWasm = createInstantiateWasmFunc(wasmPath); + } + } + // const wasm = simdSupported ? wasmFactorySimd(factoryConfig) : + // wasmFactory(factoryConfig); + const wasm = tfjsBackendWasmThreaded(factoryConfig); + const voidReturnType = null; + // wasm.mainScriptUrlOrBlob = + // new Blob([emscriptenContents], {type: 'text/javascript'}); + // Using the tfjs namespace to avoid conflict with emscripten's API. + wasm.tfjs = { + init: wasm.cwrap('init', null, []), + registerTensor: wasm.cwrap('register_tensor', null, [ + 'number', + 'number', + 'number', + ]), + disposeData: wasm.cwrap('dispose_data', voidReturnType, ['number']), + dispose: wasm.cwrap('dispose', voidReturnType, []), + }; + let initialized = false; + wasm.onRuntimeInitialized = () => { + initialized = true; + initAborted = false; + resolve({ wasm }); + }; + wasm.onAbort = () => { + if (initialized) { + // Emscripten already called console.warn so no need to double log. + return; + } + if (initAborted) { + // Emscripten calls `onAbort` twice, resulting in double error + // messages. + return; + } + initAborted = true; + const rejectMsg = 'Make sure the server can serve the `.wasm` file relative to the ' + + 'bundled js file. For more details see https://github.com/tensorflow/tfjs/blob/master/tfjs-backend-wasm/README.md#using-bundlers'; + reject({ message: rejectMsg }); + }; + }); + } + function typedArrayFromBuffer(buffer, dtype) { + switch (dtype) { + case 'float32': + return new Float32Array(buffer); + case 'int32': + return new Int32Array(buffer); + case 'bool': + return new Uint8Array(buffer); + default: + throw new Error(`Unknown dtype ${dtype}`); + } + } + let wasmPath = null; + let initAborted = false; + let customFetch = false; + /** + * Sets the path to the `.wasm` file which will be fetched when the wasm + * backend is initialized. See + * https://github.com/tensorflow/tfjs/blob/master/tfjs-backend-wasm/README.md#using-bundlers + * for more details. + * @param path wasm file path or url + * @param usePlatformFetch optional boolean to use platform fetch to download + * the wasm file, default to false. + */ + /** @doc {heading: 'Environment', namespace: 'wasm'} */ + function setWasmPath(path, usePlatformFetch = false) { + if (initAborted) { + throw new Error('The WASM backend was already initialized. Make sure you call ' + + '`setWasmPath()` before you call `tf.setBackend()` or `tf.ready()`'); + } + wasmPath = path; + customFetch = usePlatformFetch; + } + + /** @license See the LICENSE file. */ + // This code is auto-generated, do not modify this file! + const version = '0.0.0'; + + exports.BackendWasm = BackendWasm; + exports.setWasmPath = setWasmPath; + exports.version_wasm = version; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); +//# sourceMappingURL=tf-backend-wasm.js.map diff --git a/e2e/benchmarks/tfjs-backend-wasm-threaded.wasm b/e2e/benchmarks/tfjs-backend-wasm-threaded.wasm new file mode 100644 index 0000000000000000000000000000000000000000..977c0ad6bd34e0ca874c27e01c705894992873e3 GIT binary patch literal 175629 zcmeFa3!Gk6dGEjW<$dS9&CH%;a-Bf-y9qViG%5x}E3=ajKoF^*^?X`P0vTW~xy?)> z_7G+is@QtLBq~~4L!<>2D;26%E=d&?FRgezp4uW-|NVPHEfrh+NExXmRV z^dk0`ialCNt#zx{PDLq1CH!s7ywc0A;;~g5IjZd(Mb)G^e#<_c+V%!}H`m*_R88@Y zT&)UcRm4NQcdxbIhLW^}9d)#B-R8xu+u7Fw!o7wB{>D=`-9*bBU8TnI)Qu{|U3ioJ z1~&p~c;i%X9lUuGC-LzxR(D=1uJ6`E3dfV7JdHwj% zmaUs6hQ_XSiIPfNuHG>|>0d7z+BR{``0&ojq3xTl-90&U!=_hm869#pxL#bZ3pm;i(k2AVtCWU_ANUnuHP}aY3KORp5dWaKC^P|)=jS*AD$d?y(-$% z>e@AQu$8!~qrM61yJq+J_|W#r0sx_Ca`%J_RDMlI)@ycb-#R=wykq;8F)%e>F{fhv z?PkY@wrtoH!Ij73vhm&9Cx^EU&Em3!$B=2q zPEYqTSlTiEsxX?K4*0L0lqR=aJvJ2VbO(dzkE8pdYEX3*7sbw1gJv^mxLS}VE(>al z7CCqFk{)-eMx3Zp4Xa_dThLo_h=6-RQ0aBmN?3j2f(;86Dj-+c{w=R9KRs|k zH3`a@C{sN$;eMN1d;clVZi!&)^6cohbfT5VY+s8*}B+S7ts#f9Mo3w|lQ_@tAT z)oO0#VET+Otgc^BO%k`zbp@`+m0iR2IbeugsT}KHV1M;zVZEnb{3~@8{~D*1{avYR zVJV8DzMi;LDh2$ON)#zY@j!zz4P|omuC53WO119ZZvCtD_AceNe^GF5cYpc3{-s^z zM!6C9Jh!^2ws`Skw|MOm{)PROlh2792q;J3mPVq;^)=$YN~Kh)1W`~4TK_6F?n;$P zd0{jaY=8C)@!pTerH`M=_Vn-1owAK7QScw%p+U zd)Srlx$g2EJI36fg!Oe>Ca<~vMO!9cw0q3GIjpZA8{WC@RWI8z1{?odP+q@d`<`cQ za6bqZ`nz=~?w#X1c3!-F=k7`OKZ9ufjtTcSLHByn^6gt+V!Firb+Bl|5N!R*;fWzD zxAn3ulgOw0iy+!CyvKbdC|$5?_m(mDxgfgWhMn%?L1p9EjveEA_a{Nm#@!P`TMe$u zc8qUx9}4Q0Qo!;@LBBoDZefG_U{Jnr%jES#Rp?G6O- zOLW~IlyqI|_60qjM(c*hhPMxG8F#k@T`w78Bu2NtIY?fzgK=l*SBEFBfAO`~qITVz zC^@l48%6)Js8P`(0+j}N)mkZ1SR?$x?%bJIb5<(BQ&yQ%of;jtliQ}xR6E!&N&-QLC~ zqjSNVHMy)BhIIk9yUI(ySrlg0;wGddK%nGMB2 zgGgKhMK_uH-)a&(;nqF9Bln!){kR3LIK87lTi%ajo@@fwUk*A4n0YdNDLAF0$}JPG z+J24o2ZN^reD}p*)(AOIuE&DTA$Oj-Hmz}AcuM)6>HhpF<$IRpuOI@}1*86|C;)y_m5@ zyxGPCg5W+mizhs}jU{Cm6|CwW2^Mx#I5{?9;^Y1_VEmDx<&E>P;cbjN9}TMZc*Pc! z_eX-7J>({a9}XJ!ggQYuhTI~FNdEGzZ8Bkd@TGz_}{|Mh2IGOBK&%ID11+N zM|d#2J^a1!-Ql~!-wodp{!aMz@U7w7!mov23BMYCHarl1CVV9PWcaD@)8V7xd!xIf z_ebxGJ`mj#-5LFU^dW4xd!s*!4n`l0{xJH3=&tCF=uq^YXkU0+_{Q+J!`Fwe3x6|w zO*kF?H26{Q@4=6Qe-8dB_{-p{!6$+hji6rp!M|1Si~c$Y;;C>j9L(?hbGJHlS$ILW z%MaRpIF*L^)JW=frQvWE<-v=(-SX6>Vd^d^?snF*I1eXBR5GAs8no}CJiIs_v>KXW zL<^MUZJb3HDmjgIrSZn@pb^)VTuI%=ZhuQn-L4LV#}tav@Wt^|%4KIMjq1KU*H(Fd z>&w@Z(D5d3jMQ(5g3?s#;=vrYd2+qG{bliBG??H1HFuVC^tP2stM%07H;!c1i?|u3 zL6gqrH(38l`P8LA9;Bs_3{;geUabzRYXv*kG+Z0TX`GU6VuYg9I?@aQA&o6RU{#}BuFD_s0&GJLzhPRjZi=Zxt*F&QYhL`4WMN%Kk8nj>hfq0 z>z*$ zIdBa$T?heEmz)ZzgZ#kP+>=l%3xwUiilYYw_3G<`aOxD7C!<-IMW+NXR036_RWzIi zYr{tV*lEBcye1o$C;t+{ZV529bGlWoUUJE=y82^5P@XdOY=U4gZy54jS?A6P0Vx!5 zlkcL!<*OlCoHQf8Fl8B%3sAtcHHN^iR$)KBUHigYlC93U7` z+BE{T)Pk25VXu@|Hu5ga_l`6j7!lV{Luo{OL^dED%jhSS2^?}#RlVL@Pgc765>jE{ zJl%DHu_Yu*9tL$c2OeqDAzjJJZCsRBIeG|BT}qR2K7AzK#Z3u_NCUz7w9q#lUYrF3 z$&nxps8&=0%IPp^>fKEvWIGxl{gM>Ql3us>bCLc~1iC#+<3X-Qde5c7D3bW#XI=is zpKLse{yA*bO^lT=v%U2OoFIvr>0KcMuNd-?7YD zM9(9s7n26*5c;q>Ofsgd^?Ke9hlQdpWJsYk2-H&}jp8YxJByV!A}E|t3~HEBfB?~z8Cj?hS}8FZ8VVWV=~H+uhQn7k!y zbj|zz{xEq{*eIXieNoFB!ba(5=2G6zhske+HZTBYiLNn;3=&$pBvAFK zJES4;5aVc&28Rx%!G^mwKJN{$`?F8I;LwK2|M#ibCGX1E?>!_j$^&(|M=I)J=7{Pp}h zcHie*N9qmv_l}eL(crkrM}p(l@yPL$A3RlzpnB8rU^2^vhb--N+Ox3 zEjLnbS^2^OgfJkvOlrU^Fu-XVvBssm!gBA-(UHjaolq<gVYb9kV`3E60rTO>v1woY1mSxWi^X&+#A)#+Zy! z`%=hE%G;`?EN)v}@hX_98G{{z31ueGB5x9EhJ<9qX0r=1_L?cuabLqq1&1B?b;G}I z%u^bhNTo4%j$69lzwV#s^-}+O={&Dj_}44ud7b*#sl8T*A);Bu@LclgsEKV=I>vBM zvl zs&(px1BK?w1AB2ZRunp(y4^ZWN|Gz#Zr3cqKhi!@W$+^}Ytvb2UG1j5cjarw#iwqa zYJYd|GREUllb)C|E1|B<#xF|B{;zG%qP#XXS`-ZP>Lnr<<>(2Z1@$hFou55Y|Cj-@ zH=N30tULfK%aJsG07Ld7Psx9&LwV68i!KqUOc+K?Re;JD8)l-55e}nqxpxn?42J5R0E>qaNJh8GV=o~&^VB|vxa z0C=$m$)1eV>vso^T7rDKa+$y?l>HM^hrmscAML$})F6NL4amN9?xK8#ReumKd88rX(eg-moKSO|@L2vOh zgl#`Vh@XL9`5EF5+?sV=PR{_TEA9G?ta59!E4(R<)5={Vm>_r|BJ(^*2}l6tk;uy4 zha_rl$V%O1Kd>?=c8pnR$q!F9J6Fj&RZ=6Z(osMr((tB@4rqG(HF4UtF1S^!*5S?o zm=C=EX51Ni`J45uYn^)uvQXfvS*g>T%B$`g6|AAbhx;dN0o@GYw2Fyqd?gG5B#27> zZL}a=77gL>6Ljw==75+%*7ofDn95OHm%cP7BRtLL&aE z+el2SP=0Or2Hj$K+^TEEl5SBEF#fJ6EmMuzd){_*IW^u*AM)R3q-Ks4q+Mf_X(E=X zL<;v2P1R@$)LT;rW}32AY08@POXU~fBuqo-mO&Um{Q31m%IsJqokMo0Z{#`#cfPuR} z0roJ7c!=t0*9Eva@-o9vm(aVD3$0%%+^-FvZ`O5J{utIQGk*gc!d6s)0OPuFEly%` z!|At$vZHN4s?<-S7e+G~8_8OA3O?rsFF}3I+jClP&+%_p3fJOE+VsYGstyW@YVx+I zzCXbFJ%ODw!(B)06F{Y-Sv9M-U)Fi)67*Uc@fRLQ20%y?|Bo)+;&9jOfq6k_ zzx1Mh@}GP`=~+#~cUS(_FMs;+(ipDLrF&90Q9R~f`TXzws60VxcSkCZy?Sg$`46oQ zv}jGNfv>wZoH3a(*DKb2T7yfL>xu`x4y&3^kO>L!s%^U~dk?y5(Bvt^iq_jWt4aGY z>Dran3lBQU@P&EMeR=c*BGg&PR3?SwLFa-89fygP$7#_j?{8_J^7Zx3O&`@CsfcRc zkHOQo#KExN%5s;SEN4emELY)D#kj&BOSYvW>O414O@ERd`J;dC^h?LkvC_KA-ISk~ zk|Z}YA?Vl0CndnFG3`ma(*~_p`W6EWy(J$7^N*hb6P|1ZsRAfgQAM84^*;VIDD1{c zX67P>^(anVMASbeo``qTbA+Bndx7_&A{3HKW7l8QmxFe`C6DUSB@U=+dQ;mBa~ z6icf&SEWnRQ_c_svR#VUafIR5AjVzwSnoGqVgdkRoJf1Ey7QGt?Q3DWQpr<>N6S zGqy)Tp36O9FM_TMZTNCxia4v#)^f@`%Fke-~b zN>53JntOtg3gEMQQg0aA=!e zs7%qT!Bip|1SOsZB3o8X&ZG|w>HI2|V53=)*SYGmh(eKwIU<^h9#th&nhjW=q$*Y7 zg@e2xVRg7QYe>)#C!w7xC71u~AWF5(A^BIF3<+9*`*w1H`^LDy@7HsI`?hkS9%}bC z9yijwcN+5vPK^LOnL@T^npJFJdyR5FBfsYhPQPUJ+FokGk8C1Q?7NoV`vsT0%IlgU zGfV-oXr58?I>S1uT}2`n7xc-}3ugYxkN-Xze~8W<|5L zcF(AR{UtYPjOD@L<}D9%i!g=o>;ITsws!C5BF3_eHR8XLEDy}WU1_?AirL}Pj1i;wd(Vc zo{%rqGC9VF{v>xW?>7SjxUDAK;37|$CiOjbuq+ zE!4A;SqmewMAX^BMxf62d`77CHUb`gavOBqA>ep?saJib$4nzaZOu+BK*J>qFay6kl_hzo#k*gQx`~SQlW5z zHKWz^kP@OcRVl;);vUiDN$AW6!61z4t0*W;W$>V%)N|*Z(@H~K(M8=cz$X3hD&q4OjWQ)f&XCmNVCeXZpJ}Yr{4E?(DVU+5YZajc}Il`5MlG zd~nn{Hpm)!8e`$(C8G=Ua2E6!Kpp{bFt6#TEOdGvD@>-q8hD`Nyq!tn%`8OH@>ve& zGx*b8c%CyC*IAC02wdZ{T4_TQQQ@pw=8(g?u&XX%j-FgmuQy$X&k1rA9;dvvOWctB zRZxF_R4jtfU>1*{YjTJ@x(iNa@rUA4CKm1TBDoo)JdnSFYP!l#fV(3#l|p_W7n4Oe zQqyPxr6-2Qy0*C*%kE^##tI3h4Q6)vP=K)!Hj_>GVDFH`U>>XW_wBtCs^cF`KGlC+ZCcrhsuN+-aW)iK? z3aF82TR;sV2@P(d2_fEs!ns!OH>0(HX~HuP-ctPe0UB>|zJO$n!I zy&qJWk&diC!v^krs?Joyi}(+N`j`8{UL4B|H;=hvqDCMD^=tA}+C9?j#t6fT%BsFB<#FcD{Yk5+ z40%dawSG`$M+3R}5en8RRa-ef75BcL;A+W(e+JN;2^FTzr4&NpKwdHl87Ef0QvUCtSvFiW(cfuplH}KaF_y2KUI=z{qlZ1MjSF@f znJG_y=|yM3LV5P&r)%x7WS;SIC%lI2IY2W5L0pgAM3=<)){$sZQZ>C-^95#9L9-8F zA`2z!>s~}}`uK&PXvI8@NH(lx#jS)VE8xTC!hM~k3j({CqK#6lE1y2%=#RQy%0JIE zRr(XbL|7*!BH9vlPwfEwXtjCJUX0r_09b z`IlK3?N6CO;?h|i4$56rWBT0_EesaoGdC#n6kfqvNivZI+-oEU_oqdJFF+@9hqhxD zDF(6oI-)~KTfr#9dzumP#JgDj$<0i4+(lUp39T}f3`VgbP!^25Wj&@<=y?gKB;LhH zRqI|PH3<~F1PTj!Qv=|R3;tptx5$NdV;xPUHM*MyuzCs^JOs^FbG#5aJF1r$Owfkf z;`fCEG}C8#qb>MIfD{mN4ghs%0KQf>ihn^Pii3cNSv^-uW#*HOYC~~R-Ef`j?oInH z=*Gj*3{WQ;t_tH`Vk^r476DGUfGlvS8V&LqdK4%m^h&E<(%nnx0As9pP2riku~z)&H7k|xQ&2GrY?S5Unr+D-rgFmYS~2V|)zD;^B}vMMHz zdjY$_PuH;{4D#Bi&^2?c@qiXih?g)cJ2!^6MoP^Z)K`h7rUGn1H`YUUG zw5N;Z)VNV9J6Zs3av3@Hm~}i5I_KZq!-9z6%JMxgaE2dyz|8cNf%dIL=Z zI%_0X(%MA>S&t%ka5bl89;EmrXAVzHBWc1$Yv2IVnDWFD4kh%UD4b=2`j#neWiknp zY=F~-gcOBK4>4Qj%xcocoZ0t9w5j<+a*>~3ewfn|$wi3is^H+@)qzkYhxAFX?Z;@<)uoO4qLNDlIMeCLz@LX-vedH$C7 zANWZmB}7rYy6|SO{)_*%H@g;f&?X|#X8R|+(FfL{`9?q~{!(Hd+B>0m_BqhSEU1F@=fzN?4#8FFd(;j2Kd zs*VaE_gS_hLbJ+bG`Y`1Xoz2;1z1rl8hIE*1o?CQMAm9oH;Viait_ORa!dys2ULR^ z^+lO0*qUvSFIK$2+G&cq)2vxPOjkg=5_#Cilf7ut2SD6MmAZBHe_;D2E9kJB{$S0H zHktaPbeQ=t*z1CG)s}JmGBC+$b&L$Gcxwh&u^AbR9qu;Ms00?Emm)n7QDhFU_CPaM z5*iJ0McHRH*>6m!U`PCWj7~gmr%sw?0_CIV(wL>;P;OZ*ZfMTqXIOx!m5x|rHw$G< zbdu+(G43o-gEq`t#H3Bd{ffIcpE^ov5pqsRtxvW~s#$9R$fWyq39J?Z351&_@Eb;$ zN&}(q73kK4E32zRGI_e_Tgo8Xde++g4APjx+FY&~f}VgOf~9su%tgj^R+S2BUMP11 zQxp+`_Gv>e(g>>tPo+p%)La%hT3Ngc#*d$=y}@H!|4h{O*Tq>^d&Q-T6_=1z7UsKt zO@(1l{j5aecc<{7_kUCYlkJjc4*}> z>RRRfE$y4tLnk%k*N?ioY9#qFTQ~s8=DA6J^i)#4W8DHUmhytBFz%QYyujBVYaXvZ z$;T8;aY{0HtZP^Wyg(Wg6Z!^5C5i|L?Qe&1s>zQ+^X{S-VV(Rtzm&%E3acoC%qp6g z>kz9y60%{4xiH&K*yYnEB}>iV(L~pWk%4WfWCAV_iKa=zVXX(Ymw6TBre)r+)7d(E zqZC!b+#;50XoiM&dLaD8o-yOX-OA`qGMu!r8)RF%frwQsD|8kDry>>?h{cLR%U#ZW!&DeK)g%5MHDP z=u`3{D^~yaLR?s}pDQkY#Xd*|GLsaqG+P2QvrPY8zZ@o!0d>E~GClFuR!2+Jf?1*# zz(pmaAJ`ybedCHk;08n=rR6(VKM1y#&YG61`+f9Vb6ta{W2p61{Ra&DKM3I+y4rSco)+U>ea@r)<4C zlWb|!P-#h*6zDOl^Z&!5I`P{x6v6%Cii|}HhBSHYY}ul;%MW$%u2eLaoeW#XvalK| zFVlR?BDtfiOQ=M~q@z`z9AudHk{w>LjgQ2la(UelQ?E04P~}{9YPTH*JQ@)#Z`Dy) z`ts*3%1~2zA_*YB91yc>h3CQc$l~vlRuF{SZ zKn#WHnlT*SKX`$Gkw`dv4Qu>mwZEhqK=))lW~jJm5GEmEa^!TVvn-8eCu77QYY^pZ z{Xy?SCavQ(bXk=VtUx5!?)0E{F(&tvFegvIvU9;w;1@CRfl#e%2ykbh0gKYsP>m{U7|Zoa z*;~tkD!`Vhj_9>sHf2o%hnU~L!4sjP7TjZz{McmmHY81aIpCE#8tpWdtS1x5wm@-d zkJ*6KiZfhUmVZSvzpsWnJkP-zSpJ}?lE>CLue&iWy49@LYVx?A zjvmB`i#OeXaIgz}AfDMy)`FdJ_82BxAUJ_g7l8^83IJ5B03fTY=4Dq2sikz;uQNU9 zOY7vrsR(-_P1+_6$0ws88>aI@E>5gdcCr@u@8)$& zod|}C@ZT+3&c?rrwea69{4F>96MG>1FHO6FLHKXseu;1|y`u3|^YXfwz92wJxF_I8 zh*xoscoj!kq>DY5m!#34hxEQlbalU3VE+mO0~ePqPnW05t{TV&6r7=7?pN&ByN1sK{)#Lob!0ht|AB0k)wl@+ zEi`@L=_Eihu%{Nd%(Sqwqj|fxzz%pByAv;(Sna1QwuAJ7UK7+fixw8XhoV{ zHDC@2_x7}zo}^!1EhC`lWc8+ag<~aMl`h|xmiE6@MhyP?&G?2&X@DDG_&&q7(!$lbRiX5jOiCUBBGwO3_mchIeQd^ zfL_VP`V1{TSdqv?^L0fKM?NpxBZ0NT2x?9x%E+1PqYoJAOuJQmi&P>lY3lYTH79nH zs4I(&Qsg#(l&pDzMbg$3eE`o8FQ`k!yFZ*_jnoINRbsek8Nl9SSQ5)CCSuW`qa)>_ zBgVs6b-NL3sH4mNd5Td9>4dO_IaVTXj zKq)jynf_qepk;K&(CWJ(rQwa5>O4k`H!UQsGHRTR8kg#P07dI`jHq4{b{aJdpOeB&`9qC9jt9G3_{G)HsX}!f-uf(IXAeGe(UKiIonW z4Bu*ifX!t46ebsSHe}QQO+U2al4PbGn4yA20hv|IWgx9#YN?4wn8~XdJ%iyO_1XNm zOHpi6_`De$O~wTlub6C$Ld*e;|A-@Q7o>8+An`+TD}&h z%#`bIfoovl=B&$2#i0T?*HRxyH`4@!uJDTKYFZH!5wLV>hFHL0c|z-Lua=ZnK zfi4SFYj~o8!G)Cv0i|<6Qxk`Ot#0WxMYDJbk}>>APLnu}%R86}<fb`DDZ?&;|@{*J_z{*Kyq65o=8&&A~C@waZ+ z$TDEiO?)rZ(D5F4U+fL*;$dF%i-lxdbD_^egw|?oUH+uL2#XyQF?VrIC+G1mS`wou zg8Z&mv!>=-e&XoS7h8qxmXBbPYW4LXJ!CDCh)$4NRDQaze6?@kOxHNcs{769$BOE{ z{^U`uX3Ad;1q|NDsKnrERZ>7`m8|hK#WS#mOS+iQu~Mo^H<~u3mrqd1;!a48spMQ= zQ=e;~Fb&}!4BKe_V9>sOb8$lrx!bO`_{O|;#pPBe*GNR(0aVVHmCII9#wJQGhIVlMLOZ10icD>neNAZ z4cA!sa}+R%xZL-q$2AuGLPbpgHv38zI<4}%Hpp>b)srFVOkL_T*ZeD6-#WIBai7*d z;5i~VW-7FzGdPI*dVMCuXWmSPs2Km9RmT$QiF3lCohV)8i`nesSSV-o;jChXs#)sG zGPYTh40lFKIr6In>|h{OL4)wJ<25QvFEa{J+ozEU@2N9B1q4EnxKXdtVH zAt8B5aWqjR=>4Haj#D;p79UgEY_`ZRn6o=w5O5+2{SXA~M#_&pV~9hz>^!f7Oxp2v zwB3y*+>LTX=La8k`E9{ZYR(Boz>OPF#(bA%q#PuZ2Th`%@^=T!GVv|TeRsCMXw~Q@ z&1)I)`6+3`vI2F;&xhv%>*rWYH9g2l{_szgNIi~WY z38DpGoSWIivgOpetKx2*hAo8BT%KPtUV;Rq?UEY2X984UZuD%QzOcf;hnLH%{zEbRNGL6$e$%n*rzRh`_Sxa72wkxze;wcJmM zvl}DH%W1ypRY!g!+^jR{j5%HYrC@v3#ow_kA{M!#GWqnQULum0>rs;ztso$-T1r=v zs0hNFE-z_~LO;BX@@KGy0l4CVNLc|wSu@%IvlnNT0XQT=wwwIPnJJNxzKs#tS3zWu zVWXS2I}*3TvZ{sbab7kPQVx!dXoQ-#!!{P-qQcRbZ!^k?hb!7aMHTfLIFUIRJqX9V zO6D)MVE$K&=YO?g{#Pf@|7z9zuU60h>h$?vJ$?RHXV3rYy!l@}fBsh=C;n+Z)Wa1I-o5Dr?+%>c-P=y^j$>@*h4at}-u=M|-raqIckHa3x4jRY;NATv zc=xdrynFZr?~a_{-6JP>_o)-S<9LLQ{zYhWI|J5KYq5-n>LwHVHea(b;}BG$z_ee$ zG`}rK7Y2>O8jHb%SSYhR(2%o@C0BpEH>z;nOXbE5&i?)2d@aT4Ck-CTYIYV|>m(#J zf9=}k{8XWAc1B(n@`JKCDZ@A?-@%F0w9opKpoOEA_4x}QUDevEd^HWLF zzr~t(!25E3A5o;(bbB%a$0jY$Rl$q)*BcVd&MZ*sGz1e3+gqPW2;SLBYXPsil#L5^cbgiidkZ<77;&`-XfKZHc$d_@TXThX*h*@Z=ZKCAn(66y+#~ryC^J)W<2`AE^6nzS zuRUflciY_=*D4=-!tW5L353Qwc_adG<4ix`m2UXNQ$_C-pvq;`gV`$DYVt7qcG$%p z=C7WfezS$d>h{RH?N$?j!$%|RomTd#;>OSilru<~{YHodZ2W9iJni1_uHEj|=YQv% zn-0y~k@{c$>4zU*x&8NpLo;{2`&Jx4jz*%|&sp4BZ?s@Od@wT%Z@zHRzny=Gcm%g$ z!#A(`Vf_!Ue8C~3T#@k!!f@M1JUzxilP|S@Up@cep*s$3c=9!83{k=1LkF|ogAc6} z33uLn7(z7ekW9B)8(e=#X`W>6;w%&)-9wVflrWY7c8MN6dj2lv1jdr%*zu*je|P@* zS8~P_?}_NkorS2z`J4Z!N8uxJ{-f_b9oKfw97Iite+H$26#A(}C+&!#!p9zQBWFY| z>q{FC*^ywqH>c4D)}^n#<#5(ZE%z4hd+x}R7H-aGIlTAad$I-KrL$9F=xkw;t1@_y z9=U^TsK;AG`@wENz`-|8(+ehCM0L(w7SL8;-tz$2UH_ z?Hjs{o~?i1=JsIL(@BIwSwf?<(9rUJ3+y8Y(}h5BFl%(?)!QekpZ9jJ4C~E?#7m1PeC+=#Vh{j5HpeDXTxK6 zK0H2r&b1ur`VXUD`egpl0}sOxXFh)F2S;AkC*Iiq(8G(z{`A_z+`ho%_LHREkqQ3= zKe!_YrCnXxeFy1+*r{o1|2P|Wz`cOpPn=9CAK2iDa0 zW%0~*g!pcTVMxt(1h0UCi8Nx2W@kdY-i<%=@Bu~N$Lrtp@ZsmM#=T#e%%S}#(bhoO z1l#qdTo1ATIUpLZU-XjaJaAzBo8Nc(3-+<`z}Z#^`nLbAtfm){{}i%_S}w`2>nKT% z@UiUz1pL?E891;&L$<(M^t}mP*^Q&k>m1uh;EFbcSrHIpFMrBhIsa*>1O9H(YXkPx zGGctq&S$&%rs8lvS7cHH)5Xiz?xl{`?$yD5=wRWH=OxU@{r-dl_1}whn&XY$n-I=+ zEdey!QQGntprM>+3q( z`sOzd|K{wrzSMm7)Q$gr!Jx0#nktfx6wSBWTGnc7*-TqAO$k}%`~&f9!w?~4HWIVC ziPHmcqv3fQl+_Eu@D3Kok*DDqQN=2uX}kB`v-@^O{0nfQ;Sm#iR-`xFcSahzL7R@ zg8T{5Wv2dPG3_3J8Z-58Xwe9mRiA|7fp+3S-+~C?`v+lUxIbljtQOA+=}ogNw(7a5(C#P|QNyg-aS%fX_rlogU6}Az{ zh?o)yen>e=(ZTI1#|^~}~Q z@z3w*=x^2^3UG6McSD*&8;Pwyr)i(GtG`eOSjZ=SrgOHx9Q!#Mw3JLc_pzRZJAYyw zwBl6U5%NJV+cU2-0WiH;0}Jang?v<()rW_&Xx-Vj-o*j3yNDb(+IwNlv`G^(IHTYr z=eBSVrz^D+ey|?%Be_Py4zO_W2?v1zCh!NeiN&SI$gB#c&aa!Ey4j2-nC=JX-*T9G z>h-@2=}I0P_mt^yP<*C2f_eJ^UQT}-K4#K8PnO1?+s@y4q;zL`=ULL7>79p2ccyoq z9^IMVd2DoNdYT!W>0CHh`SewD(^vcS)pOI&^yz2LO<&{F*H}8Tikn+~hDr+H0z+qC z%=#7SjFI&Z3%h=R5$eh!C&HnlCqS;83v$mSTS>P~;w20z3gT=?wqAe--L{{z2Tq0A ztU^GN0{zQ4U`iYZ0jnZ(R-sSz);K;BNny!&g)7I(qV*8=Qu_*tN4kj6C>^XqJQB-j zWD^Y9>!i4PZ749P*n@9e#BrKukWN1QF|a9r>*qO{aH^yJH&Jl17qDzW8Yqf}>aN6o z^t%XF6G%?ND#Eb2q(lvKS<$q3lcjQwDZI2xmoeNzT&{1T;B?#?^C+FWz+_I#txe{e zM4agSKt9f(nKX#z#6m7fb2$QCH~H%w}iH=?r#ZHuBffz2ahO^!clI%*{Rjm~$oX9G>af~v*h z;_oxJU$IfJbE~3syX~whsaj2Y21e4JvF6Eh8(4`+ym%~KKH5x+rj&W5HPozygK5fR zKd?5_9tF4oh_!!m+8jw2j-^YbMATaAg%zIw;0Q|7!(t9oMpf`5`yWOlT` zp0qp`(54+N`z%v4x1lRH>eL_YTHv5sG9V{W{=F|l6msNvOF1m?>{8A-46hFmFK+|$ zJ)ZX97ISWX=r!7LkB>$1rFML*oF#s)t6^B<9WxglAB+0t_*fRX_^|;uujDm^@;MS~ z8%k#zd~y8&9l7QuT^-WEuGm?05!mF+PHOa`LmLtX4o{~(;&lK;%cg3GUpD4OkST;C ztiPdXAyiO8m;)8UoL=&^2suv`A|N|JoLdTMdKiPoc0(zCO&gYM<1Y_VDuTN2%z?*6d zzPzR#0E!6oL$!MVHL%(-Qcl@YK4n5vAe}Ys6T=L`$&i-k!fXkC<5U|$+fJkGO_9m^ z*Wz~n9P8j!r0LxYg2m$F+bp(W)@Qe%2L%Z{K-EU*Up;|JJ;6DMhIYcTb?$|BB5EQA zPzQ>!TEUt0N>*8#jG^vy@|<286D9DEIvsJkA^2gY*_To&6HYNQRcR|8qRS=0J;QPX zA=TyF%+Zdy6O7rKJ8283j#ZJ9k>SC(hbP+T!|@KcHACL$*#Pt?(SWF)RDFh)`tbXv zH9Ta*kPBdr*2n{Nod%(dO(^UjvNkjvN*-z)F%dK?2DDk7t>~V+P0$NlT@$>!z8KK6Wg-mbY8lhPQm1O%Abq9Fez8+{$6?zF)Pq_iT zb<~*hhz_blfTir7hUzoy+s#h6?aanmJ75)Z zz~zh+T}EazM||kHzWs;Lv9l0{DfqL4Z)`Z03I)Ro@z$@0{2~vzMR3QrotE4@q9O~>HHH<@t zI-jq?P!>FRt4(GJ&*H5V4TR=SmOLu0%|WYuUsD7_n6#NWaz>BaoTK$tGc3f~>JIIJ zNePpn@tm`oB3kI|a;I2Zi%dwhtlejsZyM)(OC#jfj?Ix^5<$;c}DA2dAT*)uor_@Mo(d8VZ-vI!)nOTbOIQVttjIJB;W}#(G-Bhen#WMjnhh6 znpW%^Br?YAo06gTm`f=(J0Zhzr3nlL>ch6ho#SgqGE}?GbMWQJBf_jiNj3vtN`g&W zRwSo&9>$^r2#|r~A+T3cq#xs#=O0WU1wUSjmXw!dHbdN3_6(5{;4vqblGzwe)L0`P#;861`PMBp<5|ik9mZTL3er)x#WV@V;B9d_4rej=gKl(G zHRe%OJfb-xq$-ZO_Ej-|VE}NL-%w_D4V7KK7#L|4^S7=z9|t_4`RS!bdncqZrPR_n zjPIjy)1cVOj^{?+Thc^voTcE06bO<1h6+qt75vkD2E#-*$RTHikyEX}H-DM&_)|i9C8zBV>uAhF6F|4Be~q4H7?YXIbV{Z> z-;2=~G4R!3+zX7BYP7us(t@F63r55Xkr0a^UBnYNa`cecPhwSiic68iF&WZ={?tzm z?`6Lh;}dvPFX>LYE^mx>+Z;L62|BXzbG$W@Jz>*-6)= z&!B^ZxF$EVNJYQRSWNOmt4P*aSDO4TtkL_YaUlvzqS$<&KSKkgYlI0qW?JLawk~Q zq!4pTbG#dPV6tk{4nrR^IIH{m)au?0`AeXdkCL~HXsO1cJ_Je3ML?X@hadWS9yl(y zsE>rLMSU0f`Ua`b4sehSiHnIN@H%VOr{1Ylq~x-}>c*__(b=Jd8my9c$hKYgUH^7RXA0hYRdw z1A~D@Mf9VX5M$_eK%@_vtrA3Q1Q7d(DUa)Y2B1~mQYLYYK8+ru#kjvbV`PcF#qXM@ zdL!kRI^;iU$^Qb=-+aHv9A+mmNLR(#Q}`)t%7h-scxA({9VO)I&66=QdvI)JPaDh7 zG758AfS%#U9J_qI(_P3EWztXVFiFL{^0amhG*@!5o0J=vd!V@*PQvIIXf~t4G@-6V z>C?toTUeByI@Zj%{L)zSH1txGuW2qJ3s=okddQjZ6%~Hbh^KQc>6iO6$jqnrnoG&7 zPw=tq&`0JTj_}}@49mC@#+CMRewhfGSTQhl-h6tBER+0nj-Xh@ z5YzM?Cn9t>qN1CGw4HEZAGs|KxtyM2_WlBD8_)@@i*4#a@RhXK(^JkY;XKQeIaH&p zUq(o{%YuHM&f90aVj$CX%~b>E(hPLdI*BF?-lGdN-35>uZk#(YkZ9|l0c5w9MhXyJ z0U|s6?DS7ZB+_w!@~5}>nT%`$xy{6m>0;_?IzUw4%bnd;rw!cWR#@Q8rbbj~6_kZM zj$k={ErvfGOoBymBK&pMtPo+a*_EE|P3Yy~BEAWd_A&M`C0nZJrD<=*nCDZLD1}ck zaRyp3QCp-M7Nz~F0n4@JDQaCM)N5?chSi}RbY^v!q&x6qiC4B0H_znU+D_alLlYmX z%1{=cW`!UdS+KmSKelBL@!jrOlyBRBB9&{+vhx`pTDbi@jVuPOi z`hw~t{QLTS0_rnz7u)EVx*{PxFOvdvo@Man%&InGCg=HY-ge?Tdr0(=b{q#z$;=%^KHX-9Y`BGCD^Po1407^H_^r8{0$}*K8@uM ztJe9nuuekLr-gNO{?o$s;?u&KPxI4t@j$Ysz^|`QI>RQLoJwfkA#f|@tmS+3N`dKc z(37RWw#H26dMaznB<543?|#D9ibeqy$^;>p~Q!Hr1K`O&Gr z^yhDC+LCkM3?gAb+pe>!VYhX7vy^x=3v0h1j8}l zQnB0=Vt}Gnl`ZOrmv})f{tRwUQ_!t%Iwiv<#>@_x8s`6PC5dK%^RYz%8|$x-ZwgB( zVs7=o=-APVSBQkI215fIr(ml|!wwsT$iOja8bWD^Vx`4qzsvJX5f*}LBA^`>Qs+1iG!~yU<&Kdh&0+eZS2`?+k z3oAq)qC%uXNp0c3$3pWnm^4!Jkw388tYG0*-+e$WGY8~`6MMzC>X4!gPUCJ^6+HRiDoVFY$ z#k5TLXnnfOR#dT0ekNd8KC=Juy7`4X<2|cLr~sXUn~UO$>~qpu7MSskd@n+;g^H1< zyHXo4i!l&~Q5CpgIZuZSN{Hw;i)8p~P`0@pJ6U2`Jm+A@E`|$DA$4dS56@j8s`^YQtoSj0b&sWVk7Er}n#{$M23#f%h%ERt_*HJMuVX;A< zQ!hbvJr^G<1M5#|NP(O#0IL3bI|Y7Zuu8% z%$Etsore~n!b^kG@M4FV*ylZh<*Aa)H8uHic_g8~@5ja$v9TiKTp)TiR0E=uP z_y#CpA&#Qc8y_IzB~y`io~df`RPVB3%2y!Qj?ayQTGCO~V*_Qu1^dZsD#V178!=(9 zn=o(`jczv@wNih0lx}7#GSejB!4w&+)}hFxunLHZa0-32%qy~Ebr=?lbeO)4SU~|c z2`DRcSQ$9<)qu3@zx&|Vr8OXx{kh3)bt4osHyX)x3sV}#EIehT%)>;pLHKYCGUF}sOg$8aT|P-8Uc=zT?0N9osrrrnf8-n4kT z^I=PYE4G@>M|2+G<*F8XjrUhdQ82@qn23o8GtT@R)UJuzQfQSEbV|=+;=)2)rLMk z!P9O+!vUDXjl_tiHCHGk{E6L#eCQ`y$Rrjb<@NSDSLnjEmBy@zM1znPO|7{@*^iMd z1sjDKFob%TQQvT|5j^w<YG!3j>OAQ*W?7U#!6?Y0_iODOmIZ26I7>+`!@l1;rO_ z4F&Bl+8!4LF4f}Ye+Cpl2arS9mM)A=vQU5?GW7*q#gAZzR5X+@VZ)4GX(FLl;zJI{ z0*7{_46CZ~vF7#zRhfz?!j_-FM{m+39!X@xra6eV1j2u9SF(XKLCZVLi_B5m9*~(h z+R^olGw_9<)P{0-pr*a9mji@?7#uc*vbjP_8IXlxAv()77#)#8F`LbJs7d036jCdI z&^PHd8OUfqr4swDdss^uEs3du)TtD@Pc~zh%FlDGAc0C@kI5_i6+?W@_kYGc$EFx1NI)#hcbOe+tHPje5>Psr81GoVs&98+LgHEX7r8*M%j%YTf z97TVWOEVWwZb)x)Y$;pBL>!Ps3U(2u(2bUab|59N6r3@kK?LMh1=A?=I~6k%GMTH! zfY;6!5j5y7u>eE~)q^UOiVf#<&u27P)mYIpv(gIVu^_zqrWP3#tV=xl8Z7}LQ$`3v z9nADq>x7;fo}zxx6tLjNKo@kzm;$lY`M@KeJi@DAE}qjv${kx-t9M0t1_2=!4TEB( ze(E#2wcIgS3#uQYkgdgl);n@|@>yRHC3TO=$P64}4A;V=af`1)QOAgwN`~r=P1D6D z8cl^1T@ijkmAYAM;$bxSJoPHf{;7_dHcBqI16_Wr2s02M(EcXz2AC{Dq!|TcA8x=C)pVN8F3PXjefZKr4n>)Wi=Yi1^ z=QSmim){J~H76v51!o%_J;T`SS#2V?=9_zpA3FD3W3ZwYU?U8Bjg02K#55!YjH*M0 zvMLo}3iuaPN=bw|83QTOuENvqJSYP#;`~&_)|YgZbTZ zNHGj@ZNZB60y5}pq2g?5k_uta$k92rCTsA(nUvAU0@KUmbtbpevGq6+JHD0wm^MP7 zGxnDf<&KRF04{97|F*jU_zi1izt@4di&n0}yi$hFQOV_ZTJJT!aA&%-p5KGtieD z8GuYp^2}$zFsCo5qwmoYgnr0EV`kY}s__%Q4zD~%1;f7PmDgCK!I>Chyz=#ySKcGc zyz(XU$`fST_R15Tgjc?{-kDckSLeO*wU$?2gFn8J8Lxa%pBPOz05ks6!cahx3{5oB z74(oH&_NS3?C0^y<3fcsO?^w|&=g*Ynm4eZIv;DM2_(DimDd-dNPzgz&WMk#{R?^J z-~E4gINVpX$I+Ng@o*AX3PSWPvJiJ*=p~1jlAb zYC8b#k#F6*bWZ%6-r{bZ34r?qc~Fbry7%@*NBEmB3ByxeJN%7XEl>w77?_pk_e^b5 zmJ2)je&4Y~KU}<4anVl|eT{>n$GvnT^x0HSI%k?*O1>JJ=+IU`jBZn82@5^++ zPjb~jQ*OT6o3g(Btdp1SBVt3N`+e*;t=^{55If?g!IaN z*}?-X+xMls)`>$rEus~9pRjeXS{4CXws2pzIBo1pYx}aELI>(v=)j&r2TGw3nUF1E z0bNCxr<7axl*^?{_S2muM69Ur;&j1NZEtbW-omF`Bwb8X)}9Xw!CRz}ibVxhl#6j* zSg@Iyp`tQRM$K(0#*CsU25!6eJ+MK@aqbC@1S);>(1&e3*SV`M$Z=FcB^H7Qq@hJB z+6j(n0;5%1S6i_786vCsZ_2v&WG!fD2Z_N0_3iZy=wD$m9)R*#FyAgQmoki1L z(KOk|@mh7mu>y3o+Ux^$HfxE#dk#$(F#d}y1ljL{fuCx*bb)BPpr9$?cTcrF_V8JI z$x|+p_KBuyZ$47hS77O-%(pZ$GB?L3NGtlPQ$5+vF)Dt8@0w#jG1nzSVs+Z3puyCn z&n6Eo|1NYwv*4$!GBjY0q*kv|%(J>$UGX1mQAUexvl`K3sxk3PM6KFzblSq8ITBGj zd`FGqeyI?%2I&BFAHYXO6qRg8zR}Ji9U-pLHJyjeM0tC|WMT59_nQSJ`?4?|S53ccw&U_oorHImFEi+KAej?mYZg>&vLG>?NnGVE-7bQG zW*fAH0%fzz$Cd@P))v*dU;CRy3Yc08N5>~d_p!vNiHagdw++;6#yk!&%y-fvhDfUg z!r8>I$Vx4Dh!}80Q5y+uVw62G#4JF_>}}@!AM{LX53A|;;>%t=;25Oc;F)44T*;O` zt>-Wnn7P`53I8*j7|aOS=@C7t3(k5N&MJ^9)6O_n23l)2X^C|@$07-Fs%-3Hr(svI z(-86yCDo#t1xaaFBoQV?OkMhMK$8J%qo~Xe7LAcXYbP1#^ph2X{^cHeKHSKXruPhK zMXDXED%gvl(95|+7_QXCa187eXSg=lL!h4<6ndp#e}XVo`>ITWoGI$lwO}t|!5C{< zh4k3Em{C=DX(sTB)T}{yk%w}SGzko~Y}KF5T3==ncz1^1L^|EcXl}#K*Bm`BXcY^{ z#pOUwM(s%qbCioXMIV*=N!=;4B60o3zN$V3Nv-;2SDd3|g;&_T$X8m|hDts_Z}CrT z?z0a*v9&L4u(^+!O#zW`jmkpHm;=sJ9RWRQgUol=G^L>TS`yK|W|U8Gi8j(|3l|hbo|_GD345u-F}egapiU^%&~>L~ zC$_194tR()+ELADx9Jreoi;fY$I8snc1x>xI`BtUwCc9~rBrKItTydxfHX`8ZMbFL ziS(!z`!Ju7LXu|P3Yu%b^4gPB!DXuHY-u6&WY9dD#zByDgKZ2I3u^TBL%R2bEGT>@$xk>F z%E?O9O1c?2b&lWypIUGUWN$`QkU(p!Mq{_)EqQg(9RvlztS40 z(N+|aij{grBoMcT!_rKsE;SueQKaU9$PD}XKZQ*E{bE-otF}Wys;gWmo33MKBLlC8 z+?c39gH=c!)ZUdZ&X*+TiP$rnF`*Rr!3Z||cr?j_&Q?zyKZixBPT70s(MT6TTbYg! zpk)Bl&otVpTk_H%3k$8MQJH$cqfi-JO)+jZx@art&uE>=^a)!Zp?_*x;-D~o-*oXb zf$Yp~8a~9f*8+u|1EnK0WQykBT9H;XZLS=FOpj>~xD7mcua!&waapp$BM}D4N z_$R@h8i}+6JIdLAUHl=4>vQ1t7@uYRSN`|7^)1Kp>fc4}xS`VQW6}!RBNaj|Jg5uv zQ_WmDHkN zEi@f~q~K4<4-Amnin6yR6b-V1SxCEW*7Ed1Ixrdx2d!}?gcc_$zzIVECPE7=oRBZX zLI~!4O%hEu6-FNrRG>U*Og(;4+yY71uUmxCOC>NdvXw68TOBJ{H1&bB`~jVKucHvD zL;P~Pp~gB*DV~gtyk=p;fQKGG&>8tbmLK^gD9Et~!>ZzOS#5wf2C_J_=9T1eAJ?LeA+fj1|r0 zsM|U?iu=OdYNX;w3C~X91%(=E@e>(a{KV2b!7e(Vk00bce;RGTRnIY|G7(Jj2bPi8 zVk&DzYaACTNA{hG_$#*9vm!h<4? z3R`QUvDj%{P%splg3WBR7>cJ3h6>rtX0MqOvzZNs;&+CjeCLkGP^f%lfYGL$eBbkw zp~&TjmOrJ981NL36ph1Ep9=!{vP^gTF_ke;fn5BJy=-zKhL&b*mBoB&7Ch6TWlWtz zI=?9bQa1xiqKKul<(pu%B4U&bK{S|}xPUy+A)%Hc?r;d8%^5zPV(#|(fGup-{}+4j z0%q5B)p?$C?yXz5>fWllrK(bus!GznM`cG&q@aKkjK{=vEI(w&Az|8~c_hI=Xfh?? z&oZ{~e8`s4@$eZ4A(6^aCY@m%cV-BoJ)b8AlAZ)dGo9(?5z_94Ny8ApJ>3K0F?1jd zgeDWu@4wbQ=RWF|9)2*H{t~Bj&e`{z{aAaw_u6Z>{?SCmA6tXM)JDiMHKUqPKLXws zc^F&fBc``Cx>+lofc(q@-WR3kFfXxsWpZ4*)#aEZt(rL|afFy-a#G}h1BC|gno=RC z*YiqdJ=r~>7s<;bl%y-j@9bW=hX`gtih#x105>L;f;$0~sWw+u3cR8)*2l+uw~E|^ zFnV#KoH>dfEYt!Lwdr-MLY^>`5A+jPQcM-mhhVYKL3I3h>@!TuKE-(@1%vGZ_a61k zd*m}S#iiXyT1x1F?Lxbg(U}9gR&HDRTr2nz4;Pr=4@E-P)oFy7BV&pPTf?&^Ud)bbVPc?|x*f2pjxxfuDodh8 z4&9`y-N+`eEPqBK4wXTYbiFTyA(>bp*<5QotYsuDwt_g~1i777FFo7Wb}VHJ)b3(q zQasN!PSPcG-puOgSm#aB9b{>USGjMywjN_5o8(%iPf1OEFtK8heDfiBGK`vaOeg$tOeOEDP&r!}yubc)s%|WQx7+O$=q{hX{W#9)5pIhgPbX}R%f~BB8fSX~YYAG9X-I4` zd)0pgU`p3US`{8U-V>$TO`(+=u!^lQ>kzm5rYtw+5gypZVxqL66~i0ZbdF(a?U2$@ z?Hn3hgVc7BYC)KF(nDewRziwGt<#{&RW(v@wc)8!jwGz-kAbYI*%1)G6gt)%tg$6; zOkpEz*-HQu;`ToF&BVQo+8-37lUP$0E11^>?S(m&PC)nLMjKxp#5Z8W;+42M$ogdi z=D?y1garUrsb9H8Ta7R-=V)$|^#kkqR`R@IcgQmbm(-5)<> zRgG2N-m02XI8cI0#HyMm8KguD6dE!q+85>FN$^Ta7z~Wnkw$}A*R(6^qiZWzO_5qO zg4TwTNqAFXifQ90VUxv#FDVSkF`vHUZn2d$8dok$F3M%8I8@&Ory*%)eXLu19q1|| zBw<_%U016t;PC_Gx&NWEu^uz#M~5ZMa9-rRgTEOVKZ2L zwB{cP1crWAlX(F_8^F^myfMD1q(Vcq``O;kqKSO6BHc-ZK)YZRN_*;D8%UIPc@=lL)xUReFeL=zG#@^kBNyr4E& ze|QhU|M(p>GEYzt6%eJSeT4dtB&{+A|He%n#I;-uA6%rgv<9tf(r;FgGF6{JEB#Pf zgC_0Dt_v?T0)!L5&;mRe6KT=9*rb#WYZpJ$|GFtjISBxBsSvX(Eq%Oe=u3PH4Y==t zhp(EY$b{LsjF4aUwiuhMs z6y=aG_bfKAd4fc-xHO6MVtj&<{Vw}TpfQfwfUX(3$doQ4jLeBCOGJXi9h^LM{>Xg8 z(W&X7VFNDJi?oj~?4s?XkMw%L+aK-gf*w2HnKuWI8ft#Hr_pGZ2fC-l_)7&3VNDn8 z-o}lI{qGCc$D2eGENIDwUm5YML(hKgd}sC1_x8DGtN1#sWuZQ7SZYUVNL~EdPSj=8 zXbzMgW@3Nx%523`lRVA#&>^=tgw(hudm}0i^z`kaDe3rn6aU@mY<*BwKoJVlkRW=+ z>qX8zE#cdFAa{}p=w?7mAo|5>JmNKaMgBG9D~5rv5)w%lKEgx2`kI0p}USH+6iq~FQ+g@z(rxxC3mCRx^Cizx7dHmQ|5 z@A9-r#>ztRhw~JZKyFW))J$rVpen+hV8c~sV8i-hqTOn_x@i5emgEt!Oe5$Cw2Hs)J zQ^^h*J?+2Ir~PwO!n8=EO#m|8C5hwFoJ?@21&YB^LaC$(^d!CaC`uB{M81(6<)C;b z+1Mzg%W%(vRp3>7VuIwhn094cHWqdh9~~_o<*iBXS@4riWgZ%#ff}P`hGlh2>41}A zR@fbm5Y`3>^WyYYsrK|qtjvR%AOf{d8I)ANhm(xGfX=yY0;(Y$HcUvwo*7}<#J)f6 zQse&Yy(v-BTsKpUH?HqWF~PXLBkk_i_2IPJ)%Bs2G-v9;k?SUnb!V@%Dg>_dvN8JJSGunD?h_EiZ8shL*< z3!t22qa4`UMvE|nzu$@MZZlt}O8vYIlx1V!ti79C=25Uj*=0`drvd4#)GI|7R-}Yw z)jV|5nsh(W1|QG`Q~S6Y{J9#a9fXN`gy{3hwf?--`*Y{${xCsz(ju3)=wjVsGWbYH z<)#8CZrnf<#dN`N-lDMzsSM448X&yWG{9JuDVWy$$CyDe!6$4c?{#3qH$BwS;_add zBM>QW2R5vi#g2d8uFe)-#X(AX!+Rwws&2hPWu{j(diC>S2gP~o))T307`pXD+Upn9 zsbfWICseSZNg;&L5obQ-iS24LRXmIx1HU!L{AiQg%GSN(_A>O<_wu9?o%g>i#6edC zag^M2R+&vR=2oGIOs`ZoBl-y^Z1Td1C!p6mPrzB!N90PcUlO^tLPR1r12b{xk0kO; zctC!5$Aj@pBk~M9b0L%`Lqx8fSC>xY9=|9K)JNoP$I#fb0U|d_gvgC(A@XSf8zKiI zjL41XA#x*nh_jWPqMC3;KZzXb%r?;SSae>GI#8lXIjPtaN z#+lZJ{4>cL`2kXgwU-4U(PV*9SRQtdI%9rcm^d%bPz!9OrOQhB4crI*Nl^|1A#0Kl zX%3*`FCS=W&Rg0U=K9*uJ*|Z~{C@J^kY!VDcDY0bK3*w5Ug`T-_xhNukrP5z-Pvb@vShjozliwNUX|Mb|4fCq3ua+vo z=3t9>D>wq|f?q0!1>N5nJ00dN7oetKLEmu>fdyyAVZ{EYKAOG`C@;PZL!-A5kY4q2 zD(D-*=r7ggB|t*sQTy8rz-!^hi$I0_9Ya{KTw=j8!z$5K_rii@VL|B=h&*6&sDjn9 zg4MnXbgv3lt%6)kBoFaq44k0&2qW=uq8$2nKj|PO$^s`Hv>grG$cWx#x{oXnt939K z;wi*7irN+tD#lfbP(@Hwr|f7`sEJU?I~SqwDB4IF0xwe5FG7y~Qme6qa3zP(Sqth3~}_p#o71eKirv!hnfT z^caSYT<;g5tdm9&st|5W)5{Z~5~ERs8UwCG=%hevB6LzBH0no?wf=KHY#&r&)IQ+U zL%EH6A4F{WE|_u)16naW5#glv3$3mx+!UQGao+DBj#b`eR-0&97T<_g>gG4jzswKFv^c;GM*}BltuICyvN|L~5iu(_fq8~L2g6;=B1lwQf_ ziXUvQq?GE-5pxBA=%AqIJVXY%ZFtD*cS(t-PD<(*nk%S~_h5y190hQz&j1b9r$O$1 z+3fd4=~(fDSCwXyrtw8XNC_}4y=4XZ>wEC7F zo(n_JY;9!-GjYajQ3r(Ho*^LQY{n$>BSWA{vs2JdhZ%xqOm9LxRINW|OwFS;$Msm7 zF_a3{>s+0v7=lW~5ULq-=8dKlXABat8EZL15C%kW%Q4^#LCzJxXbd3&d^AJopXJC9 zOlY!#saY1mt0H=iX)1=$Kg*u958X(!Trq_HS&rByhR~bj(qE@Zj%;D{j~XE;@B%Xj z)Q=u>7}L3(^v(Jtv9!S4?Pk;*-ymdU2YgqTy_hfISU#uwDb7>iep>ffbmsrTc7wT6 zAc9-=I3-($OPQW!)1q~{LfpQ6LC28Iw*+1$43maJ|L`1{agv95vrQJODmnAh8TBac z7KMRn^JSGYu}U~f2FZsdsXkp)pRn8YA2CT~z~5n3U&e`TSi(H&s6p^WTx3aH#LXp+ zcy@DX@Dp^JB>Ca6`2e~Vc2-y@=fuT2GG|B=5qm0P;gqm2Ll3`XN?{bY&f4^lGSCWmwATFM0HE&oewV7dsx_ijG3k^76m7?GB%c(FD*7odkYXRsS-zUGB^q> zrw?))YB~U1nIJWgGN3`pKGPa9l|tRa4s~ChYG)@GYTc7HQ9|b|+Z4ZJ)e4^qEtr>8 zBBhR3ffANP)Ouo@M9S)U$EzQ|g()Yrha94oZ)%{<)bdSrQ?ruj7(5bGwTL;*IJ%7Q zt)MnrA=Gb4@u|;fM-71|=gX;m(qgWpGJq?jmzpTkOF4`zy;QBxp${M=>7_Cag{2<^ zF$t!ccvF;!L)XL;Of|~{QyAy`$5}s}Lly9Cw4UpU2~fHxJAhqF&OQ|)q&N-PIOyKdD;gNPCE#Lf zwyfwcIDDy8QqWXYfvyKWbs%kBn}B8hGpqW4$qP`b-fN@%D*G_iL z9AQ1eCMvQF;qiE;E(qw+-$uHO4k4@+mGm|XP9{qkL}?7GVZtV<0WeG{(aU`SLZkrP9`|8*_#SjYblVhJ|r+qQuOZ``s1{z8Tk^fwLInCCKv zfhP;FeepsB;;3b%YFkz>0D!0dZCRC4Hgetng9?)!z3#sQ4j({bCZBB%u-$KME%X%` z*%H7vqSW4vySk=}8FqEO0Q>6N#ng+jug1tAxq9aHwA(T8TVuNz`&s0vj# z^o$$|6GvA1X8FRj^2FS>wDMD9o}g0VL!9~6zM;Q)d zP5_eHz#4^A3W(rqx~hdhU~WZ#Eyp=`(d917_s?7sj2L8JDK$G@gCtat>}Nd=%7rj#Ot`Q z408<^Ld&n_0-Yb?LY(>mE^vbVTreHixL9tuS$V)#c_QL)DO=Zn#h;q?t@xuv_uYUnDjmM%Tike>3j76&y*`dQ+Vo{*T!kD?lqBV-h z4y(GxV$ptz+FsO-MF%LF@}j9&bcmu!FPe-+S5wsTqE;-rh9VAtRQ1!b=(^z|4xNR4 zax|&MICniosPuE`)RIaGdU@ywGztamcvQ9nL%>N@G!NxDFdQ@#abQ_+U^r+fTBXQ= z;h>=?P~^aH&``8Skpsg)L(zVU92gE7iVjfZz;Mt|g#8^H7!DeWuBOO=;h>@D8j2hk z4jPKC+ggO#9%c+=1{sao zgxS8-`Ep;A#9;3TvmUXnkKH*jt5Bdp?}9?M=|sf-&NsGROa}et%VyBOmR`tyvvUnz zu-ImRSw=E%FTiS(DjI?fle0wB$`m1$9-?U|Pe`gbVWJ}X8?1c7a z@ut4Xg$Z0b+5al5zT1%fS1pO&xdp6$XEXXOTbh2cX0(4oFNZ|mzWs!L)spC&w?Osp zY(j6_()0^Ep*=U^P5n&wa!B+%+cCEx(SOnG%Lp>CAJS|Sf~e3k6d-~cDXXL}Bgjyy zV&xhkOha1?c#kCA^wu_iDq3yHy6!>zgo>dV`l1(0v~t-svUM4})h-?$s$5>I@vsOc zFHWk}CM6M}WqL&RCM{ocm+?m;?YQ;U9RAYiwRUyPGi8iRpC88qf{UC516!hHJ8zgU z%i1c?zFkyGzLEPWuG=XdgLW+phh4DtodPj1$8B|af^D`$8rpM}9ac$3sstc0afok= zC+w7npqh6%cmfdG<+*OHYnbl*qFF3|Z{0#lP`6{RN&cb@-Zm0X5(};aB@l(r|NjN0 zGS|ldlo$?B(xmeD!a)hL1WITnFB+8a*U;&RNGM6-44Nog&f{`%MC!{iY*sil3bJEFLT^iW;b7R>1~y;%7h)vz!n;bO zz#(plDzKfIWPd1}FXw`WB26&naURhfc6-n&Ay=#p7$!HU1>Q^Dd0Vdg@fdH~zAN8h zqf>kf;bn|hU2KHe$RM>KY4Ed%1mNh)@4$Y}IIO_std3?0PO~6E>QIm%mntJc!z;0L z-4pR6OV`bzzj&+Y9*aYe7#;L@dSX>ovE}N{)F)n4pJa`&&9m38j=d`RYhv&X7I3OG zN`POB-J`*e%=jAkUp(-`+Y~LlE%-^s{x$GF7w|XOE)+$BqrS<70n~@#+0IYfY5)Zn zpCdS4dZX{&Gj3;L)u>^(EumEl^;vVl(8P~A=wWlgVA*wy$(EbHRr1OtBvQ8^UpW#> zr=pyR>}0qFW-gCn2S@b|*xVdhiWWN8wI=jUGCOg3-zU}g@2R_x3R_QEaZh}IhCdF` z5UP>ENWu!PttTRC^@KvLrx`hjbv(WN#IR(`Ec0bp?kYhwmheYg1jotHVWBXd^r23X z-fyw9nm}Ip;W;5#Qb+p@$MK08*DGIc$Cs7sNeToX(2%4RKsC)->1diJBFVMHD?G3h zS|?*$S^?BvGVLJp5h$)N!xwhg^`i|gp z5g}iw0ysYM$UF09FV8@;FVBD!ih-`djz+o={~Pda8*6qt>CAT0;$6QFkvx$yAH~1@ zbkaJRjuSK3NfoYj$kYZ9S6Wi7w$5arg+VQf4S6ehkLa_f^UR7TexEf1QN4ni$3%D< znhIu95RVwkh;GGc+wLxWehmaDqy!af(mT|L&;MT1`cO)CI~wEb4m;1`4n)*-KAG~m ziU>&48q(O&kScZ##AfUit<7f1@{DxF>_GAw4*^SExmCgk+Jb5beyoeP7ak$6k5P*J zV}-<})Kw$-pUTxSHAQ43Y?oF#1+A%sEL<|nTi*eq^FwklxsB}z#Py|kcW*N$#B)SnGX^7w(h-rnT9Bc{ z%Wf}O5MQl$u)mxE6c6+l(C30RNDcpFf4Q_lRvoEMOyOuzI}U7!sbz0gdc1hsKYXZp zOzsJT5P8gslgD#B*|F;Gt<~LI%BmPd{dlo-Pfk{XtO(Zq$MZ1~=7zC{h%eO6wr*Nm=Vt61Yjy^g z4(_rirH!Ew=)v2%AWdE9@B4zW1)G z$pF;8vJ1b5>_S@ED)EJ1^a{lzvJ*Bjl3kt&7TQxPlux8!{aA-AFI#f_%(RLpekCb> zfxmx}7QgoCq=T#E$BckZVr8EPQ-(5}8)Q%<1Y_|k++z&#W2v+W2S59#u^63N?HBXt zNxJen$;6~W{P_JsZkd*~qt-#Pz<-NA(>#H49@bjd!mVPIYxinjN2~bQ?+FjONp{jY z;G-JrTp7k*M&1qSGgR8ycViO&*TOY1Mz4lk3867^+{Lf{s)OSH9xJ~1s|JeA)KN`< z*pdLL5P;0IMJJV&E+ZE$00mT`5weFZG{Uxk2cAGh(z^(1wrSahYPxL_M}{7}kH0JB zfqWwEQlE7`t#CXwE#SxddNtzgxY#SxNH{Lb`$E95To$H`1uoVXQ}gHx@je1O!9Ai9 zhcX`1ef(W1|EBe2d}LqV-q)8ASt?^+m<9pFh;Ba@h%<1pPM|0nKpNf&%ePl`q9L@U z6A+zsqA{`)CwsFrmNzPBHGmdK8v8)Vz93+nA&77_8-~L`z!(H+QwJa*nlbE(jXNq0 z&&GYd#_NOZ2m~)1Cq7+6Mz>U}l-rOax*KIwLk59C;wz;o*pTZZhx}E$M)F+}uLBwu zJn;q7J&|R?qVfccLACGZElt0WdS}_RbfBAJ!=?{iPT2M55INgum7kLC2Ge~yW7GFA zA_;vyjrJ&9KvdfmeUNU{I(Kk>-D%qg;9&1up*P|eGJ5T$Wv!g_&=GpPR6JChEDMO^ z%ev{|<Dr!rOH{I2vhAroKRL!G4srgzY1N5d!pQ*^81{u^K1Ja5a8PrCS!4LGB zXb0ug+Q~+?b7!xep@3?{Qwde>tR3WSA0JI= zAf*9Jd21jY*}!Zy@Pzl1&Xp~~mXp0ag_uy3gg)EIqi z%|tQzVuaU=Oe=dV3Z?1|y^B|9es|i5^FsPV@CiK-8?n>j(0 z`Z_nXR9C?uJN4qDrwBf5<26FtveKwaec@E6zHCLYQK|i{H~4r-bv{IV1pq7B8=W`M zje4i8A$5K`rH80|JThk7Z=E;rlCld`Wa}(sGs`eyrGHX!eK<#{6wposOrYyNs9T5^ z>~*vGs1TwYBYAB(Ri$@lZZuYgUwQ2?%xmK9we%9p-l{ezsC zT|Rx``nPauOsK7NNKc*dE%4H&*1@lV7V8zQ48$z%)2d46HO!p9Zc9Fi$Z;ka{GV#! zEBN$qE>3W3*p*3x9wCV{Q?5(}Nk(TTKu`F22d>OdMD+|vCWC+m9U=;4u=big@mczn zBN=ZN??&(@fLDs3u%;}WV};b7Etv} zZK`#-)%iDROc%+wGM~5<3BR?GP5^00Pj9U-CH!ucTP$K#b*uHiW*nL0OrU|&1ytDY zOaZ3huN~*)6gfj0X2IdAgNU^@R@fdo&igICqK@KASq{uR?i7scBEdGehAFT?FuDAO zz(>H!B|$5XreGd#->duz^qNhZW;?6|TR%YC|+ z!GbUZ0?2D9S!Nu7`CwX1;_{$1GDE_7D1ARh3_5^F3E2sgpgG!=rDvFhX91Cpfr>8s zDn6?!!Xm;A!YEX+oF&FKn&ww|bqiyUu<>l&O2OwD+i0n2nN+9D_XEWXE0fM)Kqlu8 zbrCpF6I)7ah9PpaD7m+;^5%3?1B^yE@L@(EgFvbEOB&TDzN0nfcW3LU_XPX;_=*LD zlW+5Qp}gWE>HXAh6LVbi*pXWZjNOwpZ3g*KDHiX?!=cV|5)W+Ww^DV6x317zY{gX% zS8kc=jYt#>+*;pjCqopq4RhBN>5*>Dm~QPRz;XWHC12^#Tfh&;3dw6%n91~dI&rT^ zJMECvfZd?H28fM_JhN5+pE_Sx9FjtCs`YbYK%3gquN+R^`)x*c@BOUsi_w&&>W$%T z1O+KFB=O)uAe0={C$;vdS*IcT0wRRE{Jgv+fysp!d|OB`%d;NLu7+Dl?q&>*&*X{H zWT*%xE>uf!KY;QAls5cj#}-yL8mfOJF~pt-9TANsvS ze+bDN(vUsQ0bwpR@wIslB3x<51M%JR$_ccoJTHt>j!}byU3zd(t-y;FVjyO1ZK(i+ zFj&?!emXPaEr+oLR)=PWP8%;a?ly< zI{C`31l()gEyS>d0nAG08^n;r`iRdElZ2*D%G1QqL@)*K6iul`c)U8#qvfzwN6jf=1&Ady3srIm;){Z^NeGbu;Tel9T6 zH7;hov+Qqs+zwcKot)RM%J!=-99MBw7NpR5U#Q4Vu!w!Z(h9BE?Rw~x-L?odz6fMQ z<4y02{Pyd#NEP$mm#u4t69ls%FnCXAFp!N??nknU3hh`lY}{lW&09C!Lq1_bN)$Op zqEH1mJlVYpr-!aD)l1EMnTLG#W8GKiv7RSSc3;NSQnuq`-LDUgC%bI%d9s^_9Zz=6 zhEa-UO(3h1=Ou;*;Jax=X2k?s|(urGwOA>YjRhN~X2cf-m`_az1C(K6U4DR`1)P&cce z40}TN%*UhB_RRHFdvg1JoU|o4Rv2T!FyWI)5?Ot4Z>v zus7syzK4{l>Opsno?f}xJvd?zzu0}bNaa{Q|75qzxF^Ei&Up9hYGgbW6obxDAxObO z0&UvEf`F&XBMVNS!<91#SfR*5SkGGB-Q;X{T3Y1K>X;_NMW)iAqMP5$$Ue*Bg zv3Rzi1S@PM&eX3a3k!J8&{tzZK1vg z?;*rSSk?+W1lwcuf+_viU?uaZSuda z<>^Uyie<%vB&9Lw42#UtBq4&7gFZpPvp|+ftfpk|q-TLy+<=W>EpXIc7WM%0J;HJ{ zGXoa6U9y^YV2xg;z_^@QFhFz51>VivJh|E3ubXCg39+d8OM;p5$8J>}4&Bm0&E1`V&?)7geYChOe`3tN*of zj`z~pva1)E?~8WTD%`%Cwq6%!D-#!fnITnbz17vSib51e80z1&ZC^~vcm6Q#qAQL1 z@=se?<5cqjF$7f)1j;e;G@N3O+&78`t%b5EMj{jI}y@Y5cVX{V(3e`{TEY zooUL>u!t=ILHBQyjL`Zmb^MODJ}%q)RzFLh{`8)d7Zy)&z}AVJ^^$vo3=MroDE9HA zEFWd-ykOtBnWbAo8ln-Wo??MnCoCI~3pNSZ+g4^;#&tvbj`BGqHsFvvQk9IU^3!!Q zZbPzZYw&enfVZE%B==QF-YtFWC%WkK3?kZ(_c$1C(b&D-<|8mrRy2-qx~79bem8sl zp_3c;2u7SlaW<#IN2qY(9XyJ=(N)IjFjE1*(&ebZG%4R#8=q9x?FSs}pSR?Lwc@Xz zefDonXP!9xtABCp@lF3XOdP)RhR3Eh{a^1DZPtp1HNnc9bdlEuK+6$y`jcmJ0QcdK zUB8*LT6XyE|L#v;waH{Bn}YB4x>MJl+C2PoAO7&G&upIEJp7-1_+y`hHMh=uqBwo$ z@uwJY^Q^>29pHi~Cr z!Q|Pz?em7xdghUQn&DOb)$sBeeqLWc!=xr>kdk`~K=zbu3lI(k(st#ZG;cLF(3?DYnn%ZW^SsPb)c3kW8Z#(^4 z??q#f-lRGFt@oZZin9;C+w?rrEi(U#6MNg~(_d1g3(sm#i`k1Oihp=&{rZGhNk8e^b06`y-sSmdN+xe}Rev3v3|G-@#=1+dPGn`D)POd{qj_;2OP1D@SXFC<;n&s>N}tGhh?$ zFr?VXzxd*h{pR1)HlEVR#c@LI@W1-&#cwpCQGM%>s3y)@zkYKw#{dg8BP{v~hx)TW zdN(BX;SawQva$EB{OS8CnETA90rwgHAL?h%oarVEp!MlmHp|gUC>s_{$iHb==HDH5 zaFU!c-Mwzj1yBTkT9LhDNKu+g3<9O;!c{5!$$ixAKkd6@0#%&v%DuectxZ>*TxTbBFGM zOgWnOC{0*ZRX$HO6Z&JV=1Mz$E_64#F9~y|l@Qk%(y(|e?Az$>$3{u9Opk_{V_|Ir zt8~7*gBJJm^%8;gFAZ0rVO!vT=Etd?N(N^|?@q$Y%)sDj^9%-S zV!BvN986>{#%#C}wkvi@Nm zn^)T$>~eD@_ArA1N%3`|ag@VliTF4we?;*E$}~P6{i*S5BAmLo+x2OeK4XsIu#iiX z9y|l4YLE)_oY!CM@7=F{ET11dn{EEXvVoxU)AzSNnpZFW&yPKtFATo9(D$Y^_A%h4 zpvH3G^SyCK5UOR?2VVhRmldDC{;~JR&V=){ae>~Tgw2PEkA9##FV4q*r{MaGa)%VL z8l#gl(xM_iSJO32-^XS8UKYJxm3@v0@J)sFFngaVFQ#?cSNr)H4W*^L@JFV!pj2dt z%(9QqT>lRcTyEb@>PLXgA3mrp@XhDMPg-Jugs0pi9Ar*h2HDusJq!cVT$Kbd`g>Y>LaXkCv5* z;x0f9qBxD*x+B6GB+h;^h9xi+ieB_7pjT#NSF60&vyA%+m{QFdXU#dLvoL7RzbhyD zqmPM8RbzhjW5#vF@RHjMmyxTmPMb5EFzMO+Aq_E}m{sGUTc$?*vUuj7CE8^GE1`xB z%`Q*QFA*bM-wI6a`L4rscm})TI zOFNJHkGFLNSO$T1qHhta^Y7#3$rX)ztaw6JeYM1%5E(O3j300Pc}+(%4=^fUAqm{#*@sVUbpAsM8o*eJw|$8zIokO%p0BDk)gi74&~Om( zKortdwWWs`;^PAlduS`j(sJx&rz2=+s00n#t+t$G)huVsGV5&B7pG6X{h?2`UY}Z6 zJdsq1+_W-P*Eb%2xJy(@+=wbJnDH~cfBZ*5q}tJQr@a7cYAE@NZRaE0=U zP~neuGb*%jT;g@8(5j)jSTPmK(3^;{Z_DKu@lRvyQ6Bqf4>-j-j4^s7{Xq+g{>nSNRGd@l~QF|SYP{BIy zov)d*#ojEx(}br*`$X}KeOJ~}{>(ElqzT`B_2fU7XF{Fc@v&Nz(E2V(Q>oA+lliVE!X4Q)E9aa zIPj+N5mY%%ki8B_sa75z)c{V9{Rp6wU+0X_kt;b4kPz?R(pJwO(N?~iQzt~wr<$lmkGM3UkF%}v){<6qR z4Q59&YUb^s@k$z9`q7j5qGoLKPd-;W&BWWygAcr#-x{$BtkPCkgtdz`jjM26tGkKt zv#B-|&S5Vr4TwjuINW7Q8|WGg48TZn#4qI@idL~}qnP+X(G<#Z@dwGxQsD~lkW(*t z>4zD~0wcl8Ea&GqO=C_gcL+J#1UTzzSU5qxf>UAPUZ|@(g-S@~5(mCzB|&XmIKiQA zf-oB7ag1l)5UlZ$DT5+QYXddw3>3z0$7nGs<^;Ve4u>NKZ8#iw9Oj9w3_2=ggO@=D ztt5mw>_t8W1vFAR(~JY4Nm@Fob4GyIN*<%(Ze= zr=i)%{o7~HLIBQtpUXrUz%(Ub0_OlVSX7bQAT$8m_-hp}H)YgBqYM#)2!}1>)r{Uk z-`MnY+!I_jL1WNaaVD)5h^u)UnDHaGi5C*E+vNnW;z6;)F%N2Q9?v_NoD;V0VwkIT zY}ROpd9Q(l4NT3+yA8`&q)_$|ohAjA)$UejICZTblhBICitj#N{PTo07QR--AVwy{ zfrJVq(FSm&p!|TO&WCY<$X1~V0l!n-GFBh_jdo#zvbwtRu2@(EcHzGl}(@{jCm>&Fg zny4{9wSY_y8zaxUAXeL?Rpcfg7f(b@_N%w3myVu#OA1& zIW8t{W6TYj(w13l4=@()1H{1?h0S~}27EC@Efn{1#2r~7Lk*WyBy>uu6 z5{+8_s-GQ2W@zNFBT%XYi2#T9jMYhI8_?cnL!*E(M4mt9Fw<%$n4jQrYZW^-3U=`u zLd=0ya{ykJ7OR>5Mx&TOROt>h?{nhXdeqL`tdGaIAn!q|?E^G2JJ3NfCKNn;uGGo*b^Krs0H!3}yHrY*H3 ztEC@xWhF^8IPq{aY+%9_kl4Pxg~>O)ELJyMp(ikHij7%MWmz`!G<(B1?f zR~J3F)76hKakRJ#&hRa&G0bj+8F;{kU&Qy$YH;)Q?m={;AtXOT zz;Fq}%wU+@P=6R37Smk_nYIp&`e^)kaVWlB8+iMvI&lG()c~i&@FplNmLQNkUj}*< zask#=mkeAjjh*6|zAV$+`{sM*j6CKYRwdIn0ckF8mR(30j_o&@m1AxxAR_Ap$VlcS znzNc}R6Ig0R-h0cs|VHAzV}r{VYwXes~esFB2TCsPY6MP#qScy$Got|L=|<%dL2X@ zsYFNp)Yc=9E_-R+vsSRvXoa3xg zqEUR#fNij%3ZC>XJ|{|80gppv#$HzZdr~0t#}CjG?`%C2%G(p{HM2?%Gv0Y?50Xjo zztDGW)lt8|<2B%l&tt%|)q1E#zz#00r-=$1j*r2i&K^1}T@2lt9BGiler?~i;FnJm z&il)0wq8gfs};X&ezvEH_pw(yw;(7O;wfinjN^85Jr=lv9b4qPI*{B}B)(i(N9WKm z)kzL4f)DY{A>rKU>NOQ~8}J?Cm6}46EXrSSR-ywgC>t{A%wH%2Zkw8NJS(tl3;1U+ zd}G-is6AHB;sPHV)%c~Om*!Qm3faws##YDrO=*H(AcQdHX&C4`JVV;8uk)y*u*ZQp zfaZT+TQl6TxOEb!aa9W(u~jfh^FsKqBCeI*~~X zR#Ipt*=97+xykvGA$L0;lL1T+&h3zZ;*qIoOn!xWKK`1#NsKa&S`urnkfFyM4rWoA z@1c%iqi{jof=2}twWTncro?d7nsGP0t_r5YjjJt44y^;*rltsS;}0-qMitBm2n@h6 z%Y~Ezc4aYjcw*=*@keqk4kLM}D}jvq#r}uCw|xkfb^K>=0)~fwCg7+^k5d`3*`3Z! z?2N#b(iNf)@3~?6{)d!G1JPJjltlVeHv#Tx@xMLwkuQ0mlVTx$O#Yz53I8LYh%2$M z#?I_kR(x8Ch=Rz_vU+&)I2;MbO07HHA~HQcCZ+P zcrVUB^vzv_OOa_OOl>{%{iv`o^xknzzJ3W=l<&4XuJ(+ zI*%Lbr$zn{*~8RdknrT)@%k>izAAf1O8;rOXehQrT>EK=O%(WP`XrSHC;<&Ir9UNQ z{%7qwgC_1luFQ$*l z{aTbNl!MrQGUz6)4QKURcecUd)m;YF79QhuF3#6F-=L693~995Y~`kwSTRA6JfE*g z2=2*Yw-- z9SRH5?RVsJCj{nKas)y*Wbw5cuMz%yFiGcv;)izm1J|A;txu002*poNrdyXAF zhRsD?tKGIPYveiOvSbUba86aP#9>5mcK2o?H-WV2>#K57gOmK>Yu;c-S2Gud5(tdW zgXV&Y0DmO>17DCTQo{tEgz4F71SX5;K!M{t&^6FTcy(N{5jygNXY>o9WmCB%^{lu_ zp4lyL&oahD7#zNNbDrTE;BJzPmAt9L2O)0IB?rs)Lt;`ZSA@L?8%#h3LGw;o#iy|E zv^s-6;ch%(jC}J#ZZQCsI{AwO#H$_$Nc+afsFl5^kB3lUmLrwnQ}%f1dU^e50EKWU zf<1_?$3yPrjiUjK!OQ|#NSlBd16OFTPK*r-w%*)Vy$NFQCOF}5f)cKoyh*YfRV_4PTA7?|cybJaxVrHClwcE0w?5KHo2I?7_otP& ztJSRbT9U2nKXxNYCJ5+-4j_X2V9KzPkAe~!_b37(l?9{=E?O=q@Ibk?&cvb7YI3-v zhw*Mop-@&vc#2J(vfPc!Uc#OV{DGJpkkd^xUl`*ZhBpNQ%3lM$93`-5l8B{A2AT@( zunk}zgi;xkn&6;pOjfzA!5JKbxHHS}qPCvsi6&g!8#!wm;AoK*d!@H*{J_z? zeJ^wm%m{ux@v1D$rK)N1?MWH*g#U<7FEW3IjZpQ>*sn&9rQ%x+W^+kj{y2B{QHw^pL* z8baUtMbp9Lx}IG6=03S}AZNE{tPjS6P&p*I1V`ZZ6_QI0(dd4YOO-UZ+GGsbh!|D^ zEM-`T37LF(eZF_7?K^sM>J5@pE=BUOC}!3`|0rf|mzauTCa?lv@j1x@c>z9exBhK!c*-@hDyJtMJs5 zCV~mx?*?yb>1Rlq5bIm9MPo^W(ggLzq=|XBwn`I8(=E~jUQ$r&Pb5S;P7};jZ65;t|fLk|=TWf3M zpe3QRz;Kd9zgXu;>z!lS&QrCLd7~Ob&-2IgCjRz+>Q-H4UL6)OI60jAr4&>LHsuDIF|(`CC(kLjACy;Lz>pFf|v$HOi! zpD4E%N0{)USO(Bi7{2ZUMH@er2=QF6C;>vKjijTr6&HNLsC&ov$ zo{boXmx5*-P5=_{XIzw7XJW-gBi|gCzD=#pMF;t&*>H42IyEDPLBbS?$QDx+Yle{9 zT;MmtGFT+sn6}uHAQlNCF&?SeTuQ!q3c67nJDzT$HMSsub}L=)Af< zUOBaeSE})*s-vE7;?le}xrPfpyqXJ8Is}6|tAM2DMsamNi<34wv6a6)TF>T)%8GuH zcI0OyQWnXGeTbj2Wp_Xsy)K{b@w1seezvn>N2Qht;gnh?)MKs-j`0NV;bb_KkKrih zPJF3iZ*yCj(gaw>@WhlvUUh_c>ymZDDbPVINpiuw4kcZ+XJ<#SBusAk{1V!cDJh)d z?sYgIxAGuZQbmpuzx}iyU9fl09%XH3qMk zk$u!o*xELrTpY^VrE>9#d@5=ut1|G+)LVKx>b$VLgsxyf74CxG$as!oy8oxdsb~s(){RLP!et{Df^s#)Fj|roJ9&x|OjGEO# zme5dU6r?NW)<3vNk9fKE;tdg^v%w|CD(z5kt`Dw9ZL|s_t zqAsH?h?P3s+aRXcT1JmG zInTxPhooRpg)=vdIL0Ip$G0riwVutgsUBqj1fvWr{74x_8*8`-OWJT1e}6t%io~n( zR-}!PW8b-?D~ZJY=$A$Y0+K@d2FYM{OhQZh(7<)01#^{ihm6uri6K21SzaN~2%Mk3 zY@DA6I6DV$ex|~CfB?=jev>RRZ-x7Y*nJj7XflY1->d{w-820Da6f(zWQHD%-(U$K zD&>t(y~6Q^`H8_)8@GDFy%1U&B7cU^fD_d3LujzgP_mRChR_xI8j4EClqik1xv@Yn zm7)?;Ck#`gN?6~b5)vu}ZaSvI(1od>s4&%pR8p|)H!e#Wtcw8 z%7#`kDy$nD!aA|m6fhy50TQqhVwv@zm7+>bq26QW>fpw)s86+MZc#179oc<}`EzZ8 zYAm)Vo5*-C3W}UaN%2#db_JPaBzuHHTaOcHtqT41f@V{SGTs*bM=a@Gt#@bX1naS2 zQ-}3;$F7EBSEaz4>|e6*y-PzJaeI)bPni#60uLP+DYP%*UBv@=nQL_lkS`gSRApPx z9PUm;k}Y1$|52e9h+mLoC~^G|k`OQ}7!6}bQj>10(ZYv(*-i?%BM1-xK`K#-t}el8 zp<76z;++aFfGKE`hE3RAdYj7XE;BX7V_R0kTfgto7B-8pKjRTZQ;0_>oWkx{z`cl4 zrm&wnF%ROkBj*XWQ*rVUf(8}mGL0elYu`N4bet2Ar)tPV#7`xxvF?0zXJ z^x*I>1;A|pT*t&fN^v)#A{nIm4L?c7Wz*izXU>H7xzKu#vKutQk{k_NI= z6vKh&@`#uTUGODYUN^-fUzvrvrKG3wDJrMbHyi(fgZUHpn>RTgUo5W(}5LL+hJ09DWsmH8f)Ft7i=jWU8L4pf@bL?;Rd^xZj_-Gqg-hs?2J`v-roj0?X3;rRX2#R6+ zuswN4QswYdYS+wZr}%mMsGI0U@mYyMOBwfCFFaXo4v|&$9LcJBj$~CmSMa(lvKsjO z!esUSeq^k8hY$u{BGeOy7q?JPxqM)J*(%)$m;phkkUza;G=C&^Mz-@XG$OoUD0f+XAKSJP(8;wTQma2*Q54F8avQnypO#mLaT0D30u(Cw_# zC^wD$x0|@NnCh0MdQq3eCh&*J9<2G^i6zCb!{E%}fYF-b&}>q+loL0@3H89R&3qB1 zsUw00%J8ylGr~X_M+Zqe8YnYxHwViAxAv(Fyf>$^WU!3YKmasu79m;kdVucDN}Lvh ze3;i8bD9K$08=5U7Qx*TEHO=VNiPNJb9$5GvUQnfwt)4N=Ac%rY2Fr4j(6Ti1_m$0I zv`@*1GPXkKlFfsX5yG#GXBdAW!K@}l`~}ux0$2om#!%TN?2Mtdv6iKCVbNGi^lL=) ze6G{en-@7bP{y~gmVY^>c!vid9JZU!g{C+R>#=kYMrp!CQUqZlDS|MO6hW9siXcoR zMGz*EA_x<0ltGv%i>Ig^=&=aRT@W1SB^c~+RgVj7)AmPBmLLvDY{-6{*W)5ViT+4H z`37PErfI*zRLH?kK)XM(>Of$orpJCINNGdIEa32wc#2s^Dw;UghzoxF{PS1TtCim&q_^#`nZ+#$ibC9-+mZfd^6{or3^I zi9rYgp+qpF#DD}@P$IBVVsL^OC=ui+F;GDQln8i~7_>lqN(4Vj3}E;#4Z{(O70e{@ z3|i-U*jvI(@H}TIa?S*%gYSiaSp-&3AWn*#;6W>zx6wH<6~HD@DOrg~mwz6-uJy^v ze>$FxpIUr?A8_5flTvifvWOl;^vE2Rp?RpA@H3%0=R#G)D~B;ccnnI&7rX2Qz(UNI zx`cUxilk{EF_Cp$24k<$Jm>p(1wqwsZUgK~6_gnV4kp zdAUm|b2SR#AU;1(Hls2fm(=$jYw?y{_R7F+>LlMOCuuwHk}UR06d8ML=KFcv9aj9Y zo?pe|3I`+DuYAMfo^XW?l^7;{dj;ur7lJ-p4a?l=i{-G!onBrG`)vB-%lkrzF9)_P z`OAA@b^h|MkQ>Itm-B#TXf-c!;D^7w7+w-zeo3hcMa3vGIOb%dODqdhpfnz6NH{G? z%?Xe+D_CL_&dU8ctHRx3{#=-Qj}6)Hb~0MO+r!BGP9yWXE+g~1WrpH+D-6Z&G!(zv zMc@5SefPUS-~DbeV~LPvV=;Z zjfn3xA{x?&=$vCCEpGHL!vJl zaqe;AB;G>YV=pAM2UN00I0lbP;H;!Sfy(+7Tmd=t!y@P^Jt6+E3eEZtJ0WK&#PNp} z2*`g}xCjXmg>nfbv=z}8Y1$EeCvExNf?;~9)PI&>Z(5TroHm4Q3(bVZ3nlj1uONPj z9>V)btWE^+yGWu=3b7IrQ;DdZAXFpT^Ce&r3pS}?(eGqgdTKlxOYArUb~fY2*O73r zP4opWO^{F+0uplJU?xx_anu;%y{y99dhQMrb;P<*X`4wyD`a7chb9kxb|nvW9;Qhw zZoep-_gv3NF}{ZI5?>p4z6Qq=U&GB@uFz2HEV{~jtV+L|p+3Kx9>sm8yHnygE3SFAfL~7bKSJ_ zP|DKEU1hqigkbHl zneXOt7c^>*^?VPHB3OG&@)aJJ;iE>kb3xx;0lCiweYOM{kzAg;ok*RzpqC|2jh6l8 zeMn4y88F0`yU?7!ynu+38b%f^)r`D~FV7>fyym^gB!BrOrB5Mx7@}AmmZvSDn7JDI zzxGJA{9{+Znp?ZckW8MTONhcOMq<`z@9U?I`8rnDJ6M2C+voy=xNF&Xj?*7^3*twaUzKwleG<_gNw>j zlc2*KZQdzn+Qr{==lRzn%2 z%Ztg=Ul%7Fd!VF2mQBR_FoC!7KKwYw;kMF=c%LFw*)}X>WZ$s!KKvMPI39Yuj|b;{ zWNR`(2-?n;ypPow2_yoT`*1MwK52XdKa#(li+A2psA z@7syA7v$l6i_ZJ@I5(880=LNbipH@kmct%1Giu0}g&g$-=rb>uU`t#s@7w3;*y~Ypq@)9gA@;<%X zHLj|c7tsvnf?nQjyiYGLpgKg}rdU^GQ;C-Wb&;osvC|Usy ztKG0#CHa}g;uWwXvULF9Lyf1Uu&Zxl7!7# zmnLII(fZ|T&>g26H0ohRdXR4V7_nIjDTt*f)ltX zIDr*ismgdXq14IEGcKz_{XLuNgtEryhl#--eDjlj0C@dhC>9wTnIFane;|5ZP8O{n zb4lqGdf`x*nRO+xjT$4rXBzZ97k!URPvop?y?Z=s$|)E9=Lv4&d{Uk`Fw)&}Imva| zExW3faCUs^puSH>cPN9ArM|^N7Q-@FZC{xMa8=X-FqZn|uDcciXww8t&*?1o}dVd{~9CWscB;{CV zC10L$Qt9S6&NmpYk>re)A0h?wrjm>BBQGH{n&D0sKab+xyS60QYb|}GWb89G_$MaBg0e65Au;2@%az(k@*ioTO$|$ z0Y7m3L0Qqk|7m(G8yV7&4PvA*-Xjgt@ycdlN2XZWg#0x<1V#~cw3YC;JG^D_j^na~ zQI)@}61#?oLtc42oUJ(tt*yGU>4!W~2#qg*S`If?=9r1h(@}!Ur@@ z#-Sz1mF~vXe~=(2o030BkZU=YIjDo$$^;DP*@;<75vrJG!RbBrz2CL@*za1S zcn2xn-7D61;Is_tB6zkNl?0DOb=tNY5!%4pfX`YGu_8G|brFPpwDfj~w?VI1K2ZrR zqot{yU6EJx%+RGMW!n$?Im zZ6AWpX)B7DInh?zXlqRfrboB*B*E;lp34+lHbt0UaX<061Y0-C+hLTq4|>~S_L#&N z2NUv&++;g~US5RX8#VgN5?TIo7XHC) z@3yB}L!ExAU5yTeQSL0(1>&y^Cf@C-9AJx;J8M_i9e<_w@eWYOJGvY1=x)4oE-AX#G8Cmu@{5X#0FP{$R^M!(GgKZ&(8oXy*E=x*ffKs>3{5qBD4!Wb;K>mQrX$ zmUUr)_S0F~^K}``w2@b^rC}xoCp0AwVdhLqGy&dno(6yrMeyKEiU(&>I=WcYz%Q6F zLPCy$v_(mi4}DB3&OP79J52U?_u?_B=rj{}*=RbNNquqb?}SOkRky_+lOor)F&(&- zySEn2)#XgeU0u$k_PHJ$nUowq`-Yj6+)D#=IN$riSL`%HR zN_N4OB9qd~UHF~z9j(xnOiCO`98IgrkxA)gSpp@K64Mj=lOF#3nA9iuX4Y8Ba0|i48Q-JAJUEW@gxn!pBnHoqx=$0Cm%-EFuTCODTR>{muJ;^M0xb_{E zdhL!~N_W6s$|pYq#jDHuL5)lnjdc>JAqgQ<5d}CB>J_vsArno~7!O z$mI1U4jW@lX0?#|K~G9F$Hn&Tx?UQYe1D`spI-VO(~B{AqK^S3H4ZR&TnjxWZx7Do z_JRk!A9FM`B9X5xwGAYQ&@zs!hnM;yNt^4IVzg)wGtbbQ? zAw$$5E^H4!z=dta`?-)1Z;cB%wgMM&$gFZ955baer_I)j-;8_4l>eK10jk_;t4QA& zOX>wqTbdtwH&2lr`Nl;_M<`mNNXd11%d$68v`W#07g^$8iULKJKAubbP)RnF;D-+_ zfeCMs3ePflQlwPDs{Q~)q>s~EoPc9RhbSUxw2IoX=<2OS*Mv4F@hA*|*-0d77#{y< zr_EW?dRYcBGD>^`tPWhoo3G>v6LliMa6)8=&imu*Tbj{YH>-dJ3 z*Zp!M8JESAlnF^$M+nt3qgBf&)5UL+PX52Gg=@h&oDgH}2p>?DoQn!Y?*u=Am2SP#R+hQM%1&IbWPq35E29WVGSy;ub zEbzLo>%M!y`|k0p;&O2qu~(Ncj5y%P()xxGEUe8&QFXuRrw6M0U=zb3@>HqY*is}u z3`2(V>d{@qI7B7)$Y<$PLF#8_K>KG^ z+F%*G4J0E5-Xr&^M9DzeiprJ-%h=2;ZawfGo1!GY2FmuRtUXvpj%!6Q54;ytRv#?u zsw^2S%b`e4NrbTF*6Z#A3F@IM62-yT+zfl;ZHF`uyW>6H-LMkxSxO1J;{AT^7vudQ z?ib?yHQZ~9kg8ng-s0G~Kf=9j!{Gk)+>0di&bM=~2tnQ7$vu}O~#5Ph&(p$?KTrOu5+TeDm1$~Z@q07#& zs0*HWU9d%U*%g*`Sq>|@tb|ovR>N*xc85K>>=WPLC%%sY zDowG+F+N$#CM%9XvQtLiU2u*ugz?5PhA`eZ#t_CE#~8wR;}}C2ZyaL?|NMU@5k;3>ABZcuAeuXi@$P#0OktN0mBTI}CMwS=@ zMnW6s!u%k{?0-QJh6$V-If3Mf8LK7`%~liG@d+FPu1(+&aBTvIfNK*t1Y9PtAGlhd zz~w7wm7o-~N>B<~C4_){2_PU3MA_sr2%!0k1BlU2j~xB`n&~oU&58luImiINCg4_J zBf#Zr0`6-9t|Z1`0Vn12KUvZCv$b?G@`kU8vdb4`1Gw=b3$Z`I(-^1ft5IkTfa3Xx ztB=T|Dj#1RB}_hLqS6M#(S{THSPU3$)^kLl$&0DePU3@t&WJ7ZUleFYW*>h@E;+cY z{|i*bQQ>6&M@)Tzv~Qw=a#02h(=%cQj2-BcY+6<#3^pxm3p1ORwS}2Y%i6-sre$qm zX4A5^Ftce{r$Spw2^OYD>_cZ4Gt1>G$a8cIZQYc?s<=CTAnLqEjS z7#*d?7)YiOQ)A#nANnDt#%L-v#=sZ2Y1BqtsWAqAurv+HU>V{4VO;xU*%!?~iSTvZ z(|seRFNq(c3zhm34&G`Hu(*uxzSQ^bf>Pzv$n+Y~!Q1Ejljp_HthQ>zMNb zO|8k4aZ&0E>1{S;q`sI}>I)eLfMF>01zUz?3a5C_2u&h|3A2@|Y$$01D?KuWWrS4e zODrA6P|^lVhcT42!QecUw87G03?*%_bQnWP8*m%Q)gF^J^a0u|0-Kd+5fJ$~m?}UJ zh|a1A?&w~NQxW|zmymZPntZ(+0kvXHM&mqqvf!yN+9RMy+0r0(O$Ewyz;j=A7`*Rt zC=8V0ewIUFpp57rITQxU*fS!B!ax~Y@8nPzC=(R%(i%!n_M_`%LGgKlueVvft2xfUi_+;Vo(nsT zr^I!kh?mcGUV0M})9Lhh$}OC?isy-h#JGvcEpOSKSxf`7ER!G1LPAg;3c|ePq44aX zD!|xOB-$7@U+aF(n2~EOs0#!;y)C*5h5VxwugUyFlzX?hud`CnoAw0rS zjmDVk!DX}9g-Fs>bV=*Ytc>*<_T#{V;nU=mObuewIgrHodF0FWa^tw~c5JX=?)!pT5Jg;C1C-jK%YDK7j?1_< zRW9I5uSRzTP~2lj)uA^af*R|AFvYv$K^Y%2YI>&B^o+NsoWsc>BS2*wP>CX@JcPN6 zQ}R{XU5unDn#0|hTdkui&kgdjyDUhNSo;%mf{Ch#3H5MLLaf}X4?daD^?^5X9qi1V zol3DAwlPgRCutU;H;T}kM7Z${N;3b;jX67M452rM&>KUz@r_9`Z=f+;?Z#$hvc;X> z=|e#3OG)Dhy>W!zIKqu@T#|VMjobKPJ2zSR(ilQ-452rM zaN`@3Wd4^MvovW8p*M!m8$-D9jY%?ZpfQh^R+H;4BNO`f)nqL^5~d-J&`?Aj%YDFZ zBY6ylMdC~N1ILYTR8vm$_QD@v?A7H&H6A{o=Zg6Iw5ORzMcKl^-m$Y93nIseOC4d=5y z$|e2a99F5}a)8N23#CS=AKpv67FG7+gU^&D-BH`lm(Qc*YwuCA@w{%wKGb*wM5`PR zIqI$$5AdzjE%k%Laiwl;+;{|Zs{CdHZ=F_EZ+wH~ zJOAI(pg`?vkOO3s8Bq7A+PqJHjs;+igB#!xryO6rHzM%-Nz z-Y`|L#UI&6u})UCfS8D+_ipu9dHuc$t-o zXoKFW0k{_1k8`+GTSsOZM0_0(Y^Vv`HO6&$Kqh`18}DENR~?IJ)17N`){sU~Q1J-b zS3K&HLJsY8w_ICN%{3JaejpeKMUB=dI>l66upzoP8VdSHS!co``qpLR7r{%f*E zEkdjFwryPon;ZY7TW{OZ>9^sQxPRxZ#fD{0B%vFkVJerm>r&6_TzCvUN0+p2<+=B%JQpg@eVEGSdb?D4m8JvKJM8J7 zhs?s{ht0!z5^2P~v}Ld!E=E3O!JsZ&meGYaP;+4Bm1t9)w4W()-nO?fo7MG;sL`|J=Bn zj-j&Q+{7cr$Ij45_t~lb8{D&hx34T~TLq6C} zy8SnrRS{ZVPg%B4c*0>xj70Rrk z%*JJK?{Eq#lvzWWP&Ed-<>E#=~6Tr%(H;!iM6eoTwPUp!;L3`%P$Kye78qpHG4VC>2xW}{diAg_9)6Jt0 zGh*Twv>|F1^@L-Ue!!FG3XcU|QUk3)ThG4%v?l4hW-?p?0(rgY-}6Nu71O;5$Qx}4 z3+3~fsF)F*1oXrcV-{3&7Xy{32rhN`>Bxd}?)j${rxbp45QgH&7o0N6OUHVV50;If zCkb2#8C>aN5$4QpK)@Z2TnPE(cu!6y{IRy!!lQ7_AG3b`O5Ote5%*@i)k$V;i2@jX zD|j#>#PVWZelV*KCl3J|X`A|yWJslqgN}SSQ4kz*aB(C>mMw5O2&R{i&oMG^%7kG~ zk_YQ>k~j%S!I5y7T|+<$h#68sKng7iDIp*QFSH>g1f(>rAIZSXLSCy6#~7VHPLRx5 zvipVA`h$?` z;mn6YF8UfcoBWAnnC+aiHJ6-A_26vphg=C`N_?gT*R601;aaUTx;)60_)HV}^cBhk zZm1)D&0wM<7lyPv3M~gXj}tH9C^~84ad<}|hJR79v=571>l^T90MJrs3Ion@J`GbB zrw|dpKUdL6lc}jR;GEOcVHh8{GMh>Y?3b{TFsLw&a`7KDsHbJp)r+{B4y%p*{9Xu* z1=-BhY)wqZRy0%lMx`t?iJ_m7*|W~@(L)_l16(Qie1l6mei(w?N~LqYOF{2oM4;_Z z85Ka~?%@K%-1Cv`G$oK5zCXqNVnp3A1wk{^&45jS9K>9RAXz{RyDbc-8z z=#iWilnmvLK@2|b(uBkcCo_o^09&kBKAD3jU0f3d4ogXJ{DczlN-rwH1e!18;7j$m z-(>mI^+)_5^H#EhpMPzR^sSD?HoGSn(GHB0G|j=yPFbJ@a46QpgENZckcG?cMYwV8zCONziJ*BxdmvKku#8Nx}GlI}wCZED{{mKmiG7{#fg-@AC|>KjPP) zx56-g49peKkkXi5k0jZsK88uYE_k)!%wRwVN2K5ox-`iL4%LM^ zbqQjXc)maDI3zj`G(@4Kx}E|^K%3s7c_AoG@?fG+rn2hwq6~G2nN*<66`2o28JV?J zqDjS~nyC?51STZ7ISuM;k zUBg)4g9Fsd;ffrO`Ec|s5Y8eYEurpYsJwXhE|!UW#42QdKYCd)ROe^Y1LSZ4&TWO^ zVWJqpSYoR8KeEY`?FloHbg;=qGA%N^^hdubrMC_a`lDZy!ZkDWU77uk6t0<(HkU`g zAcbpYkPh_7aQHPdTtJ{lzZ!*WW}3nyDsI1KhJ!xAcYHL$dsHmC@KD@R>sl)g_9G?5 zt%5{1#E;_?w|3LY;?UqAbXeqS@sZK6Xyl|Kx0MZxhDO6C6$cI^$JWu%NyR|}`D946 z^`zov1B*kVt)d~5iklCl(81AGlZsmmq?RqC!IN-jLbV*6np7+dq#YxoB0RYm4d)-R z1OwulxH?AL5M#*28f73Svj#?+aR&(Q_y$IJL@5lcFv3aH5wHOrL8 z@8e)sO~OQCYuaTF^81t58))hR!zSAOp{1#Wa_K z$LR${S9fQ%|Ft;FXI$S3T2K@3QFkrSW-6!02gdL5AG;ZR;?We=Y*`NLZwmGKw+A(1 zRDw!6zgbS38Pcb-h%7Y$9om7~o1ymVwe`kCihSw$X_ux=K}@zkB&*43b%48Hn{xRr zEXV!fxh1*uAmP8?r!>UTq_C}mY+*ZC6sQ(~Tfmo?@VDUTC)9eS z%8yMJxAB9D#WB$~(U?iahJhrEinf_l#4LGKG%^}BsfZo&NRSU?#_)Iq$Tz~#dN>F^ z+|fEgaL{^aG+GG0nImW4xV9T|%G4R7X3Uqlz^RO=0&4fehl!DEf@>RZ*1GD9SL<}B4zyZ}w!s*FP30PYUBuMLQV*?v5oNWZ+K5jl*K5jl* zK5jl*K5jl*K5jl*K5jl*K5p1`CgY~@k_9DZYCdjmLAW_w)(32K4_4wXv4@8N8xaO< zWEikfegc-!a=w%dAG{+OK6pnmeDIEB_=@G>+j3wr8NR_~{j89Ub&p0=DLy$g%0mhi=P5ovu=*yY zIi&a$(I~$vP@w1WS)x%EvrwWV67r!CN%#aJ37?=%;S-1?d;*b#Pax7D_zGf*9DI{Kl@hdBDt6!@}_ zctV$m8;xZ#!v`L>P>Gn~qmHjrBq3K(Q~?7?J7|k#n~&naX^_JvdeS9W111&o1JQ+} z#GX`ama3S0Cnps-XVRN*gQA(e6UD+buF0F#D^3nBC%w z`Pya0{Mi!!4?2do`IU&RKJ%WGLob0{D;=x7?tF-feU5fUqBiVsOG<0l7k35i1-$wA z20daZMRJ5^!$rDdqxPuEXJ_=#k-SNVXKAavY)Q@h5Cq_=<=2vOVHD+O?S;FzTN4_n zfk-qs$*xhd6`$3HzwY&8`<<;e-~La*4iGXTU+=K*Oz&@VJ)UCa=e|+>b+DI)>k7?f zfN7oJKtr3P%&gBnz#fO4uc%pJ7c`sJg(gmffF^2{jf19C*bdS4*O%XLeg9riqaqZ< zz4adk)VbWBv#HInftSx49NMt=1NR1TC0Bx|1QDE;Ku)6x20*6-eWV*13UW0lI03vP zI2aB2Zq4w-UkNVt!tnMp$5+n&z9rU+Y(Sol2&Ae3 z2BD+6L3Lnzp+*oPJ#@BNaHysA>TXn{ihIk;54y$uU-!QKJMs#p}!zO zadM(=QNONE)={Xs8TFSVqn0+9?Erj4={y{|PYUh(FZVf@yDFRBVo~Z;p+Y+=1%eaW zS-_+^=mG%)(T1_i%qYd+>205YO#_(Pc{&W#Ajl)q6G%l(FckD57#z?x3TVp(BT76t z;OqWEnxW|%QvqR*gu;0|x=^=gs!(7Rl9~vDa5p7GaC{pUVDF{o0;g1A05gYmMpbQB z?-`vLRb9P!&(vr3)S9U2^a3TszgmL_>A*`ZDnxemse49CE@zDv4Opmi7X23jnLhI3Bw7MIRqbt2@Ajyvt*{v- zrkNwgAw8y}7RUR(qAJZFVYr1hMy05h_!wn#DnVvWR+MqJJHrKsMF&m}TO^dDDp!ZblgO`AxfiQg`eNudrmcv*U)eKP)nMpBUhASLi@Una z02*IKYc&F?(n?hpT1Y6J#hUzPMUL?x$wFXCp?-Y|Iz}~Gr)q5QR>w4i*<4aGGObEx z(xs+ax;d2m)!+>vrW^!K_o644ciDL8O#Td>nSY5flbT97)ghXM0heEODYH94qGWUj zK5{B7W@LOxPpdHV(ypv7Dk7*YrY2yIhg}+!z>yTK;sL8byB{Wu$!O_0n7}#P&?&00 zEN8x9eq~2PhI=kxCEFbUKQVhNjgmK29@jRiNf^=WjS}F0+@v}!-PA5Z=cWmdbW6bQ zO~U4_N0ZhAA`nF+@L}5{FK)G?%oqT6e`LbfCN3~>SCf`vLqG!2u~`Jgc<%!n;a~EDXr364fdiD0*aowuAjJn*p91T*V<-c^TbhnXOwds^ zq4-j%OPt2zrH=?6G5_*ApnJ*XwsG_!`_}8reooKqV=HSIyuMG~dRR43@tV}kIF;1W z?X%SSK6`n6pS4hq8m{)nBLLTqxsRq&qGq|N>p{&>!mcJ2QRpd_ov9eg%I{b(L~V=$ zQf0WMAb$IhMZpU;TvW`Fx6mrPk($$O7;_J%LlNt;DKu>m z%g{7qGz^xYuYFAE-Xm*F2&fBbNl$4t!1!puV`r&!d~CWCkdStyAme--A8P0b9Sd1< zfvf3G*R5%?)PXO)VSz5TL%PqGbCe!G@5m6?)v`x5%FaFGi;_56ndBq*Iw zZ%$*tE&>GkmSOwZhFb<1Qlj@x}FuUg!(r%`A$}ANKf%hB&+IScNS$2o1 z%4(PfUtQ&gV0}P`NQy{nTd*{yg}O9OPAkS0=9J{gB#~H_w~~FBb%Vmyy?$m(uW@=D zRe=$nPXo;uSLExCChCJ*NDIZTfeQ{zUzKWCv#JYq2~d=HG!kUCGk(4dnfkyp>&K># zuE=&${7T4SVgV(X@@=NG0;+s;5(hiw;*+9%9Z{cNlm>f;rk6v$pt+(e5bl!bRghm2 zrIA%hbY&{+$p8rT0!hhR%Ab=IyC+p-Pi=0TS;%TJ%YluB`QI_xI*_ZLYCtI0iG-@0 zN~oQ6E2x!G(7k__u^*3P18CYiXZL&6Wlg*Yc!S5Kg> zUZ&%h9u^ZQW)O-ykb_9V;y#GPO7jF3H#umyOinRvSt(F}sP`!36z%m2!B{7=vz*Kj z%5s+_bcAq}?v9zz5%SN*(NPt2#F>B+9aT9URRub#0tc)1{4V6PD$ozoh3E%KOY}n> zq949?N@I6}HcK+oxoYU?tKyuZ>9peyY;r3{k1|DNyVFxo{AY|I(Rf+H-F%3s!Ur^r zt&bB;svOO(!58{=4SH!T89?+E&X$Sz0BR!Z8bI+Lcs6MlJz}F%r2(YV3}BKCL}37x zz&1+v0i-$I2Cy`6OOk=h<{nIORviXdonFtt$xxvO1FS|QED>yXCfIZEv;?gx=cOc& zTSmMU6b^Bm6xE1D)IgiHE+UslaL?~B)~}_USFU%gOJmyvf)qGfQ3bcH&JA%|V|=%8 z0m9)D=-!2m{5xrvXr8N1<;sE&{qM<8K^3-A)d#7JK$=Q~5I=Fopy?7UIG6xX?@u>jjybHQXN1^q^`zF6CVZa^M)Y6HcwOoNJ1ffRG$olY8--oZ(<^z?=3fIGCba36Pj~C7Nv_T!TBj{)ltfZySgv^O*Wq-8JIcY(aE#fT@W9_+F)?rZ8K`&AHDOfa4OS*F}x(#l~bNz^Vyu z@3RQZEJ#7D-4kw-bH-9)I?N_ML)1#e#Y!EeYBNh(_@ERntU$#4HQUz&ROGMt(n?jz z&>aSvX4>05&G}jNFiV=R8BM$-{(|!k@+ZthgQr;`2w|c{Mz${3D#2=H;)mT=vy^Xz zl$Iz_Dx7j!&-D2Rw_XbIwM=_C=~ zDEn4g$~+B#h)PQv;j=&^QH)U+iaUMLUd`Nk<@5xJIhwQOSDKyq+KDO9l@k*cN;FGo zQ+Kj~N6=Pnn;-9$sX?Gh5sNvkXNOtsPA2ka9b@^OY*i8+u#?^6(V-TNwKWpqILhiM zyD2gBRie=_otJ2o$0}rkVn)R4Qfwez(yLuQ(0y@fCJ4!PIs_^rZj%To!9b6AE)RkM zh*%N`?iX_dP47_%o_3S$PGi`vLW?9kpm*8Wgc!MdGt8RwoC&qP2!}zP$p}C$Sy2|s zZruW`@^WH2h?wlT)}_ZeF@mtzqd|sbk^dH{_Yj2z&7fHl`6p`aI%G3;Z{j1-XAF(@%#AxwPdLr}RP6P4DQu{5r?dn$L2Lb3HFifu=N>RP|U!NW=uUSUywEeg^UNDPOE3pI6WR*BFjo|ONb zd?~<0<`BRr4kLh2b|wIac3@WF#Gvf$tHro6!7MTEy0|Y?lm@Jg@ih;@PpkmHikT~x zrQ;hPviPEh0Fzk$qNAdkbE4{_=88*AoLfu{+>y-9@zU^BI$jlEA=_x`MC(x(<#vSy z6872^wn~`U6}CzUD~?hFua278WHqyfs zF#~*cC5*Q7epu>I3l=NBO8UF@Ptg8vJB;@7Xg>MkQ@Z)UJ`=yK?vps zR;43SD_0_GcL~p+!@?pEM7%~mtV0B28Ujruj7eSwdH9U9L}G?T^e6^?(nbTB%J%bp z&mcQ%+l`E#+ofkwY0t)%Kh1?t>8;Dry8J}~hBSE0XYB;w)d?cq(mxdjqMbCeS1-$^ zvgQ9WLGwK_Y=Z5eS~Z&%(+RnxOXLz{UFL53=5sgliqGAUmga8FSGDaDT3OD9$=lyB zdDqDzgW=FYc`ooJ`(a`0?IZ~T5~V69ZD;t&ye%e{%-eL&SKJJf&$Ntz&)c=0Wr(1LQWJSHgtjSFr$(&dcrfEvWwC<8_n7oOWCU2sp$(v|t@~(zF#)iq8WnD6P3kLP7 zOInBegcG?q%`Q}p=5N;bGRc*U>a#OX;-Q;@K~e|yN^&Tku*X{9s)!<}v0M&0q^JJ{H2)K|FV#+4W#15;o-+Or-*j+o{*8cSYddhE?0v1{tPy&aH*{Jkac zX)nMp=pjR~T!kpYVkMHjXEDe@t3fo0m#c(u0r##~v>!bz@?Mx6 zH9JnOR8%Xz1eqDH zK_OWo#Y$m`eiAgME==U?jUy0l7sp z;z?b?u&9CAQhU@uY$e2T`4G4{UN5RWVoSU2p}3z#n|kEn&N zaS;i@r`k9OM+^(>0WpE0Sa=Az=|4?4Nal4=2DXElRX@2n!tamEHJ~FWoc( zG}!qP!{&VDER){t%qP9@bnsTKPAk&*=*TmmfUT^F<|%T+*CiBz53$)HgPgyXY^ z*Aj?KY(?}2kvUxxg~-%Ir9xzCwRpF1IzBVtG7?Av9G*)|9rRq61M*q7B6t0wZM5tjtNVC&3UJRBd?)YgchKg`6h!b*>G z-3o6xdmI*acpBq7T@}TtrOJg}VvUikTyTS;Y*Mkp^f~0(rk3=kB<=^{FO;B#9Wmrn zU*bu-?1q4}4fDVZ)`N)oGMDNz7yEm)fqu}1`ni4-L^cVWxtkd^SGFQKLXk8^8$`@c zNOf8km7AvdN=@UKrxt%rzFdl$i0ULnW*jeMhzT438yL(9G#XbWBQLchM~;?tT8q`I z%n7S`8JhM!?P>|_;v`qnk`HKMCbSSimQ(A_l;{-~f8s#FSrJe0V3h@kn3LrRwO@BD zT%2FkA;!~eWN+DfD!bdwrhNG8Xt$U_T^qa!mQT0q8Gb3*=oRyM7=F|=ss_k2%~t~6 zO+3j~T1aC$>kDZOzkmr(aD!3-Pu5Qib-N6&n^Zb!S{T=|Zr5i+lLdQ%L#mUGR}@}a z{U%^@iw|sWC=by)Sqp=)f=0ExbfI9@d6>M4K^5+8%$=LoVHn!yJ(upG+;hn+l0d-q zAO>i`h*LgtCeA`?psivJ*yW1?X|Do&RF@otRCJ^K1(lO80H|6p7BeZ*GIT;d251a~ zUK%Bjk=t7*dQ_n@sl`2dN>uT|6?nl3ghH2D{L%(i(xD9ryrfJ;TkyK}&w{Rii-0P1 z1wwin*5|KrwAvVnpv$$?nJd5Yw?QMM?PL*(5eo70HC z40d>LWQL1cK?qk3s9{3tB~_r|(zNCth#Ar-Q+h%%$Fq6`;MFU+x5A#P0F(US+L`L# zw{`&TmC2|lmc~Hs@Q2jgHaGC;R<&5K^lWU^N=lVbCdE^H8VUK$wesw_4$plhovQi& zF%G)jVJcz6@MY*#CW=l6j*~rR01jDbCDa|!KO`PLn{waULi{xUfI5nkHs)UT`-L=4 zDFHpC`V5}q5{{8Lp{^Vin#qTdw(!Sy@TQp(AnQIsRsOVYi@=mwor-|gT>x$QChlI&CQfr=tH4_ zD>M)jXKoM>kgF5Utep?Wf;lX39(+2fi_S>le1Td-9*GfJ!kIx$y@R7m<66m?nE@!z zZBx}D-ZEvP1Z<~)OvJFC7A9ixYj$uk9ggaP&Q+2?RnWLr)S4VJNh(i_^%HJXZc5SDpHCM}yF*J~U=`NUb zZ(VcXhfF^SXg;8wfn(CZhM7go^upwf5T>sIP4EI1^$C6eKnN2;yj7p-mGIY1i+#)d zwXf@9`^KrlAfbEDO)nB7ottz^p7n2e>1|GbB%!&EG-}+>V+}}BiZ%CC&yp0i9Lt-Q zb>GnUiFBej=42dtB@c{mUX-2}W#$z(_ZQi@oPqT%vq2kB@%CjPup%$1c>8)2S@-z5 zZZ28}$Zj6z0)+X6P1xea=qLP(HmAmcG=X4~5cC$c^`^v4@?Xku(;d3aL|x38o^k_} zyQ~rJjWe{;9!~$Zxy6D=3JL`}4JEB||6;$6qR!9ti#AJiIsLSTEmo+F`$=uw52u!K zDjLwqd9Z!}pa{iF#~Ux_ht^gh{AZxz?koTmFQ+s8F?d%yYGAQnq7@!UbuH&a%||K1 zIcGc|Ng08|89M7dp2w|?HgR5YAd@4_g$OyCg!Qz}!w<-xlPT$k<=&1BE$M$_ zcFLOK<(y@UznNwxh62zblz|j4ebkuCfDQtL?{EQ~?lxKd)#d*3p;@2g_L}?W&(6f> zxP>1Jh`#Yxyr5lK0MZQf8mOLe5jNTyce6`9I?9@MwaeIwlswSYf~fZ><4AvH{hSuq zBn(e`1?WrdKz%aaTx;%Nn+w*ch(bRIV+)W16aq|g--EBL{1;tG);(1r>UQ=M7>8_-EOIhj$pgr$x@{T&Yx7GagaAEc^cCwe8H;;solrtOkkcU z@NrT`Ra8OHpn=xXbGd*6T6I+yqp)g<(Yf`Dzmv{^2~zn)d6^G$Vhvk<#b_sOSF8{k zS0C4MRu>Zm5OVXq9dV+__Y*eJX|VE$)9bEX5SCo9IA|LTW(!&3mk-{J5E%aawCjPF z5$$^Pm5O9%0+ygV5THgJNx*7&C;@7e!34eo-Z$)kbADEK@qMN2mybB)A0a3!V)*fdQQYP)mnEE6l6U*ftcmooIVCN73e z;;T%dSY$~=@;ygsvubHX4LXX6G%a_A5nM z@34r&0!MVzmVZs-C>CtRy10ZNrYK6pKC~He6dc=XZ5L7 zgJO;I3i1%|4{lt=+#?g@sKJjTvWGj7Q&g^xHgFvpc)Sz(~`f= zrFqT01z%QiFwnon*SWrBt;@ym?5d$+(`UYRuP>+2fqKc+^CehxJ81L z6HWjT^kGy8#-Rlu7>qWUU@x{g2y`rnU>~G0f{}z^MZ%u8@*!RV0V&2oY_9_v4b8g!UpN2o|CG zB`PC>j2BX9#W_lm4&TLQS8&tKp+Hc{L~D!aGbJsdvI<|5w_fFi4IHuz4p7W$>q$J~ zC55ynsKq#k;(GCWl-h!xi!ffyYd7kK!MJueL$kdS>BnI6&3aM~U2Uf&0UBm_GaEn5 zla2i4ye@yMwRPy4I~rmTH_c8|zregp^-DS#05>{hB6;O3ZK0HisHCP`m4-3Q4aVf@ zbcLW+!EL*5bfa2;tCXdnw2MsInZ=Az#@@Vh#a?>Pb0PCJ!4MJ!;Mnv&^o&6^Y8*n- zDW_JZJDak$jYsJn!=*`1i>+54vHZ^KX4|qywx`#hO(!EOOS{UmHGr+t0E(KvYw2kB}r+V$3?kP zbf2#1!Cld)D>}3*I;JaXT~SPkN`=YVBiZ3ABE`aE+1zjqCRz{{bxG3%kcq{Xy_uf1 z!s$xaeyccY8l@wFBoNkJ%;SsZvlxe~M>)77JB)%T>OoCo+M&Wf37kCGA8V@f@A#wd zD3c;`V#7Ln-~BuBe`)WT=&H1H$v5+&=6Txqtt_8?b``+&e^DO>6zUUO&a1fjMa+hX zMNQH+d-Gam=1`+H7MSjEM6CQN&!6+%v@&n^L^ydfOHYj_{@o7Hc+z=bh;u&LqaLU! z@Ltl|ikfGke(^i`*VCan5j|X4{o_%yhOhj!k`~@Hlwi&dsD_3Bh==;Z%)uc`^~SA| zO>;D3NJ9jTuG&fS+8Ot9?P(gI>R_iD6&}5INZoa<+7_#jtnh#4CvN7p+G^mK`d!80M- z&?L`N@Z%;;9tRYVnyX&)0kdOB2msrG;jV9I_)u^N$M8n0!r0sZL6RZ&Bi&-`$)p#* zN8>dM3KV_94v?ZutUhrOm3)w7;3MWP(z1f}`_5ejN<^Yv_lQ)&?MI<9-6fYiY+3n$ zo1CsUXm5EqGsR3;$nC0b5yTXLMdr!0@92Wbql2 ziO81*uzX({K*T^hhA~W~8Hr$C<%UeMgTYf(FUOzp#-$)4`S$BB*g5?K=p}p=3()Kt z3}ZQ-W|_fxLvAUhUSEo=u6%v} zFD(BqEw|j#Ua7vCBst#KQmik}k@a13B=}mNu8=NJoy4-oC|g*8la)4Bq61jPIwn?R zvo6~zX4MEfFoCKMzEypm)yV}c>za6CH5hat2z4kX>t!ItPC;TgC2Od9Y@j48CWYwc zQ5?cXSYv791$Lc$uUj9nY{wc4e=z!jhKvH4j_7;$ejUful@5btN4GcMS_aH07Rv|1k}S^u4rsImkaj5jVk^Tg-Q<3Y2=Z zqyaDiV+Aewx*wouP+snMZQz0tXEcH&oCuqoSgV41?bC}cyIJRem@C0htxRyWK^+2O zaZ?r>LPs4zZAL`FBs4uP%7f~GUFgj!P3kWGSC|FWl^VfCFTU;}7kUgIsy@Ndh*scy zKBzE=IX91_D4}E!s}r33V62O@67}ZXyL{;gs|RXBEJ+V8D^R;h#V*$$yvJXN`-2#O z_K#xaRF@zsprq5~m0rf?Y^|fk!kfk>sEGzp`hch|@SY4A@QyzduS3b}z8up)KN9uD zFUEj2EP$?sHPIJsAjnfN%!s;!6q{^VHu;k(l>I+5S^UFr*pIUVZGfIc*&K2TNhVlY zx3#hQp4r}}6)~fe*fre(X4X3Q0(NvlxUJbfVx8#=EY_JT^$ZnBI?(7Y_mFW&R+S}^ zK}4*uo>)amPB9RBiCRhrRZ#Sh7uvs3MWLz_Y9$L^7>g`!c#p=|w!;oSfP>i~pl|D~Lanu*t zFlLjTWIu{NE9swuvfMuhC~JQQC;)bV0$>Ly0CqM4fSm!!7O%9ZO&|$Jgr{h|TQc`y z^CN*%3Cc|Viv`q{VQJ1(OJGwpN@O{r4YGR)seN_|D{o})K|#$Rym*4Q@r@bn=l1~f zB?(NQ$i(jmrsP}RmGrLV5Z?R{ER4(&oU!d%& zM!~gyi9{A2=&VXx7TQZG=XCZZ&0@=Xl&LK+c~_>U_#X0L^$G`;F1105nZpPer`@B5 zWI+hhph?ox{ssty}#Y`C|GLn+`96_2Ok62B>fmsEi7S(|zK$_`SiG7+gntx?J z!5%QLnEqI~M7k$O?*}vwq@@9Hx=RPp=`4qGu~nc(v4kVvpyn+3*6FF>l=L&@`4IjI z<39e7Z?3ZBL{f@UE^`lxf> zA#ZJ|j;Qp-;L;aEOJ9sEeKAH~>`?k*=h7GWDNu>5uhfjBn!UnD@%`qN%>gR8cS3sy zsF;zZVuqHADOVho%HR%mgpq2<7x1ESZPVXlMXo-YJNWa#diD|B*`E*7vk&v`{(PjK zfqZD5Cml^v>_zUc61`ghF@8C;)j^4_s|2{7pkxa=yb@DEbi<~^KWT67WlgLhRpzvi zSSr%HziSx-$gq)^F1%~7+>uF_$_Nb7v67@5mtUa#a$}Vkg?Bhv*VBMv(gRLfl8vdt zp)gnlpONxIeGHsbuVs1}5a?x4p?XWa`RYZVB6}O1@q?V5nKKs)iSAZE%7Iqg=^+7* zH%w+N(!Ao~4EP2D83)xy=`x|F2b*|+7od6+^T%?hl9EVw%n7~dDve(JEF}|0GN2bw zFeo&C0PB5~hQ$>@BJ0(L*;*QY67z+efa(^#3*e2!vLV+Be8)8PJ5CpT0?6TUhbd|cLor<`_S#xEQ!BdIvgw4;XO|(AoECl z;c4iPLLuD;+;P|C4hB19s00!aDJ8E{d2h@8Fy+VI0c?O>kgNw%Lzyntfspr?KE*pbgpO?P-4jB`Iy91kDcxc9eh?a}HY5;As03Gh z0aWW$S7W)OK5PXWDBJ6$0^}GUc9=u%5HH*R_$WEDG7(5}^IS<;v^c@?g!xA*qJ$Rl zNY8t4Gp#*YywAB|7nMjFB)gSMb!e4m0x-f$D{+P0ohvx*kE0d-(i`ujxO0iM(BSx< zz#xUVxn(f(#Cu9*)n3jzRVM^6rUdvXaOlCsWOmx2^ddCI;iATPXoLW5%kS9YoQh=UU1~d+SR7O%XTHkg)po6;5 ziu9y{q+{i2MD8DXJIJ9Px)p|eu(!=$_Nej)^})z8!dGB-S4D0~G9n%s-?KG-*23TO zZ;5Rm4hTx}T85#?sCXNW`{{|(gz;!aE+H~T5gDUw8{@6m->=|l`hnQs7owfP2?kr+(Tp! zMP4G(stAgWxJH@LS;VUlAx&zH_;!y;b8%LFx0Em3;yXNzRb70i$IxjcZ&`1|t38dy zNPL&aE+Tf?cKUW1vAaEODY2h<>>Ryq(c2}&?(wuUi2dASi}kivZ`ab!dp!-4fcQR- zy+Q1Ztlqv%?0!$f%R~Ht$L=Ba3y-ZK_Mpd}AhyP1&lCHl$6hA(kjGvj_OQoZBld{L z-XQj<$KE3Ln8(%9Hlme&sQIu*FY#4Cig}(;mZFP5exVJ!Wb+{9K6f_Kd~ojR7N-1d!iP%zOC=5$s+ls{HOHVyF4b+fXdoDBD6q_*2D4+h)5F zUrCX*N?bwYd9P)8ImSL<{A*8R7cqXpW7iOS(PP&Wd&y%r5=*O)dx&^xtBL%^->oXg zZXxztPrKp~Z@{K%!1oj%WrOtjO(DI%(ti@tH&Ob1A>L2%pNBksl;??3b&nAFofo~P z9J`;`%bxaB_*~XD@sr{6W_|v0>GPL}{NA(T3N4ATy&C_))BYGfmjO@w`|x=$eg0PI z^EZh6(X+lr>=lo_LhMf-dpmsIsL%fqKF{g%B@C;>>I@=(_NGeEyop&VJP4 zQ?Jj@Qhc=4>hssgn^GdS3GrV%E4E?5-fl?QQv| zDjeM5$q2_{@etuOc1`itio8T*s3IJoiiaukG?C$o7;Y7Eo951HN%hl$a%pM<-aqB3 zjs-9)Dy@524d@BY0USQdx(}a!A1z>DSn!J?nTNHUWxgnC<0vyO+<(@BHLtH6^->x; z_G>X+xvF4**_9H7q`7wL$& zzrq1q->6a7@tRNuC3CALU9GLaR(74)_(9L%>DprtxPMZ>{W%(MDzB#Is!Bh&)wsY# zH8lqrl|Y^oJpxpV0CEK!^#Ob%!D?O;@(GDtHrC|Iq;Mr9k}=C@F#^Xf^!}@RU@Z_Dv+9 z4LqxW=U%FA4dQziJxBoOxGr$+<@e#x=b)Q}5FDyIhqjI3g~O1rHW_M$;|xC$vp7}c z5FmrPKs$g!ka{_YPFJ?w0hEAx42>0y6;U|u>=1TKFduU zcA-#P#+>SIeG20d`9OGUoKNx-iFyjT4F3A1q)pNNKNwpbZmUw`Qpp;e!Qew=wYv{1B9dQJS}o!8{;P)l405#$3V^*^1L3IX(`?-5#!7W%5`9WVIUxMadkvMlOhD z*8^_&Mip(7_hDr|xX7UuGNQIVEGjuLKDH}yS~(Fc!*WOFH{=EJ$P7H_5#N`%m$N&~ z8P3d@zQpl-vZ3Xu$dh?Q=;jFHUh#FiZ}N;CJ9Z}tzYSRi1c+h1tYle%_?Oy5Wc;`` zj$?`urp4`Wci%tMbTcy=Ag}VAAcU#1z0+g+24rSORYgYFNEjgl`$THs( z5qNqERNwtSE(!tiB9e*ZAqgm5+~?mV59tmdhP9Apn5r2Jm(?U`A`-F5nj%5-!hfYA z?Zj3HMtTCbD(1NV%0{L0x><=N|CNo#!8ZRZ8~s-{f`$J-FB@@6G2xHe6G=GZe zAp|uxypUVNN(SvKA{la<1bPJRMD>HwG|A=F2!^x9XRH7g6cLR%J6^g`HCw(;m9u1c z7At>)APD?)ohpksL9)o+ZBi`-D1{wCcY^5!>wZ<~M3Vbe5yYkVV$(u0B_flWtHl7T z0M5v1v7kHoiky9C^;EuQl}1V%gp{QlGxG~v#G(bk;Y56uyZ>e3^+A4uft&IOq$rnz zQ(;yTnQ@5+;m`qpO;oT-yjZ9TPv+cZsWRh$117nNoJ`vk4f~)CMVTHmATqMasB7|8 zT$Ok$=A+Pp8!Nt!G3w=edIktX3#3}>>Lm4s7PubJrSJrdE`_hhaOA7mvVlug_iZ2{ zPrTaiPGH3fLap*RY)9u4BbytgXB0E64}I)4TpTq73!?O#9G3TiPibLAd)0rBWiXPW z*M7xRTBu2WS6^maBZX6-D2qcjsk%sJ>u*A1i1NKOgi>Pm_(*P`(DM+?!6^ZltnUd+ z--l@U-tXhp8!U$6djJ+c+D3mE?0^=Nn)l z87XH7=0Kwfx&)0}GXANAILpgzsg8C36l-X{m3!h0gNQ{f=O;=-=%=G%KV2IzFoLVh zmEaTB%L!g_@mzI9@zTH1@@%nYVhodsYUWZVt^xv-OJ!o9na^)lNJZ&kbdtStu^v8* zxa>veC!7bYS!3*jvIxK52>^n-PKNQ3$QS>g*DZ_ckKv?|d;BTx*ErFgd%OeUYs3Oy%_=Ge>nH=AQ@_;9X?4&mEM~oK zxboa^)&&zESu+xF3r~5RU0oP508R#+LZu)U_s$7)UEos#QaF+Yslsdb-yRw#p2aXa zn@kBiqg28XL$3O{Ok4;S#Nk9wNO0pJ6f7`429Ii(-YAceLctPB=Q)f8iG7p^%v6a`o}>XJ zNO4azTQs2%G1OLcNRuVhfDxh^?tLj{{7K_p%H`WKzH`Jzlfa(JHZi*V8$AV4hi;91(w1 zy}suoP=QEKR8XM|{D&`;#)U$O^eD8+)XM}D@&|)03kBLvN~#aE_i z4^2q5VL_4yH*x7Id7!GRR4LmKlHAd{ml@0vxmN=UAX&f>)~ium)sbGPla=%sF|!_)f<&lFT2<7*f8@1iQA5p(asdUNnG+;XNH&X^{hnE>hh ziJ&qd&7T;U31I&4bkFyJ?uqoEGv`nY?T0Uv#)U$O^eFW8?vfQ|T`pNAD-HLs#7XnA zWL3p{gKQwn^;VCe5U1GMiQ26 zS=mREgjKf_#%zg%#R*19SoO&w%_S^NTk`zHmKG9Lt|Vav(71$^bqR~*s!Le(011n2 zYb31t@n(yWuoPO5uKuBk)9D#6^r?NW~4Em1X>tyJIS%1Xjw1d=B~UsHUy z5h(g%RC{`KCoC?-5r_o|E2F4*o&&JEgp~|*CXujkiR!0`69Iw1C9Gs{-e1Df;xnvq z0iPPsO~QJNglk>|730*q`=pVv{3*5PqIXki+mvnfT3)?STw7}d!-;Rg{$l*LVuiJ} zDXjZOloD@Hj6_O&tep6&V#C+gW-PvVWGUyhiuGDsn?+_*bW4@_qGEhrg?-MbQqD^i zdvDXVwbj&gkD57Dc~^ThwYIhfqdSieQSu)>TD7*e7HcApuQH`y^K*UqSY~Z)9ac&Y z=wXemt*vLa^asziCENT6q`;KdOZ)nF04Duz{{%#f-ZemyTU%#q>r!j$(rfE7YwNOW z>#Ek)Rj;k9SzA}Twyth%9ec)u)44A(YyBpbzd4n^G!s8kI&!;)!gFPC zj+;F%>YUy&pJ2wc`O#L>qA4BI6dX5YM*H+>+eC+Vv~|oru_Kz+dGeg;yf8*;+Oz{V z{63y{{H!S_ZTS6>2Ob#B@0`-PV7^y=Qb)(+sq>~!>6|`!%EIaMrW`+g@|@YT+h=qf zzumOS9VeVPb@FlBZx_v&A9c*`jOH(xI(7Q|`Nu72-v*VD5<)>+siE_yN28`j(>`^4 z)HyqvKYej!*sp)BlF+SxV;y_V zSol9clD+3Hn9{y6-_2hzXU^<-oztg9Gdkuh=$u@_vI*_8XV2Tny1U9KBk9B`ohMA6 z*S!Jni`C(S1A7p}`+wqC+oO{8lTcR+yZ3TpC}QKFb$G{yirF8U=-$^4*9?9CFSlX# z@iV4QX^-I^8^KdH)RXlPYC<;fl>be}u<_M>2zotW%1JY3EtvJ;093~517>vmD_<|z zD0=L{><^sX`L80zhKF?O><;*MN9W`@Q(*PeCZDu^M*krIyq>xehWKx<>fk9o5dD34 zMKmq4gJ++(G2`9?{_E*bLJ#w%&!6$>>61S-gQ;@*lzAU8S^hg<_#dnB(5X{8J3kb+ z-Y{6^&p3Y8>=~fbe{_ERkAdQSIyU>bPBEqbY{%yRJ8L;~!KeNQD1R7oXZO$Ehq9*G zVe_VR%%3wG;ji1Y^S<9~7|O7ug|piibk3OF@xMS(|68^F-zj-+c$9`~w%EY3;NQXN z{&VFgBk`ZBAWV1vx$=_^umWp8c{2FhF?}k+`+t}#{cqKlbZ*YP>Fo>t!(I9})`1#r zkyL1etq)B*t@R5Je6Drau4lB~dFAI@KefddTAMCf()wthFSg!s!P%|PZF+9&t}DLO z`t-I-TOYpjE3G3wd4B6_Z!Bvawd|{{ukCbE>xAboZr%0Vuebhck4sy(d-EHuhg`F~ zb^M%fwf5U_MeF15ey4TW1DCfR_020{z&UPdp+LT@6sn*Z+!cy);EuRw)MIDpKm>@^~Khjn|{+e zbC;J}f41rmtz!=QQ|rwyz1n)>X@70~>{f5KKDXxYt=FCY&(?-L-f3Mj#B9`vD2m1$ zIp!oA+5w6V3vda4n^9dfH#h5{Dx}mY$c4CBvo+Q8K2u*~sor%t((9`Ele21llYCjq ztgzzCdVNXxXr=0uT&I^gPWM#g_qhM53(5R#z+p{AmPX=P{js``%->$A;rWUzO^W-U zx{%CY{%;|*rKKg+D~W_J>hRVaV*Z!*nHov)A=w-G-lm~BN~cBTKNYPs8?)_p+wZXB z*qwIXCEj!VUVBd%HRi|>V~zyWqsE*xV$4Yq5TDU;ob7wy1nZd6VF$(s+BRNZ@+U)> zO@7scr~l(yw%36jwsu%w`{l>Cwr6&D(?0doD%<_y3s9Mjx2cD`Yd?ARd-mfgciFBT zgYBUM_OyMgpSQX{Y-5AY`=$MHvv+OS4+q)Hdt7dB?)W*|>nGdTCBHwzt{*bT;!`Kv zV_(_D4n2JryX1{s?Ci;B*wBCc)ZW@+H+%NI3$5v*Dr+A7s?~q;Y@4;kEPL?Ou~v8A z);8gwAKN#MYqe2-m~1z1y}*9+$Di3pPWg-deU}vb|uYIr0qFYesz40}B@ruoC(v+`Q?ZDsK=P#aa%lk~WbH|-vi=TMUww`~0Rab9o z_a4#Le!gE)DN^xe({`Lw(Wa%+~zaw;*U?UtKObyr!IQJ ziqn5=+r502{r0wF?bX!}So_#IJErv!>-X&AcI0l)+OuCj&mJlcwV`LeY%d&nfZcuX zc2@ghKYRYO_gVi{2ixnLU2X%OKgzc0y@Q?J@+mugpOn4%rK9ZXYZlq&zyGW4^U?8^ zKmK96@|h>>`;+&ynNxmY^+Q+K!xvv~)!+TA9ev^=`}Q5D+mzjx*ca!YWIs6PlQ#SD zpW3MJPPI2~yU)%&?Nu9c`|)=8y?fiePmZ;rD<85urkranKR?m3L;6_Dgsss4<+5I->7k{?id%S6{{AICS_q#joXKxL) z^Q)HG?Q{3AZR)PG+}^L-l9o&Cd(kPj%?+2?#Pja3Q??sz4TsONd6zG>w%=`G+urw8 zJGmdOBu{?9-gxdTdwJP~_QG$^u#307(3bqE%_dJCYd?9Xm+kYl>+Sdz?KXGbo_6jr z+u3D(Z?s!}Q)lOHyOsUDa~B&^HOM$tY5UclU?cy0q)ohXsdfG?Z9jc%u>JkB-?ff? z=GkTaUbQbR`>tL8mA~094?V;ltpBS;7j18E?suwPJM{#6W{=4>?wE{y{;WlI_{WCX zPSaM|tS9oe-9FpdQTs2j1Lrh<{gyY_YgcY+2TfmT58eJ99PKpOQ71iMTmECAopN^8 z&gwtU?*8tfHoM~md-acIU;pTlw)$5;wkwaj*%m(dp#3tvnf>rDqwJiEZ?`+IKGDwH z=U4XkW0u?9i{G%TUK?%Cyz(_`J^B_~^Xx2J`m-%;_)|Z!Z*RqU*&lq(u0Hg9`_ad< zHf+@Ow%_7Y?N>FI+rle**(sm+ruAzXZcqPsl>PHJ@7P&Sy=!OP`i{M{u-&S!SZjMM zo@1Zy=xgtM;XNC=M~zK6etR1};7mKt zMvb?vrtD}xpYsbFbKi}2Tl+h<>SLNBzBEU!L)j zZT;Sf){t2YUms-$J+R!O?_6xxed}QxeN4Sw|BpSb`B(SZXK!6&Uw`U$`(FQ_+P&X8 z&1z>JZQC5)-?p~HZBd`s?AJACTA$oB`)Yiyec{$;?N{#%x3;Z*WT%|9gH^r$uHAIo zH|&I&2iZr5ue5_!f6_+1b&Eaz$&2ibpIu;$2b^osuHUs4AD?V}T7PJZcfP>xk5V@G znKSL@&;H16JN8XGV0yEqYTE3aYp$|u*#bJ`@O^Caw|m(I^X{~7SMO%4#_ed;PoHAX z?|r`=IP9PH*uD4I%df}wnQ713*QY&UPu{w%t+?<`JMqXzY{rXs*=xV*Z8z__yG`Ej zFI?Mboi`7*-+cC1>wMyi*4THXoi?DsPCag!rH1vh%Rar(-g)O%J7Vuw?MdeDSDx%` zXWx92t-f%rZM$-7`%A~2w(PF4_Qc8~?D~~A*n{`?vX-+(+3b(+U?Yz>%P#)Ki}qM_ zleJB{()JjBi8W8Y-`>f6)PDWO+xDg1X4wm8jCkZ!;1IY@WY?BRd+vTxlO)mo6fn>W?V4M zhJ5l^YyH@tZBcWRy>Uact-bF}+u@c`{Qhh&A9KGwGwE16{!3rC^R|E0e%}8^n{wpW z?bjc_#SS_BZhK;nygf5_9~(938T-M2Z(3pG1pCD6kK2=AZphAd@9(~DhcvFRi?{!wUGaD?n^CooO~3XvTeReI zTeAO!_K#nVwZeJV*(smqpr(86u1|c? zmi=>tJ$(CJ)^yi{_S7f8Zxio2(>_1`Q&u>0Hye5KGRsf-f(_sQ6k9xUQyYIrp{pot!>$1oWyy#w=^SP;Z>SwmJrkl32%isKx^*Q2qR`^S; z-GEFp`_u#MJDVJ0H~iy!_POUCv#&lg#kgmOIxn-+zx7R<_orF5%ekMn&)s;1wQYB_ zP1yPkMHcS z@=O1X%iQ<^?-%o1<@ug|@Rur&$G+w7^qA%+Ib5rs8h%;>XtAN?O>chv`EAB;3w~Si z)9PsiztQ|upgQppelpmY$ZubM2k|?U-zWG@;WwS%@%-BO&Ehwg-y(je^E->*+59fx zcOkz^`F)$;<@~PZcOAbQ_}#|uc7Av9`x(E7`K9>%Z?*Si>gw6%FO#;uc3(kyW!rzk zbI~|n=8v8}YyPyh(F^9x?_>*cmL8|hn=yx- z{L%AIp5Hlr*68*bpBg=<^90^bQ+(c(c_&X!p0}B5UHKbWp3yOR))f8_@1*xhag%4xw|LH+b~X*AZH<&AN@}9)35Opze)6IF zPMmz;;mHFSb}XFI zK4V(6cNtz$0+gtfGnzeT>g;LL3&o`SHgS6AA%YJ53SgQR;4}+h&7NvQ7qZ_lZ1-Jv z-Q$$#;KLkL+ptsD`LWR5p~H5IK5MCiMRcYAg#7FK?;;W}=GRA5SMi?+x8grXmH!V2 CYF7aO literal 0 HcmV?d00001 diff --git a/e2e/benchmarks/tfjs-backend-wasm.wasm b/e2e/benchmarks/tfjs-backend-wasm.wasm new file mode 100644 index 0000000000000000000000000000000000000000..95851ce7e3811ceb4fa87a86e88e8bab572a0655 GIT binary patch literal 154589 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

{$l7_JtSLg2; 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 literal 0 HcmV?d00001 diff --git a/tfjs-backend-wasm/scripts/build-benchmark.sh b/tfjs-backend-wasm/scripts/build-benchmark.sh index a396217cb23..bdbf68cb47a 100755 --- a/tfjs-backend-wasm/scripts/build-benchmark.sh +++ b/tfjs-backend-wasm/scripts/build-benchmark.sh @@ -4,5 +4,5 @@ yarn rollup -c cp dist/tf-backend-wasm.js ../e2e/benchmarks/ # cp wasm-out/tfjs-backend-wasm-threaded.js ../e2e/benchmarks/tfjs-backend-wasm.js -cp wasm-out/tfjs-backend-wasm.wasm ../e2e/benchmarks/ +cp wasm-out/tfjs-backend-wasm-threaded.wasm ../e2e/benchmarks/ # cp wasm-out/tfjs-backend-wasm-simd.wasm ../e2e/benchmarks/ diff --git a/tfjs-backend-wasm/src/backend_wasm.ts b/tfjs-backend-wasm/src/backend_wasm.ts index 795d4e19003..030e7cc9160 100644 --- a/tfjs-backend-wasm/src/backend_wasm.ts +++ b/tfjs-backend-wasm/src/backend_wasm.ts @@ -19,7 +19,7 @@ import './flags_wasm'; import {backend_util, BackendTimingInfo, DataStorage, DataType, engine, KernelBackend, registerBackend, TensorInfo, util} from '@tensorflow/tfjs-core'; import {BackendWasmModule, WasmFactoryConfig} from '../wasm-out/tfjs-backend-wasm'; -import wasmFactory from '../wasm-out/tfjs-backend-wasm.js'; +import wasmFactory from '../wasm-out/tfjs-backend-wasm-threaded.js'; // @ts-ignore import {wasmWorkerContents} from '../wasm-out/tfjs-backend-wasm.worker.js'; diff --git a/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-threaded.d.ts b/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-threaded.d.ts new file mode 100644 index 00000000000..8b889dbcbe6 --- /dev/null +++ b/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-threaded.d.ts @@ -0,0 +1,39 @@ +/** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + +export interface BackendWasmModule extends EmscriptenModule { + mainScriptUrlOrBlob: string|Blob; + onRuntimeInitialized: () => void; + onAbort: (msg: string) => void; + // Using the tfjs namespace to avoid conflict with emscripten's API. + tfjs: { + init(): void, + registerTensor(id: number, size: number, memoryOffset: number): void, + // Disposes the data behind the data bucket. + disposeData(id: number): void, + // Disposes the backend and all of its associated data. + dispose(): void, + } +} + +export interface WasmFactoryConfig { + locateFile?(path: string, prefix: string): string; + instantiateWasm?: Function; +} + +declare var moduleFactory: (settings: WasmFactoryConfig) => BackendWasmModule; +export default moduleFactory; From 83379cc97a6b367a4a4956bed6764e9460db3e52 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Mon, 20 Jul 2020 13:59:05 -0400 Subject: [PATCH 03/70] works --- tfjs-backend-wasm/src/backend_wasm.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tfjs-backend-wasm/src/backend_wasm.ts b/tfjs-backend-wasm/src/backend_wasm.ts index 030e7cc9160..939eccde5f7 100644 --- a/tfjs-backend-wasm/src/backend_wasm.ts +++ b/tfjs-backend-wasm/src/backend_wasm.ts @@ -237,8 +237,10 @@ export async function init(): Promise<{wasm: BackendWasmModule}> { // wasmFactory(factoryConfig); const wasm = wasmFactory(factoryConfig); const voidReturnType: string = null; - // wasm.mainScriptUrlOrBlob = - // new Blob([emscriptenContents], {type: 'text/javascript'}); + wasm.mainScriptUrlOrBlob = new Blob( + [`var _scriptDir = undefined; var WasmBackendModule = ` + + wasmFactory.toString()], + {type: 'text/javascript'}); // Using the tfjs namespace to avoid conflict with emscripten's API. wasm.tfjs = { init: wasm.cwrap('init', null, []), From 6883c1741c5de094c7e266637d363fe04c578ea4 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Tue, 21 Jul 2020 10:16:21 -0400 Subject: [PATCH 04/70] use tp --- tfjs-backend-wasm/src/cc/binary.cc | 4 ++-- tfjs-backend-wasm/src/cc/clamp_impl.cc | 4 ++-- tfjs-backend-wasm/src/cc/conv2d_impl.cc | 4 ++-- tfjs-backend-wasm/src/cc/kernels/AvgPool.cc | 4 ++-- tfjs-backend-wasm/src/cc/kernels/ClipByValue.cc | 4 ++-- tfjs-backend-wasm/src/cc/kernels/MaxPool.cc | 4 ++-- tfjs-backend-wasm/src/cc/kernels/PadV2.cc | 4 ++-- tfjs-backend-wasm/src/cc/kernels/ResizeBilinear.cc | 4 ++-- tfjs-backend-wasm/src/cc/kernels/Sigmoid.cc | 4 ++-- tfjs-backend-wasm/src/cc/kernels/Softmax.cc | 4 ++-- tfjs-backend-wasm/src/cc/prelu_impl.cc | 4 ++-- tfjs-backend-wasm/src/cc/unary.cc | 4 ++-- 12 files changed, 24 insertions(+), 24 deletions(-) diff --git a/tfjs-backend-wasm/src/cc/binary.cc b/tfjs-backend-wasm/src/cc/binary.cc index 7d62a52af1f..db76d24673d 100644 --- a/tfjs-backend-wasm/src/cc/binary.cc +++ b/tfjs-backend-wasm/src/cc/binary.cc @@ -64,7 +64,7 @@ void binary_xnn_f32(const size_t a_id, const size_t* a_shape_ptr, const size_t batch_size = out_info.size; xnn_status status = setup_op(binary_op, a_shape_len, a_shape_ptr, b_shape_len, b_shape_ptr, - a_buf, b_buf, out_buf, nullptr /* thread pool */); + a_buf, b_buf, out_buf, tfjs::backend::threadpool); if (status != xnn_status_success) { util::warn( "XNN status for xnn_setup_*_nd_f32 is not successful. Got " @@ -73,7 +73,7 @@ void binary_xnn_f32(const size_t a_id, const size_t* a_shape_ptr, return; } - xnn_run_operator(binary_op, nullptr /* thread pool */); + xnn_run_operator(binary_op, tfjs::backend::threadpool); } } // namespace wasm diff --git a/tfjs-backend-wasm/src/cc/clamp_impl.cc b/tfjs-backend-wasm/src/cc/clamp_impl.cc index 29df75703ac..939a4922974 100644 --- a/tfjs-backend-wasm/src/cc/clamp_impl.cc +++ b/tfjs-backend-wasm/src/cc/clamp_impl.cc @@ -62,7 +62,7 @@ void xnn_clamp(const size_t x_id, const size_t out_id, const float min, const size_t batch_size = out_info.size; xnn_status status = xnn_setup_clamp_nc_f32(op, batch_size, x_buf, out_buf, - nullptr /* thread pool */); + tfjs::backend::threadpool); if (status != xnn_status_success) { util::warn( "XNN status for xnn_setup_clamp_nc_f32 is not successful. " @@ -71,7 +71,7 @@ void xnn_clamp(const size_t x_id, const size_t out_id, const float min, return; } - xnn_run_operator(op, nullptr /* thread pool */); + xnn_run_operator(op, tfjs::backend::threadpool); } } // namespace wasm diff --git a/tfjs-backend-wasm/src/cc/conv2d_impl.cc b/tfjs-backend-wasm/src/cc/conv2d_impl.cc index 40449aed08c..35f87405277 100644 --- a/tfjs-backend-wasm/src/cc/conv2d_impl.cc +++ b/tfjs-backend-wasm/src/cc/conv2d_impl.cc @@ -259,7 +259,7 @@ void conv2d(const size_t x_id, const size_t batch_size, xnn_status status = xnn_setup_convolution2d_nhwc_f32( conv2d_op, batch_size, input_height, input_width, x_buf, out_buf, - nullptr /* thread pool */); + tfjs::backend::threadpool); if (status != xnn_status_success) { util::warn( "XNN status for xnn_setup_convolution2d_nhwc_f32 is not successful. " @@ -267,7 +267,7 @@ void conv2d(const size_t x_id, const size_t batch_size, status); } - xnn_run_operator(conv2d_op, nullptr /* thread pool */); + xnn_run_operator(conv2d_op, tfjs::backend::threadpool); if (activation == FusableActivation::PRELU) { prelu(out_buf, out_info.size, prelu_weights_id, out_id); diff --git a/tfjs-backend-wasm/src/cc/kernels/AvgPool.cc b/tfjs-backend-wasm/src/cc/kernels/AvgPool.cc index 89b29987171..e9181a016ef 100644 --- a/tfjs-backend-wasm/src/cc/kernels/AvgPool.cc +++ b/tfjs-backend-wasm/src/cc/kernels/AvgPool.cc @@ -93,7 +93,7 @@ void AvgPool(const size_t x_id, const size_t batch_size, xnn_status status = xnn_setup_average_pooling2d_nhwc_f32( avg_pool_op, batch_size, input_height, input_width, x_buf, out_buf, - nullptr /* thread pool */); + tfjs::backend::threadpool); if (status != xnn_status_success) { util::warn( "XNN status for xnn_setup_average_pooling2d_nhwc_f32 is not " @@ -103,7 +103,7 @@ void AvgPool(const size_t x_id, const size_t batch_size, return; } - xnn_run_operator(avg_pool_op, nullptr /* thread pool */); + xnn_run_operator(avg_pool_op, tfjs::backend::threadpool); } } // extern "C" } // namespace wasm diff --git a/tfjs-backend-wasm/src/cc/kernels/ClipByValue.cc b/tfjs-backend-wasm/src/cc/kernels/ClipByValue.cc index 8f3ab20f234..133ce8dd4c2 100644 --- a/tfjs-backend-wasm/src/cc/kernels/ClipByValue.cc +++ b/tfjs-backend-wasm/src/cc/kernels/ClipByValue.cc @@ -79,7 +79,7 @@ void ClipByValue(const size_t x_id, const float min, const float max, const size_t batch_size = x_info.size; xnn_status status = xnn_setup_clamp_nc_f32( - clamp_op, batch_size, x_buf, out_buf, nullptr /* thread pool */); + clamp_op, batch_size, x_buf, out_buf, tfjs::backend::threadpool); if (status != xnn_status_success) { util::warn( "XNN status for xnn_setup_clamp_nc_f32 is not successful. Got " @@ -87,7 +87,7 @@ void ClipByValue(const size_t x_id, const float min, const float max, status); } - xnn_run_operator(clamp_op, nullptr /* thread pool */); + xnn_run_operator(clamp_op, tfjs::backend::threadpool); } } // extern "C" diff --git a/tfjs-backend-wasm/src/cc/kernels/MaxPool.cc b/tfjs-backend-wasm/src/cc/kernels/MaxPool.cc index 4be48c592ba..0d4a21e2ba8 100644 --- a/tfjs-backend-wasm/src/cc/kernels/MaxPool.cc +++ b/tfjs-backend-wasm/src/cc/kernels/MaxPool.cc @@ -95,7 +95,7 @@ void MaxPool(const size_t x_id, const size_t batch_size, xnn_status status = xnn_setup_max_pooling2d_nhwc_f32( max_pool_op, batch_size, input_height, input_width, x_buf, out_buf, - nullptr /* thread pool */); + tfjs::backend::threadpool); if (status != xnn_status_success) { util::warn( "XNN status for xnn_setup_max_pooling2d_nhwc_f32 is not successful. " @@ -104,7 +104,7 @@ void MaxPool(const size_t x_id, const size_t batch_size, return; } - xnn_run_operator(max_pool_op, nullptr /* thread pool */); + xnn_run_operator(max_pool_op, tfjs::backend::threadpool); } } // extern "C" } // namespace wasm diff --git a/tfjs-backend-wasm/src/cc/kernels/PadV2.cc b/tfjs-backend-wasm/src/cc/kernels/PadV2.cc index c7fed57b7de..63f33acfbae 100644 --- a/tfjs-backend-wasm/src/cc/kernels/PadV2.cc +++ b/tfjs-backend-wasm/src/cc/kernels/PadV2.cc @@ -250,7 +250,7 @@ void PadV2(const size_t x_id, const size_t* x_shape_ptr, xnn_status status = xnn_setup_constant_pad_nd_x32( pad_op, x_shape_length, x_shape_ptr, pre_paddings_ptr, post_paddings_ptr, x_info.f32(), out_info.f32_write(), - nullptr /* threadpool */); + tfjs::backend::threadpool); if (status != xnn_status_success) { tfjs::util::warn( "XNN status for xnn_setup_constant_pad_nd_x32 is not " @@ -259,7 +259,7 @@ void PadV2(const size_t x_id, const size_t* x_shape_ptr, return; } - xnn_run_operator(pad_op, nullptr /* threadpool */); + xnn_run_operator(pad_op, tfjs::backend::threadpool); break; } case DType::int32: diff --git a/tfjs-backend-wasm/src/cc/kernels/ResizeBilinear.cc b/tfjs-backend-wasm/src/cc/kernels/ResizeBilinear.cc index b50ed3246e1..e99e0737581 100644 --- a/tfjs-backend-wasm/src/cc/kernels/ResizeBilinear.cc +++ b/tfjs-backend-wasm/src/cc/kernels/ResizeBilinear.cc @@ -90,7 +90,7 @@ void ResizeBilinear(size_t x_id, size_t batch, size_t old_height, xnn_status status = xnn_setup_resize_bilinear2d_nhwc_f32( resize_bilinear_op, batch, old_height, old_width, new_height, new_width, - x_buf, out_buf, nullptr /* thread pool */); + x_buf, out_buf, tfjs::backend::threadpool); if (status != xnn_status_success) { tfjs::util::warn( "XNN status for xnn_setup_resize_bilinear2d_nhwc_f32 is not " @@ -99,7 +99,7 @@ void ResizeBilinear(size_t x_id, size_t batch, size_t old_height, return; } - xnn_run_operator(resize_bilinear_op, nullptr /* thread pool */); + xnn_run_operator(resize_bilinear_op, tfjs::backend::threadpool); } } // extern "C" diff --git a/tfjs-backend-wasm/src/cc/kernels/Sigmoid.cc b/tfjs-backend-wasm/src/cc/kernels/Sigmoid.cc index c9a67b3e529..1c9bbc1e0ad 100644 --- a/tfjs-backend-wasm/src/cc/kernels/Sigmoid.cc +++ b/tfjs-backend-wasm/src/cc/kernels/Sigmoid.cc @@ -83,7 +83,7 @@ void Sigmoid(const size_t x_id, const size_t out_id) { const size_t batch = x_info.size; xnn_status status = xnn_setup_sigmoid_nc_f32( - sigmoid_op, batch, x_buf, out_buf, nullptr /* thread pool */); + sigmoid_op, batch, x_buf, out_buf, tfjs::backend::threadpool); if (status != xnn_status_success) { tfjs::util::warn( "XNN status for xnn_setup_resize_bilinear2d_nhwc_f32 is not " @@ -92,7 +92,7 @@ void Sigmoid(const size_t x_id, const size_t out_id) { return; } - xnn_run_operator(sigmoid_op, nullptr /* thread pool */); + xnn_run_operator(sigmoid_op, tfjs::backend::threadpool); } } // extern "C" diff --git a/tfjs-backend-wasm/src/cc/kernels/Softmax.cc b/tfjs-backend-wasm/src/cc/kernels/Softmax.cc index 84dc027cb52..76acba23a56 100644 --- a/tfjs-backend-wasm/src/cc/kernels/Softmax.cc +++ b/tfjs-backend-wasm/src/cc/kernels/Softmax.cc @@ -82,7 +82,7 @@ void Softmax(const size_t x_id, const size_t out_id, const size_t channels, } xnn_status status = xnn_setup_softmax_nc_f32( - softmax_op, batch, x_buf, out_buf, nullptr /* thread pool */); + softmax_op, batch, x_buf, out_buf, tfjs::backend::threadpool); if (status != xnn_status_success) { tfjs::util::warn( "XNN status for xnn_setup_softmax_nc_f32 is not " @@ -91,7 +91,7 @@ void Softmax(const size_t x_id, const size_t out_id, const size_t channels, return; } - xnn_run_operator(softmax_op, nullptr /* thread pool */); + xnn_run_operator(softmax_op, tfjs::backend::threadpool); } } // extern "C" diff --git a/tfjs-backend-wasm/src/cc/prelu_impl.cc b/tfjs-backend-wasm/src/cc/prelu_impl.cc index 2d67ce3d50c..82af9c19471 100644 --- a/tfjs-backend-wasm/src/cc/prelu_impl.cc +++ b/tfjs-backend-wasm/src/cc/prelu_impl.cc @@ -80,7 +80,7 @@ void prelu(const float* x_buf, const size_t x_size, const size_t weights_id, const size_t batch_size = x_size / weights_info.size; xnn_status status = xnn_setup_prelu_nc_f32( - prelu_op, batch_size, x_buf, out_buf, nullptr /* thread pool */); + prelu_op, batch_size, x_buf, out_buf, tfjs::backend::threadpool); if (status != xnn_status_success) { util::warn( "XNN status for xnn_setup_prelu_nc_f32 is not successful. Got " @@ -88,7 +88,7 @@ void prelu(const float* x_buf, const size_t x_size, const size_t weights_id, status); } - xnn_run_operator(prelu_op, nullptr /* thread pool */); + xnn_run_operator(prelu_op, tfjs::backend::threadpool); } } // namespace wasm diff --git a/tfjs-backend-wasm/src/cc/unary.cc b/tfjs-backend-wasm/src/cc/unary.cc index 40e9c226ace..544f6b01a72 100644 --- a/tfjs-backend-wasm/src/cc/unary.cc +++ b/tfjs-backend-wasm/src/cc/unary.cc @@ -58,7 +58,7 @@ void unary_xnn_f32(const size_t x_id, const size_t out_id, } const size_t batch_size = out_info.size; xnn_status status = - setup_op(unary_op, batch_size, x_buf, out_buf, nullptr /* thread pool */); + setup_op(unary_op, batch_size, x_buf, out_buf, tfjs::backend::threadpool); if (status != xnn_status_success) { util::warn( "XNN status for xnn_setup_*_nd_f32 is not successful. Got " @@ -67,7 +67,7 @@ void unary_xnn_f32(const size_t x_id, const size_t out_id, return; } - xnn_run_operator(unary_op, nullptr /* thread pool */); + xnn_run_operator(unary_op, tfjs::backend::threadpool); } } // namespace wasm From e1c2355295328ebd7710baa079458d608a73d7ad Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Tue, 21 Jul 2020 11:12:00 -0400 Subject: [PATCH 05/70] ctest --- e2e/benchmarks/index.html | 3 +- e2e/benchmarks/tf-backend-wasm.js | 442 +- e2e/benchmarks/tf-core.js | 32359 ++++++++++++++++ .../tfjs-backend-wasm-threaded.wasm | Bin 175629 -> 175880 bytes 4 files changed, 32582 insertions(+), 222 deletions(-) create mode 100644 e2e/benchmarks/tf-core.js diff --git a/e2e/benchmarks/index.html b/e2e/benchmarks/index.html index 98710181447..7dac26eb480 100644 --- a/e2e/benchmarks/index.html +++ b/e2e/benchmarks/index.html @@ -85,7 +85,8 @@

TensorFlow.js Model Benchmark

- + + diff --git a/e2e/benchmarks/tf-backend-wasm.js b/e2e/benchmarks/tf-backend-wasm.js index 818167900a8..7f42210d84e 100644 --- a/e2e/benchmarks/tf-backend-wasm.js +++ b/e2e/benchmarks/tf-backend-wasm.js @@ -1,30 +1,30 @@ -/** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tensorflow/tfjs-core'), require('path'), require('fs'), require('worker_threads'), require('perf_hooks')) : - typeof define === 'function' && define.amd ? define(['exports', '@tensorflow/tfjs-core', 'path', 'fs', 'worker_threads', 'perf_hooks'], factory) : - (global = global || self, factory((global.tf = global.tf || {}, global.tf.wasm = global.tf.wasm || {}), global.tf, global.path, global.fs, global.worker_threads, global.perf_hooks)); -}(this, (function (exports, tfjsCore, path, fs, worker_threads, perf_hooks) { 'use strict'; - - path = path && path.hasOwnProperty('default') ? path['default'] : path; - fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; - worker_threads = worker_threads && worker_threads.hasOwnProperty('default') ? worker_threads['default'] : worker_threads; - perf_hooks = perf_hooks && perf_hooks.hasOwnProperty('default') ? perf_hooks['default'] : perf_hooks; - +/** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tensorflow/tfjs-core'), require('path'), require('fs'), require('worker_threads'), require('perf_hooks')) : + typeof define === 'function' && define.amd ? define(['exports', '@tensorflow/tfjs-core', 'path', 'fs', 'worker_threads', 'perf_hooks'], factory) : + (global = global || self, factory((global.tf = global.tf || {}, global.tf.wasm = global.tf.wasm || {}), global.tf, global.path, global.fs, global.worker_threads, global.perf_hooks)); +}(this, (function (exports, tfjsCore, path, fs, worker_threads, perf_hooks) { 'use strict'; + + path = path && path.hasOwnProperty('default') ? path['default'] : path; + fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; + worker_threads = worker_threads && worker_threads.hasOwnProperty('default') ? worker_threads['default'] : worker_threads; + perf_hooks = perf_hooks && perf_hooks.hasOwnProperty('default') ? perf_hooks['default'] : perf_hooks; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -57,8 +57,8 @@ FusableActivation[FusableActivation["relu"] = 1] = "relu"; FusableActivation[FusableActivation["relu6"] = 2] = "relu6"; FusableActivation[FusableActivation["prelu"] = 3] = "prelu"; - })(FusableActivation || (FusableActivation = {})); - + })(FusableActivation || (FusableActivation = {})); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -133,8 +133,8 @@ backendName: 'wasm', setupFunc: setup, kernelFunc: fusedBatchMatMul - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -170,10 +170,10 @@ return out; } return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; - } - - const absConfig = createUnaryKernelConfig('Abs'); - + } + + const absConfig = createUnaryKernelConfig('Abs'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -239,8 +239,8 @@ } } return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; - } - + } + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -258,8 +258,8 @@ * ============================================================================= */ const supportsFullBroadcast = true; - const addConfig = createBinaryKernelConfig('Add', supportsFullBroadcast); - + const addConfig = createBinaryKernelConfig('Add', supportsFullBroadcast); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -303,8 +303,8 @@ backendName: 'wasm', setupFunc, kernelFunc: addn, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -333,8 +333,8 @@ kernelName: tfjsCore.Identity, backendName: 'wasm', kernelFunc: identity, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -428,8 +428,8 @@ backendName: 'wasm', kernelFunc: transpose, setupFunc: setup$1, - }; - + }; + /** * @license * Copyright 2020 Google Inc. All Rights Reserved. @@ -477,8 +477,8 @@ } } return { transposed: xTransposed, originalAxes, axes, inputWasTransposed }; - } - + } + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -539,8 +539,8 @@ backendName: 'wasm', kernelFunc: argmax, setupFunc: setup$2 - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -609,8 +609,8 @@ backendName: 'wasm', setupFunc: setup$3, kernelFunc: avgPool - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -665,8 +665,8 @@ backendName: 'wasm', setupFunc: setup$4, kernelFunc: batchMatMul - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -695,8 +695,8 @@ kernelName: 'Cast', backendName: 'wasm', kernelFunc: cast, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -737,8 +737,8 @@ backendName: 'wasm', setupFunc: setup$5, kernelFunc: clip - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -785,8 +785,8 @@ kernelName: 'Concat', backendName: 'wasm', kernelFunc: concat, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -862,8 +862,8 @@ backendName: 'wasm', setupFunc: setup$6, kernelFunc: conv2d - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -946,8 +946,8 @@ backendName: 'wasm', setupFunc: setup$7, kernelFunc: conv2DBackpropInput - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -964,8 +964,8 @@ * limitations under the License. * ============================================================================= */ - const cosConfig = createUnaryKernelConfig('Cos'); - + const cosConfig = createUnaryKernelConfig('Cos'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1033,8 +1033,8 @@ backendName: 'wasm', setupFunc: setup$8, kernelFunc: cropAndResize - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1111,8 +1111,8 @@ backendName: 'wasm', setupFunc: setup$9, kernelFunc: depthwiseConv2d - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1130,13 +1130,13 @@ * ============================================================================= */ const supportsFullBroadcast$1 = true; - const divConfig = createBinaryKernelConfig('Div', supportsFullBroadcast$1); - + const divConfig = createBinaryKernelConfig('Div', supportsFullBroadcast$1); + const supportsFullBroadcast$2 = false; - const equalConfig = createBinaryKernelConfig('Equal', supportsFullBroadcast$2, 'bool'); - - const expConfig = createUnaryKernelConfig('Exp'); - + const equalConfig = createBinaryKernelConfig('Equal', supportsFullBroadcast$2, 'bool'); + + const expConfig = createUnaryKernelConfig('Exp'); + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -1164,8 +1164,8 @@ kernelName: tfjsCore.Fill, backendName: 'wasm', kernelFunc: fill, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1183,8 +1183,8 @@ * ============================================================================= */ const supportsFullBroadcast$3 = false; - const floorDivConfig = createBinaryKernelConfig('FloorDiv', supportsFullBroadcast$3); - + const floorDivConfig = createBinaryKernelConfig('FloorDiv', supportsFullBroadcast$3); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1228,8 +1228,8 @@ backendName: 'wasm', setupFunc: setup$a, kernelFunc: fusedBatchNorm - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1330,8 +1330,8 @@ backendName: 'wasm', setupFunc: setup$b, kernelFunc: fusedConv2d - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1433,8 +1433,8 @@ backendName: 'wasm', setupFunc: setup$c, kernelFunc: fusedDepthwiseConv2d - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1488,8 +1488,8 @@ backendName: 'wasm', setupFunc: setup$d, kernelFunc: gatherNd - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1549,17 +1549,17 @@ backendName: 'wasm', setupFunc: setup$e, kernelFunc: gatherV2 - }; - + }; + const supportsFullBroadcast$4 = false; - const greaterConfig = createBinaryKernelConfig('Greater', supportsFullBroadcast$4, 'bool'); - + const greaterConfig = createBinaryKernelConfig('Greater', supportsFullBroadcast$4, 'bool'); + const supportsFullBroadcast$5 = false; - const greaterEqualConfig = createBinaryKernelConfig('GreaterEqual', supportsFullBroadcast$5, 'bool'); - + const greaterEqualConfig = createBinaryKernelConfig('GreaterEqual', supportsFullBroadcast$5, 'bool'); + const supportsFullBroadcast$6 = false; - const lessConfig = createBinaryKernelConfig('Less', supportsFullBroadcast$6, 'bool'); - + const lessConfig = createBinaryKernelConfig('Less', supportsFullBroadcast$6, 'bool'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1577,13 +1577,13 @@ * ============================================================================= */ const supportsFullBroadcast$7 = false; - const lessEqualConfig = createBinaryKernelConfig('LessEqual', supportsFullBroadcast$7, 'bool'); - - const logConfig = createUnaryKernelConfig('Log'); - + const lessEqualConfig = createBinaryKernelConfig('LessEqual', supportsFullBroadcast$7, 'bool'); + + const logConfig = createUnaryKernelConfig('Log'); + const supportsFullBroadcast$8 = false; - const logicalAndConfig = createBinaryKernelConfig('LogicalAnd', supportsFullBroadcast$8, 'bool'); - + const logicalAndConfig = createBinaryKernelConfig('LogicalAnd', supportsFullBroadcast$8, 'bool'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1643,11 +1643,11 @@ backendName: 'wasm', setupFunc: setup$f, kernelFunc: max - }; - + }; + const supportsFullBroadcast$9 = false; - const maximumConfig = createBinaryKernelConfig('Maximum', supportsFullBroadcast$9); - + const maximumConfig = createBinaryKernelConfig('Maximum', supportsFullBroadcast$9); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1718,8 +1718,8 @@ backendName: 'wasm', setupFunc: setup$g, kernelFunc: maxPool - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1783,11 +1783,11 @@ backendName: 'wasm', setupFunc: setup$h, kernelFunc: min - }; - + }; + const supportsFullBroadcast$a = false; - const minimumConfig = createBinaryKernelConfig('Minimum', supportsFullBroadcast$a); - + const minimumConfig = createBinaryKernelConfig('Minimum', supportsFullBroadcast$a); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1805,10 +1805,10 @@ * ============================================================================= */ const supportsFullBroadcast$b = true; - const multiplyConfig = createBinaryKernelConfig(tfjsCore.Multiply, supportsFullBroadcast$b); - - const negateConfig = createUnaryKernelConfig('Negate'); - + const multiplyConfig = createBinaryKernelConfig(tfjsCore.Multiply, supportsFullBroadcast$b); + + const negateConfig = createUnaryKernelConfig('Negate'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1838,8 +1838,8 @@ // Since the result was allocated on the heap, we have to delete it. backend.wasm._free(resOffset); return { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs }; - } - + } + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1886,8 +1886,8 @@ backendName: 'wasm', setupFunc: setup$i, kernelFunc, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -1935,8 +1935,8 @@ backendName: 'wasm', setupFunc: setup$j, kernelFunc: nonMaxSuppressionV4, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1985,11 +1985,11 @@ backendName: 'wasm', setupFunc: setup$k, kernelFunc: kernelFunc$1, - }; - + }; + const supportsFullBroadcast$c = false; - const notEqualConfig = createBinaryKernelConfig('NotEqual', supportsFullBroadcast$c, 'bool'); - + const notEqualConfig = createBinaryKernelConfig('NotEqual', supportsFullBroadcast$c, 'bool'); + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2032,8 +2032,8 @@ backendName: 'wasm', setupFunc: setup$l, kernelFunc: oneHot, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2061,8 +2061,8 @@ kernelName: 'OnesLike', backendName: 'wasm', kernelFunc: onesLike, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2111,11 +2111,11 @@ backendName: 'wasm', kernelFunc: pad, setupFunc: setup$m - }; - + }; + const supportsFullBroadcast$d = false; - const powConfig = createBinaryKernelConfig('Pow', supportsFullBroadcast$d); - + const powConfig = createBinaryKernelConfig('Pow', supportsFullBroadcast$d); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2155,12 +2155,12 @@ backendName: 'wasm', setupFunc: setup$n, kernelFunc: prelu - }; - - const reluConfig = createUnaryKernelConfig('Relu'); - - const relu6Config = createUnaryKernelConfig('Relu6'); - + }; + + const reluConfig = createUnaryKernelConfig('Relu'); + + const relu6Config = createUnaryKernelConfig('Relu6'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2187,8 +2187,8 @@ kernelName: tfjsCore.Reshape, backendName: 'wasm', kernelFunc: reshape, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2250,8 +2250,8 @@ backendName: 'wasm', setupFunc: setup$o, kernelFunc: resizeBilinear - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2300,8 +2300,8 @@ backendName: 'wasm', kernelFunc: reverse, setupFunc: setup$p - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2357,10 +2357,10 @@ backendName: 'wasm', kernelFunc: rotateWithOffset, setupFunc: setup$q - }; - - const rsqrtConfig = createUnaryKernelConfig('Rsqrt'); - + }; + + const rsqrtConfig = createUnaryKernelConfig('Rsqrt'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2414,8 +2414,8 @@ backendName: 'wasm', setupFunc: setup$r, kernelFunc: scatterNd - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2463,8 +2463,8 @@ backendName: 'wasm', kernelFunc: select, setupFunc: setup$s - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2503,10 +2503,10 @@ backendName: 'wasm', setupFunc: setup$t, kernelFunc: sigmoid - }; - - const sinConfig = createUnaryKernelConfig('Sin'); - + }; + + const sinConfig = createUnaryKernelConfig('Sin'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2609,8 +2609,8 @@ kernelName: 'Slice', backendName: 'wasm', kernelFunc: slice, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2655,8 +2655,8 @@ backendName: 'wasm', setupFunc: setup$u, kernelFunc: softmax - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2693,8 +2693,8 @@ kernelName: tfjsCore.SplitV, backendName: 'wasm', kernelFunc: split - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2711,13 +2711,13 @@ * limitations under the License. * ============================================================================= */ - const sqrtConfig = createUnaryKernelConfig('Sqrt'); - - const squareConfig = createUnaryKernelConfig('Square'); - + const sqrtConfig = createUnaryKernelConfig('Sqrt'); + + const squareConfig = createUnaryKernelConfig('Square'); + const supportsFullBroadcast$e = true; - const subConfig = createBinaryKernelConfig('Sub', supportsFullBroadcast$e); - + const subConfig = createBinaryKernelConfig('Sub', supportsFullBroadcast$e); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2782,10 +2782,10 @@ backendName: 'wasm', setupFunc: setup$v, kernelFunc: sum - }; - - const tanhConfig = createUnaryKernelConfig('Tanh'); - + }; + + const tanhConfig = createUnaryKernelConfig('Tanh'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2834,8 +2834,8 @@ backendName: 'wasm', setupFunc: setup$w, kernelFunc: tile - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2879,8 +2879,8 @@ kernelName: tfjsCore.Unpack, backendName: 'wasm', kernelFunc: unpack, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2908,8 +2908,8 @@ kernelName: 'ZerosLike', backendName: 'wasm', kernelFunc: zerosLike, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -3002,8 +3002,8 @@ ]; for (const kernelConfig of kernelConfigs) { tfjsCore.registerKernel(kernelConfig); - } - + } + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -3028,32 +3028,32 @@ ENV.registerFlag('WASM_HAS_SIMD_SUPPORT', async () => WebAssembly.validate(new Uint8Array([ 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 10, 9, 1, 7, 0, 65, 0, 253, 15, 26, 11 - ]))); - - function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; - } - - var tfjsBackendWasmThreaded = createCommonjsModule(function (module, exports) { - var WasmBackendModule = (function() { - var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; - if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; - return ( - function(WasmBackendModule) { - WasmBackendModule = WasmBackendModule || {}; - - function GROWABLE_HEAP_I8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP8}function GROWABLE_HEAP_U8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU8}function GROWABLE_HEAP_I32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP32}function GROWABLE_HEAP_U32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPF64}var Module=typeof WasmBackendModule!=="undefined"?WasmBackendModule:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(Module["ENVIRONMENT"]){throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -s ENVIRONMENT=web or -s ENVIRONMENT=node)")}var ENVIRONMENT_IS_PTHREAD=Module["ENVIRONMENT_IS_PTHREAD"]||false;if(ENVIRONMENT_IS_PTHREAD){buffer=Module["buffer"];DYNAMIC_BASE=Module["DYNAMIC_BASE"];DYNAMICTOP_PTR=Module["DYNAMICTOP_PTR"];}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};var nodeWorkerThreads;try{nodeWorkerThreads=worker_threads;}catch(e){console.error('The "worker_threads" module is not supported in this node.js build - perhaps a newer version is needed?');throw e}Worker=nodeWorkerThreads.Worker;}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}if(ENVIRONMENT_IS_NODE){read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};}else{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}else{throw new Error("environment detection error")}if(ENVIRONMENT_IS_NODE){if(typeof performance==="undefined"){performance=perf_hooks.performance;}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(!Object.getOwnPropertyDescriptor(Module,"arguments"))Object.defineProperty(Module,"arguments",{configurable:true,get:function(){abort("Module.arguments has been replaced with plain arguments_");}});if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(!Object.getOwnPropertyDescriptor(Module,"thisProgram"))Object.defineProperty(Module,"thisProgram",{configurable:true,get:function(){abort("Module.thisProgram has been replaced with plain thisProgram");}});if(Module["quit"])quit_=Module["quit"];if(!Object.getOwnPropertyDescriptor(Module,"quit"))Object.defineProperty(Module,"quit",{configurable:true,get:function(){abort("Module.quit has been replaced with plain quit_");}});assert(typeof Module["memoryInitializerPrefixURL"]==="undefined","Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["pthreadMainPrefixURL"]==="undefined","Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["cdInitializerPrefixURL"]==="undefined","Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["filePackagePrefixURL"]==="undefined","Module.filePackagePrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["read"]==="undefined","Module.read option was removed (modify read_ in JS)");assert(typeof Module["readAsync"]==="undefined","Module.readAsync option was removed (modify readAsync in JS)");assert(typeof Module["readBinary"]==="undefined","Module.readBinary option was removed (modify readBinary in JS)");assert(typeof Module["setWindowTitle"]==="undefined","Module.setWindowTitle option was removed (modify setWindowTitle in JS)");assert(typeof Module["TOTAL_MEMORY"]==="undefined","Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");if(!Object.getOwnPropertyDescriptor(Module,"read"))Object.defineProperty(Module,"read",{configurable:true,get:function(){abort("Module.read has been replaced with plain read_");}});if(!Object.getOwnPropertyDescriptor(Module,"readAsync"))Object.defineProperty(Module,"readAsync",{configurable:true,get:function(){abort("Module.readAsync has been replaced with plain readAsync");}});if(!Object.getOwnPropertyDescriptor(Module,"readBinary"))Object.defineProperty(Module,"readBinary",{configurable:true,get:function(){abort("Module.readBinary has been replaced with plain readBinary");}});if(!Object.getOwnPropertyDescriptor(Module,"setWindowTitle"))Object.defineProperty(Module,"setWindowTitle",{configurable:true,get:function(){abort("Module.setWindowTitle has been replaced with plain setWindowTitle");}});assert(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER||ENVIRONMENT_IS_NODE,"Pthreads do not work in this environment yet (need Web Workers, or an alternative to them)");var stackSave;var stackRestore;var stackAlloc;stackSave=stackRestore=stackAlloc=function(){abort("cannot use the stack before compiled code is ready to run, and has provided stack access");};function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text);}}var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(!Object.getOwnPropertyDescriptor(Module,"wasmBinary"))Object.defineProperty(Module,"wasmBinary",{configurable:true,get:function(){abort("Module.wasmBinary has been replaced with plain wasmBinary");}});var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(!Object.getOwnPropertyDescriptor(Module,"noExitRuntime"))Object.defineProperty(Module,"noExitRuntime",{configurable:true,get:function(){abort("Module.noExitRuntime has been replaced with plain noExitRuntime");}});if(typeof WebAssembly!=="object"){abort("No WebAssembly support found. Build with -s WASM=0 to target JavaScript instead.");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":160,"maximum":160+0,"element":"anyfunc"});var wasmModule;var threadInfoStruct=0;var selfThreadId=0;var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;assert(returnType!=="array",'Return type should not be "array".');if(args){for(var i=0;i=endIdx)){var u0=heap[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heap[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heap[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2;}else{if((u0&248)!=240)warnOnce("Invalid UTF-8 leading byte 0x"+u0.toString(16)+" encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!");u0=(u0&7)<<18|u1<<12|u2<<6|heap[idx++]&63;}if(u0<65536){str+=String.fromCharCode(u0);}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023);}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;if(u>=2097152)warnOnce("Invalid Unicode code point 0x"+u.toString(16)+" encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).");heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){assert(typeof maxBytesToWrite=="number","stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");return stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4;}return len}function writeArrayToMemory(array,buffer){assert(array.length>=0,"writeArrayToMemory array must have a length (should be an array or typed array)");GROWABLE_HEAP_I8().set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var STACK_BASE=5256544,STACKTOP=STACK_BASE,STACK_MAX=13664,DYNAMIC_BASE=5256544,DYNAMICTOP_PTR=12736;assert(STACK_BASE%16===0,"stack must start aligned");assert(DYNAMIC_BASE%16===0,"heap must start aligned");if(ENVIRONMENT_IS_PTHREAD){STACK_MAX=STACKTOP=STACK_MAX=2147483647;}var TOTAL_STACK=5242880;if(Module["TOTAL_STACK"])assert(TOTAL_STACK===Module["TOTAL_STACK"],"the stack size can no longer be determined at runtime");var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||1073741824;if(!Object.getOwnPropertyDescriptor(Module,"INITIAL_MEMORY"))Object.defineProperty(Module,"INITIAL_MEMORY",{configurable:true,get:function(){abort("Module.INITIAL_MEMORY has been replaced with plain INITIAL_INITIAL_MEMORY");}});assert(INITIAL_INITIAL_MEMORY>=TOTAL_STACK,"INITIAL_MEMORY should be larger than TOTAL_STACK, was "+INITIAL_INITIAL_MEMORY+"! (TOTAL_STACK="+TOTAL_STACK+")");assert(typeof Int32Array!=="undefined"&&typeof Float64Array!=="undefined"&&Int32Array.prototype.subarray!==undefined&&Int32Array.prototype.set!==undefined,"JS engine does not provide full typed array support");if(ENVIRONMENT_IS_PTHREAD){wasmMemory=Module["wasmMemory"];buffer=Module["buffer"];}else{if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":1073741824/WASM_PAGE_SIZE,"shared":true});if(!(wasmMemory.buffer instanceof SharedArrayBuffer)){err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");if(ENVIRONMENT_IS_NODE){console.log("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)");}throw Error("bad memory")}}}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;assert(INITIAL_INITIAL_MEMORY%WASM_PAGE_SIZE===0);assert(65536%WASM_PAGE_SIZE===0);updateGlobalBufferAndViews(buffer);if(!ENVIRONMENT_IS_PTHREAD){GROWABLE_HEAP_I32()[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;}function writeStackCookie(){assert((STACK_MAX&3)==0);GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1]=34821223;GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2]=2310721022;GROWABLE_HEAP_I32()[0]=1668509029;}function checkStackCookie(){var cookie1=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1];var cookie2=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2];if(cookie1!=34821223||cookie2!=2310721022){abort("Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x"+cookie2.toString(16)+" "+cookie1.toString(16));}if(GROWABLE_HEAP_I32()[0]!==1668509029)abort("Runtime error: The application has corrupted its heap memory area (address zero)!");}function abortStackOverflow(allocSize){abort("Stack overflow! Attempted to allocate "+allocSize+" bytes on the stack, but stack has only "+(STACK_MAX-stackSave()+allocSize)+" bytes available!");}(function(){var h16=new Int16Array(1);var h8=new Int8Array(h16.buffer);h16[0]=25459;if(h8[0]!==115||h8[1]!==99)throw "Runtime error: expected the system to be little-endian!"})();function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;if(ENVIRONMENT_IS_PTHREAD)runtimeInitialized=true;function preRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){checkStackCookie();assert(!runtimeInitialized);runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__);}function preMain(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;callRuntimeCallbacks(__ATMAIN__);}function postRun(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}assert(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;var runDependencyTracking={};function addRunDependency(id){assert(!ENVIRONMENT_IS_PTHREAD,"addRunDependency cannot be used in a pthread worker");runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(!runDependencyTracking[id]);runDependencyTracking[id]=1;if(runDependencyWatcher===null&&typeof setInterval!=="undefined"){runDependencyWatcher=setInterval(function(){if(ABORT){clearInterval(runDependencyWatcher);runDependencyWatcher=null;return}var shown=false;for(var dep in runDependencyTracking){if(!shown){shown=true;err("still waiting on run dependencies:");}err("dependency: "+dep);}if(shown){err("(end of list)");}},1e4);}}else{err("warning: run dependency added without ID");}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(runDependencyTracking[id]);delete runDependencyTracking[id];}else{err("warning: run dependency removed without ID");}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}if(ENVIRONMENT_IS_PTHREAD)console.error("Pthread aborting at "+(new Error).stack);what+="";out(what);err(what);ABORT=true;var output="abort("+what+") at "+stackTrace();what=output;throw new WebAssembly.RuntimeError(what)}var FS={error:function(){abort("Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -s FORCE_FILESYSTEM=1");},init:function(){FS.error();},createDataFile:function(){FS.error();},createPreloadedFile:function(){FS.error();},createLazyFile:function(){FS.error();},open:function(){FS.error();},mkdev:function(){FS.error();},registerDevice:function(){FS.error();},analyzePath:function(){FS.error();},loadFilesFromDB:function(){FS.error();},ErrnoError:function ErrnoError(){FS.error();}};Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm-threaded.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmModule=module;if(!ENVIRONMENT_IS_PTHREAD){var numWorkersToLoad=PThread.unusedWorkers.length;PThread.unusedWorkers.forEach(function(w){PThread.loadWasmModuleToWorker(w,function(){if(!--numWorkersToLoad)removeRunDependency("wasm-instantiate");});});}}if(!ENVIRONMENT_IS_PTHREAD){addRunDependency("wasm-instantiate");}var trueModule=Module;function receiveInstantiatedSource(output){assert(Module===trueModule,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");trueModule=null;receiveInstance(output["instance"],output["module"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}var ASM_CONSTS={};function initPthreadsJS(){PThread.initRuntime();}if(!ENVIRONMENT_IS_PTHREAD)__ATINIT__.push({func:function(){___wasm_call_ctors();}});function demangle(func){warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling");return func}function demangleAll(text){var regex=/\b_Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}var __pthread_ptr=0;var __pthread_is_main_runtime_thread=0;var __pthread_is_main_browser_thread=0;function __register_pthread_ptr(pthreadPtr,isMainBrowserThread,isMainRuntimeThread){pthreadPtr=pthreadPtr|0;isMainBrowserThread=isMainBrowserThread|0;isMainRuntimeThread=isMainRuntimeThread|0;__pthread_ptr=pthreadPtr;__pthread_is_main_browser_thread=isMainBrowserThread;__pthread_is_main_runtime_thread=isMainRuntimeThread;}Module["__register_pthread_ptr"]=__register_pthread_ptr;var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var __main_thread_futex_wait_address=13648;function _emscripten_futex_wake(addr,count){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0||count<0)return -28;if(count==0)return 0;if(count>=2147483647)count=Infinity;var mainThreadWaitAddress=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);var mainThreadWoken=0;if(mainThreadWaitAddress==addr){var loadedAddr=Atomics.compareExchange(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,mainThreadWaitAddress,0);if(loadedAddr==mainThreadWaitAddress){--count;mainThreadWoken=1;if(count<=0)return 1}}var ret=Atomics.notify(GROWABLE_HEAP_I32(),addr>>2,count);if(ret>=0)return ret+mainThreadWoken;throw "Atomics.notify returned an unexpected value "+ret}Module["_emscripten_futex_wake"]=_emscripten_futex_wake;function __kill_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _kill_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _kill_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];pthread.worker.terminate();PThread.freeThreadData(pthread);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(pthread.worker),1);pthread.worker.pthread=undefined;}function __cancel_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cancel_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cancel_thread!";var pthread=PThread.pthreads[pthread_ptr];pthread.worker.postMessage({"cmd":"cancel"});}function __cleanup_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cleanup_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cleanup_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];if(pthread){var worker=pthread.worker;PThread.returnWorkerToPool(worker);}}var PThread={MAIN_THREAD_ID:1,mainThreadInfo:{schedPolicy:0,schedPrio:0},unusedWorkers:[],runningWorkers:[],initRuntime:function(){__register_pthread_ptr(PThread.mainThreadBlock,!ENVIRONMENT_IS_WORKER,1);_emscripten_register_main_browser_thread_id(PThread.mainThreadBlock);},initMainThreadBlock:function(){assert(!ENVIRONMENT_IS_PTHREAD);var pthreadPoolSize=8;for(var i=0;i>2]=PThread.mainThreadBlock;var headPtr=PThread.mainThreadBlock+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var tlsMemory=13136;for(var i=0;i<128;++i)GROWABLE_HEAP_U32()[tlsMemory/4+i]=0;Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+104>>2,tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+40>>2,PThread.mainThreadBlock);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+44>>2,42);},initWorker:function(){},pthreads:{},exitHandlers:null,setThreadStatus:function(){},runExitHandlers:function(){if(PThread.exitHandlers!==null){while(PThread.exitHandlers.length>0){PThread.exitHandlers.pop()();}PThread.exitHandlers=null;}if(ENVIRONMENT_IS_PTHREAD&&threadInfoStruct)___pthread_tsd_run_dtors();},threadExit:function(exitCode){var tb=_pthread_self();if(tb){err("Pthread 0x"+tb.toString(16)+" exited.");Atomics.store(GROWABLE_HEAP_U32(),tb+4>>2,exitCode);Atomics.store(GROWABLE_HEAP_U32(),tb+0>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+60>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+64>>2,0);PThread.runExitHandlers();_emscripten_futex_wake(tb+0,2147483647);__register_pthread_ptr(0,0,0);threadInfoStruct=0;if(ENVIRONMENT_IS_PTHREAD){postMessage({"cmd":"exit"});}}},threadCancel:function(){PThread.runExitHandlers();Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+4>>2,-1);Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+0>>2,1);_emscripten_futex_wake(threadInfoStruct+0,2147483647);threadInfoStruct=selfThreadId=0;__register_pthread_ptr(0,0,0);postMessage({"cmd":"cancelDone"});},terminateAllThreads:function(){for(var t in PThread.pthreads){var pthread=PThread.pthreads[t];if(pthread&&pthread.worker){PThread.returnWorkerToPool(pthread.worker);}}PThread.pthreads={};for(var i=0;i>2];GROWABLE_HEAP_I32()[pthread.threadInfoStruct+104>>2]=0;_free(tlsMemory);_free(pthread.threadInfoStruct);}pthread.threadInfoStruct=0;if(pthread.allocatedOwnStack&&pthread.stackBase)_free(pthread.stackBase);pthread.stackBase=0;if(pthread.worker)pthread.worker.pthread=null;},returnWorkerToPool:function(worker){delete PThread.pthreads[worker.pthread.thread];PThread.unusedWorkers.push(worker);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);PThread.freeThreadData(worker.pthread);worker.pthread=undefined;},receiveObjectTransfer:function(data){},loadWasmModuleToWorker:function(worker,onFinishedLoading){worker.onmessage=function(e){var d=e["data"];var cmd=d["cmd"];if(worker.pthread)PThread.currentProxiedOperationCallerThread=worker.pthread.threadInfoStruct;if(d["targetThread"]&&d["targetThread"]!=_pthread_self()){var thread=PThread.pthreads[d.targetThread];if(thread){thread.worker.postMessage(e.data,d["transferList"]);}else{console.error('Internal error! Worker sent a message "'+cmd+'" to target pthread '+d["targetThread"]+", but that thread no longer exists!");}PThread.currentProxiedOperationCallerThread=undefined;return}if(cmd==="processQueuedMainThreadWork"){_emscripten_main_thread_process_queued_calls();}else if(cmd==="spawnThread"){__spawn_thread(e.data);}else if(cmd==="cleanupThread"){__cleanup_thread(d["thread"]);}else if(cmd==="killThread"){__kill_thread(d["thread"]);}else if(cmd==="cancelThread"){__cancel_thread(d["thread"]);}else if(cmd==="loaded"){worker.loaded=true;if(onFinishedLoading)onFinishedLoading(worker);if(worker.runPthread){worker.runPthread();delete worker.runPthread;}}else if(cmd==="print"){out("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="printErr"){err("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="alert"){alert("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="exit"){var detached=worker.pthread&&Atomics.load(GROWABLE_HEAP_U32(),worker.pthread.thread+68>>2);if(detached){PThread.returnWorkerToPool(worker);}}else if(cmd==="cancelDone"){PThread.returnWorkerToPool(worker);}else if(cmd==="objectTransfer"){PThread.receiveObjectTransfer(e.data);}else if(e.data.target==="setimmediate"){worker.postMessage(e.data);}else{err("worker sent an unknown command "+cmd);}PThread.currentProxiedOperationCallerThread=undefined;};worker.onerror=function(e){err("pthread sent an error! "+e.filename+":"+e.lineno+": "+e.message);};if(ENVIRONMENT_IS_NODE){worker.on("message",function(data){worker.onmessage({data:data});});worker.on("error",function(data){worker.onerror(data);});worker.on("exit",function(data){console.log("worker exited - TODO: update the worker queue?");});}assert(wasmMemory instanceof WebAssembly.Memory,"WebAssembly memory should have been loaded by now!");assert(wasmModule instanceof WebAssembly.Module,"WebAssembly Module should have been loaded by now!");worker.postMessage({"cmd":"load","urlOrBlob":Module["mainScriptUrlOrBlob"]||_scriptDir,"wasmMemory":wasmMemory,"wasmModule":wasmModule,"DYNAMIC_BASE":DYNAMIC_BASE,"DYNAMICTOP_PTR":DYNAMICTOP_PTR});},allocateUnusedWorker:function(){var pthreadMainJs=locateFile("tfjs-backend-wasm-threaded.worker.js");PThread.unusedWorkers.push(new Worker(pthreadMainJs));},getNewWorker:function(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]);}if(PThread.unusedWorkers.length>0)return PThread.unusedWorkers.pop();else return null},busySpinWait:function(msecs){var t=performance.now()+msecs;while(performance.now()>2]=value;return value}function _atexit(func,arg){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(1,1,func,arg);warnOnce("atexit() called, but EXIT_RUNTIME is not set, so atexits() will not be called. set EXIT_RUNTIME to 1 (see the FAQ)");}function ___handle_stack_overflow(){abort("stack overflow");}function __emscripten_notify_thread_queue(targetThreadId,mainThreadId){if(targetThreadId==mainThreadId){postMessage({"cmd":"processQueuedMainThreadWork"});}else if(ENVIRONMENT_IS_PTHREAD){postMessage({"targetThread":targetThreadId,"cmd":"processThreadQueue"});}else{var pthread=PThread.pthreads[targetThreadId];var worker=pthread&&pthread.worker;if(!worker){err("Cannot send message to thread with ID "+targetThreadId+", unknown thread ID!");return}worker.postMessage({"cmd":"processThreadQueue"});}return 1}function _abort(){abort();}function _emscripten_conditional_set_current_thread_status(expectedStatus,newStatus){}function _emscripten_futex_wait(addr,val,timeout){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0)return -28;if(ENVIRONMENT_IS_WORKER){var ret=Atomics.wait(GROWABLE_HEAP_I32(),addr>>2,val,timeout);if(ret==="timed-out")return -73;if(ret==="not-equal")return -6;if(ret==="ok")return 0;throw "Atomics.wait returned an unexpected value "+ret}else{var loadedVal=Atomics.load(GROWABLE_HEAP_I32(),addr>>2);if(val!=loadedVal)return -6;var tNow=performance.now();var tEnd=tNow+timeout;Atomics.store(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,addr);var ourWaitAddress=addr;while(addr==ourWaitAddress){tNow=performance.now();if(tNow>tEnd){return -73}_emscripten_main_thread_process_queued_calls();addr=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);}return 0}}function _emscripten_is_main_browser_thread(){return __pthread_is_main_browser_thread|0}function _emscripten_is_main_runtime_thread(){return __pthread_is_main_runtime_thread|0}function _emscripten_memcpy_big(dest,src,num){GROWABLE_HEAP_U8().copyWithin(dest,src,src+num);}function _emscripten_proxy_to_main_thread_js(index,sync){var numCallArgs=arguments.length-2;if(numCallArgs>20-1)throw "emscripten_proxy_to_main_thread_js: Too many arguments "+numCallArgs+" to proxied function idx="+index+", maximum supported is "+(20-1)+"!";var stack=stackSave();var args=stackAlloc(numCallArgs*8);var b=args>>3;for(var i=0;i>3]);buf+=8;}else if(ch===105){buf=buf+3&~3;args.push(GROWABLE_HEAP_I32()[buf>>2]);buf+=4;}else abort("unexpected char in asm const signature "+ch);}return args}function _emscripten_receive_on_main_thread_js(index,numCallArgs,args){_emscripten_receive_on_main_thread_js_callArgs.length=numCallArgs;var b=args>>3;for(var i=0;i>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){console.error("emscripten_realloc_buffer: Attempted to grow heap from "+buffer.byteLength+" bytes to "+size+" bytes, but got error: "+e);}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();if(requestedSize<=oldSize){return false}var PAGE_MULTIPLE=65536;var maxHeapSize=1073741824;if(requestedSize>maxHeapSize){err("Cannot enlarge memory, asked to go up to "+requestedSize+" bytes, but the limit is "+maxHeapSize+" bytes!");return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}err("Failed to grow the heap from "+oldSize+" bytes to "+newSize+" bytes, not enough memory!");return false}var JSEvents={keyEvent:0,mouseEvent:0,wheelEvent:0,uiEvent:0,focusEvent:0,deviceOrientationEvent:0,deviceMotionEvent:0,fullscreenChangeEvent:0,pointerlockChangeEvent:0,visibilityChangeEvent:0,touchEvent:0,previousFullscreenElement:null,previousScreenX:null,previousScreenY:null,removeEventListenersRegistered:false,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i);}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[];},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){JSEvents.removeEventListenersRegistered=true;}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence>2]=eventTypeId;GROWABLE_HEAP_I32()[varargs+4>>2]=eventData;GROWABLE_HEAP_I32()[varargs+8>>2]=userData;_emscripten_async_queue_on_thread_(targetThread,637534208,eventHandlerFunc,eventData,varargs);stackRestore(stackTop);},getTargetThreadForEventCallback:function(targetThread){switch(targetThread){case 1:return 0;case 2:return PThread.currentProxiedOperationCallerThread;default:return targetThread}},getNodeNameForTarget:function(target){if(!target)return "";if(target==window)return "#window";if(target==screen)return "#screen";return target&&target.nodeName?target.nodeName:""},fullscreenEnabled:function(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+1;var cString=_malloc(length);stringToUTF8(jsString,cString,length);return cString}function _emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height){var stackTop=stackSave();var varargs=stackAlloc(12);var targetCanvasPtr=0;if(targetCanvas){targetCanvasPtr=stringToNewUTF8(targetCanvas);}GROWABLE_HEAP_I32()[varargs>>2]=targetCanvasPtr;GROWABLE_HEAP_I32()[varargs+4>>2]=width;GROWABLE_HEAP_I32()[varargs+8>>2]=height;_emscripten_async_queue_on_thread_(targetThread,657457152,0,targetCanvasPtr,varargs);stackRestore(stackTop);}function _emscripten_set_offscreencanvas_size_on_target_thread(targetThread,targetCanvas,width,height){targetCanvas=targetCanvas?UTF8ToString(targetCanvas):"";_emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height);}function __maybeCStringToJsString(cString){return cString>2?UTF8ToString(cString):cString}var specialHTMLTargets=[0,typeof document!=="undefined"?document:0,typeof window!=="undefined"?window:0];function __findEventTarget(target){target=__maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!=="undefined"?document.querySelector(target):undefined);return domElement}function __findCanvasEventTarget(target){return __findEventTarget(target)}function _emscripten_set_canvas_element_size_calling_thread(target,width,height){var canvas=__findCanvasEventTarget(target);if(!canvas)return -4;if(canvas.canvasSharedPtr){GROWABLE_HEAP_I32()[canvas.canvasSharedPtr>>2]=width;GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+4>>2]=height;}if(canvas.offscreenCanvas||!canvas.controlTransferredOffscreen){if(canvas.offscreenCanvas)canvas=canvas.offscreenCanvas;var autoResizeViewport=false;if(canvas.GLctxObject&&canvas.GLctxObject.GLctx){var prevViewport=canvas.GLctxObject.GLctx.getParameter(2978);autoResizeViewport=prevViewport[0]===0&&prevViewport[1]===0&&prevViewport[2]===canvas.width&&prevViewport[3]===canvas.height;}canvas.width=width;canvas.height=height;if(autoResizeViewport){canvas.GLctxObject.GLctx.viewport(0,0,width,height);}}else if(canvas.canvasSharedPtr){var targetThread=GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+8>>2];_emscripten_set_offscreencanvas_size_on_target_thread(targetThread,target,width,height);return 1}else{return -4}return 0}function _emscripten_set_canvas_element_size_main_thread(target,width,height){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(2,1,target,width,height);return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}function _emscripten_set_canvas_element_size(target,width,height){var canvas=__findCanvasEventTarget(target);if(canvas){return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}else{return _emscripten_set_canvas_element_size_main_thread(target,width,height)}}function _emscripten_set_current_thread_status(newStatus){}function _emscripten_set_thread_name(threadId,name){}function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=function(index,divisor){ext["vertexAttribDivisorANGLE"](index,divisor);};ctx["drawArraysInstanced"]=function(mode,first,count,primcount){ext["drawArraysInstancedANGLE"](mode,first,count,primcount);};ctx["drawElementsInstanced"]=function(mode,count,type,indices,primcount){ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);};return 1}}function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=function(){return ext["createVertexArrayOES"]()};ctx["deleteVertexArray"]=function(vao){ext["deleteVertexArrayOES"](vao);};ctx["bindVertexArray"]=function(vao){ext["bindVertexArrayOES"](vao);};ctx["isVertexArray"]=function(vao){return ext["isVertexArrayOES"](vao)};return 1}}function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=function(n,bufs){ext["drawBuffersWEBGL"](n,bufs);};return 1}}var GL={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:{},currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],programInfos:{},stringCache:{},unpackAlignment:4,init:function(){var miniTempFloatBuffer=new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);for(var i=0;i>2]:-1;source+=UTF8ToString(GROWABLE_HEAP_I32()[string+i*4>>2],len<0?undefined:len);}return source},createContext:function(canvas,webGLContextAttributes){var ctx=canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=_malloc(8);GROWABLE_HEAP_I32()[handle+4>>2]=_pthread_self();var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context);}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return !(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;_free(GL.contexts[contextHandle].handle);GL.contexts[contextHandle]=null;},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;__webgl_enable_ANGLE_instanced_arrays(GLctx);__webgl_enable_OES_vertex_array_object(GLctx);__webgl_enable_WEBGL_draw_buffers(GLctx);GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query");var automaticallyEnabledExtensions=["OES_texture_float","OES_texture_half_float","OES_standard_derivatives","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBGL_depth_texture","OES_element_index_uint","EXT_texture_filter_anisotropic","EXT_frag_depth","WEBGL_draw_buffers","ANGLE_instanced_arrays","OES_texture_float_linear","OES_texture_half_float_linear","EXT_blend_minmax","EXT_shader_texture_lod","EXT_texture_norm16","WEBGL_compressed_texture_pvrtc","EXT_color_buffer_half_float","WEBGL_color_buffer_float","EXT_sRGB","WEBGL_compressed_texture_etc1","EXT_disjoint_timer_query","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_astc","EXT_color_buffer_float","WEBGL_compressed_texture_s3tc_srgb","EXT_disjoint_timer_query_webgl2","WEBKIT_WEBGL_compressed_texture_pvrtc"];var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext);}});},populateUniformTable:function(program){var p=GL.programs[program];var ptable=GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,35718);for(var i=0;i>2;contextAttributes["alpha"]=!!GROWABLE_HEAP_I32()[a+(0>>2)];contextAttributes["depth"]=!!GROWABLE_HEAP_I32()[a+(4>>2)];contextAttributes["stencil"]=!!GROWABLE_HEAP_I32()[a+(8>>2)];contextAttributes["antialias"]=!!GROWABLE_HEAP_I32()[a+(12>>2)];contextAttributes["premultipliedAlpha"]=!!GROWABLE_HEAP_I32()[a+(16>>2)];contextAttributes["preserveDrawingBuffer"]=!!GROWABLE_HEAP_I32()[a+(20>>2)];var powerPreference=GROWABLE_HEAP_I32()[a+(24>>2)];contextAttributes["powerPreference"]=__emscripten_webgl_power_preferences[powerPreference];contextAttributes["failIfMajorPerformanceCaveat"]=!!GROWABLE_HEAP_I32()[a+(28>>2)];contextAttributes.majorVersion=GROWABLE_HEAP_I32()[a+(32>>2)];contextAttributes.minorVersion=GROWABLE_HEAP_I32()[a+(36>>2)];contextAttributes.enableExtensionsByDefault=GROWABLE_HEAP_I32()[a+(40>>2)];contextAttributes.explicitSwapControl=GROWABLE_HEAP_I32()[a+(44>>2)];contextAttributes.proxyContextToMainThread=GROWABLE_HEAP_I32()[a+(48>>2)];contextAttributes.renderViaOffscreenBackBuffer=GROWABLE_HEAP_I32()[a+(52>>2)];var canvas=__findCanvasEventTarget(target);if(!canvas){return -4}if(contextAttributes.explicitSwapControl){return -1}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}function _emscripten_webgl_create_context(a0,a1){return _emscripten_webgl_do_create_context(a0,a1)}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];assert(buffer);if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){assert(SYSCALLS.varargs!=undefined);SYSCALLS.varargs+=4;var ret=GROWABLE_HEAP_I32()[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){if(low>=0)assert(high===0);else assert(high===-1);return low}};function _fd_close(fd){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(3,1,fd);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(4,1,fd,offset_low,offset_high,whence,newOffset);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");}function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(5,1,fd,iov,iovcnt,pnum);var num=0;for(var i=0;i>2];var len=GROWABLE_HEAP_I32()[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _pthread_cleanup_pop(execute){var routine=PThread.exitHandlers.pop();if(execute)routine();}function _pthread_cleanup_push(routine,arg){if(PThread.exitHandlers===null){PThread.exitHandlers=[];}PThread.exitHandlers.push(function(){dynCall_vi(routine,arg);});}function __spawn_thread(threadParams){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _spawn_thread() can only ever be called from main application thread!";var worker=PThread.getNewWorker();if(worker.pthread!==undefined)throw "Internal error!";if(!threadParams.pthread_ptr)throw "Internal error, no pthread ptr!";PThread.runningWorkers.push(worker);var tlsMemory=_malloc(128*4);for(var i=0;i<128;++i){GROWABLE_HEAP_I32()[tlsMemory+i*4>>2]=0;}var stackHigh=threadParams.stackBase+threadParams.stackSize;var pthread=PThread.pthreads[threadParams.pthread_ptr]={worker:worker,stackBase:threadParams.stackBase,stackSize:threadParams.stackSize,allocatedOwnStack:threadParams.allocatedOwnStack,thread:threadParams.pthread_ptr,threadInfoStruct:threadParams.pthread_ptr};var tis=pthread.threadInfoStruct>>2;Atomics.store(GROWABLE_HEAP_U32(),tis+(0>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(4>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(8>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(68>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(104>>2),tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),tis+(48>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(40>>2),pthread.threadInfoStruct);Atomics.store(GROWABLE_HEAP_U32(),tis+(44>>2),42);Atomics.store(GROWABLE_HEAP_U32(),tis+(108>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(84>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(80>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+8>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+12>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+20>>2),threadParams.schedPolicy);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+24>>2),threadParams.schedPrio);var global_libc=_emscripten_get_global_libc();var global_locale=global_libc+40;Atomics.store(GROWABLE_HEAP_U32(),tis+(176>>2),global_locale);worker.pthread=pthread;var msg={"cmd":"run","start_routine":threadParams.startRoutine,"arg":threadParams.arg,"threadInfoStruct":threadParams.pthread_ptr,"selfThreadId":threadParams.pthread_ptr,"parentThreadId":threadParams.parent_pthread_ptr,"stackBase":threadParams.stackBase,"stackSize":threadParams.stackSize};worker.runPthread=function(){msg.time=performance.now();worker.postMessage(msg,threadParams.transferList);};if(worker.loaded){worker.runPthread();delete worker.runPthread;}}function _pthread_getschedparam(thread,policy,schedparam){if(!policy&&!schedparam)return ERRNO_CODES.EINVAL;if(!thread){err("pthread_getschedparam called with a null thread pointer!");return ERRNO_CODES.ESRCH}var self=GROWABLE_HEAP_I32()[thread+12>>2];if(self!==thread){err("pthread_getschedparam attempted on thread "+thread+", which does not point to a valid thread, or does not exist anymore!");return ERRNO_CODES.ESRCH}var schedPolicy=Atomics.load(GROWABLE_HEAP_U32(),thread+108+20>>2);var schedPrio=Atomics.load(GROWABLE_HEAP_U32(),thread+108+24>>2);if(policy)GROWABLE_HEAP_I32()[policy>>2]=schedPolicy;if(schedparam)GROWABLE_HEAP_I32()[schedparam>>2]=schedPrio;return 0}function _pthread_self(){return __pthread_ptr|0}Module["_pthread_self"]=_pthread_self;function _pthread_create(pthread_ptr,attr,start_routine,arg){if(typeof SharedArrayBuffer==="undefined"){err("Current environment does not support SharedArrayBuffer, pthreads are not available!");return 6}if(!pthread_ptr){err("pthread_create called with a null thread pointer!");return 28}var transferList=[];var error=0;if(ENVIRONMENT_IS_PTHREAD&&(transferList.length===0||error)){return _emscripten_sync_run_in_main_thread_4(687865856,pthread_ptr,attr,start_routine,arg)}var stackSize=0;var stackBase=0;var detached=0;var schedPolicy=0;var schedPrio=0;if(attr){stackSize=GROWABLE_HEAP_I32()[attr>>2];stackSize+=81920;stackBase=GROWABLE_HEAP_I32()[attr+8>>2];detached=GROWABLE_HEAP_I32()[attr+12>>2]!==0;var inheritSched=GROWABLE_HEAP_I32()[attr+16>>2]===0;if(inheritSched){var prevSchedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];var prevSchedPrio=GROWABLE_HEAP_I32()[attr+24>>2];var parentThreadPtr=PThread.currentProxiedOperationCallerThread?PThread.currentProxiedOperationCallerThread:_pthread_self();_pthread_getschedparam(parentThreadPtr,attr+20,attr+24);schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];GROWABLE_HEAP_I32()[attr+20>>2]=prevSchedPolicy;GROWABLE_HEAP_I32()[attr+24>>2]=prevSchedPrio;}else{schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];}}else{stackSize=2097152;}var allocatedOwnStack=stackBase==0;if(allocatedOwnStack){stackBase=_memalign(16,stackSize);}else{stackBase-=stackSize;assert(stackBase>0);}var threadInfoStruct=_malloc(232);for(var i=0;i<232>>2;++i)GROWABLE_HEAP_U32()[(threadInfoStruct>>2)+i]=0;GROWABLE_HEAP_I32()[pthread_ptr>>2]=threadInfoStruct;GROWABLE_HEAP_I32()[threadInfoStruct+12>>2]=threadInfoStruct;var headPtr=threadInfoStruct+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var threadParams={stackBase:stackBase,stackSize:stackSize,allocatedOwnStack:allocatedOwnStack,schedPolicy:schedPolicy,schedPrio:schedPrio,detached:detached,startRoutine:start_routine,pthread_ptr:threadInfoStruct,parent_pthread_ptr:_pthread_self(),arg:arg,transferList:transferList};if(ENVIRONMENT_IS_PTHREAD){threadParams.cmd="spawnThread";postMessage(threadParams,transferList);}else{__spawn_thread(threadParams);}return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}function _sysconf(name){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(6,1,name);switch(name){case 30:return 16384;case 85:var maxHeapSize=1073741824;return maxHeapSize/16384;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:case 79:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return -1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}setErrNo(28);return -1}if(!ENVIRONMENT_IS_PTHREAD)PThread.initMainThreadBlock();else PThread.initWorker();var GLctx;GL.init();var proxiedFunctionTable=[null,_atexit,_emscripten_set_canvas_element_size_main_thread,_fd_close,_fd_seek,_fd_write,_sysconf];var asmLibraryArg={"__assert_fail":___assert_fail,"__call_main":___call_main,"__handle_stack_overflow":___handle_stack_overflow,"_emscripten_notify_thread_queue":__emscripten_notify_thread_queue,"abort":_abort,"emscripten_conditional_set_current_thread_status":_emscripten_conditional_set_current_thread_status,"emscripten_futex_wait":_emscripten_futex_wait,"emscripten_futex_wake":_emscripten_futex_wake,"emscripten_get_now":_emscripten_get_now,"emscripten_is_main_browser_thread":_emscripten_is_main_browser_thread,"emscripten_is_main_runtime_thread":_emscripten_is_main_runtime_thread,"emscripten_memcpy_big":_emscripten_memcpy_big,"emscripten_receive_on_main_thread_js":_emscripten_receive_on_main_thread_js,"emscripten_resize_heap":_emscripten_resize_heap,"emscripten_set_canvas_element_size":_emscripten_set_canvas_element_size,"emscripten_set_current_thread_status":_emscripten_set_current_thread_status,"emscripten_set_thread_name":_emscripten_set_thread_name,"emscripten_webgl_create_context":_emscripten_webgl_create_context,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"initPthreadsJS":initPthreadsJS,"memory":wasmMemory||Module["wasmMemory"],"pthread_cleanup_pop":_pthread_cleanup_pop,"pthread_cleanup_push":_pthread_cleanup_push,"pthread_create":_pthread_create,"pthread_self":_pthread_self,"roundf":_roundf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__wasm_call_ctors"].apply(null,arguments)};var _init=Module["_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["init"].apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["register_tensor"].apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose_data"].apply(null,arguments)};var _dispose=Module["_dispose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose"].apply(null,arguments)};var _Abs=Module["_Abs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Abs"].apply(null,arguments)};var _Add=Module["_Add"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Add"].apply(null,arguments)};var _AddN=Module["_AddN"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AddN"].apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ArgMax"].apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AvgPool"].apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["BatchMatMul"].apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ClipByValue"].apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2D"].apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2DBackpropInput"].apply(null,arguments)};var _Cos=Module["_Cos"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Cos"].apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["CropAndResize"].apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["DepthwiseConv2dNative"].apply(null,arguments)};var _Div=Module["_Div"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Div"].apply(null,arguments)};var _Equal=Module["_Equal"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Equal"].apply(null,arguments)};var _Exp=Module["_Exp"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Exp"].apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FloorDiv"].apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedBatchNorm"].apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedConv2D"].apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedDepthwiseConv2D"].apply(null,arguments)};var _Gather=Module["_Gather"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Gather"].apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GatherNd"].apply(null,arguments)};var _Greater=Module["_Greater"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Greater"].apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GreaterEqual"].apply(null,arguments)};var _Less=Module["_Less"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Less"].apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LessEqual"].apply(null,arguments)};var _Log=Module["_Log"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Log"].apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LogicalAnd"].apply(null,arguments)};var _Max=Module["_Max"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Max"].apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["MaxPool"].apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Maximum"].apply(null,arguments)};var _Min=Module["_Min"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Min"].apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Minimum"].apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Multiply"].apply(null,arguments)};var _Negate=Module["_Negate"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Negate"].apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV3"].apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV4"].apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV5"].apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NotEqual"].apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["OneHot"].apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["PadV2"].apply(null,arguments)};var _Pow=Module["_Pow"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Pow"].apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Prelu"].apply(null,arguments)};var _Relu=Module["_Relu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu"].apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu6"].apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ResizeBilinear"].apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Reverse"].apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["RotateWithOffset"].apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Rsqrt"].apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ScatterNd"].apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["SelectV2"].apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sigmoid"].apply(null,arguments)};var _Sin=Module["_Sin"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sin"].apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Softmax"].apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sqrt"].apply(null,arguments)};var _Square=Module["_Square"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Square"].apply(null,arguments)};var _Sub=Module["_Sub"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sub"].apply(null,arguments)};var _Sum=Module["_Sum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sum"].apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tanh"].apply(null,arguments)};var _Tile=Module["_Tile"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tile"].apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Transpose"].apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["_FusedMatMul"].apply(null,arguments)};var _malloc=Module["_malloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["malloc"].apply(null,arguments)};var _free=Module["_free"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["free"].apply(null,arguments)};var ___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__em_js__initPthreadsJS"].apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__errno_location"].apply(null,arguments)};var _emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_get_global_libc"].apply(null,arguments)};var _memalign=Module["_memalign"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["memalign"].apply(null,arguments)};var ___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__pthread_tsd_run_dtors"].apply(null,arguments)};var _emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_current_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_register_main_browser_thread_id"].apply(null,arguments)};var _emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_browser_thread_id"].apply(null,arguments)};var _emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_0"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_1"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_2"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_xprintf_varargs"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_3"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_4"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_5"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_6"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_7"].apply(null,arguments)};var _emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_run_in_main_runtime_thread_js"].apply(null,arguments)};var _emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_queue_on_thread_"].apply(null,arguments)};var _emscripten_tls_init=Module["_emscripten_tls_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_tls_init"].apply(null,arguments)};var ___set_stack_limit=Module["___set_stack_limit"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__set_stack_limit"].apply(null,arguments)};var stackSave=Module["stackSave"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackSave"].apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackAlloc"].apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackRestore"].apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_vi"].apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_v"].apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_ii"].apply(null,arguments)};Module["asm"]=asm;if(!Object.getOwnPropertyDescriptor(Module,"intArrayFromString"))Module["intArrayFromString"]=function(){abort("'intArrayFromString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"intArrayToString"))Module["intArrayToString"]=function(){abort("'intArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ccall"))Module["ccall"]=function(){abort("'ccall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["cwrap"]=cwrap;if(!Object.getOwnPropertyDescriptor(Module,"setValue"))Module["setValue"]=function(){abort("'setValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getValue"))Module["getValue"]=function(){abort("'getValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocate"))Module["allocate"]=function(){abort("'allocate' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getMemory"))Module["getMemory"]=function(){abort("'getMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ArrayToString"))Module["UTF8ArrayToString"]=function(){abort("'UTF8ArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ToString"))Module["UTF8ToString"]=function(){abort("'UTF8ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8Array"))Module["stringToUTF8Array"]=function(){abort("'stringToUTF8Array' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8"))Module["stringToUTF8"]=function(){abort("'stringToUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF8"))Module["lengthBytesUTF8"]=function(){abort("'lengthBytesUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreRun"))Module["addOnPreRun"]=function(){abort("'addOnPreRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnInit"))Module["addOnInit"]=function(){abort("'addOnInit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreMain"))Module["addOnPreMain"]=function(){abort("'addOnPreMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnExit"))Module["addOnExit"]=function(){abort("'addOnExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPostRun"))Module["addOnPostRun"]=function(){abort("'addOnPostRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeStringToMemory"))Module["writeStringToMemory"]=function(){abort("'writeStringToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeArrayToMemory"))Module["writeArrayToMemory"]=function(){abort("'writeArrayToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeAsciiToMemory"))Module["writeAsciiToMemory"]=function(){abort("'writeAsciiToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addRunDependency"))Module["addRunDependency"]=function(){abort("'addRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"removeRunDependency"))Module["removeRunDependency"]=function(){abort("'removeRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createFolder"))Module["FS_createFolder"]=function(){abort("'FS_createFolder' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPath"))Module["FS_createPath"]=function(){abort("'FS_createPath' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDataFile"))Module["FS_createDataFile"]=function(){abort("'FS_createDataFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPreloadedFile"))Module["FS_createPreloadedFile"]=function(){abort("'FS_createPreloadedFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLazyFile"))Module["FS_createLazyFile"]=function(){abort("'FS_createLazyFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLink"))Module["FS_createLink"]=function(){abort("'FS_createLink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDevice"))Module["FS_createDevice"]=function(){abort("'FS_createDevice' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_unlink"))Module["FS_unlink"]=function(){abort("'FS_unlink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"dynamicAlloc"))Module["dynamicAlloc"]=function(){abort("'dynamicAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadDynamicLibrary"))Module["loadDynamicLibrary"]=function(){abort("'loadDynamicLibrary' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadWebAssemblyModule"))Module["loadWebAssemblyModule"]=function(){abort("'loadWebAssemblyModule' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getLEB"))Module["getLEB"]=function(){abort("'getLEB' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFunctionTables"))Module["getFunctionTables"]=function(){abort("'getFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"alignFunctionTables"))Module["alignFunctionTables"]=function(){abort("'alignFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"registerFunctions"))Module["registerFunctions"]=function(){abort("'registerFunctions' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addFunction"))Module["addFunction"]=function(){abort("'addFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"removeFunction"))Module["removeFunction"]=function(){abort("'removeFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFuncWrapper"))Module["getFuncWrapper"]=function(){abort("'getFuncWrapper' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"prettyPrint"))Module["prettyPrint"]=function(){abort("'prettyPrint' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"makeBigInt"))Module["makeBigInt"]=function(){abort("'makeBigInt' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"dynCall"))Module["dynCall"]=function(){abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getCompilerSetting"))Module["getCompilerSetting"]=function(){abort("'getCompilerSetting' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"print"))Module["print"]=function(){abort("'print' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"printErr"))Module["printErr"]=function(){abort("'printErr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getTempRet0"))Module["getTempRet0"]=function(){abort("'getTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setTempRet0"))Module["setTempRet0"]=function(){abort("'setTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"callMain"))Module["callMain"]=function(){abort("'callMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"abort"))Module["abort"]=function(){abort("'abort' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToNewUTF8"))Module["stringToNewUTF8"]=function(){abort("'stringToNewUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscripten_realloc_buffer"))Module["emscripten_realloc_buffer"]=function(){abort("'emscripten_realloc_buffer' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ENV"))Module["ENV"]=function(){abort("'ENV' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setjmpId"))Module["setjmpId"]=function(){abort("'setjmpId' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_CODES"))Module["ERRNO_CODES"]=function(){abort("'ERRNO_CODES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_MESSAGES"))Module["ERRNO_MESSAGES"]=function(){abort("'ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setErrNo"))Module["setErrNo"]=function(){abort("'setErrNo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"DNS"))Module["DNS"]=function(){abort("'DNS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GAI_ERRNO_MESSAGES"))Module["GAI_ERRNO_MESSAGES"]=function(){abort("'GAI_ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Protocols"))Module["Protocols"]=function(){abort("'Protocols' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Sockets"))Module["Sockets"]=function(){abort("'Sockets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UNWIND_CACHE"))Module["UNWIND_CACHE"]=function(){abort("'UNWIND_CACHE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readAsmConstArgs"))Module["readAsmConstArgs"]=function(){abort("'readAsmConstArgs' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_q"))Module["jstoi_q"]=function(){abort("'jstoi_q' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_s"))Module["jstoi_s"]=function(){abort("'jstoi_s' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"reallyNegative"))Module["reallyNegative"]=function(){abort("'reallyNegative' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"formatString"))Module["formatString"]=function(){abort("'formatString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH"))Module["PATH"]=function(){abort("'PATH' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH_FS"))Module["PATH_FS"]=function(){abort("'PATH_FS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SYSCALLS"))Module["SYSCALLS"]=function(){abort("'SYSCALLS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMmap2"))Module["syscallMmap2"]=function(){abort("'syscallMmap2' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMunmap"))Module["syscallMunmap"]=function(){abort("'syscallMunmap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"flush_NO_FILESYSTEM"))Module["flush_NO_FILESYSTEM"]=function(){abort("'flush_NO_FILESYSTEM' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"JSEvents"))Module["JSEvents"]=function(){abort("'JSEvents' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"specialHTMLTargets"))Module["specialHTMLTargets"]=function(){abort("'specialHTMLTargets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangle"))Module["demangle"]=function(){abort("'demangle' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangleAll"))Module["demangleAll"]=function(){abort("'demangleAll' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jsStackTrace"))Module["jsStackTrace"]=function(){abort("'jsStackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getEnvStrings"))Module["getEnvStrings"]=function(){abort("'getEnvStrings' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64"))Module["writeI53ToI64"]=function(){abort("'writeI53ToI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Clamped"))Module["writeI53ToI64Clamped"]=function(){abort("'writeI53ToI64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Signaling"))Module["writeI53ToI64Signaling"]=function(){abort("'writeI53ToI64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Clamped"))Module["writeI53ToU64Clamped"]=function(){abort("'writeI53ToU64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Signaling"))Module["writeI53ToU64Signaling"]=function(){abort("'writeI53ToU64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromI64"))Module["readI53FromI64"]=function(){abort("'readI53FromI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromU64"))Module["readI53FromU64"]=function(){abort("'readI53FromU64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertI32PairToI53"))Module["convertI32PairToI53"]=function(){abort("'convertI32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertU32PairToI53"))Module["convertU32PairToI53"]=function(){abort("'convertU32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Browser"))Module["Browser"]=function(){abort("'Browser' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GL"))Module["GL"]=function(){abort("'GL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGet"))Module["emscriptenWebGLGet"]=function(){abort("'emscriptenWebGLGet' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetTexPixelData"))Module["emscriptenWebGLGetTexPixelData"]=function(){abort("'emscriptenWebGLGetTexPixelData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetUniform"))Module["emscriptenWebGLGetUniform"]=function(){abort("'emscriptenWebGLGetUniform' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetVertexAttrib"))Module["emscriptenWebGLGetVertexAttrib"]=function(){abort("'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AL"))Module["AL"]=function(){abort("'AL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_unicode"))Module["SDL_unicode"]=function(){abort("'SDL_unicode' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_ttfContext"))Module["SDL_ttfContext"]=function(){abort("'SDL_ttfContext' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_audio"))Module["SDL_audio"]=function(){abort("'SDL_audio' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL"))Module["SDL"]=function(){abort("'SDL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_gfx"))Module["SDL_gfx"]=function(){abort("'SDL_gfx' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLUT"))Module["GLUT"]=function(){abort("'GLUT' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"EGL"))Module["EGL"]=function(){abort("'EGL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW_Window"))Module["GLFW_Window"]=function(){abort("'GLFW_Window' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW"))Module["GLFW"]=function(){abort("'GLFW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLEW"))Module["GLEW"]=function(){abort("'GLEW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"IDBStore"))Module["IDBStore"]=function(){abort("'IDBStore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"runAndAbortIfError"))Module["runAndAbortIfError"]=function(){abort("'runAndAbortIfError' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["PThread"]=PThread;if(!Object.getOwnPropertyDescriptor(Module,"establishStackSpace"))Module["establishStackSpace"]=function(){abort("'establishStackSpace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getNoExitRuntime"))Module["getNoExitRuntime"]=function(){abort("'getNoExitRuntime' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"resetPrototype"))Module["resetPrototype"]=function(){abort("'resetPrototype' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"warnOnce"))Module["warnOnce"]=function(){abort("'warnOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackSave"))Module["stackSave"]=function(){abort("'stackSave' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackRestore"))Module["stackRestore"]=function(){abort("'stackRestore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackAlloc"))Module["stackAlloc"]=function(){abort("'stackAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AsciiToString"))Module["AsciiToString"]=function(){abort("'AsciiToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToAscii"))Module["stringToAscii"]=function(){abort("'stringToAscii' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF16ToString"))Module["UTF16ToString"]=function(){abort("'UTF16ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF16"))Module["stringToUTF16"]=function(){abort("'stringToUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF16"))Module["lengthBytesUTF16"]=function(){abort("'lengthBytesUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF32ToString"))Module["UTF32ToString"]=function(){abort("'UTF32ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF32"))Module["stringToUTF32"]=function(){abort("'stringToUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF32"))Module["lengthBytesUTF32"]=function(){abort("'lengthBytesUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8"))Module["allocateUTF8"]=function(){abort("'allocateUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8OnStack"))Module["allocateUTF8OnStack"]=function(){abort("'allocateUTF8OnStack' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["writeStackCookie"]=writeStackCookie;Module["checkStackCookie"]=checkStackCookie;Module["abortStackOverflow"]=abortStackOverflow;Module["PThread"]=PThread;Module["_pthread_self"]=_pthread_self;Module["wasmMemory"]=wasmMemory;Module["ExitStatus"]=ExitStatus;if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NORMAL"))Object.defineProperty(Module,"ALLOC_NORMAL",{configurable:true,get:function(){abort("'ALLOC_NORMAL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_STACK"))Object.defineProperty(Module,"ALLOC_STACK",{configurable:true,get:function(){abort("'ALLOC_STACK' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_DYNAMIC"))Object.defineProperty(Module,"ALLOC_DYNAMIC",{configurable:true,get:function(){abort("'ALLOC_DYNAMIC' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NONE"))Object.defineProperty(Module,"ALLOC_NONE",{configurable:true,get:function(){abort("'ALLOC_NONE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}writeStackCookie();preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();assert(!Module["_main"],'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}checkStackCookie();}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}if(!ENVIRONMENT_IS_PTHREAD)noExitRuntime=true;if(!ENVIRONMENT_IS_PTHREAD)run(); - - - return WasmBackendModule - } - ); - })(); - module.exports = WasmBackendModule; - }); - - const wasmWorkerContents = 'var threadInfoStruct=0;var selfThreadId=0;var parentThreadId=0;var Module={};function assert(condition,text){if(!condition)abort("Assertion failed: "+text)}function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:selfThreadId})}var out=function(){throw"out() is not defined in worker.js."};var err=threadPrintErr;this.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);Module["wasmModule"]=null;receiveInstance(instance);return instance.exports};this.onmessage=function(e){try{if(e.data.cmd==="load"){console.log("LOADING");console.log(e.data);Module["DYNAMIC_BASE"]=e.data.DYNAMIC_BASE;Module["DYNAMICTOP_PTR"]=e.data.DYNAMICTOP_PTR;Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob==="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}Module=WasmBackendModule(Module);postMessage({"cmd":"loaded"})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;threadInfoStruct=e.data.threadInfoStruct;Module["__register_pthread_ptr"](threadInfoStruct,0,0);selfThreadId=e.data.selfThreadId;parentThreadId=e.data.parentThreadId;var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;assert(threadInfoStruct);assert(selfThreadId);assert(parentThreadId);assert(top!=0);assert(max!=0);assert(top>max);Module["establishStackSpace"](top,max);Module["_emscripten_tls_init"]();Module["writeStackCookie"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].setThreadStatus(Module["_pthread_self"](),1);try{var result=Module["dynCall_ii"](e.data.start_routine,e.data.arg);Module["checkStackCookie"]();if(!Module["getNoExitRuntime"]())Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){Atomics.store(Module["HEAPU32"],threadInfoStruct+4>>2,ex instanceof Module["ExitStatus"]?ex.status:-2);Atomics.store(Module["HEAPU32"],threadInfoStruct+0>>2,1);if(typeof Module["_emscripten_futex_wake"]!=="function"){err("Thread Initialisation failed.");throw ex}Module["_emscripten_futex_wake"](threadInfoStruct+0,2147483647);if(!(ex instanceof Module["ExitStatus"]))throw ex}else{err("Pthread 0x"+threadInfoStruct.toString(16)+" completed its pthread main entry point with an unwind, keeping the pthread worker alive for asynchronous operation.")}}}else if(e.data.cmd==="cancel"){if(threadInfoStruct){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(threadInfoStruct){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex.stack)err(ex.stack);throw ex}};if(typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string"){self={location:{href:__filename}};var onmessage=this.onmessage;var nodeWorkerThreads=require("worker_threads");Worker=nodeWorkerThreads.Worker;var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var nodeFS=require("fs");var nodeRead=function(filename){return nodeFS.readFileSync(filename,"utf8")};function globalEval(x){global.require=require;global.Module=Module;eval.call(null,x)}importScripts=function(f){globalEval(nodeRead(f))};postMessage=function(msg){parentPort.postMessage(msg)};if(typeof performance==="undefined"){performance={now:function(){return Date.now()}}}}'; - + ]))); + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var tfjsBackendWasmThreaded = createCommonjsModule(function (module, exports) { + var WasmBackendModule = (function() { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( + function(WasmBackendModule) { + WasmBackendModule = WasmBackendModule || {}; + + function GROWABLE_HEAP_I8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP8}function GROWABLE_HEAP_U8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU8}function GROWABLE_HEAP_I32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP32}function GROWABLE_HEAP_U32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPF64}var Module=typeof WasmBackendModule!=="undefined"?WasmBackendModule:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(Module["ENVIRONMENT"]){throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -s ENVIRONMENT=web or -s ENVIRONMENT=node)")}var ENVIRONMENT_IS_PTHREAD=Module["ENVIRONMENT_IS_PTHREAD"]||false;if(ENVIRONMENT_IS_PTHREAD){buffer=Module["buffer"];DYNAMIC_BASE=Module["DYNAMIC_BASE"];DYNAMICTOP_PTR=Module["DYNAMICTOP_PTR"];}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};var nodeWorkerThreads;try{nodeWorkerThreads=worker_threads;}catch(e){console.error('The "worker_threads" module is not supported in this node.js build - perhaps a newer version is needed?');throw e}Worker=nodeWorkerThreads.Worker;}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}if(ENVIRONMENT_IS_NODE){read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};}else{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}else{throw new Error("environment detection error")}if(ENVIRONMENT_IS_NODE){if(typeof performance==="undefined"){performance=perf_hooks.performance;}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(!Object.getOwnPropertyDescriptor(Module,"arguments"))Object.defineProperty(Module,"arguments",{configurable:true,get:function(){abort("Module.arguments has been replaced with plain arguments_");}});if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(!Object.getOwnPropertyDescriptor(Module,"thisProgram"))Object.defineProperty(Module,"thisProgram",{configurable:true,get:function(){abort("Module.thisProgram has been replaced with plain thisProgram");}});if(Module["quit"])quit_=Module["quit"];if(!Object.getOwnPropertyDescriptor(Module,"quit"))Object.defineProperty(Module,"quit",{configurable:true,get:function(){abort("Module.quit has been replaced with plain quit_");}});assert(typeof Module["memoryInitializerPrefixURL"]==="undefined","Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["pthreadMainPrefixURL"]==="undefined","Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["cdInitializerPrefixURL"]==="undefined","Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["filePackagePrefixURL"]==="undefined","Module.filePackagePrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["read"]==="undefined","Module.read option was removed (modify read_ in JS)");assert(typeof Module["readAsync"]==="undefined","Module.readAsync option was removed (modify readAsync in JS)");assert(typeof Module["readBinary"]==="undefined","Module.readBinary option was removed (modify readBinary in JS)");assert(typeof Module["setWindowTitle"]==="undefined","Module.setWindowTitle option was removed (modify setWindowTitle in JS)");assert(typeof Module["TOTAL_MEMORY"]==="undefined","Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");if(!Object.getOwnPropertyDescriptor(Module,"read"))Object.defineProperty(Module,"read",{configurable:true,get:function(){abort("Module.read has been replaced with plain read_");}});if(!Object.getOwnPropertyDescriptor(Module,"readAsync"))Object.defineProperty(Module,"readAsync",{configurable:true,get:function(){abort("Module.readAsync has been replaced with plain readAsync");}});if(!Object.getOwnPropertyDescriptor(Module,"readBinary"))Object.defineProperty(Module,"readBinary",{configurable:true,get:function(){abort("Module.readBinary has been replaced with plain readBinary");}});if(!Object.getOwnPropertyDescriptor(Module,"setWindowTitle"))Object.defineProperty(Module,"setWindowTitle",{configurable:true,get:function(){abort("Module.setWindowTitle has been replaced with plain setWindowTitle");}});assert(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER||ENVIRONMENT_IS_NODE,"Pthreads do not work in this environment yet (need Web Workers, or an alternative to them)");var stackSave;var stackRestore;var stackAlloc;stackSave=stackRestore=stackAlloc=function(){abort("cannot use the stack before compiled code is ready to run, and has provided stack access");};function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text);}}var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(!Object.getOwnPropertyDescriptor(Module,"wasmBinary"))Object.defineProperty(Module,"wasmBinary",{configurable:true,get:function(){abort("Module.wasmBinary has been replaced with plain wasmBinary");}});var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(!Object.getOwnPropertyDescriptor(Module,"noExitRuntime"))Object.defineProperty(Module,"noExitRuntime",{configurable:true,get:function(){abort("Module.noExitRuntime has been replaced with plain noExitRuntime");}});if(typeof WebAssembly!=="object"){abort("No WebAssembly support found. Build with -s WASM=0 to target JavaScript instead.");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":160,"maximum":160+0,"element":"anyfunc"});var wasmModule;var threadInfoStruct=0;var selfThreadId=0;var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;assert(returnType!=="array",'Return type should not be "array".');if(args){for(var i=0;i=endIdx)){var u0=heap[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heap[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heap[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2;}else{if((u0&248)!=240)warnOnce("Invalid UTF-8 leading byte 0x"+u0.toString(16)+" encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!");u0=(u0&7)<<18|u1<<12|u2<<6|heap[idx++]&63;}if(u0<65536){str+=String.fromCharCode(u0);}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023);}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;if(u>=2097152)warnOnce("Invalid Unicode code point 0x"+u.toString(16)+" encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).");heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){assert(typeof maxBytesToWrite=="number","stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");return stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4;}return len}function writeArrayToMemory(array,buffer){assert(array.length>=0,"writeArrayToMemory array must have a length (should be an array or typed array)");GROWABLE_HEAP_I8().set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var STACK_BASE=5256544,STACKTOP=STACK_BASE,STACK_MAX=13664,DYNAMIC_BASE=5256544,DYNAMICTOP_PTR=12736;assert(STACK_BASE%16===0,"stack must start aligned");assert(DYNAMIC_BASE%16===0,"heap must start aligned");if(ENVIRONMENT_IS_PTHREAD){STACK_MAX=STACKTOP=STACK_MAX=2147483647;}var TOTAL_STACK=5242880;if(Module["TOTAL_STACK"])assert(TOTAL_STACK===Module["TOTAL_STACK"],"the stack size can no longer be determined at runtime");var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||1073741824;if(!Object.getOwnPropertyDescriptor(Module,"INITIAL_MEMORY"))Object.defineProperty(Module,"INITIAL_MEMORY",{configurable:true,get:function(){abort("Module.INITIAL_MEMORY has been replaced with plain INITIAL_INITIAL_MEMORY");}});assert(INITIAL_INITIAL_MEMORY>=TOTAL_STACK,"INITIAL_MEMORY should be larger than TOTAL_STACK, was "+INITIAL_INITIAL_MEMORY+"! (TOTAL_STACK="+TOTAL_STACK+")");assert(typeof Int32Array!=="undefined"&&typeof Float64Array!=="undefined"&&Int32Array.prototype.subarray!==undefined&&Int32Array.prototype.set!==undefined,"JS engine does not provide full typed array support");if(ENVIRONMENT_IS_PTHREAD){wasmMemory=Module["wasmMemory"];buffer=Module["buffer"];}else{if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":1073741824/WASM_PAGE_SIZE,"shared":true});if(!(wasmMemory.buffer instanceof SharedArrayBuffer)){err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");if(ENVIRONMENT_IS_NODE){console.log("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)");}throw Error("bad memory")}}}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;assert(INITIAL_INITIAL_MEMORY%WASM_PAGE_SIZE===0);assert(65536%WASM_PAGE_SIZE===0);updateGlobalBufferAndViews(buffer);if(!ENVIRONMENT_IS_PTHREAD){GROWABLE_HEAP_I32()[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;}function writeStackCookie(){assert((STACK_MAX&3)==0);GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1]=34821223;GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2]=2310721022;GROWABLE_HEAP_I32()[0]=1668509029;}function checkStackCookie(){var cookie1=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1];var cookie2=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2];if(cookie1!=34821223||cookie2!=2310721022){abort("Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x"+cookie2.toString(16)+" "+cookie1.toString(16));}if(GROWABLE_HEAP_I32()[0]!==1668509029)abort("Runtime error: The application has corrupted its heap memory area (address zero)!");}function abortStackOverflow(allocSize){abort("Stack overflow! Attempted to allocate "+allocSize+" bytes on the stack, but stack has only "+(STACK_MAX-stackSave()+allocSize)+" bytes available!");}(function(){var h16=new Int16Array(1);var h8=new Int8Array(h16.buffer);h16[0]=25459;if(h8[0]!==115||h8[1]!==99)throw "Runtime error: expected the system to be little-endian!"})();function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;if(ENVIRONMENT_IS_PTHREAD)runtimeInitialized=true;function preRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){checkStackCookie();assert(!runtimeInitialized);runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__);}function preMain(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;callRuntimeCallbacks(__ATMAIN__);}function postRun(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}assert(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;var runDependencyTracking={};function addRunDependency(id){assert(!ENVIRONMENT_IS_PTHREAD,"addRunDependency cannot be used in a pthread worker");runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(!runDependencyTracking[id]);runDependencyTracking[id]=1;if(runDependencyWatcher===null&&typeof setInterval!=="undefined"){runDependencyWatcher=setInterval(function(){if(ABORT){clearInterval(runDependencyWatcher);runDependencyWatcher=null;return}var shown=false;for(var dep in runDependencyTracking){if(!shown){shown=true;err("still waiting on run dependencies:");}err("dependency: "+dep);}if(shown){err("(end of list)");}},1e4);}}else{err("warning: run dependency added without ID");}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(runDependencyTracking[id]);delete runDependencyTracking[id];}else{err("warning: run dependency removed without ID");}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}if(ENVIRONMENT_IS_PTHREAD)console.error("Pthread aborting at "+(new Error).stack);what+="";out(what);err(what);ABORT=true;var output="abort("+what+") at "+stackTrace();what=output;throw new WebAssembly.RuntimeError(what)}var FS={error:function(){abort("Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -s FORCE_FILESYSTEM=1");},init:function(){FS.error();},createDataFile:function(){FS.error();},createPreloadedFile:function(){FS.error();},createLazyFile:function(){FS.error();},open:function(){FS.error();},mkdev:function(){FS.error();},registerDevice:function(){FS.error();},analyzePath:function(){FS.error();},loadFilesFromDB:function(){FS.error();},ErrnoError:function ErrnoError(){FS.error();}};Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm-threaded.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmModule=module;if(!ENVIRONMENT_IS_PTHREAD){var numWorkersToLoad=PThread.unusedWorkers.length;PThread.unusedWorkers.forEach(function(w){PThread.loadWasmModuleToWorker(w,function(){if(!--numWorkersToLoad)removeRunDependency("wasm-instantiate");});});}}if(!ENVIRONMENT_IS_PTHREAD){addRunDependency("wasm-instantiate");}var trueModule=Module;function receiveInstantiatedSource(output){assert(Module===trueModule,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");trueModule=null;receiveInstance(output["instance"],output["module"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}var ASM_CONSTS={};function initPthreadsJS(){PThread.initRuntime();}if(!ENVIRONMENT_IS_PTHREAD)__ATINIT__.push({func:function(){___wasm_call_ctors();}});function demangle(func){warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling");return func}function demangleAll(text){var regex=/\b_Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}var __pthread_ptr=0;var __pthread_is_main_runtime_thread=0;var __pthread_is_main_browser_thread=0;function __register_pthread_ptr(pthreadPtr,isMainBrowserThread,isMainRuntimeThread){pthreadPtr=pthreadPtr|0;isMainBrowserThread=isMainBrowserThread|0;isMainRuntimeThread=isMainRuntimeThread|0;__pthread_ptr=pthreadPtr;__pthread_is_main_browser_thread=isMainBrowserThread;__pthread_is_main_runtime_thread=isMainRuntimeThread;}Module["__register_pthread_ptr"]=__register_pthread_ptr;var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var __main_thread_futex_wait_address=13648;function _emscripten_futex_wake(addr,count){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0||count<0)return -28;if(count==0)return 0;if(count>=2147483647)count=Infinity;var mainThreadWaitAddress=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);var mainThreadWoken=0;if(mainThreadWaitAddress==addr){var loadedAddr=Atomics.compareExchange(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,mainThreadWaitAddress,0);if(loadedAddr==mainThreadWaitAddress){--count;mainThreadWoken=1;if(count<=0)return 1}}var ret=Atomics.notify(GROWABLE_HEAP_I32(),addr>>2,count);if(ret>=0)return ret+mainThreadWoken;throw "Atomics.notify returned an unexpected value "+ret}Module["_emscripten_futex_wake"]=_emscripten_futex_wake;function __kill_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _kill_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _kill_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];pthread.worker.terminate();PThread.freeThreadData(pthread);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(pthread.worker),1);pthread.worker.pthread=undefined;}function __cancel_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cancel_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cancel_thread!";var pthread=PThread.pthreads[pthread_ptr];pthread.worker.postMessage({"cmd":"cancel"});}function __cleanup_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cleanup_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cleanup_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];if(pthread){var worker=pthread.worker;PThread.returnWorkerToPool(worker);}}var PThread={MAIN_THREAD_ID:1,mainThreadInfo:{schedPolicy:0,schedPrio:0},unusedWorkers:[],runningWorkers:[],initRuntime:function(){__register_pthread_ptr(PThread.mainThreadBlock,!ENVIRONMENT_IS_WORKER,1);_emscripten_register_main_browser_thread_id(PThread.mainThreadBlock);},initMainThreadBlock:function(){assert(!ENVIRONMENT_IS_PTHREAD);var pthreadPoolSize=8;for(var i=0;i>2]=PThread.mainThreadBlock;var headPtr=PThread.mainThreadBlock+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var tlsMemory=13136;for(var i=0;i<128;++i)GROWABLE_HEAP_U32()[tlsMemory/4+i]=0;Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+104>>2,tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+40>>2,PThread.mainThreadBlock);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+44>>2,42);},initWorker:function(){},pthreads:{},exitHandlers:null,setThreadStatus:function(){},runExitHandlers:function(){if(PThread.exitHandlers!==null){while(PThread.exitHandlers.length>0){PThread.exitHandlers.pop()();}PThread.exitHandlers=null;}if(ENVIRONMENT_IS_PTHREAD&&threadInfoStruct)___pthread_tsd_run_dtors();},threadExit:function(exitCode){var tb=_pthread_self();if(tb){err("Pthread 0x"+tb.toString(16)+" exited.");Atomics.store(GROWABLE_HEAP_U32(),tb+4>>2,exitCode);Atomics.store(GROWABLE_HEAP_U32(),tb+0>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+60>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+64>>2,0);PThread.runExitHandlers();_emscripten_futex_wake(tb+0,2147483647);__register_pthread_ptr(0,0,0);threadInfoStruct=0;if(ENVIRONMENT_IS_PTHREAD){postMessage({"cmd":"exit"});}}},threadCancel:function(){PThread.runExitHandlers();Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+4>>2,-1);Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+0>>2,1);_emscripten_futex_wake(threadInfoStruct+0,2147483647);threadInfoStruct=selfThreadId=0;__register_pthread_ptr(0,0,0);postMessage({"cmd":"cancelDone"});},terminateAllThreads:function(){for(var t in PThread.pthreads){var pthread=PThread.pthreads[t];if(pthread&&pthread.worker){PThread.returnWorkerToPool(pthread.worker);}}PThread.pthreads={};for(var i=0;i>2];GROWABLE_HEAP_I32()[pthread.threadInfoStruct+104>>2]=0;_free(tlsMemory);_free(pthread.threadInfoStruct);}pthread.threadInfoStruct=0;if(pthread.allocatedOwnStack&&pthread.stackBase)_free(pthread.stackBase);pthread.stackBase=0;if(pthread.worker)pthread.worker.pthread=null;},returnWorkerToPool:function(worker){delete PThread.pthreads[worker.pthread.thread];PThread.unusedWorkers.push(worker);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);PThread.freeThreadData(worker.pthread);worker.pthread=undefined;},receiveObjectTransfer:function(data){},loadWasmModuleToWorker:function(worker,onFinishedLoading){worker.onmessage=function(e){var d=e["data"];var cmd=d["cmd"];if(worker.pthread)PThread.currentProxiedOperationCallerThread=worker.pthread.threadInfoStruct;if(d["targetThread"]&&d["targetThread"]!=_pthread_self()){var thread=PThread.pthreads[d.targetThread];if(thread){thread.worker.postMessage(e.data,d["transferList"]);}else{console.error('Internal error! Worker sent a message "'+cmd+'" to target pthread '+d["targetThread"]+", but that thread no longer exists!");}PThread.currentProxiedOperationCallerThread=undefined;return}if(cmd==="processQueuedMainThreadWork"){_emscripten_main_thread_process_queued_calls();}else if(cmd==="spawnThread"){__spawn_thread(e.data);}else if(cmd==="cleanupThread"){__cleanup_thread(d["thread"]);}else if(cmd==="killThread"){__kill_thread(d["thread"]);}else if(cmd==="cancelThread"){__cancel_thread(d["thread"]);}else if(cmd==="loaded"){worker.loaded=true;if(onFinishedLoading)onFinishedLoading(worker);if(worker.runPthread){worker.runPthread();delete worker.runPthread;}}else if(cmd==="print"){out("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="printErr"){err("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="alert"){alert("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="exit"){var detached=worker.pthread&&Atomics.load(GROWABLE_HEAP_U32(),worker.pthread.thread+68>>2);if(detached){PThread.returnWorkerToPool(worker);}}else if(cmd==="cancelDone"){PThread.returnWorkerToPool(worker);}else if(cmd==="objectTransfer"){PThread.receiveObjectTransfer(e.data);}else if(e.data.target==="setimmediate"){worker.postMessage(e.data);}else{err("worker sent an unknown command "+cmd);}PThread.currentProxiedOperationCallerThread=undefined;};worker.onerror=function(e){err("pthread sent an error! "+e.filename+":"+e.lineno+": "+e.message);};if(ENVIRONMENT_IS_NODE){worker.on("message",function(data){worker.onmessage({data:data});});worker.on("error",function(data){worker.onerror(data);});worker.on("exit",function(data){console.log("worker exited - TODO: update the worker queue?");});}assert(wasmMemory instanceof WebAssembly.Memory,"WebAssembly memory should have been loaded by now!");assert(wasmModule instanceof WebAssembly.Module,"WebAssembly Module should have been loaded by now!");worker.postMessage({"cmd":"load","urlOrBlob":Module["mainScriptUrlOrBlob"]||_scriptDir,"wasmMemory":wasmMemory,"wasmModule":wasmModule,"DYNAMIC_BASE":DYNAMIC_BASE,"DYNAMICTOP_PTR":DYNAMICTOP_PTR});},allocateUnusedWorker:function(){var pthreadMainJs=locateFile("tfjs-backend-wasm-threaded.worker.js");PThread.unusedWorkers.push(new Worker(pthreadMainJs));},getNewWorker:function(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]);}if(PThread.unusedWorkers.length>0)return PThread.unusedWorkers.pop();else return null},busySpinWait:function(msecs){var t=performance.now()+msecs;while(performance.now()>2]=value;return value}function _atexit(func,arg){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(1,1,func,arg);warnOnce("atexit() called, but EXIT_RUNTIME is not set, so atexits() will not be called. set EXIT_RUNTIME to 1 (see the FAQ)");}function ___handle_stack_overflow(){abort("stack overflow");}function __emscripten_notify_thread_queue(targetThreadId,mainThreadId){if(targetThreadId==mainThreadId){postMessage({"cmd":"processQueuedMainThreadWork"});}else if(ENVIRONMENT_IS_PTHREAD){postMessage({"targetThread":targetThreadId,"cmd":"processThreadQueue"});}else{var pthread=PThread.pthreads[targetThreadId];var worker=pthread&&pthread.worker;if(!worker){err("Cannot send message to thread with ID "+targetThreadId+", unknown thread ID!");return}worker.postMessage({"cmd":"processThreadQueue"});}return 1}function _abort(){abort();}function _emscripten_conditional_set_current_thread_status(expectedStatus,newStatus){}function _emscripten_futex_wait(addr,val,timeout){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0)return -28;if(ENVIRONMENT_IS_WORKER){var ret=Atomics.wait(GROWABLE_HEAP_I32(),addr>>2,val,timeout);if(ret==="timed-out")return -73;if(ret==="not-equal")return -6;if(ret==="ok")return 0;throw "Atomics.wait returned an unexpected value "+ret}else{var loadedVal=Atomics.load(GROWABLE_HEAP_I32(),addr>>2);if(val!=loadedVal)return -6;var tNow=performance.now();var tEnd=tNow+timeout;Atomics.store(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,addr);var ourWaitAddress=addr;while(addr==ourWaitAddress){tNow=performance.now();if(tNow>tEnd){return -73}_emscripten_main_thread_process_queued_calls();addr=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);}return 0}}function _emscripten_is_main_browser_thread(){return __pthread_is_main_browser_thread|0}function _emscripten_is_main_runtime_thread(){return __pthread_is_main_runtime_thread|0}function _emscripten_memcpy_big(dest,src,num){GROWABLE_HEAP_U8().copyWithin(dest,src,src+num);}function _emscripten_proxy_to_main_thread_js(index,sync){var numCallArgs=arguments.length-2;if(numCallArgs>20-1)throw "emscripten_proxy_to_main_thread_js: Too many arguments "+numCallArgs+" to proxied function idx="+index+", maximum supported is "+(20-1)+"!";var stack=stackSave();var args=stackAlloc(numCallArgs*8);var b=args>>3;for(var i=0;i>3]);buf+=8;}else if(ch===105){buf=buf+3&~3;args.push(GROWABLE_HEAP_I32()[buf>>2]);buf+=4;}else abort("unexpected char in asm const signature "+ch);}return args}function _emscripten_receive_on_main_thread_js(index,numCallArgs,args){_emscripten_receive_on_main_thread_js_callArgs.length=numCallArgs;var b=args>>3;for(var i=0;i>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){console.error("emscripten_realloc_buffer: Attempted to grow heap from "+buffer.byteLength+" bytes to "+size+" bytes, but got error: "+e);}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();if(requestedSize<=oldSize){return false}var PAGE_MULTIPLE=65536;var maxHeapSize=1073741824;if(requestedSize>maxHeapSize){err("Cannot enlarge memory, asked to go up to "+requestedSize+" bytes, but the limit is "+maxHeapSize+" bytes!");return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}err("Failed to grow the heap from "+oldSize+" bytes to "+newSize+" bytes, not enough memory!");return false}var JSEvents={keyEvent:0,mouseEvent:0,wheelEvent:0,uiEvent:0,focusEvent:0,deviceOrientationEvent:0,deviceMotionEvent:0,fullscreenChangeEvent:0,pointerlockChangeEvent:0,visibilityChangeEvent:0,touchEvent:0,previousFullscreenElement:null,previousScreenX:null,previousScreenY:null,removeEventListenersRegistered:false,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i);}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[];},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){JSEvents.removeEventListenersRegistered=true;}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence>2]=eventTypeId;GROWABLE_HEAP_I32()[varargs+4>>2]=eventData;GROWABLE_HEAP_I32()[varargs+8>>2]=userData;_emscripten_async_queue_on_thread_(targetThread,637534208,eventHandlerFunc,eventData,varargs);stackRestore(stackTop);},getTargetThreadForEventCallback:function(targetThread){switch(targetThread){case 1:return 0;case 2:return PThread.currentProxiedOperationCallerThread;default:return targetThread}},getNodeNameForTarget:function(target){if(!target)return "";if(target==window)return "#window";if(target==screen)return "#screen";return target&&target.nodeName?target.nodeName:""},fullscreenEnabled:function(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+1;var cString=_malloc(length);stringToUTF8(jsString,cString,length);return cString}function _emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height){var stackTop=stackSave();var varargs=stackAlloc(12);var targetCanvasPtr=0;if(targetCanvas){targetCanvasPtr=stringToNewUTF8(targetCanvas);}GROWABLE_HEAP_I32()[varargs>>2]=targetCanvasPtr;GROWABLE_HEAP_I32()[varargs+4>>2]=width;GROWABLE_HEAP_I32()[varargs+8>>2]=height;_emscripten_async_queue_on_thread_(targetThread,657457152,0,targetCanvasPtr,varargs);stackRestore(stackTop);}function _emscripten_set_offscreencanvas_size_on_target_thread(targetThread,targetCanvas,width,height){targetCanvas=targetCanvas?UTF8ToString(targetCanvas):"";_emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height);}function __maybeCStringToJsString(cString){return cString>2?UTF8ToString(cString):cString}var specialHTMLTargets=[0,typeof document!=="undefined"?document:0,typeof window!=="undefined"?window:0];function __findEventTarget(target){target=__maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!=="undefined"?document.querySelector(target):undefined);return domElement}function __findCanvasEventTarget(target){return __findEventTarget(target)}function _emscripten_set_canvas_element_size_calling_thread(target,width,height){var canvas=__findCanvasEventTarget(target);if(!canvas)return -4;if(canvas.canvasSharedPtr){GROWABLE_HEAP_I32()[canvas.canvasSharedPtr>>2]=width;GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+4>>2]=height;}if(canvas.offscreenCanvas||!canvas.controlTransferredOffscreen){if(canvas.offscreenCanvas)canvas=canvas.offscreenCanvas;var autoResizeViewport=false;if(canvas.GLctxObject&&canvas.GLctxObject.GLctx){var prevViewport=canvas.GLctxObject.GLctx.getParameter(2978);autoResizeViewport=prevViewport[0]===0&&prevViewport[1]===0&&prevViewport[2]===canvas.width&&prevViewport[3]===canvas.height;}canvas.width=width;canvas.height=height;if(autoResizeViewport){canvas.GLctxObject.GLctx.viewport(0,0,width,height);}}else if(canvas.canvasSharedPtr){var targetThread=GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+8>>2];_emscripten_set_offscreencanvas_size_on_target_thread(targetThread,target,width,height);return 1}else{return -4}return 0}function _emscripten_set_canvas_element_size_main_thread(target,width,height){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(2,1,target,width,height);return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}function _emscripten_set_canvas_element_size(target,width,height){var canvas=__findCanvasEventTarget(target);if(canvas){return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}else{return _emscripten_set_canvas_element_size_main_thread(target,width,height)}}function _emscripten_set_current_thread_status(newStatus){}function _emscripten_set_thread_name(threadId,name){}function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=function(index,divisor){ext["vertexAttribDivisorANGLE"](index,divisor);};ctx["drawArraysInstanced"]=function(mode,first,count,primcount){ext["drawArraysInstancedANGLE"](mode,first,count,primcount);};ctx["drawElementsInstanced"]=function(mode,count,type,indices,primcount){ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);};return 1}}function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=function(){return ext["createVertexArrayOES"]()};ctx["deleteVertexArray"]=function(vao){ext["deleteVertexArrayOES"](vao);};ctx["bindVertexArray"]=function(vao){ext["bindVertexArrayOES"](vao);};ctx["isVertexArray"]=function(vao){return ext["isVertexArrayOES"](vao)};return 1}}function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=function(n,bufs){ext["drawBuffersWEBGL"](n,bufs);};return 1}}var GL={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:{},currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],programInfos:{},stringCache:{},unpackAlignment:4,init:function(){var miniTempFloatBuffer=new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);for(var i=0;i>2]:-1;source+=UTF8ToString(GROWABLE_HEAP_I32()[string+i*4>>2],len<0?undefined:len);}return source},createContext:function(canvas,webGLContextAttributes){var ctx=canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=_malloc(8);GROWABLE_HEAP_I32()[handle+4>>2]=_pthread_self();var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context);}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return !(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;_free(GL.contexts[contextHandle].handle);GL.contexts[contextHandle]=null;},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;__webgl_enable_ANGLE_instanced_arrays(GLctx);__webgl_enable_OES_vertex_array_object(GLctx);__webgl_enable_WEBGL_draw_buffers(GLctx);GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query");var automaticallyEnabledExtensions=["OES_texture_float","OES_texture_half_float","OES_standard_derivatives","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBGL_depth_texture","OES_element_index_uint","EXT_texture_filter_anisotropic","EXT_frag_depth","WEBGL_draw_buffers","ANGLE_instanced_arrays","OES_texture_float_linear","OES_texture_half_float_linear","EXT_blend_minmax","EXT_shader_texture_lod","EXT_texture_norm16","WEBGL_compressed_texture_pvrtc","EXT_color_buffer_half_float","WEBGL_color_buffer_float","EXT_sRGB","WEBGL_compressed_texture_etc1","EXT_disjoint_timer_query","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_astc","EXT_color_buffer_float","WEBGL_compressed_texture_s3tc_srgb","EXT_disjoint_timer_query_webgl2","WEBKIT_WEBGL_compressed_texture_pvrtc"];var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext);}});},populateUniformTable:function(program){var p=GL.programs[program];var ptable=GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,35718);for(var i=0;i>2;contextAttributes["alpha"]=!!GROWABLE_HEAP_I32()[a+(0>>2)];contextAttributes["depth"]=!!GROWABLE_HEAP_I32()[a+(4>>2)];contextAttributes["stencil"]=!!GROWABLE_HEAP_I32()[a+(8>>2)];contextAttributes["antialias"]=!!GROWABLE_HEAP_I32()[a+(12>>2)];contextAttributes["premultipliedAlpha"]=!!GROWABLE_HEAP_I32()[a+(16>>2)];contextAttributes["preserveDrawingBuffer"]=!!GROWABLE_HEAP_I32()[a+(20>>2)];var powerPreference=GROWABLE_HEAP_I32()[a+(24>>2)];contextAttributes["powerPreference"]=__emscripten_webgl_power_preferences[powerPreference];contextAttributes["failIfMajorPerformanceCaveat"]=!!GROWABLE_HEAP_I32()[a+(28>>2)];contextAttributes.majorVersion=GROWABLE_HEAP_I32()[a+(32>>2)];contextAttributes.minorVersion=GROWABLE_HEAP_I32()[a+(36>>2)];contextAttributes.enableExtensionsByDefault=GROWABLE_HEAP_I32()[a+(40>>2)];contextAttributes.explicitSwapControl=GROWABLE_HEAP_I32()[a+(44>>2)];contextAttributes.proxyContextToMainThread=GROWABLE_HEAP_I32()[a+(48>>2)];contextAttributes.renderViaOffscreenBackBuffer=GROWABLE_HEAP_I32()[a+(52>>2)];var canvas=__findCanvasEventTarget(target);if(!canvas){return -4}if(contextAttributes.explicitSwapControl){return -1}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}function _emscripten_webgl_create_context(a0,a1){return _emscripten_webgl_do_create_context(a0,a1)}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];assert(buffer);if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){assert(SYSCALLS.varargs!=undefined);SYSCALLS.varargs+=4;var ret=GROWABLE_HEAP_I32()[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){if(low>=0)assert(high===0);else assert(high===-1);return low}};function _fd_close(fd){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(3,1,fd);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(4,1,fd,offset_low,offset_high,whence,newOffset);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");}function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(5,1,fd,iov,iovcnt,pnum);var num=0;for(var i=0;i>2];var len=GROWABLE_HEAP_I32()[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _pthread_cleanup_pop(execute){var routine=PThread.exitHandlers.pop();if(execute)routine();}function _pthread_cleanup_push(routine,arg){if(PThread.exitHandlers===null){PThread.exitHandlers=[];}PThread.exitHandlers.push(function(){dynCall_vi(routine,arg);});}function __spawn_thread(threadParams){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _spawn_thread() can only ever be called from main application thread!";var worker=PThread.getNewWorker();if(worker.pthread!==undefined)throw "Internal error!";if(!threadParams.pthread_ptr)throw "Internal error, no pthread ptr!";PThread.runningWorkers.push(worker);var tlsMemory=_malloc(128*4);for(var i=0;i<128;++i){GROWABLE_HEAP_I32()[tlsMemory+i*4>>2]=0;}var stackHigh=threadParams.stackBase+threadParams.stackSize;var pthread=PThread.pthreads[threadParams.pthread_ptr]={worker:worker,stackBase:threadParams.stackBase,stackSize:threadParams.stackSize,allocatedOwnStack:threadParams.allocatedOwnStack,thread:threadParams.pthread_ptr,threadInfoStruct:threadParams.pthread_ptr};var tis=pthread.threadInfoStruct>>2;Atomics.store(GROWABLE_HEAP_U32(),tis+(0>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(4>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(8>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(68>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(104>>2),tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),tis+(48>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(40>>2),pthread.threadInfoStruct);Atomics.store(GROWABLE_HEAP_U32(),tis+(44>>2),42);Atomics.store(GROWABLE_HEAP_U32(),tis+(108>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(84>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(80>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+8>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+12>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+20>>2),threadParams.schedPolicy);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+24>>2),threadParams.schedPrio);var global_libc=_emscripten_get_global_libc();var global_locale=global_libc+40;Atomics.store(GROWABLE_HEAP_U32(),tis+(176>>2),global_locale);worker.pthread=pthread;var msg={"cmd":"run","start_routine":threadParams.startRoutine,"arg":threadParams.arg,"threadInfoStruct":threadParams.pthread_ptr,"selfThreadId":threadParams.pthread_ptr,"parentThreadId":threadParams.parent_pthread_ptr,"stackBase":threadParams.stackBase,"stackSize":threadParams.stackSize};worker.runPthread=function(){msg.time=performance.now();worker.postMessage(msg,threadParams.transferList);};if(worker.loaded){worker.runPthread();delete worker.runPthread;}}function _pthread_getschedparam(thread,policy,schedparam){if(!policy&&!schedparam)return ERRNO_CODES.EINVAL;if(!thread){err("pthread_getschedparam called with a null thread pointer!");return ERRNO_CODES.ESRCH}var self=GROWABLE_HEAP_I32()[thread+12>>2];if(self!==thread){err("pthread_getschedparam attempted on thread "+thread+", which does not point to a valid thread, or does not exist anymore!");return ERRNO_CODES.ESRCH}var schedPolicy=Atomics.load(GROWABLE_HEAP_U32(),thread+108+20>>2);var schedPrio=Atomics.load(GROWABLE_HEAP_U32(),thread+108+24>>2);if(policy)GROWABLE_HEAP_I32()[policy>>2]=schedPolicy;if(schedparam)GROWABLE_HEAP_I32()[schedparam>>2]=schedPrio;return 0}function _pthread_self(){return __pthread_ptr|0}Module["_pthread_self"]=_pthread_self;function _pthread_create(pthread_ptr,attr,start_routine,arg){if(typeof SharedArrayBuffer==="undefined"){err("Current environment does not support SharedArrayBuffer, pthreads are not available!");return 6}if(!pthread_ptr){err("pthread_create called with a null thread pointer!");return 28}var transferList=[];var error=0;if(ENVIRONMENT_IS_PTHREAD&&(transferList.length===0||error)){return _emscripten_sync_run_in_main_thread_4(687865856,pthread_ptr,attr,start_routine,arg)}var stackSize=0;var stackBase=0;var detached=0;var schedPolicy=0;var schedPrio=0;if(attr){stackSize=GROWABLE_HEAP_I32()[attr>>2];stackSize+=81920;stackBase=GROWABLE_HEAP_I32()[attr+8>>2];detached=GROWABLE_HEAP_I32()[attr+12>>2]!==0;var inheritSched=GROWABLE_HEAP_I32()[attr+16>>2]===0;if(inheritSched){var prevSchedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];var prevSchedPrio=GROWABLE_HEAP_I32()[attr+24>>2];var parentThreadPtr=PThread.currentProxiedOperationCallerThread?PThread.currentProxiedOperationCallerThread:_pthread_self();_pthread_getschedparam(parentThreadPtr,attr+20,attr+24);schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];GROWABLE_HEAP_I32()[attr+20>>2]=prevSchedPolicy;GROWABLE_HEAP_I32()[attr+24>>2]=prevSchedPrio;}else{schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];}}else{stackSize=2097152;}var allocatedOwnStack=stackBase==0;if(allocatedOwnStack){stackBase=_memalign(16,stackSize);}else{stackBase-=stackSize;assert(stackBase>0);}var threadInfoStruct=_malloc(232);for(var i=0;i<232>>2;++i)GROWABLE_HEAP_U32()[(threadInfoStruct>>2)+i]=0;GROWABLE_HEAP_I32()[pthread_ptr>>2]=threadInfoStruct;GROWABLE_HEAP_I32()[threadInfoStruct+12>>2]=threadInfoStruct;var headPtr=threadInfoStruct+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var threadParams={stackBase:stackBase,stackSize:stackSize,allocatedOwnStack:allocatedOwnStack,schedPolicy:schedPolicy,schedPrio:schedPrio,detached:detached,startRoutine:start_routine,pthread_ptr:threadInfoStruct,parent_pthread_ptr:_pthread_self(),arg:arg,transferList:transferList};if(ENVIRONMENT_IS_PTHREAD){threadParams.cmd="spawnThread";postMessage(threadParams,transferList);}else{__spawn_thread(threadParams);}return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}function _sysconf(name){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(6,1,name);switch(name){case 30:return 16384;case 85:var maxHeapSize=1073741824;return maxHeapSize/16384;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:case 79:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return -1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}setErrNo(28);return -1}if(!ENVIRONMENT_IS_PTHREAD)PThread.initMainThreadBlock();else PThread.initWorker();var GLctx;GL.init();var proxiedFunctionTable=[null,_atexit,_emscripten_set_canvas_element_size_main_thread,_fd_close,_fd_seek,_fd_write,_sysconf];var asmLibraryArg={"__assert_fail":___assert_fail,"__call_main":___call_main,"__handle_stack_overflow":___handle_stack_overflow,"_emscripten_notify_thread_queue":__emscripten_notify_thread_queue,"abort":_abort,"emscripten_conditional_set_current_thread_status":_emscripten_conditional_set_current_thread_status,"emscripten_futex_wait":_emscripten_futex_wait,"emscripten_futex_wake":_emscripten_futex_wake,"emscripten_get_now":_emscripten_get_now,"emscripten_is_main_browser_thread":_emscripten_is_main_browser_thread,"emscripten_is_main_runtime_thread":_emscripten_is_main_runtime_thread,"emscripten_memcpy_big":_emscripten_memcpy_big,"emscripten_receive_on_main_thread_js":_emscripten_receive_on_main_thread_js,"emscripten_resize_heap":_emscripten_resize_heap,"emscripten_set_canvas_element_size":_emscripten_set_canvas_element_size,"emscripten_set_current_thread_status":_emscripten_set_current_thread_status,"emscripten_set_thread_name":_emscripten_set_thread_name,"emscripten_webgl_create_context":_emscripten_webgl_create_context,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"initPthreadsJS":initPthreadsJS,"memory":wasmMemory||Module["wasmMemory"],"pthread_cleanup_pop":_pthread_cleanup_pop,"pthread_cleanup_push":_pthread_cleanup_push,"pthread_create":_pthread_create,"pthread_self":_pthread_self,"roundf":_roundf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__wasm_call_ctors"].apply(null,arguments)};var _init=Module["_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["init"].apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["register_tensor"].apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose_data"].apply(null,arguments)};var _dispose=Module["_dispose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose"].apply(null,arguments)};var _Abs=Module["_Abs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Abs"].apply(null,arguments)};var _Add=Module["_Add"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Add"].apply(null,arguments)};var _AddN=Module["_AddN"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AddN"].apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ArgMax"].apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AvgPool"].apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["BatchMatMul"].apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ClipByValue"].apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2D"].apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2DBackpropInput"].apply(null,arguments)};var _Cos=Module["_Cos"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Cos"].apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["CropAndResize"].apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["DepthwiseConv2dNative"].apply(null,arguments)};var _Div=Module["_Div"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Div"].apply(null,arguments)};var _Equal=Module["_Equal"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Equal"].apply(null,arguments)};var _Exp=Module["_Exp"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Exp"].apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FloorDiv"].apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedBatchNorm"].apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedConv2D"].apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedDepthwiseConv2D"].apply(null,arguments)};var _Gather=Module["_Gather"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Gather"].apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GatherNd"].apply(null,arguments)};var _Greater=Module["_Greater"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Greater"].apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GreaterEqual"].apply(null,arguments)};var _Less=Module["_Less"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Less"].apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LessEqual"].apply(null,arguments)};var _Log=Module["_Log"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Log"].apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LogicalAnd"].apply(null,arguments)};var _Max=Module["_Max"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Max"].apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["MaxPool"].apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Maximum"].apply(null,arguments)};var _Min=Module["_Min"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Min"].apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Minimum"].apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Multiply"].apply(null,arguments)};var _Negate=Module["_Negate"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Negate"].apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV3"].apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV4"].apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV5"].apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NotEqual"].apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["OneHot"].apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["PadV2"].apply(null,arguments)};var _Pow=Module["_Pow"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Pow"].apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Prelu"].apply(null,arguments)};var _Relu=Module["_Relu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu"].apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu6"].apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ResizeBilinear"].apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Reverse"].apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["RotateWithOffset"].apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Rsqrt"].apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ScatterNd"].apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["SelectV2"].apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sigmoid"].apply(null,arguments)};var _Sin=Module["_Sin"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sin"].apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Softmax"].apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sqrt"].apply(null,arguments)};var _Square=Module["_Square"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Square"].apply(null,arguments)};var _Sub=Module["_Sub"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sub"].apply(null,arguments)};var _Sum=Module["_Sum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sum"].apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tanh"].apply(null,arguments)};var _Tile=Module["_Tile"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tile"].apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Transpose"].apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["_FusedMatMul"].apply(null,arguments)};var _malloc=Module["_malloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["malloc"].apply(null,arguments)};var _free=Module["_free"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["free"].apply(null,arguments)};var ___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__em_js__initPthreadsJS"].apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__errno_location"].apply(null,arguments)};var _emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_get_global_libc"].apply(null,arguments)};var _memalign=Module["_memalign"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["memalign"].apply(null,arguments)};var ___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__pthread_tsd_run_dtors"].apply(null,arguments)};var _emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_current_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_register_main_browser_thread_id"].apply(null,arguments)};var _emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_browser_thread_id"].apply(null,arguments)};var _emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_0"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_1"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_2"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_xprintf_varargs"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_3"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_4"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_5"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_6"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_7"].apply(null,arguments)};var _emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_run_in_main_runtime_thread_js"].apply(null,arguments)};var _emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_queue_on_thread_"].apply(null,arguments)};var _emscripten_tls_init=Module["_emscripten_tls_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_tls_init"].apply(null,arguments)};var ___set_stack_limit=Module["___set_stack_limit"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__set_stack_limit"].apply(null,arguments)};var stackSave=Module["stackSave"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackSave"].apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackAlloc"].apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackRestore"].apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_vi"].apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_v"].apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_ii"].apply(null,arguments)};Module["asm"]=asm;if(!Object.getOwnPropertyDescriptor(Module,"intArrayFromString"))Module["intArrayFromString"]=function(){abort("'intArrayFromString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"intArrayToString"))Module["intArrayToString"]=function(){abort("'intArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ccall"))Module["ccall"]=function(){abort("'ccall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["cwrap"]=cwrap;if(!Object.getOwnPropertyDescriptor(Module,"setValue"))Module["setValue"]=function(){abort("'setValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getValue"))Module["getValue"]=function(){abort("'getValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocate"))Module["allocate"]=function(){abort("'allocate' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getMemory"))Module["getMemory"]=function(){abort("'getMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ArrayToString"))Module["UTF8ArrayToString"]=function(){abort("'UTF8ArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ToString"))Module["UTF8ToString"]=function(){abort("'UTF8ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8Array"))Module["stringToUTF8Array"]=function(){abort("'stringToUTF8Array' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8"))Module["stringToUTF8"]=function(){abort("'stringToUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF8"))Module["lengthBytesUTF8"]=function(){abort("'lengthBytesUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreRun"))Module["addOnPreRun"]=function(){abort("'addOnPreRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnInit"))Module["addOnInit"]=function(){abort("'addOnInit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreMain"))Module["addOnPreMain"]=function(){abort("'addOnPreMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnExit"))Module["addOnExit"]=function(){abort("'addOnExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPostRun"))Module["addOnPostRun"]=function(){abort("'addOnPostRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeStringToMemory"))Module["writeStringToMemory"]=function(){abort("'writeStringToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeArrayToMemory"))Module["writeArrayToMemory"]=function(){abort("'writeArrayToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeAsciiToMemory"))Module["writeAsciiToMemory"]=function(){abort("'writeAsciiToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addRunDependency"))Module["addRunDependency"]=function(){abort("'addRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"removeRunDependency"))Module["removeRunDependency"]=function(){abort("'removeRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createFolder"))Module["FS_createFolder"]=function(){abort("'FS_createFolder' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPath"))Module["FS_createPath"]=function(){abort("'FS_createPath' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDataFile"))Module["FS_createDataFile"]=function(){abort("'FS_createDataFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPreloadedFile"))Module["FS_createPreloadedFile"]=function(){abort("'FS_createPreloadedFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLazyFile"))Module["FS_createLazyFile"]=function(){abort("'FS_createLazyFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLink"))Module["FS_createLink"]=function(){abort("'FS_createLink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDevice"))Module["FS_createDevice"]=function(){abort("'FS_createDevice' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_unlink"))Module["FS_unlink"]=function(){abort("'FS_unlink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"dynamicAlloc"))Module["dynamicAlloc"]=function(){abort("'dynamicAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadDynamicLibrary"))Module["loadDynamicLibrary"]=function(){abort("'loadDynamicLibrary' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadWebAssemblyModule"))Module["loadWebAssemblyModule"]=function(){abort("'loadWebAssemblyModule' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getLEB"))Module["getLEB"]=function(){abort("'getLEB' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFunctionTables"))Module["getFunctionTables"]=function(){abort("'getFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"alignFunctionTables"))Module["alignFunctionTables"]=function(){abort("'alignFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"registerFunctions"))Module["registerFunctions"]=function(){abort("'registerFunctions' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addFunction"))Module["addFunction"]=function(){abort("'addFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"removeFunction"))Module["removeFunction"]=function(){abort("'removeFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFuncWrapper"))Module["getFuncWrapper"]=function(){abort("'getFuncWrapper' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"prettyPrint"))Module["prettyPrint"]=function(){abort("'prettyPrint' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"makeBigInt"))Module["makeBigInt"]=function(){abort("'makeBigInt' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"dynCall"))Module["dynCall"]=function(){abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getCompilerSetting"))Module["getCompilerSetting"]=function(){abort("'getCompilerSetting' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"print"))Module["print"]=function(){abort("'print' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"printErr"))Module["printErr"]=function(){abort("'printErr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getTempRet0"))Module["getTempRet0"]=function(){abort("'getTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setTempRet0"))Module["setTempRet0"]=function(){abort("'setTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"callMain"))Module["callMain"]=function(){abort("'callMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"abort"))Module["abort"]=function(){abort("'abort' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToNewUTF8"))Module["stringToNewUTF8"]=function(){abort("'stringToNewUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscripten_realloc_buffer"))Module["emscripten_realloc_buffer"]=function(){abort("'emscripten_realloc_buffer' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ENV"))Module["ENV"]=function(){abort("'ENV' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setjmpId"))Module["setjmpId"]=function(){abort("'setjmpId' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_CODES"))Module["ERRNO_CODES"]=function(){abort("'ERRNO_CODES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_MESSAGES"))Module["ERRNO_MESSAGES"]=function(){abort("'ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setErrNo"))Module["setErrNo"]=function(){abort("'setErrNo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"DNS"))Module["DNS"]=function(){abort("'DNS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GAI_ERRNO_MESSAGES"))Module["GAI_ERRNO_MESSAGES"]=function(){abort("'GAI_ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Protocols"))Module["Protocols"]=function(){abort("'Protocols' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Sockets"))Module["Sockets"]=function(){abort("'Sockets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UNWIND_CACHE"))Module["UNWIND_CACHE"]=function(){abort("'UNWIND_CACHE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readAsmConstArgs"))Module["readAsmConstArgs"]=function(){abort("'readAsmConstArgs' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_q"))Module["jstoi_q"]=function(){abort("'jstoi_q' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_s"))Module["jstoi_s"]=function(){abort("'jstoi_s' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"reallyNegative"))Module["reallyNegative"]=function(){abort("'reallyNegative' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"formatString"))Module["formatString"]=function(){abort("'formatString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH"))Module["PATH"]=function(){abort("'PATH' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH_FS"))Module["PATH_FS"]=function(){abort("'PATH_FS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SYSCALLS"))Module["SYSCALLS"]=function(){abort("'SYSCALLS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMmap2"))Module["syscallMmap2"]=function(){abort("'syscallMmap2' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMunmap"))Module["syscallMunmap"]=function(){abort("'syscallMunmap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"flush_NO_FILESYSTEM"))Module["flush_NO_FILESYSTEM"]=function(){abort("'flush_NO_FILESYSTEM' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"JSEvents"))Module["JSEvents"]=function(){abort("'JSEvents' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"specialHTMLTargets"))Module["specialHTMLTargets"]=function(){abort("'specialHTMLTargets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangle"))Module["demangle"]=function(){abort("'demangle' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangleAll"))Module["demangleAll"]=function(){abort("'demangleAll' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jsStackTrace"))Module["jsStackTrace"]=function(){abort("'jsStackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getEnvStrings"))Module["getEnvStrings"]=function(){abort("'getEnvStrings' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64"))Module["writeI53ToI64"]=function(){abort("'writeI53ToI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Clamped"))Module["writeI53ToI64Clamped"]=function(){abort("'writeI53ToI64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Signaling"))Module["writeI53ToI64Signaling"]=function(){abort("'writeI53ToI64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Clamped"))Module["writeI53ToU64Clamped"]=function(){abort("'writeI53ToU64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Signaling"))Module["writeI53ToU64Signaling"]=function(){abort("'writeI53ToU64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromI64"))Module["readI53FromI64"]=function(){abort("'readI53FromI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromU64"))Module["readI53FromU64"]=function(){abort("'readI53FromU64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertI32PairToI53"))Module["convertI32PairToI53"]=function(){abort("'convertI32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertU32PairToI53"))Module["convertU32PairToI53"]=function(){abort("'convertU32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Browser"))Module["Browser"]=function(){abort("'Browser' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GL"))Module["GL"]=function(){abort("'GL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGet"))Module["emscriptenWebGLGet"]=function(){abort("'emscriptenWebGLGet' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetTexPixelData"))Module["emscriptenWebGLGetTexPixelData"]=function(){abort("'emscriptenWebGLGetTexPixelData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetUniform"))Module["emscriptenWebGLGetUniform"]=function(){abort("'emscriptenWebGLGetUniform' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetVertexAttrib"))Module["emscriptenWebGLGetVertexAttrib"]=function(){abort("'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AL"))Module["AL"]=function(){abort("'AL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_unicode"))Module["SDL_unicode"]=function(){abort("'SDL_unicode' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_ttfContext"))Module["SDL_ttfContext"]=function(){abort("'SDL_ttfContext' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_audio"))Module["SDL_audio"]=function(){abort("'SDL_audio' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL"))Module["SDL"]=function(){abort("'SDL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_gfx"))Module["SDL_gfx"]=function(){abort("'SDL_gfx' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLUT"))Module["GLUT"]=function(){abort("'GLUT' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"EGL"))Module["EGL"]=function(){abort("'EGL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW_Window"))Module["GLFW_Window"]=function(){abort("'GLFW_Window' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW"))Module["GLFW"]=function(){abort("'GLFW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLEW"))Module["GLEW"]=function(){abort("'GLEW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"IDBStore"))Module["IDBStore"]=function(){abort("'IDBStore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"runAndAbortIfError"))Module["runAndAbortIfError"]=function(){abort("'runAndAbortIfError' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["PThread"]=PThread;if(!Object.getOwnPropertyDescriptor(Module,"establishStackSpace"))Module["establishStackSpace"]=function(){abort("'establishStackSpace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getNoExitRuntime"))Module["getNoExitRuntime"]=function(){abort("'getNoExitRuntime' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"resetPrototype"))Module["resetPrototype"]=function(){abort("'resetPrototype' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"warnOnce"))Module["warnOnce"]=function(){abort("'warnOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackSave"))Module["stackSave"]=function(){abort("'stackSave' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackRestore"))Module["stackRestore"]=function(){abort("'stackRestore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackAlloc"))Module["stackAlloc"]=function(){abort("'stackAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AsciiToString"))Module["AsciiToString"]=function(){abort("'AsciiToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToAscii"))Module["stringToAscii"]=function(){abort("'stringToAscii' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF16ToString"))Module["UTF16ToString"]=function(){abort("'UTF16ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF16"))Module["stringToUTF16"]=function(){abort("'stringToUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF16"))Module["lengthBytesUTF16"]=function(){abort("'lengthBytesUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF32ToString"))Module["UTF32ToString"]=function(){abort("'UTF32ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF32"))Module["stringToUTF32"]=function(){abort("'stringToUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF32"))Module["lengthBytesUTF32"]=function(){abort("'lengthBytesUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8"))Module["allocateUTF8"]=function(){abort("'allocateUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8OnStack"))Module["allocateUTF8OnStack"]=function(){abort("'allocateUTF8OnStack' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["writeStackCookie"]=writeStackCookie;Module["checkStackCookie"]=checkStackCookie;Module["abortStackOverflow"]=abortStackOverflow;Module["PThread"]=PThread;Module["_pthread_self"]=_pthread_self;Module["wasmMemory"]=wasmMemory;Module["ExitStatus"]=ExitStatus;if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NORMAL"))Object.defineProperty(Module,"ALLOC_NORMAL",{configurable:true,get:function(){abort("'ALLOC_NORMAL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_STACK"))Object.defineProperty(Module,"ALLOC_STACK",{configurable:true,get:function(){abort("'ALLOC_STACK' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_DYNAMIC"))Object.defineProperty(Module,"ALLOC_DYNAMIC",{configurable:true,get:function(){abort("'ALLOC_DYNAMIC' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NONE"))Object.defineProperty(Module,"ALLOC_NONE",{configurable:true,get:function(){abort("'ALLOC_NONE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}writeStackCookie();preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();assert(!Module["_main"],'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}checkStackCookie();}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}if(!ENVIRONMENT_IS_PTHREAD)noExitRuntime=true;if(!ENVIRONMENT_IS_PTHREAD)run(); + + + return WasmBackendModule + } + ); + })(); + module.exports = WasmBackendModule; + }); + + const wasmWorkerContents = 'var threadInfoStruct=0;var selfThreadId=0;var parentThreadId=0;var Module={};function assert(condition,text){if(!condition)abort("Assertion failed: "+text)}function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:selfThreadId})}var out=function(){throw"out() is not defined in worker.js."};var err=threadPrintErr;this.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);Module["wasmModule"]=null;receiveInstance(instance);return instance.exports};this.onmessage=function(e){try{if(e.data.cmd==="load"){Module["DYNAMIC_BASE"]=e.data.DYNAMIC_BASE;Module["DYNAMICTOP_PTR"]=e.data.DYNAMICTOP_PTR;Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob==="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}Module=WasmBackendModule(Module);postMessage({"cmd":"loaded"})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;threadInfoStruct=e.data.threadInfoStruct;Module["__register_pthread_ptr"](threadInfoStruct,0,0);selfThreadId=e.data.selfThreadId;parentThreadId=e.data.parentThreadId;var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;assert(threadInfoStruct);assert(selfThreadId);assert(parentThreadId);assert(top!=0);assert(max!=0);assert(top>max);Module["establishStackSpace"](top,max);Module["_emscripten_tls_init"]();Module["writeStackCookie"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].setThreadStatus(Module["_pthread_self"](),1);try{var result=Module["dynCall_ii"](e.data.start_routine,e.data.arg);Module["checkStackCookie"]();if(!Module["getNoExitRuntime"]())Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){Atomics.store(Module["HEAPU32"],threadInfoStruct+4>>2,ex instanceof Module["ExitStatus"]?ex.status:-2);Atomics.store(Module["HEAPU32"],threadInfoStruct+0>>2,1);if(typeof Module["_emscripten_futex_wake"]!=="function"){err("Thread Initialisation failed.");throw ex}Module["_emscripten_futex_wake"](threadInfoStruct+0,2147483647);if(!(ex instanceof Module["ExitStatus"]))throw ex}else{err("Pthread 0x"+threadInfoStruct.toString(16)+" completed its pthread main entry point with an unwind, keeping the pthread worker alive for asynchronous operation.")}}}else if(e.data.cmd==="cancel"){if(threadInfoStruct){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(threadInfoStruct){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex.stack)err(ex.stack);throw ex}};if(typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string"){self={location:{href:__filename}};var onmessage=this.onmessage;var nodeWorkerThreads=require("worker_threads");Worker=nodeWorkerThreads.Worker;var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var nodeFS=require("fs");var nodeRead=function(filename){return nodeFS.readFileSync(filename,"utf8")};function globalEval(x){global.require=require;global.Module=Module;eval.call(null,x)}importScripts=function(f){globalEval(nodeRead(f))};postMessage=function(msg){parentPort.postMessage(msg)};if(typeof performance==="undefined"){performance={now:function(){return Date.now()}}}}'; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -3236,8 +3236,8 @@ // wasmFactory(factoryConfig); const wasm = tfjsBackendWasmThreaded(factoryConfig); const voidReturnType = null; - // wasm.mainScriptUrlOrBlob = - // new Blob([emscriptenContents], {type: 'text/javascript'}); + wasm.mainScriptUrlOrBlob = new Blob([`var _scriptDir = undefined; var WasmBackendModule = ` + + tfjsBackendWasmThreaded.toString()], { type: 'text/javascript' }); // Using the tfjs namespace to avoid conflict with emscripten's API. wasm.tfjs = { init: wasm.cwrap('init', null, []), @@ -3304,17 +3304,17 @@ } wasmPath = path; customFetch = usePlatformFetch; - } - + } + /** @license See the LICENSE file. */ // This code is auto-generated, do not modify this file! - const version = '0.0.0'; - - exports.BackendWasm = BackendWasm; - exports.setWasmPath = setWasmPath; - exports.version_wasm = version; - - Object.defineProperty(exports, '__esModule', { value: true }); - -}))); -//# sourceMappingURL=tf-backend-wasm.js.map + const version = '0.0.0'; + + exports.BackendWasm = BackendWasm; + exports.setWasmPath = setWasmPath; + exports.version_wasm = version; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); +//# sourceMappingURL=tf-backend-wasm.js.map diff --git a/e2e/benchmarks/tf-core.js b/e2e/benchmarks/tf-core.js new file mode 100644 index 00000000000..3490af9c005 --- /dev/null +++ b/e2e/benchmarks/tf-core.js @@ -0,0 +1,32359 @@ +/** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = global || self, factory(global.tf = global.tf || {})); +}(this, (function (exports) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + function __awaiter(thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + } + + function __generator(thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } + } + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // Expects flags from URL in the format ?tfjsflags=FLAG1:1,FLAG2:true. + var TENSORFLOWJS_FLAGS_PREFIX = 'tfjsflags'; + /** + * The environment contains evaluated flags as well as the registered platform. + * This is always used as a global singleton and can be retrieved with + * `tf.env()`. + */ + /** @doc {heading: 'Environment'} */ + var Environment = /** @class */ (function () { + // tslint:disable-next-line: no-any + function Environment(global) { + this.global = global; + this.flags = {}; + this.flagRegistry = {}; + this.urlFlags = {}; + this.populateURLFlags(); + } + Environment.prototype.setPlatform = function (platformName, platform) { + if (this.platform != null) { + console.warn("Platform " + this.platformName + " has already been set. " + + ("Overwriting the platform with " + platform + ".")); + } + this.platformName = platformName; + this.platform = platform; + }; + Environment.prototype.registerFlag = function (flagName, evaluationFn, setHook) { + this.flagRegistry[flagName] = { evaluationFn: evaluationFn, setHook: setHook }; + // Override the flag value from the URL. This has to happen here because the + // environment is initialized before flags get registered. + if (this.urlFlags[flagName] != null) { + var flagValue = this.urlFlags[flagName]; + console.warn("Setting feature override from URL " + flagName + ": " + flagValue + "."); + this.set(flagName, flagValue); + } + }; + Environment.prototype.getAsync = function (flagName) { + return __awaiter(this, void 0, void 0, function () { + var _a, _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + if (flagName in this.flags) { + return [2 /*return*/, this.flags[flagName]]; + } + _a = this.flags; + _b = flagName; + return [4 /*yield*/, this.evaluateFlag(flagName)]; + case 1: + _a[_b] = _c.sent(); + return [2 /*return*/, this.flags[flagName]]; + } + }); + }); + }; + Environment.prototype.get = function (flagName) { + if (flagName in this.flags) { + return this.flags[flagName]; + } + var flagValue = this.evaluateFlag(flagName); + if (flagValue instanceof Promise) { + throw new Error("Flag " + flagName + " cannot be synchronously evaluated. " + + "Please use getAsync() instead."); + } + this.flags[flagName] = flagValue; + return this.flags[flagName]; + }; + Environment.prototype.getNumber = function (flagName) { + return this.get(flagName); + }; + Environment.prototype.getBool = function (flagName) { + return this.get(flagName); + }; + Environment.prototype.getFlags = function () { + return this.flags; + }; + Object.defineProperty(Environment.prototype, "features", { + // For backwards compatibility. + get: function () { + return this.flags; + }, + enumerable: true, + configurable: true + }); + Environment.prototype.set = function (flagName, value) { + if (this.flagRegistry[flagName] == null) { + throw new Error("Cannot set flag " + flagName + " as it has not been registered."); + } + this.flags[flagName] = value; + if (this.flagRegistry[flagName].setHook != null) { + this.flagRegistry[flagName].setHook(value); + } + }; + Environment.prototype.evaluateFlag = function (flagName) { + if (this.flagRegistry[flagName] == null) { + throw new Error("Cannot evaluate flag '" + flagName + "': no evaluation function found."); + } + return this.flagRegistry[flagName].evaluationFn(); + }; + Environment.prototype.setFlags = function (flags) { + this.flags = Object.assign({}, flags); + }; + Environment.prototype.reset = function () { + this.flags = {}; + this.urlFlags = {}; + this.populateURLFlags(); + }; + Environment.prototype.populateURLFlags = function () { + var _this = this; + if (typeof this.global === 'undefined' || + typeof this.global.location === 'undefined' || + typeof this.global.location.search === 'undefined') { + return; + } + var urlParams = getQueryParams(this.global.location.search); + if (TENSORFLOWJS_FLAGS_PREFIX in urlParams) { + var keyValues = urlParams[TENSORFLOWJS_FLAGS_PREFIX].split(','); + keyValues.forEach(function (keyValue) { + var _a = keyValue.split(':'), key = _a[0], value = _a[1]; + _this.urlFlags[key] = parseValue(key, value); + }); + } + }; + return Environment; + }()); + function getQueryParams(queryString) { + var params = {}; + queryString.replace(/[?&]([^=?&]+)(?:=([^&]*))?/g, function (s) { + var t = []; + for (var _i = 1; _i < arguments.length; _i++) { + t[_i - 1] = arguments[_i]; + } + decodeParam(params, t[0], t[1]); + return t.join('='); + }); + return params; + } + function decodeParam(params, name, value) { + params[decodeURIComponent(name)] = decodeURIComponent(value || ''); + } + function parseValue(flagName, value) { + value = value.toLowerCase(); + if (value === 'true' || value === 'false') { + return value === 'true'; + } + else if ("" + +value === value) { + return +value; + } + throw new Error("Could not parse value flag value " + value + " for flag " + flagName + "."); + } + /** + * Returns the current environment (a global singleton). + * + * The environment object contains the evaluated feature values as well as the + * active platform. + */ + /** @doc {heading: 'Environment'} */ + function env() { + return exports.ENV; + } + exports.ENV = null; + function setEnvironmentGlobal(environment) { + exports.ENV = environment; + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // Note that the identifier globalNameSpace is scoped to this module, but will + // always resolve to the same global object regardless of how the module is + // resolved. + // tslint:disable-next-line:no-any + var globalNameSpace; + // tslint:disable-next-line:no-any + function getGlobalNamespace() { + if (globalNameSpace == null) { + // tslint:disable-next-line:no-any + var ns = void 0; + if (typeof (window) !== 'undefined') { + ns = window; + } + else if (typeof (global) !== 'undefined') { + ns = global; + } + else if (typeof (process) !== 'undefined') { + ns = process; + } + else if (typeof (self) !== 'undefined') { + ns = self; + } + else { + throw new Error('Could not find a global object'); + } + globalNameSpace = ns; + } + return globalNameSpace; + } + // tslint:disable-next-line:no-any + function getGlobalMap() { + var ns = getGlobalNamespace(); + if (ns._tfGlobals == null) { + ns._tfGlobals = new Map(); + } + return ns._tfGlobals; + } + /** + * Returns a globally accessible 'singleton' object. + * + * @param key the name of the object + * @param init a function to initialize to initialize this object + * the first time it is fetched. + */ + function getGlobal(key, init) { + var globalMap = getGlobalMap(); + if (globalMap.has(key)) { + return globalMap.get(key); + } + else { + var singleton = init(); + globalMap.set(key, singleton); + return globalMap.get(key); + } + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var kernelRegistry = getGlobal('kernelRegistry', function () { return new Map(); }); + var gradRegistry = getGlobal('gradRegistry', function () { return new Map(); }); + /** + * Returns the kernel function (code) associated with the provided names. + * + * @param kernelName The official name of the kernel. + * @param backendName The official name of the backend. + */ + function getKernel(kernelName, backendName) { + var key = makeKey(kernelName, backendName); + return kernelRegistry.get(key); + } + /** + * Returns the registered gradient info associated with the provided kernel. + * @param kernelName The official TF kernel name. + */ + function getGradient(kernelName) { + return gradRegistry.get(kernelName); + } + function getKernelsForBackend(backendName) { + var it = kernelRegistry.entries(); + var result = []; + while (true) { + var _a = it.next(), done = _a.done, value = _a.value; + if (done) { + break; + } + var key = value[0], config = value[1]; + var backend = key.split('_')[0]; + if (backend === backendName) { + result.push(config); + } + } + return result; + } + /** + * Registers the function (forward pass) for the kernel in a global registry. + * + * @param config A config object with the following properties: + * - `kernelName` The official name of the kernel. + * - `backendName` The official name of the backend. + * - `kernelFunc` The function to run during the forward pass of the kernel. + * - `setupFunc` Optional. Gets called once, after the backend initializes. + * - `disposeFunc` Optional. Gets called once, right before the backend is + * disposed. + */ + function registerKernel(config) { + var kernelName = config.kernelName, backendName = config.backendName; + var key = makeKey(kernelName, backendName); + if (kernelRegistry.has(key)) { + console.warn("The kernel '" + kernelName + "' for backend " + + ("'" + backendName + "' is already registered")); + } + kernelRegistry.set(key, config); + } + /** + * Registers a gradient function for a given kernel in the global registry, + * to be used during the back-propagation of that kernel. + * + * @param config An object with the following properties: + * - `kernelName` The name of the kernel that the gradient function is for. + * - `gradFunc` The function to run during back-propagation. + */ + function registerGradient(config) { + var kernelName = config.kernelName; + if (gradRegistry.has(kernelName)) { + // TODO (yassogba) after 3.0 assess whether we need to keep this gated + // to debug mode. + if (env().getBool('DEBUG')) { + console.warn("Overriding the gradient for '" + kernelName + "'"); + } + } + gradRegistry.set(kernelName, config); + } + /** + * Removes the kernel function from the registry. + * + * @param kernelName The official name of the kernel. + * @param backendName The official name of the backend. + * + */ + function unregisterKernel(kernelName, backendName) { + var key = makeKey(kernelName, backendName); + if (!kernelRegistry.has(key)) { + throw new Error("The kernel '" + kernelName + "' for backend " + + ("'" + backendName + "' is not registered")); + } + kernelRegistry.delete(key); + } + /** Removes the registered gradient from the global registry. */ + function unregisterGradient(kernelName) { + if (!gradRegistry.has(kernelName)) { + throw new Error("The gradient '" + kernelName + "' for backend is not registered"); + } + gradRegistry.delete(kernelName); + } + function makeKey(kernelName, backendName) { + return backendName + "_" + kernelName; + } + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Shuffles the array in-place using Fisher-Yates algorithm. + * + * ```js + * const a = [1, 2, 3, 4, 5]; + * tf.util.shuffle(a); + * console.log(a); + * ``` + * + * @param array The array to shuffle in-place. + */ + /** @doc {heading: 'Util', namespace: 'util'} */ + // tslint:disable-next-line:no-any + function shuffle(array) { + var counter = array.length; + var temp = 0; + var index = 0; + // While there are elements in the array + while (counter > 0) { + // Pick a random index + index = (Math.random() * counter) | 0; + // Decrease counter by 1 + counter--; + // And swap the last element with it + temp = array[counter]; + array[counter] = array[index]; + array[index] = temp; + } + } + /** Clamps a value to a specified range. */ + function clamp(min, x, max) { + return Math.max(min, Math.min(x, max)); + } + function nearestLargerEven(val) { + return val % 2 === 0 ? val : val + 1; + } + function sum(arr) { + var sum = 0; + for (var i = 0; i < arr.length; i++) { + sum += arr[i]; + } + return sum; + } + /** + * Returns a sample from a uniform [a, b) distribution. + * + * @param a The minimum support (inclusive). + * @param b The maximum support (exclusive). + * @return A pseudorandom number on the half-open interval [a,b). + */ + function randUniform(a, b) { + var r = Math.random(); + return (b * r) + (1 - r) * a; + } + /** Returns the squared Euclidean distance between two vectors. */ + function distSquared(a, b) { + var result = 0; + for (var i = 0; i < a.length; i++) { + var diff = Number(a[i]) - Number(b[i]); + result += diff * diff; + } + return result; + } + /** + * Asserts that the expression is true. Otherwise throws an error with the + * provided message. + * + * ```js + * const x = 2; + * tf.util.assert(x === 2, 'x is not 2'); + * ``` + * + * @param expr The expression to assert (as a boolean). + * @param msg A function that returns the message to report when throwing an + * error. We use a function for performance reasons. + */ + /** @doc {heading: 'Util', namespace: 'util'} */ + function assert(expr, msg) { + if (!expr) { + throw new Error(typeof msg === 'string' ? msg : msg()); + } + } + function assertShapesMatch(shapeA, shapeB, errorMessagePrefix) { + if (errorMessagePrefix === void 0) { errorMessagePrefix = ''; } + assert(arraysEqual(shapeA, shapeB), function () { return errorMessagePrefix + (" Shapes " + shapeA + " and " + shapeB + " must match"); }); + } + function assertNonNull(a) { + assert(a != null, function () { return "The input to the tensor constructor must be a non-null value."; }); + } + // NOTE: We explicitly type out what T extends instead of any so that + // util.flatten on a nested array of number doesn't try to infer T as a + // number[][], causing us to explicitly type util.flatten(). + /** + * Flattens an arbitrarily nested array. + * + * ```js + * const a = [[1, 2], [3, 4], [5, [6, [7]]]]; + * const flat = tf.util.flatten(a); + * console.log(flat); + * ``` + * + * @param arr The nested array to flatten. + * @param result The destination array which holds the elements. + * @param skipTypedArray If true, avoids flattening the typed arrays. Defaults + * to false. + */ + /** @doc {heading: 'Util', namespace: 'util'} */ + function flatten(arr, result, skipTypedArray) { + if (result === void 0) { result = []; } + if (skipTypedArray === void 0) { skipTypedArray = false; } + if (result == null) { + result = []; + } + if (Array.isArray(arr) || isTypedArray(arr) && !skipTypedArray) { + for (var i = 0; i < arr.length; ++i) { + flatten(arr[i], result, skipTypedArray); + } + } + else { + result.push(arr); + } + return result; + } + /** + * Returns the size (number of elements) of the tensor given its shape. + * + * ```js + * const shape = [3, 4, 2]; + * const size = tf.util.sizeFromShape(shape); + * console.log(size); + * ``` + */ + /** @doc {heading: 'Util', namespace: 'util'} */ + function sizeFromShape(shape) { + if (shape.length === 0) { + // Scalar. + return 1; + } + var size = shape[0]; + for (var i = 1; i < shape.length; i++) { + size *= shape[i]; + } + return size; + } + function isScalarShape(shape) { + return shape.length === 0; + } + function arraysEqual(n1, n2) { + if (n1 === n2) { + return true; + } + if (n1 == null || n2 == null) { + return false; + } + if (n1.length !== n2.length) { + return false; + } + for (var i = 0; i < n1.length; i++) { + if (n1[i] !== n2[i]) { + return false; + } + } + return true; + } + function isInt(a) { + return a % 1 === 0; + } + function tanh(x) { + // tslint:disable-next-line:no-any + if (Math.tanh != null) { + // tslint:disable-next-line:no-any + return Math.tanh(x); + } + if (x === Infinity) { + return 1; + } + else if (x === -Infinity) { + return -1; + } + else { + var e2x = Math.exp(2 * x); + return (e2x - 1) / (e2x + 1); + } + } + function sizeToSquarishShape(size) { + var width = Math.ceil(Math.sqrt(size)); + return [width, Math.ceil(size / width)]; + } + /** + * Creates a new array with randomized indicies to a given quantity. + * + * ```js + * const randomTen = tf.util.createShuffledIndices(10); + * console.log(randomTen); + * ``` + * + * @param number Quantity of how many shuffled indicies to create. + */ + /** @doc {heading: 'Util', namespace: 'util'} */ + function createShuffledIndices(n) { + var shuffledIndices = new Uint32Array(n); + for (var i = 0; i < n; ++i) { + shuffledIndices[i] = i; + } + shuffle(shuffledIndices); + return shuffledIndices; + } + function rightPad(a, size) { + if (size <= a.length) { + return a; + } + return a + ' '.repeat(size - a.length); + } + function repeatedTry(checkFn, delayFn, maxCounter) { + if (delayFn === void 0) { delayFn = function (counter) { return 0; }; } + return new Promise(function (resolve, reject) { + var tryCount = 0; + var tryFn = function () { + if (checkFn()) { + resolve(); + return; + } + tryCount++; + var nextBackoff = delayFn(tryCount); + if (maxCounter != null && tryCount >= maxCounter) { + reject(); + return; + } + setTimeout(tryFn, nextBackoff); + }; + tryFn(); + }); + } + /** + * Given the full size of the array and a shape that may contain -1 as the + * implicit dimension, returns the inferred shape where -1 is replaced. + * E.g. For shape=[2, -1, 3] and size=24, it will return [2, 4, 3]. + * + * @param shape The shape, which may contain -1 in some dimension. + * @param size The full size (number of elements) of the array. + * @return The inferred shape where -1 is replaced with the inferred size. + */ + function inferFromImplicitShape(shape, size) { + var shapeProd = 1; + var implicitIdx = -1; + for (var i = 0; i < shape.length; ++i) { + if (shape[i] >= 0) { + shapeProd *= shape[i]; + } + else if (shape[i] === -1) { + if (implicitIdx !== -1) { + throw Error("Shapes can only have 1 implicit size. " + + ("Found -1 at dim " + implicitIdx + " and dim " + i)); + } + implicitIdx = i; + } + else if (shape[i] < 0) { + throw Error("Shapes can not be < 0. Found " + shape[i] + " at dim " + i); + } + } + if (implicitIdx === -1) { + if (size > 0 && size !== shapeProd) { + throw Error("Size(" + size + ") must match the product of shape " + shape); + } + return shape; + } + if (shapeProd === 0) { + throw Error("Cannot infer the missing size in [" + shape + "] when " + + "there are 0 elements"); + } + if (size % shapeProd !== 0) { + throw Error("The implicit shape can't be a fractional number. " + + ("Got " + size + " / " + shapeProd)); + } + var newShape = shape.slice(); + newShape[implicitIdx] = size / shapeProd; + return newShape; + } + function parseAxisParam(axis, shape) { + var rank = shape.length; + // Normalize input + axis = axis == null ? shape.map(function (s, i) { return i; }) : [].concat(axis); + // Check for valid range + assert(axis.every(function (ax) { return ax >= -rank && ax < rank; }), function () { + return "All values in axis param must be in range [-" + rank + ", " + rank + ") but " + + ("got axis " + axis); + }); + // Check for only integers + assert(axis.every(function (ax) { return isInt(ax); }), function () { return "All values in axis param must be integers but " + + ("got axis " + axis); }); + // Handle negative axis. + return axis.map(function (a) { return a < 0 ? rank + a : a; }); + } + /** Reduces the shape by removing all dimensions of shape 1. */ + function squeezeShape(shape, axis) { + var newShape = []; + var keptDims = []; + var isEmptyArray = axis != null && Array.isArray(axis) && axis.length === 0; + var axes = (axis == null || isEmptyArray) ? + null : + parseAxisParam(axis, shape).sort(); + var j = 0; + for (var i = 0; i < shape.length; ++i) { + if (axes != null) { + if (axes[j] === i && shape[i] !== 1) { + throw new Error("Can't squeeze axis " + i + " since its dim '" + shape[i] + "' is not 1"); + } + if ((axes[j] == null || axes[j] > i) && shape[i] === 1) { + newShape.push(shape[i]); + keptDims.push(i); + } + if (axes[j] <= i) { + j++; + } + } + if (shape[i] !== 1) { + newShape.push(shape[i]); + keptDims.push(i); + } + } + return { newShape: newShape, keptDims: keptDims }; + } + function getTypedArrayFromDType(dtype, size) { + var values = null; + if (dtype == null || dtype === 'float32') { + values = new Float32Array(size); + } + else if (dtype === 'int32') { + values = new Int32Array(size); + } + else if (dtype === 'bool') { + values = new Uint8Array(size); + } + else { + throw new Error("Unknown data type " + dtype); + } + return values; + } + function getArrayFromDType(dtype, size) { + var values = null; + if (dtype == null || dtype === 'float32') { + values = new Float32Array(size); + } + else if (dtype === 'int32') { + values = new Int32Array(size); + } + else if (dtype === 'bool') { + values = new Uint8Array(size); + } + else if (dtype === 'string') { + values = new Array(size); + } + else { + throw new Error("Unknown data type " + dtype); + } + return values; + } + function checkConversionForErrors(vals, dtype) { + for (var i = 0; i < vals.length; i++) { + var num = vals[i]; + if (isNaN(num) || !isFinite(num)) { + throw Error("A tensor of type " + dtype + " being uploaded contains " + num + "."); + } + } + } + /** Returns true if the dtype is valid. */ + function isValidDtype(dtype) { + return dtype === 'bool' || dtype === 'complex64' || dtype === 'float32' || + dtype === 'int32' || dtype === 'string'; + } + /** + * Returns true if the new type can't encode the old type without loss of + * precision. + */ + function hasEncodingLoss(oldType, newType) { + if (newType === 'complex64') { + return false; + } + if (newType === 'float32' && oldType !== 'complex64') { + return false; + } + if (newType === 'int32' && oldType !== 'float32' && oldType !== 'complex64') { + return false; + } + if (newType === 'bool' && oldType === 'bool') { + return false; + } + return true; + } + function isTypedArray(a) { + return a instanceof Float32Array || a instanceof Int32Array || + a instanceof Uint8Array; + } + function bytesPerElement(dtype) { + if (dtype === 'float32' || dtype === 'int32') { + return 4; + } + else if (dtype === 'complex64') { + return 8; + } + else if (dtype === 'bool') { + return 1; + } + else { + throw new Error("Unknown dtype " + dtype); + } + } + /** + * Returns the approximate number of bytes allocated in the string array - 2 + * bytes per character. Computing the exact bytes for a native string in JS is + * not possible since it depends on the encoding of the html page that serves + * the website. + */ + function bytesFromStringArray(arr) { + if (arr == null) { + return 0; + } + var bytes = 0; + arr.forEach(function (x) { return bytes += x.length; }); + return bytes; + } + /** Returns true if the value is a string. */ + function isString(value) { + return typeof value === 'string' || value instanceof String; + } + function isBoolean(value) { + return typeof value === 'boolean'; + } + function isNumber(value) { + return typeof value === 'number'; + } + function inferDtype(values) { + if (Array.isArray(values)) { + return inferDtype(values[0]); + } + if (values instanceof Float32Array) { + return 'float32'; + } + else if (values instanceof Int32Array || values instanceof Uint8Array) { + return 'int32'; + } + else if (isNumber(values)) { + return 'float32'; + } + else if (isString(values)) { + return 'string'; + } + else if (isBoolean(values)) { + return 'bool'; + } + return 'float32'; + } + function isFunction(f) { + return !!(f && f.constructor && f.call && f.apply); + } + function nearestDivisor(size, start) { + for (var i = start; i < size; ++i) { + if (size % i === 0) { + return i; + } + } + return size; + } + function computeStrides(shape) { + var rank = shape.length; + if (rank < 2) { + return []; + } + // Last dimension has implicit stride of 1, thus having D-1 (instead of D) + // strides. + var strides = new Array(rank - 1); + strides[rank - 2] = shape[rank - 1]; + for (var i = rank - 3; i >= 0; --i) { + strides[i] = strides[i + 1] * shape[i + 1]; + } + return strides; + } + function toTypedArray(a, dtype) { + if (dtype === 'string') { + throw new Error('Cannot convert a string[] to a TypedArray'); + } + if (Array.isArray(a)) { + a = flatten(a); + } + if (env().getBool('DEBUG')) { + checkConversionForErrors(a, dtype); + } + if (noConversionNeeded(a, dtype)) { + return a; + } + if (dtype == null || dtype === 'float32' || dtype === 'complex64') { + return new Float32Array(a); + } + else if (dtype === 'int32') { + return new Int32Array(a); + } + else if (dtype === 'bool') { + var bool = new Uint8Array(a.length); + for (var i = 0; i < bool.length; ++i) { + if (Math.round(a[i]) !== 0) { + bool[i] = 1; + } + } + return bool; + } + else { + throw new Error("Unknown data type " + dtype); + } + } + function createNestedArray(offset, shape, a) { + var ret = new Array(); + if (shape.length === 1) { + var d = shape[0]; + for (var i = 0; i < d; i++) { + ret[i] = a[offset + i]; + } + } + else { + var d = shape[0]; + var rest = shape.slice(1); + var len = rest.reduce(function (acc, c) { return acc * c; }); + for (var i = 0; i < d; i++) { + ret[i] = createNestedArray(offset + i * len, rest, a); + } + } + return ret; + } + // Provide a nested array of TypedArray in given shape. + function toNestedArray(shape, a) { + if (shape.length === 0) { + // Scalar type should return a single number. + return a[0]; + } + var size = shape.reduce(function (acc, c) { return acc * c; }); + if (size === 0) { + // A tensor with shape zero should be turned into empty list. + return []; + } + if (size !== a.length) { + throw new Error("[" + shape + "] does not match the input size " + a.length + "."); + } + return createNestedArray(0, shape, a); + } + function noConversionNeeded(a, dtype) { + return (a instanceof Float32Array && dtype === 'float32') || + (a instanceof Int32Array && dtype === 'int32') || + (a instanceof Uint8Array && dtype === 'bool'); + } + function makeOnesTypedArray(size, dtype) { + var array = makeZerosTypedArray(size, dtype); + for (var i = 0; i < array.length; i++) { + array[i] = 1; + } + return array; + } + function makeZerosTypedArray(size, dtype) { + if (dtype == null || dtype === 'float32' || dtype === 'complex64') { + return new Float32Array(size); + } + else if (dtype === 'int32') { + return new Int32Array(size); + } + else if (dtype === 'bool') { + return new Uint8Array(size); + } + else { + throw new Error("Unknown data type " + dtype); + } + } + /** + * Make nested `TypedArray` filled with zeros. + * @param shape The shape information for the nested array. + * @param dtype dtype of the array element. + */ + function makeZerosNestedTypedArray(shape, dtype) { + var size = shape.reduce(function (prev, curr) { return prev * curr; }, 1); + if (dtype == null || dtype === 'float32') { + return toNestedArray(shape, new Float32Array(size)); + } + else if (dtype === 'int32') { + return toNestedArray(shape, new Int32Array(size)); + } + else if (dtype === 'bool') { + return toNestedArray(shape, new Uint8Array(size)); + } + else { + throw new Error("Unknown data type " + dtype); + } + } + /** + * Returns the current high-resolution time in milliseconds relative to an + * arbitrary time in the past. It works across different platforms (node.js, + * browsers). + * + * ```js + * console.log(tf.util.now()); + * ``` + */ + /** @doc {heading: 'Util', namespace: 'util'} */ + function now() { + return env().platform.now(); + } + function assertNonNegativeIntegerDimensions(shape) { + shape.forEach(function (dimSize) { + assert(Number.isInteger(dimSize) && dimSize >= 0, function () { + return "Tensor must have a shape comprised of positive integers but got " + + ("shape [" + shape + "]."); + }); + }); + } + /** + * Returns a platform-specific implementation of + * [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). + * + * If `fetch` is defined on the global object (`window`, `process`, etc.), + * `tf.util.fetch` returns that function. + * + * If not, `tf.util.fetch` returns a platform-specific solution. + * + * ```js + * const resource = await tf.util.fetch('https://unpkg.com/@tensorflow/tfjs'); + * // handle response + * ``` + */ + /** @doc {heading: 'Util'} */ + function fetch$1(path, requestInits) { + return env().platform.fetch(path, requestInits); + } + /** + * Encodes the provided string into bytes using the provided encoding scheme. + * + * @param s The string to encode. + * @param encoding The encoding scheme. Defaults to utf-8. + * + */ + /** @doc {heading: 'Util'} */ + function encodeString(s, encoding) { + if (encoding === void 0) { encoding = 'utf-8'; } + encoding = encoding || 'utf-8'; + return env().platform.encode(s, encoding); + } + /** + * Decodes the provided bytes into a string using the provided encoding scheme. + * @param bytes The bytes to decode. + * + * @param encoding The encoding scheme. Defaults to utf-8. + */ + /** @doc {heading: 'Util'} */ + function decodeString(bytes, encoding) { + if (encoding === void 0) { encoding = 'utf-8'; } + encoding = encoding || 'utf-8'; + return env().platform.decode(bytes, encoding); + } + /** + * Computes flat index for a given location (multidimentionsal index) in a + * Tensor/multidimensional array. + * + * @param locs Location in the tensor. + * @param rank Rank of the tensor. + * @param strides Tensor strides. + */ + function locToIndex(locs, rank, strides) { + if (rank === 0) { + return 0; + } + else if (rank === 1) { + return locs[0]; + } + var index = locs[locs.length - 1]; + for (var i = 0; i < locs.length - 1; ++i) { + index += strides[i] * locs[i]; + } + return index; + } + /** + * Computes the location (multidimensional index) in a tensor/multidimentional + * array for a given flat index. + * + * @param index Index in flat array. + * @param rank Rank of tensor. + * @param strides Strides of tensor. + */ + function indexToLoc(index, rank, strides) { + if (rank === 0) { + return []; + } + else if (rank === 1) { + return [index]; + } + var locs = new Array(rank); + for (var i = 0; i < locs.length - 1; ++i) { + locs[i] = Math.floor(index / strides[i]); + index -= locs[i] * strides[i]; + } + locs[locs.length - 1] = index; + return locs; + } + + var util = { + __proto__: null, + shuffle: shuffle, + clamp: clamp, + nearestLargerEven: nearestLargerEven, + sum: sum, + randUniform: randUniform, + distSquared: distSquared, + assert: assert, + assertShapesMatch: assertShapesMatch, + assertNonNull: assertNonNull, + flatten: flatten, + sizeFromShape: sizeFromShape, + isScalarShape: isScalarShape, + arraysEqual: arraysEqual, + isInt: isInt, + tanh: tanh, + sizeToSquarishShape: sizeToSquarishShape, + createShuffledIndices: createShuffledIndices, + rightPad: rightPad, + repeatedTry: repeatedTry, + inferFromImplicitShape: inferFromImplicitShape, + parseAxisParam: parseAxisParam, + squeezeShape: squeezeShape, + getTypedArrayFromDType: getTypedArrayFromDType, + getArrayFromDType: getArrayFromDType, + checkConversionForErrors: checkConversionForErrors, + isValidDtype: isValidDtype, + hasEncodingLoss: hasEncodingLoss, + isTypedArray: isTypedArray, + bytesPerElement: bytesPerElement, + bytesFromStringArray: bytesFromStringArray, + isString: isString, + isBoolean: isBoolean, + isNumber: isNumber, + inferDtype: inferDtype, + isFunction: isFunction, + nearestDivisor: nearestDivisor, + computeStrides: computeStrides, + toTypedArray: toTypedArray, + toNestedArray: toNestedArray, + makeOnesTypedArray: makeOnesTypedArray, + makeZerosTypedArray: makeZerosTypedArray, + makeZerosNestedTypedArray: makeZerosNestedTypedArray, + now: now, + assertNonNegativeIntegerDimensions: assertNonNegativeIntegerDimensions, + fetch: fetch$1, + encodeString: encodeString, + decodeString: decodeString, + locToIndex: locToIndex, + indexToLoc: indexToLoc + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var Profiler = /** @class */ (function () { + function Profiler(backendTimer, logger) { + this.backendTimer = backendTimer; + this.logger = logger; + if (logger == null) { + this.logger = new Logger(); + } + } + Profiler.prototype.profileKernel = function (kernelName, inputs, f) { + var _this = this; + var outputs; + var holdResultWrapperFn = function () { + outputs = f(); + }; + var timer = this.backendTimer.time(holdResultWrapperFn); + outputs.forEach(function (r) { + // Dangling promise here because we don't want to propagate up + // asynchronicity. + r.data().then(function (vals) { + checkComputationForErrors(vals, r.dtype, kernelName); + timer.then(function (timing) { + var extraInfo = ''; + if (timing.getExtraProfileInfo != null) { + extraInfo = timing.getExtraProfileInfo(); + } + _this.logger.logKernelProfile(kernelName, r, vals, timing.kernelMs, inputs, extraInfo); + }); + }); + }); + return outputs; + }; + return Profiler; + }()); + function checkComputationForErrors(vals, dtype, kernelName) { + if (dtype !== 'float32') { + // Only floating point computations will generate NaN values + return false; + } + for (var i = 0; i < vals.length; i++) { + var num = vals[i]; + if (isNaN(num) || !isFinite(num)) { + // Throwing custom exception so behavior is testable. + console.warn("Found " + num + " in the result of '" + kernelName + "'"); + return true; + } + } + return false; + } + var Logger = /** @class */ (function () { + function Logger() { + } + Logger.prototype.logKernelProfile = function (name, result, vals, timeMs, inputs, extraInfo) { + var time = typeof timeMs === 'number' ? rightPad(timeMs + "ms", 9) : + timeMs['error']; + var paddedName = rightPad(name, 25); + var rank = result.rank; + var size = result.size; + var shape = rightPad(result.shape.toString(), 14); + var inputShapesDescription = ''; + for (var name_1 in inputs) { + var input = inputs[name_1]; + // The input might be a non-tensor (e.g HTMLImageElement), in which case + // we claim the output shape as input shape. + var inputShape = input.shape || result.shape; + var inputRank = inputShape.length; + inputShapesDescription += + name_1 + ": " + inputRank + "D " + (inputRank > 0 ? inputShape : '') + " "; + } + console.log("%c" + paddedName + "\t%c" + time + "\t%c" + rank + "D " + shape + "\t%c" + size + "\t%c" + inputShapesDescription + "\t%c" + extraInfo, 'font-weight:bold', 'color:red', 'color:blue', 'color: orange', 'color: green', 'color: steelblue'); + }; + return Logger; + }()); + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes a list of TapeNodes that connect x to y, filtering everything else + * out and preserving the order of the original tape elements. + * + * @param tape The tape elements to filter. + * @param xs The input Tensors. + * @param y The output Tensor. + */ + function getFilteredNodesXToY(tape, xs, y) { + // Forward pass to compute all the nodes and Tensors that are transitively a + // function of x. + var tensorsFromX = {}; + var nodesFromX = {}; + for (var i = 0; i < xs.length; i++) { + tensorsFromX[xs[i].id] = true; + } + for (var i = 0; i < tape.length; i++) { + var node = tape[i]; + var nodeInputs = node.inputs; + for (var inputName in nodeInputs) { + var input = nodeInputs[inputName]; + var anyInputFromX = false; + for (var j = 0; j < xs.length; j++) { + if (tensorsFromX[input.id]) { + node.outputs.forEach(function (output) { return tensorsFromX[output.id] = true; }); + anyInputFromX = true; + nodesFromX[node.id] = true; + break; + } + } + if (anyInputFromX) { + break; + } + } + } + // Backward pass to find all of the nodes and Tensors that lead to y. + var tensorsLeadToY = {}; + tensorsLeadToY[y.id] = true; + var nodesToY = {}; + for (var i = tape.length - 1; i >= 0; i--) { + var node = tape[i]; + var nodeInputs = node.inputs; + // If any of the outputs lead to y, mark all of the inputs as leading to y. + for (var j = 0; j < node.outputs.length; j++) { + if (tensorsLeadToY[node.outputs[j].id]) { + for (var inputName in nodeInputs) { + tensorsLeadToY[nodeInputs[inputName].id] = true; + nodesToY[node.id] = true; + } + break; + } + } + } + // Return the paths that come from x and lead to y. + var filteredTape = []; + for (var i = 0; i < tape.length; i++) { + var node = tape[i]; + if (nodesFromX[node.id] && nodesToY[node.id]) { + // Prune the inputs from the node that aren't a function of x. + var prunedInputs = {}; + for (var inputName in node.inputs) { + var nodeInput = node.inputs[inputName]; + if (tensorsFromX[nodeInput.id]) { + prunedInputs[inputName] = nodeInput; + } + } + // Copy the node and overwrite inputsAndArgs to the pruned version. + var prunedNode = Object.assign({}, node); + prunedNode.inputs = prunedInputs; + prunedNode.outputs = node.outputs; + filteredTape.push(prunedNode); + } + } + return filteredTape; + } + /** + * Backpropagate gradients through the filtered TapeNodes. + * + * @param tensorAccumulatedGradientMap A map of Tensor to its gradient. This map + * is mutated by this method. + * @param filteredTape The filtered TapeNodes to backprop through. + */ + function backpropagateGradients(tensorAccumulatedGradientMap, filteredTape, tidy) { + var _loop_1 = function (i) { + var node = filteredTape[i]; + var dys = []; + node.outputs.forEach(function (o) { + var gradTensor = tensorAccumulatedGradientMap[o.id]; + if (gradTensor != null) { + dys.push(gradTensor); + } + else { + // This particular output is not in the back-propagation subgraph, so it + // does not affect the final output, thus we put null for its dy. + dys.push(null); + } + }); + if (node.gradient == null) { + throw new Error("Cannot compute gradient: gradient function not found " + + ("for " + node.kernelName + ".")); + } + // Backprop dy through this node and accumulate gradients over the inputs. + var inputGradients = node.gradient(dys); + var _loop_2 = function (inputName) { + if (!(inputName in inputGradients)) { + throw new Error("Cannot backprop through input " + inputName + ". " + + ("Available gradients found: " + Object.keys(inputGradients) + ".")); + } + // Call the gradient function. + var dx = tidy(function () { return inputGradients[inputName](); }); + if (dx.dtype !== 'float32') { + throw new Error("Error in gradient for op " + node.kernelName + ". The gradient of input " + + (inputName + " must have 'float32' dtype, but has '" + dx.dtype + "'")); + } + var x = node.inputs[inputName]; + if (!arraysEqual(dx.shape, x.shape)) { + throw new Error("Error in gradient for op " + node.kernelName + ". The gradient of input " + + ("'" + inputName + "' has shape '" + dx.shape + "', which does not match ") + + ("the shape of the input '" + x.shape + "'")); + } + if (tensorAccumulatedGradientMap[x.id] == null) { + tensorAccumulatedGradientMap[x.id] = dx; + } + else { + var curGradient = tensorAccumulatedGradientMap[x.id]; + tensorAccumulatedGradientMap[x.id] = curGradient.add(dx); + curGradient.dispose(); + } + }; + for (var inputName in node.inputs) { + _loop_2(inputName); + } + }; + // Walk the tape backward and keep a map of Tensor to its gradient. + for (var i = filteredTape.length - 1; i >= 0; i--) { + _loop_1(i); + } + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // Maximum number of values before we decide to show ellipsis. + var FORMAT_LIMIT_NUM_VALS = 20; + // Number of first and last values to show when displaying a, b,...,y, z. + var FORMAT_NUM_FIRST_LAST_VALS = 3; + // Number of significant digits to show. + var FORMAT_NUM_SIG_DIGITS = 7; + function tensorToString(vals, shape, dtype, verbose) { + var strides = computeStrides(shape); + var padPerCol = computeMaxSizePerColumn(vals, shape, dtype, strides); + var rank = shape.length; + var valsLines = subTensorToString(vals, shape, dtype, strides, padPerCol); + var lines = ['Tensor']; + if (verbose) { + lines.push(" dtype: " + dtype); + lines.push(" rank: " + rank); + lines.push(" shape: [" + shape + "]"); + lines.push(" values:"); + } + lines.push(valsLines.map(function (l) { return ' ' + l; }).join('\n')); + return lines.join('\n'); + } + function computeMaxSizePerColumn(vals, shape, dtype, strides) { + var n = sizeFromShape(shape); + var numCols = strides[strides.length - 1]; + var padPerCol = new Array(numCols).fill(0); + var rank = shape.length; + var valuesOrTuples = dtype === 'complex64' ? createComplexTuples(vals) : vals; + if (rank > 1) { + for (var row = 0; row < n / numCols; row++) { + var offset = row * numCols; + for (var j = 0; j < numCols; j++) { + padPerCol[j] = Math.max(padPerCol[j], valToString(valuesOrTuples[offset + j], 0, dtype).length); + } + } + } + return padPerCol; + } + function valToString(val, pad, dtype) { + var valStr; + if (Array.isArray(val)) { + valStr = parseFloat(val[0].toFixed(FORMAT_NUM_SIG_DIGITS)) + " + " + + (parseFloat(val[1].toFixed(FORMAT_NUM_SIG_DIGITS)) + "j"); + } + else if (isString(val)) { + valStr = "'" + val + "'"; + } + else if (dtype === 'bool') { + valStr = boolNumToString(val); + } + else { + valStr = parseFloat(val.toFixed(FORMAT_NUM_SIG_DIGITS)).toString(); + } + return rightPad(valStr, pad); + } + function boolNumToString(v) { + return v === 0 ? 'false' : 'true'; + } + function subTensorToString(vals, shape, dtype, strides, padPerCol, isLast) { + if (isLast === void 0) { isLast = true; } + var storagePerElement = dtype === 'complex64' ? 2 : 1; + var size = shape[0]; + var rank = shape.length; + if (rank === 0) { + if (dtype === 'complex64') { + var complexTuple = createComplexTuples(vals); + return [valToString(complexTuple[0], 0, dtype)]; + } + if (dtype === 'bool') { + return [boolNumToString(vals[0])]; + } + return [vals[0].toString()]; + } + if (rank === 1) { + if (size > FORMAT_LIMIT_NUM_VALS) { + var firstValsSize = FORMAT_NUM_FIRST_LAST_VALS * storagePerElement; + var firstVals = Array.from(vals.slice(0, firstValsSize)); + var lastVals = Array.from(vals.slice((size - FORMAT_NUM_FIRST_LAST_VALS) * storagePerElement, size * storagePerElement)); + if (dtype === 'complex64') { + firstVals = createComplexTuples(firstVals); + lastVals = createComplexTuples(lastVals); + } + return [ + '[' + + firstVals.map(function (x, i) { return valToString(x, padPerCol[i], dtype); }) + .join(', ') + + ', ..., ' + + lastVals + .map(function (x, i) { return valToString(x, padPerCol[size - FORMAT_NUM_FIRST_LAST_VALS + i], dtype); }) + .join(', ') + + ']' + ]; + } + var displayVals = dtype === 'complex64' ? createComplexTuples(vals) : + Array.from(vals); + return [ + '[' + + displayVals.map(function (x, i) { return valToString(x, padPerCol[i], dtype); }) + .join(', ') + + ']' + ]; + } + // The array is rank 2 or more. + var subshape = shape.slice(1); + var substrides = strides.slice(1); + var stride = strides[0] * storagePerElement; + var lines = []; + if (size > FORMAT_LIMIT_NUM_VALS) { + for (var i = 0; i < FORMAT_NUM_FIRST_LAST_VALS; i++) { + var start = i * stride; + var end = start + stride; + lines.push.apply(lines, subTensorToString(vals.slice(start, end), subshape, dtype, substrides, padPerCol, false /* isLast */)); + } + lines.push('...'); + for (var i = size - FORMAT_NUM_FIRST_LAST_VALS; i < size; i++) { + var start = i * stride; + var end = start + stride; + lines.push.apply(lines, subTensorToString(vals.slice(start, end), subshape, dtype, substrides, padPerCol, i === size - 1 /* isLast */)); + } + } + else { + for (var i = 0; i < size; i++) { + var start = i * stride; + var end = start + stride; + lines.push.apply(lines, subTensorToString(vals.slice(start, end), subshape, dtype, substrides, padPerCol, i === size - 1 /* isLast */)); + } + } + var sep = rank === 2 ? ',' : ''; + lines[0] = '[' + lines[0] + sep; + for (var i = 1; i < lines.length - 1; i++) { + lines[i] = ' ' + lines[i] + sep; + } + var newLineSep = ',\n'; + for (var i = 2; i < rank; i++) { + newLineSep += '\n'; + } + lines[lines.length - 1] = + ' ' + lines[lines.length - 1] + ']' + (isLast ? '' : newLineSep); + return lines; + } + function createComplexTuples(vals) { + var complexTuples = []; + for (var i = 0; i < vals.length; i += 2) { + complexTuples.push([vals[i], vals[i + 1]]); + } + return complexTuples; + } + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * A mutable object, similar to `tf.Tensor`, that allows users to set values + * at locations before converting to an immutable `tf.Tensor`. + * + * See `tf.buffer` for creating a tensor buffer. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + var TensorBuffer = /** @class */ (function () { + function TensorBuffer(shape, dtype, values) { + var _this = this; + this.dtype = dtype; + this.shape = shape.slice(); + this.size = sizeFromShape(shape); + if (values != null) { + var n_1 = values.length; + assert(n_1 === this.size, function () { return "Length of values '" + n_1 + "' does not match the size " + + ("inferred by the shape '" + _this.size + "'."); }); + } + if (dtype === 'complex64') { + throw new Error("complex64 dtype TensorBuffers are not supported. Please create " + + "a TensorBuffer for the real and imaginary parts separately and " + + "call tf.complex(real, imag)."); + } + this.values = values || getArrayFromDType(dtype, this.size); + this.strides = computeStrides(shape); + } + /** + * Sets a value in the buffer at a given location. + * + * @param value The value to set. + * @param locs The location indices. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + TensorBuffer.prototype.set = function (value) { + var _this = this; + var locs = []; + for (var _i = 1; _i < arguments.length; _i++) { + locs[_i - 1] = arguments[_i]; + } + if (locs.length === 0) { + locs = [0]; + } + assert(locs.length === this.rank, function () { return "The number of provided coordinates (" + locs.length + ") must " + + ("match the rank (" + _this.rank + ")"); }); + var index = this.locToIndex(locs); + this.values[index] = value; + }; + /** + * Returns the value in the buffer at the provided location. + * + * @param locs The location indices. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + TensorBuffer.prototype.get = function () { + var locs = []; + for (var _i = 0; _i < arguments.length; _i++) { + locs[_i] = arguments[_i]; + } + if (locs.length === 0) { + locs = [0]; + } + var i = 0; + for (var _a = 0, locs_1 = locs; _a < locs_1.length; _a++) { + var loc = locs_1[_a]; + if (loc < 0 || loc >= this.shape[i]) { + var msg = "Requested out of range element at " + locs + ". " + + (" Buffer shape=" + this.shape); + throw new Error(msg); + } + i++; + } + var index = locs[locs.length - 1]; + for (var i_1 = 0; i_1 < locs.length - 1; ++i_1) { + index += this.strides[i_1] * locs[i_1]; + } + return this.values[index]; + }; + TensorBuffer.prototype.locToIndex = function (locs) { + if (this.rank === 0) { + return 0; + } + else if (this.rank === 1) { + return locs[0]; + } + var index = locs[locs.length - 1]; + for (var i = 0; i < locs.length - 1; ++i) { + index += this.strides[i] * locs[i]; + } + return index; + }; + TensorBuffer.prototype.indexToLoc = function (index) { + if (this.rank === 0) { + return []; + } + else if (this.rank === 1) { + return [index]; + } + var locs = new Array(this.shape.length); + for (var i = 0; i < locs.length - 1; ++i) { + locs[i] = Math.floor(index / this.strides[i]); + index -= locs[i] * this.strides[i]; + } + locs[locs.length - 1] = index; + return locs; + }; + Object.defineProperty(TensorBuffer.prototype, "rank", { + get: function () { + return this.shape.length; + }, + enumerable: true, + configurable: true + }); + /** + * Creates an immutable `tf.Tensor` object from the buffer. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + TensorBuffer.prototype.toTensor = function () { + return trackerFn().makeTensor(this.values, this.shape, this.dtype); + }; + return TensorBuffer; + }()); + // For tracking tensor creation and disposal. + var trackerFn = null; + // Used by chaining methods to call into ops. + var opHandler = null; + /** + * An external consumer can register itself as the tensor tracker. This way + * the Tensor class can notify the tracker for every tensor created and + * disposed. + */ + function setTensorTracker(fn) { + trackerFn = fn; + } + /** + * An external consumer can register itself as the op handler. This way the + * Tensor class can have chaining methods that call into ops via the op + * handler. + */ + function setOpHandler(handler) { + opHandler = handler; + } + /** + * A `tf.Tensor` object represents an immutable, multidimensional array of + * numbers that has a shape and a data type. + * + * See `tf.tensor` for details on how to create a `tf.Tensor`. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + var Tensor = /** @class */ (function () { + function Tensor(shape, dtype, dataId, id) { + /** Whether this tensor has been globally kept. */ + this.kept = false; + this.isDisposedInternal = false; + this.shape = shape.slice(); + this.dtype = dtype || 'float32'; + this.size = sizeFromShape(shape); + this.strides = computeStrides(shape); + this.dataId = dataId; + this.id = id; + this.rankType = (this.rank < 5 ? this.rank.toString() : 'higher'); + } + Object.defineProperty(Tensor.prototype, "rank", { + get: function () { + return this.shape.length; + }, + enumerable: true, + configurable: true + }); + /** + * Returns a promise of `tf.TensorBuffer` that holds the underlying data. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.buffer = function () { + return __awaiter(this, void 0, void 0, function () { + var vals; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, this.data()]; + case 1: + vals = _a.sent(); + return [2 /*return*/, opHandler.buffer(this.shape, this.dtype, vals)]; + } + }); + }); + }; + /** Returns a `tf.TensorBuffer` that holds the underlying data. */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.bufferSync = function () { + return opHandler.buffer(this.shape, this.dtype, this.dataSync()); + }; + /** + * Returns the tensor data as a nested array. The transfer of data is done + * asynchronously. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.array = function () { + return __awaiter(this, void 0, void 0, function () { + var vals; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, this.data()]; + case 1: + vals = _a.sent(); + return [2 /*return*/, toNestedArray(this.shape, vals)]; + } + }); + }); + }; + /** + * Returns the tensor data as a nested array. The transfer of data is done + * synchronously. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.arraySync = function () { + return toNestedArray(this.shape, this.dataSync()); + }; + /** + * Asynchronously downloads the values from the `tf.Tensor`. Returns a + * promise of `TypedArray` that resolves when the computation has finished. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.data = function () { + return __awaiter(this, void 0, void 0, function () { + var data, bytes; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + this.throwIfDisposed(); + data = trackerFn().read(this.dataId); + if (!(this.dtype === 'string')) return [3 /*break*/, 2]; + return [4 /*yield*/, data]; + case 1: + bytes = _a.sent(); + try { + return [2 /*return*/, bytes.map(function (b) { return decodeString(b); })]; + } + catch (_b) { + throw new Error('Failed to decode the string bytes into utf-8. ' + + 'To get the original bytes, call tensor.bytes().'); + } + _a.label = 2; + case 2: return [2 /*return*/, data]; + } + }); + }); + }; + /** + * Synchronously downloads the values from the `tf.Tensor`. This blocks the + * UI thread until the values are ready, which can cause performance issues. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.dataSync = function () { + this.throwIfDisposed(); + var data = trackerFn().readSync(this.dataId); + if (this.dtype === 'string') { + try { + return data.map(function (b) { return decodeString(b); }); + } + catch (_a) { + throw new Error('Failed to decode the string bytes into utf-8. ' + + 'To get the original bytes, call tensor.bytes().'); + } + } + return data; + }; + /** Returns the underlying bytes of the tensor's data. */ + Tensor.prototype.bytes = function () { + return __awaiter(this, void 0, void 0, function () { + var data; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + this.throwIfDisposed(); + return [4 /*yield*/, trackerFn().read(this.dataId)]; + case 1: + data = _a.sent(); + if (this.dtype === 'string') { + return [2 /*return*/, data]; + } + else { + return [2 /*return*/, new Uint8Array(data.buffer)]; + } + } + }); + }); + }; + /** + * Disposes `tf.Tensor` from memory. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.dispose = function () { + if (this.isDisposed) { + return; + } + trackerFn().disposeTensor(this); + this.isDisposedInternal = true; + }; + Object.defineProperty(Tensor.prototype, "isDisposed", { + get: function () { + return this.isDisposedInternal; + }, + enumerable: true, + configurable: true + }); + Tensor.prototype.throwIfDisposed = function () { + if (this.isDisposed) { + throw new Error("Tensor is disposed."); + } + }; + /** + * Prints the `tf.Tensor`. See `tf.print` for details. + * + * @param verbose Whether to print verbose information about the tensor, + * including dtype and size. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.print = function (verbose) { + if (verbose === void 0) { verbose = false; } + return opHandler.print(this, verbose); + }; + /** Returns a copy of the tensor. See `tf.clone` for details. */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.clone = function () { + this.throwIfDisposed(); + return opHandler.clone(this); + }; + /** + * Returns a human-readable description of the tensor. Useful for logging. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.toString = function (verbose) { + if (verbose === void 0) { verbose = false; } + var vals = this.dataSync(); + return tensorToString(vals, this.shape, this.dtype, verbose); + }; + Tensor.prototype.cast = function (dtype) { + this.throwIfDisposed(); + return opHandler.cast(this, dtype); + }; + Tensor.prototype.variable = function (trainable, name, dtype) { + if (trainable === void 0) { trainable = true; } + this.throwIfDisposed(); + return trackerFn().makeVariable(this, trainable, name, dtype); + }; + return Tensor; + }()); + Object.defineProperty(Tensor, Symbol.hasInstance, { + value: function (instance) { + return !!instance && instance.dataId != null && instance.shape != null && + instance.dtype != null; + } + }); + /** + * A mutable `tf.Tensor`, useful for persisting state, e.g. for training. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + var Variable = /** @class */ (function (_super) { + __extends(Variable, _super); + function Variable(initialValue, trainable, name, tensorId) { + var _this = _super.call(this, initialValue.shape, initialValue.dtype, initialValue.dataId, tensorId) || this; + _this.trainable = trainable; + _this.name = name; + return _this; + } + /** + * Assign a new `tf.Tensor` to this variable. The new `tf.Tensor` must have + * the same shape and dtype as the old `tf.Tensor`. + * + * @param newValue New tensor to be assigned to this variable. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Variable.prototype.assign = function (newValue) { + if (newValue.dtype !== this.dtype) { + throw new Error("dtype of the new value (" + newValue.dtype + ") and " + + ("previous value (" + this.dtype + ") must match")); + } + if (!arraysEqual(newValue.shape, this.shape)) { + throw new Error("shape of the new value (" + newValue.shape + ") and " + + ("previous value (" + this.shape + ") must match")); + } + trackerFn().disposeTensor(this); + this.dataId = newValue.dataId; + trackerFn().incRef(this, null /* backend */); + }; + Variable.prototype.dispose = function () { + trackerFn().disposeVariable(this); + this.isDisposedInternal = true; + }; + return Variable; + }(Tensor)); + Object.defineProperty(Variable, Symbol.hasInstance, { + value: function (instance) { + return instance instanceof Tensor && instance.assign != null && + instance.assign instanceof Function; + } + }); + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + (function (Rank) { + Rank["R0"] = "R0"; + Rank["R1"] = "R1"; + Rank["R2"] = "R2"; + Rank["R3"] = "R3"; + Rank["R4"] = "R4"; + Rank["R5"] = "R5"; + Rank["R6"] = "R6"; + })(exports.Rank || (exports.Rank = {})); + // Looks for upcasting types. Used, for example, in operations with mixed dtype + // inputs. + var UpcastInt32AndMap; + (function (UpcastInt32AndMap) { + UpcastInt32AndMap["float32"] = "float32"; + UpcastInt32AndMap["int32"] = "int32"; + UpcastInt32AndMap["bool"] = "int32"; + UpcastInt32AndMap["complex64"] = "complex64"; + })(UpcastInt32AndMap || (UpcastInt32AndMap = {})); + var UpcastBoolAndMap; + (function (UpcastBoolAndMap) { + UpcastBoolAndMap["float32"] = "float32"; + UpcastBoolAndMap["int32"] = "int32"; + UpcastBoolAndMap["bool"] = "bool"; + UpcastBoolAndMap["complex64"] = "complex64"; + })(UpcastBoolAndMap || (UpcastBoolAndMap = {})); + var UpcastFloat32AndMap; + (function (UpcastFloat32AndMap) { + UpcastFloat32AndMap["float32"] = "float32"; + UpcastFloat32AndMap["int32"] = "float32"; + UpcastFloat32AndMap["bool"] = "float32"; + UpcastFloat32AndMap["complex64"] = "complex64"; + })(UpcastFloat32AndMap || (UpcastFloat32AndMap = {})); + var UpcastComplex64AndMap; + (function (UpcastComplex64AndMap) { + UpcastComplex64AndMap["float32"] = "complex64"; + UpcastComplex64AndMap["int32"] = "complex64"; + UpcastComplex64AndMap["bool"] = "complex64"; + UpcastComplex64AndMap["complex64"] = "complex64"; + })(UpcastComplex64AndMap || (UpcastComplex64AndMap = {})); + var upcastTypeMap = { + 'float32': UpcastFloat32AndMap, + 'int32': UpcastInt32AndMap, + 'bool': UpcastBoolAndMap, + 'complex64': UpcastComplex64AndMap + }; + function upcastType(typeA, typeB) { + if (typeA === 'string' || typeB === 'string') { + if (typeA === 'string' && typeB === 'string') { + return 'string'; + } + throw new Error("Can not upcast " + typeA + " with " + typeB); + } + return upcastTypeMap[typeA][typeB]; + } + /** Returns the output type after summation. */ + function sumOutType(type) { + return upcastType(type, 'int32'); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function makeTypesMatch(a, b) { + if (a.dtype === b.dtype) { + return [a, b]; + } + var dtype = upcastType(a.dtype, b.dtype); + return [a.cast(dtype), b.cast(dtype)]; + } + function assertTypesMatch(a, b) { + assert(a.dtype === b.dtype, function () { return "The dtypes of the first(" + a.dtype + ") and" + + (" second(" + b.dtype + ") input must match"); }); + } + function isTensorInList(tensor, tensorList) { + return tensorList.some(function (x) { return x.id === tensor.id; }); + } + /** + * Extracts any `Tensor`s found within the provided object. + * + * @param container an object that may be a `Tensor` or may directly contain + * `Tensor`s, such as a `Tensor[]` or `{key: Tensor, ...}`. In general it + * is safe to pass any object here, except that `Promise`s are not + * supported. + * @returns An array of `Tensors` found within the passed object. If the + * argument is simply a `Tensor', a list containing that `Tensor` is + * returned. If the object is not a `Tensor` or does not + * contain `Tensors`, an empty list is returned. + */ + function getTensorsInContainer(result) { + var list = []; + var seen = new Set(); + walkTensorContainer(result, list, seen); + return list; + } + function walkTensorContainer(container, list, seen) { + if (container == null) { + return; + } + if (container instanceof Tensor) { + list.push(container); + return; + } + if (!isIterable(container)) { + return; + } + // Iteration over keys works also for arrays. + var iterable = container; + for (var k in iterable) { + var val = iterable[k]; + if (!seen.has(val)) { + seen.add(val); + walkTensorContainer(val, list, seen); + } + } + } + // tslint:disable-next-line:no-any + function isIterable(obj) { + return Array.isArray(obj) || typeof obj === 'object'; + } + + var tensor_util = { + __proto__: null, + makeTypesMatch: makeTypesMatch, + assertTypesMatch: assertTypesMatch, + isTensorInList: isTensorInList, + getTensorsInContainer: getTensorsInContainer + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var EngineState = /** @class */ (function () { + function EngineState() { + // Public since optimizers will use it. + this.registeredVariables = {}; + this.nextTapeNodeId = 0; + this.numBytes = 0; + this.numTensors = 0; + this.numStringTensors = 0; + this.numDataBuffers = 0; + // Number of nested tf.grad() statements when computing higher-order + // gradients. E.g. `1` for first-order gradients and `2` for second-order + // gradients. Used to track if the tape should be removed after a backprop. + this.gradientDepth = 0; + // Number of nested kernel calls. When kernel depth is greater than 1, we turn + // off the tape. + this.kernelDepth = 0; + this.scopeStack = []; + /** + * Keeps track of the number of data moves during a kernel execution. We + * maintain a stack since kernels can call other kernels, recursively. + */ + this.numDataMovesStack = []; + this.nextScopeId = 0; + this.tensorInfo = new WeakMap(); + this.profiling = false; + this.activeProfile = { newBytes: 0, newTensors: 0, peakBytes: 0, kernels: [], result: null }; + } + EngineState.prototype.dispose = function () { + for (var variableName in this.registeredVariables) { + this.registeredVariables[variableName].dispose(); + } + }; + return EngineState; + }()); + var Engine = /** @class */ (function () { + function Engine(ENV) { + this.ENV = ENV; + this.registry = {}; + this.registryFactory = {}; + this.pendingBackendInitId = 0; + this.state = new EngineState(); + } + Engine.prototype.ready = function () { + return __awaiter(this, void 0, void 0, function () { + var sortedBackends, i, backendName, success; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (this.pendingBackendInit != null) { + return [2 /*return*/, this.pendingBackendInit.then(function () { })]; + } + if (this.backendInstance != null) { + return [2 /*return*/]; + } + sortedBackends = this.getSortedBackends(); + i = 0; + _a.label = 1; + case 1: + if (!(i < sortedBackends.length)) return [3 /*break*/, 5]; + backendName = sortedBackends[i]; + return [4 /*yield*/, this.initializeBackend(backendName).success]; + case 2: + success = _a.sent(); + if (!success) return [3 /*break*/, 4]; + return [4 /*yield*/, this.setBackend(backendName)]; + case 3: + _a.sent(); + return [2 /*return*/]; + case 4: + i++; + return [3 /*break*/, 1]; + case 5: throw new Error("Could not initialize any backends, all backend initializations " + + "failed."); + } + }); + }); + }; + Object.defineProperty(Engine.prototype, "backend", { + get: function () { + if (this.pendingBackendInit != null) { + throw new Error("Backend '" + this.backendName + "' has not yet been initialized. Make " + + "sure to await tf.ready() or await tf.setBackend() before calling " + + "other methods"); + } + if (this.backendInstance == null) { + var _a = this.initializeBackendsAndReturnBest(), name_1 = _a.name, asyncInit = _a.asyncInit; + if (asyncInit) { + throw new Error("The highest priority backend '" + name_1 + "' has not yet been " + + "initialized. Make sure to await tf.ready() or " + + "await tf.setBackend() before calling other methods"); + } + this.setBackend(name_1); + } + return this.backendInstance; + }, + enumerable: true, + configurable: true + }); + Engine.prototype.backendNames = function () { + return Object.keys(this.registryFactory); + }; + Engine.prototype.findBackend = function (backendName) { + if (!(backendName in this.registry)) { + // If the backend hasn't been initialized but we have a registry entry for + // it, initialize it and return it. + if (backendName in this.registryFactory) { + var asyncInit = this.initializeBackend(backendName).asyncInit; + if (asyncInit) { + // Backend is not ready yet. + return null; + } + } + else { + return null; + } + } + return this.registry[backendName]; + }; + Engine.prototype.findBackendFactory = function (backendName) { + if (!(backendName in this.registryFactory)) { + return null; + } + return this.registryFactory[backendName].factory; + }; + Engine.prototype.registerBackend = function (backendName, factory, priority) { + if (priority === void 0) { priority = 1; } + if (backendName in this.registryFactory) { + console.warn(backendName + " backend was already registered. " + + "Reusing existing backend factory."); + return false; + } + this.registryFactory[backendName] = { factory: factory, priority: priority }; + return true; + }; + Engine.prototype.setBackend = function (backendName) { + return __awaiter(this, void 0, void 0, function () { + var _a, success, asyncInit, result, _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + if (this.registryFactory[backendName] == null) { + throw new Error("Backend name '" + backendName + "' not found in registry"); + } + this.backendName = backendName; + if (!(this.registry[backendName] == null)) return [3 /*break*/, 4]; + this.backendInstance = null; + _a = this.initializeBackend(backendName), success = _a.success, asyncInit = _a.asyncInit; + if (!asyncInit) return [3 /*break*/, 2]; + return [4 /*yield*/, success]; + case 1: + _b = _c.sent(); + return [3 /*break*/, 3]; + case 2: + _b = success; + _c.label = 3; + case 3: + result = _b; + if (!result) { + return [2 /*return*/, false]; + } + _c.label = 4; + case 4: + this.backendInstance = this.registry[backendName]; + this.setupRegisteredKernels(); + // Reset the profiler. + this.profiler = new Profiler(this.backendInstance); + return [2 /*return*/, true]; + } + }); + }); + }; + Engine.prototype.setupRegisteredKernels = function () { + var _this = this; + var kernels = getKernelsForBackend(this.backendName); + kernels.forEach(function (kernel) { + if (kernel.setupFunc != null) { + kernel.setupFunc(_this.backendInstance); + } + }); + }; + Engine.prototype.disposeRegisteredKernels = function (backendName) { + var _this = this; + var kernels = getKernelsForBackend(backendName); + kernels.forEach(function (kernel) { + if (kernel.disposeFunc != null) { + kernel.disposeFunc(_this.registry[backendName]); + } + }); + }; + /** + * Initializes a backend by looking up the backend name in the factory + * registry and calling the factory method. Returns a boolean representing + * whether the initialization of the backend suceeded. Throws an error if + * there is no backend in the factory registry. + */ + Engine.prototype.initializeBackend = function (backendName) { + var _this = this; + var registryFactoryEntry = this.registryFactory[backendName]; + if (registryFactoryEntry == null) { + throw new Error("Cannot initialize backend " + backendName + ", no registration found."); + } + try { + var backend = registryFactoryEntry.factory(); + // Test if the factory returns a promise. + if (Promise.resolve(backend) === backend) { + var promiseId_1 = ++this.pendingBackendInitId; + var success = backend + .then(function (backendInstance) { + // Outdated promise. Another backend was set in the meantime. + if (promiseId_1 < _this.pendingBackendInitId) { + return false; + } + _this.registry[backendName] = backendInstance; + _this.pendingBackendInit = null; + return true; + }) + .catch(function (err) { + // Outdated promise. Another backend was set in the meantime. + if (promiseId_1 < _this.pendingBackendInitId) { + return false; + } + _this.pendingBackendInit = null; + console.warn("Initialization of backend " + backendName + " failed"); + console.warn(err.stack || err.message); + return false; + }); + this.pendingBackendInit = success; + return { success: success, asyncInit: true }; + } + else { + this.registry[backendName] = backend; + return { success: true, asyncInit: false }; + } + } + catch (err) { + console.warn("Initialization of backend " + backendName + " failed"); + console.warn(err.stack || err.message); + return { success: false, asyncInit: false }; + } + }; + Engine.prototype.removeBackend = function (backendName) { + if (!(backendName in this.registryFactory)) { + throw new Error(backendName + " backend not found in registry"); + } + if (this.backendName === backendName && this.pendingBackendInit != null) { + // There is a pending promise of the backend we want to remove. Make it + // obsolete. + this.pendingBackendInitId++; + } + if (backendName in this.registry) { + this.disposeRegisteredKernels(backendName); + this.registry[backendName].dispose(); + delete this.registry[backendName]; + } + delete this.registryFactory[backendName]; + // Unset the backend if it is active. + if (this.backendName === backendName) { + this.pendingBackendInit = null; + this.backendName = null; + this.backendInstance = null; + } + }; + Engine.prototype.getSortedBackends = function () { + var _this = this; + if (Object.keys(this.registryFactory).length === 0) { + throw new Error('No backend found in registry.'); + } + return Object.keys(this.registryFactory).sort(function (a, b) { + // Highest priority comes first. + return _this.registryFactory[b].priority - + _this.registryFactory[a].priority; + }); + }; + Engine.prototype.initializeBackendsAndReturnBest = function () { + var sortedBackends = this.getSortedBackends(); + for (var i = 0; i < sortedBackends.length; i++) { + var backendName = sortedBackends[i]; + var _a = this.initializeBackend(backendName), success = _a.success, asyncInit = _a.asyncInit; + if (asyncInit || success) { + return { name: backendName, asyncInit: asyncInit }; + } + } + throw new Error("Could not initialize any backends, all backend initializations " + + "failed."); + }; + Engine.prototype.moveData = function (backend, dataId) { + var info = this.state.tensorInfo.get(dataId); + var srcBackend = info.backend; + var values = this.readSync(dataId); + // Delete the tensor from the old backend and move it to the new + // backend. + srcBackend.disposeData(dataId); + info.backend = backend; + backend.move(dataId, values, info.shape, info.dtype); + if (this.shouldCheckForMemLeaks()) { + // Track the number of moves during a kernel execution to correctly + // detect memory leaks. + this.state.numDataMovesStack[this.state.numDataMovesStack.length - 1]++; + } + }; + Engine.prototype.tidy = function (nameOrFn, fn) { + var _this = this; + var name = null; + if (fn == null) { + // Called with only 1 argument. + if (typeof nameOrFn !== 'function') { + throw new Error('Please provide a function to tidy()'); + } + fn = nameOrFn; + } + else { + // Called with 2 arguments. + if (typeof nameOrFn !== 'string' && !(nameOrFn instanceof String)) { + throw new Error('When calling with two arguments, the first argument ' + + 'to tidy() must be a string'); + } + if (typeof fn !== 'function') { + throw new Error('When calling with two arguments, the 2nd argument ' + + 'to tidy() must be a function'); + } + name = nameOrFn; + // TODO(nsthorat,smilkov): Do operation logging and performance + // profiling. + } + var result; + return this.scopedRun(function () { return _this.startScope(name); }, function () { return _this.endScope(result); }, function () { + result = fn(); + if (result instanceof Promise) { + console.error('Cannot return a Promise inside of tidy.'); + } + return result; + }); + }; + Engine.prototype.scopedRun = function (start, end, f) { + start(); + try { + var res = f(); + end(); + return res; + } + catch (ex) { + end(); + throw ex; + } + }; + Engine.prototype.nextTensorId = function () { + return Engine.nextTensorId++; + }; + Engine.prototype.nextVariableId = function () { + return Engine.nextVariableId++; + }; + /** + * This method is called instead of the public-facing tensor.clone() when + * saving a tensor for backwards pass. It makes sure to add the clone + * operation to the tape regardless of being called inside a kernel + * execution. + * + * This method will go away once all kernels are modularized since we won't + * need to turn off the tape inside runKernel(). + */ + Engine.prototype.clone = function (x) { + var y = this.makeTensorFromDataId(x.dataId, x.shape, x.dtype); + var inputs = { x: x }; + var grad = function (dy) { return ({ x: function () { return dy.toFloat(); } }); }; + var saved = []; + this.addTapeNode(this.state.activeScope.name, inputs, [y], grad, saved, {}); + return y; + }; + /** + * Execute a kernel with the given name and return the output tensor. + * + * @param kernelName The name of the kernel to execute. + * @param inputs A map of input names to tensors. + * @param attrs A map of attribute names to their values. An attribute is a + * primitive (non-tensor) input to the kernel. + * @param inputsToSave A list of tensors, inputs to save for the backprop + * computation. + * @param outputsToSave A list of booleans, specifying which output to save + * for the backprop computation. These are booleans since the output + * tensors are not visible to the user. + */ + Engine.prototype.runKernel = function (kernelName, inputs, attrs, inputsToSave, outputsToSave) { + var forwardFunc = null; + var backwardsFunc = null; + // Call runKernel as a stop-gap until we modularize all kernels. + // Once we modularize all kernels, we will remove the existing + // `runKernelFunc`. + return this.runKernelFunc(forwardFunc, inputs, backwardsFunc, kernelName, attrs, inputsToSave, outputsToSave); + }; + Engine.prototype.shouldCheckForMemLeaks = function () { + return this.ENV.getBool('IS_TEST'); + }; + Engine.prototype.checkKernelForMemLeak = function (kernelName, numDataIdsBefore, outInfos) { + var numDataIdsAfter = this.backend.numDataIds(); + // Count the number of data ids associated with the result of the kernel. + var numOutputDataIds = 0; + outInfos.forEach(function (info) { + // Complex numbers allocate 3 data ids, one for 'real', one for + // 'imaginary', and one for the container that holds the former two. + numOutputDataIds += (info.dtype === 'complex64' ? 3 : 1); + }); + // Account for the number of moves during kernel execution. A "data move" + // can happen in the middle of a kernel execution, placing a new (key,value) + // pair in the data storage. Since data moves have net zero effect (we + // always remove the data from the old backend), we have to cancel them out + // when detecting memory leaks. + var numMoves = this.state.numDataMovesStack[this.state.numDataMovesStack.length - 1]; + var dataIdsLeaked = numDataIdsAfter - numDataIdsBefore - numOutputDataIds - numMoves; + if (dataIdsLeaked > 0) { + throw new Error("Backend '" + this.backendName + "' has an internal memory leak " + + ("(" + dataIdsLeaked + " data ids) after running '" + kernelName + "'")); + } + }; + /** + * @deprecated Use `runKernel` for newly added kernels. Keep using this method + * only for kernels that are not yet fully modularized. + */ + Engine.prototype.runKernelFunc = function (forwardFunc, inputs, backwardsFunc, kernelName, attrs, inputsToSave, outputsToSave) { + var _this = this; + var outputs; + var saved = []; + var isTapeOn = this.isTapeOn(); + if (kernelName == null) { + kernelName = + this.state.activeScope != null ? this.state.activeScope.name : ''; + } + var startingBytecount = this.state.numBytes; + var startingNumTensors = this.state.numTensors; + if (this.shouldCheckForMemLeaks()) { + this.state.numDataMovesStack.push(0); + } + var kernelFunc; + var kernel = getKernel(kernelName, this.backendName); + var out; + if (kernel != null) { + kernelFunc = function () { + var numDataIdsBefore = _this.backend.numDataIds(); + out = kernel.kernelFunc({ inputs: inputs, attrs: attrs, backend: _this.backend }); + var outInfos = Array.isArray(out) ? out : [out]; + if (_this.shouldCheckForMemLeaks()) { + _this.checkKernelForMemLeak(kernelName, numDataIdsBefore, outInfos); + } + var outTensors = outInfos.map(function (_a) { + var dataId = _a.dataId, shape = _a.shape, dtype = _a.dtype; + return _this.makeTensorFromDataId(dataId, shape, dtype); + }); + // Save the inputs and outputs. + // Do not save unless we are recording to the tape. Otherwise it would + // cause a mem leak since we would never run backprop, which disposes + // the kept tensors. + if (isTapeOn) { + var tensorsToSave = _this.getTensorsForGradient(kernelName, inputs, outTensors); + if (tensorsToSave == null) { + // Fallback for ops that call runKernelFunc and pass in + // inputsToSave and outputsToSave. Currently this is the set of ops + // with kernel support in the WASM backend. Once those ops and + // respective gradients are modularised we can remove this path. + if (outputsToSave == null) { + outputsToSave = []; + } + var outsToSave = outTensors.filter(function (_, i) { return outputsToSave[i]; }); + tensorsToSave = (inputsToSave || []).slice().concat(outsToSave); + } + saved = _this.saveTensorsForBackwardMode(tensorsToSave); + } + return outTensors; + }; + } + else { + var saveFunc_1 = function (tensors) { + // Do not save unless we are recording to the tape. Otherwise it would + // cause a mem leak since we would never run backprop, which disposes + // the kept tensors. + if (!isTapeOn) { + return; + } + saved = tensors.map(function (tensor) { return _this.keep(_this.clone(tensor)); }); + }; + kernelFunc = function () { + var numDataIdsBefore = _this.backend.numDataIds(); + out = _this.tidy(function () { return forwardFunc(_this.backend, saveFunc_1); }); + var outs = (Array.isArray(out) ? out : [out]); + if (_this.shouldCheckForMemLeaks()) { + _this.checkKernelForMemLeak(kernelName, numDataIdsBefore, outs); + } + return outs; + }; + } + // Stop recording to a tape when running a kernel. + this.scopedRun(function () { return _this.state.kernelDepth++; }, function () { return _this.state.kernelDepth--; }, function () { + if (!_this.ENV.getBool('DEBUG')) { + outputs = kernelFunc(); + } + else { + outputs = _this.profiler.profileKernel(kernelName, inputs, function () { return kernelFunc(); }); + } + }); + if (isTapeOn) { + this.addTapeNode(kernelName, inputs, outputs, backwardsFunc, saved, attrs); + } + if (this.state.profiling) { + this.state.activeProfile.kernels.push({ + name: kernelName, + bytesAdded: this.state.numBytes - startingBytecount, + totalBytesSnapshot: this.state.numBytes, + tensorsAdded: this.state.numTensors - startingNumTensors, + totalTensorsSnapshot: this.state.numTensors, + inputShapes: Object.keys(inputs).map(function (key) { return inputs[key].shape; }), + outputShapes: outputs.map(function (item) { return item.shape; }) + }); + } + return (Array.isArray(out) ? outputs : outputs[0]); + }; + /** + * Saves tensors used in forward mode for use in backward mode. + * + * @param tensors the list of tensors to save. + */ + Engine.prototype.saveTensorsForBackwardMode = function (tensors) { + var _this = this; + var saved = tensors.map(function (tensor) { return _this.keep(_this.clone(tensor)); }); + return saved; + }; + /** + * Returns a list of tensors to save for a given gradient calculation. + * + * Returns undefined if their is no registered gradient for this kernel in the + * gradient registry. + * + * @param kernelName name of kernel to look up gradient for. + * @param inputs a map of input tensors. + * @param outputs an array of output tensors from forward mode of kernel. + */ + Engine.prototype.getTensorsForGradient = function (kernelName, inputs, outputs) { + var gradConfig = getGradient(kernelName); + if (gradConfig != null) { + var inputsToSave = gradConfig.inputsToSave || []; + var outputsToSave_1 = gradConfig.outputsToSave || []; + // If saveAllInputs is true, all inputs will be saved. Otherwise, inputs + // specified in inputsToSave will be saved. + var inputTensorsToSave = void 0; + if (gradConfig.saveAllInputs) { + assert(Array.isArray(inputs), function () { return 'saveAllInputs is true, expected inputs to be an array.'; }); + inputTensorsToSave = Object.keys(inputs).map(function (key) { return inputs[key]; }); + } + else { + inputTensorsToSave = inputsToSave.map(function (inputName) { return inputs[inputName]; }); + } + var outputTensorsToSave = outputs.filter(function (_, i) { return outputsToSave_1[i]; }); + return inputTensorsToSave.concat(outputTensorsToSave); + } + // TODO(yassogba) throw exception here once all runkernelFunc calls with + // inputsToSave/outputsToSave are removed + return null; + }; + /** + * Internal method used by public APIs for tensor creation. Makes a new + * tensor with the provided shape, dtype and values. It always + * creates a new data id and writes the values to the underlying backend. + */ + Engine.prototype.makeTensor = function (values, shape, dtype, backend) { + if (values == null) { + throw new Error('Values passed to engine.makeTensor() are null'); + } + dtype = dtype || 'float32'; + backend = backend || this.backend; + var backendVals = values; + if (dtype === 'string' && isString(values[0])) { + backendVals = values.map(function (d) { return encodeString(d); }); + } + var dataId = backend.write(backendVals, shape, dtype); + var t = new Tensor(shape, dtype, dataId, this.nextTensorId()); + this.incRef(t, backend); + // Count bytes for string tensors. + if (dtype === 'string') { + var info = this.state.tensorInfo.get(dataId); + var newBytes = bytesFromStringArray(backendVals); + this.state.numBytes += newBytes - info.bytes; + info.bytes = newBytes; + } + return t; + }; + /** + * Internal method used by backends. Makes a new tensor + * that is a wrapper around an existing data id. It doesn't create + * a new data id, only increments the ref count used in memory tracking. + */ + Engine.prototype.makeTensorFromDataId = function (dataId, shape, dtype, backend) { + dtype = dtype || 'float32'; + var t = new Tensor(shape, dtype, dataId, this.nextTensorId()); + this.incRef(t, backend); + return t; + }; + Engine.prototype.makeVariable = function (initialValue, trainable, name, dtype) { + if (trainable === void 0) { trainable = true; } + name = name || this.nextVariableId().toString(); + if (dtype != null && dtype !== initialValue.dtype) { + initialValue = initialValue.cast(dtype); + } + var v = new Variable(initialValue, trainable, name, this.nextTensorId()); + if (this.state.registeredVariables[v.name] != null) { + throw new Error("Variable with name " + v.name + " was already registered"); + } + this.state.registeredVariables[v.name] = v; + this.incRef(v, this.backend); + return v; + }; + Engine.prototype.incRef = function (a, backend) { + var refCount = this.state.tensorInfo.has(a.dataId) ? + this.state.tensorInfo.get(a.dataId).refCount : + 0; + this.state.numTensors++; + if (a.dtype === 'string') { + this.state.numStringTensors++; + } + if (refCount === 0) { + this.state.numDataBuffers++; + // Bytes for complex numbers are counted by their components. Bytes for + // string tensors are counted when writing values. + var bytes = 0; + if (a.dtype !== 'complex64' && a.dtype !== 'string') { + bytes = a.size * bytesPerElement(a.dtype); + } + this.state.tensorInfo.set(a.dataId, { + backend: backend || this.backend, + dtype: a.dtype, + shape: a.shape, + bytes: bytes, + refCount: 0 + }); + this.state.numBytes += bytes; + } + this.state.tensorInfo.get(a.dataId).refCount++; + if (!(a instanceof Variable)) { + this.track(a); + } + }; + Engine.prototype.disposeTensor = function (a) { + if (!this.state.tensorInfo.has(a.dataId)) { + return; + } + this.state.numTensors--; + if (a.dtype === 'string') { + this.state.numStringTensors--; + } + var info = this.state.tensorInfo.get(a.dataId); + var refCount = info.refCount; + if (refCount <= 1) { + // Don't count bytes for complex numbers as they are counted by their + // components. + if (a.dtype !== 'complex64') { + this.state.numBytes -= info.bytes; + } + this.state.numDataBuffers--; + info.backend.disposeData(a.dataId); + this.state.tensorInfo.delete(a.dataId); + } + else { + this.state.tensorInfo.get(a.dataId).refCount--; + } + // TODO(nsthorat): Construct an error and save the stack trace for + // debugging when in debug mode. Creating a stack trace is too expensive + // to do unconditionally. + }; + Engine.prototype.disposeVariables = function () { + for (var varName in this.state.registeredVariables) { + var v = this.state.registeredVariables[varName]; + this.disposeVariable(v); + } + }; + Engine.prototype.disposeVariable = function (v) { + this.disposeTensor(v); + if (this.state.registeredVariables[v.name] != null) { + delete this.state.registeredVariables[v.name]; + } + }; + Engine.prototype.memory = function () { + var info = this.backend.memory(); + info.numTensors = this.state.numTensors; + info.numDataBuffers = this.state.numDataBuffers; + info.numBytes = this.state.numBytes; + if (this.state.numStringTensors > 0) { + info.unreliable = true; + if (info.reasons == null) { + info.reasons = []; + } + info.reasons.push('Memory usage by string tensors is approximate ' + + '(2 bytes per character)'); + } + return info; + }; + Engine.prototype.profile = function (query) { + return __awaiter(this, void 0, void 0, function () { + var startBytes, startNumTensors, _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + this.state.profiling = true; + startBytes = this.state.numBytes; + startNumTensors = this.state.numTensors; + this.state.activeProfile.kernels = []; + _a = this.state.activeProfile; + return [4 /*yield*/, query()]; + case 1: + _a.result = _b.sent(); + this.state.profiling = false; + this.state.activeProfile.peakBytes = Math.max.apply(Math, this.state.activeProfile.kernels.map(function (d) { return d.totalBytesSnapshot; })); + this.state.activeProfile.newBytes = this.state.numBytes - startBytes; + this.state.activeProfile.newTensors = + this.state.numTensors - startNumTensors; + return [2 /*return*/, this.state.activeProfile]; + } + }); + }); + }; + Engine.prototype.isTapeOn = function () { + return this.state.gradientDepth > 0 && this.state.kernelDepth === 0; + }; + Engine.prototype.addTapeNode = function (kernelName, inputs, outputs, gradientsFunc, saved, attrs) { + var _this = this; + var tapeNode = { id: this.state.nextTapeNodeId++, kernelName: kernelName, inputs: inputs, outputs: outputs, saved: saved }; + var gradConfig = getGradient(kernelName); + if (gradConfig != null) { + gradientsFunc = gradConfig.gradFunc; + } + if (gradientsFunc != null) { + tapeNode.gradient = function (dys) { + // TODO(smilkov): To optimize back-prop, pass dys that are not used in + // the backprop graph to the user as null instead of zeros + dys = dys.map(function (dy, i) { + if (dy == null) { + var output = outputs[i]; + var vals = makeZerosTypedArray(output.size, output.dtype); + return _this.makeTensor(vals, output.shape, output.dtype); + } + return dy; + }); + // Grad functions of ops with single outputs expect a dy, while ops + // with multiple outputs expect dys (array of dy). + return gradientsFunc(dys.length > 1 ? dys : dys[0], saved, attrs); + }; + } + this.state.activeTape.push(tapeNode); + }; + Engine.prototype.keep = function (result) { + result.kept = true; + return result; + }; + Engine.prototype.startTape = function () { + if (this.state.gradientDepth === 0) { + this.state.activeTape = []; + } + this.state.gradientDepth++; + }; + Engine.prototype.endTape = function () { + this.state.gradientDepth--; + }; + /** + * Start a scope. Use this with endScope() to achieve the same functionality + * as scope() without the need for a function closure. + */ + Engine.prototype.startScope = function (name) { + var scopeInfo = { + track: [], + name: 'unnamed scope', + id: this.state.nextScopeId++ + }; + if (name) { + scopeInfo.name = name; + } + this.state.scopeStack.push(scopeInfo); + this.state.activeScope = scopeInfo; + }; + /** + * End a scope. Use this with startScope() to achieve the same functionality + * as scope() without the need for a function closure. + */ + Engine.prototype.endScope = function (result) { + var _this = this; + var tensorsToTrackInParent = getTensorsInContainer(result); + var tensorsToTrackInParentSet = new Set(tensorsToTrackInParent.map(function (t) { return t.id; })); + // Dispose the arrays tracked in this scope. + for (var i = 0; i < this.state.activeScope.track.length; i++) { + var tensor = this.state.activeScope.track[i]; + if (!tensor.kept && !tensorsToTrackInParentSet.has(tensor.id)) { + tensor.dispose(); + } + } + var oldScope = this.state.scopeStack.pop(); + this.state.activeScope = this.state.scopeStack.length === 0 ? + null : + this.state.scopeStack[this.state.scopeStack.length - 1]; + // Track the current result in the parent scope. + tensorsToTrackInParent.forEach(function (tensor) { + // Only track the tensor if was allocated in the inner scope and is not + // globally kept. + if (!tensor.kept && tensor.scopeId === oldScope.id) { + _this.track(tensor); + } + }); + }; + /** + * Returns gradients of `f` with respect to each of the `xs`. The gradients + * returned are of the same length as `xs`, but some might be null if `f` + * was not a function of that `x`. It also takes optional dy to multiply the + * gradient, which defaults to `1`. + */ + Engine.prototype.gradients = function (f, xs, dy, allowNoGradients) { + var _this = this; + if (allowNoGradients === void 0) { allowNoGradients = false; } + assert(xs.length > 0, function () { return 'gradients() received an empty list of xs.'; }); + if (dy != null && dy.dtype !== 'float32') { + throw new Error("dy must have 'float32' dtype, but has '" + dy.dtype + "'"); + } + var y = this.scopedRun(function () { return _this.startTape(); }, function () { return _this.endTape(); }, function () { return _this.tidy('forward', f); }); + assert(y instanceof Tensor, function () { return 'The result y returned by f() must be a tensor.'; }); + // Filter out the nodes that don't connect x => y. + var filteredTape = getFilteredNodesXToY(this.state.activeTape, xs, y); + if (!allowNoGradients && filteredTape.length === 0 && xs.length > 0) { + throw new Error('Cannot compute gradient of y=f(x) with respect to x. Make sure ' + + 'that the f you passed encloses all operations that lead from x ' + + 'to y.'); + } + return this.tidy('backward', function () { + var accumulatedGradientMap = {}; + accumulatedGradientMap[y.id] = (dy == null) ? ones(y.shape) : dy; + // Backprop gradients through the filtered nodes. + backpropagateGradients(accumulatedGradientMap, filteredTape, + // Pass the tidy function to avoid circular dep with `tape.ts`. + function (f) { return _this.tidy(f); }); + var grads = xs.map(function (x) { return accumulatedGradientMap[x.id]; }); + if (_this.state.gradientDepth === 0) { + // This means that we are not computing higher-order gradients + // and can clean up the tape. + _this.state.activeTape.forEach(function (node) { + for (var _i = 0, _a = node.saved; _i < _a.length; _i++) { + var tensor = _a[_i]; + tensor.dispose(); + } + }); + _this.state.activeTape = null; + } + return { value: y, grads: grads }; + }); + }; + Engine.prototype.customGrad = function (f) { + var _this = this; + assert(isFunction(f), function () { return 'The f passed in customGrad(f) must be a function.'; }); + return function () { + var inputs = []; + for (var _i = 0; _i < arguments.length; _i++) { + inputs[_i] = arguments[_i]; + } + assert(inputs.every(function (t) { return t instanceof Tensor; }), function () { return 'The args passed in customGrad(f)(x1, x2,...) must all be ' + + 'tensors'; }); + var res; + var inputMap = {}; + inputs.forEach(function (input, i) { + inputMap[i] = input; + }); + return _this.runKernelFunc(function (_, save) { + res = f.apply(void 0, inputs.concat([save])); + assert(res.value instanceof Tensor, function () { return 'The function f passed in customGrad(f) must return an ' + + 'object where `obj.value` is a tensor'; }); + assert(isFunction(res.gradFunc), function () { return 'The function f passed in customGrad(f) must return an ' + + 'object where `obj.gradFunc` is a function.'; }); + return res.value; + }, inputMap, function (dy, saved) { + var gradRes = res.gradFunc(dy, saved); + var grads = Array.isArray(gradRes) ? gradRes : [gradRes]; + assert(grads.length === inputs.length, function () { return 'The function f passed in customGrad(f) must return an ' + + 'object where `obj.gradFunc` is a function that returns ' + + 'the same number of tensors as inputs passed to f(...).'; }); + assert(grads.every(function (t) { return t instanceof Tensor; }), function () { return 'The function f passed in customGrad(f) must return an ' + + 'object where `obj.gradFunc` is a function that returns ' + + 'a list of only tensors.'; }); + var gradMap = {}; + grads.forEach(function (grad, i) { + gradMap[i] = function () { return grad; }; + }); + return gradMap; + }); + }; + }; + Engine.prototype.readSync = function (dataId) { + // Route the read to the correct backend. + var info = this.state.tensorInfo.get(dataId); + return info.backend.readSync(dataId); + }; + Engine.prototype.read = function (dataId) { + // Route the read to the correct backend. + var info = this.state.tensorInfo.get(dataId); + return info.backend.read(dataId); + }; + Engine.prototype.time = function (query) { + return __awaiter(this, void 0, void 0, function () { + var start, timingInfo; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + start = now(); + return [4 /*yield*/, this.backend.time(query)]; + case 1: + timingInfo = _a.sent(); + timingInfo.wallMs = now() - start; + return [2 /*return*/, timingInfo]; + } + }); + }); + }; + /** + * Tracks a Tensor in the current scope to be automatically cleaned up + * when the current scope ends, and returns the value. + * + * @param result The Tensor to track in the current scope. + */ + Engine.prototype.track = function (result) { + if (this.state.activeScope != null) { + result.scopeId = this.state.activeScope.id; + this.state.activeScope.track.push(result); + } + return result; + }; + Object.defineProperty(Engine.prototype, "registeredVariables", { + get: function () { + return this.state.registeredVariables; + }, + enumerable: true, + configurable: true + }); + /** + * Resets the engine state. Removes all backends but does not remove + * registered backend factories. + */ + Engine.prototype.reset = function () { + // Make any pending promise obsolete. + this.pendingBackendInitId++; + this.state.dispose(); + this.ENV.reset(); + this.state = new EngineState(); + for (var backendName in this.registry) { + this.disposeRegisteredKernels(backendName); + this.registry[backendName].dispose(); + delete this.registry[backendName]; + } + this.backendName = null; + this.backendInstance = null; + this.pendingBackendInit = null; + }; + Engine.nextTensorId = 0; + Engine.nextVariableId = 0; + return Engine; + }()); + function ones(shape) { + var values = makeOnesTypedArray(sizeFromShape(shape), 'float32'); + return ENGINE.makeTensor(values, shape, 'float32'); + } + function getOrMakeEngine() { + var ns = getGlobalNamespace(); + if (ns._tfengine == null) { + var environment = new Environment(ns); + ns._tfengine = new Engine(environment); + } + setEnvironmentGlobal(ns._tfengine.ENV); + // Tell the current tensor interface that the global engine is responsible + // for tracking. + setTensorTracker(function () { return ns._tfengine; }); + return ns._tfengine; + } + var ENGINE = getOrMakeEngine(); + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // tslint:disable-next-line:no-any + function _isNavigatorDefined() { + return typeof navigator !== 'undefined' && navigator != null; + } + function isMobile() { + if (_isNavigatorDefined()) { + // tslint:disable-next-line:no-any + var a = navigator.userAgent || navigator.vendor || window.opera; + // tslint:disable-next-line:max-line-length + return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i + .test(a) || + // tslint:disable-next-line:max-line-length + /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i + .test(a.substr(0, 4)); + } + return false; + } + function isBrowser() { + return (typeof window !== 'undefined' && window.document != null) || + //@ts-ignore + (typeof WorkerGlobalScope !== 'undefined'); + } + + var device_util = { + __proto__: null, + isMobile: isMobile, + isBrowser: isBrowser + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var ENV = env(); + /** + * This file contains environment-related flag registrations. + */ + /** Whether to enable debug mode. */ + ENV.registerFlag('DEBUG', function () { return false; }, function (debugValue) { + if (debugValue) { + console.warn('Debugging mode is ON. The output of every math call will ' + + 'be downloaded to CPU and checked for NaNs. ' + + 'This significantly impacts performance.'); + } + }); + /** Whether we are in a browser (as versus, say, node.js) environment. */ + ENV.registerFlag('IS_BROWSER', function () { return isBrowser(); }); + /** Whether we are in a browser (as versus, say, node.js) environment. */ + ENV.registerFlag('IS_NODE', function () { return (typeof process !== 'undefined') && + (typeof process.versions !== 'undefined') && + (typeof process.versions.node !== 'undefined'); }); + /** Whether this browser is Chrome. */ + ENV.registerFlag('IS_CHROME', function () { return typeof navigator !== 'undefined' && navigator != null && + navigator.userAgent != null && /Chrome/.test(navigator.userAgent) && + /Google Inc/.test(navigator.vendor); }); + /** + * True when the environment is "production" where we disable safety checks + * to gain performance. + */ + ENV.registerFlag('PROD', function () { return false; }); + /** + * Whether to do sanity checks when inferring a shape from user-provided + * values, used when creating a new tensor. + */ + ENV.registerFlag('TENSORLIKE_CHECK_SHAPE_CONSISTENCY', function () { return ENV.getBool('DEBUG'); }); + /** Whether deprecation warnings are enabled. */ + ENV.registerFlag('DEPRECATION_WARNINGS_ENABLED', function () { return true; }); + /** True if running unit tests. */ + ENV.registerFlag('IS_TEST', function () { return false; }); + + var Abs = 'Abs'; + var Acos = 'Acos'; + var Acosh = 'Acosh'; + var Add = 'Add'; + var AddN = 'AddN'; + var All = 'All'; + var Any = 'Any'; + var ArgMax = 'ArgMax'; + var ArgMin = 'ArgMin'; + var Asin = 'Asin'; + var Asinh = 'Asinh'; + var Atan = 'Atan'; + var Atanh = 'Atanh'; + var Atan2 = 'Atan2'; + var AvgPool = 'AvgPool'; + var AvgPoolBackprop = 'AvgPoolBackprop'; + var AvgPool3D = 'AvgPool3D'; + var AvgPool3DBackprop = 'AvgPool3DBackprop'; + var BatchMatMul = 'BatchMatMul'; + var BatchToSpaceND = 'BatchToSpaceND'; + var BroadcastTo = 'BroadcastTo'; + var Cast = 'Cast'; + var Ceil = 'Ceil'; + var ClipByValue = 'ClipByValue'; + var Complex = 'Complex'; + var Concat = 'Concat'; + var Conv2D = 'Conv2D'; + var Conv2DBackpropFilter = 'Conv2DBackpropFilter'; + var Conv2DBackpropInput = 'Conv2DBackpropInput'; + var Conv3D = 'Conv3D'; + var Conv3DBackpropFilterV2 = 'Conv3DBackpropFilterV2'; + var Conv3DBackpropInputV2 = 'Conv3DBackpropInputV2'; + var Cos = 'Cos'; + var Cosh = 'Cosh'; + var Cumsum = 'Cumsum'; + var CropAndResize = 'CropAndResize'; + var DepthToSpace = 'DepthToSpace'; + var DepthwiseConv2dNative = 'DepthwiseConv2dNative'; + var DepthwiseConv2dNativeBackpropFilter = 'DepthwiseConv2dNativeBackpropFilter'; + var DepthwiseConv2dNativeBackpropInput = 'DepthwiseConv2dNativeBackpropInput'; + var Diag = 'Diag'; + var Dilation2D = 'Dilation2D'; + var Dilation2DBackpropInput = 'Dilation2DBackpropInput'; + var Dilation2DBackpropFilter = 'Dilation2DBackpropFilter'; + var Div = 'Div'; + var Elu = 'Elu'; + var EluGrad = 'EluGrad'; + var Erf = 'Erf'; + var Equal = 'Equal'; + var Exp = 'Exp'; + var Expm1 = 'Expm1'; + var FFT = 'FFT'; + var Floor = 'Floor'; + var FloorDiv = 'FloorDiv'; + var Fill = 'Fill'; + var FusedBatchNorm = 'FusedBatchNorm'; + var GatherV2 = 'GatherV2'; + var GatherNd = 'GatherNd'; + var Greater = 'Greater'; + var GreaterEqual = 'GreaterEqual'; + var Identity = 'Identity'; + var IFFT = 'IFFT'; + var Imag = 'Imag'; + var IsFinite = 'IsFinite'; + var IsInf = 'IsInf'; + var IsNan = 'IsNan'; + var Less = 'Less'; + var LessEqual = 'LessEqual'; + var LinSpace = 'LinSpace'; + var Log = 'Log'; + var Log1p = 'Log1p'; + var LogicalAnd = 'LogicalAnd'; + var LogicalNot = 'LogicalNot'; + var LogicalOr = 'LogicalOr'; + var LogSoftmax = 'LogSoftmax'; + var LRN = 'LRN'; + var LRNBackprop = 'LRNBackprop'; + var Max = 'Max'; + var Maximum = 'Maximum'; + var MaxPool = 'MaxPool'; + var MaxPoolBackprop = 'MaxPoolBackprop'; + var MaxPool3D = 'MaxPool3D'; + var MaxPool3DBackprop = 'MaxPool3DBackprop'; + var MaxPoolWithArgmax = 'MaxPoolWithArgmax'; + var Mean = 'Mean'; + var Min = 'Min'; + var Minimum = 'Minimum'; + var Mod = 'Mod'; + var Multiply = 'Multiply'; + var Negate = 'Negate'; + var NotEqual = 'NotEqual'; + var NonMaxSuppressionV3 = 'NonMaxSuppressionV3'; + var NonMaxSuppressionV4 = 'NonMaxSuppressionV4'; + var NonMaxSuppressionV5 = 'NonMaxSuppressionV5'; + var OnesLike = 'OnesLike'; + var OneHot = 'OneHot'; + var PadV2 = 'PadV2'; + var Pool = 'Pool'; + var Pow = 'Pow'; + var Prelu = 'Prelu'; + var Prod = 'Prod'; + var Range = 'Range'; + var Real = 'Real'; + var Reciprocal = 'Reciprocal'; + var Relu = 'Relu'; + var Reshape = 'Reshape'; + var ResizeNearestNeighbor = 'ResizeNearestNeighbor'; + var ResizeNearestNeighborGrad = 'ResizeNearestNeighborGrad'; + var ResizeBilinear = 'ResizeBilinear'; + var ResizeBilinearGrad = 'ResizeBilinearGrad'; + var Relu6 = 'Relu6'; + var Reverse = 'Reverse'; + var Round = 'Round'; + var Rsqrt = 'Rsqrt'; + var ScatterNd = 'ScatterNd'; + var SelectV2 = 'SelectV2'; + var Selu = 'Selu'; + var Slice = 'Slice'; + var Sin = 'Sin'; + var Sinh = 'Sinh'; + var Sign = 'Sign'; + var Sigmoid = 'Sigmoid'; + var Softplus = 'Softplus'; + var Sqrt = 'Sqrt'; + var Sum = 'Sum'; + var SpaceToBatchND = 'SpaceToBatchND'; + var SplitV = 'SplitV'; + var Softmax = 'Softmax'; + var SquaredDifference = 'SquaredDifference'; + var Square = 'Square'; + var Sub = 'Sub'; + var SparseToDense = 'SparseToDense'; + var StridedSlice = 'StridedSlice'; + var Tan = 'Tan'; + var Tanh = 'Tanh'; + var Tile = 'Tile'; + var TopK = 'TopK'; + var Transpose = 'Transpose'; + var Unpack = 'Unpack'; + var UnsortedSegmentSum = 'UnsortedSegmentSum'; + var ZerosLike = 'ZerosLike'; + /** + * TensorFlow.js-only kernels + */ + var Step = 'Step'; + var FromPixels = 'FromPixels'; + var RotateWithOffset = 'RotateWithOffset'; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function inferShape(val, dtype) { + var firstElem = val; + if (isTypedArray(val)) { + return dtype === 'string' ? [] : [val.length]; + } + if (!Array.isArray(val)) { + return []; // Scalar. + } + var shape = []; + while (Array.isArray(firstElem) || + isTypedArray(firstElem) && dtype !== 'string') { + shape.push(firstElem.length); + firstElem = firstElem[0]; + } + if (Array.isArray(val) && + env().getBool('TENSORLIKE_CHECK_SHAPE_CONSISTENCY')) { + deepAssertShapeConsistency(val, shape, []); + } + return shape; + } + function deepAssertShapeConsistency(val, shape, indices) { + indices = indices || []; + if (!(Array.isArray(val)) && !isTypedArray(val)) { + assert(shape.length === 0, function () { return "Element arr[" + indices.join('][') + "] is a primitive, " + + ("but should be an array/TypedArray of " + shape[0] + " elements"); }); + return; + } + assert(shape.length > 0, function () { return "Element arr[" + indices.join('][') + "] should be a primitive, " + + ("but is an array of " + val.length + " elements"); }); + assert(val.length === shape[0], function () { return "Element arr[" + indices.join('][') + "] should have " + shape[0] + " " + + ("elements, but has " + val.length + " elements"); }); + var subShape = shape.slice(1); + for (var i = 0; i < val.length; ++i) { + deepAssertShapeConsistency(val[i], subShape, indices.concat(i)); + } + } + function assertDtype(expectedDtype, actualDType, argName, functionName) { + if (expectedDtype == null) { + return; + } + if (expectedDtype !== 'numeric' && expectedDtype !== actualDType || + expectedDtype === 'numeric' && actualDType === 'string') { + throw new Error("Argument '" + argName + "' passed to '" + functionName + "' must " + + ("be " + expectedDtype + " tensor, but got " + actualDType + " tensor")); + } + } + function convertToTensor(x, argName, functionName, parseAsDtype) { + if (parseAsDtype === void 0) { parseAsDtype = 'numeric'; } + if (x instanceof Tensor) { + assertDtype(parseAsDtype, x.dtype, argName, functionName); + return x; + } + var inferredDtype = inferDtype(x); + // If the user expects a bool/int/float, use that info to update the + // inferredDtype when it is not a string. + if (inferredDtype !== 'string' && + ['bool', 'int32', 'float32'].indexOf(parseAsDtype) >= 0) { + inferredDtype = parseAsDtype; + } + assertDtype(parseAsDtype, inferredDtype, argName, functionName); + if ((x == null) || + (!isTypedArray(x) && !Array.isArray(x) && typeof x !== 'number' && + typeof x !== 'boolean' && typeof x !== 'string')) { + var type = x == null ? 'null' : x.constructor.name; + throw new Error("Argument '" + argName + "' passed to '" + functionName + "' must be a " + + ("Tensor or TensorLike, but got '" + type + "'")); + } + var inferredShape = inferShape(x, inferredDtype); + if (!isTypedArray(x) && !Array.isArray(x)) { + x = [x]; + } + var skipTypedArray = true; + var values = inferredDtype !== 'string' ? + toTypedArray(x, inferredDtype) : + flatten(x, [], skipTypedArray); + return ENGINE.makeTensor(values, inferredShape, inferredDtype); + } + function convertToTensorArray(arg, argName, functionName, parseAsDtype) { + if (parseAsDtype === void 0) { parseAsDtype = 'numeric'; } + if (!Array.isArray(arg)) { + throw new Error("Argument " + argName + " passed to " + functionName + " must be a " + + '`Tensor[]` or `TensorLike[]`'); + } + var tensors = arg; + return tensors.map(function (t, i) { return convertToTensor(t, argName + "[" + i + "]", functionName); }, parseAsDtype); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Used for wrapping functions that perform math operations on + * Tensors. The function will be wrapped in a named scope that cleans all + * memory usage after the function is done. + */ + function op(f) { + var keys = Object.keys(f); + if (keys.length !== 1) { + throw new Error("Please provide an object with a single key " + + "(operation name) mapping to a function. Got an object with " + + (keys.length + " keys.")); + } + var opName = keys[0]; + var fn = f[opName]; + // Strip the underscore from the end of the function name. + if (opName.endsWith('_')) { + opName = opName.substring(0, opName.length - 1); + } + // tslint:disable-next-line:no-any + var f2 = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + ENGINE.startScope(opName); + try { + var result = fn.apply(void 0, args); + if (result instanceof Promise) { + console.error('Cannot return a Promise inside of tidy.'); + } + ENGINE.endScope(result); + return result; + } + catch (ex) { + ENGINE.endScope(null); + throw ex; + } + }; + Object.defineProperty(f2, 'name', { value: opName, configurable: true }); + // tslint:disable-next-line:no-any + return f2; + } + + /** + * @license + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Casts a `tf.Tensor` to a new dtype. + * + * ```js + * const x = tf.tensor1d([1.5, 2.5, 3]); + * tf.cast(x, 'int32').print(); + * ``` + * @param x The input tensor to be casted. + * @param dtype The dtype to cast the input tensor to. + */ + /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ + function cast_(x, dtype) { + var $x = convertToTensor(x, 'x', 'cast'); + // Sanity checks. + if (!isValidDtype(dtype)) { + throw new Error("Failed to cast to unknown dtype " + dtype); + } + if (dtype === 'string' && $x.dtype !== 'string' || + dtype !== 'string' && $x.dtype === 'string') { + throw new Error('Only strings can be casted to strings'); + } + var inputs = { x: $x }; + var attrs = { dtype: dtype }; + return ENGINE.runKernelFunc(function (backend) { return backend.cast($x, dtype); }, inputs, null /* grad */, Cast, attrs); + } + var cast = op({ cast_: cast_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Multiplies two `tf.Tensor`s element-wise, A * B. Supports broadcasting. + * + * We also expose `tf.mulStrict` which has the same signature as this op and + * asserts that `a` and `b` are the same shape (does not broadcast). + * + * ```js + * const a = tf.tensor1d([1, 2, 3, 4]); + * const b = tf.tensor1d([2, 3, 4, 5]); + * + * a.mul(b).print(); // or tf.mul(a, b) + * ``` + * + * ```js + * // Broadcast mul a with b. + * const a = tf.tensor1d([1, 2, 3, 4]); + * const b = tf.scalar(5); + * + * a.mul(b).print(); // or tf.mul(a, b) + * ``` + * @param a The first tensor to multiply. + * @param b The second tensor to multiply. Must have the same dtype as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ + function mul_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'mul'); + var $b = convertToTensor(b, 'b', 'mul'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + var forward = function (backend, save) { + var res = backend.multiply($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Multiply); + } + var mul = op({ mul_: mul_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes step of the input `tf.Tensor` element-wise: `x > 0 ? 1 : alpha * x` + * + * ```js + * const x = tf.tensor1d([0, 2, -1, -3]); + * + * x.step(.5).print(); // or tf.step(x, .5) + * ``` + * @param x The input tensor. + * @param alpha The gradient when input is negative. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function step_(x, alpha) { + if (alpha === void 0) { alpha = 0.0; } + var $x = convertToTensor(x, 'x', 'step'); + var inputs = { x: $x }; + var attrs = { alpha: alpha }; + return ENGINE.runKernelFunc(function (backend) { return backend.step($x, alpha); }, inputs, null /* grad */, Step, attrs); + } + var step = op({ step_: step_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var absGradConfig = { + kernelName: Abs, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(dy, step(cast(x, 'float32'), -1)); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Divides two `tf.Tensor`s element-wise, A / B. Supports broadcasting. + * The result is rounded with floor function. + * + * + * ```js + * const a = tf.tensor1d([1, 4, 9, 16]); + * const b = tf.tensor1d([1, 2, 3, 4]); + * + * a.floorDiv(b).print(); // or tf.div(a, b) + * ``` + * + * ```js + * // Broadcast div a with b. + * const a = tf.tensor1d([2, 4, 6, 8]); + * const b = tf.scalar(2); + * + * a.floorDiv(b).print(); // or tf.floorDiv(a, b) + * ``` + * + * @param a The first tensor as the numerator. + * @param b The second tensor as the denominator. Must have the same dtype as + * `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ + function floorDiv_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'floorDiv'); + var $b = convertToTensor(b, 'b', 'floorDiv'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + var forward = function (backend, save) { + var res = backend.floorDiv($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, FloorDiv); + } + var floorDiv = op({ floorDiv_: floorDiv_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Divides two `tf.Tensor`s element-wise, A / B. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([1, 4, 9, 16]); + * const b = tf.tensor1d([1, 2, 3, 4]); + * + * a.div(b).print(); // or tf.div(a, b) + * ``` + * + * ```js + * // Broadcast div a with b. + * const a = tf.tensor1d([2, 4, 6, 8]); + * const b = tf.scalar(2); + * + * a.div(b).print(); // or tf.div(a, b) + * ``` + * + * @param a The first tensor as the numerator. + * @param b The second tensor as the denominator. Must have the same dtype as + * `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ + function div_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'div'); + var $b = convertToTensor(b, 'b', 'div'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + if ($a.dtype === 'int32' && $b.dtype === 'int32') { + return floorDiv($a, $b); + } + var forward = function (backend, save) { + var res = backend.realDivide($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + var attrs = {}; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Div, attrs); + } + var div = op({ div_: div_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes `-1 * x` element-wise. + * + * ```js + * const x = tf.tensor2d([1, 2, -2, 0], [2, 2]); + * + * x.neg().print(); // or tf.neg(x) + * ``` + * + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function neg_(x) { + var $x = convertToTensor(x, 'x', 'neg'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend) { return backend.neg($x); }, inputs, null /* grad */, Negate); + } + var neg = op({ neg_: neg_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** This is shared code across all tensor creation methods. */ + function makeTensor(values, shape, inferredShape, dtype) { + if (dtype == null) { + dtype = inferDtype(values); + } + if (dtype === 'complex64') { + throw new Error("Cannot construct a complex64 tensor directly. " + + "Please use tf.complex(real, imag)."); + } + if (!isTypedArray(values) && !Array.isArray(values) && + typeof values !== 'number' && typeof values !== 'boolean' && + typeof values !== 'string') { + throw new Error('values passed to tensor(values) must be a number/boolean/string or ' + + 'an array of numbers/booleans/strings, or a TypedArray'); + } + if (shape != null) { + assertNonNegativeIntegerDimensions(shape); + var providedSize_1 = sizeFromShape(shape); + var inferredSize_1 = sizeFromShape(inferredShape); + assert(providedSize_1 === inferredSize_1, function () { + return "Based on the provided shape, [" + shape + "], the tensor should have " + + (providedSize_1 + " values but has " + inferredSize_1); + }); + for (var i = 0; i < inferredShape.length; ++i) { + var inferred = inferredShape[i]; + var flatDimsDontMatch = i === inferredShape.length - 1 ? + inferred !== sizeFromShape(shape.slice(i)) : + true; + assert(inferredShape[i] === shape[i] || !flatDimsDontMatch, function () { return "Error creating a new Tensor. Inferred shape " + + ("(" + inferredShape + ") does not match the provided ") + + ("shape (" + shape + "). "); }); + } + } + if (!isTypedArray(values) && !Array.isArray(values)) { + values = [values]; + } + shape = shape || inferredShape; + values = dtype !== 'string' ? + toTypedArray(values, dtype) : + flatten(values, [], true); + return ENGINE.makeTensor(values, shape, dtype); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates rank-0 `tf.Tensor` (scalar) with the provided value and dtype. + * + * The same functionality can be achieved with `tf.tensor`, but in general + * we recommend using `tf.scalar` as it makes the code more readable. + * + * ```js + * tf.scalar(3.14).print(); + * ``` + * + * @param value The value of the scalar. + * @param dtype The data type. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function scalar(value, dtype) { + if (((isTypedArray(value) && dtype !== 'string') || Array.isArray(value)) && + dtype !== 'complex64') { + throw new Error('Error creating a new Scalar: value must be a primitive ' + + '(number|boolean|string)'); + } + if (dtype === 'string' && isTypedArray(value) && + !(value instanceof Uint8Array)) { + throw new Error('When making a scalar from encoded string, ' + + 'the value must be `Uint8Array`.'); + } + var shape = []; + var inferredShape = []; + return makeTensor(value, shape, inferredShape, dtype); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes square root of the input `tf.Tensor` element-wise: `y = sqrt(x)` + * + * ```js + * const x = tf.tensor1d([1, 2, 4, -1]); + * + * x.sqrt().print(); // or tf.sqrt(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function sqrt_(x) { + var $x = convertToTensor(x, 'x', 'sqrt'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.sqrt($x); + save([$x]); + return res; + }, inputs, null /* grad */, Sqrt); + } + var sqrt = op({ sqrt_: sqrt_ }); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes square of `x` element-wise: `x ^ 2` + * + * ```js + * const x = tf.tensor1d([1, 2, Math.sqrt(2), -1]); + * + * x.square().print(); // or tf.square(x) + * ``` + * @param x The input Tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function square_(x) { + var $x = convertToTensor(x, 'x', 'square'); + var attrs = {}; + var inputsToSave = [$x]; + var outputsToSave = []; + return ENGINE.runKernelFunc(function (backend, save) { + save([$x]); + return backend.square($x); + }, { x: $x }, null /* grad */, 'Square', attrs, inputsToSave, outputsToSave); + } + var square = op({ square_: square_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Subtracts two `tf.Tensor`s element-wise, A - B. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([10, 20, 30, 40]); + * const b = tf.tensor1d([1, 2, 3, 4]); + * + * a.sub(b).print(); // or tf.sub(a, b) + * ``` + * + * ```js + * // Broadcast subtract a with b. + * const a = tf.tensor1d([10, 20, 30, 40]); + * const b = tf.scalar(5); + * + * a.sub(b).print(); // or tf.sub(a, b) + * ``` + * @param a The first `tf.Tensor` to subtract from. + * @param b The second `tf.Tensor` to be subtracted. Must have the same dtype as + * `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ + function sub_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'sub'); + var $b = convertToTensor(b, 'b', 'sub'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + var forward = function (backend, save) { + var res = backend.subtract($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Sub); + } + var sub = op({ sub_: sub_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var acosGradConfig = { + kernelName: Acos, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { + x: function () { + var a = square(cast(x, 'float32')); + var b = sqrt(sub(scalar(1), a)); + return neg(div(dy, b)); + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var acoshGradConfig = { + kernelName: Acosh, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { + x: function () { + var a = sqrt(sub(square(cast(x, 'float32')), 1)); + return div(dy, a); + } + }; + } + }; + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the dimensions in the input shape that are broadcasted to + * produce the provided output shape. + * + * The returned dimensions are 0-indexed and sorted. An example: + * inShape = [4, 1, 3] + * outShape = [5, 4, 3, 3] + * result = [1]. Dimension 1 (2nd dimension of input) gets broadcasted 1 => 3. + */ + function getBroadcastDims(inShape, outShape) { + var inRank = inShape.length; + var dims = []; + for (var i = 0; i < inRank; i++) { + var dim = inRank - 1 - i; + var a = inShape[dim] || 1; + var b = outShape[outShape.length - 1 - i] || 1; + if (b > 1 && a === 1) { + dims.unshift(dim); + } + } + return dims; + } + /** + * Returns the axes in the output space that should be reduced to produce + * the input space. + */ + function getReductionAxes(inShape, outShape) { + var result = []; + for (var i = 0; i < outShape.length; i++) { + var inDim = inShape[inShape.length - i - 1]; + var outAxis = outShape.length - i - 1; + var outDim = outShape[outAxis]; + if (inDim == null || (inDim === 1 && outDim > 1)) { + result.unshift(outAxis); + } + } + return result; + } + function assertAndGetBroadcastShape(shapeA, shapeB) { + var result = []; + var l = Math.max(shapeA.length, shapeB.length); + for (var i = 0; i < l; i++) { + var a = shapeA[shapeA.length - i - 1]; + if (a == null) { + a = 1; + } + var b = shapeB[shapeB.length - i - 1]; + if (b == null) { + b = 1; + } + if (a === 1) { + result.unshift(b); + } + else if (b === 1) { + result.unshift(a); + } + else if (a !== b) { + var errMsg = "Operands could not be broadcast together with shapes " + + (shapeA + " and " + shapeB + "."); + throw Error(errMsg); + } + else { + result.unshift(a); + } + } + return result; + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var addGradConfig = { + kernelName: Add, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var outShape = assertAndGetBroadcastShape(a.shape, b.shape); + var derA = function () { + var res = dy; + var reduceAxes = getReductionAxes(a.shape, outShape); + if (reduceAxes.length > 0) { + res = res.sum(reduceAxes); + } + return res.reshape(a.shape); + }; + var derB = function () { + var res = dy; + var reduceAxes = getReductionAxes(b.shape, outShape); + if (reduceAxes.length > 0) { + res = res.sum(reduceAxes); + } + return res.reshape(b.shape); + }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var addNGradConfig = { + kernelName: AddN, + saveAllInputs: true, + gradFunc: function (dy, saved) { + var ders = {}; + saved.forEach(function (_, i) { + ders[i] = function () { return dy.clone(); }; + }); + return ders; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates a `tf.Tensor` with all elements set to 0 with the same shape as the + * given tensor. + * + * ```js + * const x = tf.tensor([1, 2]); + * tf.zerosLike(x).print(); + * ``` + * + * @param x The tensor of required shape. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function zerosLike_(x) { + var $x = convertToTensor(x, 'x', 'zerosLike'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend) { return backend.zerosLike($x); }, inputs, null /* grad */, ZerosLike); + } + var zerosLike = op({ zerosLike_: zerosLike_ }); + + /** + * @license + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var argMaxGradConfig = { + kernelName: ArgMax, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return zerosLike(x); } }; + } + }; + + /** + * @license + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var argMinGradConfig = { + kernelName: ArgMin, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return zerosLike(x); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var asinGradConfig = { + kernelName: Asin, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, sqrt(sub(scalar(1), square(cast(x, 'float32'))))); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Adds two `tf.Tensor`s element-wise, A + B. Supports broadcasting. + * + * + * ```js + * const a = tf.tensor1d([1, 2, 3, 4]); + * const b = tf.tensor1d([10, 20, 30, 40]); + * + * a.add(b).print(); // or tf.add(a, b) + * ``` + * + * ```js + * // Broadcast add a with b. + * const a = tf.scalar(5); + * const b = tf.tensor1d([10, 20, 30, 40]); + * + * a.add(b).print(); // or tf.add(a, b) + * ``` + * @param a The first `tf.Tensor` to add. + * @param b The second `tf.Tensor` to add. Must have the same type as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ + function add_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'add'); + var $b = convertToTensor(b, 'b', 'add'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + var forward = function (backend, save) { + var res = backend.add($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Add); + } + var add = op({ add_: add_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var asinhGradConfig = { + kernelName: Asinh, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { + x: function () { + var a = sqrt(add(scalar(1), square(cast(x, 'float32')))); + return div(dy, a); + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Reshapes a `tf.Tensor` to a given shape. + * + * Given an input tensor, returns a new tensor with the same values as the + * input tensor with shape `shape`. + * + * If one component of shape is the special value -1, the size of that + * dimension is computed so that the total size remains constant. In + * particular, a shape of [-1] flattens into 1-D. At most one component of + * shape can be -1. + * + * If shape is 1-D or higher, then the operation returns a tensor with shape + * shape filled with the values of tensor. In this case, the number of + * elements implied by shape must be the same as the number of elements in + * tensor. + * + * ```js + * const x = tf.tensor1d([1, 2, 3, 4]); + * x.reshape([2, 2]).print(); + * ``` + * + * @param x The input tensor to be reshaped. + * @param shape An array of integers defining the output tensor shape. + */ + /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ + function reshape_(x, shape) { + var $x = convertToTensor(x, 'x', 'reshape', null); + shape = inferFromImplicitShape(shape, $x.size); + assert($x.size === sizeFromShape(shape), function () { return 'new shape and old shape must have the same number of elements.'; }); + var inputs = { x: $x }; + var attrs = { shape: shape }; + var forward = function (backend, save) { + save([$x]); + return backend.reshape($x, shape); + }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Reshape, attrs); + } + var reshape = op({ reshape_: reshape_ }); + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns true if the axis specifies the inner most dimensions of the + * array. + */ + function axesAreInnerMostDims(axes, rank) { + for (var i = 0; i < axes.length; ++i) { + if (axes[axes.length - i - 1] !== rank - 1 - i) { + return false; + } + } + return true; + } + function combineLocations(outputLoc, reduceLoc, axes) { + var rank = outputLoc.length + reduceLoc.length; + var loc = []; + var outIdx = 0; + var reduceIdx = 0; + for (var dim = 0; dim < rank; dim++) { + if (axes.indexOf(dim) === -1) { + loc.push(outputLoc[outIdx++]); + } + else { + loc.push(reduceLoc[reduceIdx++]); + } + } + return loc; + } + function computeOutAndReduceShapes(aShape, axes) { + var outShape = []; + var rank = aShape.length; + for (var dim = 0; dim < rank; dim++) { + if (axes.indexOf(dim) === -1) { + outShape.push(aShape[dim]); + } + } + var reduceShape = axes.map(function (dim) { return aShape[dim]; }); + return [outShape, reduceShape]; + } + function expandShapeToKeepDim(shape, axes) { + var reduceSubShape = axes.map(function (x) { return 1; }); + return combineLocations(shape, reduceSubShape, axes); + } + function assertAxesAreInnerMostDims(msg, axes, rank) { + assert(axesAreInnerMostDims(axes, rank), function () { return msg + " supports only inner-most axes for now. " + + ("Got axes " + axes + " and rank-" + rank + " input."); }); + } + /** + * Returns the axes permutation to be used with `tf.transpose`, if such + * permutation is necessary. Otherwise it returns null. This method is used by + * operations that operate only on inner-most axes. + */ + function getAxesPermutation(axes, rank) { + if (axesAreInnerMostDims(axes, rank)) { + return null; + } + var result = []; + for (var i = 0; i < rank; ++i) { + if (axes.indexOf(i) === -1) { + result.push(i); + } + } + axes.forEach(function (axis) { return result.push(axis); }); + return result; + } + /** Returns the axes permutation that undoes the original permutation. */ + function getUndoAxesPermutation(axes) { + return axes.map(function (axis, i) { return [i, axis]; }) + .sort(function (a, b) { return a[1] - b[1]; }) + .map(function (x) { return x[0]; }); + } + function getInnerMostAxes(numAxes, rank) { + var res = []; + for (var i = rank - numAxes; i < rank; ++i) { + res.push(i); + } + return res; + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the sum of elements across dimensions of a `tf.Tensor`. + * + * Reduces the input along the dimensions given in `axes`. Unless `keepDims` + * is true, the rank of the `tf.Tensor` is reduced by 1 for each entry in + * `axes`. If `keepDims` is true, the reduced dimensions are retained with + * length 1. If axes has no entries, all dimensions are reduced, and a + * `tf.Tensor` with a single element is returned. + * + * ```js + * const x = tf.tensor1d([1, 2, 3]); + * + * x.sum().print(); // or tf.sum(x) + * ``` + * + * ```js + * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); + * + * const axis = 1; + * x.sum(axis).print(); // or tf.sum(x, axis) + * ``` + * + * @param x The input tensor to compute the sum over. If the dtype is `bool` + * it will be converted to `int32` and the output dtype will be `int32`. + * @param axis The dimension(s) to reduce. By default it reduces + * all dimensions. + * @param keepDims If true, retains reduced dimensions with size 1. + */ + /** @doc {heading: 'Operations', subheading: 'Reduction'} */ + function sum_(x, axis, keepDims) { + if (axis === void 0) { axis = null; } + if (keepDims === void 0) { keepDims = false; } + var $x = convertToTensor(x, 'x', 'sum'); + if ($x.dtype === 'bool') { + $x = $x.toInt(); + } + var forward = function (backend, save) { + save([$x]); + var axes = parseAxisParam(axis, $x.shape); + var permutation = getAxesPermutation(axes, $x.rank); + var reductionAxes = axes; + var permutedX = $x; + if (permutation != null) { + permutedX = $x.transpose(permutation); + reductionAxes = getInnerMostAxes(reductionAxes.length, $x.rank); + } + var value = backend.sum(permutedX, reductionAxes); + if (keepDims) { + var newShape = expandShapeToKeepDim(value.shape, axes); + value = value.reshape(newShape); + } + return value; + }; + var inputs = { x: $x }; + var attrs = { axis: axis, keepDims: keepDims }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Sum, attrs); + } + var sum$1 = op({ sum_: sum_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var atan2GradConfig = { + kernelName: Atan2, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var outShape = assertAndGetBroadcastShape(a.shape, b.shape); + var derA = function () { + var d = add(square(a), square(b)); + var res = mul(dy, div(b, d)); + var reduceAxes = getReductionAxes(a.shape, outShape); + if (reduceAxes.length > 0) { + res = sum$1(res, reduceAxes); + } + return reshape(res, a.shape); + }; + var derB = function () { + var d = add(square(a), square(b)); + var res = neg(mul(dy, div(a, d))); + var reduceAxes = getReductionAxes(b.shape, outShape); + if (reduceAxes.length > 0) { + res = sum$1(res, reduceAxes); + } + return reshape(res, b.shape); + }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var atanGradConfig = { + kernelName: Atan, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, add(square(cast(x, 'float32')), 1)); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var atanhGradConfig = { + kernelName: Atanh, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, sub(scalar(1), square(cast(x, 'float32')))); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * + * @param inputShape Input tensor shape is of the following dimensions: + * `[batch, height, width, inChannels]`. + * @param filterShape The filter shape is of the following dimensions: + * `[filterHeight, filterWidth, depth]`. + * @param strides The strides of the sliding window for each dimension of the + * input tensor: `[strideHeight, strideWidth]`. + * If `strides` is a single number, + * then `strideHeight == strideWidth`. + * @param pad The type of padding algorithm. + * - `same` and stride 1: output will be of same size as input, + * regardless of filter size. + * - `valid`: output will be smaller than input if filter is larger + * than 1*1x1. + * - For more info, see this guide: + * [https://www.tensorflow.org/api_guides/python/nn#Convolution]( + * https://www.tensorflow.org/api_guides/python/nn#Convolution) + * @param dataFormat The data format of the input and output data. + * Defaults to 'NHWC'. + * @param dilations The dilation rates: `[dilationHeight, dilationWidth]`. + * Defaults to `[1, 1]`. If `dilations` is a single number, then + * `dilationHeight == dilationWidth`. + */ + function computeDilation2DInfo(inputShape, filterShape, strides, pad, dataFormat, dilations) { + if (dataFormat === void 0) { dataFormat = 'NHWC'; } + // `computerConv2DInfo` require filterShape to be in the dimension of: + // `[filterHeight, filterWidth, depth, outDepth]`, dilation2d doesn't have + // outDepth, it should have the same depth as the input. + // Input shape: [batch, height, width, inChannels] + var inputChannels = inputShape[3]; + var $filterShape = filterShape.concat([inputChannels]); + var $dataFormat = convertConv2DDataFormat(dataFormat); + return computeConv2DInfo(inputShape, $filterShape, strides, dilations, pad, null /* roundingMode */, null /* depthWise */, $dataFormat); + } + function computePool2DInfo(inShape, filterSize, strides, dilations, pad, roundingMode, dataFormat) { + if (dataFormat === void 0) { dataFormat = 'channelsLast'; } + var _a = parseTupleParam(filterSize), filterHeight = _a[0], filterWidth = _a[1]; + var filterShape; + if (dataFormat === 'channelsLast') { + filterShape = [filterHeight, filterWidth, inShape[3], inShape[3]]; + } + else if (dataFormat === 'channelsFirst') { + filterShape = [filterHeight, filterWidth, inShape[1], inShape[1]]; + } + else { + throw new Error("Unknown dataFormat " + dataFormat); + } + return computeConv2DInfo(inShape, filterShape, strides, dilations, pad, roundingMode, false, dataFormat); + } + /** + * Computes the information for a forward pass of a pooling3D operation. + */ + function computePool3DInfo(inShape, filterSize, strides, dilations, pad, roundingMode, dataFormat) { + if (dataFormat === void 0) { dataFormat = 'NDHWC'; } + var _a = parse3TupleParam(filterSize), filterDepth = _a[0], filterHeight = _a[1], filterWidth = _a[2]; + var filterShape; + var $dataFormat; + if (dataFormat === 'NDHWC') { + $dataFormat = 'channelsLast'; + filterShape = + [filterDepth, filterHeight, filterWidth, inShape[4], inShape[4]]; + } + else if (dataFormat === 'NCDHW') { + $dataFormat = 'channelsFirst'; + filterShape = + [filterDepth, filterHeight, filterWidth, inShape[1], inShape[1]]; + } + else { + throw new Error("Unknown dataFormat " + dataFormat); + } + return computeConv3DInfo(inShape, filterShape, strides, dilations, pad, false, $dataFormat, roundingMode); + } + /** + * Computes the information for a forward pass of a convolution/pooling + * operation. + */ + function computeConv2DInfo(inShape, filterShape, strides, dilations, pad, roundingMode, depthwise, dataFormat) { + if (depthwise === void 0) { depthwise = false; } + if (dataFormat === void 0) { dataFormat = 'channelsLast'; } + var _a = [-1, -1, -1, -1], batchSize = _a[0], inHeight = _a[1], inWidth = _a[2], inChannels = _a[3]; + if (dataFormat === 'channelsLast') { + batchSize = inShape[0], inHeight = inShape[1], inWidth = inShape[2], inChannels = inShape[3]; + } + else if (dataFormat === 'channelsFirst') { + batchSize = inShape[0], inChannels = inShape[1], inHeight = inShape[2], inWidth = inShape[3]; + } + else { + throw new Error("Unknown dataFormat " + dataFormat); + } + var filterHeight = filterShape[0], filterWidth = filterShape[1], filterChannels = filterShape[3]; + var _b = parseTupleParam(strides), strideHeight = _b[0], strideWidth = _b[1]; + var _c = parseTupleParam(dilations), dilationHeight = _c[0], dilationWidth = _c[1]; + var effectiveFilterHeight = getEffectiveFilterSize(filterHeight, dilationHeight); + var effectiveFilterWidth = getEffectiveFilterSize(filterWidth, dilationWidth); + var _d = getPadAndOutInfo(pad, inHeight, inWidth, strideHeight, strideWidth, effectiveFilterHeight, effectiveFilterWidth, roundingMode, dataFormat), padInfo = _d.padInfo, outHeight = _d.outHeight, outWidth = _d.outWidth; + var outChannels = depthwise ? filterChannels * inChannels : filterChannels; + var outShape; + if (dataFormat === 'channelsFirst') { + outShape = [batchSize, outChannels, outHeight, outWidth]; + } + else if (dataFormat === 'channelsLast') { + outShape = [batchSize, outHeight, outWidth, outChannels]; + } + return { + batchSize: batchSize, + dataFormat: dataFormat, + inHeight: inHeight, + inWidth: inWidth, + inChannels: inChannels, + outHeight: outHeight, + outWidth: outWidth, + outChannels: outChannels, + padInfo: padInfo, + strideHeight: strideHeight, + strideWidth: strideWidth, + filterHeight: filterHeight, + filterWidth: filterWidth, + effectiveFilterHeight: effectiveFilterHeight, + effectiveFilterWidth: effectiveFilterWidth, + dilationHeight: dilationHeight, + dilationWidth: dilationWidth, + inShape: inShape, + outShape: outShape, + filterShape: filterShape + }; + } + /** + * Computes the information for a forward pass of a 3D convolution/pooling + * operation. + */ + function computeConv3DInfo(inShape, filterShape, strides, dilations, pad, depthwise, dataFormat, roundingMode) { + if (depthwise === void 0) { depthwise = false; } + if (dataFormat === void 0) { dataFormat = 'channelsLast'; } + var _a = [-1, -1, -1, -1, -1], batchSize = _a[0], inDepth = _a[1], inHeight = _a[2], inWidth = _a[3], inChannels = _a[4]; + if (dataFormat === 'channelsLast') { + batchSize = inShape[0], inDepth = inShape[1], inHeight = inShape[2], inWidth = inShape[3], inChannels = inShape[4]; + } + else if (dataFormat === 'channelsFirst') { + batchSize = inShape[0], inChannels = inShape[1], inDepth = inShape[2], inHeight = inShape[3], inWidth = inShape[4]; + } + else { + throw new Error("Unknown dataFormat " + dataFormat); + } + var filterDepth = filterShape[0], filterHeight = filterShape[1], filterWidth = filterShape[2], filterChannels = filterShape[4]; + var _b = parse3TupleParam(strides), strideDepth = _b[0], strideHeight = _b[1], strideWidth = _b[2]; + var _c = parse3TupleParam(dilations), dilationDepth = _c[0], dilationHeight = _c[1], dilationWidth = _c[2]; + var effectiveFilterDepth = getEffectiveFilterSize(filterDepth, dilationDepth); + var effectiveFilterHeight = getEffectiveFilterSize(filterHeight, dilationHeight); + var effectiveFilterWidth = getEffectiveFilterSize(filterWidth, dilationWidth); + var _d = get3DPadAndOutInfo(pad, inDepth, inHeight, inWidth, strideDepth, strideHeight, strideWidth, effectiveFilterDepth, effectiveFilterHeight, effectiveFilterWidth, roundingMode), padInfo = _d.padInfo, outDepth = _d.outDepth, outHeight = _d.outHeight, outWidth = _d.outWidth; + var outChannels = depthwise ? filterChannels * inChannels : filterChannels; + var outShape; + if (dataFormat === 'channelsFirst') { + outShape = [batchSize, outChannels, outDepth, outHeight, outWidth]; + } + else if (dataFormat === 'channelsLast') { + outShape = [batchSize, outDepth, outHeight, outWidth, outChannels]; + } + return { + batchSize: batchSize, + dataFormat: dataFormat, + inDepth: inDepth, + inHeight: inHeight, + inWidth: inWidth, + inChannels: inChannels, + outDepth: outDepth, + outHeight: outHeight, + outWidth: outWidth, + outChannels: outChannels, + padInfo: padInfo, + strideDepth: strideDepth, + strideHeight: strideHeight, + strideWidth: strideWidth, + filterDepth: filterDepth, + filterHeight: filterHeight, + filterWidth: filterWidth, + effectiveFilterDepth: effectiveFilterDepth, + effectiveFilterHeight: effectiveFilterHeight, + effectiveFilterWidth: effectiveFilterWidth, + dilationDepth: dilationDepth, + dilationHeight: dilationHeight, + dilationWidth: dilationWidth, + inShape: inShape, + outShape: outShape, + filterShape: filterShape + }; + } + function computeOutputShape2D(inShape, fieldSize, stride, zeroPad, roundingMode) { + if (zeroPad == null) { + zeroPad = computeDefaultPad(inShape, fieldSize, stride); + } + var inputRows = inShape[0]; + var inputCols = inShape[1]; + var outputRows = conditionalRound((inputRows - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); + assert(isInt(outputRows), function () { return "The output # of rows (" + outputRows + ") must be an integer. " + + "Change the stride and/or zero pad parameters"; }); + var outputCols = conditionalRound((inputCols - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); + assert(isInt(outputCols), function () { return "The output # of columns (" + outputCols + ") must be an integer. " + + "Change the stride and/or zero pad parameters"; }); + return [outputRows, outputCols]; + } + function computeOutputShape4D(inShape, fieldSize, outChannels, stride, zeroPad, roundingMode) { + if (zeroPad == null) { + zeroPad = computeDefaultPad(inShape, fieldSize, stride); + } + var inputDepth = inShape[0]; + var inputRows = inShape[1]; + var inputCols = inShape[2]; + var outputDepths = conditionalRound((inputDepth - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); + assert(isInt(outputDepths), function () { return "The output # of depths (" + outputDepths + ") must be an integer. " + + "Change the stride and/or zero pad parameters"; }); + var outputRows = conditionalRound((inputRows - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); + assert(isInt(outputRows), function () { return "The output # of rows (" + outputRows + ") must be an integer. " + + "Change the stride and/or zero pad parameters"; }); + var outputCols = conditionalRound((inputCols - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); + assert(isInt(outputCols), function () { return "The output # of columns (" + outputCols + ") must be an integer. " + + "Change the stride and/or zero pad parameters"; }); + return [outputDepths, outputRows, outputCols, outChannels]; + } + function computeDefaultPad(inputShape, fieldSize, stride, dilation) { + if (dilation === void 0) { dilation = 1; } + var effectiveFieldSize = getEffectiveFilterSize(fieldSize, dilation); + return Math.floor((inputShape[0] * (stride - 1) - stride + effectiveFieldSize) / 2); + } + function parseTupleParam(param) { + if (typeof param === 'number') { + return [param, param, param]; + } + if (param.length === 2) { + return [param[0], param[1], 1]; + } + return param; + } + function parse3TupleParam(param) { + return typeof param === 'number' ? [param, param, param] : param; + } + /* See https://www.tensorflow.org/api_docs/python/tf/nn/atrous_conv2d + * Atrous convolution is equivalent to standard convolution with upsampled + * filters with effective_filter_height = + * filter_height + (filter_height - 1) * (dilation - 1) + * and effective_filter_width = + * filter_width + (filter_width - 1) * (dilation - 1), + * produced by inserting dilation - 1 zeros along consecutive elements across + * the filters' spatial dimensions. + * When there is a dilation, this converts a filter dimension to the + * effective filter dimension, so it can be used in a standard convolution. + */ + function getEffectiveFilterSize(filterSize, dilation) { + if (dilation <= 1) { + return filterSize; + } + return filterSize + (filterSize - 1) * (dilation - 1); + } + function getPadAndOutInfo(pad, inHeight, inWidth, strideHeight, strideWidth, filterHeight, filterWidth, roundingMode, dataFormat) { + var padInfo; + var outHeight; + var outWidth; + if (typeof pad === 'number') { + var padType = (pad === 0) ? 'VALID' : 'NUMBER'; + padInfo = { top: pad, bottom: pad, left: pad, right: pad, type: padType }; + var outShape = computeOutputShape2D([inHeight, inWidth], filterHeight, strideHeight, pad, roundingMode); + outHeight = outShape[0]; + outWidth = outShape[1]; + } + else if (pad === 'same') { + outHeight = Math.ceil(inHeight / strideHeight); + outWidth = Math.ceil(inWidth / strideWidth); + var padAlongHeight = Math.max(0, (outHeight - 1) * strideHeight + filterHeight - inHeight); + var padAlongWidth = Math.max(0, (outWidth - 1) * strideWidth + filterWidth - inWidth); + var top_1 = Math.floor(padAlongHeight / 2); + var bottom = padAlongHeight - top_1; + var left = Math.floor(padAlongWidth / 2); + var right = padAlongWidth - left; + padInfo = { top: top_1, bottom: bottom, left: left, right: right, type: 'SAME' }; + } + else if (pad === 'valid') { + padInfo = { top: 0, bottom: 0, left: 0, right: 0, type: 'VALID' }; + outHeight = Math.ceil((inHeight - filterHeight + 1) / strideHeight); + outWidth = Math.ceil((inWidth - filterWidth + 1) / strideWidth); + } + else if (typeof pad === 'object') { + var top_2 = dataFormat === 'channelsLast' ? pad[1][0] : pad[2][0]; + var bottom = dataFormat === 'channelsLast' ? pad[1][1] : pad[2][1]; + var left = dataFormat === 'channelsLast' ? pad[2][0] : pad[3][0]; + var right = dataFormat === 'channelsLast' ? pad[2][1] : pad[3][1]; + var padType = (top_2 === 0 && bottom === 0 && left === 0 && right === 0) ? + 'VALID' : + 'EXPLICIT'; + padInfo = { top: top_2, bottom: bottom, left: left, right: right, type: padType }; + outHeight = conditionalRound((inHeight - filterHeight + top_2 + bottom) / strideHeight + 1, roundingMode); + outWidth = conditionalRound((inWidth - filterWidth + left + right) / strideWidth + 1, roundingMode); + } + else { + throw Error("Unknown padding parameter: " + pad); + } + return { padInfo: padInfo, outHeight: outHeight, outWidth: outWidth }; + } + function get3DPadAndOutInfo(pad, inDepth, inHeight, inWidth, strideDepth, strideHeight, strideWidth, filterDepth, filterHeight, filterWidth, roundingMode) { + var padInfo; + var outDepth; + var outHeight; + var outWidth; + if (typeof pad === 'number') { + var padType = (pad === 0) ? 'VALID' : 'NUMBER'; + padInfo = { + top: pad, + bottom: pad, + left: pad, + right: pad, + front: pad, + back: pad, + type: padType + }; + var outShape = computeOutputShape4D([inDepth, inHeight, inWidth, 1], filterDepth, 1, strideDepth, pad, roundingMode); + outDepth = outShape[0]; + outHeight = outShape[1]; + outWidth = outShape[2]; + } + else if (pad === 'same') { + outDepth = Math.ceil(inDepth / strideDepth); + outHeight = Math.ceil(inHeight / strideHeight); + outWidth = Math.ceil(inWidth / strideWidth); + var padAlongDepth = (outDepth - 1) * strideDepth + filterDepth - inDepth; + var padAlongHeight = (outHeight - 1) * strideHeight + filterHeight - inHeight; + var padAlongWidth = (outWidth - 1) * strideWidth + filterWidth - inWidth; + var front = Math.floor(padAlongDepth / 2); + var back = padAlongDepth - front; + var top_3 = Math.floor(padAlongHeight / 2); + var bottom = padAlongHeight - top_3; + var left = Math.floor(padAlongWidth / 2); + var right = padAlongWidth - left; + padInfo = { top: top_3, bottom: bottom, left: left, right: right, front: front, back: back, type: 'SAME' }; + } + else if (pad === 'valid') { + padInfo = { + top: 0, + bottom: 0, + left: 0, + right: 0, + front: 0, + back: 0, + type: 'VALID' + }; + outDepth = Math.ceil((inDepth - filterDepth + 1) / strideDepth); + outHeight = Math.ceil((inHeight - filterHeight + 1) / strideHeight); + outWidth = Math.ceil((inWidth - filterWidth + 1) / strideWidth); + } + else { + throw Error("Unknown padding parameter: " + pad); + } + return { padInfo: padInfo, outDepth: outDepth, outHeight: outHeight, outWidth: outWidth }; + } + /** + * Rounds a value depending on the rounding mode + * @param value + * @param roundingMode + */ + function conditionalRound(value, roundingMode) { + if (!roundingMode) { + return value; + } + switch (roundingMode) { + case 'round': + // used for Caffe Conv + return Math.round(value); + case 'ceil': + // used for Caffe Pool + return Math.ceil(value); + case 'floor': + return Math.floor(value); + default: + throw new Error("Unknown roundingMode " + roundingMode); + } + } + function tupleValuesAreOne(param) { + var _a = parseTupleParam(param), dimA = _a[0], dimB = _a[1], dimC = _a[2]; + return dimA === 1 && dimB === 1 && dimC === 1; + } + function eitherStridesOrDilationsAreOne(strides, dilations) { + return tupleValuesAreOne(strides) || tupleValuesAreOne(dilations); + } + /** + * Convert Conv2D dataFormat from 'NHWC'|'NCHW' to + * 'channelsLast'|'channelsFirst' + * @param dataFormat in 'NHWC'|'NCHW' mode + * @return dataFormat in 'channelsLast'|'channelsFirst' mode + * @throws unknown dataFormat + */ + function convertConv2DDataFormat(dataFormat) { + if (dataFormat === 'NHWC') { + return 'channelsLast'; + } + else if (dataFormat === 'NCHW') { + return 'channelsFirst'; + } + else { + throw new Error("Unknown dataFormat " + dataFormat); + } + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the backprop of a 3d avg pool. + * + * @param dy The dy error, of rank 5 of shape + * [batchSize, depth, height, width, channels]. + * assumed. + * @param input The original input image, of rank 5 or rank4 of shape + * [batchSize, depth, height, width, channels]. + * @param filterSize The filter size: + * `[filterDepth, filterHeight, filterWidth]`. + * `filterSize` is a single number, + * then `filterDepth == filterHeight == filterWidth`. + * @param strides The strides of the pooling: + * `[strideDepth, strideHeight, strideWidth]`. If + * `strides` is a single number, then `strideHeight == strideWidth`. + * @param dilations Deprecated, this field will be gone in v3.0.0. The dilation + * rates: `[dilationDepth, dilationHeight, dilationWidth]` + * in which we sample input values across the depth, height and width + * dimensions in dilated pooling. + * Defaults to `[1, 1, 1]`. If `dilations` is a single number, + * then `dilationDepth == dilationHeight == dilationWidth`. + * If it is greater than 1, then all values of `strides` must be 1. + * @param pad A string from: 'same', 'valid'. The type of padding algorithm + * used in the forward prop of the op. + * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The + * rounding mode used when computing output dimensions if pad is a + * number. If none is provided, it will not round and error if the output + * is of fractional size. + */ + function avgPool3dBackprop_(dy, input, filterSize, strides, dilations, pad, dimRoundingMode) { + if (dilations === void 0) { dilations = [1, 1, 1]; } + var $dy = convertToTensor(dy, 'dy', 'avgPool3dBackprop'); + var $input = convertToTensor(input, 'input', 'avgPool3dBackprop'); + var dy5D = $dy; + var input5D = $input; + var reshapedTo5D = false; + if ($input.rank === 4) { + reshapedTo5D = true; + dy5D = reshape($dy, [1, $dy.shape[0], $dy.shape[1], $dy.shape[2], $dy.shape[3]]); + input5D = reshape($input, [ + 1, $input.shape[0], $input.shape[1], $input.shape[2], $input.shape[3] + ]); + } + assert(dy5D.rank === 5, function () { return "Error in avgPool3dBackprop: dy must be rank 5 but got rank " + + (dy5D.rank + "."); }); + assert(input5D.rank === 5, function () { return "Error in avgPool3dBackprop: input must be rank 5 but got rank " + + (input5D.rank + "."); }); + assert(eitherStridesOrDilationsAreOne(strides, dilations), function () { return 'Error in avgPool3dBackprop: Either strides or dilations ' + + ("must be 1. Got strides " + strides + " and dilations '" + dilations + "'"); }); + if (dimRoundingMode != null) { + assert(isInt(pad), function () { return "Error in maxPool3dBackprop: pad must be an integer when " + + ("using, dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); + } + var forward = function (backend) { + var convInfo = computePool3DInfo(input5D.shape, filterSize, strides, dilations, pad, dimRoundingMode); + return backend.avgPool3dBackprop(dy5D, input5D, convInfo); + }; + var inputs = { dy: dy5D, input: input5D }; + var attrs = { filterSize: filterSize, strides: strides, dilations: dilations, pad: pad, dimRoundingMode: dimRoundingMode }; + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, AvgPool3DBackprop, attrs); + if (reshapedTo5D) { + return reshape(res, [res.shape[1], res.shape[2], res.shape[3], res.shape[4]]); + } + return res; + } + var avgPool3dBackprop = op({ avgPool3dBackprop_: avgPool3dBackprop_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var avgPool3DGradConfig = { + kernelName: AvgPool3D, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0]; + var _a = attrs, filterSize = _a.filterSize, strides = _a.strides, dilations = _a.dilations, pad = _a.pad, dimRoundingMode = _a.dimRoundingMode; + var $dilations = dilations == null ? [1, 1, 1] : dilations; + return { + x: function () { return avgPool3dBackprop(dy, x, filterSize, strides, $dilations, pad, dimRoundingMode); } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the backprop of an 2D avg pool. + * + * @param dy The dy error, of rank 4 or rank 3 of shape + * [batchSize, height, width, channels]. If rank 3, batch of 1 is + * assumed. + * @param input The input image, of rank 4 or rank 3 of shape + * [batchSize, height, width, channels]. If rank 3, batch of 1 is + * assumed. + * @param filterSize The filter size: `[filterHeight, filterWidth]`. If + * `filterSize` is a single number, then `filterHeight == filterWidth`. + * @param strides The strides of the pooling: `[strideHeight, strideWidth]`. If + * `strides` is a single number, then `strideHeight == strideWidth`. + * @param pad A string from: 'same', 'valid'. The type of padding algorithm + * used in the forward prop of the op. + */ + function avgPoolBackprop_(dy, input, filterSize, strides, pad) { + var $dy = convertToTensor(dy, 'dy', 'avgPoolBackprop'); + var $input = convertToTensor(input, 'input', 'avgPoolBackprop'); + assert($input.rank === $dy.rank, function () { return "Rank of input (" + $input.rank + ") does not match rank of dy (" + $dy.rank + ")"; }); + var input4D = $input; + var dy4D = $dy; + var reshapedTo4D = false; + if ($input.rank === 3) { + reshapedTo4D = true; + input4D = + reshape($input, [1, $input.shape[0], $input.shape[1], $input.shape[2]]); + dy4D = reshape($dy, [1, $dy.shape[0], $dy.shape[1], $dy.shape[2]]); + } + assert(dy4D.rank === 4, function () { return "Error in avgPoolBackprop: dy must be rank 4 but got rank " + + (dy4D.rank + "."); }); + assert(input4D.rank === 4, function () { return "Error in avgPoolBackprop: input must be rank 4 but got rank " + + (input4D.rank + "."); }); + var forward = function (backend) { + var convInfo = computePool2DInfo(input4D.shape, filterSize, strides, 1 /* dilations */, pad); + return backend.avgPoolBackprop(dy4D, input4D, convInfo); + }; + var inputs = { dy: dy4D, input: input4D }; + var attrs = { filterSize: filterSize, strides: strides, pad: pad }; + var res = ENGINE.runKernelFunc(forward, inputs, null, AvgPoolBackprop, attrs); + if (reshapedTo4D) { + return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); + } + return res; + } + var avgPoolBackprop = op({ avgPoolBackprop_: avgPoolBackprop_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var avgPoolGradConfig = { + kernelName: AvgPool, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0]; + var _a = attrs, filterSize = _a.filterSize, strides = _a.strides, pad = _a.pad; + return { + x: function () { return avgPoolBackprop(dy, x, filterSize, strides, pad); } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the dot product of two matrices, A * B. These must be matrices. + * + * ```js + * const a = tf.tensor2d([1, 2], [1, 2]); + * const b = tf.tensor2d([1, 2, 3, 4], [2, 2]); + * + * a.matMul(b).print(); // or tf.matMul(a, b) + * ``` + * @param a First matrix in dot product operation. + * @param b Second matrix in dot product operation. + * @param transposeA If true, `a` is transposed before multiplication. + * @param transposeB If true, `b` is transposed before multiplication. + */ + /** @doc {heading: 'Operations', subheading: 'Matrices'} */ + function matMul_(a, b, transposeA, transposeB) { + var _a; + if (transposeA === void 0) { transposeA = false; } + if (transposeB === void 0) { transposeB = false; } + var $a = convertToTensor(a, 'a', 'matMul'); + var $b = convertToTensor(b, 'b', 'matMul'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + assert($a.rank >= 2 && $b.rank >= 2 && $a.rank === $b.rank, function () { return "Error in matMul: inputs must have the same rank of at least 2, " + + ("got ranks " + $a.rank + " and " + $b.rank + "."); }); + var innerShapeA = transposeA ? $a.shape[$a.rank - 2] : $a.shape[$a.rank - 1]; + var innerShapeB = transposeB ? $b.shape[$b.rank - 1] : $b.shape[$b.rank - 2]; + var outerShapeA = transposeA ? $a.shape[$a.rank - 1] : $a.shape[$a.rank - 2]; + var outerShapeB = transposeB ? $b.shape[$b.rank - 2] : $b.shape[$b.rank - 1]; + var outerDimsA = $a.shape.slice(0, -2); + var outerDimsB = $b.shape.slice(0, -2); + var batchDimA = sizeFromShape(outerDimsA); + var batchDimB = sizeFromShape(outerDimsB); + assert(arraysEqual(outerDimsA, outerDimsB), function () { return "Error in matMul: outer dimensions (" + outerDimsA + ") and (" + + (outerDimsB + ") of Tensors with shapes " + $a.shape + " and ") + + ($b.shape + " must match."); }); + assert(innerShapeA === innerShapeB, function () { return "Error in matMul: inner shapes (" + innerShapeA + ") and (" + + (innerShapeB + ") of Tensors with shapes " + $a.shape + " and ") + + ($b.shape + " and transposeA=" + transposeA) + + (" and transposeB=" + transposeB + " must match."); }); + var outShape = $a.shape.slice(0, -2).concat([outerShapeA, outerShapeB]); + var a3D = transposeA ? reshape($a, [batchDimA, innerShapeA, outerShapeA]) : + reshape($a, [batchDimA, outerShapeA, innerShapeA]); + var b3D = transposeB ? reshape($b, [batchDimB, outerShapeB, innerShapeB]) : + reshape($b, [batchDimB, innerShapeB, outerShapeB]); + var forward = function (backend, save) { + save([a3D, b3D]); + return backend.batchMatMul(a3D, b3D, transposeA, transposeB); + }; + var inputs = { a: a3D, b: b3D }; + var attrs = { transposeA: transposeA, transposeB: transposeB }; + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, BatchMatMul, attrs); + return reshape(res, outShape); + } + var matMul = op({ matMul_: matMul_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var batchMatMulGradConfig = { + kernelName: BatchMatMul, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved, attrs) { + var _a = saved, a = _a[0], b = _a[1]; + var _b = attrs, transposeA = _b.transposeA, transposeB = _b.transposeB; + if (!transposeA && !transposeB) { + return { + a: function () { return matMul(dy, b, false, true); }, + b: function () { return matMul(a, dy, true, false); } + }; + } + else if (!transposeA && transposeB) { + return { + a: function () { return matMul(dy, b, false, false); }, + b: function () { return matMul(dy, a, true, false); } + }; + } + else if (transposeA && !transposeB) { + return { + a: function () { return matMul(b, dy, false, true); }, + b: function () { return matMul(a, dy, false, false); } + }; + } + else { + return { + a: function () { return matMul(b, dy, true, true); }, + b: function () { return matMul(dy, a, true, true); } + }; + } + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * This operation divides "spatial" dimensions `[1, ..., M]` of the input into + * a grid of blocks of shape `blockShape`, and interleaves these blocks with + * the "batch" dimension (0) such that in the output, the spatial + * dimensions `[1, ..., M]` correspond to the position within the grid, + * and the batch dimension combines both the position within a spatial block + * and the original batch position. Prior to division into blocks, + * the spatial dimensions of the input are optionally zero padded + * according to `paddings`. See below for a precise description. + * + * ```js + * const x = tf.tensor4d([1, 2, 3, 4], [1, 2, 2, 1]); + * const blockShape = [2, 2]; + * const paddings = [[0, 0], [0, 0]]; + * + * x.spaceToBatchND(blockShape, paddings).print(); + * ``` + * + * @param x A `tf.Tensor`. N-D with `x.shape` = `[batch] + spatialShape + + * remainingShape`, where spatialShape has `M` dimensions. + * @param blockShape A 1-D array. Must have shape `[M]`, all values must + * be >= 1. + * @param paddings A 2-D array. Must have shape `[M, 2]`, all values must be >= + * 0. `paddings[i] = [padStart, padEnd]` specifies the amount to zero-pad + * from input dimension `i + 1`, which corresponds to spatial dimension `i`. It + * is required that + * `(inputShape[i + 1] + padStart + padEnd) % blockShape[i] === 0` + * + * This operation is equivalent to the following steps: + * + * 1. Zero-pad the start and end of dimensions `[1, ..., M]` of the input + * according to `paddings` to produce `padded` of shape paddedShape. + * + * 2. Reshape `padded` to `reshapedPadded` of shape: + * `[batch] + [paddedShape[1] / blockShape[0], blockShape[0], ..., + * paddedShape[M] / blockShape[M-1], blockShape[M-1]] + remainingShape` + * + * 3. Permute dimensions of `reshapedPadded` to produce `permutedReshapedPadded` + * of shape: `blockShape + [batch] + [paddedShape[1] / blockShape[0], ..., + * paddedShape[M] / blockShape[M-1]] + remainingShape` + * + * 4. Reshape `permutedReshapedPadded` to flatten `blockShape` into the + * batch dimension, producing an output tensor of shape: + * `[batch * prod(blockShape)] + [paddedShape[1] / blockShape[0], ..., + * paddedShape[M] / blockShape[M-1]] + remainingShape` + */ + /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ + function spaceToBatchND_(x, blockShape, paddings) { + var $x = convertToTensor(x, 'x', 'spaceToBatchND'); + assert($x.rank >= 1 + blockShape.length, function () { return "input rank " + $x.rank + " should be > than [blockShape] " + blockShape.length; }); + assert(paddings.length === blockShape.length, function () { return "paddings.shape[0] " + paddings.length + " must be equal to [blockShape] " + blockShape.length; }); + assert($x.shape.reduce(function (a, b, i) { + if (i > 0 && i <= blockShape.length) { + return a && + ((b + paddings[i - 1][0] + paddings[i - 1][1]) % + blockShape[i - 1] === + 0); + } + return a; + }, true), function () { return "input spatial dimensions " + $x.shape.slice(1) + " with paddings " + paddings.toString() + " must be divisible by blockShapes " + blockShape.toString(); }); + var forward = function (backend) { + return backend.spaceToBatchND($x, blockShape, paddings); + }; + var inputs = { x: $x }; + var attrs = { blockShape: blockShape, paddings: paddings }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, SpaceToBatchND, attrs); + } + var spaceToBatchND = op({ spaceToBatchND_: spaceToBatchND_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var batchToSpaceNDGradConfig = { + kernelName: BatchToSpaceND, + gradFunc: function (dy, saved, attrs) { + var _a = attrs, blockShape = _a.blockShape, crops = _a.crops; + return { x: function () { return spaceToBatchND(dy, blockShape, crops); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var broadcastToGradConfig = { + kernelName: BroadcastTo, + gradFunc: function (dy, saved, attrs) { + var broadCastToAttrs = attrs; + var inputShape = broadCastToAttrs.inputShape; + var outputShape = broadCastToAttrs.shape; + var reps = Array.from(outputShape); + for (var i = inputShape.length - 1; i >= 0; i--) { + if (inputShape[i] === outputShape[i]) { + reps[i] = 1; + } + else if (inputShape[i] !== 1) { + throw new Error("broadcastTo(): [" + inputShape + "] cannot be broadcast to [" + outputShape + "]."); + } + } + var axes = []; + for (var i = 0; i < reps.length; i++) { + if (reps[i] > 1) { + axes.push(i); + } + } + return { x: function () { return sum$1(dy, axes, true /* keepDims */); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var castGradConfig = { + kernelName: Cast, + gradFunc: function (dy) { + return { x: function () { return dy.clone(); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var ceilGradConfig = { + kernelName: Ceil, + gradFunc: function (dy) { + // TODO(manrajgrover): Return null for gradients when backprop supports it. + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the truth value of (a >= b) element-wise. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([1, 2, 3]); + * const b = tf.tensor1d([2, 2, 2]); + * + * a.greaterEqual(b).print(); + * ``` + * + * @param a The first input tensor. + * @param b The second input tensor. Must have the same dtype as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function greaterEqual_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'greaterEqual'); + var $b = convertToTensor(b, 'b', 'greaterEqual'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + assertAndGetBroadcastShape($a.shape, $b.shape); + var forward = function (backend, save) { + var res = backend.greaterEqual($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, GreaterEqual); + } + var greaterEqual = op({ greaterEqual_: greaterEqual_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the truth value of (a <= b) element-wise. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([1, 2, 3]); + * const b = tf.tensor1d([2, 2, 2]); + * + * a.lessEqual(b).print(); + * ``` + * + * @param a The first input tensor. + * @param b The second input tensor. Must have the same dtype as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function lessEqual_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'lessEqual'); + var $b = convertToTensor(b, 'b', 'lessEqual'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + assertAndGetBroadcastShape($a.shape, $b.shape); + var forward = function (backend, save) { + var res = backend.lessEqual($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, LessEqual); + } + var lessEqual = op({ lessEqual_: lessEqual_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the truth value of `a AND b` element-wise. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([false, false, true, true], 'bool'); + * const b = tf.tensor1d([false, true, false, true], 'bool'); + * + * a.logicalAnd(b).print(); + * ``` + * + * @param a The first input tensor. Must be of dtype bool. + * @param b The second input tensor. Must be of dtype bool. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function logicalAnd_(a, b) { + var $a = convertToTensor(a, 'a', 'logicalAnd', 'bool'); + var $b = convertToTensor(b, 'b', 'logicalAnd', 'bool'); + assertAndGetBroadcastShape($a.shape, $b.shape); + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(function (backend) { return backend.logicalAnd($a, $b); }, inputs, null /* grad */, LogicalAnd); + } + var logicalAnd = op({ logicalAnd_: logicalAnd_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the elements, either `a` or `b` depending on the `condition`. + * + * If the condition is true, select from `a`, otherwise select from `b`. + * + * ```js + * const cond = tf.tensor1d([false, false, true], 'bool'); + * const a = tf.tensor1d([1 , 2, 3]); + * const b = tf.tensor1d([-1, -2, -3]); + * + * a.where(cond, b).print(); + * ``` + * + * @param condition The input condition. Must be of dtype bool. + * @param a If `condition` is rank 1, `a` may have a higher rank but + * its first dimension must match the size of `condition`. + * @param b A tensor with the same dtype as `a` and with shape that is + * compatible with `a`. + * @return A tensor with same dtype as `a` and `b`, and shape that is + * broadcastable from `a` and `b`. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function where_(condition, a, b) { + var $a = convertToTensor(a, 'a', 'where'); + var $b = convertToTensor(b, 'b', 'where'); + var $condition = convertToTensor(condition, 'condition', 'where', 'bool'); + // TODO: move this logic to forward function when the broadcastTo op is + // implemented in WASM. + // Find the broadcastable shape for $a and $b. + var broadcastShape = assertAndGetBroadcastShape($a.shape, $b.shape); + var $broadcastedA = $a.broadcastTo(broadcastShape); + var $broadcastedB = $b.broadcastTo(broadcastShape); + if ($condition.rank === 1) { + // If condition rank is 1, then the first dimension must match the size of + // condition. + assert($condition.shape[0] === $a.shape[0], function () { return 'The first dimension of `a` must match the size of `condition`.'; }); + } + if ($condition.rank !== 1) { + // A must have the same shape as condition. + assertShapesMatch($condition.shape, $broadcastedB.shape, 'Error in where: '); + } + var forward = function (backend, save) { + var res = backend.select($condition, $broadcastedA, $broadcastedB); + save([$condition]); + return res; + }; + var inputs = { + condition: $condition, + t: $broadcastedA, + e: $broadcastedB + }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, SelectV2); + } + var where = op({ where_: where_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var clipByValueGradConfig = { + kernelName: ClipByValue, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0]; + var _a = attrs, clipValueMin = _a.clipValueMin, clipValueMax = _a.clipValueMax; + return { + x: function () { return where(logicalAnd(greaterEqual(x, clipValueMin), lessEqual(x, clipValueMax)), dy, zerosLike(dy)); }, + }; + } + }; + + /** + * Prepare the split size array. When the input is a number, the axis is evenly + * divided among the split size. When the input contains the negative value, the + * rest of the axis is allocated toward that. + */ + function prepareSplitSize(x, numOrSizeSplits, axis) { + if (axis === void 0) { axis = 0; } + var splitSizes = []; + if (typeof (numOrSizeSplits) === 'number') { + assert(x.shape[axis] % numOrSizeSplits === 0, function () { return 'Number of splits must evenly divide the axis.'; }); + splitSizes = + new Array(numOrSizeSplits).fill(x.shape[axis] / numOrSizeSplits); + } + else { + var numOfNegs = numOrSizeSplits.reduce(function (count, value) { + if (value === -1) { + count += 1; + } + return count; + }, 0); + assert(numOfNegs <= 1, function () { return 'There should be only one negative value in split array.'; }); + var negIndex = numOrSizeSplits.indexOf(-1); + // Allow the number of split array to be -1, which indicates the rest + // of dimension is allocated to that split. + if (negIndex !== -1) { + var total = numOrSizeSplits.reduce(function (a, b) { return b > 0 ? a + b : a; }); + numOrSizeSplits[negIndex] = x.shape[axis] - total; + } + assert(x.shape[axis] === numOrSizeSplits.reduce(function (a, b) { return a + b; }), function () { return 'The sum of sizes must match the size of the axis dimension.'; }); + splitSizes = numOrSizeSplits; + } + return splitSizes; + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Splits a `tf.Tensor` into sub tensors. + * + * If `numOrSizeSplits` is a number, splits `x` along dimension `axis` + * into `numOrSizeSplits` smaller tensors. + * Requires that `numOrSizeSplits` evenly divides `x.shape[axis]`. + * + * If `numOrSizeSplits` is a number array, splits `x` into + * `numOrSizeSplits.length` pieces. The shape of the `i`-th piece has the + * same size as `x` except along dimension `axis` where the size is + * `numOrSizeSplits[i]`. + * + * ```js + * const x = tf.tensor2d([1, 2, 3, 4, 5, 6, 7, 8], [2, 4]); + * const [a, b] = tf.split(x, 2, 1); + * a.print(); + * b.print(); + * + * const [c, d, e] = tf.split(x, [1, 2, 1], 1); + * c.print(); + * d.print(); + * e.print(); + * ``` + * + * @param x The input tensor to split. + * @param numOrSizeSplits Either an integer indicating the number of + * splits along the axis or an array of integers containing the sizes of + * each output tensor along the axis. If a number then it must evenly divide + * `x.shape[axis]`; otherwise the sum of sizes must match `x.shape[axis]`. + * Can contain one -1 indicating that dimension is to be inferred. + * @param axis The dimension along which to split. Defaults to 0 (the first + * dim). + */ + /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ + function split_(x, numOrSizeSplits, axis) { + if (axis === void 0) { axis = 0; } + var $x = convertToTensor(x, 'x', 'split'); + var forward = function (backend, _) { + var $axis = parseAxisParam(axis, $x.shape)[0]; + var splitSizes = prepareSplitSize($x, numOrSizeSplits, $axis); + return backend.split($x, splitSizes, $axis); + }; + var inputs = { x: $x }; + var attr = { numOrSizeSplits: numOrSizeSplits, axis: axis }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, SplitV, attr); + } + var split = op({ split_: split_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var concatGradConfig = { + kernelName: Concat, + saveAllInputs: true, + gradFunc: function (dy, saved, attrs) { + var shapes = saved.map(function (t) { return t.shape; }); + var axis = attrs.axis; + var $axis = parseAxisParam(axis, saved[0].shape)[0]; + var sizeSplits = shapes.map(function (s) { return s[$axis]; }); + var derTensors = split(dy, sizeSplits, $axis); + return derTensors.map(function (t) { return function () { return t; }; }); + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the derivative of the filter of a 2D convolution. + * + * @param x The input tensor, of rank 4 or rank 3 of shape + * [batch, height, width, inChannels]. If rank 3, batch of 1 is assumed. + * @param dy The dy image, of rank 4 or rank 3, of shape + * [batch, height, width, outDepth]. If rank 3, batch of 1 is assumed. + * @param filterShape The shape of the filter, length 4, + * [filterHeight, filterWidth, inDepth, outDepth]. + * @param strides The strides of the convolution: [strideHeight, + * strideWidth]. + * @param pad A string from: 'same', 'valid'. The type of padding algorithm + * used in the forward prop of the op. + * @param dataFormat: An optional string from: "NHWC", "NCHW". Defaults to + * "NHWC". Specify the data format of the input and output data. With the + * default format "NHWC", the data is stored in the order of: [batch, + * height, width, channels]. + * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The + * rounding mode used when computing output dimensions if pad is a + * number. If none is provided, it will not round and error if the output + * is of fractional size. + */ + function conv2DBackpropFilter_(x, dy, filterShape, strides, pad, dataFormat, dimRoundingMode) { + if (dataFormat === void 0) { dataFormat = 'NHWC'; } + var x4D = x; + if (x.rank === 3) { + x4D = reshape(x, [1, x.shape[0], x.shape[1], x.shape[2]]); + } + var dy4D = dy; + if (dy4D.rank === 3) { + dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); + } + assert(x4D.rank === 4, function () { return "Error in conv2dDerFilter: input must be rank 4, but got shape " + + (x4D.shape + "."); }); + assert(dy4D.rank === 4, function () { return "Error in conv2dDerFilter: dy must be rank 4, but got shape " + + (dy4D.shape + "."); }); + assert(filterShape.length === 4, function () { return "Error in conv2dDerFilter: filterShape must be length 4, but got " + + (filterShape + "."); }); + var inDepth = dataFormat === 'NHWC' ? x4D.shape[3] : x4D.shape[1]; + var outDepth = dataFormat === 'NHWC' ? dy4D.shape[3] : dy4D.shape[1]; + assert(inDepth === filterShape[2], function () { return "Error in conv2dDerFilter: depth of input " + inDepth + ") must " + + ("match input depth in filter (" + filterShape[2] + "."); }); + assert(outDepth === filterShape[3], function () { return "Error in conv2dDerFilter: depth of dy (" + outDepth + ") must " + + ("match output depth for filter (" + filterShape[3] + ")."); }); + if (dimRoundingMode != null) { + assert(isInt(pad), function () { return "Error in conv2dDerFilter: pad must be an integer when using, " + + ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); + } + var forward = function (backend) { + var dilations = 1; + var $dataFormat = convertConv2DDataFormat(dataFormat); + var convInfo = computeConv2DInfo(x4D.shape, filterShape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); + return backend.conv2dDerFilter(x4D, dy4D, convInfo); + }; + var inputs = { x: x4D, dy: dy4D }; + var attrs = { strides: strides, pad: pad, dataFormat: dataFormat, dimRoundingMode: dimRoundingMode }; + return ENGINE.runKernelFunc(forward, inputs, null, Conv2DBackpropFilter, attrs); + } + var conv2DBackpropFilter = op({ conv2DBackpropFilter_: conv2DBackpropFilter_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the derivative of the input of a 2D convolution. + * + * @param xShape The shape of the input: [batch, height, width, inDepth]. + * If length of 3, batch of 1 is assumed. + * @param dy The derivative of the output, of rank 4 or rank 3 of shape + * `[batch, outHeight, outWidth, outDepth]`. If rank 3, batch of 1 is + * assumed. + * @param filter The filter, rank 4, of shape + * `[filterHeight, filterWidth, inDepth, outDepth]`. + * @param strides The strides of the convolution: `[strideHeight, + * strideWidth]`. + * @param pad The type of padding algorithm used: + * - `same` and stride 1: output will be of same size as input, + * regardless of filter size. + * - `valid`: output will be smaller than input if filter is larger + * than 1x1. + * @param dataFormat: An optional string from: "NHWC", "NCHW". Defaults to + * "NHWC". Specify the data format of the input and output data. With the + * default format "NHWC", the data is stored in the order of: [batch, + * height, width, channels]. + * @param dimRoundingMode The rounding mode used when computing output + * dimensions if pad is a number. If none is provided, it will not round + * and error if the output is of fractional size. + */ + function conv2DBackpropInput_(xShape, dy, filter, strides, pad, dataFormat, dimRoundingMode) { + if (dataFormat === void 0) { dataFormat = 'NHWC'; } + assert(xShape.length === dy.rank, function () { return "Length of inShape " + + ("(" + xShape.length + ") and rank of dy (" + dy.rank + ") must match"); }); + var xShape4D = xShape; + var dy4D = dy; + var reshapedTo4D = false; + if (dy.rank === 3) { + reshapedTo4D = true; + dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); + xShape4D = [1, xShape[0], xShape[1], xShape[2]]; + } + assert(xShape4D.length === 4, function () { + return "Error in conv2dDerInput: inShape must be length 4, but got length " + + (xShape4D.length + "."); + }); + assert(dy4D.rank === 4, function () { return "Error in conv2dDerInput: dy must be rank 4, but got " + + ("rank " + dy4D.rank); }); + assert(filter.rank === 4, function () { return "Error in conv2dDerInput: filter must be rank 4, but got " + + ("rank " + filter.rank); }); + var inDepth = dataFormat === 'NHWC' ? xShape4D[3] : xShape4D[1]; + var outDepth = dataFormat === 'NHWC' ? dy4D.shape[3] : dy4D.shape[1]; + assert(inDepth === filter.shape[2], function () { return "Error in conv2dDerInput: depth of input (" + inDepth + ") must " + + ("match input depth for filter " + filter.shape[2] + "."); }); + assert(outDepth === filter.shape[3], function () { return "Error in conv2dDerInput: depth of output (" + outDepth + ") must " + + ("match output depth for filter " + filter.shape[3] + "."); }); + if (dimRoundingMode != null) { + assert(isInt(pad), function () { return "Error in conv2dDerInput: pad must be an integer when using, " + + ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); + } + var forward = function (backend, save) { + var dilations = 1; + var $dataFormat = convertConv2DDataFormat(dataFormat); + var convInfo = computeConv2DInfo(xShape4D, filter.shape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); + var res = backend.conv2dDerInput(dy4D, filter, convInfo); + save([dy4D, filter]); + return res; + }; + var inputs = { dy: dy4D, filter: filter }; + var attrs = { strides: strides, pad: pad, dataFormat: dataFormat, dimRoundingMode: dimRoundingMode, inputShape: xShape4D }; + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, Conv2DBackpropInput, attrs); + if (reshapedTo4D) { + return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); + } + return res; + } + var conv2DBackpropInput = op({ conv2DBackpropInput_: conv2DBackpropInput_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var conv2DGradConfig = { + kernelName: Conv2D, + inputsToSave: ['x', 'filter'], + gradFunc: function (dy, saved, attrs) { + var _a = saved, x4D = _a[0], $filter = _a[1]; + var _b = attrs, dilations = _b.dilations, strides = _b.strides, pad = _b.pad, dataFormat = _b.dataFormat; + assert(tupleValuesAreOne(dilations), function () { return 'Error in gradient of conv2D: dilation rates greater than 1 ' + + ("are not yet supported in gradients. Got dilations '" + dilations + "'"); }); + return { + x: function () { + return conv2DBackpropInput(x4D.shape, dy, $filter, strides, pad, dataFormat); + }, + filter: function () { + return conv2DBackpropFilter(x4D, dy, $filter.shape, strides, pad, dataFormat); + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes a 2D convolution over the input x. + * + * @param x The input tensor, of rank 4 or rank 3, of shape + * `[batch, height, width, inChannels]`. If rank 3, batch of 1 is + * assumed. + * @param filter The filter, rank 4, of shape + * `[filterHeight, filterWidth, inDepth, outDepth]`. + * @param strides The strides of the convolution: `[strideHeight, + * strideWidth]`. + * @param pad The type of padding algorithm. + * - `same` and stride 1: output will be of same size as input, + * regardless of filter size. + * - `valid`: output will be smaller than input if filter is larger + * than 1x1. + * - For more info, see this guide: + * [https://www.tensorflow.org/api_guides/python/nn#Convolution]( + * https://www.tensorflow.org/api_guides/python/nn#Convolution) + * @param dataFormat: An optional string from: "NHWC", "NCHW". Defaults to + * "NHWC". Specify the data format of the input and output data. With the + * default format "NHWC", the data is stored in the order of: [batch, + * height, width, channels]. + * @param dilations The dilation rates: `[dilationHeight, dilationWidth]` + * in which we sample input values across the height and width dimensions + * in atrous convolution. Defaults to `[1, 1]`. If `dilations` is a single + * number, then `dilationHeight == dilationWidth`. If it is greater than + * 1, then all values of `strides` must be 1. + * @param dimRoundingMode The rounding mode used when computing output + * dimensions if pad is a number. If none is provided, it will not round + * and error if the output is of fractional size. + */ + /** @doc {heading: 'Operations', subheading: 'Convolution'} */ + function conv2d_(x, filter, strides, pad, dataFormat, dilations, dimRoundingMode) { + if (dataFormat === void 0) { dataFormat = 'NHWC'; } + if (dilations === void 0) { dilations = [1, 1]; } + var $x = convertToTensor(x, 'x', 'conv2d'); + var $filter = convertToTensor(filter, 'filter', 'conv2d'); + var x4D = $x; + var reshapedTo4D = false; + if ($x.rank === 3) { + reshapedTo4D = true; + x4D = reshape($x, [1, $x.shape[0], $x.shape[1], $x.shape[2]]); + } + assert(x4D.rank === 4, function () { return "Error in conv2d: input must be rank 4, but got rank " + x4D.rank + "."; }); + assert($filter.rank === 4, function () { return "Error in conv2d: filter must be rank 4, but got rank " + + ($filter.rank + "."); }); + if (dimRoundingMode != null) { + assert(isInt(pad), function () { return "Error in conv2d: pad must be an integer when using, " + + ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); + } + var inDepth = dataFormat === 'NHWC' ? x4D.shape[3] : x4D.shape[1]; + assert(inDepth === $filter.shape[2], function () { return "Error in conv2d: depth of input (" + inDepth + ") must match " + + ("input depth for filter " + $filter.shape[2] + "."); }); + assert(eitherStridesOrDilationsAreOne(strides, dilations), function () { return 'Error in conv2D: Either strides or dilations must be 1. ' + + ("Got strides " + strides + " and dilations '" + dilations + "'"); }); + var forward = function (backend, save) { + var $dataFormat = convertConv2DDataFormat(dataFormat); + var convInfo = computeConv2DInfo(x4D.shape, $filter.shape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); + var res = backend.conv2d(x4D, $filter, convInfo); + save([x4D, $filter]); + return res; + }; + var inputs = { x: x4D, filter: $filter }; + var attrs = { strides: strides, pad: pad, dataFormat: dataFormat, dilations: dilations, dimRoundingMode: dimRoundingMode }; + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, Conv2D, attrs); + if (reshapedTo4D) { + return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); + } + return res; + } + var conv2d = op({ conv2d_: conv2d_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var conv2DBackpropInputGradConfig = { + kernelName: Conv2DBackpropInput, + inputsToSave: ['dy', 'filter'], + gradFunc: function (ddx, saved, attrs) { + var _a = saved, dy = _a[0], filter = _a[1]; + var _b = attrs, strides = _b.strides, pad = _b.pad, dataFormat = _b.dataFormat, dimRoundingMode = _b.dimRoundingMode; + return { + dy: function () { return conv2d(ddx, filter, strides, pad, dataFormat, 1 /* dilations */, dimRoundingMode); }, + filter: function () { return conv2DBackpropFilter(ddx, dy, filter.shape, strides, pad, dataFormat, dimRoundingMode); } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the derivative of the filter of a 3D convolution. + * + * @param x The input tensor, of rank 5 or rank 4 of shape + * [batch, depth, height, width, inChannels]. If rank 4, batch of 1 is + * assumed. + * @param dy The dy image, of rank 5 or rank 4, of shape + * [batch, depth, height, width, outDepth]. If rank 4, batch of 1 is + * assumed. + * @param filterShape The shape of the filter, length 5, + * [filterDepth, filterHeight, filterWidth, inDepth, outDepth]. + * @param strides The strides of the convolution: [strideDepth, strideHeight, + * strideWidth]. + * @param pad A string from: 'same', 'valid'. The type of padding algorithm + * used in the forward prop of the op. + */ + function conv3DBackpropFilter_(x, dy, filterShape, strides, pad) { + var x5D = x; + if (x.rank === 4) { + x5D = reshape(x, [1, x.shape[0], x.shape[1], x.shape[2], x.shape[3]]); + } + var dy5D = dy; + if (dy5D.rank === 4) { + dy5D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2], dy.shape[3]]); + } + assert(x5D.rank === 5, function () { return "Error in conv3dDerFilter: input must be rank 5, but got shape " + + (x5D.shape + "."); }); + assert(dy5D.rank === 5, function () { return "Error in conv3dDerFilter: dy must be rank 5, but got shape " + + (dy5D.shape + "."); }); + assert(filterShape.length === 5, function () { return "Error in conv3dDerFilter: filterShape must be length 5, but got " + + (filterShape + "."); }); + assert(x5D.shape[4] === filterShape[3], function () { return "Error in conv3dDerFilter: depth of input " + x5D.shape[4] + ") must " + + ("match input depth in filter (" + filterShape[3] + "."); }); + assert(dy5D.shape[4] === filterShape[4], function () { return "Error in conv3dDerFilter: depth of dy (" + dy5D.shape[4] + ") must " + + ("match output depth for filter (" + filterShape[4] + ")."); }); + var forward = function (backend) { + var dilations = 1; + var convInfo = computeConv3DInfo(x5D.shape, filterShape, strides, dilations, pad); + return backend.conv3dDerFilter(x5D, dy5D, convInfo); + }; + var inputs = { x: x5D, y: dy5D }; + var attrs = { strides: strides, pad: pad }; + return ENGINE.runKernelFunc(forward, inputs, null, Conv3DBackpropFilterV2, attrs); + } + var conv3DBackpropFilter = op({ conv3DBackpropFilter_: conv3DBackpropFilter_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the derivative of the input of a 3D convolution. + * + * @param xShape The shape of the input: [batch, depth, height, width, + * in_channels]. If length of 4, batch of 1 is assumed. + * @param dy The derivative of the output, of rank 5 or rank 4 of shape + * `[batch, outDepth, outHeight, outWidth, in_channels]`. + * If rank 4, batch of 1 is assumed. + * @param filter The filter, rank 5, of shape + * `[filterDepth, filterHeight, filterWidth, inDepth, outDepth]`. + * @param strides The strides of the convolution: `[strideDepth, strideHeight, + * strideWidth]`. + * @param pad The type of padding algorithm used: + * - `same` and stride 1: output will be of same size as input, + * regardless of filter size. + * - `valid`: output will be smaller than input if filter is larger + * than 1x1. + */ + function conv3DBackpropInput_(xShape, dy, filter, strides, pad) { + assert(xShape.length === dy.rank, function () { return "Length of inShape " + + ("(" + xShape.length + ") and rank of dy (" + dy.rank + ") must match"); }); + var xShape5D = xShape; + var dy5D = dy; + var reshapedTo5D = false; + if (dy.rank === 4) { + reshapedTo5D = true; + dy5D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2], dy.shape[3]]); + xShape5D = [1, xShape[0], xShape[1], xShape[2], xShape[3]]; + } + var inDepth = xShape5D[4]; + var outDepth = dy5D.shape[4]; + assert(xShape5D.length === 5, function () { + return "Error in conv3dDerInput: inShape must be length 5, but got length " + + (xShape5D.length + "."); + }); + assert(dy5D.rank === 5, function () { return "Error in conv3dDerInput: dy must be rank 5, but got " + + ("rank " + dy5D.rank); }); + assert(filter.rank === 5, function () { return "Error in conv3dDerInput: filter must be rank 5, but got " + + ("rank " + filter.rank); }); + assert(inDepth === filter.shape[3], function () { return "Error in conv3dDerInput: depth of input (" + inDepth + ") must " + + ("match input depth for filter " + filter.shape[3] + "."); }); + assert(outDepth === filter.shape[4], function () { return "Error in conv3dDerInput: depth of output (" + outDepth + ") must " + + ("match output depth for filter " + filter.shape[4] + "."); }); + var forward = function (backend) { + var dilations = 1; + var convInfo = computeConv3DInfo(xShape5D, filter.shape, strides, dilations, pad); + return backend.conv3dDerInput(dy5D, filter, convInfo); + }; + var inputs = { dy: dy5D }; + var attrs = { pad: pad }; + var res = ENGINE.runKernelFunc(forward, inputs, null, Conv3DBackpropInputV2, attrs); + if (reshapedTo5D) { + return reshape(res, [res.shape[1], res.shape[2], res.shape[3], res.shape[4]]); + } + return res; + } + var conv3DBackpropInput = op({ conv3DBackpropInput_: conv3DBackpropInput_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var conv3DGradConfig = { + kernelName: Conv3D, + inputsToSave: ['x', 'filter'], + gradFunc: function (dy, saved, attrs) { + var _a = attrs, dilations = _a.dilations, strides = _a.strides, pad = _a.pad; + assert(tupleValuesAreOne(dilations), function () { + return 'Error in gradient of conv3D: dilation rates greater than 1 are ' + + ("not yet supported in gradients. Got dilations '" + dilations + "'"); + }); + var x5D = saved[0], $filter = saved[1]; + return { + x: function () { return conv3DBackpropInput(x5D.shape, dy, $filter, strides, pad); }, + filter: function () { return conv3DBackpropFilter(x5D, dy, $filter.shape, strides, pad); } + }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes sin of the input Tensor element-wise: `sin(x)` + * + * ```js + * const x = tf.tensor1d([0, Math.PI / 2, Math.PI * 3 / 4]); + * + * x.sin().print(); // or tf.sin(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function sin_(x) { + var $x = convertToTensor(x, 'x', 'sin'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.sin($x); + save([$x]); + return res; + }, inputs, null /* grad */, Sin); + } + var sin = op({ sin_: sin_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var cosGradConfig = { + kernelName: Cos, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(neg(sin(cast(x, 'float32'))), dy); } }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes hyperbolic sin of the input `tf.Tensor` element-wise: `sinh(x)` + * + * ```js + * const x = tf.tensor1d([0, 1, -1, .7]); + * + * x.sinh().print(); // or tf.sinh(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function sinh_(x) { + var $x = convertToTensor(x, 'x', 'sinh'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.sinh($x); + save([$x]); + return res; + }, inputs, null /* grad */, Sinh); + } + var sinh = op({ sinh_: sinh_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var coshGradConfig = { + kernelName: Cosh, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(sinh(cast(x, 'float32')), dy); } }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Transposes the `tf.Tensor`. Permutes the dimensions according to `perm`. + * + * The returned `tf.Tensor`'s dimension `i` will correspond to the input + * dimension `perm[i]`. If `perm` is not given, it is set to `[n-1...0]`, + * where `n` is the rank of the input `tf.Tensor`. Hence by default, this + * operation performs a regular matrix transpose on 2-D input `tf.Tensor`s. + * + * ```js + * const a = tf.tensor2d([1, 2, 3, 4, 5, 6], [2, 3]); + * + * a.transpose().print(); // or tf.transpose(a) + * ``` + * + * @param x The tensor to transpose. + * @param perm The permutation of the dimensions of a. + */ + /** @doc {heading: 'Operations', subheading: 'Matrices'} */ + function transpose_(x, perm) { + var $x = convertToTensor(x, 'x', 'transpose'); + if (perm == null) { + perm = $x.shape.map(function (s, i) { return i; }).reverse(); + } + assert($x.rank === perm.length, function () { return "Error in transpose: rank of input " + $x.rank + " " + + ("must match length of perm " + perm + "."); }); + perm.forEach(function (axis) { + assert(axis >= 0 && axis < $x.rank, function () { return "All entries in 'perm' must be between 0 and " + ($x.rank - 1) + + (" but got " + perm); }); + }); + if ($x.rank <= 1) { + return $x.clone(); + } + var inputs = { x: $x }; + var attrs = { perm: perm }; + return ENGINE.runKernelFunc(function (backend) { return backend.transpose($x, perm); }, inputs, null /* gradient */, Transpose, attrs); + } + var transpose = op({ transpose_: transpose_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the cumulative sum of a `tf.Tensor` along `axis`. + * + * ```js + * const x = tf.tensor([1, 2, 3, 4]); + * x.cumsum().print(); + * ``` + * ```js + * const x = tf.tensor([[1, 2], [3, 4]]); + * x.cumsum().print(); + * ``` + * + * @param x The input tensor to be summed. + * @param axis The axis along which to sum. Optional. Defaults to 0. + * @param exclusive Whether to perform exclusive cumulative sum. Optional. + * Defaults to false. If set to true then the sum of each tensor entry + * does not include its own value, but only the values previous to it + * along the specified axis. + * @param reverse Whether to sum in the opposite direction. Optional. + * Defaults to false. + */ + /** @doc {heading: 'Operations', subheading: 'Scan'} */ + function cumsum_(x, axis, exclusive, reverse) { + if (axis === void 0) { axis = 0; } + if (exclusive === void 0) { exclusive = false; } + if (reverse === void 0) { reverse = false; } + var $x = convertToTensor(x, 'x', 'cumsum'); + var forward = function (backend, save) { + var permutation = getAxesPermutation([axis], $x.rank); + var permutedX = $x; + if (permutation != null) { + permutedX = transpose($x, permutation); + } + var permutedAxis = getInnerMostAxes(1, $x.rank)[0]; + var value = backend.cumsum(permutedX, permutedAxis, exclusive, reverse); + save([$x]); + if (permutation != null) { + value = transpose(value, permutation); + } + return value; + }; + var inputs = { x: $x }; + var attrs = { axis: axis, exclusive: exclusive, reverse: reverse }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Cumsum, attrs); + } + var cumsum = op({ cumsum_: cumsum_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var cumsumGradConfig = { + kernelName: Cumsum, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0]; + var _a = attrs, axis = _a.axis, exclusive = _a.exclusive, reverse = _a.reverse; + return { + x: function () { + var permutation = getAxesPermutation([axis], x.rank); + var out = cumsum(dy, axis, exclusive, !reverse); + if (permutation != null) { + out = transpose(out, permutation); + } + return out; + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function depthwiseConv2dNativeBackpropFilter_(x, dy, filterShape, convInfo) { + var x4D = x; + if (x.rank === 3) { + x4D = reshape(x, [1, x.shape[0], x.shape[1], x.shape[2]]); + } + var dy4D = dy; + if (dy4D.rank === 3) { + dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); + } + var forward = function (backend) { + return backend.depthwiseConv2DDerFilter(x4D, dy4D, convInfo); + }; + var inputs = { x: x4D, dy: dy4D }; + return ENGINE.runKernelFunc(forward, inputs, null, DepthwiseConv2dNativeBackpropFilter); + } + var depthwiseConv2dNativeBackpropFilter = op({ depthwiseConv2dNativeBackpropFilter_: depthwiseConv2dNativeBackpropFilter_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function depthwiseConv2dNativeBackpropInput_(xShape, dy, filter, convInfo) { + var dy4D = dy; + var reshapedTo4D = false; + if (dy.rank === 3) { + reshapedTo4D = true; + dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); + } + var forward = function (backend) { + return backend.depthwiseConv2DDerInput(dy4D, filter, convInfo); + }; + var inputs = { dy: dy4D }; + var res = ENGINE.runKernelFunc(forward, inputs, null, DepthwiseConv2dNativeBackpropInput); + if (reshapedTo4D) { + return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); + } + return res; + } + var depthwiseConv2dNativeBackpropInput = op({ depthwiseConv2dNativeBackpropInput_: depthwiseConv2dNativeBackpropInput_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var depthwiseConv2dNativeGradConfig = { + kernelName: DepthwiseConv2dNative, + inputsToSave: ['x', 'filter'], + gradFunc: function (dy, saved, attrs) { + var _a = attrs, dilations = _a.dilations, strides = _a.strides, pad = _a.pad, dimRoundingMode = _a.dimRoundingMode; + var $dilations = dilations == null ? [1, 1] : dilations; + assert(tupleValuesAreOne($dilations), function () { return 'Error in gradient of depthwiseConv2dNative: dilation rates ' + + "greater than 1 are not yet supported. Got dilations " + + ("'" + $dilations + "'"); }); + var _b = saved, x = _b[0], filter = _b[1]; + assert(x.rank === 4, function () { return "Error in gradient of depthwiseConv2dNative: input must be " + + ("rank 4, but got rank " + x.rank + "."); }); + assert(filter.rank === 4, function () { return "Error in gradient of depthwiseConv2dNative: filter must be " + + ("rank 4, but got rank " + filter.rank + "."); }); + assert(x.shape[3] === filter.shape[2], function () { return "Error in gradient of depthwiseConv2d: number of input " + + ("channels (" + x.shape[3] + ") must match the inChannels dimension ") + + ("in filter " + filter.shape[2] + "."); }); + assert(eitherStridesOrDilationsAreOne(strides, $dilations), function () { return 'Error in gradient of depthwiseConv2d: Either strides or ' + + ("dilations must be 1. Got strides " + strides + " and dilations ") + + ("'" + $dilations + "'."); }); + if (dimRoundingMode != null) { + assert(isInt(pad), function () { + return "Error in depthwiseConv2d: pad must be an integer when using, " + + ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); + }); + } + var convInfo = computeConv2DInfo(x.shape, filter.shape, strides, $dilations, pad, dimRoundingMode, true /* depthwise */); + return { + x: function () { + return depthwiseConv2dNativeBackpropInput(x.shape, dy, filter, convInfo); + }, + filter: function () { + return depthwiseConv2dNativeBackpropFilter(x, dy, filter.shape, convInfo); + }, + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var dilation2dGradConfig = { + kernelName: Dilation2D, + inputsToSave: ['x', 'filter'], + gradFunc: function (dy, saved, attrs) { + var _a = saved, x = _a[0], filter = _a[1]; + var inputInputs = { x: x, filter: filter, dy: dy }; + var filterInputs = { x: x, filter: filter, dy: dy }; + return { + x: function () { return ENGINE.runKernel(Dilation2DBackpropInput, inputInputs, attrs); }, + filter: function () { return ENGINE.runKernel(Dilation2DBackpropFilter, filterInputs, attrs); } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var divGradConfig = { + kernelName: Div, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var outShape = assertAndGetBroadcastShape(a.shape, b.shape); + var derA = function () { + var res = div(dy, b.toFloat()); + var reduceAxes = getReductionAxes(a.shape, outShape); + if (reduceAxes.length > 0) { + return sum$1(res, reduceAxes).reshape(a.shape); + } + return res; + }; + var derB = function () { + var res = mul(dy, a.toFloat()); + var reduceAxes = getReductionAxes(b.shape, outShape); + if (reduceAxes.length > 0) { + res = reshape(sum$1(res, reduceAxes), b.shape); + } + var tmp = square(b); + return neg(div(res, tmp.toFloat())); + }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var eluGradConfig = { + kernelName: Elu, + outputsToSave: [true], + gradFunc: function (dy, saved) { + var y = saved[0]; + var backPropKernelFunc = function (backend) { + return backend.eluDer(dy, y); + }; + var inputs = { dy: dy, y: y }; + return { + x: function () { return ENGINE.runKernelFunc(backPropKernelFunc, inputs, null /* grad */, EluGrad); } + }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes exponential of the input `tf.Tensor` element-wise. `e ^ x` + * + * ```js + * const x = tf.tensor1d([1, 2, -3]); + * + * x.exp().print(); // or tf.exp(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function exp_(x) { + var $x = convertToTensor(x, 'x', 'exp'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.exp($x); + save([res]); + return res; + }, inputs, null /* grad */, Exp); + } + var exp = op({ exp_: exp_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var erfGradConfig = { + kernelName: Erf, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + var a = mul(exp(neg(square(x))), 2 / Math.sqrt(Math.PI)); + return { x: function () { return mul(dy, a); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var expGradConfig = { + kernelName: Exp, + outputsToSave: [true], + gradFunc: function (dy, saved) { + var y = saved[0]; + return { x: function () { return mul(dy, y); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var expm1GradConfig = { + kernelName: Expm1, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(dy, exp(x)); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var floorGradConfig = { + kernelName: Floor, + gradFunc: function (dy) { + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var floorDivGradConfig = { + kernelName: FloorDiv, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var outShape = assertAndGetBroadcastShape(a.shape, b.shape); + var derA = function () { + var res = dy.div(b.toFloat()); + var reduceAxes = getReductionAxes(a.shape, outShape); + if (reduceAxes.length > 0) { + return res.sum(reduceAxes).reshape(a.shape); + } + return res; + }; + var derB = function () { + var res = dy.mul(a.toFloat()); + var reduceAxes = getReductionAxes(b.shape, outShape); + if (reduceAxes.length > 0) { + res = res.sum(reduceAxes).reshape(b.shape); + } + var tmp = b.square(); + return res.div(tmp.toFloat()).neg(); + }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes reciprocal of square root of the input `tf.Tensor` element-wise: + * `y = 1 / sqrt(x)` + * + * ```js + * const x = tf.tensor1d([1, 2, 4, -1]); + * + * x.rsqrt().print(); // or tf.rsqrt(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function rsqrt_(x) { + var $x = convertToTensor(x, 'x', 'rsqrt'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.rsqrt($x); + save([$x]); + return res; + }, inputs, null /* grad */, Rsqrt); + } + var rsqrt = op({ rsqrt_: rsqrt_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Construct a tensor by repeating it the number of times given by reps. + * + * This operation creates a new tensor by replicating `input` `reps` + * times. The output tensor's i'th dimension has `input.shape[i] * + * reps[i]` elements, and the values of `input` are replicated + * `reps[i]` times along the i'th dimension. For example, tiling + * `[a, b, c, d]` by `[2]` produces `[a, b, c, d, a, b, c, d]`. + * + * ```js + * const a = tf.tensor1d([1, 2]); + * + * a.tile([2]).print(); // or a.tile([2]) + * ``` + * + * ```js + * const a = tf.tensor2d([1, 2, 3, 4], [2, 2]); + * + * a.tile([1, 2]).print(); // or a.tile([1, 2]) + * ``` + * @param x The tensor to tile. + * @param reps Determines the number of replications per dimension. + */ + /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ + function tile_(x, reps) { + var parseAs = null; + var $x = convertToTensor(x, 'x', 'tile', parseAs); + assert($x.rank === reps.length, function () { return "Error in transpose: rank of input " + $x.rank + " " + + ("must match length of reps " + reps + "."); }); + var forward = function (backend, save) { + var res = backend.tile($x, reps); + save([$x]); + return res; + }; + var inputsToSave = [$x]; + var inputs = { x: $x }; + var attrs = { reps: reps }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Tile, attrs, inputsToSave); + } + var tile = op({ tile_: tile_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var fusedBatchNormGradConfig = { + kernelName: FusedBatchNorm, + inputsToSave: ['x', 'mean', 'variance', 'scale'], + gradFunc: function (dy, saved, attrs) { + var varianceEpsilon = attrs.varianceEpsilon; + var x = saved[0], mean = saved[1], variance = saved[2], scale = saved[3]; + var scaleValue = scale == null ? scalar(1) : scale; + var reductionAxes = getReductionAxes(mean.shape, x.shape); + var tileShape = []; + if (mean.rank === 1) { + for (var i = 0; i < x.shape.length - 1; ++i) { + tileShape.push(x.shape[i]); + } + tileShape.push(1); + } + var xMinusMean = sub(x, mean); + var dyTimesScaleValue = mul(dy, scaleValue); + var oneOverSqrtVariance = rsqrt(add(variance, scalar(varianceEpsilon))); + var minusHalfRCube = mul(mul(mul(oneOverSqrtVariance, oneOverSqrtVariance), oneOverSqrtVariance), scalar(-0.5)); + var derX = function () { + if (mean.rank === 1) { + return reshape(mul(mul(dy, tile(oneOverSqrtVariance.as4D(1, 1, 1, mean.shape[0]), tileShape)), scaleValue), x.shape); + } + else { + return reshape(mul(mul(dy, oneOverSqrtVariance), scaleValue), x.shape); + } + }; + var derMean = function () { + var meanDer = mul(mul(oneOverSqrtVariance, scalar(-1)), dyTimesScaleValue); + if (mean.rank === 1) { + meanDer = sum$1(meanDer, reductionAxes); + } + return reshape(meanDer, mean.shape); + }; + var derVariance = function () { + var varianceDer = mul(mul(minusHalfRCube, xMinusMean), dyTimesScaleValue); + if (mean.rank === 1) { + varianceDer = sum$1(varianceDer, reductionAxes); + } + return reshape(varianceDer, mean.shape); + }; + var derScale = function () { + var xMinusMean2TimesRsqrt = mul(xMinusMean, oneOverSqrtVariance); + var scaleDer = mul(dy, xMinusMean2TimesRsqrt); + if (mean.rank === 1) { + scaleDer = sum$1(scaleDer, reductionAxes); + } + return reshape(scaleDer, mean.shape); + }; + var derOffset = function () { + var offsetDer = dy; + if (mean.rank === 1) { + offsetDer = sum$1(offsetDer, reductionAxes); + } + return reshape(offsetDer, mean.shape); + }; + return { + x: derX, + mean: derMean, + variance: derVariance, + scale: derScale, + offset: derOffset + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the sum along segments of a `tf.Tensor`. + * + * ```js + * const x = tf.tensor1d([1, 2, 3, 4]); + * const segmentIds = tf.tensor1d([1, 2, 0, 1], 'int32'); + * const numSegments = 3; + * + * x.unsortedSegmentSum(segmentIds, numSegments).print() + * //or tf.unsortedSegmentSum(x, segmentIds, numSegments) + * ``` + * @param x The `tf.Tensor` that will be summed along its segments. + * @param segmentIds A `tf.Tensor1D` whose rank is equal to the rank of `x`'s + * dimension along the `axis`. Maps each element of `x` to a segment. + * @param numSegments The number of distinct `segmentIds`. + */ + /** @doc {heading: 'Operations', subheading: 'Segment'} */ + function unsortedSegmentSum_(x, segmentIds, numSegments) { + var $x = convertToTensor(x, 'x', 'unsortedSegmentSum'); + var $segmentIds = convertToTensor(segmentIds, 'segmentIds', 'unsortedSegmentSum', 'int32'); + assert(isInt(numSegments), function () { return 'numSegments must be of dtype int'; }); + var inputs = { x: $x, segmentIds: $segmentIds }; + var attrs = { numSegments: numSegments }; + var forward = function (backend, save) { + var res = backend.unsortedSegmentSum($x, $segmentIds, numSegments); + save([$segmentIds]); + return res; + }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, UnsortedSegmentSum, attrs); + } + var unsortedSegmentSum = op({ unsortedSegmentSum_: unsortedSegmentSum_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var gatherGradConfig = { + kernelName: GatherV2, + inputsToSave: ['x', 'indices'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0], indices = saved[1]; + var axis = attrs.axis; + var parsedAxis = parseAxisParam(axis, x.shape)[0]; + var derX = function () { + var paramsShape = x.shape; + var indicesSize = indices.size; + var outerShape = paramsShape.slice(0, parsedAxis); + var outerDims = outerShape.length; + var innerShape = paramsShape.slice(axis, paramsShape.length).slice(1); + var innerDims = innerShape.length; + var outerAxesIndices = arrayRange(0, outerDims); + var innerAxesIndices = arrayRange(outerDims + 1, outerDims + 1 + innerDims); + var valuesShape = arrayConcat([outerShape, [indicesSize], innerShape]); + var values = reshape(dy, valuesShape); + var reshapedIndices = reshape(indices, [indicesSize]); + var transposeDims = arrayConcat([[outerDims], outerAxesIndices, innerAxesIndices]); + var valuesTranspose = transpose(values, transposeDims); + var paramsGrad = unsortedSegmentSum(valuesTranspose, reshapedIndices, x.shape[parsedAxis]); + var invertTransposeDims = getUndoAxesPermutation(transposeDims); + paramsGrad = transpose(paramsGrad, invertTransposeDims); + return paramsGrad; + }; + return { x: derX, indices: function () { return indices; } }; + } + }; + function arrayRange(start, stop) { + var result = []; + for (var i = start; i < stop; ++i) { + result.push(i); + } + return result; + } + function arrayConcat(arrays) { + var result = []; + for (var i = 0; i < arrays.length; ++i) { + for (var j = 0; j < arrays[i].length; ++j) { + result.push(arrays[i][j]); + } + } + return result; + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var greaterEqualGradConfig = { + kernelName: GreaterEqual, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + return { a: function () { return zerosLike(a); }, b: function () { return zerosLike(b); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var identityGradConfig = { + kernelName: Identity, + gradFunc: function (dy) { + return { x: function () { return dy.toFloat(); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var isFiniteGradConfig = { + kernelName: IsFinite, + gradFunc: function (dy) { + // TODO(nsthorat): Let gradients be null for cases where we want to stop + // backpropgation. + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var isInfGradConfig = { + kernelName: IsInf, + gradFunc: function (dy) { + // TODO(nsthorat): Let gradients be null for cases where we want to stop + // backpropgation. + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var isNanGradConfig = { + kernelName: IsNan, + gradFunc: function (dy) { + // TODO(nsthorat): Let gradients be null for cases where we want to stop + // backpropgation. + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var log1pGradConfig = { + kernelName: Log1p, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, add(x, 1)); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var logGradConfig = { + kernelName: Log, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, cast(x, 'float32')); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var logSoftmaxGradConfig = { + kernelName: LogSoftmax, + inputsToSave: [], + outputsToSave: [true], + gradFunc: function (dy, saved, attrs) { + var value = saved[0]; + var axis = attrs.axis; + return { + logits: function () { + var keepDims = true; + var softmax = value.exp(); + return dy.sub(dy.sum(axis, keepDims).mul(softmax)); + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function localResponseNormalizationBackprop_(x, y, dy, depthRadius, bias, alpha, beta) { + if (depthRadius === void 0) { depthRadius = 5; } + if (bias === void 0) { bias = 1; } + if (alpha === void 0) { alpha = 1; } + if (beta === void 0) { beta = 0.5; } + var forward = function (backend) { + return backend.LRNGrad(dy, x, y, depthRadius, bias, alpha, beta); + }; + var inputs = { x: x, y: y, dy: dy }; + var attrs = { depthRadius: depthRadius, bias: bias, alpha: alpha, beta: beta }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, LRNBackprop, attrs); + } + var localResponseNormalizationBackprop = op({ localResponseNormalizationBackprop_: localResponseNormalizationBackprop_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var lrnGradConfig = { + kernelName: LRN, + inputsToSave: ['x'], + outputsToSave: [true], + gradFunc: function (dy, saved, attrs) { + var _a = saved, x = _a[0], y = _a[1]; + var _b = attrs, depthRadius = _b.depthRadius, bias = _b.bias, alpha = _b.alpha, beta = _b.beta; + return { + x: function () { return localResponseNormalizationBackprop(x, y, dy, depthRadius, bias, alpha, beta); } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the truth value of (a == b) element-wise. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([1, 2, 3]); + * const b = tf.tensor1d([2, 2, 2]); + * + * a.equal(b).print(); + * ``` + * + * @param a The first input tensor. + * @param b The second input tensor. Must have the same dtype as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function equal_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'equal'); + var $b = convertToTensor(b, 'b', 'equal'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + assertAndGetBroadcastShape($a.shape, $b.shape); + var forward = function (backend) { return backend.equal($a, $b); }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null, Equal); + } + var equal = op({ equal_: equal_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Gradient helper function for the min and max operations. + */ + function gradForMinAndMax(dy, y, xOrig, origAxes, permutedAxes) { + if (y.rank < xOrig.rank) { + y = reshape(y, expandShapeToKeepDim(y.shape, origAxes)); + } + if (dy.rank < xOrig.rank) { + dy = reshape(dy, expandShapeToKeepDim(dy.shape, origAxes)); + } + return { + x: function () { + var dx = mul(dy, cast(equal(xOrig, y), dy.dtype)); + return permutedAxes == null ? dx : transpose(dx, permutedAxes); + } + }; + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var maxGradConfig = { + kernelName: Max, + inputsToSave: ['x'], + outputsToSave: [true], + gradFunc: function (dy, saved, attrs) { + var maxAttrs = attrs; + var reductionIndices = maxAttrs.reductionIndices; + var x = saved[0], y = saved[1]; + var origAxes = parseAxisParam(reductionIndices, x.shape); + var permutedAxes = getAxesPermutation(origAxes, x.rank); + var maxGrad = gradForMinAndMax(dy, y, x, origAxes, permutedAxes); + return { + x: function () { + var out = maxGrad['x'](); + if (permutedAxes != null) { + out = transpose(out); + } + return out; + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the truth value of (a < b) element-wise. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([1, 2, 3]); + * const b = tf.tensor1d([2, 2, 2]); + * + * a.less(b).print(); + * ``` + * @param a The first input tensor. + * @param b The second input tensor. Must have the same dtype as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function less_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'less'); + var $b = convertToTensor(b, 'b', 'less'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + assertAndGetBroadcastShape($a.shape, $b.shape); + var forward = function (backend) { return backend.less($a, $b); }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Less); + } + var less = op({ less_: less_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var maximumGradConfig = { + kernelName: Maximum, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var derA = function () { return mul(dy, cast(greaterEqual(a, b), 'float32')); }; + var derB = function () { return mul(dy, cast(less(a, b), 'float32')); }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the backprop of a 3d max pool. + * + * @param dy The dy error, of rank 5 of shape + * [batchSize, depth, height, width, channels]. + * assumed. + * @param input The original input image, of rank 5 or rank 4 of shape + * [batchSize, depth, height, width, channels]. + * @param output The original output image, of rank 5 of shape + * [batchSize, outDepth, outHeight, outWidth, channels]. + * @param filterSize The filter size: + * `[filterDepth, filterHeight, filterWidth]`. + * `filterSize` is a single number, + * then `filterDepth == filterHeight == filterWidth`. + * @param strides The strides of the pooling: + * `[strideDepth, strideHeight, strideWidth]`. If + * `strides` is a single number, then `strideHeight == strideWidth`. + * @param dilations Deprecated, this field will be gone in v3.0.0. + * The dilation rates: `[dilationDepth, dilationHeight, dilationWidth]` + * in which we sample input values across the depth, height and width + * dimensions in dilated pooling. + * Defaults to `[1, 1, 1]`. If `dilations` is a single number, + * then `dilationDepth == dilationHeight == dilationWidth`. + * If it is greater than 1, then all values of `strides` must be 1. + * @param pad A string from: 'same', 'valid'. The type of padding algorithm + * used in the forward prop of the op. + * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The + * rounding mode used when computing output dimensions if pad is a + * number. If none is provided, it will not round and error if the output + * is of fractional size. + */ + function maxPool3dBackprop_(dy, input, output, filterSize, strides, dilations, pad, dimRoundingMode) { + if (dilations === void 0) { dilations = [1, 1, 1]; } + var $dy = convertToTensor(dy, 'dy', 'maxPool3dBackprop'); + var $input = convertToTensor(input, 'input', 'maxPool3dBackprop'); + var $output = convertToTensor(output, 'output', 'maxPool3dBackprop'); + var dy5D = $dy; + var input5D = $input; + var output5D = $output; + var reshapedTo5D = false; + if ($input.rank === 4) { + reshapedTo5D = true; + dy5D = reshape($dy, [1, $dy.shape[0], $dy.shape[1], $dy.shape[2], $dy.shape[3]]); + input5D = reshape($input, [ + 1, $input.shape[0], $input.shape[1], $input.shape[2], $input.shape[3] + ]); + output5D = reshape($output, [ + 1, $output.shape[0], $output.shape[1], $output.shape[2], $output.shape[3] + ]); + } + assert(dy5D.rank === 5, function () { return "Error in maxPool3dBackprop: dy must be rank 5 but got rank " + + (dy5D.rank + "."); }); + assert(input5D.rank === 5, function () { return "Error in maxPool3dBackprop: input must be rank 5 but got rank " + + (input5D.rank + "."); }); + assert(output5D.rank === 5, function () { return "Error in maxPool3dBackprop: output must be rank 5 but got rank " + + (output5D.rank + "."); }); + assert(eitherStridesOrDilationsAreOne(strides, dilations), function () { return 'Error in maxPool3dBackprop: Either strides or dilations ' + + ("must be 1. Got strides " + strides + " and dilations '" + dilations + "'"); }); + if (dimRoundingMode != null) { + assert(isInt(pad), function () { return "Error in maxPool3dBackprop: pad must be an integer when " + + ("using, dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); + } + var forward = function (backend) { + var convInfo = computePool3DInfo(input5D.shape, filterSize, strides, dilations, pad, dimRoundingMode); + return backend.maxPool3dBackprop(dy5D, input5D, output5D, convInfo); + }; + var inputs = { dy: dy5D, input: input5D, output: output5D }; + var attrs = { filterSize: filterSize, strides: strides, dilations: dilations, pad: pad, dimRoundingMode: dimRoundingMode }; + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, MaxPool3DBackprop, attrs); + if (reshapedTo5D) { + return reshape(res, [res.shape[1], res.shape[2], res.shape[3], res.shape[4]]); + } + return res; + } + var maxPool3dBackprop = op({ maxPool3dBackprop_: maxPool3dBackprop_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var maxPool3DGradConfig = { + kernelName: MaxPool3D, + inputsToSave: ['x'], + outputsToSave: [true], + gradFunc: function (dy, saved, attrs) { + var _a = saved, x = _a[0], y = _a[1]; + var _b = attrs, filterSize = _b.filterSize, strides = _b.strides, dilations = _b.dilations, pad = _b.pad, dimRoundingMode = _b.dimRoundingMode; + var $dilations = dilations == null ? [1, 1, 1] : dilations; + return { + x: function () { return maxPool3dBackprop(dy, x, y, filterSize, strides, $dilations, pad, dimRoundingMode); } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the backprop of a 2D max pool. + * + * @param dy The dy error, of rank 4 or rank 3 of shape + * [batchSize, height, width, channels]. If rank 3, batch of 1 is + * assumed. + * @param input The original input image, of rank 4, of shape + * [batchSize, height, width, channels]. + * @param output The original output image, of rank 4, of shape + * [batchSize, outHeight, outWidth, channels]. + * @param filterSize The filter size: `[filterHeight, filterWidth]`. If + * `filterSize` is a single number, then `filterHeight == filterWidth`. + * @param strides The strides of the pooling: `[strideHeight, strideWidth]`. If + * `strides` is a single number, then `strideHeight == strideWidth`. + * @param pad A string from: 'same', 'valid'. The type of padding algorithm + * used in the forward prop of the op. + * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The + * rounding mode used when computing output dimensions if pad is a + * number. If none is provided, it will not round and error if the output + * is of fractional size. + */ + function maxPoolBackprop_(dy, input, output, filterSize, strides, pad, dimRoundingMode) { + var $dy = convertToTensor(dy, 'dy', 'maxPoolBackprop'); + var $input = convertToTensor(input, 'input', 'maxPoolBackprop'); + var $output = convertToTensor(output, 'output', 'maxPoolBackprop'); + assert($input.rank === $dy.rank, function () { return "Rank of input (" + $input.rank + ") does not match rank of dy " + + ("(" + $dy.rank + ")"); }); + assert($dy.rank === 4, function () { return "Error in maxPoolBackprop: dy must be rank 4 but got rank " + + ($dy.rank + "."); }); + assert($input.rank === 4, function () { return "Error in maxPoolBackprop: input must be rank 4 but got rank " + + ($input.rank + "."); }); + if (dimRoundingMode != null) { + assert(isInt(pad), function () { return "Error in maxPoolBackprop: pad must be an integer when using, " + + ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); + } + var forward = function (backend) { + var convInfo = computePool2DInfo($input.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); + return backend.maxPoolBackprop($dy, $input, $output, convInfo); + }; + var inputs = { dy: $dy, input: $input, output: $output }; + var attrs = { filterSize: filterSize, strides: strides, pad: pad, dimRoundingMode: dimRoundingMode }; + return ENGINE.runKernelFunc(forward, inputs, null, MaxPoolBackprop, attrs); + } + var maxPoolBackprop = op({ maxPoolBackprop_: maxPoolBackprop_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var maxPoolGradConfig = { + kernelName: MaxPool, + inputsToSave: ['x'], + outputsToSave: [true], + gradFunc: function (dy, saved, attrs) { + var _a = saved, x = _a[0], y = _a[1]; + var _b = attrs, filterSize = _b.filterSize, strides = _b.strides, pad = _b.pad; + return { + x: function () { return maxPoolBackprop(dy, x, y, filterSize, strides, pad); } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var minGradConfig = { + kernelName: Min, + inputsToSave: ['x'], + outputsToSave: [true], + gradFunc: function (dy, saved, attrs) { + var minAttrs = attrs; + var axis = minAttrs.axis; + var x = saved[0], y = saved[1]; + var origAxes = parseAxisParam(axis, x.shape); + var permutedAxes = getAxesPermutation(origAxes, x.rank); + var minGrad = gradForMinAndMax(dy, y, x, origAxes, permutedAxes); + return { + x: function () { + var out = minGrad['x'](); + if (permutedAxes != null) { + out = transpose(out); + } + return out; + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the truth value of (a > b) element-wise. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([1, 2, 3]); + * const b = tf.tensor1d([2, 2, 2]); + * + * a.greater(b).print(); + * ``` + * + * @param a The first input tensor. + * @param b The second input tensor. Must have the same dtype as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function greater_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'greater'); + var $b = convertToTensor(b, 'b', 'greater'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + assertAndGetBroadcastShape($a.shape, $b.shape); + var forward = function (backend) { return backend.greater($a, $b); }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Greater); + } + var greater = op({ greater_: greater_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var minimumGradConfig = { + kernelName: Minimum, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var derA = function () { return mul(dy, cast(lessEqual(a, b), 'float32')); }; + var derB = function () { return mul(dy, cast(greater(a, b), 'float32')); }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes floor of input `tf.Tensor` element-wise: `floor(x)`. + * + * ```js + * const x = tf.tensor1d([.6, 1.1, -3.3]); + * + * x.floor().print(); // or tf.floor(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function floor_(x) { + var $x = convertToTensor(x, 'x', 'floor'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend) { return backend.floor($x); }, inputs, null /* grad */, Floor); + } + var floor = op({ floor_: floor_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var modGradConfig = { + kernelName: Mod, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var outShape = assertAndGetBroadcastShape(a.shape, b.shape); + var derA = function () { + var reduceAxes = getReductionAxes(a.shape, outShape); + if (reduceAxes.length > 0) { + return reshape(sum$1(dy, reduceAxes), a.shape); + } + return dy; + }; + var derB = function () { + var res = mul(dy, neg(floor(div(a, b)))); + var reduceAxes = getReductionAxes(b.shape, outShape); + if (reduceAxes.length > 0) { + return reshape(sum$1(res, reduceAxes), b.shape); + } + return res; + }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var multiplyGradConfig = { + kernelName: Multiply, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var outShape = assertAndGetBroadcastShape(a.shape, b.shape); + var derA = function () { + var res = mul(dy, cast(b, 'float32')); + var reduceAxes = getReductionAxes(a.shape, outShape); + if (reduceAxes.length > 0) { + return reshape(sum$1(res, reduceAxes), a.shape); + } + return res; + }; + var derB = function () { + var res = mul(dy, cast(a, 'float32')); + var reduceAxes = getReductionAxes(b.shape, outShape); + if (reduceAxes.length > 0) { + return reshape(sum$1(res, reduceAxes), b.shape); + } + return res; + }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var negateGradConfig = { + kernelName: Negate, + gradFunc: function (dy) { + return { x: function () { return neg(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Converts two real numbers to a complex number. + * + * Given a tensor `real` representing the real part of a complex number, and a + * tensor `imag` representing the imaginary part of a complex number, this + * operation returns complex numbers elementwise of the form [r0, i0, r1, i1], + * where r represents the real part and i represents the imag part. + * + * The input tensors real and imag must have the same shape. + * + * ```js + * const real = tf.tensor1d([2.25, 3.25]); + * const imag = tf.tensor1d([4.75, 5.75]); + * const complex = tf.complex(real, imag); + * + * complex.print(); + * ``` + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function complex_(real, imag) { + var $real = convertToTensor(real, 'real', 'complex'); + var $imag = convertToTensor(imag, 'imag', 'complex'); + assertShapesMatch($real.shape, $imag.shape, "real and imag shapes, " + $real.shape + " and " + $imag.shape + ", " + + "must match in call to tf.complex()."); + var forward = function (backend) { + return backend.complex($real, $imag); + }; + var inputs = { real: $real, imag: $imag }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Complex); + } + var complex = op({ complex_: complex_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates a `tf.Tensor` with all elements set to 0. + * + * ```js + * tf.zeros([2, 2]).print(); + * ``` + * + * @param shape An array of integers defining the output tensor shape. + * @param dtype The type of an element in the resulting tensor. Can + * be 'float32', 'int32' or 'bool'. Defaults to 'float'. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function zeros(shape, dtype) { + if (dtype === void 0) { dtype = 'float32'; } + if (dtype === 'complex64') { + var real = zeros(shape, 'float32'); + var imag = zeros(shape, 'float32'); + return complex(real, imag); + } + var values = makeZerosTypedArray(sizeFromShape(shape), dtype); + return ENGINE.makeTensor(values, shape, dtype); + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var oneHotGradConfig = { + kernelName: OneHot, + inputsToSave: ['indices'], + gradFunc: function (dy, saved) { + var indices = saved[0]; + return { indices: function () { return zeros(indices.shape, 'float32'); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var onesLikeGradConfig = { + kernelName: OnesLike, + gradFunc: function (dy) { + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var padV2GradConfig = { + kernelName: PadV2, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + // Pad introduces values around the original tensor, so the gradient + // slices the original shape out of the gradient. + var x = saved[0]; + var paddings = attrs.paddings; + var begin = paddings.map(function (p) { return p[0]; }); + return { x: function () { return dy.slice(begin, x.shape); } }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes natural logarithm of the input `tf.Tensor` element-wise: `ln(x)` + * + * ```js + * const x = tf.tensor1d([1, 2, Math.E]); + * + * x.log().print(); // or tf.log(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function log_(x) { + var $x = convertToTensor(x, 'x', 'log'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.log($x); + save([$x]); + return res; + }, inputs, null /* grad */, Log); + } + var log = op({ log_: log_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the power of one `tf.Tensor` to another. Supports broadcasting. + * + * Given a `tf.Tensor` x and a `tf.Tensor` y, this operation computes x^y for + * corresponding elements in x and y. The result's dtype will be the upcasted + * type of the `base` and `exp` dtypes. + * + * ```js + * const a = tf.tensor([[2, 3], [4, 5]]) + * const b = tf.tensor([[1, 2], [3, 0]]).toInt(); + * + * a.pow(b).print(); // or tf.pow(a, b) + * ``` + * + * ```js + * const a = tf.tensor([[1, 2], [3, 4]]) + * const b = tf.tensor(2).toInt(); + * + * a.pow(b).print(); // or tf.pow(a, b) + * ``` + * We also expose `powStrict` which has the same signature as this op and + * asserts that `base` and `exp` are the same shape (does not broadcast). + * + * @param base The base `tf.Tensor` to pow element-wise. + * @param exp The exponent `tf.Tensor` to pow element-wise. + */ + /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ + function pow_(base, exp) { + var _a; + var $base = convertToTensor(base, 'base', 'pow'); + var $exp = convertToTensor(exp, 'exp', 'pow'); + _a = makeTypesMatch($base, $exp), $base = _a[0], $exp = _a[1]; + var inputs = { a: $base, b: $exp }; + var forward = function (backend, save) { + var y = backend.pow($base, $exp); + save([$base, $exp, y]); + return y; + }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Pow); + } + var pow = op({ pow_: pow_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var powGradConfig = { + kernelName: Pow, + inputsToSave: ['a', 'b'], + outputsToSave: [true], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1], y = saved[2]; + var base = a; + var exp = b; + var outShape = assertAndGetBroadcastShape(base.shape, exp.shape); + var derBase = function () { + var expFloat = cast(exp, 'float32'); + var res = mul(dy, mul(expFloat, pow(base, sub(expFloat, scalar(1))))); + var reduceAxes = getReductionAxes(base.shape, outShape); + if (reduceAxes.length > 0) { + res = sum$1(res, reduceAxes); + } + return reshape(res, base.shape); + }; + var derExp = function () { + var condition = greater(base, 0); + var logBase = where(condition, log(base), zerosLike(base)); + var res = mul(dy, mul(y, logBase)); + var reduceAxes = getReductionAxes(exp.shape, outShape); + if (reduceAxes.length > 0) { + res = sum$1(res, reduceAxes); + } + return reshape(res, exp.shape); + }; + return { a: derBase, b: derExp }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var preluGradConfig = { + kernelName: Prelu, + inputsToSave: ['x', 'alpha'], + gradFunc: function (dy, saved) { + var x = saved[0], alpha = saved[1]; + var mask = greater(x, 0); + return { + x: function () { return where(mask, dy, mul(dy, alpha)); }, + alpha: function () { + var res = where(mask, zerosLike(dy), mul(dy, x)); + var reduceAxes = getReductionAxes(alpha.shape, dy.shape); + if (reduceAxes.length > 0) { + res = sum$1(res, reduceAxes); + } + return reshape(res, alpha.shape); + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var reciprocalGradConfig = { + kernelName: Reciprocal, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, neg(square(x))); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var relu6GradConfig = { + kernelName: Relu6, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + var mask = mul(lessEqual(x, 6), step(x)); + return { x: function () { return mul(dy, cast(mask, 'float32')); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var reluGradConfig = { + kernelName: Relu, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(dy, cast(step(x), 'float32')); } }; + } + }; + + /** + * @license + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var reshapeGradConfig = { + kernelName: Reshape, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return reshape(dy, x.shape); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var resizeBilinearGradConfig = { + kernelName: ResizeBilinear, + inputsToSave: ['images'], + gradFunc: function (dy, saved, attrs) { + var images = saved[0]; + var backPropKernelFunc = function (backend) { + var alignCorners = attrs.alignCorners; + return backend.resizeBilinearBackprop(dy, images, alignCorners); + }; + var inputs = { images: images }; + var imagesDer = function () { return ENGINE.runKernelFunc(backPropKernelFunc, inputs, null /* gradient */, ResizeBilinearGrad, attrs); }; + return { images: imagesDer }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var resizeNearestNeighborGradConfig = { + kernelName: ResizeNearestNeighbor, + inputsToSave: ['images'], + gradFunc: function (dy, saved, attrs) { + var images = saved[0]; + var backPropKernelFunc = function (backend) { + var alignCorners = attrs.alignCorners; + return backend.resizeNearestNeighborBackprop(dy, images, alignCorners); + }; + var inputs = { images: images }; + var imagesDer = function () { return ENGINE.runKernelFunc(backPropKernelFunc, inputs, null /* gradient */, ResizeNearestNeighborGrad, attrs); }; + return { images: imagesDer }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates a new tensor with the same values and shape as the specified + * tensor. + * + * ```js + * const x = tf.tensor([1, 2]); + * + * x.clone().print(); + * ``` + * + * @param x The tensor to clone. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function clone_(x) { + var $x = convertToTensor(x, 'x', 'clone', null); + var forward = function () { + return ENGINE.makeTensorFromDataId($x.dataId, $x.shape, $x.dtype); + }; + var inputs = { x: $x }; + // Note this op is called tf.identity in python. Hence the kernel name used + // here. + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Identity); + } + var clone = op({ clone_: clone_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Reverses a `tf.Tensor` along a specified axis. + * + * Also available are stricter rank-specific methods that assert that `x` is + * of the given rank: + * - `tf.reverse1d` + * - `tf.reverse2d` + * - `tf.reverse3d` + * - `tf.reverse4d` + * + * Except `tf.reverse1d` (which does not have axis param), all methods have + * same signature as this method. + * + * ```js + * const x = tf.tensor1d([1, 2, 3, 4]); + * + * x.reverse().print(); + * ``` + * + * ```js + * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); + * + * const axis = 1; + * x.reverse(axis).print(); + * ``` + * @param x The input tensor to be reversed. + * @param axis The set of dimensions to reverse. Must be in the + * range [-rank(x), rank(x)). Defaults to all axes. + */ + /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ + function reverse_(x, axis) { + var $x = convertToTensor(x, 'x', 'reverse'); + var forward = function (backend) { + var axes = parseAxisParam(axis, $x.shape); + if ($x.rank === 0) { + return clone($x); + } + var res = backend.reverse($x, axes); + return reshape(res, $x.shape); + }; + var inputs = { x: $x }; + var attrs = { dims: axis }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Reverse, attrs); + } + var reverse = op({ reverse_: reverse_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var reverseGradConfig = { + kernelName: Reverse, + gradFunc: function (dy, saved, attrs) { + var dims = attrs.dims; + var axes = parseAxisParam(dims, dy.shape); + return { x: function () { return reverse(dy, axes); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var roundGradConfig = { + kernelName: Round, + gradFunc: function (dy) { + // TODO(nsthorat): Let gradients be null for cases where we want to stop + // backpropgation. + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var rsqrtGradConfig = { + kernelName: Rsqrt, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return neg(div(dy, mul(pow(x, 1.5), 2))); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the truth value of `NOT x` element-wise. + * + * ```js + * const a = tf.tensor1d([false, true], 'bool'); + * + * a.logicalNot().print(); + * ``` + * + * @param x The input tensor. Must be of dtype 'bool'. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function logicalNot_(x) { + var $x = convertToTensor(x, 'x', 'logicalNot', 'bool'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend) { return backend.logicalNot($x); }, inputs, null /* grad */, LogicalNot); + } + var logicalNot = op({ logicalNot_: logicalNot_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var selectV2PoolGradConfig = { + kernelName: SelectV2, + inputsToSave: ['condition'], + gradFunc: function (dy, saved) { + var condition = saved[0]; + return { + // TODO(julianoks): Return null for condition gradient + // when backprop supports it. + condition: function () { return cast(zerosLike(condition), 'float32'); }, + t: function () { return mul(dy, cast(condition, dy.dtype)); }, + e: function () { return mul(dy, cast(logicalNot(condition), dy.dtype)); } + }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var SELU_SCALEALPHA = 1.7580993408473768599402175208123; + var SELU_SCALE = 1.0507009873554804934193349852946; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var seluGradConfig = { + kernelName: Selu, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { + x: function () { + var mask = greater(x, scalar(0)); + var scaleAlpha = scalar(SELU_SCALEALPHA); + var scale = scalar(SELU_SCALE); + var greaterThanZeroDer = mul(dy, scale); + var lessEqualZeroDer = mul(mul(dy, scaleAlpha), exp(cast(x, 'float32'))); + return where(mask, greaterThanZeroDer, lessEqualZeroDer); + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var sigmoidGradConfig = { + kernelName: Sigmoid, + outputsToSave: [true], + gradFunc: function (dy, saved) { + var y = saved[0]; + return { x: function () { return mul(dy, mul(y, sub(scalar(1), y))); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var signGradConfig = { + kernelName: Sign, + gradFunc: function (dy) { + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes cos of the input `tf.Tensor` element-wise: `cos(x)` + * + * ```js + * const x = tf.tensor1d([0, Math.PI / 2, Math.PI * 3 / 4]); + * + * x.cos().print(); // or tf.cos(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function cos_(x) { + var $x = convertToTensor(x, 'x', 'cos'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.cos($x); + save([$x]); + return res; + }, inputs, null /* grad */, Cos); + } + var cos = op({ cos_: cos_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var sinGradConfig = { + kernelName: Sin, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(cos(cast(x, 'float32')), dy); } }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes hyperbolic cos of the input `tf.Tensor` element-wise: `cosh(x)` + * + * ```js + * const x = tf.tensor1d([0, 1, -1, .7]); + * + * x.cosh().print(); // or tf.cosh(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function cosh_(x) { + var $x = convertToTensor(x, 'x', 'cosh'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.cosh($x); + save([$x]); + return res; + }, inputs, null /* grad */, Cosh); + } + var cosh = op({ cosh_: cosh_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var sinhGradConfig = { + kernelName: Sinh, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(cosh(cast(x, 'float32')), dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Pads a `tf.Tensor` with a given value and paddings. + * + * This operation currently only implements the `CONSTANT` mode. + * + * Also available are stricter rank-specific methods with the same signature + * as this method that assert that `paddings` is of given length. + * - `tf.pad1d` + * - `tf.pad2d` + * - `tf.pad3d` + * - `tf.pad4d` + * + * ```js + * const x = tf.tensor1d([1, 2, 3, 4]); + * x.pad([[1, 2]]).print(); + * ``` + * @param x The tensor to pad. + * @param paddings An array of length `R` (the rank of the tensor), where + * each element is a length-2 tuple of ints `[padBefore, padAfter]`, + * specifying how much to pad along each dimension of the tensor. + * @param constantValue The pad value to use. Defaults to 0. + */ + /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ + function pad_(x, paddings, constantValue) { + if (constantValue === void 0) { constantValue = 0; } + var $x = convertToTensor(x, 'x', 'pad'); + if ($x.rank === 0) { + throw new Error('pad(scalar) is not defined. Pass non-scalar to pad'); + } + var forward = function (backend, save) { + save([$x]); + return backend.pad($x, paddings, constantValue); + }; + var attrs = { paddings: paddings, constantValue: constantValue }; + var inputs = { x: $x }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, PadV2, attrs); + } + var pad = op({ pad_: pad_ }); + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function assertParamsValid(input, begin, size) { + assert(input.rank === begin.length, function () { return "Error in slice" + input.rank + "D: Length of begin " + begin + " must " + + ("match the rank of the array (" + input.rank + ")."); }); + assert(input.rank === size.length, function () { return "Error in slice" + input.rank + "D: Length of size " + size + " must " + + ("match the rank of the array (" + input.rank + ")."); }); + var _loop_1 = function (i) { + assert(begin[i] + size[i] <= input.shape[i], function () { return "Error in slice" + input.rank + "D: begin[" + i + "] + size[" + i + "] " + + ("(" + (begin[i] + size[i]) + ") would overflow input.shape[" + i + "] (" + input.shape[i] + ")"); }); + }; + for (var i = 0; i < input.rank; ++i) { + _loop_1(i); + } + } + /** Converts a binary mask to an array of axes. Used in stridedSlice(). */ + function maskToAxes(mask) { + var axes = []; + var axis = 0; + while (mask > 0) { + if (mask & 1) { + axes.push(axis); + } + mask /= 2; + axis++; + } + return axes; + } + /** Computes the output shape given the strided slice params. */ + function computeOutShape(begin, end, strides) { + var size = []; + for (var axis = 0; axis < begin.length; axis++) { + size[axis] = Math.ceil((end[axis] - begin[axis]) / strides[axis]); + } + return size; + } + // Creates full selection at the elided dimensions. If the dimension matches + // the ellipsis mask, override the current stride value. Otherwise, insert. + function stridesWithElidedDims(strides, ellipsisInsertionIndex, numElidedAxes, inputShape) { + var newStrides = strides.slice(); + for (var i = newStrides.length; i < inputShape.length; i++) { + newStrides.push(1); + } + for (var i = 0; i < numElidedAxes; i++) { + if (i === 0) { + newStrides[ellipsisInsertionIndex] = 1; + } + else { + newStrides.splice(ellipsisInsertionIndex, 0 /* num elements to delete */, 1 /* element to add */); + newStrides.pop(); + } + } + return newStrides; + } + function unnormalizeAxis(ellipsisInsertionIndex, numElidedAxes, normalizedAxis) { + if (normalizedAxis <= ellipsisInsertionIndex) { + return normalizedAxis; + } + return normalizedAxis - (numElidedAxes - 1); + } + function getElidedAxes(numElidedAxes, ellipsisInsertionIndex) { + var elidedAxes = []; + for (var i = 0; i < numElidedAxes; i++) { + elidedAxes.push(ellipsisInsertionIndex + i); + } + return elidedAxes; + } + // Creates full selection at the elided dimensions. If the dimension matches + // the ellipsis mask, override the current start value. Otherwise, insert. + function startIndicesWithElidedDims(beginMask, ellipsisInsertionIndex, numElidedAxes, originalBegin, inputShape) { + var newIndices = inputShape.slice(); + var elidedAxes = getElidedAxes(numElidedAxes, ellipsisInsertionIndex); + for (var axis = 0; axis < newIndices.length; axis++) { + if (elidedAxes.indexOf(axis) > -1) { + newIndices[axis] = 0; + } + else { + var originalAxis = unnormalizeAxis(ellipsisInsertionIndex, numElidedAxes, axis); + var originalValue = originalBegin[originalAxis]; + if (beginMask & 1 << originalAxis) { + originalValue = 0; + } + newIndices[axis] = originalValue; + } + } + return newIndices; + } + // Creates full selection at the elided dimensions. If the dimension matches + // the ellipsis mask, override the current stop value. Otherwise, insert. + function stopIndicesWithElidedDims(endMask, ellipsisInsertionIndex, numElidedAxes, originalEnd, inputShape) { + var newIndices = inputShape.slice(); + var elidedAxes = getElidedAxes(numElidedAxes, ellipsisInsertionIndex); + for (var axis = 0; axis < newIndices.length; axis++) { + if (elidedAxes.indexOf(axis) > -1) { + newIndices[axis] = Number.MAX_SAFE_INTEGER; + } + else { + var originalAxis = unnormalizeAxis(ellipsisInsertionIndex, numElidedAxes, axis); + var originalValue = originalEnd[originalAxis]; + if (endMask & 1 << originalAxis) { + originalValue = Number.MAX_SAFE_INTEGER; + } + newIndices[axis] = originalValue; + } + } + for (var i = 0; i < newIndices.length; i++) { + newIndices[i] = clamp(0, newIndices[i], inputShape[i]); + } + return newIndices; + } + function stridesForAxis(strides, axis, ellipsisMask) { + var stride = strides[axis]; + if (ellipsisMask & (1 << axis) || stride == null) { + stride = 1; + } + return stride; + } + function startForAxis(beginMask, startIndices, strides, inputShape, axis, ellipsisMask) { + // Begin with the specified index + var start = startIndices[axis]; + var stride = strides[axis] || 1; + // Check the axis bit from right of masked axes, or the begin index is not set + // for the axis. + if (beginMask & 1 << axis || ellipsisMask & 1 << axis || start == null) { + if (stride > 0) { + // Forward iteration - use the first element. These values will get + // clamped below (Note: We could have set them to 0 and axis_size-1, but + // use lowest() and max() to maintain symmetry with StopForAxis()) + start = Number.MIN_SAFE_INTEGER; + } + else { + // Backward iteration - use the last element. + start = Number.MAX_SAFE_INTEGER; + } + } + // Handle negative indices + var axisSize = inputShape[axis]; + if (start < 0) { + start += axisSize; + } + // Clamping + start = clamp(0, start, axisSize - 1); + return start; + } + function stopForAxis(endMask, stopIndices, strides, inputShape, axis, ellipsisMask) { + // Begin with the specified index + var stop = stopIndices[axis]; + var stride = strides[axis] || 1; + // Check the axis bit from right of masked axes, or if the stop index is not + // set for this axis. + if (endMask & (1 << axis) || ellipsisMask & (1 << axis) || stop == null) { + if (stride > 0) { + // Forward iteration - use the last element. These values will get + // clamped below + stop = Number.MAX_SAFE_INTEGER; + } + else { + // Backward iteration - use the first element. + stop = Number.MIN_SAFE_INTEGER; + } + } + // Handle negative indices + var axisSize = inputShape[axis]; + if (stop < 0) { + stop += axisSize; + } + // Clamping + // Because the end index points one past the last element, we need slightly + // different clamping ranges depending on the direction. + if (stride > 0) { + // Forward iteration + stop = clamp(0, stop, axisSize); + } + else { + // Backward iteration + stop = clamp(-1, stop, axisSize - 1); + } + return stop; + } + /** + * Returns true if the slice occupies a continous set of elements in the + * 'flat' space. + */ + function isSliceContinous(shape, begin, size) { + // Index of the first axis that has size > 1. + var firstNonOneAxis = size.length; + for (var i = 0; i < size.length; i++) { + if (size[i] > 1) { + firstNonOneAxis = i; + break; + } + } + for (var i = firstNonOneAxis + 1; i < size.length; i++) { + if (begin[i] > 0 || size[i] !== shape[i]) { + return false; + } + } + return true; + } + function computeFlatOffset(begin, strides) { + var flatOffset = begin.length > 0 ? begin[begin.length - 1] : 1; + for (var i = 0; i < begin.length - 1; i++) { + flatOffset += begin[i] * strides[i]; + } + return flatOffset; + } + function parseSliceParams(x, begin, size) { + // The following logic allows for more ergonomic calls. + var begin_; + if (typeof begin === 'number') { + begin_ = [begin].concat(new Array(x.rank - 1).fill(0)); + } + else if (begin.length < x.rank) { + begin_ = begin.concat(new Array(x.rank - begin.length).fill(0)); + } + else { + begin_ = begin.slice(); + } + begin_.forEach(function (d) { + assert(d !== -1, function () { return 'slice() does not support negative begin indexing.'; }); + }); + var size_; + if (size == null) { + size_ = new Array(x.rank).fill(-1); + } + else if (typeof size === 'number') { + size_ = [size].concat(new Array(x.rank - 1).fill(-1)); + } + else if (size.length < x.rank) { + size_ = size.concat(new Array(x.rank - size.length).fill(-1)); + } + else { + size_ = size; + } + size_ = size_.map(function (d, i) { + if (d >= 0) { + return d; + } + else { + assert(d === -1, function () { return "Negative size values should be exactly -1 but got " + + (d + " for the slice() size at index " + i + "."); }); + return x.shape[i] - begin_[i]; + } + }); + return [begin_, size_]; + } + + var slice_util = { + __proto__: null, + assertParamsValid: assertParamsValid, + maskToAxes: maskToAxes, + computeOutShape: computeOutShape, + stridesWithElidedDims: stridesWithElidedDims, + startIndicesWithElidedDims: startIndicesWithElidedDims, + stopIndicesWithElidedDims: stopIndicesWithElidedDims, + stridesForAxis: stridesForAxis, + startForAxis: startForAxis, + stopForAxis: stopForAxis, + isSliceContinous: isSliceContinous, + computeFlatOffset: computeFlatOffset, + parseSliceParams: parseSliceParams + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var sliceGradConfig = { + kernelName: Slice, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0]; + var _a = attrs, begin = _a.begin, size = _a.size; + var inputShape = x.shape; + var _b = parseSliceParams(x, begin, size), begin_ = _b[0], size_ = _b[1]; + // Create an Nx2 padding where the first column represents how many + // zeros are prepended (at start) for each dimension, and the second + // column indicates how many zeros are appended (at end). + // The number of zeros to append is the shape of the input + // elementwise-subtracted by both the begin vector and sizes vector. + var paddings = []; + for (var i = 0; i < dy.rank; i++) { + paddings.push([begin_[i], inputShape[i] - begin_[i] - size_[i]]); + } + return { x: function () { return pad(dy, paddings); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var softmaxGradConfig = { + kernelName: Softmax, + outputsToSave: [true], + gradFunc: function (dy, saved, attrs) { + var y = saved[0]; + var dim = attrs.dim; + var keepDims = true; + var dyTimesY = mul(dy, y); + return { + logits: function () { return sub(dyTimesY, mul(sum$1(dyTimesY, [dim], keepDims), y)); } + }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes sigmoid element-wise, `1 / (1 + exp(-x))` + * + * ```js + * const x = tf.tensor1d([0, -1, 2, -3]); + * + * x.sigmoid().print(); // or tf.sigmoid(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function sigmoid_(x) { + var $x = convertToTensor(x, 'x', 'sigmoid'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.sigmoid($x); + save([res]); + return res; + }, inputs, null /* grad */, Sigmoid); + } + var sigmoid = op({ sigmoid_: sigmoid_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var softplusGradConfig = { + kernelName: Softplus, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(dy, sigmoid(x)); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * This operation reshapes the "batch" dimension 0 into `M + 1` dimensions of + * shape `blockShape + [batch]`, interleaves these blocks back into the grid + * defined by the spatial dimensions `[1, ..., M]`, to obtain a result with + * the same rank as the input. The spatial dimensions of this intermediate + * result are then optionally cropped according to `crops` to produce the + * output. This is the reverse of `tf.spaceToBatchND`. See below for a precise + * description. + * + * ```js + * const x = tf.tensor4d([1, 2, 3, 4], [4, 1, 1, 1]); + * const blockShape = [2, 2]; + * const crops = [[0, 0], [0, 0]]; + * + * x.batchToSpaceND(blockShape, crops).print(); + * ``` + * + * @param x A `tf.Tensor`. N-D with `x.shape` = `[batch] + spatialShape + + * remainingShape`, where spatialShape has `M` dimensions. + * @param blockShape A 1-D array. Must have shape `[M]`, all values must + * be >= 1. + * @param crops A 2-D array. Must have shape `[M, 2]`, all values must be >= 0. + * `crops[i] = [cropStart, cropEnd]` specifies the amount to crop from input + * dimension `i + 1`, which corresponds to spatial dimension `i`. It is required + * that `cropStart[i] + cropEnd[i] <= blockShape[i] * inputShape[i + 1]` + * + * This operation is equivalent to the following steps: + * + * 1. Reshape `x` to `reshaped` of shape: `[blockShape[0], ..., + * blockShape[M-1], batch / prod(blockShape), x.shape[1], ..., + * x.shape[N-1]]` + * + * 2. Permute dimensions of `reshaped`to produce `permuted` of shape `[batch / + * prod(blockShape),x.shape[1], blockShape[0], ..., x.shape[M], + * blockShape[M-1],x.shape[M+1], ..., x.shape[N-1]]` + * + * 3. Reshape `permuted` to produce `reshapedPermuted` of shape `[batch / + * prod(blockShape),x.shape[1] * blockShape[0], ..., x.shape[M] * + * blockShape[M-1],x.shape[M+1], ..., x.shape[N-1]]` + * + * 4. Crop the start and end of dimensions `[1, ..., M]` of `reshapedPermuted` + * according to `crops` to produce the output of shape: `[batch / + * prod(blockShape),x.shape[1] * blockShape[0] - crops[0,0] - crops[0,1], + * ..., x.shape[M] * blockShape[M-1] - crops[M-1,0] - + * crops[M-1,1],x.shape[M+1], ..., x.shape[N-1]]` + */ + /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ + function batchToSpaceND_(x, blockShape, crops) { + var $x = convertToTensor(x, 'x', 'batchToSpaceND'); + var prod = blockShape.reduce(function (a, b) { return a * b; }); + assert($x.rank >= 1 + blockShape.length, function () { return "input rank is " + $x.rank + " but should be > than blockShape.length " + blockShape.length; }); + assert(crops.length === blockShape.length, function () { return "crops.length is " + crops.length + " but should be equal to blockShape.length " + blockShape.length; }); + assert($x.shape[0] % prod === 0, function () { return "input tensor batch is " + $x.shape[0] + " but is not divisible by the product of " + + ("the elements of blockShape " + blockShape.join(' * ') + " === " + prod); }); + var forward = function (backend) { + return backend.batchToSpaceND($x, blockShape, crops); + }; + var inputs = { x: $x }; + var attrs = { blockShape: blockShape, crops: crops }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, BatchToSpaceND, attrs); + } + var batchToSpaceND = op({ batchToSpaceND_: batchToSpaceND_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var spaceToBatchNDGradConfig = { + kernelName: SpaceToBatchND, + gradFunc: function (dy, saved, attrs) { + var _a = attrs, blockShape = _a.blockShape, paddings = _a.paddings; + return { x: function () { return batchToSpaceND(dy, blockShape, paddings); } }; + } + }; + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function assertParamsConsistent(shapes, axis) { + var rank = shapes[0].length; + shapes.forEach(function (shape, i) { + assert(shape.length === rank, function () { + return "Error in concat" + rank + "D: rank of tensors[" + i + "] must be the same " + + ("as the rank of the rest (" + rank + ")"); + }); + }); + assert(axis >= 0 && axis < rank, function () { return "Error in concat" + rank + "D: axis must be between 0 and " + (rank - 1) + "."; }); + var firstShape = shapes[0]; + shapes.forEach(function (shape, i) { + for (var r = 0; r < rank; r++) { + assert((r === axis) || (shape[r] === firstShape[r]), function () { return "Error in concat" + rank + "D: Shape of tensors[" + i + "] (" + shape + ") " + + ("does not match the shape of the rest (" + firstShape + ") ") + + ("along the non-concatenated axis " + i + "."); }); + } + }); + } + function computeOutShape$1(shapes, axis) { + var outputShape = shapes[0].slice(); + for (var i = 1; i < shapes.length; i++) { + outputShape[axis] += shapes[i][axis]; + } + return outputShape; + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates a `tf.Tensor` with the provided values, shape and dtype. + * + * ```js + * // Pass an array of values to create a vector. + * tf.tensor([1, 2, 3, 4]).print(); + * ``` + * + * ```js + * // Pass a nested array of values to make a matrix or a higher + * // dimensional tensor. + * tf.tensor([[1, 2], [3, 4]]).print(); + * ``` + * + * ```js + * // Pass a flat array and specify a shape yourself. + * tf.tensor([1, 2, 3, 4], [2, 2]).print(); + * ``` + * + * @param values The values of the tensor. Can be nested array of numbers, + * or a flat array, or a `TypedArray`. If the values are strings, + * they will be encoded as utf-8 and kept as `Uint8Array[]`. + * @param shape The shape of the tensor. Optional. If not provided, + * it is inferred from `values`. + * @param dtype The data type. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function tensor(values, shape, dtype) { + var inferredShape = inferShape(values, dtype); + return makeTensor(values, shape, inferredShape, dtype); + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Concatenates a list of `tf.Tensor`s along a given axis. + * + * The tensors ranks and types must match, and their sizes must match in all + * dimensions except `axis`. + * + * Also available are stricter rank-specific methods that assert that + * `tensors` are of the given rank: + * - `tf.concat1d` + * - `tf.concat2d` + * - `tf.concat3d` + * - `tf.concat4d` + * + * Except `tf.concat1d` (which does not have axis param), all methods have + * same signature as this method. + * + * ```js + * const a = tf.tensor1d([1, 2]); + * const b = tf.tensor1d([3, 4]); + * a.concat(b).print(); // or a.concat(b) + * ``` + * + * ```js + * const a = tf.tensor1d([1, 2]); + * const b = tf.tensor1d([3, 4]); + * const c = tf.tensor1d([5, 6]); + * tf.concat([a, b, c]).print(); + * ``` + * + * ```js + * const a = tf.tensor2d([[1, 2], [10, 20]]); + * const b = tf.tensor2d([[3, 4], [30, 40]]); + * const axis = 1; + * tf.concat([a, b], axis).print(); + * ``` + * @param tensors A list of tensors to concatenate. + * @param axis The axis to concate along. Defaults to 0 (the first dim). + */ + /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ + function concat_(tensors, axis) { + if (axis === void 0) { axis = 0; } + assert(tensors.length >= 1, function () { return 'Pass at least one tensor to concat'; }); + var $tensors = convertToTensorArray(tensors, 'tensors', 'concat'); + if ($tensors[0].dtype === 'complex64') { + $tensors.forEach(function (tensor) { + if (tensor.dtype !== 'complex64') { + throw new Error("Cannot concatenate complex64 tensors with a tensor\n with dtype " + tensor.dtype + ". "); + } + }); + } + var $axis = parseAxisParam(axis, $tensors[0].shape)[0]; + var outShape = computeOutShape$1($tensors.map(function (t) { return t.shape; }), $axis); + if (sizeFromShape(outShape) === 0) { + return tensor([], outShape); + } + // Keep only non-empty tensors (ignore tensors with 0 in their shape). + $tensors = $tensors.filter(function (t) { return t.size > 0; }); + if ($tensors.length === 1) { + return $tensors[0]; + } + var shapes = $tensors.map(function (t) { return t.shape; }); + assertParamsConsistent(shapes, $axis); + var forward = function (backend, save) { + var res = backend.concat($tensors, $axis); + save($tensors); + return res; + }; + var inputs = $tensors; + var attr = { axis: axis }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Concat, attr); + } + var concat = op({ concat_: concat_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var splitVGradConfig = { + kernelName: SplitV, + gradFunc: function (dy, saved, attrs) { + var axis = attrs.axis; + return { x: function () { return concat(dy, axis); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var sqrtGradConfig = { + kernelName: Sqrt, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, mul(sqrt(cast(x, 'float32')), 2)); } }; + } + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var squareGradConfig = { + kernelName: Square, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(dy, mul(x.toFloat(), 2)); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var squaredDifferenceGradConfig = { + kernelName: SquaredDifference, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var two = scalar(2); + var derA = function () { return mul(dy, mul(two, sub(a, b))); }; + var derB = function () { return mul(dy, mul(two, sub(b, a))); }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var stepGradConfig = { + kernelName: Step, + gradFunc: function (dy) { + // TODO(manrajgrover): Return null for gradients when backprop supports + // it. + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var subGradConfig = { + kernelName: Sub, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var outShape = assertAndGetBroadcastShape(a.shape, b.shape); + var derA = function () { + var res = dy; + var reduceAxes = getReductionAxes(a.shape, outShape); + if (reduceAxes.length > 0) { + res = sum$1(res, reduceAxes); + } + return reshape(res, a.shape); + }; + var derB = function () { + var res = dy; + var reduceAxes = getReductionAxes(b.shape, outShape); + if (reduceAxes.length > 0) { + res = sum$1(res, reduceAxes); + } + return reshape(neg(res), b.shape); + }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates a `tf.Tensor` with all elements set to 1. + * + * ```js + * tf.ones([2, 2]).print(); + * ``` + * + * @param shape An array of integers defining the output tensor shape. + * @param dtype The type of an element in the resulting tensor. Defaults to + * 'float'. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function ones$1(shape, dtype) { + if (dtype === void 0) { dtype = 'float32'; } + if (dtype === 'complex64') { + var real = ones$1(shape, 'float32'); + var imag = zeros(shape, 'float32'); + return complex(real, imag); + } + var values = makeOnesTypedArray(sizeFromShape(shape), dtype); + return ENGINE.makeTensor(values, shape, dtype); + } + + /** + * @license + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var sumGradConfig = { + kernelName: Sum, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0]; + var expandedDyShape = x.shape.slice(); + var axis = attrs.axis; + var axes = parseAxisParam(axis, x.shape); + axes.forEach(function (axis) { + expandedDyShape[axis] = 1; + }); + var expandedDy = reshape(dy, expandedDyShape); + var derX = mul(expandedDy, ones$1(x.shape, 'float32')); + return { x: function () { return derX; } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var tanGradConfig = { + kernelName: Tan, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, square(cos(x))); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var tanhGradConfig = { + kernelName: Tanh, + outputsToSave: [true], + gradFunc: function (dy, saved) { + var y = saved[0]; + return { x: function () { return mul(sub(scalar(1), square(y)), dy); } }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Extracts a slice from a `tf.Tensor` starting at coordinates `begin` + * and is of size `size`. + * + * Also available are stricter rank-specific methods with the same signature + * as this method that assert that `x` is of the given rank: + * - `tf.slice1d` + * - `tf.slice2d` + * - `tf.slice3d` + * - `tf.slice4d` + * + * ```js + * const x = tf.tensor1d([1, 2, 3, 4]); + * + * x.slice([1], [2]).print(); + * ``` + * + * ```js + * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); + * + * x.slice([1, 0], [1, 2]).print(); + * ``` + * @param x The input `tf.Tensor` to slice from. + * @param begin The coordinates to start the slice from. The length can be + * less than the rank of x - the rest of the axes will have implicit 0 as + * start. Can also be a single number, in which case it specifies the + * first axis. + * @param size The size of the slice. The length can be less than the rank of + * x - the rest of the axes will have implicit -1. A value of -1 requests + * the rest of the dimensions in the axis. Can also be a single number, + * in which case it specifies the size of the first axis. + */ + /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ + function slice_(x, begin, size) { + var $x = convertToTensor(x, 'x', 'slice'); + if ($x.rank === 0) { + throw new Error('Slicing scalar is not possible'); + } + var _a = parseSliceParams($x, begin, size), begin_ = _a[0], size_ = _a[1]; + assertParamsValid($x, begin_, size_); + var forward = function (backend, save) { + save([$x]); + return backend.slice($x, begin_, size_); + }; + var inputs = { x: $x }; + var attrs = { begin: begin, size: size }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Slice, attrs); + } + var slice = op({ slice_: slice_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var tileGradConfig = { + kernelName: Tile, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0]; + var reps = attrs.reps; + var derX = function () { + var xGrad = zerosLike(x); + // TODO(cais): Maybe reduce memory footprint by avoiding repeated + // slicing. + if (x.rank === 1) { + for (var i = 0; i < reps[0]; ++i) { + xGrad = add(xGrad, slice(dy, [i * x.shape[0]], [x.shape[0]])); + } + } + else if (x.rank === 2) { + for (var i = 0; i < reps[0]; ++i) { + for (var j = 0; j < reps[1]; ++j) { + xGrad = add(xGrad, slice(dy, [i * x.shape[0], j * x.shape[1]], [ + x.shape[0], x.shape[1] + ])); + } + } + } + else if (x.rank === 3) { + for (var i = 0; i < reps[0]; ++i) { + for (var j = 0; j < reps[1]; ++j) { + for (var k = 0; k < reps[2]; ++k) { + xGrad = + add(xGrad, slice(dy, [i * x.shape[0], j * x.shape[1], k * x.shape[2]], [x.shape[0], x.shape[1], x.shape[2]])); + } + } + } + } + else if (x.rank === 4) { + for (var i = 0; i < reps[0]; ++i) { + for (var j = 0; j < reps[1]; ++j) { + for (var k = 0; k < reps[2]; ++k) { + for (var l = 0; l < reps[3]; ++l) { + xGrad = + add(xGrad, slice(dy, [ + i * x.shape[0], j * x.shape[1], k * x.shape[2], + l * x.shape[3] + ], [x.shape[0], x.shape[1], x.shape[2], x.shape[3]])); + } + } + } + } + } + else { + throw new Error("Gradient for tile operation is not implemented for rank-" + + (x.rank + " tensors yet.")); + } + return xGrad; + }; + return { x: derX }; + }, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var transposeGradConfig = { + kernelName: Transpose, + gradFunc: function (dy, saved, attrs) { + var transposeAttrs = attrs; + var perm = transposeAttrs.perm; + var undoPerm = getUndoAxesPermutation(perm); + return { x: function () { return transpose(dy, undoPerm); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns a `tf.Tensor` that has expanded rank, by inserting a dimension + * into the tensor's shape. + * + * ```js + * const x = tf.tensor1d([1, 2, 3, 4]); + * const axis = 1; + * x.expandDims(axis).print(); + * ``` + * + * @param x The input tensor whose dimensions to be expanded. + * @param axis The dimension index at which to insert shape of `1`. Defaults + * to 0 (the first dimension). + */ + /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ + function expandDims_(x, axis) { + if (axis === void 0) { axis = 0; } + var parseAs = null; + var $x = convertToTensor(x, 'x', 'expandDims', parseAs); + assert(axis <= $x.rank, function () { return 'Axis must be <= rank of the tensor'; }); + var newShape = $x.shape.slice(); + if (axis < 0) { + // Negative value is counted from the tail of rank. + assert(-($x.rank + 1) <= axis, function () { return "Axis must be in the interval [" + -($x.rank + 1) + ", " + $x.rank + "]"; }); + axis = $x.rank + axis + 1; + } + newShape.splice(axis, 0, 1); + return reshape($x, newShape); + } + var expandDims = op({ expandDims_: expandDims_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Stacks a list of rank-`R` `tf.Tensor`s into one rank-`(R+1)` `tf.Tensor`. + * + * ```js + * const a = tf.tensor1d([1, 2]); + * const b = tf.tensor1d([3, 4]); + * const c = tf.tensor1d([5, 6]); + * tf.stack([a, b, c]).print(); + * ``` + * + * @param tensors A list of tensor objects with the same shape and dtype. + * @param axis The axis to stack along. Defaults to 0 (the first dim). + */ + /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ + function stack_(tensors, axis) { + if (axis === void 0) { axis = 0; } + var $tensors = convertToTensorArray(tensors, 'tensors', 'stack'); + assert($tensors.length >= 1, function () { return 'Pass at least one tensor to tf.stack'; }); + if ($tensors.length === 1) { + return expandDims($tensors[0], axis); + } + var rank = $tensors[0].rank; + var shape = $tensors[0].shape; + var dtype = $tensors[0].dtype; + assert(axis <= rank, function () { return 'Axis must be <= rank of the tensor'; }); + $tensors.forEach(function (t) { + assertShapesMatch(shape, t.shape, 'All tensors passed to stack must have matching shapes'); + assert(dtype === t.dtype, function () { return 'All tensors passed to stack must have matching dtypes'; }); + }); + var expandedTensors = $tensors.map(function (t) { return expandDims(t, axis); }); + // Stack exists in the TensorFlow C++ API + // (https://www.tensorflow.org/api_docs/cc/class/tensorflow/ops/stack) but not + // in + // https://raw.githubusercontent.com/tensorflow/tensorflow/master/tensorflow/core/ops/ops.pbtxt. + // Therefore we are treating it like a high-level op rather than + // creating a dedicated stack kernel. + return concat(expandedTensors, axis); + } + var stack = op({ stack_: stack_ }); + + /** + * @license + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var unpackGradConfig = { + kernelName: Unpack, + gradFunc: function (dy, saved, attrs) { + var unpackAttrs = attrs; + var axis = unpackAttrs.axis; + return { value: function () { return stack(dy, axis); } }; + } + }; + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var PARALLELIZE_THRESHOLD = 30; + function computeOptimalWindowSize(inSize) { + if (inSize <= PARALLELIZE_THRESHOLD) { + return inSize; + } + return nearestDivisor(inSize, Math.floor(Math.sqrt(inSize))); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function segOpComputeOptimalWindowSize(inSize, numSegments) { + var done = false; + var res; + if (inSize <= PARALLELIZE_THRESHOLD) { + res = inSize; + done = true; + } + else { + res = nearestDivisor(inSize, Math.floor(Math.sqrt(inSize))); + } + while (!done) { + if (res > numSegments || res === inSize) { + done = true; + } + else { + res = nearestDivisor(inSize, res + 1); + } + } + return res; + } + function computeOutShape$2(aShape, axis, numSegments) { + var outShape = []; + var rank = aShape.length; + for (var dim = 0; dim < rank; dim++) { + if (dim !== axis) { + outShape.push(aShape[dim]); + } + else { + outShape.push(numSegments); + } + } + return outShape; + } + function collectGatherOpShapeInfo(x, indices, axis) { + var dimSize = x.shape[axis]; + var outputShape = []; + var batchSize = 1; + var sliceSize = 1; + for (var i = 0; i < axis; i++) { + outputShape.push(x.shape[i]); + batchSize *= x.shape[i]; + } + for (var i = 0; i < indices.rank; i++) { + outputShape.push(indices.shape[i]); + } + for (var i = axis + 1; i < x.rank; i++) { + outputShape.push(x.shape[i]); + sliceSize *= x.shape[i]; + } + return { batchSize: batchSize, sliceSize: sliceSize, dimSize: dimSize, outputShape: outputShape }; + } + + var segment_util = { + __proto__: null, + segOpComputeOptimalWindowSize: segOpComputeOptimalWindowSize, + computeOutShape: computeOutShape$2, + collectGatherOpShapeInfo: collectGatherOpShapeInfo + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Gather slices from tensor `x`'s axis `axis` according to `indices`. + * + * ```js + * const x = tf.tensor1d([1, 2, 3, 4]); + * const indices = tf.tensor1d([1, 3, 3], 'int32'); + * + * x.gather(indices).print(); + * ``` + * + * ```js + * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); + * const indices = tf.tensor1d([1, 1, 0], 'int32'); + * + * x.gather(indices).print(); + * ``` + * @param x The input tensor whose slices to be gathered. + * @param indices The indices of the values to extract. + * @param axis The axis over which to select values. Defaults to 0. + */ + /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ + function gather_(x, indices, axis) { + if (axis === void 0) { axis = 0; } + var $x = convertToTensor(x, 'x', 'gather'); + var $indices = convertToTensor(indices, 'indices', 'gather', 'int32'); + var inputs = { x: $x, indices: $indices }; + var attrs = { axis: axis }; + var forward = function (backend, save) { + var parsedAxis = parseAxisParam(axis, $x.shape)[0]; + var shapeInfo = collectGatherOpShapeInfo($x, $indices, parsedAxis); + var res = backend.gather($x, $indices.flatten(), parsedAxis); + save([$x, $indices]); + return res.reshape(shapeInfo.outputShape); + }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, GatherV2, attrs); + } + var gather = op({ gather_: gather_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the max of a and b (`a > b ? a : b`) element-wise. + * Supports broadcasting. + * + * We also expose `tf.maximumStrict` which has the same signature as this op and + * asserts that `a` and `b` are the same shape (does not broadcast). + * + * ```js + * const a = tf.tensor1d([1, 4, 3, 16]); + * const b = tf.tensor1d([1, 2, 9, 4]); + * + * a.maximum(b).print(); // or tf.maximum(a, b) + * ``` + * + * ```js + * // Broadcast maximum a with b. + * const a = tf.tensor1d([2, 4, 6, 8]); + * const b = tf.scalar(5); + * + * a.maximum(b).print(); // or tf.maximum(a, b) + * ``` + * + * @param a The first tensor. + * @param b The second tensor. Must have the same type as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ + function maximum_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'maximum'); + var $b = convertToTensor(b, 'b', 'maximum'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + if ($a.dtype === 'bool') { + $a = cast($a, 'int32'); + $b = cast($b, 'int32'); + } + assertAndGetBroadcastShape($a.shape, $b.shape); + var forward = function (backend, save) { + var res = backend.maximum($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Maximum); + } + var maximum = op({ maximum_: maximum_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var unsortedSegmentSumGradConfig = { + kernelName: UnsortedSegmentSum, + inputsToSave: ['segmentIds'], + gradFunc: function (dy, saved) { + var segmentIds = saved[0]; + var derX = function () { + return gatherDropNegatives(dy, segmentIds); + }; + return { x: derX }; + } + }; + function gatherDropNegatives(x, indices) { + // Helper function for unsorted segment ops. Gathers params for + // positive segment ids and gathers 0 for inputs with negative segment id. + // Mirrors _GatherDropNegatives from tensorflow/python/ops/math_grad.py + var zeroClippedIndices = maximum(indices, zerosLike(indices)); + var gathered = gather(x, zeroClippedIndices); + var isPositive = greaterEqual(indices, scalar(0, 'int32')); + var numIters = gathered.rank - isPositive.rank; + for (var i = 0; i < numIters; ++i) { + isPositive = expandDims(isPositive, i + 1); + } + isPositive = logicalAnd(isPositive, ones$1(gathered.shape, 'bool')); + var zeroSlice = zerosLike(gathered); + return where(isPositive, gathered, zeroSlice); + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var zerosLikeGradConfig = { + kernelName: ZerosLike, + gradFunc: function (dy) { + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // Export all kernel configs here so that the package can auto register them + var gradConfigs = [ + absGradConfig, + acosGradConfig, + acoshGradConfig, + addGradConfig, + addNGradConfig, + argMaxGradConfig, + argMinGradConfig, + asinGradConfig, + asinhGradConfig, + atan2GradConfig, + atanGradConfig, + atanhGradConfig, + avgPool3DGradConfig, + avgPoolGradConfig, + batchMatMulGradConfig, + batchToSpaceNDGradConfig, + broadcastToGradConfig, + castGradConfig, + ceilGradConfig, + clipByValueGradConfig, + concatGradConfig, + conv2DBackpropInputGradConfig, + conv2DGradConfig, + conv3DGradConfig, + cosGradConfig, + coshGradConfig, + cumsumGradConfig, + depthwiseConv2dNativeGradConfig, + dilation2dGradConfig, + divGradConfig, + eluGradConfig, + erfGradConfig, + expGradConfig, + expm1GradConfig, + floorDivGradConfig, + floorGradConfig, + fusedBatchNormGradConfig, + gatherGradConfig, + greaterEqualGradConfig, + identityGradConfig, + isFiniteGradConfig, + isInfGradConfig, + isNanGradConfig, + log1pGradConfig, + logGradConfig, + logSoftmaxGradConfig, + lrnGradConfig, + maxGradConfig, + maxGradConfig, + maximumGradConfig, + maxPool3DGradConfig, + maxPoolGradConfig, + minGradConfig, + minimumGradConfig, + modGradConfig, + multiplyGradConfig, + negateGradConfig, + oneHotGradConfig, + onesLikeGradConfig, + padV2GradConfig, + padV2GradConfig, + powGradConfig, + preluGradConfig, + reciprocalGradConfig, + relu6GradConfig, + reluGradConfig, + reshapeGradConfig, + resizeBilinearGradConfig, + resizeNearestNeighborGradConfig, + reverseGradConfig, + roundGradConfig, + rsqrtGradConfig, + selectV2PoolGradConfig, + seluGradConfig, + sigmoidGradConfig, + signGradConfig, + sinGradConfig, + sinhGradConfig, + sliceGradConfig, + softmaxGradConfig, + softplusGradConfig, + spaceToBatchNDGradConfig, + spaceToBatchNDGradConfig, + splitVGradConfig, + splitVGradConfig, + sqrtGradConfig, + squaredDifferenceGradConfig, + squareGradConfig, + stepGradConfig, + subGradConfig, + sumGradConfig, + tanGradConfig, + tanhGradConfig, + tileGradConfig, + transposeGradConfig, + unpackGradConfig, + unsortedSegmentSumGradConfig, + zerosLikeGradConfig + ]; + for (var _i = 0, gradConfigs_1 = gradConfigs; _i < gradConfigs_1.length; _i++) { + var gradientConfig = gradConfigs_1[_i]; + registerGradient(gradientConfig); + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var PlatformBrowser = /** @class */ (function () { + function PlatformBrowser() { + } + PlatformBrowser.prototype.fetch = function (path, init) { + return fetch(path, init); + }; + PlatformBrowser.prototype.now = function () { + return performance.now(); + }; + PlatformBrowser.prototype.encode = function (text, encoding) { + if (encoding !== 'utf-8' && encoding !== 'utf8') { + throw new Error("Browser's encoder only supports utf-8, but got " + encoding); + } + if (this.textEncoder == null) { + this.textEncoder = new TextEncoder(); + } + return this.textEncoder.encode(text); + }; + PlatformBrowser.prototype.decode = function (bytes, encoding) { + return new TextDecoder(encoding).decode(bytes); + }; + return PlatformBrowser; + }()); + if (env().get('IS_BROWSER')) { + env().setPlatform('browser', new PlatformBrowser()); + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // We are wrapping this within an object so it can be stubbed by Jasmine. + var getNodeFetch = { + // tslint:disable-next-line:no-require-imports + importFetch: function () { return require('node-fetch'); } + }; + var systemFetch; + var PlatformNode = /** @class */ (function () { + function PlatformNode() { + // tslint:disable-next-line:no-require-imports + this.util = require('util'); + // According to the spec, the built-in encoder can do only UTF-8 encoding. + // https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder/TextEncoder + this.textEncoder = new this.util.TextEncoder(); + } + PlatformNode.prototype.fetch = function (path, requestInits) { + if (env().global.fetch != null) { + return env().global.fetch(path, requestInits); + } + if (systemFetch == null) { + systemFetch = getNodeFetch.importFetch(); + } + return systemFetch(path, requestInits); + }; + PlatformNode.prototype.now = function () { + var time = process.hrtime(); + return time[0] * 1000 + time[1] / 1000000; + }; + PlatformNode.prototype.encode = function (text, encoding) { + if (encoding !== 'utf-8' && encoding !== 'utf8') { + throw new Error("Node built-in encoder only supports utf-8, but got " + encoding); + } + return this.textEncoder.encode(text); + }; + PlatformNode.prototype.decode = function (bytes, encoding) { + if (bytes.length === 0) { + return ''; + } + return new this.util.TextDecoder(encoding).decode(bytes); + }; + return PlatformNode; + }()); + if (env().get('IS_NODE')) { + env().setPlatform('node', new PlatformNode()); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /* Type definitions for exporting and importing of models. */ + /** + * A map from Tensor dtype to number of bytes per element of the Tensor. + */ + var DTYPE_VALUE_SIZE_MAP = { + 'float32': 4, + 'float16': 2, + 'int32': 4, + 'uint16': 2, + 'uint8': 1, + 'bool': 1, + 'complex64': 8 + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** Number of bytes reserved for the length of the string. (32bit integer). */ + var NUM_BYTES_STRING_LENGTH = 4; + /** + * Encode a map from names to weight values as an ArrayBuffer, along with an + * `Array` of `WeightsManifestEntry` as specification of the encoded weights. + * + * This function does not perform sharding. + * + * This function is the reverse of `decodeWeights`. + * + * @param tensors A map ("dict") from names to tensors. + * @param group Group to which the weights belong (optional). + * @returns A `Promise` of + * - A flat `ArrayBuffer` with all the binary values of the `Tensor`s + * concatenated. + * - An `Array` of `WeightManifestEntry`s, carrying information including + * tensor names, `dtype`s and shapes. + * @throws Error: on unsupported tensor `dtype`. + */ + function encodeWeights(tensors, group) { + return __awaiter(this, void 0, void 0, function () { + var specs, dataPromises, names, _loop_1, i, tensorValues; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + specs = []; + dataPromises = []; + names = Array.isArray(tensors) ? + tensors.map(function (tensor) { return tensor.name; }) : + Object.keys(tensors); + _loop_1 = function (i) { + var name_1 = names[i]; + var t = Array.isArray(tensors) ? tensors[i].tensor : tensors[name_1]; + if (t.dtype !== 'float32' && t.dtype !== 'int32' && t.dtype !== 'bool' && + t.dtype !== 'string' && t.dtype !== 'complex64') { + throw new Error("Unsupported dtype in weight '" + name_1 + "': " + t.dtype); + } + var spec = { name: name_1, shape: t.shape, dtype: t.dtype }; + if (t.dtype === 'string') { + var utf8bytes = new Promise(function (resolve) { return __awaiter(_this, void 0, void 0, function () { + var vals, totalNumBytes, bytes, offset, i_1, val, bytesOfLength; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, t.bytes()]; + case 1: + vals = _a.sent(); + totalNumBytes = vals.reduce(function (p, c) { return p + c.length; }, 0) + + NUM_BYTES_STRING_LENGTH * vals.length; + bytes = new Uint8Array(totalNumBytes); + offset = 0; + for (i_1 = 0; i_1 < vals.length; i_1++) { + val = vals[i_1]; + bytesOfLength = new Uint8Array(new Uint32Array([val.length]).buffer); + bytes.set(bytesOfLength, offset); + offset += NUM_BYTES_STRING_LENGTH; + bytes.set(val, offset); + offset += val.length; + } + resolve(bytes); + return [2 /*return*/]; + } + }); + }); }); + dataPromises.push(utf8bytes); + } + else { + dataPromises.push(t.data()); + } + if (group != null) { + spec.group = group; + } + specs.push(spec); + }; + for (i = 0; i < names.length; ++i) { + _loop_1(i); + } + return [4 /*yield*/, Promise.all(dataPromises)]; + case 1: + tensorValues = _a.sent(); + return [2 /*return*/, { data: concatenateTypedArrays(tensorValues), specs: specs }]; + } + }); + }); + } + /** + * Decode flat ArrayBuffer as weights. + * + * This function does not handle sharding. + * + * This function is the reverse of `encodeWeights`. + * + * @param buffer A flat ArrayBuffer carrying the binary values of the tensors + * concatenated in the order specified in `specs`. + * @param specs Specifications of the names, dtypes and shapes of the tensors + * whose value are encoded by `buffer`. + * @return A map from tensor name to tensor value, with the names corresponding + * to names in `specs`. + * @throws Error, if any of the tensors has unsupported dtype. + */ + function decodeWeights(buffer, specs) { + // TODO(adarob, cais): Support quantization. + var out = {}; + var float16Decode; + var offset = 0; + for (var _i = 0, specs_1 = specs; _i < specs_1.length; _i++) { + var spec = specs_1[_i]; + var name_2 = spec.name; + var dtype = spec.dtype; + var shape = spec.shape; + var size = sizeFromShape(shape); + var values = void 0; + if ('quantization' in spec) { + var quantization = spec.quantization; + if (quantization.dtype === 'uint8' || quantization.dtype === 'uint16') { + if (!('min' in quantization && 'scale' in quantization)) { + throw new Error("Weight " + spec.name + " with quantization " + quantization.dtype + " " + + "doesn't have corresponding metadata min and scale."); + } + } + else if (quantization.dtype === 'float16') { + if (dtype !== 'float32') { + throw new Error("Weight " + spec.name + " is quantized with " + quantization.dtype + " " + + ("which only supports weights of type float32 not " + dtype + ".")); + } + } + else { + throw new Error("Weight " + spec.name + " has unknown " + + ("quantization dtype " + quantization.dtype + ". ") + + "Supported quantization dtypes are: " + + "'uint8', 'uint16', and 'float16'."); + } + var quantizationSizeFactor = DTYPE_VALUE_SIZE_MAP[quantization.dtype]; + var byteBuffer = buffer.slice(offset, offset + size * quantizationSizeFactor); + var quantizedArray = (quantization.dtype === 'uint8') ? + new Uint8Array(byteBuffer) : + new Uint16Array(byteBuffer); + if (dtype === 'float32') { + if (quantization.dtype === 'uint8' || quantization.dtype === 'uint16') { + values = new Float32Array(quantizedArray.length); + for (var i = 0; i < quantizedArray.length; i++) { + var v = quantizedArray[i]; + values[i] = v * quantization.scale + quantization.min; + } + } + else if (quantization.dtype === 'float16') { + if (float16Decode === undefined) { + float16Decode = getFloat16Decoder(); + } + values = float16Decode(quantizedArray); + } + else { + throw new Error("Unsupported quantization type " + quantization.dtype + " " + + "for weight type float32."); + } + } + else if (dtype === 'int32') { + if (quantization.dtype !== 'uint8' && quantization.dtype !== 'uint16') { + throw new Error("Unsupported quantization type " + quantization.dtype + " " + + "for weight type int32."); + } + values = new Int32Array(quantizedArray.length); + for (var i = 0; i < quantizedArray.length; i++) { + var v = quantizedArray[i]; + values[i] = Math.round(v * quantization.scale + quantization.min); + } + } + else { + throw new Error("Unsupported dtype in weight '" + name_2 + "': " + dtype); + } + offset += size * quantizationSizeFactor; + } + else if (dtype === 'string') { + var size_1 = sizeFromShape(spec.shape); + values = []; + for (var i = 0; i < size_1; i++) { + var byteLength = new Uint32Array(buffer.slice(offset, offset + NUM_BYTES_STRING_LENGTH))[0]; + offset += NUM_BYTES_STRING_LENGTH; + var bytes = new Uint8Array(buffer.slice(offset, offset + byteLength)); + values.push(bytes); + offset += byteLength; + } + } + else { + var dtypeFactor = DTYPE_VALUE_SIZE_MAP[dtype]; + var byteBuffer = buffer.slice(offset, offset + size * dtypeFactor); + if (dtype === 'float32') { + values = new Float32Array(byteBuffer); + } + else if (dtype === 'int32') { + values = new Int32Array(byteBuffer); + } + else if (dtype === 'bool') { + values = new Uint8Array(byteBuffer); + } + else if (dtype === 'complex64') { + values = new Float32Array(byteBuffer); + var real = new Float32Array(values.length / 2); + var image = new Float32Array(values.length / 2); + for (var i = 0; i < real.length; i++) { + real[i] = values[i * 2]; + image[i] = values[i * 2 + 1]; + } + var realTensor = tensor(real, shape, 'float32'); + var imageTensor = tensor(image, shape, 'float32'); + out[name_2] = complex(realTensor, imageTensor); + } + else { + throw new Error("Unsupported dtype in weight '" + name_2 + "': " + dtype); + } + offset += size * dtypeFactor; + } + if (dtype !== 'complex64') { + out[name_2] = tensor(values, shape, dtype); + } + } + return out; + } + /** + * Concatenate TypedArrays into an ArrayBuffer. + */ + function concatenateTypedArrays(xs) { + // TODO(adarob, cais): Support quantization. + if (xs === null) { + throw new Error("Invalid input value: " + JSON.stringify(xs)); + } + var totalByteLength = 0; + // `normalizedXs` is here for this reason: a `TypedArray`'s `buffer' + // can have a different byte length from that of the `TypedArray` itself, + // for example, when the `TypedArray` is created from an offset in an + // `ArrayBuffer`. `normliazedXs` holds `TypedArray`s whose `buffer`s match + // the `TypedArray` in byte length. If an element of `xs` does not show + // this property, a new `TypedArray` that satisfy this property will be + // constructed and pushed into `normalizedXs`. + var normalizedXs = []; + xs.forEach(function (x) { + totalByteLength += x.byteLength; + // tslint:disable:no-any + normalizedXs.push(x.byteLength === x.buffer.byteLength ? x : + new x.constructor(x)); + if (!(x instanceof Float32Array || x instanceof Int32Array || + x instanceof Uint8Array)) { + throw new Error("Unsupported TypedArray subtype: " + x.constructor.name); + } + // tslint:enable:no-any + }); + var y = new Uint8Array(totalByteLength); + var offset = 0; + normalizedXs.forEach(function (x) { + y.set(new Uint8Array(x.buffer), offset); + offset += x.byteLength; + }); + return y.buffer; + } + // Use Buffer on Node.js instead of Blob/atob/btoa + var useNodeBuffer = typeof Buffer !== 'undefined' && + (typeof Blob === 'undefined' || typeof atob === 'undefined' || + typeof btoa === 'undefined'); + /** + * Calculate the byte length of a JavaScript string. + * + * Note that a JavaScript string can contain wide characters, therefore the + * length of the string is not necessarily equal to the byte length. + * + * @param str Input string. + * @returns Byte length. + */ + function stringByteLength(str) { + if (useNodeBuffer) { + return Buffer.byteLength(str); + } + return new Blob([str]).size; + } + /** + * Encode an ArrayBuffer as a base64 encoded string. + * + * @param buffer `ArrayBuffer` to be converted. + * @returns A string that base64-encodes `buffer`. + */ + function arrayBufferToBase64String(buffer) { + if (useNodeBuffer) { + return Buffer.from(buffer).toString('base64'); + } + var buf = new Uint8Array(buffer); + var s = ''; + for (var i = 0, l = buf.length; i < l; i++) { + s += String.fromCharCode(buf[i]); + } + return btoa(s); + } + /** + * Decode a base64 string as an ArrayBuffer. + * + * @param str Base64 string. + * @returns Decoded `ArrayBuffer`. + */ + function base64StringToArrayBuffer(str) { + if (useNodeBuffer) { + var buf = Buffer.from(str, 'base64'); + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + } + var s = atob(str); + var buffer = new Uint8Array(s.length); + for (var i = 0; i < s.length; ++i) { + buffer.set([s.charCodeAt(i)], i); + } + return buffer.buffer; + } + /** + * Concatenate a number of ArrayBuffers into one. + * + * @param buffers A number of array buffers to concatenate. + * @returns Result of concatenating `buffers` in order. + */ + function concatenateArrayBuffers(buffers) { + if (buffers.length === 1) { + return buffers[0]; + } + var totalByteLength = 0; + buffers.forEach(function (buffer) { + totalByteLength += buffer.byteLength; + }); + var temp = new Uint8Array(totalByteLength); + var offset = 0; + buffers.forEach(function (buffer) { + temp.set(new Uint8Array(buffer), offset); + offset += buffer.byteLength; + }); + return temp.buffer; + } + /** + * Get the basename of a path. + * + * Behaves in a way analogous to Linux's basename command. + * + * @param path + */ + function basename(path) { + var SEPARATOR = '/'; + path = path.trim(); + while (path.endsWith(SEPARATOR)) { + path = path.slice(0, path.length - 1); + } + var items = path.split(SEPARATOR); + return items[items.length - 1]; + } + /** + * Populate ModelArtifactsInfo fields for a model with JSON topology. + * @param modelArtifacts + * @returns A ModelArtifactsInfo object. + */ + function getModelArtifactsInfoForJSON(modelArtifacts) { + if (modelArtifacts.modelTopology instanceof ArrayBuffer) { + throw new Error('Expected JSON model topology, received ArrayBuffer.'); + } + return { + dateSaved: new Date(), + modelTopologyType: 'JSON', + modelTopologyBytes: modelArtifacts.modelTopology == null ? + 0 : + stringByteLength(JSON.stringify(modelArtifacts.modelTopology)), + weightSpecsBytes: modelArtifacts.weightSpecs == null ? + 0 : + stringByteLength(JSON.stringify(modelArtifacts.weightSpecs)), + weightDataBytes: modelArtifacts.weightData == null ? + 0 : + modelArtifacts.weightData.byteLength, + }; + } + /** + * Computes mantisa table for casting Float16 to Float32 + * See http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf + * + * @returns Uint32Array, 2048 mantissa lookup values. + */ + function computeFloat16MantisaTable() { + var convertMantissa = function (i) { + var m = i << 13; + var e = 0; + while ((m & 0x00800000) === 0) { + e -= 0x00800000; + m <<= 1; + } + m &= ~0x00800000; + e += 0x38800000; + return m | e; + }; + var mantisaTable = new Uint32Array(2048); + mantisaTable[0] = 0; + for (var i = 1; i < 1024; i++) { + mantisaTable[i] = convertMantissa(i); + } + for (var i = 1024; i < 2048; i++) { + mantisaTable[i] = 0x38000000 + ((i - 1024) << 13); + } + return mantisaTable; + } + /** + * Computes exponent table for casting Float16 to Float32 + * See http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf + * + * @returns Uint32Array, 64 exponent lookup values. + */ + function computeFloat16ExponentTable() { + var exponentTable = new Uint32Array(64); + exponentTable[0] = 0; + exponentTable[31] = 0x47800000; + exponentTable[32] = 0x80000000; + exponentTable[63] = 0xc7800000; + for (var i = 1; i < 31; i++) { + exponentTable[i] = i << 23; + } + for (var i = 33; i < 63; i++) { + exponentTable[i] = 0x80000000 + ((i - 32) << 23); + } + return exponentTable; + } + /** + * Computes offset table for casting Float16 to Float32 + * See http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf + * + * @returns Uint32Array, 6d offset values. + */ + function computeFloat16OffsetTable() { + var offsetTable = new Uint32Array(64); + for (var i = 0; i < 64; i++) { + offsetTable[i] = 1024; + } + offsetTable[0] = offsetTable[32] = 0; + return offsetTable; + } + /** + * Retrieve a Float16 decoder which will decode a ByteArray of Float16 values + * to a Float32Array. + * + * @returns Function (buffer: Uint16Array) => Float32Array which decodes + * the Uint16Array of Float16 bytes to a Float32Array. + */ + function getFloat16Decoder() { + // Algorithm is based off of + // http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf + // Cache lookup tables + var mantisaTable = computeFloat16MantisaTable(); + var exponentTable = computeFloat16ExponentTable(); + var offsetTable = computeFloat16OffsetTable(); + return function (quantizedArray) { + var buffer = new ArrayBuffer(4 * quantizedArray.length); + var bufferUint32View = new Uint32Array(buffer); + for (var index = 0; index < quantizedArray.length; index++) { + var float16Bits = quantizedArray[index]; + var float32Bits = mantisaTable[offsetTable[float16Bits >> 10] + (float16Bits & 0x3ff)] + + exponentTable[float16Bits >> 10]; + bufferUint32View[index] = float32Bits; + } + return new Float32Array(buffer); + }; + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var IORouterRegistry = /** @class */ (function () { + function IORouterRegistry() { + this.saveRouters = []; + this.loadRouters = []; + } + IORouterRegistry.getInstance = function () { + if (IORouterRegistry.instance == null) { + IORouterRegistry.instance = new IORouterRegistry(); + } + return IORouterRegistry.instance; + }; + /** + * Register a save-handler router. + * + * @param saveRouter A function that maps a URL-like string onto an instance + * of `IOHandler` with the `save` method defined or `null`. + */ + IORouterRegistry.registerSaveRouter = function (saveRouter) { + IORouterRegistry.getInstance().saveRouters.push(saveRouter); + }; + /** + * Register a load-handler router. + * + * @param loadRouter A function that maps a URL-like string onto an instance + * of `IOHandler` with the `load` method defined or `null`. + */ + IORouterRegistry.registerLoadRouter = function (loadRouter) { + IORouterRegistry.getInstance().loadRouters.push(loadRouter); + }; + /** + * Look up IOHandler for saving, given a URL-like string. + * + * @param url + * @returns If only one match is found, an instance of IOHandler with the + * `save` method defined. If no match is found, `null`. + * @throws Error, if more than one match is found. + */ + IORouterRegistry.getSaveHandlers = function (url) { + return IORouterRegistry.getHandlers(url, 'save'); + }; + /** + * Look up IOHandler for loading, given a URL-like string. + * + * @param url + * @param loadOptions Optional, custom load options. + * @returns All valid handlers for `url`, given the currently registered + * handler routers. + */ + IORouterRegistry.getLoadHandlers = function (url, loadOptions) { + return IORouterRegistry.getHandlers(url, 'load', loadOptions); + }; + IORouterRegistry.getHandlers = function (url, handlerType, loadOptions) { + var validHandlers = []; + var routers = handlerType === 'load' ? + IORouterRegistry.getInstance().loadRouters : + IORouterRegistry.getInstance().saveRouters; + routers.forEach(function (router) { + var handler = router(url, loadOptions); + if (handler !== null) { + validHandlers.push(handler); + } + }); + return validHandlers; + }; + return IORouterRegistry; + }()); + var registerSaveRouter = function (loudRouter) { + return IORouterRegistry.registerSaveRouter(loudRouter); + }; + var registerLoadRouter = function (loudRouter) { + return IORouterRegistry.registerLoadRouter(loudRouter); + }; + var getSaveHandlers = function (url) { + return IORouterRegistry.getSaveHandlers(url); + }; + var getLoadHandlers = function (url, loadOptions) { + return IORouterRegistry.getLoadHandlers(url, loadOptions); + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var URL_SCHEME_SUFFIX = '://'; + var ModelStoreManagerRegistry = /** @class */ (function () { + function ModelStoreManagerRegistry() { + this.managers = {}; + } + ModelStoreManagerRegistry.getInstance = function () { + if (ModelStoreManagerRegistry.instance == null) { + ModelStoreManagerRegistry.instance = new ModelStoreManagerRegistry(); + } + return ModelStoreManagerRegistry.instance; + }; + /** + * Register a save-handler router. + * + * @param saveRouter A function that maps a URL-like string onto an instance + * of `IOHandler` with the `save` method defined or `null`. + */ + ModelStoreManagerRegistry.registerManager = function (scheme, manager) { + assert(scheme != null, function () { return 'scheme must not be undefined or null.'; }); + if (scheme.endsWith(URL_SCHEME_SUFFIX)) { + scheme = scheme.slice(0, scheme.indexOf(URL_SCHEME_SUFFIX)); + } + assert(scheme.length > 0, function () { return 'scheme must not be an empty string.'; }); + var registry = ModelStoreManagerRegistry.getInstance(); + assert(registry.managers[scheme] == null, function () { return "A model store manager is already registered for scheme '" + scheme + "'."; }); + registry.managers[scheme] = manager; + }; + ModelStoreManagerRegistry.getManager = function (scheme) { + var manager = this.getInstance().managers[scheme]; + if (manager == null) { + throw new Error("Cannot find model manager for scheme '" + scheme + "'"); + } + return manager; + }; + ModelStoreManagerRegistry.getSchemes = function () { + return Object.keys(this.getInstance().managers); + }; + return ModelStoreManagerRegistry; + }()); + /** + * Helper method for parsing a URL string into a scheme and a path. + * + * @param url E.g., 'localstorage://my-model' + * @returns A dictionary with two fields: scheme and path. + * Scheme: e.g., 'localstorage' in the example above. + * Path: e.g., 'my-model' in the example above. + */ + function parseURL(url) { + if (url.indexOf(URL_SCHEME_SUFFIX) === -1) { + throw new Error("The url string provided does not contain a scheme. " + + "Supported schemes are: " + + ("" + ModelStoreManagerRegistry.getSchemes().join(','))); + } + return { + scheme: url.split(URL_SCHEME_SUFFIX)[0], + path: url.split(URL_SCHEME_SUFFIX)[1], + }; + } + function cloneModelInternal(sourceURL, destURL, deleteSource) { + if (deleteSource === void 0) { deleteSource = false; } + return __awaiter(this, void 0, void 0, function () { + var loadHandlers, loadHandler, saveHandlers, saveHandler, sourceScheme, sourcePath, sameMedium, modelArtifacts, saveResult; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + assert(sourceURL !== destURL, function () { return "Old path and new path are the same: '" + sourceURL + "'"; }); + loadHandlers = IORouterRegistry.getLoadHandlers(sourceURL); + assert(loadHandlers.length > 0, function () { return "Copying failed because no load handler is found for source URL " + sourceURL + "."; }); + assert(loadHandlers.length < 2, function () { return "Copying failed because more than one (" + loadHandlers.length + ") " + + ("load handlers for source URL " + sourceURL + "."); }); + loadHandler = loadHandlers[0]; + saveHandlers = IORouterRegistry.getSaveHandlers(destURL); + assert(saveHandlers.length > 0, function () { return "Copying failed because no save handler is found for destination " + + ("URL " + destURL + "."); }); + assert(saveHandlers.length < 2, function () { return "Copying failed because more than one (" + loadHandlers.length + ") " + + ("save handlers for destination URL " + destURL + "."); }); + saveHandler = saveHandlers[0]; + sourceScheme = parseURL(sourceURL).scheme; + sourcePath = parseURL(sourceURL).path; + sameMedium = sourceScheme === parseURL(sourceURL).scheme; + return [4 /*yield*/, loadHandler.load()]; + case 1: + modelArtifacts = _a.sent(); + if (!(deleteSource && sameMedium)) return [3 /*break*/, 3]; + return [4 /*yield*/, ModelStoreManagerRegistry.getManager(sourceScheme) + .removeModel(sourcePath)]; + case 2: + _a.sent(); + _a.label = 3; + case 3: return [4 /*yield*/, saveHandler.save(modelArtifacts)]; + case 4: + saveResult = _a.sent(); + if (!(deleteSource && !sameMedium)) return [3 /*break*/, 6]; + return [4 /*yield*/, ModelStoreManagerRegistry.getManager(sourceScheme) + .removeModel(sourcePath)]; + case 5: + _a.sent(); + _a.label = 6; + case 6: return [2 /*return*/, saveResult.modelArtifactsInfo]; + } + }); + }); + } + /** + * List all models stored in registered storage mediums. + * + * For a web browser environment, the registered mediums are Local Storage and + * IndexedDB. + * + * ```js + * // First create and save a model. + * const model = tf.sequential(); + * model.add(tf.layers.dense( + * {units: 1, inputShape: [10], activation: 'sigmoid'})); + * await model.save('localstorage://demo/management/model1'); + * + * // Then list existing models. + * console.log(JSON.stringify(await tf.io.listModels())); + * + * // Delete the model. + * await tf.io.removeModel('localstorage://demo/management/model1'); + * + * // List models again. + * console.log(JSON.stringify(await tf.io.listModels())); + * ``` + * + * @returns A `Promise` of a dictionary mapping URLs of existing models to + * their model artifacts info. URLs include medium-specific schemes, e.g., + * 'indexeddb://my/model/1'. Model artifacts info include type of the + * model's topology, byte sizes of the topology, weights, etc. + */ + /** + * @doc { + * heading: 'Models', + * subheading: 'Management', + * namespace: 'io', + * ignoreCI: true + * } + */ + function listModels() { + return __awaiter(this, void 0, void 0, function () { + var schemes, out, _i, schemes_1, scheme, schemeOut, path, url; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + schemes = ModelStoreManagerRegistry.getSchemes(); + out = {}; + _i = 0, schemes_1 = schemes; + _a.label = 1; + case 1: + if (!(_i < schemes_1.length)) return [3 /*break*/, 4]; + scheme = schemes_1[_i]; + return [4 /*yield*/, ModelStoreManagerRegistry.getManager(scheme).listModels()]; + case 2: + schemeOut = _a.sent(); + for (path in schemeOut) { + url = scheme + URL_SCHEME_SUFFIX + path; + out[url] = schemeOut[path]; + } + _a.label = 3; + case 3: + _i++; + return [3 /*break*/, 1]; + case 4: return [2 /*return*/, out]; + } + }); + }); + } + /** + * Remove a model specified by URL from a reigstered storage medium. + * + * ```js + * // First create and save a model. + * const model = tf.sequential(); + * model.add(tf.layers.dense( + * {units: 1, inputShape: [10], activation: 'sigmoid'})); + * await model.save('localstorage://demo/management/model1'); + * + * // Then list existing models. + * console.log(JSON.stringify(await tf.io.listModels())); + * + * // Delete the model. + * await tf.io.removeModel('localstorage://demo/management/model1'); + * + * // List models again. + * console.log(JSON.stringify(await tf.io.listModels())); + * ``` + * + * @param url A URL to a stored model, with a scheme prefix, e.g., + * 'localstorage://my-model-1', 'indexeddb://my/model/2'. + * @returns ModelArtifactsInfo of the deleted model (if and only if deletion + * is successful). + * @throws Error if deletion fails, e.g., if no model exists at `path`. + */ + /** + * @doc { + * heading: 'Models', + * subheading: 'Management', + * namespace: 'io', + * ignoreCI: true + * } + */ + function removeModel(url) { + return __awaiter(this, void 0, void 0, function () { + var schemeAndPath, manager; + return __generator(this, function (_a) { + schemeAndPath = parseURL(url); + manager = ModelStoreManagerRegistry.getManager(schemeAndPath.scheme); + return [2 /*return*/, manager.removeModel(schemeAndPath.path)]; + }); + }); + } + /** + * Copy a model from one URL to another. + * + * This function supports: + * + * 1. Copying within a storage medium, e.g., + * `tf.io.copyModel('localstorage://model-1', 'localstorage://model-2')` + * 2. Copying between two storage mediums, e.g., + * `tf.io.copyModel('localstorage://model-1', 'indexeddb://model-1')` + * + * ```js + * // First create and save a model. + * const model = tf.sequential(); + * model.add(tf.layers.dense( + * {units: 1, inputShape: [10], activation: 'sigmoid'})); + * await model.save('localstorage://demo/management/model1'); + * + * // Then list existing models. + * console.log(JSON.stringify(await tf.io.listModels())); + * + * // Copy the model, from Local Storage to IndexedDB. + * await tf.io.copyModel( + * 'localstorage://demo/management/model1', + * 'indexeddb://demo/management/model1'); + * + * // List models again. + * console.log(JSON.stringify(await tf.io.listModels())); + * + * // Remove both models. + * await tf.io.removeModel('localstorage://demo/management/model1'); + * await tf.io.removeModel('indexeddb://demo/management/model1'); + * ``` + * + * @param sourceURL Source URL of copying. + * @param destURL Destination URL of copying. + * @returns ModelArtifactsInfo of the copied model (if and only if copying + * is successful). + * @throws Error if copying fails, e.g., if no model exists at `sourceURL`, or + * if `oldPath` and `newPath` are identical. + */ + /** + * @doc { + * heading: 'Models', + * subheading: 'Management', + * namespace: 'io', + * ignoreCI: true + * } + */ + function copyModel(sourceURL, destURL) { + return __awaiter(this, void 0, void 0, function () { + var deleteSource; + return __generator(this, function (_a) { + deleteSource = false; + return [2 /*return*/, cloneModelInternal(sourceURL, destURL, deleteSource)]; + }); + }); + } + /** + * Move a model from one URL to another. + * + * This function supports: + * + * 1. Moving within a storage medium, e.g., + * `tf.io.moveModel('localstorage://model-1', 'localstorage://model-2')` + * 2. Moving between two storage mediums, e.g., + * `tf.io.moveModel('localstorage://model-1', 'indexeddb://model-1')` + * + * ```js + * // First create and save a model. + * const model = tf.sequential(); + * model.add(tf.layers.dense( + * {units: 1, inputShape: [10], activation: 'sigmoid'})); + * await model.save('localstorage://demo/management/model1'); + * + * // Then list existing models. + * console.log(JSON.stringify(await tf.io.listModels())); + * + * // Move the model, from Local Storage to IndexedDB. + * await tf.io.moveModel( + * 'localstorage://demo/management/model1', + * 'indexeddb://demo/management/model1'); + * + * // List models again. + * console.log(JSON.stringify(await tf.io.listModels())); + * + * // Remove the moved model. + * await tf.io.removeModel('indexeddb://demo/management/model1'); + * ``` + * + * @param sourceURL Source URL of moving. + * @param destURL Destination URL of moving. + * @returns ModelArtifactsInfo of the copied model (if and only if copying + * is successful). + * @throws Error if moving fails, e.g., if no model exists at `sourceURL`, or + * if `oldPath` and `newPath` are identical. + */ + /** + * @doc { + * heading: 'Models', + * subheading: 'Management', + * namespace: 'io', + * ignoreCI: true + * } + */ + function moveModel(sourceURL, destURL) { + return __awaiter(this, void 0, void 0, function () { + var deleteSource; + return __generator(this, function (_a) { + deleteSource = true; + return [2 /*return*/, cloneModelInternal(sourceURL, destURL, deleteSource)]; + }); + }); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var DATABASE_NAME = 'tensorflowjs'; + var DATABASE_VERSION = 1; + // Model data and ModelArtifactsInfo (metadata) are stored in two separate + // stores for efficient access of the list of stored models and their metadata. + // 1. The object store for model data: topology, weights and weight manifests. + var MODEL_STORE_NAME = 'models_store'; + // 2. The object store for ModelArtifactsInfo, including meta-information such + // as the type of topology (JSON vs binary), byte size of the topology, byte + // size of the weights, etc. + var INFO_STORE_NAME = 'model_info_store'; + function getIndexedDBFactory() { + if (!env().getBool('IS_BROWSER')) { + // TODO(cais): Add more info about what IOHandler subtypes are available. + // Maybe point to a doc page on the web and/or automatically determine + // the available IOHandlers and print them in the error message. + throw new Error('Failed to obtain IndexedDB factory because the current environment' + + 'is not a web browser.'); + } + // tslint:disable-next-line:no-any + var theWindow = typeof window === 'undefined' ? self : window; + var factory = theWindow.indexedDB || theWindow.mozIndexedDB || + theWindow.webkitIndexedDB || theWindow.msIndexedDB || + theWindow.shimIndexedDB; + if (factory == null) { + throw new Error('The current browser does not appear to support IndexedDB.'); + } + return factory; + } + function setUpDatabase(openRequest) { + var db = openRequest.result; + db.createObjectStore(MODEL_STORE_NAME, { keyPath: 'modelPath' }); + db.createObjectStore(INFO_STORE_NAME, { keyPath: 'modelPath' }); + } + /** + * IOHandler subclass: Browser IndexedDB. + * + * See the doc string of `browserIndexedDB` for more details. + */ + var BrowserIndexedDB = /** @class */ (function () { + function BrowserIndexedDB(modelPath) { + this.indexedDB = getIndexedDBFactory(); + if (modelPath == null || !modelPath) { + throw new Error('For IndexedDB, modelPath must not be null, undefined or empty.'); + } + this.modelPath = modelPath; + } + BrowserIndexedDB.prototype.save = function (modelArtifacts) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + // TODO(cais): Support saving GraphDef models. + if (modelArtifacts.modelTopology instanceof ArrayBuffer) { + throw new Error('BrowserLocalStorage.save() does not support saving model topology ' + + 'in binary formats yet.'); + } + return [2 /*return*/, this.databaseAction(this.modelPath, modelArtifacts)]; + }); + }); + }; + BrowserIndexedDB.prototype.load = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, this.databaseAction(this.modelPath)]; + }); + }); + }; + /** + * Perform database action to put model artifacts into or read model artifacts + * from IndexedDB object store. + * + * Whether the action is put or get depends on whether `modelArtifacts` is + * specified. If it is specified, the action will be put; otherwise the action + * will be get. + * + * @param modelPath A unique string path for the model. + * @param modelArtifacts If specified, it will be the model artifacts to be + * stored in IndexedDB. + * @returns A `Promise` of `SaveResult`, if the action is put, or a `Promise` + * of `ModelArtifacts`, if the action is get. + */ + BrowserIndexedDB.prototype.databaseAction = function (modelPath, modelArtifacts) { + var _this = this; + return new Promise(function (resolve, reject) { + var openRequest = _this.indexedDB.open(DATABASE_NAME, DATABASE_VERSION); + openRequest.onupgradeneeded = function () { return setUpDatabase(openRequest); }; + openRequest.onsuccess = function () { + var db = openRequest.result; + if (modelArtifacts == null) { + // Read model out from object store. + var modelTx = db.transaction(MODEL_STORE_NAME, 'readonly'); + var modelStore = modelTx.objectStore(MODEL_STORE_NAME); + var getRequest_1 = modelStore.get(_this.modelPath); + getRequest_1.onsuccess = function () { + if (getRequest_1.result == null) { + db.close(); + return reject(new Error("Cannot find model with path '" + _this.modelPath + "' " + + "in IndexedDB.")); + } + else { + resolve(getRequest_1.result.modelArtifacts); + } + }; + getRequest_1.onerror = function (error) { + db.close(); + return reject(getRequest_1.error); + }; + modelTx.oncomplete = function () { return db.close(); }; + } + else { + // Put model into object store. + var modelArtifactsInfo_1 = getModelArtifactsInfoForJSON(modelArtifacts); + // First, put ModelArtifactsInfo into info store. + var infoTx_1 = db.transaction(INFO_STORE_NAME, 'readwrite'); + var infoStore_1 = infoTx_1.objectStore(INFO_STORE_NAME); + var putInfoRequest_1 = infoStore_1.put({ modelPath: _this.modelPath, modelArtifactsInfo: modelArtifactsInfo_1 }); + var modelTx_1; + putInfoRequest_1.onsuccess = function () { + // Second, put model data into model store. + modelTx_1 = db.transaction(MODEL_STORE_NAME, 'readwrite'); + var modelStore = modelTx_1.objectStore(MODEL_STORE_NAME); + var putModelRequest = modelStore.put({ + modelPath: _this.modelPath, + modelArtifacts: modelArtifacts, + modelArtifactsInfo: modelArtifactsInfo_1 + }); + putModelRequest.onsuccess = function () { return resolve({ modelArtifactsInfo: modelArtifactsInfo_1 }); }; + putModelRequest.onerror = function (error) { + // If the put-model request fails, roll back the info entry as + // well. + infoStore_1 = infoTx_1.objectStore(INFO_STORE_NAME); + var deleteInfoRequest = infoStore_1.delete(_this.modelPath); + deleteInfoRequest.onsuccess = function () { + db.close(); + return reject(putModelRequest.error); + }; + deleteInfoRequest.onerror = function (error) { + db.close(); + return reject(putModelRequest.error); + }; + }; + }; + putInfoRequest_1.onerror = function (error) { + db.close(); + return reject(putInfoRequest_1.error); + }; + infoTx_1.oncomplete = function () { + if (modelTx_1 == null) { + db.close(); + } + else { + modelTx_1.oncomplete = function () { return db.close(); }; + } + }; + } + }; + openRequest.onerror = function (error) { return reject(openRequest.error); }; + }); + }; + BrowserIndexedDB.URL_SCHEME = 'indexeddb://'; + return BrowserIndexedDB; + }()); + var indexedDBRouter = function (url) { + if (!env().getBool('IS_BROWSER')) { + return null; + } + else { + if (!Array.isArray(url) && url.startsWith(BrowserIndexedDB.URL_SCHEME)) { + return browserIndexedDB(url.slice(BrowserIndexedDB.URL_SCHEME.length)); + } + else { + return null; + } + } + }; + IORouterRegistry.registerSaveRouter(indexedDBRouter); + IORouterRegistry.registerLoadRouter(indexedDBRouter); + /** + * Creates a browser IndexedDB IOHandler for saving and loading models. + * + * ```js + * const model = tf.sequential(); + * model.add( + * tf.layers.dense({units: 1, inputShape: [100], activation: 'sigmoid'})); + * + * const saveResult = await model.save('indexeddb://MyModel')); + * console.log(saveResult); + * ``` + * + * @param modelPath A unique identifier for the model to be saved. Must be a + * non-empty string. + * @returns An instance of `BrowserIndexedDB` (sublcass of `IOHandler`), + * which can be used with, e.g., `tf.Model.save`. + */ + function browserIndexedDB(modelPath) { + return new BrowserIndexedDB(modelPath); + } + function maybeStripScheme(key) { + return key.startsWith(BrowserIndexedDB.URL_SCHEME) ? + key.slice(BrowserIndexedDB.URL_SCHEME.length) : + key; + } + var BrowserIndexedDBManager = /** @class */ (function () { + function BrowserIndexedDBManager() { + this.indexedDB = getIndexedDBFactory(); + } + BrowserIndexedDBManager.prototype.listModels = function () { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2 /*return*/, new Promise(function (resolve, reject) { + var openRequest = _this.indexedDB.open(DATABASE_NAME, DATABASE_VERSION); + openRequest.onupgradeneeded = function () { return setUpDatabase(openRequest); }; + openRequest.onsuccess = function () { + var db = openRequest.result; + var tx = db.transaction(INFO_STORE_NAME, 'readonly'); + var store = tx.objectStore(INFO_STORE_NAME); + // tslint:disable:max-line-length + // Need to cast `store` as `any` here because TypeScript's DOM + // library does not have the `getAll()` method even though the + // method is supported in the latest version of most mainstream + // browsers: + // https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/getAll + // tslint:enable:max-line-length + // tslint:disable-next-line:no-any + var getAllInfoRequest = store.getAll(); + getAllInfoRequest.onsuccess = function () { + var out = {}; + for (var _i = 0, _a = getAllInfoRequest.result; _i < _a.length; _i++) { + var item = _a[_i]; + out[item.modelPath] = item.modelArtifactsInfo; + } + resolve(out); + }; + getAllInfoRequest.onerror = function (error) { + db.close(); + return reject(getAllInfoRequest.error); + }; + tx.oncomplete = function () { return db.close(); }; + }; + openRequest.onerror = function (error) { return reject(openRequest.error); }; + })]; + }); + }); + }; + BrowserIndexedDBManager.prototype.removeModel = function (path) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + path = maybeStripScheme(path); + return [2 /*return*/, new Promise(function (resolve, reject) { + var openRequest = _this.indexedDB.open(DATABASE_NAME, DATABASE_VERSION); + openRequest.onupgradeneeded = function () { return setUpDatabase(openRequest); }; + openRequest.onsuccess = function () { + var db = openRequest.result; + var infoTx = db.transaction(INFO_STORE_NAME, 'readwrite'); + var infoStore = infoTx.objectStore(INFO_STORE_NAME); + var getInfoRequest = infoStore.get(path); + var modelTx; + getInfoRequest.onsuccess = function () { + if (getInfoRequest.result == null) { + db.close(); + return reject(new Error("Cannot find model with path '" + path + "' " + + "in IndexedDB.")); + } + else { + // First, delete the entry in the info store. + var deleteInfoRequest = infoStore.delete(path); + var deleteModelData_1 = function () { + // Second, delete the entry in the model store. + modelTx = db.transaction(MODEL_STORE_NAME, 'readwrite'); + var modelStore = modelTx.objectStore(MODEL_STORE_NAME); + var deleteModelRequest = modelStore.delete(path); + deleteModelRequest.onsuccess = function () { + return resolve(getInfoRequest.result.modelArtifactsInfo); + }; + deleteModelRequest.onerror = function (error) { + return reject(getInfoRequest.error); + }; + }; + // Proceed with deleting model data regardless of whether deletion + // of info data succeeds or not. + deleteInfoRequest.onsuccess = deleteModelData_1; + deleteInfoRequest.onerror = function (error) { + deleteModelData_1(); + db.close(); + return reject(getInfoRequest.error); + }; + } + }; + getInfoRequest.onerror = function (error) { + db.close(); + return reject(getInfoRequest.error); + }; + infoTx.oncomplete = function () { + if (modelTx == null) { + db.close(); + } + else { + modelTx.oncomplete = function () { return db.close(); }; + } + }; + }; + openRequest.onerror = function (error) { return reject(openRequest.error); }; + })]; + }); + }); + }; + return BrowserIndexedDBManager; + }()); + if (env().getBool('IS_BROWSER')) { + // Wrap the construction and registration, to guard against browsers that + // don't support Local Storage. + try { + ModelStoreManagerRegistry.registerManager(BrowserIndexedDB.URL_SCHEME, new BrowserIndexedDBManager()); + } + catch (err) { + } + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var PATH_SEPARATOR = '/'; + var PATH_PREFIX = 'tensorflowjs_models'; + var INFO_SUFFIX = 'info'; + var MODEL_TOPOLOGY_SUFFIX = 'model_topology'; + var WEIGHT_SPECS_SUFFIX = 'weight_specs'; + var WEIGHT_DATA_SUFFIX = 'weight_data'; + var MODEL_METADATA_SUFFIX = 'model_metadata'; + function getModelKeys(path) { + return { + info: [PATH_PREFIX, path, INFO_SUFFIX].join(PATH_SEPARATOR), + topology: [PATH_PREFIX, path, MODEL_TOPOLOGY_SUFFIX].join(PATH_SEPARATOR), + weightSpecs: [PATH_PREFIX, path, WEIGHT_SPECS_SUFFIX].join(PATH_SEPARATOR), + weightData: [PATH_PREFIX, path, WEIGHT_DATA_SUFFIX].join(PATH_SEPARATOR), + modelMetadata: [PATH_PREFIX, path, MODEL_METADATA_SUFFIX].join(PATH_SEPARATOR) + }; + } + /** + * Get model path from a local-storage key. + * + * E.g., 'tensorflowjs_models/my/model/1/info' --> 'my/model/1' + * + * @param key + */ + function getModelPathFromKey(key) { + var items = key.split(PATH_SEPARATOR); + if (items.length < 3) { + throw new Error("Invalid key format: " + key); + } + return items.slice(1, items.length - 1).join(PATH_SEPARATOR); + } + function maybeStripScheme$1(key) { + return key.startsWith(BrowserLocalStorage.URL_SCHEME) ? + key.slice(BrowserLocalStorage.URL_SCHEME.length) : + key; + } + /** + * IOHandler subclass: Browser Local Storage. + * + * See the doc string to `browserLocalStorage` for more details. + */ + var BrowserLocalStorage = /** @class */ (function () { + function BrowserLocalStorage(modelPath) { + if (!env().getBool('IS_BROWSER') || + typeof window === 'undefined' || + typeof window.localStorage === 'undefined') { + // TODO(cais): Add more info about what IOHandler subtypes are + // available. + // Maybe point to a doc page on the web and/or automatically determine + // the available IOHandlers and print them in the error message. + throw new Error('The current environment does not support local storage.'); + } + this.LS = window.localStorage; + if (modelPath == null || !modelPath) { + throw new Error('For local storage, modelPath must not be null, undefined or empty.'); + } + this.modelPath = modelPath; + this.keys = getModelKeys(this.modelPath); + } + /** + * Save model artifacts to browser local storage. + * + * See the documentation to `browserLocalStorage` for details on the saved + * artifacts. + * + * @param modelArtifacts The model artifacts to be stored. + * @returns An instance of SaveResult. + */ + BrowserLocalStorage.prototype.save = function (modelArtifacts) { + return __awaiter(this, void 0, void 0, function () { + var topology, weightSpecs, modelArtifactsInfo; + return __generator(this, function (_a) { + if (modelArtifacts.modelTopology instanceof ArrayBuffer) { + throw new Error('BrowserLocalStorage.save() does not support saving model topology ' + + 'in binary formats yet.'); + } + else { + topology = JSON.stringify(modelArtifacts.modelTopology); + weightSpecs = JSON.stringify(modelArtifacts.weightSpecs); + modelArtifactsInfo = getModelArtifactsInfoForJSON(modelArtifacts); + try { + this.LS.setItem(this.keys.info, JSON.stringify(modelArtifactsInfo)); + this.LS.setItem(this.keys.topology, topology); + this.LS.setItem(this.keys.weightSpecs, weightSpecs); + this.LS.setItem(this.keys.weightData, arrayBufferToBase64String(modelArtifacts.weightData)); + this.LS.setItem(this.keys.modelMetadata, JSON.stringify({ + format: modelArtifacts.format, + generatedBy: modelArtifacts.generatedBy, + convertedBy: modelArtifacts.convertedBy, + userDefinedMetadata: modelArtifacts.userDefinedMetadata + })); + return [2 /*return*/, { modelArtifactsInfo: modelArtifactsInfo }]; + } + catch (err) { + // If saving failed, clean up all items saved so far. + this.LS.removeItem(this.keys.info); + this.LS.removeItem(this.keys.topology); + this.LS.removeItem(this.keys.weightSpecs); + this.LS.removeItem(this.keys.weightData); + this.LS.removeItem(this.keys.modelMetadata); + throw new Error("Failed to save model '" + this.modelPath + "' to local storage: " + + "size quota being exceeded is a possible cause of this failure: " + + ("modelTopologyBytes=" + modelArtifactsInfo.modelTopologyBytes + ", ") + + ("weightSpecsBytes=" + modelArtifactsInfo.weightSpecsBytes + ", ") + + ("weightDataBytes=" + modelArtifactsInfo.weightDataBytes + ".")); + } + } + return [2 /*return*/]; + }); + }); + }; + /** + * Load a model from local storage. + * + * See the documentation to `browserLocalStorage` for details on the saved + * artifacts. + * + * @returns The loaded model (if loading succeeds). + */ + BrowserLocalStorage.prototype.load = function () { + return __awaiter(this, void 0, void 0, function () { + var info, out, topology, weightSpecs, metadataString, metadata, weightDataBase64; + return __generator(this, function (_a) { + info = JSON.parse(this.LS.getItem(this.keys.info)); + if (info == null) { + throw new Error("In local storage, there is no model with name '" + this.modelPath + "'"); + } + if (info.modelTopologyType !== 'JSON') { + throw new Error('BrowserLocalStorage does not support loading non-JSON model ' + + 'topology yet.'); + } + out = {}; + topology = JSON.parse(this.LS.getItem(this.keys.topology)); + if (topology == null) { + throw new Error("In local storage, the topology of model '" + this.modelPath + "' " + + "is missing."); + } + out.modelTopology = topology; + weightSpecs = JSON.parse(this.LS.getItem(this.keys.weightSpecs)); + if (weightSpecs == null) { + throw new Error("In local storage, the weight specs of model '" + this.modelPath + "' " + + "are missing."); + } + out.weightSpecs = weightSpecs; + metadataString = this.LS.getItem(this.keys.modelMetadata); + if (metadataString != null) { + metadata = JSON.parse(metadataString); + out.format = metadata['format']; + out.generatedBy = metadata['generatedBy']; + out.convertedBy = metadata['convertedBy']; + out.userDefinedMetadata = metadata['userDefinedMetadata']; + } + weightDataBase64 = this.LS.getItem(this.keys.weightData); + if (weightDataBase64 == null) { + throw new Error("In local storage, the binary weight values of model " + + ("'" + this.modelPath + "' are missing.")); + } + out.weightData = base64StringToArrayBuffer(weightDataBase64); + return [2 /*return*/, out]; + }); + }); + }; + BrowserLocalStorage.URL_SCHEME = 'localstorage://'; + return BrowserLocalStorage; + }()); + var localStorageRouter = function (url) { + if (!env().getBool('IS_BROWSER')) { + return null; + } + else { + if (!Array.isArray(url) && url.startsWith(BrowserLocalStorage.URL_SCHEME)) { + return browserLocalStorage(url.slice(BrowserLocalStorage.URL_SCHEME.length)); + } + else { + return null; + } + } + }; + IORouterRegistry.registerSaveRouter(localStorageRouter); + IORouterRegistry.registerLoadRouter(localStorageRouter); + /** + * Factory function for local storage IOHandler. + * + * This `IOHandler` supports both `save` and `load`. + * + * For each model's saved artifacts, four items are saved to local storage. + * - `${PATH_SEPARATOR}/${modelPath}/info`: Contains meta-info about the + * model, such as date saved, type of the topology, size in bytes, etc. + * - `${PATH_SEPARATOR}/${modelPath}/topology`: Model topology. For Keras- + * style models, this is a stringized JSON. + * - `${PATH_SEPARATOR}/${modelPath}/weight_specs`: Weight specs of the + * model, can be used to decode the saved binary weight values (see + * item below). + * - `${PATH_SEPARATOR}/${modelPath}/weight_data`: Concatenated binary + * weight values, stored as a base64-encoded string. + * + * Saving may throw an `Error` if the total size of the artifacts exceed the + * browser-specific quota. + * + * @param modelPath A unique identifier for the model to be saved. Must be a + * non-empty string. + * @returns An instance of `IOHandler`, which can be used with, e.g., + * `tf.Model.save`. + */ + function browserLocalStorage(modelPath) { + return new BrowserLocalStorage(modelPath); + } + var BrowserLocalStorageManager = /** @class */ (function () { + function BrowserLocalStorageManager() { + assert(env().getBool('IS_BROWSER'), function () { return 'Current environment is not a web browser'; }); + assert(typeof window === 'undefined' || + typeof window.localStorage !== 'undefined', function () { return 'Current browser does not appear to support localStorage'; }); + this.LS = window.localStorage; + } + BrowserLocalStorageManager.prototype.listModels = function () { + return __awaiter(this, void 0, void 0, function () { + var out, prefix, suffix, i, key, modelPath; + return __generator(this, function (_a) { + out = {}; + prefix = PATH_PREFIX + PATH_SEPARATOR; + suffix = PATH_SEPARATOR + INFO_SUFFIX; + for (i = 0; i < this.LS.length; ++i) { + key = this.LS.key(i); + if (key.startsWith(prefix) && key.endsWith(suffix)) { + modelPath = getModelPathFromKey(key); + out[modelPath] = JSON.parse(this.LS.getItem(key)); + } + } + return [2 /*return*/, out]; + }); + }); + }; + BrowserLocalStorageManager.prototype.removeModel = function (path) { + return __awaiter(this, void 0, void 0, function () { + var keys, info; + return __generator(this, function (_a) { + path = maybeStripScheme$1(path); + keys = getModelKeys(path); + if (this.LS.getItem(keys.info) == null) { + throw new Error("Cannot find model at path '" + path + "'"); + } + info = JSON.parse(this.LS.getItem(keys.info)); + this.LS.removeItem(keys.info); + this.LS.removeItem(keys.topology); + this.LS.removeItem(keys.weightSpecs); + this.LS.removeItem(keys.weightData); + return [2 /*return*/, info]; + }); + }); + }; + return BrowserLocalStorageManager; + }()); + if (env().getBool('IS_BROWSER')) { + // Wrap the construction and registration, to guard against browsers that + // don't support Local Storage. + try { + ModelStoreManagerRegistry.registerManager(BrowserLocalStorage.URL_SCHEME, new BrowserLocalStorageManager()); + } + catch (err) { + } + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var DEFAULT_FILE_NAME_PREFIX = 'model'; + var DEFAULT_JSON_EXTENSION_NAME = '.json'; + var DEFAULT_WEIGHT_DATA_EXTENSION_NAME = '.weights.bin'; + function defer(f) { + return new Promise(function (resolve) { return setTimeout(resolve); }).then(f); + } + var BrowserDownloads = /** @class */ (function () { + function BrowserDownloads(fileNamePrefix) { + if (!env().getBool('IS_BROWSER')) { + // TODO(cais): Provide info on what IOHandlers are available under the + // current environment. + throw new Error('browserDownloads() cannot proceed because the current environment ' + + 'is not a browser.'); + } + if (fileNamePrefix.startsWith(BrowserDownloads.URL_SCHEME)) { + fileNamePrefix = fileNamePrefix.slice(BrowserDownloads.URL_SCHEME.length); + } + if (fileNamePrefix == null || fileNamePrefix.length === 0) { + fileNamePrefix = DEFAULT_FILE_NAME_PREFIX; + } + this.modelTopologyFileName = fileNamePrefix + DEFAULT_JSON_EXTENSION_NAME; + this.weightDataFileName = + fileNamePrefix + DEFAULT_WEIGHT_DATA_EXTENSION_NAME; + } + BrowserDownloads.prototype.save = function (modelArtifacts) { + return __awaiter(this, void 0, void 0, function () { + var weightsURL, weightsManifest, modelTopologyAndWeightManifest, modelTopologyAndWeightManifestURL, jsonAnchor_1, weightDataAnchor_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (typeof (document) === 'undefined') { + throw new Error('Browser downloads are not supported in ' + + 'this environment since `document` is not present'); + } + weightsURL = window.URL.createObjectURL(new Blob([modelArtifacts.weightData], { type: 'application/octet-stream' })); + if (!(modelArtifacts.modelTopology instanceof ArrayBuffer)) return [3 /*break*/, 1]; + throw new Error('BrowserDownloads.save() does not support saving model topology ' + + 'in binary formats yet.'); + case 1: + weightsManifest = [{ + paths: ['./' + this.weightDataFileName], + weights: modelArtifacts.weightSpecs + }]; + modelTopologyAndWeightManifest = { + modelTopology: modelArtifacts.modelTopology, + format: modelArtifacts.format, + generatedBy: modelArtifacts.generatedBy, + convertedBy: modelArtifacts.convertedBy, + weightsManifest: weightsManifest + }; + modelTopologyAndWeightManifestURL = window.URL.createObjectURL(new Blob([JSON.stringify(modelTopologyAndWeightManifest)], { type: 'application/json' })); + jsonAnchor_1 = this.jsonAnchor == null ? document.createElement('a') : + this.jsonAnchor; + jsonAnchor_1.download = this.modelTopologyFileName; + jsonAnchor_1.href = modelTopologyAndWeightManifestURL; + // Trigger downloads by evoking a click event on the download anchors. + // When multiple downloads are started synchronously, Firefox will only + // save the last one. + return [4 /*yield*/, defer(function () { return jsonAnchor_1.dispatchEvent(new MouseEvent('click')); })]; + case 2: + // Trigger downloads by evoking a click event on the download anchors. + // When multiple downloads are started synchronously, Firefox will only + // save the last one. + _a.sent(); + if (!(modelArtifacts.weightData != null)) return [3 /*break*/, 4]; + weightDataAnchor_1 = this.weightDataAnchor == null ? + document.createElement('a') : + this.weightDataAnchor; + weightDataAnchor_1.download = this.weightDataFileName; + weightDataAnchor_1.href = weightsURL; + return [4 /*yield*/, defer(function () { return weightDataAnchor_1.dispatchEvent(new MouseEvent('click')); })]; + case 3: + _a.sent(); + _a.label = 4; + case 4: return [2 /*return*/, { modelArtifactsInfo: getModelArtifactsInfoForJSON(modelArtifacts) }]; + } + }); + }); + }; + BrowserDownloads.URL_SCHEME = 'downloads://'; + return BrowserDownloads; + }()); + var BrowserFiles = /** @class */ (function () { + function BrowserFiles(files) { + if (files == null || files.length < 1) { + throw new Error("When calling browserFiles, at least 1 file is required, " + + ("but received " + files)); + } + this.files = files; + } + BrowserFiles.prototype.load = function () { + return __awaiter(this, void 0, void 0, function () { + var jsonFile, weightFiles; + var _this = this; + return __generator(this, function (_a) { + jsonFile = this.files[0]; + weightFiles = this.files.slice(1); + return [2 /*return*/, new Promise(function (resolve, reject) { + var jsonReader = new FileReader(); + jsonReader.onload = function (event) { + // tslint:disable-next-line:no-any + var modelJSON = JSON.parse(event.target.result); + var modelTopology = modelJSON.modelTopology; + if (modelTopology == null) { + reject(new Error("modelTopology field is missing from file " + jsonFile.name)); + return; + } + if (weightFiles.length === 0) { + resolve({ modelTopology: modelTopology }); + } + var weightsManifest = modelJSON.weightsManifest; + if (weightsManifest == null) { + reject(new Error("weightManifest field is missing from file " + jsonFile.name)); + return; + } + var pathToFile; + try { + pathToFile = + _this.checkManifestAndWeightFiles(weightsManifest, weightFiles); + } + catch (err) { + reject(err); + return; + } + var weightSpecs = []; + var paths = []; + var perFileBuffers = []; + weightsManifest.forEach(function (weightsGroup) { + weightsGroup.paths.forEach(function (path) { + paths.push(path); + perFileBuffers.push(null); + }); + weightSpecs.push.apply(weightSpecs, weightsGroup.weights); + }); + weightsManifest.forEach(function (weightsGroup) { + weightsGroup.paths.forEach(function (path) { + var weightFileReader = new FileReader(); + weightFileReader.onload = function (event) { + // tslint:disable-next-line:no-any + var weightData = event.target.result; + var index = paths.indexOf(path); + perFileBuffers[index] = weightData; + if (perFileBuffers.indexOf(null) === -1) { + resolve({ + modelTopology: modelTopology, + weightSpecs: weightSpecs, + weightData: concatenateArrayBuffers(perFileBuffers), + format: modelJSON.format, + generatedBy: modelJSON.generatedBy, + convertedBy: modelJSON.convertedBy, + userDefinedMetadata: modelJSON.userDefinedMetadata + }); + } + }; + weightFileReader.onerror = function (error) { + return reject("Failed to weights data from file of path '" + path + "'."); + }; + weightFileReader.readAsArrayBuffer(pathToFile[path]); + }); + }); + }; + jsonReader.onerror = function (error) { return reject("Failed to read model topology and weights manifest JSON " + + ("from file '" + jsonFile.name + "'. BrowserFiles supports loading ") + + "Keras-style tf.Model artifacts only."); }; + jsonReader.readAsText(jsonFile); + })]; + }); + }); + }; + /** + * Check the compatibility between weights manifest and weight files. + */ + BrowserFiles.prototype.checkManifestAndWeightFiles = function (manifest, files) { + var basenames = []; + var fileNames = files.map(function (file) { return basename(file.name); }); + var pathToFile = {}; + for (var _i = 0, manifest_1 = manifest; _i < manifest_1.length; _i++) { + var group = manifest_1[_i]; + group.paths.forEach(function (path) { + var pathBasename = basename(path); + if (basenames.indexOf(pathBasename) !== -1) { + throw new Error("Duplicate file basename found in weights manifest: " + + ("'" + pathBasename + "'")); + } + basenames.push(pathBasename); + if (fileNames.indexOf(pathBasename) === -1) { + throw new Error("Weight file with basename '" + pathBasename + "' is not provided."); + } + else { + pathToFile[path] = files[fileNames.indexOf(pathBasename)]; + } + }); + } + if (basenames.length !== files.length) { + throw new Error("Mismatch in the number of files in weights manifest " + + ("(" + basenames.length + ") and the number of weight files provided ") + + ("(" + files.length + ").")); + } + return pathToFile; + }; + return BrowserFiles; + }()); + var browserDownloadsRouter = function (url) { + if (!env().getBool('IS_BROWSER')) { + return null; + } + else { + if (!Array.isArray(url) && url.startsWith(BrowserDownloads.URL_SCHEME)) { + return browserDownloads(url.slice(BrowserDownloads.URL_SCHEME.length)); + } + else { + return null; + } + } + }; + IORouterRegistry.registerSaveRouter(browserDownloadsRouter); + /** + * Creates an IOHandler that triggers file downloads from the browser. + * + * The returned `IOHandler` instance can be used as model exporting methods such + * as `tf.Model.save` and supports only saving. + * + * ```js + * const model = tf.sequential(); + * model.add(tf.layers.dense( + * {units: 1, inputShape: [10], activation: 'sigmoid'})); + * const saveResult = await model.save('downloads://mymodel'); + * // This will trigger downloading of two files: + * // 'mymodel.json' and 'mymodel.weights.bin'. + * console.log(saveResult); + * ``` + * + * @param fileNamePrefix Prefix name of the files to be downloaded. For use with + * `tf.Model`, `fileNamePrefix` should follow either of the following two + * formats: + * 1. `null` or `undefined`, in which case the default file + * names will be used: + * - 'model.json' for the JSON file containing the model topology and + * weights manifest. + * - 'model.weights.bin' for the binary file containing the binary weight + * values. + * 2. A single string or an Array of a single string, as the file name prefix. + * For example, if `'foo'` is provided, the downloaded JSON + * file and binary weights file will be named 'foo.json' and + * 'foo.weights.bin', respectively. + * @param config Additional configuration for triggering downloads. + * @returns An instance of `BrowserDownloads` `IOHandler`. + */ + /** + * @doc { + * heading: 'Models', + * subheading: 'Loading', + * namespace: 'io', + * ignoreCI: true + * } + */ + function browserDownloads(fileNamePrefix) { + if (fileNamePrefix === void 0) { fileNamePrefix = 'model'; } + return new BrowserDownloads(fileNamePrefix); + } + /** + * Creates an IOHandler that loads model artifacts from user-selected files. + * + * This method can be used for loading from files such as user-selected files + * in the browser. + * When used in conjunction with `tf.loadLayersModel`, an instance of + * `tf.LayersModel` (Keras-style) can be constructed from the loaded artifacts. + * + * ```js + * // Note: This code snippet won't run properly without the actual file input + * // elements in the HTML DOM. + * + * // Suppose there are two HTML file input (``) + * // elements. + * const uploadJSONInput = document.getElementById('upload-json'); + * const uploadWeightsInput = document.getElementById('upload-weights'); + * const model = await tf.loadLayersModel(tf.io.browserFiles( + * [uploadJSONInput.files[0], uploadWeightsInput.files[0]])); + * ``` + * + * @param files `File`s to load from. Currently, this function supports only + * loading from files that contain Keras-style models (i.e., `tf.Model`s), for + * which an `Array` of `File`s is expected (in that order): + * - A JSON file containing the model topology and weight manifest. + * - Optionally, One or more binary files containing the binary weights. + * These files must have names that match the paths in the `weightsManifest` + * contained by the aforementioned JSON file, or errors will be thrown + * during loading. These weights files have the same format as the ones + * generated by `tensorflowjs_converter` that comes with the `tensorflowjs` + * Python PIP package. If no weights files are provided, only the model + * topology will be loaded from the JSON file above. + * @returns An instance of `Files` `IOHandler`. + */ + /** + * @doc { + * heading: 'Models', + * subheading: 'Loading', + * namespace: 'io', + * ignoreCI: true + * } + */ + function browserFiles(files) { + return new BrowserFiles(files); + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Monitor Promise.all progress, fire onProgress callback function. + * + * @param promises Promise list going to be monitored + * @param onProgress Callback function. Fired when a promise resolved. + * @param startFraction Optional fraction start. Default to 0. + * @param endFraction Optional fraction end. Default to 1. + */ + function monitorPromisesProgress(promises, onProgress, startFraction, endFraction) { + checkPromises(promises); + startFraction = startFraction == null ? 0 : startFraction; + endFraction = endFraction == null ? 1 : endFraction; + checkFraction(startFraction, endFraction); + var resolvedPromise = 0; + var registerMonitor = function (promise) { + promise.then(function (value) { + var fraction = startFraction + + ++resolvedPromise / promises.length * (endFraction - startFraction); + // pass fraction as parameter to callback function. + onProgress(fraction); + return value; + }); + return promise; + }; + function checkPromises(promises) { + assert(promises != null && Array.isArray(promises) && promises.length > 0, function () { return 'promises must be a none empty array'; }); + } + function checkFraction(startFraction, endFraction) { + assert(startFraction >= 0 && startFraction <= 1, function () { return "Progress fraction must be in range [0, 1], but " + + ("got startFraction " + startFraction); }); + assert(endFraction >= 0 && endFraction <= 1, function () { return "Progress fraction must be in range [0, 1], but " + + ("got endFraction " + endFraction); }); + assert(endFraction >= startFraction, function () { return "startFraction must be no more than endFraction, but " + + ("got startFraction " + startFraction + " and endFraction ") + + ("" + endFraction); }); + } + return Promise.all(promises.map(registerMonitor)); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Reads binary weights data from a number of URLs. + * + * @param fetchURLs URLs to send the HTTP requests at, using `fetch` calls. + * @param requestOptions RequestInit (options) for the HTTP requests. + * @param fetchFunc Optional overriding value for the `window.fetch` function. + * @param onProgress Optional, progress callback function, fired periodically + * before the load is completed. + * @returns A `Promise` of an Array of `ArrayBuffer`. The Array has the same + * length as `fetchURLs`. + */ + function loadWeightsAsArrayBuffer(fetchURLs, loadOptions) { + return __awaiter(this, void 0, void 0, function () { + var fetchFunc, requests, fetchStartFraction, fetchEndFraction, responses, _a, bufferPromises, bufferStartFraction, bufferEndFraction, buffers, _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + if (loadOptions == null) { + loadOptions = {}; + } + fetchFunc = loadOptions.fetchFunc == null ? env().platform.fetch : + loadOptions.fetchFunc; + requests = fetchURLs.map(function (fetchURL) { + return fetchFunc(fetchURL, loadOptions.requestInit, { isBinary: true }); + }); + fetchStartFraction = 0; + fetchEndFraction = 0.5; + if (!(loadOptions.onProgress == null)) return [3 /*break*/, 2]; + return [4 /*yield*/, Promise.all(requests)]; + case 1: + _a = _c.sent(); + return [3 /*break*/, 4]; + case 2: return [4 /*yield*/, monitorPromisesProgress(requests, loadOptions.onProgress, fetchStartFraction, fetchEndFraction)]; + case 3: + _a = _c.sent(); + _c.label = 4; + case 4: + responses = _a; + bufferPromises = responses.map(function (response) { return response.arrayBuffer(); }); + bufferStartFraction = 0.5; + bufferEndFraction = 1; + if (!(loadOptions.onProgress == null)) return [3 /*break*/, 6]; + return [4 /*yield*/, Promise.all(bufferPromises)]; + case 5: + _b = _c.sent(); + return [3 /*break*/, 8]; + case 6: return [4 /*yield*/, monitorPromisesProgress(bufferPromises, loadOptions.onProgress, bufferStartFraction, bufferEndFraction)]; + case 7: + _b = _c.sent(); + _c.label = 8; + case 8: + buffers = _b; + return [2 /*return*/, buffers]; + } + }); + }); + } + /** + * Reads a weights manifest JSON configuration, fetches the weights and + * returns them as `Tensor`s. + * + * @param manifest The weights manifest JSON. + * @param filePathPrefix The path prefix for filenames given in the manifest. + * Defaults to the empty string. + * @param weightNames The names of the weights to be fetched. + */ + function loadWeights(manifest, filePathPrefix, weightNames, requestInit) { + if (filePathPrefix === void 0) { filePathPrefix = ''; } + return __awaiter(this, void 0, void 0, function () { + var fetchWeights, loadWeights; + return __generator(this, function (_a) { + fetchWeights = function (fetchUrls) { + return loadWeightsAsArrayBuffer(fetchUrls, { requestInit: requestInit }); + }; + loadWeights = weightsLoaderFactory(fetchWeights); + return [2 /*return*/, loadWeights(manifest, filePathPrefix, weightNames)]; + }); + }); + } + /** + * Creates a function, which reads a weights manifest JSON configuration, + * fetches the weight files using the specified function and returns them as + * `Tensor`s. + * + * ```js + * // example for creating a nodejs weight loader, which reads the weight files + * // from disk using fs.readFileSync + * + * import * as fs from 'fs' + * + * const fetchWeightsFromDisk = (filePaths: string[]) => + * filePaths.map(filePath => fs.readFileSync(filePath).buffer) + * + * const loadWeights = tf.io.weightsLoaderFactory(fetchWeightsFromDisk) + * + * const manifest = JSON.parse( + * fs.readFileSync('./my_model-weights_manifest').toString() + * ) + * const weightMap = await loadWeights(manifest, './') + * ``` + * @param fetchWeightsFunction The function used for fetching the weight files. + * @returns Weight loading function. + */ + function weightsLoaderFactory(fetchWeightsFunction) { + var _this = this; + return function (manifest, filePathPrefix, weightNames) { + if (filePathPrefix === void 0) { filePathPrefix = ''; } + return __awaiter(_this, void 0, void 0, function () { + var groupIndicesToFetchMap, groupWeightsToFetch, weightsFound, allManifestWeightNames, weightsNotFound, groupIndicesToFetch, fetchUrls, buffers, weightsTensorMap, bufferIndexOffset; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + groupIndicesToFetchMap = manifest.map(function () { return false; }); + groupWeightsToFetch = {}; + weightsFound = weightNames != null ? weightNames.map(function () { return false; }) : []; + allManifestWeightNames = []; + manifest.forEach(function (manifestGroupConfig, groupIndex) { + var groupOffset = 0; + manifestGroupConfig.weights.forEach(function (weightsEntry) { + var rawDtype = ('quantization' in weightsEntry) ? + weightsEntry.quantization.dtype : + weightsEntry.dtype; + var weightsBytes = DTYPE_VALUE_SIZE_MAP[rawDtype] * + sizeFromShape(weightsEntry.shape); + var enqueueWeightsForFetchingFn = function () { + groupIndicesToFetchMap[groupIndex] = true; + if (groupWeightsToFetch[groupIndex] == null) { + groupWeightsToFetch[groupIndex] = []; + } + groupWeightsToFetch[groupIndex].push({ + manifestEntry: weightsEntry, + groupOffset: groupOffset, + sizeBytes: weightsBytes + }); + }; + if (weightNames != null) { + weightNames.forEach(function (weightName, weightIndex) { + if (weightName === weightsEntry.name) { + enqueueWeightsForFetchingFn(); + weightsFound[weightIndex] = true; + } + }); + } + else { + enqueueWeightsForFetchingFn(); + } + allManifestWeightNames.push(weightsEntry.name); + groupOffset += weightsBytes; + }); + }); + if (!weightsFound.every(function (found) { return found; })) { + weightsNotFound = weightNames.filter(function (_, i) { return !weightsFound[i]; }); + throw new Error("Could not find weights in manifest with names: " + + (weightsNotFound.join(', ') + ". \n") + + "Manifest JSON has weights with names: " + + (allManifestWeightNames.join(', ') + ".")); + } + groupIndicesToFetch = groupIndicesToFetchMap.reduce(function (accumulator, shouldFetch, i) { + if (shouldFetch) { + accumulator.push(i); + } + return accumulator; + }, []); + fetchUrls = []; + groupIndicesToFetch.forEach(function (i) { + manifest[i].paths.forEach(function (filepath) { + var fetchUrl = filePathPrefix + + (!filePathPrefix.endsWith('/') ? '/' : '') + filepath; + fetchUrls.push(fetchUrl); + }); + }); + return [4 /*yield*/, fetchWeightsFunction(fetchUrls)]; + case 1: + buffers = _a.sent(); + weightsTensorMap = {}; + bufferIndexOffset = 0; + groupIndicesToFetch.forEach(function (i) { + var numBuffers = manifest[i].paths.length; + var groupBytes = 0; + for (var i_1 = 0; i_1 < numBuffers; i_1++) { + groupBytes += buffers[bufferIndexOffset + i_1].byteLength; + } + // Create a buffer for the whole group. + var groupBuffer = new ArrayBuffer(groupBytes); + var groupByteBuffer = new Uint8Array(groupBuffer); + var groupBufferOffset = 0; + for (var i_2 = 0; i_2 < numBuffers; i_2++) { + var buffer = new Uint8Array(buffers[bufferIndexOffset + i_2]); + groupByteBuffer.set(buffer, groupBufferOffset); + groupBufferOffset += buffer.byteLength; + } + var weightsEntries = groupWeightsToFetch[i]; + weightsEntries.forEach(function (weightsEntry) { + var byteBuffer = groupBuffer.slice(weightsEntry.groupOffset, weightsEntry.groupOffset + weightsEntry.sizeBytes); + var nameToTensorMap = decodeWeights(byteBuffer, [weightsEntry.manifestEntry]); + for (var name_1 in nameToTensorMap) { + weightsTensorMap[name_1] = nameToTensorMap[name_1]; + } + }); + bufferIndexOffset += numBuffers; + }); + return [2 /*return*/, weightsTensorMap]; + } + }); + }); + }; + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var OCTET_STREAM_MIME_TYPE = 'application/octet-stream'; + var JSON_TYPE = 'application/json'; + var HTTPRequest = /** @class */ (function () { + function HTTPRequest(path, loadOptions) { + this.DEFAULT_METHOD = 'POST'; + if (loadOptions == null) { + loadOptions = {}; + } + this.weightPathPrefix = loadOptions.weightPathPrefix; + this.onProgress = loadOptions.onProgress; + if (loadOptions.fetchFunc != null) { + assert(typeof loadOptions.fetchFunc === 'function', function () { return 'Must pass a function that matches the signature of ' + + '`fetch` (see ' + + 'https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)'; }); + this.fetch = loadOptions.fetchFunc; + } + else { + this.fetch = env().platform.fetch; + } + assert(path != null && path.length > 0, function () { return 'URL path for http must not be null, undefined or ' + + 'empty.'; }); + if (Array.isArray(path)) { + assert(path.length === 2, function () { return 'URL paths for http must have a length of 2, ' + + ("(actual length is " + path.length + ")."); }); + } + this.path = path; + if (loadOptions.requestInit != null && + loadOptions.requestInit.body != null) { + throw new Error('requestInit is expected to have no pre-existing body, but has one.'); + } + this.requestInit = loadOptions.requestInit || {}; + } + HTTPRequest.prototype.save = function (modelArtifacts) { + return __awaiter(this, void 0, void 0, function () { + var init, weightsManifest, modelTopologyAndWeightManifest, response; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (modelArtifacts.modelTopology instanceof ArrayBuffer) { + throw new Error('BrowserHTTPRequest.save() does not support saving model topology ' + + 'in binary formats yet.'); + } + init = Object.assign({ method: this.DEFAULT_METHOD }, this.requestInit); + init.body = new FormData(); + weightsManifest = [{ + paths: ['./model.weights.bin'], + weights: modelArtifacts.weightSpecs, + }]; + modelTopologyAndWeightManifest = { + modelTopology: modelArtifacts.modelTopology, + format: modelArtifacts.format, + generatedBy: modelArtifacts.generatedBy, + convertedBy: modelArtifacts.convertedBy, + userDefinedMetadata: modelArtifacts.userDefinedMetadata, + weightsManifest: weightsManifest + }; + init.body.append('model.json', new Blob([JSON.stringify(modelTopologyAndWeightManifest)], { type: JSON_TYPE }), 'model.json'); + if (modelArtifacts.weightData != null) { + init.body.append('model.weights.bin', new Blob([modelArtifacts.weightData], { type: OCTET_STREAM_MIME_TYPE }), 'model.weights.bin'); + } + return [4 /*yield*/, this.fetch(this.path, init)]; + case 1: + response = _a.sent(); + if (response.ok) { + return [2 /*return*/, { + modelArtifactsInfo: getModelArtifactsInfoForJSON(modelArtifacts), + responses: [response], + }]; + } + else { + throw new Error("BrowserHTTPRequest.save() failed due to HTTP response status " + + (response.status + ".")); + } + } + }); + }); + }; + /** + * Load model artifacts via HTTP request(s). + * + * See the documentation to `tf.io.http` for details on the saved + * artifacts. + * + * @returns The loaded model artifacts (if loading succeeds). + */ + HTTPRequest.prototype.load = function () { + return __awaiter(this, void 0, void 0, function () { + var modelConfigRequest, modelConfig, e_1, message, modelTopology, weightsManifest, generatedBy, convertedBy, format, userDefinedMetadata, weightSpecs, weightData, results; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, this.fetch(this.path, this.requestInit)]; + case 1: + modelConfigRequest = _a.sent(); + if (!modelConfigRequest.ok) { + throw new Error("Request to " + this.path + " failed with status code " + + (modelConfigRequest.status + ". Please verify this URL points to ") + + "the model JSON of the model to load."); + } + _a.label = 2; + case 2: + _a.trys.push([2, 4, , 5]); + return [4 /*yield*/, modelConfigRequest.json()]; + case 3: + modelConfig = _a.sent(); + return [3 /*break*/, 5]; + case 4: + e_1 = _a.sent(); + message = "Failed to parse model JSON of response from " + this.path + "."; + // TODO(nsthorat): Remove this after some time when we're comfortable that + // .pb files are mostly gone. + if (this.path.endsWith('.pb')) { + message += ' Your path contains a .pb file extension. ' + + 'Support for .pb models have been removed in TensorFlow.js 1.0 ' + + 'in favor of .json models. You can re-convert your Python ' + + 'TensorFlow model using the TensorFlow.js 1.0 conversion scripts ' + + 'or you can convert your.pb models with the \'pb2json\'' + + 'NPM script in the tensorflow/tfjs-converter repository.'; + } + else { + message += ' Please make sure the server is serving valid ' + + 'JSON for this request.'; + } + throw new Error(message); + case 5: + modelTopology = modelConfig.modelTopology; + weightsManifest = modelConfig.weightsManifest; + generatedBy = modelConfig.generatedBy; + convertedBy = modelConfig.convertedBy; + format = modelConfig.format; + userDefinedMetadata = modelConfig.userDefinedMetadata; + // We do not allow both modelTopology and weightsManifest to be missing. + if (modelTopology == null && weightsManifest == null) { + throw new Error("The JSON from HTTP path " + this.path + " contains neither model " + + "topology or manifest for weights."); + } + if (!(weightsManifest != null)) return [3 /*break*/, 7]; + return [4 /*yield*/, this.loadWeights(weightsManifest)]; + case 6: + results = _a.sent(); + weightSpecs = results[0], weightData = results[1]; + _a.label = 7; + case 7: return [2 /*return*/, { + modelTopology: modelTopology, + weightSpecs: weightSpecs, + weightData: weightData, + userDefinedMetadata: userDefinedMetadata, + generatedBy: generatedBy, + convertedBy: convertedBy, + format: format + }]; + } + }); + }); + }; + HTTPRequest.prototype.loadWeights = function (weightsManifest) { + return __awaiter(this, void 0, void 0, function () { + var weightPath, _a, prefix, suffix, pathPrefix, weightSpecs, _i, weightsManifest_1, entry, fetchURLs, buffers; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + weightPath = Array.isArray(this.path) ? this.path[1] : this.path; + _a = parseUrl(weightPath), prefix = _a[0], suffix = _a[1]; + pathPrefix = this.weightPathPrefix || prefix; + weightSpecs = []; + for (_i = 0, weightsManifest_1 = weightsManifest; _i < weightsManifest_1.length; _i++) { + entry = weightsManifest_1[_i]; + weightSpecs.push.apply(weightSpecs, entry.weights); + } + fetchURLs = []; + weightsManifest.forEach(function (weightsGroup) { + weightsGroup.paths.forEach(function (path) { + fetchURLs.push(pathPrefix + path + suffix); + }); + }); + return [4 /*yield*/, loadWeightsAsArrayBuffer(fetchURLs, { + requestInit: this.requestInit, + fetchFunc: this.fetch, + onProgress: this.onProgress + })]; + case 1: + buffers = _b.sent(); + return [2 /*return*/, [weightSpecs, concatenateArrayBuffers(buffers)]]; + } + }); + }); + }; + HTTPRequest.URL_SCHEME_REGEX = /^https?:\/\//; + return HTTPRequest; + }()); + /** + * Extract the prefix and suffix of the url, where the prefix is the path before + * the last file, and suffix is the search params after the last file. + * ``` + * const url = 'http://tfhub.dev/model/1/tensorflowjs_model.pb?tfjs-format=file' + * [prefix, suffix] = parseUrl(url) + * // prefix = 'http://tfhub.dev/model/1/' + * // suffix = '?tfjs-format=file' + * ``` + * @param url the model url to be parsed. + */ + function parseUrl(url) { + var lastSlash = url.lastIndexOf('/'); + var lastSearchParam = url.lastIndexOf('?'); + var prefix = url.substring(0, lastSlash); + var suffix = lastSearchParam > lastSlash ? url.substring(lastSearchParam) : ''; + return [prefix + '/', suffix]; + } + function isHTTPScheme(url) { + return url.match(HTTPRequest.URL_SCHEME_REGEX) != null; + } + var httpRouter = function (url, loadOptions) { + if (typeof fetch === 'undefined' && + (loadOptions == null || loadOptions.fetchFunc == null)) { + // `http` uses `fetch` or `node-fetch`, if one wants to use it in + // an environment that is not the browser or node they have to setup a + // global fetch polyfill. + return null; + } + else { + var isHTTP = true; + if (Array.isArray(url)) { + isHTTP = url.every(function (urlItem) { return isHTTPScheme(urlItem); }); + } + else { + isHTTP = isHTTPScheme(url); + } + if (isHTTP) { + return http(url, loadOptions); + } + } + return null; + }; + IORouterRegistry.registerSaveRouter(httpRouter); + IORouterRegistry.registerLoadRouter(httpRouter); + /** + * Creates an IOHandler subtype that sends model artifacts to HTTP server. + * + * An HTTP request of the `multipart/form-data` mime type will be sent to the + * `path` URL. The form data includes artifacts that represent the topology + * and/or weights of the model. In the case of Keras-style `tf.Model`, two + * blobs (files) exist in form-data: + * - A JSON file consisting of `modelTopology` and `weightsManifest`. + * - A binary weights file consisting of the concatenated weight values. + * These files are in the same format as the one generated by + * [tfjs_converter](https://js.tensorflow.org/tutorials/import-keras.html). + * + * The following code snippet exemplifies the client-side code that uses this + * function: + * + * ```js + * const model = tf.sequential(); + * model.add( + * tf.layers.dense({units: 1, inputShape: [100], activation: 'sigmoid'})); + * + * const saveResult = await model.save(tf.io.http( + * 'http://model-server:5000/upload', {requestInit: {method: 'PUT'}})); + * console.log(saveResult); + * ``` + * + * If the default `POST` method is to be used, without any custom parameters + * such as headers, you can simply pass an HTTP or HTTPS URL to `model.save`: + * + * ```js + * const saveResult = await model.save('http://model-server:5000/upload'); + * ``` + * + * The following GitHub Gist + * https://gist.github.com/dsmilkov/1b6046fd6132d7408d5257b0976f7864 + * implements a server based on [flask](https://github.com/pallets/flask) that + * can receive the request. Upon receiving the model artifacts via the requst, + * this particular server reconsistutes instances of [Keras + * Models](https://keras.io/models/model/) in memory. + * + * + * @param path A URL path to the model. + * Can be an absolute HTTP path (e.g., + * 'http://localhost:8000/model-upload)') or a relative path (e.g., + * './model-upload'). + * @param requestInit Request configurations to be used when sending + * HTTP request to server using `fetch`. It can contain fields such as + * `method`, `credentials`, `headers`, `mode`, etc. See + * https://developer.mozilla.org/en-US/docs/Web/API/Request/Request + * for more information. `requestInit` must not have a body, because the + * body will be set by TensorFlow.js. File blobs representing the model + * topology (filename: 'model.json') and the weights of the model (filename: + * 'model.weights.bin') will be appended to the body. If `requestInit` has a + * `body`, an Error will be thrown. + * @param loadOptions Optional configuration for the loading. It includes the + * following fields: + * - weightPathPrefix Optional, this specifies the path prefix for weight + * files, by default this is calculated from the path param. + * - fetchFunc Optional, custom `fetch` function. E.g., in Node.js, + * the `fetch` from node-fetch can be used here. + * - onProgress Optional, progress callback function, fired periodically + * before the load is completed. + * @returns An instance of `IOHandler`. + */ + /** + * @doc { + * heading: 'Models', + * subheading: 'Loading', + * namespace: 'io', + * ignoreCI: true + * } + */ + function http(path, loadOptions) { + return new HTTPRequest(path, loadOptions); + } + /** + * Deprecated. Use `tf.io.http`. + * @param path + * @param loadOptions + */ + function browserHTTPRequest(path, loadOptions) { + return http(path, loadOptions); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var PassthroughLoader = /** @class */ (function () { + function PassthroughLoader(modelArtifacts) { + this.modelArtifacts = modelArtifacts; + } + PassthroughLoader.prototype.load = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, this.modelArtifacts]; + }); + }); + }; + return PassthroughLoader; + }()); + var PassthroughSaver = /** @class */ (function () { + function PassthroughSaver(saveHandler) { + this.saveHandler = saveHandler; + } + PassthroughSaver.prototype.save = function (modelArtifacts) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, this.saveHandler(modelArtifacts)]; + }); + }); + }; + return PassthroughSaver; + }()); + /** + * Creates an IOHandler that loads model artifacts from memory. + * + * When used in conjunction with `tf.loadLayersModel`, an instance of + * `tf.LayersModel` (Keras-style) can be constructed from the loaded artifacts. + * + * ```js + * const model = await tf.loadLayersModel(tf.io.fromMemory( + * modelTopology, weightSpecs, weightData)); + * ``` + * + * @param modelArtifacts a object containing model topology (i.e., parsed from + * the JSON format). + * @param weightSpecs An array of `WeightsManifestEntry` objects describing the + * names, shapes, types, and quantization of the weight data. + * @param weightData A single `ArrayBuffer` containing the weight data, + * concatenated in the order described by the weightSpecs. + * @param trainingConfig Model training configuration. Optional. + * + * @returns A passthrough `IOHandler` that simply loads the provided data. + */ + function fromMemory(modelArtifacts, weightSpecs, weightData, trainingConfig) { + if (arguments.length === 1) { + var isModelArtifacts = modelArtifacts.modelTopology != null || + modelArtifacts.weightSpecs != null; + if (isModelArtifacts) { + return new PassthroughLoader(modelArtifacts); + } + else { + // Legacy support: with only modelTopology. + // TODO(cais): Remove this deprecated API. + console.warn('Please call tf.io.fromMemory() with only one argument. ' + + 'The argument should be of type ModelArtifacts. ' + + 'The multi-argument signature of tf.io.fromMemory() has been ' + + 'deprecated and will be removed in a future release.'); + return new PassthroughLoader({ modelTopology: modelArtifacts }); + } + } + else { + // Legacy support. + // TODO(cais): Remove this deprecated API. + console.warn('Please call tf.io.fromMemory() with only one argument. ' + + 'The argument should be of type ModelArtifacts. ' + + 'The multi-argument signature of tf.io.fromMemory() has been ' + + 'deprecated and will be removed in a future release.'); + return new PassthroughLoader({ + modelTopology: modelArtifacts, + weightSpecs: weightSpecs, + weightData: weightData, + trainingConfig: trainingConfig + }); + } + } + /** + * Creates an IOHandler that passes saved model artifacts to a callback. + * + * ```js + * function handleSave(artifacts) { + * // ... do something with the artifacts ... + * return {modelArtifactsInfo: {...}, ...}; + * } + * + * const saveResult = model.save(tf.io.withSaveHandler(handleSave)); + * ``` + * + * @param saveHandler A function that accepts a `ModelArtifacts` and returns a + * `SaveResult`. + */ + function withSaveHandler(saveHandler) { + return new PassthroughSaver(saveHandler); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + + var io = { + __proto__: null, + browserFiles: browserFiles, + browserHTTPRequest: browserHTTPRequest, + concatenateArrayBuffers: concatenateArrayBuffers, + decodeWeights: decodeWeights, + encodeWeights: encodeWeights, + fromMemory: fromMemory, + getLoadHandlers: getLoadHandlers, + getModelArtifactsInfoForJSON: getModelArtifactsInfoForJSON, + getSaveHandlers: getSaveHandlers, + http: http, + isHTTPScheme: isHTTPScheme, + loadWeights: loadWeights, + registerLoadRouter: registerLoadRouter, + registerSaveRouter: registerSaveRouter, + weightsLoaderFactory: weightsLoaderFactory, + withSaveHandler: withSaveHandler, + copyModel: copyModel, + listModels: listModels, + moveModel: moveModel, + removeModel: removeModel + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates a one-hot `tf.Tensor`. The locations represented by `indices` take + * value `onValue` (defaults to 1), while all other locations take value + * `offValue` (defaults to 0). If `indices` is rank `R`, the output has rank + * `R+1` with the last axis of size `depth`. + * + * ```js + * tf.oneHot(tf.tensor1d([0, 1], 'int32'), 3).print(); + * ``` + * + * @param indices `tf.Tensor` of indices with dtype `int32`. + * @param depth The depth of the one hot dimension. + * @param onValue A number used to fill in the output when the index matches + * the location. + * @param offValue A number used to fill in the output when the index does + * not match the location. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function oneHot_(indices, depth, onValue, offValue) { + if (onValue === void 0) { onValue = 1; } + if (offValue === void 0) { offValue = 0; } + if (depth < 2) { + throw new Error("Error in oneHot: depth must be >=2, but it is " + depth); + } + var $indices = convertToTensor(indices, 'indices', 'oneHot', 'int32'); + var outShape = $indices.shape.concat([depth]); + var forward = function (backend, save) { + save([$indices]); + return reshape(backend.oneHot($indices.flatten(), depth, onValue, offValue), outShape); + }; + var inputs = { indices: $indices }; + var attrs = { depth: depth, onValue: onValue, offValue: offValue }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, OneHot, attrs); + } + var oneHot = op({ oneHot_: oneHot_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the confusion matrix from true labels and predicted labels. + * + * ```js + * const labels = tf.tensor1d([0, 1, 2, 1, 0], 'int32'); + * const predictions = tf.tensor1d([0, 2, 2, 1, 0], 'int32'); + * const numClasses = 3; + * const out = tf.math.confusionMatrix(labels, predictions, numClasses); + * out.print(); + * // Expected output matrix: + * // [[2, 0, 0], + * // [0, 1, 1], + * // [0, 0, 1]] + * ``` + * + * @param labels The target labels, assumed to be 0-based integers + * for the classes. The shape is `[numExamples]`, where + * `numExamples` is the number of examples included. + * @param predictions The predicted classes, assumed to be + * 0-based integers for the classes. Must have the same shape as `labels`. + * @param numClasses Number of all classes, as an integer. + * Its value must be larger than the largest element in `labels` and + * `predictions`. + * @returns The confusion matrix as a int32-type 2D tensor. The value at + * row `r` and column `c` is the number of times examples of actual class + * `r` were predicted as class `c`. + */ + /** @doc {heading: 'Operations', subheading: 'Evaluation'} */ + function confusionMatrix_(labels, predictions, numClasses) { + var $labels = convertToTensor(labels, 'labels', 'confusionMatrix'); + var $predictions = convertToTensor(predictions, 'predictions', 'confusionMatrix'); + assert(numClasses == null || numClasses > 0 && Number.isInteger(numClasses), function () { return "If provided, numClasses must be a positive integer, " + + ("but got " + numClasses); }); + assert($labels.rank === 1, function () { return "Expected the rank of labels to be 1, but got " + $labels.rank; }); + assert($predictions.rank === 1, function () { return "Expected the rank of predictions to be 1, " + + ("but got " + $predictions.rank); }); + assert($labels.shape[0] === $predictions.shape[0], function () { return "Mismatch in the number of examples: " + + ($labels.shape[0] + " vs. " + $predictions.shape[0] + ". ") + + "Labels and predictions should have the same number of elements."; }); + assert(numClasses > 0 && Number.isInteger(numClasses), function () { return "numClasses is required to be a positive integer, but got " + + ("" + numClasses); }); + // TODO(cais): In the future, if oneHot supports tensors inputs for + // `numClasses`, `confusionMatrix` can make `numClasses` optional. + var oneHotLabels = oneHot($labels.asType('int32'), numClasses); + var oneHotPredictions = oneHot($predictions.asType('int32'), numClasses); + var oneHotLabelsT = oneHotLabels.transpose(); + return oneHotLabelsT.matMul(oneHotPredictions).asType('int32'); + } + var confusionMatrix = op({ confusionMatrix_: confusionMatrix_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + + var math = { + __proto__: null, + confusionMatrix: confusionMatrix + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates rank-3 `tf.Tensor` with the provided values, shape and dtype. + * + * The same functionality can be achieved with `tf.tensor`, but in general + * we recommend using `tf.tensor3d` as it makes the code more readable. + * + * ```js + * // Pass a nested array. + * tf.tensor3d([[[1], [2]], [[3], [4]]]).print(); + * ``` + * ```js + * // Pass a flat array and specify a shape. + * tf.tensor3d([1, 2, 3, 4], [2, 2, 1]).print(); + * ``` + * + * @param values The values of the tensor. Can be nested array of numbers, + * or a flat array, or a `TypedArray`. + * @param shape The shape of the tensor. If not provided, it is inferred from + * `values`. + * @param dtype The data type. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function tensor3d(values, shape, dtype) { + assertNonNull(values); + if (shape != null && shape.length !== 3) { + throw new Error('tensor3d() requires shape to have three numbers'); + } + var inferredShape = inferShape(values, dtype); + if (inferredShape.length !== 3 && inferredShape.length !== 1) { + throw new Error('tensor3d() requires values to be number[][][] or flat/TypedArray'); + } + if (inferredShape.length === 1 && shape == null) { + throw new Error('tensor3d() requires shape to be provided when `values` ' + + 'are a flat array'); + } + return makeTensor(values, shape, inferredShape, dtype); + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var fromPixels2DContext; + /** + * Creates a `tf.Tensor` from an image. + * + * ```js + * const image = new ImageData(1, 1); + * image.data[0] = 100; + * image.data[1] = 150; + * image.data[2] = 200; + * image.data[3] = 255; + * + * tf.browser.fromPixels(image).print(); + * ``` + * + * @param pixels The input image to construct the tensor from. The + * supported image types are all 4-channel. You can also pass in an image + * object with following attributes: + * `{data: Uint8Array; width: number; height: number}` + * @param numChannels The number of channels of the output tensor. A + * numChannels value less than 4 allows you to ignore channels. Defaults to + * 3 (ignores alpha channel of input image). + */ + /** @doc {heading: 'Browser', namespace: 'browser', ignoreCI: true} */ + function fromPixels_(pixels, numChannels) { + if (numChannels === void 0) { numChannels = 3; } + // Sanity checks. + if (numChannels > 4) { + throw new Error('Cannot construct Tensor with more than 4 channels from pixels.'); + } + if (pixels == null) { + throw new Error('pixels passed to tf.browser.fromPixels() can not be null'); + } + var isPixelData = false; + var isImageData = false; + var isVideo = false; + var isImage = false; + var isCanvasLike = false; + if (pixels.data instanceof Uint8Array) { + isPixelData = true; + } + else if (typeof (ImageData) !== 'undefined' && pixels instanceof ImageData) { + isImageData = true; + } + else if (typeof (HTMLVideoElement) !== 'undefined' && + pixels instanceof HTMLVideoElement) { + isVideo = true; + } + else if (typeof (HTMLImageElement) !== 'undefined' && + pixels instanceof HTMLImageElement) { + isImage = true; + // tslint:disable-next-line: no-any + } + else if (pixels.getContext != null) { + isCanvasLike = true; + } + else { + throw new Error('pixels passed to tf.browser.fromPixels() must be either an ' + + "HTMLVideoElement, HTMLImageElement, HTMLCanvasElement, ImageData " + + "in browser, or OffscreenCanvas, ImageData in webworker" + + " or {data: Uint32Array, width: number, height: number}, " + + ("but was " + pixels.constructor.name)); + } + if (isVideo) { + var HAVE_CURRENT_DATA_READY_STATE = 2; + if (isVideo && + pixels.readyState < + HAVE_CURRENT_DATA_READY_STATE) { + throw new Error('The video element has not loaded data yet. Please wait for ' + + '`loadeddata` event on the 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 literal 0 HcmV?d00001 diff --git a/e2e/benchmarks/tfjs-backend-wasm-threaded-simd.wasm b/e2e/benchmarks/tfjs-backend-wasm-threaded-simd.wasm new file mode 100644 index 0000000000000000000000000000000000000000..4674086b3865c0ad51264aa3f8f7116550bdd8f7 GIT binary patch literal 234393 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
  • |w%FV-0aE+E&8hn}THE+3^7B)hyr zbxe*+MHi%(k)tj)w`tglm6bUrij64C3UL!flz{ccoLVRv-!mpUZg2|VtwaZMVKK^u#X>H4v)R-^gfbFD z(N+xI%b`xi$c=Kr$Zk(Xxo~WCPd;!Nm8xVIm5XA^uT4$irNuaGqU$g>!^^at4;z$* zpbW!iF&{S3EqAM7^J*LH((qv;sKGS3{YC+ao8t46zEuF%5Vi1bu@Lbi=-3RnYv%$6q*7t?G2x zTj(Ih#VVQ%rtcO^-xbq;1CmB?HIATYp}m#j>EAVJnkb$VjUa+DC&Ri-K{0}= z6_kyj3GTKLG{N0Af+iFc8_NdnUh*X$k-G~XjND!DU^>Nvk-H0t8@YQ$9JoBifv?r1 z0gmIqW7zAi*G&pJvcO4&Xu$#}6{4>#Cfg@tfeRHZaE}YoJ;x}|mM3Dy0?(B5j0L{4 zoM$ZXbUDw2=#%9<6Qb`c=a~?FZ#mC|=%eL46QY;PdF)%epFCX7!`{80JXFqGSKfo= zyba}DEa&0T-cRl?=dtv8KiMzmomSpnId4mOX*rKL%c+Sr+XhTcw0D&^p@hyTZ$b&3 zRo;XWN|iS;Ooz&w7^a!>CWh&`e3(!WbD$jZ?W^LqIug9$Q zJnJhlYc0=uF;3YEZT(WrGCP53tT>BvQ-Ni@5=#{d`_-6LXzbTwRw0sJk6DGh{7TFk zQ`(I{!a`!c6tnJ;$h!ZH?J*vm&3R#oeQUt537S{7H^>j?)`FvVZXw>s3oX!7OmuboB_n;a7w3<-eB7g~1#}LajpzWB< zgnByI0=6sz6Y6#_7VNl4t20hbDlt&?2xf<~!GxMx#S z%IzLuUWF}F7QQ#vBx;>>>?AX4^Fn7u-Cd}xTvHb+D_6^f%F1%ANMKB6{;yi?GIGs047nC%i|)H0B*Imd@SF%v#e$v_q3E~-5OP!9IM>-Z^Y#I zUs~w)y4d(F)1h-}A=M-Q6jD77j6$eKjw<*t4wZrrBac;>4$Ex!mcdZF1m%dfFcTgx zybDBoQZwOa8wl^n_0_`r>)G5_=9;euBVV;??|5NVblXWyd*3h9UhKBFOmvD}dCNrS z$cNzmILQw{gRqR4lLlz;mWhsN(Qh0RU0KY%WtdZ}?^`xyQQ_;&dMa2$F z86O+H$bTOGac=277&?diK;!ECt^LKD-C%C1UIyO_ivCVTlZtqa~F{0k} zY>S;~n*7cms-=nI�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 Cnnj8L literal 0 HcmV?d00001 diff --git a/e2e/benchmarks/tfjs-backend-wasm-threaded.wasm b/e2e/benchmarks/tfjs-backend-wasm-threaded.wasm deleted file mode 100644 index fef876d698c1429c1f6d0f270797ddd05d9d676a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 175880 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 diff --git a/tfjs-backend-wasm/scripts/build-wasm.sh b/tfjs-backend-wasm/scripts/build-wasm.sh index 04a3faea228..90d1c8bebb1 100755 --- a/tfjs-backend-wasm/scripts/build-wasm.sh +++ b/tfjs-backend-wasm/scripts/build-wasm.sh @@ -31,7 +31,7 @@ cp -f bazel-bin/src/cc/tfjs-backend-wasm-simd.js \ wasm-out/ # Threaded + SIMD build. -yarn bazel build -c opt //src/cc:tfjs-backend-wasm-threaded-simd.js --config=wasm --copt="-msimd128" --copt="-pthread" +yarn bazel build -c opt //src/cc:tfjs-backend-wasm-threaded-simd.js --config=wasm --copt="-pthread" --copt="-msimd128" cp -f bazel-bin/src/cc/tfjs-backend-wasm-threaded-simd.js \ bazel-bin/src/cc/tfjs-backend-wasm-threaded-simd.worker.js \ bazel-bin/src/cc/tfjs-backend-wasm-threaded-simd.wasm \ diff --git a/tfjs-backend-wasm/src/backend_wasm.ts b/tfjs-backend-wasm/src/backend_wasm.ts index ab25a6a8ff1..6350c1ca32d 100644 --- a/tfjs-backend-wasm/src/backend_wasm.ts +++ b/tfjs-backend-wasm/src/backend_wasm.ts @@ -242,8 +242,8 @@ export async function init(): Promise<{wasm: BackendWasmModule}> { if (threadsSupported && simdSupported) { wasm = wasmFactoryThreadedSimd(factoryConfig); wasm.mainScriptUrlOrBlob = new Blob( - [`var _scriptDir = undefined; var WasmBackendModule = ` + - wasmFactory.toString()], + [`var _scriptDir = undefined; var WasmBackendModuleSimd = ` + + wasmFactoryThreadedSimd.toString()], {type: 'text/javascript'}); } else if (simdSupported) { wasm = wasmFactorySimd(factoryConfig); From 3ee07cc67b1213421a53665d4f92a688e607661c Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 22 Jul 2020 07:56:15 -0400 Subject: [PATCH 10/70] fix feature test --- e2e/benchmarks/tf-backend-wasm.js | 4 ++-- tfjs-backend-wasm/src/flags_wasm.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/e2e/benchmarks/tf-backend-wasm.js b/e2e/benchmarks/tf-backend-wasm.js index d01b674ea4d..3e2ffe0b9b3 100644 --- a/e2e/benchmarks/tf-backend-wasm.js +++ b/e2e/benchmarks/tf-backend-wasm.js @@ -3039,8 +3039,8 @@ // https://groups.google.com/forum/#!msg/mozilla.dev.platform/IHkBZlHETpA/dwsMNchWEQAJ new MessageChannel().port1.postMessage(new SharedArrayBuffer(1)); return WebAssembly.validate(new Uint8Array([ - 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, - 0, 3, 2, 1, 0, 10, 6, 1, 4, 0, 18, 0, 11 + 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 5, + 4, 1, 3, 1, 1, 10, 11, 1, 9, 0, 65, 0, 254, 16, 2, 0, 26, 11 ])); } catch (e) { diff --git a/tfjs-backend-wasm/src/flags_wasm.ts b/tfjs-backend-wasm/src/flags_wasm.ts index 592f3baddcf..5187beb3708 100644 --- a/tfjs-backend-wasm/src/flags_wasm.ts +++ b/tfjs-backend-wasm/src/flags_wasm.ts @@ -39,8 +39,8 @@ ENV.registerFlag('WASM_HAS_MULTITHREAD_SUPPORT', async () => { // https://groups.google.com/forum/#!msg/mozilla.dev.platform/IHkBZlHETpA/dwsMNchWEQAJ new MessageChannel().port1.postMessage(new SharedArrayBuffer(1)); return WebAssembly.validate(new Uint8Array([ - 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, - 0, 3, 2, 1, 0, 10, 6, 1, 4, 0, 18, 0, 11 + 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 5, + 4, 1, 3, 1, 1, 10, 11, 1, 9, 0, 65, 0, 254, 16, 2, 0, 26, 11 ])); } catch (e) { return false; From f075dde836f03c6db96d79edb7fba56f912f1f15 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 22 Jul 2020 08:46:26 -0400 Subject: [PATCH 11/70] clean --- tfjs-backend-wasm/README.md | 8 +++--- tfjs-backend-wasm/scripts/build-benchmark.sh | 1 - tfjs-backend-wasm/scripts/build-wasm.sh | 2 ++ .../scripts/create-worker-module.js | 28 +++++++++++++++++++ tfjs-backend-wasm/scripts/inline-worker.js | 7 ----- tfjs-backend-wasm/src/backend_wasm.ts | 2 +- 6 files changed, 35 insertions(+), 13 deletions(-) create mode 100755 tfjs-backend-wasm/scripts/create-worker-module.js delete mode 100644 tfjs-backend-wasm/scripts/inline-worker.js diff --git a/tfjs-backend-wasm/README.md b/tfjs-backend-wasm/README.md index 5549139c4b0..5cfbd204438 100644 --- a/tfjs-backend-wasm/README.md +++ b/tfjs-backend-wasm/README.md @@ -108,8 +108,8 @@ JS backend, and ~5.3-7.7X slower than the WebGL backend. -| MobileNet inference (ms) | WASM | WebGL | Plain JS | WASM + SIMD | -|--------------------------|-------|-------|----------|-------------| +| MobileNet inference (ms) | WASM | WebGL | Plain JS | WASM + SIMD | WASM + SIMD + threads +|--------------------------|-------|-------|----------|-------------|---------------------- | iPhone X | 147.1 | 20.3 | 941.3 | N/A | | iPhone XS | 140 | 18.1 | 426.4 | N/A | | Pixel 3 | 266.2 | 77.3 | 2345.2 | N/A | @@ -128,8 +128,8 @@ the device). -| Face Detector inference (ms) | WASM | WebGL | Plain JS | WASM + SIMD | -|------------------------------|------|-------|----------|-------------| +| Face Detector inference (ms) | WASM | WebGL | Plain JS | WASM + SIMD | WASM + SIMD + threads +|------------------------------|------|-------|----------|-------------|---------------------- | iPhone X | 22.4 | 13.5 | 318 | N/A | | iPhone XS | 21.4 | 10.5 | 176.9 | N/A | | Pixel 3 | 40.7 | 31.8 | 535.2 | N/A | diff --git a/tfjs-backend-wasm/scripts/build-benchmark.sh b/tfjs-backend-wasm/scripts/build-benchmark.sh index 5b91fb8023d..dfe81513c97 100755 --- a/tfjs-backend-wasm/scripts/build-benchmark.sh +++ b/tfjs-backend-wasm/scripts/build-benchmark.sh @@ -1,5 +1,4 @@ yarn build -node ./scripts/inline-worker.js yarn rollup -c cp dist/tf-backend-wasm.js ../e2e/benchmarks/ diff --git a/tfjs-backend-wasm/scripts/build-wasm.sh b/tfjs-backend-wasm/scripts/build-wasm.sh index 90d1c8bebb1..ec8482e1fb7 100755 --- a/tfjs-backend-wasm/scripts/build-wasm.sh +++ b/tfjs-backend-wasm/scripts/build-wasm.sh @@ -37,6 +37,8 @@ cp -f bazel-bin/src/cc/tfjs-backend-wasm-threaded-simd.js \ bazel-bin/src/cc/tfjs-backend-wasm-threaded-simd.wasm \ wasm-out/ +node ./scripts/create-worker-module.js + mkdir -p dist # Only copying binary into dist because the js module gets bundled. cp wasm-out/*.wasm dist/ diff --git a/tfjs-backend-wasm/scripts/create-worker-module.js b/tfjs-backend-wasm/scripts/create-worker-module.js new file mode 100755 index 00000000000..4cb511463e3 --- /dev/null +++ b/tfjs-backend-wasm/scripts/create-worker-module.js @@ -0,0 +1,28 @@ +/** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + +/** + * This file creates a TypeScript module that exports the contents of the Emscripten-generated WASM worker script so that it can be inlined by the tf-backend-wasm bundle. + */ + +const fs = require('fs'); + +const workerContents = fs.readFileSync('./wasm-out/tfjs-backend-wasm-threaded-simd.worker.js', "utf8"); + +const fileContents = `export const wasmWorkerContents = '${workerContents.trim()}';`; + +fs.writeFileSync('./wasm-out/tfjs-backend-wasm-threaded-simd.worker.ts', fileContents); diff --git a/tfjs-backend-wasm/scripts/inline-worker.js b/tfjs-backend-wasm/scripts/inline-worker.js deleted file mode 100644 index d7a42721f15..00000000000 --- a/tfjs-backend-wasm/scripts/inline-worker.js +++ /dev/null @@ -1,7 +0,0 @@ -const fs = require('fs'); - -const workerContents = fs.readFileSync('./wasm-out/tfjs-backend-wasm-threaded-simd.worker.js', "utf8"); - -const fileContents = `export const wasmWorkerContents = '${workerContents.trim()}';`; - -fs.writeFileSync('./wasm-out/tfjs-backend-wasm-threaded-simd.worker.ts', fileContents); diff --git a/tfjs-backend-wasm/src/backend_wasm.ts b/tfjs-backend-wasm/src/backend_wasm.ts index 6350c1ca32d..e8beb12e8fd 100644 --- a/tfjs-backend-wasm/src/backend_wasm.ts +++ b/tfjs-backend-wasm/src/backend_wasm.ts @@ -22,7 +22,7 @@ import {BackendWasmModule, WasmFactoryConfig} from '../wasm-out/tfjs-backend-was import wasmFactorySimd, {BackendWasmModuleSimd} from '../wasm-out/tfjs-backend-wasm-simd.js'; import wasmFactoryThreadedSimd from '../wasm-out/tfjs-backend-wasm-threaded-simd.js'; // @ts-ignore -import {wasmWorkerContents} from '../wasm-out/tfjs-backend-wasm-threaded-simd.worker.js'; +import {wasmWorkerContents} from '../wasm-out/tfjs-backend-wasm-threaded-simd.worker.ts'; import wasmFactory from '../wasm-out/tfjs-backend-wasm.js'; const WASM_PRIORITY = 2; From 5054af050a57eb60b2867da67f2263a50446b360 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 22 Jul 2020 09:46:09 -0400 Subject: [PATCH 12/70] 2 builds --- tfjs-backend-wasm/karma.conf.js | 2 +- tfjs-backend-wasm/scripts/build-benchmark.sh | 2 +- tfjs-backend-wasm/scripts/build-wasm.sh | 8 ++++---- tfjs-backend-wasm/src/backend_wasm.ts | 9 +++++---- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/tfjs-backend-wasm/karma.conf.js b/tfjs-backend-wasm/karma.conf.js index 7eb551002fc..0287ccc85ae 100644 --- a/tfjs-backend-wasm/karma.conf.js +++ b/tfjs-backend-wasm/karma.conf.js @@ -22,7 +22,7 @@ const karmaTypescriptConfig = { sourceMap: true, // Ignore the import of the `worker_threads` package used in a core test // meant to run in node. - exclude: ['worker_threads'], + exclude: ['worker_threads', 'perf_hooks'], // worker_node_test in tfjs-core contains a conditional require statement // that confuses the bundler of karma-typescript. ignore: ['./worker_node_test'], diff --git a/tfjs-backend-wasm/scripts/build-benchmark.sh b/tfjs-backend-wasm/scripts/build-benchmark.sh index dfe81513c97..f9635006b24 100755 --- a/tfjs-backend-wasm/scripts/build-benchmark.sh +++ b/tfjs-backend-wasm/scripts/build-benchmark.sh @@ -3,5 +3,5 @@ yarn rollup -c cp dist/tf-backend-wasm.js ../e2e/benchmarks/ cp wasm-out/tfjs-backend-wasm.wasm ../e2e/benchmarks/ -cp wasm-out/tfjs-backend-wasm-simd.wasm ../e2e/benchmarks/ +# cp wasm-out/tfjs-backend-wasm-simd.wasm ../e2e/benchmarks/ cp wasm-out/tfjs-backend-wasm-threaded-simd.wasm ../e2e/benchmarks/ diff --git a/tfjs-backend-wasm/scripts/build-wasm.sh b/tfjs-backend-wasm/scripts/build-wasm.sh index ec8482e1fb7..bc45ffe0e33 100755 --- a/tfjs-backend-wasm/scripts/build-wasm.sh +++ b/tfjs-backend-wasm/scripts/build-wasm.sh @@ -25,10 +25,10 @@ cp -f bazel-bin/src/cc/tfjs-backend-wasm.js \ wasm-out/ # # SIMD build. -yarn bazel build -c opt //src/cc:tfjs-backend-wasm-simd.js --config=wasm --copt="-msimd128" -cp -f bazel-bin/src/cc/tfjs-backend-wasm-simd.js \ - bazel-bin/src/cc/tfjs-backend-wasm-simd.wasm \ - wasm-out/ +# yarn bazel build -c opt //src/cc:tfjs-backend-wasm-simd.js --config=wasm --copt="-msimd128" +# cp -f bazel-bin/src/cc/tfjs-backend-wasm-simd.js \ +# bazel-bin/src/cc/tfjs-backend-wasm-simd.wasm \ +# wasm-out/ # Threaded + SIMD build. yarn bazel build -c opt //src/cc:tfjs-backend-wasm-threaded-simd.js --config=wasm --copt="-pthread" --copt="-msimd128" diff --git a/tfjs-backend-wasm/src/backend_wasm.ts b/tfjs-backend-wasm/src/backend_wasm.ts index e8beb12e8fd..b557d9d9804 100644 --- a/tfjs-backend-wasm/src/backend_wasm.ts +++ b/tfjs-backend-wasm/src/backend_wasm.ts @@ -19,7 +19,8 @@ import './flags_wasm'; import {backend_util, BackendTimingInfo, DataStorage, DataType, engine, env, KernelBackend, registerBackend, TensorInfo, util} from '@tensorflow/tfjs-core'; import {BackendWasmModule, WasmFactoryConfig} from '../wasm-out/tfjs-backend-wasm'; -import wasmFactorySimd, {BackendWasmModuleSimd} from '../wasm-out/tfjs-backend-wasm-simd.js'; +// import wasmFactorySimd, {BackendWasmModuleSimd} from +// '../wasm-out/tfjs-backend-wasm-simd.js'; import wasmFactoryThreadedSimd from '../wasm-out/tfjs-backend-wasm-threaded-simd.js'; // @ts-ignore import {wasmWorkerContents} from '../wasm-out/tfjs-backend-wasm-threaded-simd.worker.ts'; @@ -238,15 +239,15 @@ export async function init(): Promise<{wasm: BackendWasmModule}> { factoryConfig.instantiateWasm = createInstantiateWasmFunc(wasmPath); } } - let wasm: BackendWasmModule|BackendWasmModuleSimd; + let wasm: BackendWasmModule; if (threadsSupported && simdSupported) { wasm = wasmFactoryThreadedSimd(factoryConfig); wasm.mainScriptUrlOrBlob = new Blob( [`var _scriptDir = undefined; var WasmBackendModuleSimd = ` + wasmFactoryThreadedSimd.toString()], {type: 'text/javascript'}); - } else if (simdSupported) { - wasm = wasmFactorySimd(factoryConfig); + // } else if (simdSupported) { + // wasm = wasmFactorySimd(factoryConfig); } else { wasm = wasmFactory(factoryConfig); } From 0819bd7563a3622b3e7100fddee70a882fac5ec2 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 22 Jul 2020 09:48:40 -0400 Subject: [PATCH 13/70] redcue build --- tfjs-backend-wasm/src/cc/BUILD | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/tfjs-backend-wasm/src/cc/BUILD b/tfjs-backend-wasm/src/cc/BUILD index 9651aa13cb3..c4da0713cee 100644 --- a/tfjs-backend-wasm/src/cc/BUILD +++ b/tfjs-backend-wasm/src/cc/BUILD @@ -28,28 +28,6 @@ cc_binary( ], ) -cc_binary( - name = "tfjs-backend-wasm-simd.js", - srcs = ["backend.cc"] + KERNELS_WITH_KEEPALIVE, - linkopts = [ - "-s ALLOW_MEMORY_GROWTH=1", - "-s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]", - "-s DISABLE_EXCEPTION_CATCHING=1", - "-s FILESYSTEM=0", - "-s EXIT_RUNTIME=0", - "-s EXPORTED_FUNCTIONS='[\"_malloc\", \"_free\"]'", - "-s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'", - "-s MODULARIZE=1", - "-s EXPORT_NAME=WasmBackendModule", - "-s MALLOC=emmalloc", - "-s SIMD=1", - ], - deps = [ - ":all_kernels", - ":backend", - ], -) - cc_binary( name = "tfjs-backend-wasm-threaded-simd.js", srcs = ["backend.cc"] + KERNELS_WITH_KEEPALIVE, From a2c07e7f8692338a93a89874f8640dce3a0516d0 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 22 Jul 2020 09:59:24 -0400 Subject: [PATCH 14/70] fix --- tfjs-backend-wasm/karma.conf.js | 2 + .../scripts/create-worker-module.js | 9 ++++- .../wasm-out/tfjs-backend-wasm-simd.d.ts | 40 ------------------- 3 files changed, 9 insertions(+), 42 deletions(-) delete mode 100644 tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-simd.d.ts diff --git a/tfjs-backend-wasm/karma.conf.js b/tfjs-backend-wasm/karma.conf.js index 0287ccc85ae..6adc79d948d 100644 --- a/tfjs-backend-wasm/karma.conf.js +++ b/tfjs-backend-wasm/karma.conf.js @@ -61,6 +61,8 @@ module.exports = function(config) { {pattern: 'wasm-out/**/*.wasm', included: false}, // Import the generated js library from emscripten. {pattern: 'wasm-out/**/*.js'}, + // Import the generated worker file from emscripten. + {pattern: 'wasm-out/tfjs-backend-wasm-threaded-simd.worker.ts'}, // Import the rest of the sources. {pattern: 'src/**/*.ts'}, ], diff --git a/tfjs-backend-wasm/scripts/create-worker-module.js b/tfjs-backend-wasm/scripts/create-worker-module.js index 4cb511463e3..b76ed3a3273 100755 --- a/tfjs-backend-wasm/scripts/create-worker-module.js +++ b/tfjs-backend-wasm/scripts/create-worker-module.js @@ -21,8 +21,13 @@ const fs = require('fs'); -const workerContents = fs.readFileSync('./wasm-out/tfjs-backend-wasm-threaded-simd.worker.js', "utf8"); +const BASE_PATH = './wasm-out/'; +const WORKER_PATH = `${BASE_PATH}tfjs-backend-wasm-threaded-simd.worker.js`; + +const workerContents = fs.readFileSync(WORKER_PATH, "utf8"); const fileContents = `export const wasmWorkerContents = '${workerContents.trim()}';`; -fs.writeFileSync('./wasm-out/tfjs-backend-wasm-threaded-simd.worker.ts', fileContents); +fs.writeFileSync(`${BASE_PATH}tfjs-backend-wasm-threaded-simd.worker.ts`, fileContents); + +fs.unlinkSync(WORKER_PATH) diff --git a/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-simd.d.ts b/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-simd.d.ts deleted file mode 100644 index 22d46f1cac3..00000000000 --- a/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-simd.d.ts +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - -export interface BackendWasmModuleSimd extends EmscriptenModule { - mainScriptUrlOrBlob: string|Blob; - onRuntimeInitialized: () => void; - onAbort: (msg: string) => void; - // Using the tfjs namespace to avoid conflict with emscripten's API. - tfjs: { - init(): void, - registerTensor(id: number, size: number, memoryOffset: number): void, - // Disposes the data behind the data bucket. - disposeData(id: number): void, - // Disposes the backend and all of its associated data. - dispose(): void, - } -} - -export interface WasmFactoryConfigSimd { - locateFile?(path: string, prefix: string): string; - instantiateWasm?: Function; -} - -declare var moduleFactory: (settings: WasmFactoryConfigSimd) => - BackendWasmModuleSimd; -export default moduleFactory; From 2c5643574bb4c29d24a059515fc61aa34d4beba9 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 22 Jul 2020 10:09:10 -0400 Subject: [PATCH 15/70] fix --- tfjs-backend-wasm/scripts/build-wasm.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tfjs-backend-wasm/scripts/build-wasm.sh b/tfjs-backend-wasm/scripts/build-wasm.sh index bc45ffe0e33..579ae80c257 100755 --- a/tfjs-backend-wasm/scripts/build-wasm.sh +++ b/tfjs-backend-wasm/scripts/build-wasm.sh @@ -42,4 +42,3 @@ node ./scripts/create-worker-module.js mkdir -p dist # Only copying binary into dist because the js module gets bundled. cp wasm-out/*.wasm dist/ -cp wasm-out/*.worker.js dist/ From b3c69b27807043fe44f2e17eba875762186539ac Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 22 Jul 2020 10:11:28 -0400 Subject: [PATCH 16/70] fix comment --- tfjs-backend-wasm/karma.conf.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tfjs-backend-wasm/karma.conf.js b/tfjs-backend-wasm/karma.conf.js index 6adc79d948d..837285b3d90 100644 --- a/tfjs-backend-wasm/karma.conf.js +++ b/tfjs-backend-wasm/karma.conf.js @@ -20,8 +20,8 @@ const karmaTypescriptConfig = { compilerOptions: {allowJs: true, declaration: false}, bundlerOptions: { sourceMap: true, - // Ignore the import of the `worker_threads` package used in a core test - // meant to run in node. + // Ignore the import of the `worker_threads`/`perf_hooks` packages used in a + // core test meant to run in node. exclude: ['worker_threads', 'perf_hooks'], // worker_node_test in tfjs-core contains a conditional require statement // that confuses the bundler of karma-typescript. From 418860a25b13bcc880947f409b553f6bc39c3f00 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 22 Jul 2020 10:13:31 -0400 Subject: [PATCH 17/70] update --- e2e/benchmarks/tf-backend-wasm.js | 497 ++++++++++++++---------------- 1 file changed, 239 insertions(+), 258 deletions(-) diff --git a/e2e/benchmarks/tf-backend-wasm.js b/e2e/benchmarks/tf-backend-wasm.js index 3e2ffe0b9b3..8fbfd96702e 100644 --- a/e2e/benchmarks/tf-backend-wasm.js +++ b/e2e/benchmarks/tf-backend-wasm.js @@ -1,30 +1,30 @@ -/** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tensorflow/tfjs-core'), require('path'), require('fs'), require('worker_threads'), require('perf_hooks')) : - typeof define === 'function' && define.amd ? define(['exports', '@tensorflow/tfjs-core', 'path', 'fs', 'worker_threads', 'perf_hooks'], factory) : - (global = global || self, factory((global.tf = global.tf || {}, global.tf.wasm = global.tf.wasm || {}), global.tf, global.path, global.fs, global.worker_threads, global.perf_hooks)); -}(this, (function (exports, tfjsCore, path, fs, worker_threads, perf_hooks) { 'use strict'; - - path = path && path.hasOwnProperty('default') ? path['default'] : path; - fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; - worker_threads = worker_threads && worker_threads.hasOwnProperty('default') ? worker_threads['default'] : worker_threads; - perf_hooks = perf_hooks && perf_hooks.hasOwnProperty('default') ? perf_hooks['default'] : perf_hooks; - +/** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tensorflow/tfjs-core'), require('path'), require('fs'), require('worker_threads'), require('perf_hooks')) : + typeof define === 'function' && define.amd ? define(['exports', '@tensorflow/tfjs-core', 'path', 'fs', 'worker_threads', 'perf_hooks'], factory) : + (global = global || self, factory((global.tf = global.tf || {}, global.tf.wasm = global.tf.wasm || {}), global.tf, global.path, global.fs, global.worker_threads, global.perf_hooks)); +}(this, (function (exports, tfjsCore, path, fs, worker_threads, perf_hooks) { 'use strict'; + + path = path && path.hasOwnProperty('default') ? path['default'] : path; + fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; + worker_threads = worker_threads && worker_threads.hasOwnProperty('default') ? worker_threads['default'] : worker_threads; + perf_hooks = perf_hooks && perf_hooks.hasOwnProperty('default') ? perf_hooks['default'] : perf_hooks; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -57,8 +57,8 @@ FusableActivation[FusableActivation["relu"] = 1] = "relu"; FusableActivation[FusableActivation["relu6"] = 2] = "relu6"; FusableActivation[FusableActivation["prelu"] = 3] = "prelu"; - })(FusableActivation || (FusableActivation = {})); - + })(FusableActivation || (FusableActivation = {})); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -133,8 +133,8 @@ backendName: 'wasm', setupFunc: setup, kernelFunc: fusedBatchMatMul - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -170,10 +170,10 @@ return out; } return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; - } - - const absConfig = createUnaryKernelConfig('Abs'); - + } + + const absConfig = createUnaryKernelConfig('Abs'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -239,8 +239,8 @@ } } return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; - } - + } + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -258,8 +258,8 @@ * ============================================================================= */ const supportsFullBroadcast = true; - const addConfig = createBinaryKernelConfig('Add', supportsFullBroadcast); - + const addConfig = createBinaryKernelConfig('Add', supportsFullBroadcast); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -303,8 +303,8 @@ backendName: 'wasm', setupFunc, kernelFunc: addn, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -333,8 +333,8 @@ kernelName: tfjsCore.Identity, backendName: 'wasm', kernelFunc: identity, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -428,8 +428,8 @@ backendName: 'wasm', kernelFunc: transpose, setupFunc: setup$1, - }; - + }; + /** * @license * Copyright 2020 Google Inc. All Rights Reserved. @@ -477,8 +477,8 @@ } } return { transposed: xTransposed, originalAxes, axes, inputWasTransposed }; - } - + } + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -539,8 +539,8 @@ backendName: 'wasm', kernelFunc: argmax, setupFunc: setup$2 - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -609,8 +609,8 @@ backendName: 'wasm', setupFunc: setup$3, kernelFunc: avgPool - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -665,8 +665,8 @@ backendName: 'wasm', setupFunc: setup$4, kernelFunc: batchMatMul - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -695,8 +695,8 @@ kernelName: 'Cast', backendName: 'wasm', kernelFunc: cast, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -737,8 +737,8 @@ backendName: 'wasm', setupFunc: setup$5, kernelFunc: clip - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -785,8 +785,8 @@ kernelName: 'Concat', backendName: 'wasm', kernelFunc: concat, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -862,8 +862,8 @@ backendName: 'wasm', setupFunc: setup$6, kernelFunc: conv2d - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -946,8 +946,8 @@ backendName: 'wasm', setupFunc: setup$7, kernelFunc: conv2DBackpropInput - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -964,8 +964,8 @@ * limitations under the License. * ============================================================================= */ - const cosConfig = createUnaryKernelConfig('Cos'); - + const cosConfig = createUnaryKernelConfig('Cos'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1033,8 +1033,8 @@ backendName: 'wasm', setupFunc: setup$8, kernelFunc: cropAndResize - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1111,8 +1111,8 @@ backendName: 'wasm', setupFunc: setup$9, kernelFunc: depthwiseConv2d - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1130,13 +1130,13 @@ * ============================================================================= */ const supportsFullBroadcast$1 = true; - const divConfig = createBinaryKernelConfig('Div', supportsFullBroadcast$1); - + const divConfig = createBinaryKernelConfig('Div', supportsFullBroadcast$1); + const supportsFullBroadcast$2 = false; - const equalConfig = createBinaryKernelConfig('Equal', supportsFullBroadcast$2, 'bool'); - - const expConfig = createUnaryKernelConfig('Exp'); - + const equalConfig = createBinaryKernelConfig('Equal', supportsFullBroadcast$2, 'bool'); + + const expConfig = createUnaryKernelConfig('Exp'); + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -1164,8 +1164,8 @@ kernelName: tfjsCore.Fill, backendName: 'wasm', kernelFunc: fill, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1183,8 +1183,8 @@ * ============================================================================= */ const supportsFullBroadcast$3 = false; - const floorDivConfig = createBinaryKernelConfig('FloorDiv', supportsFullBroadcast$3); - + const floorDivConfig = createBinaryKernelConfig('FloorDiv', supportsFullBroadcast$3); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1228,8 +1228,8 @@ backendName: 'wasm', setupFunc: setup$a, kernelFunc: fusedBatchNorm - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1330,8 +1330,8 @@ backendName: 'wasm', setupFunc: setup$b, kernelFunc: fusedConv2d - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1433,8 +1433,8 @@ backendName: 'wasm', setupFunc: setup$c, kernelFunc: fusedDepthwiseConv2d - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1488,8 +1488,8 @@ backendName: 'wasm', setupFunc: setup$d, kernelFunc: gatherNd - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1549,17 +1549,17 @@ backendName: 'wasm', setupFunc: setup$e, kernelFunc: gatherV2 - }; - + }; + const supportsFullBroadcast$4 = false; - const greaterConfig = createBinaryKernelConfig('Greater', supportsFullBroadcast$4, 'bool'); - + const greaterConfig = createBinaryKernelConfig('Greater', supportsFullBroadcast$4, 'bool'); + const supportsFullBroadcast$5 = false; - const greaterEqualConfig = createBinaryKernelConfig('GreaterEqual', supportsFullBroadcast$5, 'bool'); - + const greaterEqualConfig = createBinaryKernelConfig('GreaterEqual', supportsFullBroadcast$5, 'bool'); + const supportsFullBroadcast$6 = false; - const lessConfig = createBinaryKernelConfig('Less', supportsFullBroadcast$6, 'bool'); - + const lessConfig = createBinaryKernelConfig('Less', supportsFullBroadcast$6, 'bool'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1577,13 +1577,13 @@ * ============================================================================= */ const supportsFullBroadcast$7 = false; - const lessEqualConfig = createBinaryKernelConfig('LessEqual', supportsFullBroadcast$7, 'bool'); - - const logConfig = createUnaryKernelConfig('Log'); - + const lessEqualConfig = createBinaryKernelConfig('LessEqual', supportsFullBroadcast$7, 'bool'); + + const logConfig = createUnaryKernelConfig('Log'); + const supportsFullBroadcast$8 = false; - const logicalAndConfig = createBinaryKernelConfig('LogicalAnd', supportsFullBroadcast$8, 'bool'); - + const logicalAndConfig = createBinaryKernelConfig('LogicalAnd', supportsFullBroadcast$8, 'bool'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1643,11 +1643,11 @@ backendName: 'wasm', setupFunc: setup$f, kernelFunc: max - }; - + }; + const supportsFullBroadcast$9 = false; - const maximumConfig = createBinaryKernelConfig('Maximum', supportsFullBroadcast$9); - + const maximumConfig = createBinaryKernelConfig('Maximum', supportsFullBroadcast$9); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1718,8 +1718,8 @@ backendName: 'wasm', setupFunc: setup$g, kernelFunc: maxPool - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1783,11 +1783,11 @@ backendName: 'wasm', setupFunc: setup$h, kernelFunc: min - }; - + }; + const supportsFullBroadcast$a = false; - const minimumConfig = createBinaryKernelConfig('Minimum', supportsFullBroadcast$a); - + const minimumConfig = createBinaryKernelConfig('Minimum', supportsFullBroadcast$a); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1805,10 +1805,10 @@ * ============================================================================= */ const supportsFullBroadcast$b = true; - const multiplyConfig = createBinaryKernelConfig(tfjsCore.Multiply, supportsFullBroadcast$b); - - const negateConfig = createUnaryKernelConfig('Negate'); - + const multiplyConfig = createBinaryKernelConfig(tfjsCore.Multiply, supportsFullBroadcast$b); + + const negateConfig = createUnaryKernelConfig('Negate'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1838,8 +1838,8 @@ // Since the result was allocated on the heap, we have to delete it. backend.wasm._free(resOffset); return { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs }; - } - + } + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1886,8 +1886,8 @@ backendName: 'wasm', setupFunc: setup$i, kernelFunc, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -1935,8 +1935,8 @@ backendName: 'wasm', setupFunc: setup$j, kernelFunc: nonMaxSuppressionV4, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1985,11 +1985,11 @@ backendName: 'wasm', setupFunc: setup$k, kernelFunc: kernelFunc$1, - }; - + }; + const supportsFullBroadcast$c = false; - const notEqualConfig = createBinaryKernelConfig('NotEqual', supportsFullBroadcast$c, 'bool'); - + const notEqualConfig = createBinaryKernelConfig('NotEqual', supportsFullBroadcast$c, 'bool'); + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2032,8 +2032,8 @@ backendName: 'wasm', setupFunc: setup$l, kernelFunc: oneHot, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2061,8 +2061,8 @@ kernelName: 'OnesLike', backendName: 'wasm', kernelFunc: onesLike, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2111,11 +2111,11 @@ backendName: 'wasm', kernelFunc: pad, setupFunc: setup$m - }; - + }; + const supportsFullBroadcast$d = false; - const powConfig = createBinaryKernelConfig('Pow', supportsFullBroadcast$d); - + const powConfig = createBinaryKernelConfig('Pow', supportsFullBroadcast$d); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2155,12 +2155,12 @@ backendName: 'wasm', setupFunc: setup$n, kernelFunc: prelu - }; - - const reluConfig = createUnaryKernelConfig('Relu'); - - const relu6Config = createUnaryKernelConfig('Relu6'); - + }; + + const reluConfig = createUnaryKernelConfig('Relu'); + + const relu6Config = createUnaryKernelConfig('Relu6'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2187,8 +2187,8 @@ kernelName: tfjsCore.Reshape, backendName: 'wasm', kernelFunc: reshape, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2250,8 +2250,8 @@ backendName: 'wasm', setupFunc: setup$o, kernelFunc: resizeBilinear - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2300,8 +2300,8 @@ backendName: 'wasm', kernelFunc: reverse, setupFunc: setup$p - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2357,10 +2357,10 @@ backendName: 'wasm', kernelFunc: rotateWithOffset, setupFunc: setup$q - }; - - const rsqrtConfig = createUnaryKernelConfig('Rsqrt'); - + }; + + const rsqrtConfig = createUnaryKernelConfig('Rsqrt'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2414,8 +2414,8 @@ backendName: 'wasm', setupFunc: setup$r, kernelFunc: scatterNd - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2463,8 +2463,8 @@ backendName: 'wasm', kernelFunc: select, setupFunc: setup$s - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2503,10 +2503,10 @@ backendName: 'wasm', setupFunc: setup$t, kernelFunc: sigmoid - }; - - const sinConfig = createUnaryKernelConfig('Sin'); - + }; + + const sinConfig = createUnaryKernelConfig('Sin'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2609,8 +2609,8 @@ kernelName: 'Slice', backendName: 'wasm', kernelFunc: slice, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2655,8 +2655,8 @@ backendName: 'wasm', setupFunc: setup$u, kernelFunc: softmax - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2693,8 +2693,8 @@ kernelName: tfjsCore.SplitV, backendName: 'wasm', kernelFunc: split - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2711,13 +2711,13 @@ * limitations under the License. * ============================================================================= */ - const sqrtConfig = createUnaryKernelConfig('Sqrt'); - - const squareConfig = createUnaryKernelConfig('Square'); - + const sqrtConfig = createUnaryKernelConfig('Sqrt'); + + const squareConfig = createUnaryKernelConfig('Square'); + const supportsFullBroadcast$e = true; - const subConfig = createBinaryKernelConfig('Sub', supportsFullBroadcast$e); - + const subConfig = createBinaryKernelConfig('Sub', supportsFullBroadcast$e); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2782,10 +2782,10 @@ backendName: 'wasm', setupFunc: setup$v, kernelFunc: sum - }; - - const tanhConfig = createUnaryKernelConfig('Tanh'); - + }; + + const tanhConfig = createUnaryKernelConfig('Tanh'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2834,8 +2834,8 @@ backendName: 'wasm', setupFunc: setup$w, kernelFunc: tile - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2879,8 +2879,8 @@ kernelName: tfjsCore.Unpack, backendName: 'wasm', kernelFunc: unpack, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2908,8 +2908,8 @@ kernelName: 'ZerosLike', backendName: 'wasm', kernelFunc: zerosLike, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -3002,8 +3002,8 @@ ]; for (const kernelConfig of kernelConfigs) { tfjsCore.registerKernel(kernelConfig); - } - + } + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -3046,68 +3046,50 @@ catch (e) { return false; } - }); - - function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; - } - - var tfjsBackendWasmSimd = createCommonjsModule(function (module, exports) { - var WasmBackendModule = (function() { - var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; - if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; - return ( - function(WasmBackendModule) { - WasmBackendModule = WasmBackendModule || {}; - - var Module=typeof WasmBackendModule!=="undefined"?WasmBackendModule:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":151,"maximum":151+0,"element":"anyfunc"});var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023);}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var DYNAMIC_BASE=5254544,DYNAMICTOP_PTR=11504;var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":2147483648/WASM_PAGE_SIZE});}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm-simd.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;removeRunDependency();}addRunDependency();function receiveInstantiatedSource(output){receiveInstance(output["instance"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}__ATINIT__.push({func:function(){___wasm_call_ctors();}});function _abort(){abort();}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num);}function _emscripten_get_heap_size(){return HEAPU8.length}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=65536;var maxHeapSize=2147483648;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}var asmLibraryArg={"a":_abort,"e":_emscripten_memcpy_big,"f":_emscripten_resize_heap,"g":_fd_close,"d":_fd_seek,"c":_fd_write,"memory":wasmMemory,"b":_roundf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return (___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["h"]).apply(null,arguments)};var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["i"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["j"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["k"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["l"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["m"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["n"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["o"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["p"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["q"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["r"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["s"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["t"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["u"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["v"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["w"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["x"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["y"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["z"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["A"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["B"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["C"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["D"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["E"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["F"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["G"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["H"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["I"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["J"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["K"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["L"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["M"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["N"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["O"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["P"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["Q"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["R"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["S"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["T"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["U"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["V"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["W"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["X"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["Y"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["Z"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["_"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["$"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["aa"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["ba"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["ca"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["da"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["ea"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["fa"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["ga"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["ha"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["ia"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["ja"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["ka"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["la"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["ma"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["na"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["oa"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["pa"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["qa"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["ra"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["sa"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["ta"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["ua"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["va"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["wa"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["xa"]).apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){return (dynCall_vi=Module["dynCall_vi"]=Module["asm"]["ya"]).apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){return (dynCall_v=Module["dynCall_v"]=Module["asm"]["za"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}noExitRuntime=true;run(); - - - return WasmBackendModule - } - ); - })(); - module.exports = WasmBackendModule; - }); - - var tfjsBackendWasmThreadedSimd = createCommonjsModule(function (module, exports) { - var WasmBackendModuleSimd = (function() { - var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; - if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; - return ( - function(WasmBackendModuleSimd) { - WasmBackendModuleSimd = WasmBackendModuleSimd || {}; - - function GROWABLE_HEAP_I8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP8}function GROWABLE_HEAP_U8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU8}function GROWABLE_HEAP_I32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP32}function GROWABLE_HEAP_U32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPF64}var Module=typeof WasmBackendModuleSimd!=="undefined"?WasmBackendModuleSimd:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(Module["ENVIRONMENT"]){throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -s ENVIRONMENT=web or -s ENVIRONMENT=node)")}var ENVIRONMENT_IS_PTHREAD=Module["ENVIRONMENT_IS_PTHREAD"]||false;if(ENVIRONMENT_IS_PTHREAD){buffer=Module["buffer"];DYNAMIC_BASE=Module["DYNAMIC_BASE"];DYNAMICTOP_PTR=Module["DYNAMICTOP_PTR"];}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};var nodeWorkerThreads;try{nodeWorkerThreads=worker_threads;}catch(e){console.error('The "worker_threads" module is not supported in this node.js build - perhaps a newer version is needed?');throw e}Worker=nodeWorkerThreads.Worker;}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}if(ENVIRONMENT_IS_NODE){read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};}else{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}else{throw new Error("environment detection error")}if(ENVIRONMENT_IS_NODE){if(typeof performance==="undefined"){performance=perf_hooks.performance;}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(!Object.getOwnPropertyDescriptor(Module,"arguments"))Object.defineProperty(Module,"arguments",{configurable:true,get:function(){abort("Module.arguments has been replaced with plain arguments_");}});if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(!Object.getOwnPropertyDescriptor(Module,"thisProgram"))Object.defineProperty(Module,"thisProgram",{configurable:true,get:function(){abort("Module.thisProgram has been replaced with plain thisProgram");}});if(Module["quit"])quit_=Module["quit"];if(!Object.getOwnPropertyDescriptor(Module,"quit"))Object.defineProperty(Module,"quit",{configurable:true,get:function(){abort("Module.quit has been replaced with plain quit_");}});assert(typeof Module["memoryInitializerPrefixURL"]==="undefined","Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["pthreadMainPrefixURL"]==="undefined","Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["cdInitializerPrefixURL"]==="undefined","Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["filePackagePrefixURL"]==="undefined","Module.filePackagePrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["read"]==="undefined","Module.read option was removed (modify read_ in JS)");assert(typeof Module["readAsync"]==="undefined","Module.readAsync option was removed (modify readAsync in JS)");assert(typeof Module["readBinary"]==="undefined","Module.readBinary option was removed (modify readBinary in JS)");assert(typeof Module["setWindowTitle"]==="undefined","Module.setWindowTitle option was removed (modify setWindowTitle in JS)");assert(typeof Module["TOTAL_MEMORY"]==="undefined","Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");if(!Object.getOwnPropertyDescriptor(Module,"read"))Object.defineProperty(Module,"read",{configurable:true,get:function(){abort("Module.read has been replaced with plain read_");}});if(!Object.getOwnPropertyDescriptor(Module,"readAsync"))Object.defineProperty(Module,"readAsync",{configurable:true,get:function(){abort("Module.readAsync has been replaced with plain readAsync");}});if(!Object.getOwnPropertyDescriptor(Module,"readBinary"))Object.defineProperty(Module,"readBinary",{configurable:true,get:function(){abort("Module.readBinary has been replaced with plain readBinary");}});if(!Object.getOwnPropertyDescriptor(Module,"setWindowTitle"))Object.defineProperty(Module,"setWindowTitle",{configurable:true,get:function(){abort("Module.setWindowTitle has been replaced with plain setWindowTitle");}});assert(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER||ENVIRONMENT_IS_NODE,"Pthreads do not work in this environment yet (need Web Workers, or an alternative to them)");var stackSave;var stackRestore;var stackAlloc;stackSave=stackRestore=stackAlloc=function(){abort("cannot use the stack before compiled code is ready to run, and has provided stack access");};function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text);}}var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(!Object.getOwnPropertyDescriptor(Module,"wasmBinary"))Object.defineProperty(Module,"wasmBinary",{configurable:true,get:function(){abort("Module.wasmBinary has been replaced with plain wasmBinary");}});var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(!Object.getOwnPropertyDescriptor(Module,"noExitRuntime"))Object.defineProperty(Module,"noExitRuntime",{configurable:true,get:function(){abort("Module.noExitRuntime has been replaced with plain noExitRuntime");}});if(typeof WebAssembly!=="object"){abort("No WebAssembly support found. Build with -s WASM=0 to target JavaScript instead.");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":165,"maximum":165+0,"element":"anyfunc"});var wasmModule;var threadInfoStruct=0;var selfThreadId=0;var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;assert(returnType!=="array",'Return type should not be "array".');if(args){for(var i=0;i=endIdx)){var u0=heap[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heap[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heap[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2;}else{if((u0&248)!=240)warnOnce("Invalid UTF-8 leading byte 0x"+u0.toString(16)+" encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!");u0=(u0&7)<<18|u1<<12|u2<<6|heap[idx++]&63;}if(u0<65536){str+=String.fromCharCode(u0);}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023);}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;if(u>=2097152)warnOnce("Invalid Unicode code point 0x"+u.toString(16)+" encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).");heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){assert(typeof maxBytesToWrite=="number","stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");return stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4;}return len}function writeArrayToMemory(array,buffer){assert(array.length>=0,"writeArrayToMemory array must have a length (should be an array or typed array)");GROWABLE_HEAP_I8().set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var STACK_BASE=5256288,STACKTOP=STACK_BASE,STACK_MAX=13408,DYNAMIC_BASE=5256288,DYNAMICTOP_PTR=12480;assert(STACK_BASE%16===0,"stack must start aligned");assert(DYNAMIC_BASE%16===0,"heap must start aligned");if(ENVIRONMENT_IS_PTHREAD){STACK_MAX=STACKTOP=STACK_MAX=2147483647;}var TOTAL_STACK=5242880;if(Module["TOTAL_STACK"])assert(TOTAL_STACK===Module["TOTAL_STACK"],"the stack size can no longer be determined at runtime");var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||1073741824;if(!Object.getOwnPropertyDescriptor(Module,"INITIAL_MEMORY"))Object.defineProperty(Module,"INITIAL_MEMORY",{configurable:true,get:function(){abort("Module.INITIAL_MEMORY has been replaced with plain INITIAL_INITIAL_MEMORY");}});assert(INITIAL_INITIAL_MEMORY>=TOTAL_STACK,"INITIAL_MEMORY should be larger than TOTAL_STACK, was "+INITIAL_INITIAL_MEMORY+"! (TOTAL_STACK="+TOTAL_STACK+")");assert(typeof Int32Array!=="undefined"&&typeof Float64Array!=="undefined"&&Int32Array.prototype.subarray!==undefined&&Int32Array.prototype.set!==undefined,"JS engine does not provide full typed array support");if(ENVIRONMENT_IS_PTHREAD){wasmMemory=Module["wasmMemory"];buffer=Module["buffer"];}else{if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":1073741824/WASM_PAGE_SIZE,"shared":true});if(!(wasmMemory.buffer instanceof SharedArrayBuffer)){err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");if(ENVIRONMENT_IS_NODE){console.log("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)");}throw Error("bad memory")}}}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;assert(INITIAL_INITIAL_MEMORY%WASM_PAGE_SIZE===0);assert(65536%WASM_PAGE_SIZE===0);updateGlobalBufferAndViews(buffer);if(!ENVIRONMENT_IS_PTHREAD){GROWABLE_HEAP_I32()[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;}function writeStackCookie(){assert((STACK_MAX&3)==0);GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1]=34821223;GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2]=2310721022;GROWABLE_HEAP_I32()[0]=1668509029;}function checkStackCookie(){var cookie1=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1];var cookie2=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2];if(cookie1!=34821223||cookie2!=2310721022){abort("Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x"+cookie2.toString(16)+" "+cookie1.toString(16));}if(GROWABLE_HEAP_I32()[0]!==1668509029)abort("Runtime error: The application has corrupted its heap memory area (address zero)!");}function abortStackOverflow(allocSize){abort("Stack overflow! Attempted to allocate "+allocSize+" bytes on the stack, but stack has only "+(STACK_MAX-stackSave()+allocSize)+" bytes available!");}(function(){var h16=new Int16Array(1);var h8=new Int8Array(h16.buffer);h16[0]=25459;if(h8[0]!==115||h8[1]!==99)throw "Runtime error: expected the system to be little-endian!"})();function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;if(ENVIRONMENT_IS_PTHREAD)runtimeInitialized=true;function preRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){checkStackCookie();assert(!runtimeInitialized);runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__);}function preMain(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;callRuntimeCallbacks(__ATMAIN__);}function postRun(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}assert(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;var runDependencyTracking={};function addRunDependency(id){assert(!ENVIRONMENT_IS_PTHREAD,"addRunDependency cannot be used in a pthread worker");runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(!runDependencyTracking[id]);runDependencyTracking[id]=1;if(runDependencyWatcher===null&&typeof setInterval!=="undefined"){runDependencyWatcher=setInterval(function(){if(ABORT){clearInterval(runDependencyWatcher);runDependencyWatcher=null;return}var shown=false;for(var dep in runDependencyTracking){if(!shown){shown=true;err("still waiting on run dependencies:");}err("dependency: "+dep);}if(shown){err("(end of list)");}},1e4);}}else{err("warning: run dependency added without ID");}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(runDependencyTracking[id]);delete runDependencyTracking[id];}else{err("warning: run dependency removed without ID");}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}if(ENVIRONMENT_IS_PTHREAD)console.error("Pthread aborting at "+(new Error).stack);what+="";out(what);err(what);ABORT=true;var output="abort("+what+") at "+stackTrace();what=output;throw new WebAssembly.RuntimeError(what)}var FS={error:function(){abort("Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -s FORCE_FILESYSTEM=1");},init:function(){FS.error();},createDataFile:function(){FS.error();},createPreloadedFile:function(){FS.error();},createLazyFile:function(){FS.error();},open:function(){FS.error();},mkdev:function(){FS.error();},registerDevice:function(){FS.error();},analyzePath:function(){FS.error();},loadFilesFromDB:function(){FS.error();},ErrnoError:function ErrnoError(){FS.error();}};Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm-threaded-simd.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmModule=module;if(!ENVIRONMENT_IS_PTHREAD){var numWorkersToLoad=PThread.unusedWorkers.length;PThread.unusedWorkers.forEach(function(w){PThread.loadWasmModuleToWorker(w,function(){if(!--numWorkersToLoad)removeRunDependency("wasm-instantiate");});});}}if(!ENVIRONMENT_IS_PTHREAD){addRunDependency("wasm-instantiate");}var trueModule=Module;function receiveInstantiatedSource(output){assert(Module===trueModule,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");trueModule=null;receiveInstance(output["instance"],output["module"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}var ASM_CONSTS={};function initPthreadsJS(){PThread.initRuntime();}if(!ENVIRONMENT_IS_PTHREAD)__ATINIT__.push({func:function(){___wasm_call_ctors();}});function demangle(func){warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling");return func}function demangleAll(text){var regex=/\b_Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}var __pthread_ptr=0;var __pthread_is_main_runtime_thread=0;var __pthread_is_main_browser_thread=0;function __register_pthread_ptr(pthreadPtr,isMainBrowserThread,isMainRuntimeThread){pthreadPtr=pthreadPtr|0;isMainBrowserThread=isMainBrowserThread|0;isMainRuntimeThread=isMainRuntimeThread|0;__pthread_ptr=pthreadPtr;__pthread_is_main_browser_thread=isMainBrowserThread;__pthread_is_main_runtime_thread=isMainRuntimeThread;}Module["__register_pthread_ptr"]=__register_pthread_ptr;var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var __main_thread_futex_wait_address=13392;function _emscripten_futex_wake(addr,count){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0||count<0)return -28;if(count==0)return 0;if(count>=2147483647)count=Infinity;var mainThreadWaitAddress=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);var mainThreadWoken=0;if(mainThreadWaitAddress==addr){var loadedAddr=Atomics.compareExchange(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,mainThreadWaitAddress,0);if(loadedAddr==mainThreadWaitAddress){--count;mainThreadWoken=1;if(count<=0)return 1}}var ret=Atomics.notify(GROWABLE_HEAP_I32(),addr>>2,count);if(ret>=0)return ret+mainThreadWoken;throw "Atomics.notify returned an unexpected value "+ret}Module["_emscripten_futex_wake"]=_emscripten_futex_wake;function __kill_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _kill_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _kill_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];pthread.worker.terminate();PThread.freeThreadData(pthread);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(pthread.worker),1);pthread.worker.pthread=undefined;}function __cancel_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cancel_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cancel_thread!";var pthread=PThread.pthreads[pthread_ptr];pthread.worker.postMessage({"cmd":"cancel"});}function __cleanup_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cleanup_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cleanup_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];if(pthread){var worker=pthread.worker;PThread.returnWorkerToPool(worker);}}var PThread={MAIN_THREAD_ID:1,mainThreadInfo:{schedPolicy:0,schedPrio:0},unusedWorkers:[],runningWorkers:[],initRuntime:function(){__register_pthread_ptr(PThread.mainThreadBlock,!ENVIRONMENT_IS_WORKER,1);_emscripten_register_main_browser_thread_id(PThread.mainThreadBlock);},initMainThreadBlock:function(){assert(!ENVIRONMENT_IS_PTHREAD);var pthreadPoolSize=8;for(var i=0;i>2]=PThread.mainThreadBlock;var headPtr=PThread.mainThreadBlock+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var tlsMemory=12880;for(var i=0;i<128;++i)GROWABLE_HEAP_U32()[tlsMemory/4+i]=0;Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+104>>2,tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+40>>2,PThread.mainThreadBlock);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+44>>2,42);},initWorker:function(){},pthreads:{},exitHandlers:null,setThreadStatus:function(){},runExitHandlers:function(){if(PThread.exitHandlers!==null){while(PThread.exitHandlers.length>0){PThread.exitHandlers.pop()();}PThread.exitHandlers=null;}if(ENVIRONMENT_IS_PTHREAD&&threadInfoStruct)___pthread_tsd_run_dtors();},threadExit:function(exitCode){var tb=_pthread_self();if(tb){err("Pthread 0x"+tb.toString(16)+" exited.");Atomics.store(GROWABLE_HEAP_U32(),tb+4>>2,exitCode);Atomics.store(GROWABLE_HEAP_U32(),tb+0>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+60>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+64>>2,0);PThread.runExitHandlers();_emscripten_futex_wake(tb+0,2147483647);__register_pthread_ptr(0,0,0);threadInfoStruct=0;if(ENVIRONMENT_IS_PTHREAD){postMessage({"cmd":"exit"});}}},threadCancel:function(){PThread.runExitHandlers();Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+4>>2,-1);Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+0>>2,1);_emscripten_futex_wake(threadInfoStruct+0,2147483647);threadInfoStruct=selfThreadId=0;__register_pthread_ptr(0,0,0);postMessage({"cmd":"cancelDone"});},terminateAllThreads:function(){for(var t in PThread.pthreads){var pthread=PThread.pthreads[t];if(pthread&&pthread.worker){PThread.returnWorkerToPool(pthread.worker);}}PThread.pthreads={};for(var i=0;i>2];GROWABLE_HEAP_I32()[pthread.threadInfoStruct+104>>2]=0;_free(tlsMemory);_free(pthread.threadInfoStruct);}pthread.threadInfoStruct=0;if(pthread.allocatedOwnStack&&pthread.stackBase)_free(pthread.stackBase);pthread.stackBase=0;if(pthread.worker)pthread.worker.pthread=null;},returnWorkerToPool:function(worker){delete PThread.pthreads[worker.pthread.thread];PThread.unusedWorkers.push(worker);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);PThread.freeThreadData(worker.pthread);worker.pthread=undefined;},receiveObjectTransfer:function(data){},loadWasmModuleToWorker:function(worker,onFinishedLoading){worker.onmessage=function(e){var d=e["data"];var cmd=d["cmd"];if(worker.pthread)PThread.currentProxiedOperationCallerThread=worker.pthread.threadInfoStruct;if(d["targetThread"]&&d["targetThread"]!=_pthread_self()){var thread=PThread.pthreads[d.targetThread];if(thread){thread.worker.postMessage(e.data,d["transferList"]);}else{console.error('Internal error! Worker sent a message "'+cmd+'" to target pthread '+d["targetThread"]+", but that thread no longer exists!");}PThread.currentProxiedOperationCallerThread=undefined;return}if(cmd==="processQueuedMainThreadWork"){_emscripten_main_thread_process_queued_calls();}else if(cmd==="spawnThread"){__spawn_thread(e.data);}else if(cmd==="cleanupThread"){__cleanup_thread(d["thread"]);}else if(cmd==="killThread"){__kill_thread(d["thread"]);}else if(cmd==="cancelThread"){__cancel_thread(d["thread"]);}else if(cmd==="loaded"){worker.loaded=true;if(onFinishedLoading)onFinishedLoading(worker);if(worker.runPthread){worker.runPthread();delete worker.runPthread;}}else if(cmd==="print"){out("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="printErr"){err("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="alert"){alert("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="exit"){var detached=worker.pthread&&Atomics.load(GROWABLE_HEAP_U32(),worker.pthread.thread+68>>2);if(detached){PThread.returnWorkerToPool(worker);}}else if(cmd==="cancelDone"){PThread.returnWorkerToPool(worker);}else if(cmd==="objectTransfer"){PThread.receiveObjectTransfer(e.data);}else if(e.data.target==="setimmediate"){worker.postMessage(e.data);}else{err("worker sent an unknown command "+cmd);}PThread.currentProxiedOperationCallerThread=undefined;};worker.onerror=function(e){err("pthread sent an error! "+e.filename+":"+e.lineno+": "+e.message);};if(ENVIRONMENT_IS_NODE){worker.on("message",function(data){worker.onmessage({data:data});});worker.on("error",function(data){worker.onerror(data);});worker.on("exit",function(data){console.log("worker exited - TODO: update the worker queue?");});}assert(wasmMemory instanceof WebAssembly.Memory,"WebAssembly memory should have been loaded by now!");assert(wasmModule instanceof WebAssembly.Module,"WebAssembly Module should have been loaded by now!");worker.postMessage({"cmd":"load","urlOrBlob":Module["mainScriptUrlOrBlob"]||_scriptDir,"wasmMemory":wasmMemory,"wasmModule":wasmModule,"DYNAMIC_BASE":DYNAMIC_BASE,"DYNAMICTOP_PTR":DYNAMICTOP_PTR});},allocateUnusedWorker:function(){var pthreadMainJs=locateFile("tfjs-backend-wasm-threaded-simd.worker.js");PThread.unusedWorkers.push(new Worker(pthreadMainJs));},getNewWorker:function(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]);}if(PThread.unusedWorkers.length>0)return PThread.unusedWorkers.pop();else return null},busySpinWait:function(msecs){var t=performance.now()+msecs;while(performance.now()>2]=value;return value}function _atexit(func,arg){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(1,1,func,arg);warnOnce("atexit() called, but EXIT_RUNTIME is not set, so atexits() will not be called. set EXIT_RUNTIME to 1 (see the FAQ)");}function ___handle_stack_overflow(){abort("stack overflow");}function __emscripten_notify_thread_queue(targetThreadId,mainThreadId){if(targetThreadId==mainThreadId){postMessage({"cmd":"processQueuedMainThreadWork"});}else if(ENVIRONMENT_IS_PTHREAD){postMessage({"targetThread":targetThreadId,"cmd":"processThreadQueue"});}else{var pthread=PThread.pthreads[targetThreadId];var worker=pthread&&pthread.worker;if(!worker){err("Cannot send message to thread with ID "+targetThreadId+", unknown thread ID!");return}worker.postMessage({"cmd":"processThreadQueue"});}return 1}function _abort(){abort();}function _emscripten_conditional_set_current_thread_status(expectedStatus,newStatus){}function _emscripten_futex_wait(addr,val,timeout){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0)return -28;if(ENVIRONMENT_IS_WORKER){var ret=Atomics.wait(GROWABLE_HEAP_I32(),addr>>2,val,timeout);if(ret==="timed-out")return -73;if(ret==="not-equal")return -6;if(ret==="ok")return 0;throw "Atomics.wait returned an unexpected value "+ret}else{var loadedVal=Atomics.load(GROWABLE_HEAP_I32(),addr>>2);if(val!=loadedVal)return -6;var tNow=performance.now();var tEnd=tNow+timeout;Atomics.store(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,addr);var ourWaitAddress=addr;while(addr==ourWaitAddress){tNow=performance.now();if(tNow>tEnd){return -73}_emscripten_main_thread_process_queued_calls();addr=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);}return 0}}function _emscripten_is_main_browser_thread(){return __pthread_is_main_browser_thread|0}function _emscripten_is_main_runtime_thread(){return __pthread_is_main_runtime_thread|0}function _emscripten_memcpy_big(dest,src,num){GROWABLE_HEAP_U8().copyWithin(dest,src,src+num);}function _emscripten_proxy_to_main_thread_js(index,sync){var numCallArgs=arguments.length-2;if(numCallArgs>20-1)throw "emscripten_proxy_to_main_thread_js: Too many arguments "+numCallArgs+" to proxied function idx="+index+", maximum supported is "+(20-1)+"!";var stack=stackSave();var args=stackAlloc(numCallArgs*8);var b=args>>3;for(var i=0;i>3]);buf+=8;}else if(ch===105){buf=buf+3&~3;args.push(GROWABLE_HEAP_I32()[buf>>2]);buf+=4;}else abort("unexpected char in asm const signature "+ch);}return args}function _emscripten_receive_on_main_thread_js(index,numCallArgs,args){_emscripten_receive_on_main_thread_js_callArgs.length=numCallArgs;var b=args>>3;for(var i=0;i>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){console.error("emscripten_realloc_buffer: Attempted to grow heap from "+buffer.byteLength+" bytes to "+size+" bytes, but got error: "+e);}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();if(requestedSize<=oldSize){return false}var PAGE_MULTIPLE=65536;var maxHeapSize=1073741824;if(requestedSize>maxHeapSize){err("Cannot enlarge memory, asked to go up to "+requestedSize+" bytes, but the limit is "+maxHeapSize+" bytes!");return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}err("Failed to grow the heap from "+oldSize+" bytes to "+newSize+" bytes, not enough memory!");return false}var JSEvents={keyEvent:0,mouseEvent:0,wheelEvent:0,uiEvent:0,focusEvent:0,deviceOrientationEvent:0,deviceMotionEvent:0,fullscreenChangeEvent:0,pointerlockChangeEvent:0,visibilityChangeEvent:0,touchEvent:0,previousFullscreenElement:null,previousScreenX:null,previousScreenY:null,removeEventListenersRegistered:false,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i);}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[];},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){JSEvents.removeEventListenersRegistered=true;}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence>2]=eventTypeId;GROWABLE_HEAP_I32()[varargs+4>>2]=eventData;GROWABLE_HEAP_I32()[varargs+8>>2]=userData;_emscripten_async_queue_on_thread_(targetThread,637534208,eventHandlerFunc,eventData,varargs);stackRestore(stackTop);},getTargetThreadForEventCallback:function(targetThread){switch(targetThread){case 1:return 0;case 2:return PThread.currentProxiedOperationCallerThread;default:return targetThread}},getNodeNameForTarget:function(target){if(!target)return "";if(target==window)return "#window";if(target==screen)return "#screen";return target&&target.nodeName?target.nodeName:""},fullscreenEnabled:function(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+1;var cString=_malloc(length);stringToUTF8(jsString,cString,length);return cString}function _emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height){var stackTop=stackSave();var varargs=stackAlloc(12);var targetCanvasPtr=0;if(targetCanvas){targetCanvasPtr=stringToNewUTF8(targetCanvas);}GROWABLE_HEAP_I32()[varargs>>2]=targetCanvasPtr;GROWABLE_HEAP_I32()[varargs+4>>2]=width;GROWABLE_HEAP_I32()[varargs+8>>2]=height;_emscripten_async_queue_on_thread_(targetThread,657457152,0,targetCanvasPtr,varargs);stackRestore(stackTop);}function _emscripten_set_offscreencanvas_size_on_target_thread(targetThread,targetCanvas,width,height){targetCanvas=targetCanvas?UTF8ToString(targetCanvas):"";_emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height);}function __maybeCStringToJsString(cString){return cString>2?UTF8ToString(cString):cString}var specialHTMLTargets=[0,typeof document!=="undefined"?document:0,typeof window!=="undefined"?window:0];function __findEventTarget(target){target=__maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!=="undefined"?document.querySelector(target):undefined);return domElement}function __findCanvasEventTarget(target){return __findEventTarget(target)}function _emscripten_set_canvas_element_size_calling_thread(target,width,height){var canvas=__findCanvasEventTarget(target);if(!canvas)return -4;if(canvas.canvasSharedPtr){GROWABLE_HEAP_I32()[canvas.canvasSharedPtr>>2]=width;GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+4>>2]=height;}if(canvas.offscreenCanvas||!canvas.controlTransferredOffscreen){if(canvas.offscreenCanvas)canvas=canvas.offscreenCanvas;var autoResizeViewport=false;if(canvas.GLctxObject&&canvas.GLctxObject.GLctx){var prevViewport=canvas.GLctxObject.GLctx.getParameter(2978);autoResizeViewport=prevViewport[0]===0&&prevViewport[1]===0&&prevViewport[2]===canvas.width&&prevViewport[3]===canvas.height;}canvas.width=width;canvas.height=height;if(autoResizeViewport){canvas.GLctxObject.GLctx.viewport(0,0,width,height);}}else if(canvas.canvasSharedPtr){var targetThread=GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+8>>2];_emscripten_set_offscreencanvas_size_on_target_thread(targetThread,target,width,height);return 1}else{return -4}return 0}function _emscripten_set_canvas_element_size_main_thread(target,width,height){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(2,1,target,width,height);return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}function _emscripten_set_canvas_element_size(target,width,height){var canvas=__findCanvasEventTarget(target);if(canvas){return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}else{return _emscripten_set_canvas_element_size_main_thread(target,width,height)}}function _emscripten_set_current_thread_status(newStatus){}function _emscripten_set_thread_name(threadId,name){}function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=function(index,divisor){ext["vertexAttribDivisorANGLE"](index,divisor);};ctx["drawArraysInstanced"]=function(mode,first,count,primcount){ext["drawArraysInstancedANGLE"](mode,first,count,primcount);};ctx["drawElementsInstanced"]=function(mode,count,type,indices,primcount){ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);};return 1}}function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=function(){return ext["createVertexArrayOES"]()};ctx["deleteVertexArray"]=function(vao){ext["deleteVertexArrayOES"](vao);};ctx["bindVertexArray"]=function(vao){ext["bindVertexArrayOES"](vao);};ctx["isVertexArray"]=function(vao){return ext["isVertexArrayOES"](vao)};return 1}}function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=function(n,bufs){ext["drawBuffersWEBGL"](n,bufs);};return 1}}var GL={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:{},currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],programInfos:{},stringCache:{},unpackAlignment:4,init:function(){var miniTempFloatBuffer=new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);for(var i=0;i>2]:-1;source+=UTF8ToString(GROWABLE_HEAP_I32()[string+i*4>>2],len<0?undefined:len);}return source},createContext:function(canvas,webGLContextAttributes){var ctx=canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=_malloc(8);GROWABLE_HEAP_I32()[handle+4>>2]=_pthread_self();var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context);}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return !(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;_free(GL.contexts[contextHandle].handle);GL.contexts[contextHandle]=null;},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;__webgl_enable_ANGLE_instanced_arrays(GLctx);__webgl_enable_OES_vertex_array_object(GLctx);__webgl_enable_WEBGL_draw_buffers(GLctx);GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query");var automaticallyEnabledExtensions=["OES_texture_float","OES_texture_half_float","OES_standard_derivatives","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBGL_depth_texture","OES_element_index_uint","EXT_texture_filter_anisotropic","EXT_frag_depth","WEBGL_draw_buffers","ANGLE_instanced_arrays","OES_texture_float_linear","OES_texture_half_float_linear","EXT_blend_minmax","EXT_shader_texture_lod","EXT_texture_norm16","WEBGL_compressed_texture_pvrtc","EXT_color_buffer_half_float","WEBGL_color_buffer_float","EXT_sRGB","WEBGL_compressed_texture_etc1","EXT_disjoint_timer_query","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_astc","EXT_color_buffer_float","WEBGL_compressed_texture_s3tc_srgb","EXT_disjoint_timer_query_webgl2","WEBKIT_WEBGL_compressed_texture_pvrtc"];var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext);}});},populateUniformTable:function(program){var p=GL.programs[program];var ptable=GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,35718);for(var i=0;i>2;contextAttributes["alpha"]=!!GROWABLE_HEAP_I32()[a+(0>>2)];contextAttributes["depth"]=!!GROWABLE_HEAP_I32()[a+(4>>2)];contextAttributes["stencil"]=!!GROWABLE_HEAP_I32()[a+(8>>2)];contextAttributes["antialias"]=!!GROWABLE_HEAP_I32()[a+(12>>2)];contextAttributes["premultipliedAlpha"]=!!GROWABLE_HEAP_I32()[a+(16>>2)];contextAttributes["preserveDrawingBuffer"]=!!GROWABLE_HEAP_I32()[a+(20>>2)];var powerPreference=GROWABLE_HEAP_I32()[a+(24>>2)];contextAttributes["powerPreference"]=__emscripten_webgl_power_preferences[powerPreference];contextAttributes["failIfMajorPerformanceCaveat"]=!!GROWABLE_HEAP_I32()[a+(28>>2)];contextAttributes.majorVersion=GROWABLE_HEAP_I32()[a+(32>>2)];contextAttributes.minorVersion=GROWABLE_HEAP_I32()[a+(36>>2)];contextAttributes.enableExtensionsByDefault=GROWABLE_HEAP_I32()[a+(40>>2)];contextAttributes.explicitSwapControl=GROWABLE_HEAP_I32()[a+(44>>2)];contextAttributes.proxyContextToMainThread=GROWABLE_HEAP_I32()[a+(48>>2)];contextAttributes.renderViaOffscreenBackBuffer=GROWABLE_HEAP_I32()[a+(52>>2)];var canvas=__findCanvasEventTarget(target);if(!canvas){return -4}if(contextAttributes.explicitSwapControl){return -1}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}function _emscripten_webgl_create_context(a0,a1){return _emscripten_webgl_do_create_context(a0,a1)}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];assert(buffer);if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){assert(SYSCALLS.varargs!=undefined);SYSCALLS.varargs+=4;var ret=GROWABLE_HEAP_I32()[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){if(low>=0)assert(high===0);else assert(high===-1);return low}};function _fd_close(fd){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(3,1,fd);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(4,1,fd,offset_low,offset_high,whence,newOffset);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");}function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(5,1,fd,iov,iovcnt,pnum);var num=0;for(var i=0;i>2];var len=GROWABLE_HEAP_I32()[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _pthread_cleanup_pop(execute){var routine=PThread.exitHandlers.pop();if(execute)routine();}function _pthread_cleanup_push(routine,arg){if(PThread.exitHandlers===null){PThread.exitHandlers=[];}PThread.exitHandlers.push(function(){dynCall_vi(routine,arg);});}function __spawn_thread(threadParams){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _spawn_thread() can only ever be called from main application thread!";var worker=PThread.getNewWorker();if(worker.pthread!==undefined)throw "Internal error!";if(!threadParams.pthread_ptr)throw "Internal error, no pthread ptr!";PThread.runningWorkers.push(worker);var tlsMemory=_malloc(128*4);for(var i=0;i<128;++i){GROWABLE_HEAP_I32()[tlsMemory+i*4>>2]=0;}var stackHigh=threadParams.stackBase+threadParams.stackSize;var pthread=PThread.pthreads[threadParams.pthread_ptr]={worker:worker,stackBase:threadParams.stackBase,stackSize:threadParams.stackSize,allocatedOwnStack:threadParams.allocatedOwnStack,thread:threadParams.pthread_ptr,threadInfoStruct:threadParams.pthread_ptr};var tis=pthread.threadInfoStruct>>2;Atomics.store(GROWABLE_HEAP_U32(),tis+(0>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(4>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(8>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(68>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(104>>2),tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),tis+(48>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(40>>2),pthread.threadInfoStruct);Atomics.store(GROWABLE_HEAP_U32(),tis+(44>>2),42);Atomics.store(GROWABLE_HEAP_U32(),tis+(108>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(84>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(80>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+8>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+12>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+20>>2),threadParams.schedPolicy);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+24>>2),threadParams.schedPrio);var global_libc=_emscripten_get_global_libc();var global_locale=global_libc+40;Atomics.store(GROWABLE_HEAP_U32(),tis+(176>>2),global_locale);worker.pthread=pthread;var msg={"cmd":"run","start_routine":threadParams.startRoutine,"arg":threadParams.arg,"threadInfoStruct":threadParams.pthread_ptr,"selfThreadId":threadParams.pthread_ptr,"parentThreadId":threadParams.parent_pthread_ptr,"stackBase":threadParams.stackBase,"stackSize":threadParams.stackSize};worker.runPthread=function(){msg.time=performance.now();worker.postMessage(msg,threadParams.transferList);};if(worker.loaded){worker.runPthread();delete worker.runPthread;}}function _pthread_getschedparam(thread,policy,schedparam){if(!policy&&!schedparam)return ERRNO_CODES.EINVAL;if(!thread){err("pthread_getschedparam called with a null thread pointer!");return ERRNO_CODES.ESRCH}var self=GROWABLE_HEAP_I32()[thread+12>>2];if(self!==thread){err("pthread_getschedparam attempted on thread "+thread+", which does not point to a valid thread, or does not exist anymore!");return ERRNO_CODES.ESRCH}var schedPolicy=Atomics.load(GROWABLE_HEAP_U32(),thread+108+20>>2);var schedPrio=Atomics.load(GROWABLE_HEAP_U32(),thread+108+24>>2);if(policy)GROWABLE_HEAP_I32()[policy>>2]=schedPolicy;if(schedparam)GROWABLE_HEAP_I32()[schedparam>>2]=schedPrio;return 0}function _pthread_self(){return __pthread_ptr|0}Module["_pthread_self"]=_pthread_self;function _pthread_create(pthread_ptr,attr,start_routine,arg){if(typeof SharedArrayBuffer==="undefined"){err("Current environment does not support SharedArrayBuffer, pthreads are not available!");return 6}if(!pthread_ptr){err("pthread_create called with a null thread pointer!");return 28}var transferList=[];var error=0;if(ENVIRONMENT_IS_PTHREAD&&(transferList.length===0||error)){return _emscripten_sync_run_in_main_thread_4(687865856,pthread_ptr,attr,start_routine,arg)}var stackSize=0;var stackBase=0;var detached=0;var schedPolicy=0;var schedPrio=0;if(attr){stackSize=GROWABLE_HEAP_I32()[attr>>2];stackSize+=81920;stackBase=GROWABLE_HEAP_I32()[attr+8>>2];detached=GROWABLE_HEAP_I32()[attr+12>>2]!==0;var inheritSched=GROWABLE_HEAP_I32()[attr+16>>2]===0;if(inheritSched){var prevSchedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];var prevSchedPrio=GROWABLE_HEAP_I32()[attr+24>>2];var parentThreadPtr=PThread.currentProxiedOperationCallerThread?PThread.currentProxiedOperationCallerThread:_pthread_self();_pthread_getschedparam(parentThreadPtr,attr+20,attr+24);schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];GROWABLE_HEAP_I32()[attr+20>>2]=prevSchedPolicy;GROWABLE_HEAP_I32()[attr+24>>2]=prevSchedPrio;}else{schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];}}else{stackSize=2097152;}var allocatedOwnStack=stackBase==0;if(allocatedOwnStack){stackBase=_memalign(16,stackSize);}else{stackBase-=stackSize;assert(stackBase>0);}var threadInfoStruct=_malloc(232);for(var i=0;i<232>>2;++i)GROWABLE_HEAP_U32()[(threadInfoStruct>>2)+i]=0;GROWABLE_HEAP_I32()[pthread_ptr>>2]=threadInfoStruct;GROWABLE_HEAP_I32()[threadInfoStruct+12>>2]=threadInfoStruct;var headPtr=threadInfoStruct+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var threadParams={stackBase:stackBase,stackSize:stackSize,allocatedOwnStack:allocatedOwnStack,schedPolicy:schedPolicy,schedPrio:schedPrio,detached:detached,startRoutine:start_routine,pthread_ptr:threadInfoStruct,parent_pthread_ptr:_pthread_self(),arg:arg,transferList:transferList};if(ENVIRONMENT_IS_PTHREAD){threadParams.cmd="spawnThread";postMessage(threadParams,transferList);}else{__spawn_thread(threadParams);}return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}function _sysconf(name){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(6,1,name);switch(name){case 30:return 16384;case 85:var maxHeapSize=1073741824;return maxHeapSize/16384;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:case 79:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return -1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}setErrNo(28);return -1}if(!ENVIRONMENT_IS_PTHREAD)PThread.initMainThreadBlock();else PThread.initWorker();var GLctx;GL.init();var proxiedFunctionTable=[null,_atexit,_emscripten_set_canvas_element_size_main_thread,_fd_close,_fd_seek,_fd_write,_sysconf];var asmLibraryArg={"__assert_fail":___assert_fail,"__call_main":___call_main,"__handle_stack_overflow":___handle_stack_overflow,"_emscripten_notify_thread_queue":__emscripten_notify_thread_queue,"abort":_abort,"emscripten_conditional_set_current_thread_status":_emscripten_conditional_set_current_thread_status,"emscripten_futex_wait":_emscripten_futex_wait,"emscripten_futex_wake":_emscripten_futex_wake,"emscripten_get_now":_emscripten_get_now,"emscripten_is_main_browser_thread":_emscripten_is_main_browser_thread,"emscripten_is_main_runtime_thread":_emscripten_is_main_runtime_thread,"emscripten_memcpy_big":_emscripten_memcpy_big,"emscripten_receive_on_main_thread_js":_emscripten_receive_on_main_thread_js,"emscripten_resize_heap":_emscripten_resize_heap,"emscripten_set_canvas_element_size":_emscripten_set_canvas_element_size,"emscripten_set_current_thread_status":_emscripten_set_current_thread_status,"emscripten_set_thread_name":_emscripten_set_thread_name,"emscripten_webgl_create_context":_emscripten_webgl_create_context,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"initPthreadsJS":initPthreadsJS,"memory":wasmMemory||Module["wasmMemory"],"pthread_cleanup_pop":_pthread_cleanup_pop,"pthread_cleanup_push":_pthread_cleanup_push,"pthread_create":_pthread_create,"pthread_self":_pthread_self,"roundf":_roundf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__wasm_call_ctors"].apply(null,arguments)};var _init=Module["_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["init"].apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["register_tensor"].apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose_data"].apply(null,arguments)};var _dispose=Module["_dispose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose"].apply(null,arguments)};var _Abs=Module["_Abs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Abs"].apply(null,arguments)};var _Add=Module["_Add"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Add"].apply(null,arguments)};var _AddN=Module["_AddN"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AddN"].apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ArgMax"].apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AvgPool"].apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["BatchMatMul"].apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ClipByValue"].apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2D"].apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2DBackpropInput"].apply(null,arguments)};var _Cos=Module["_Cos"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Cos"].apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["CropAndResize"].apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["DepthwiseConv2dNative"].apply(null,arguments)};var _Div=Module["_Div"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Div"].apply(null,arguments)};var _Equal=Module["_Equal"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Equal"].apply(null,arguments)};var _Exp=Module["_Exp"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Exp"].apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FloorDiv"].apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedBatchNorm"].apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedConv2D"].apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedDepthwiseConv2D"].apply(null,arguments)};var _Gather=Module["_Gather"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Gather"].apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GatherNd"].apply(null,arguments)};var _Greater=Module["_Greater"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Greater"].apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GreaterEqual"].apply(null,arguments)};var _Less=Module["_Less"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Less"].apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LessEqual"].apply(null,arguments)};var _Log=Module["_Log"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Log"].apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LogicalAnd"].apply(null,arguments)};var _Max=Module["_Max"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Max"].apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["MaxPool"].apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Maximum"].apply(null,arguments)};var _Min=Module["_Min"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Min"].apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Minimum"].apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Multiply"].apply(null,arguments)};var _Negate=Module["_Negate"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Negate"].apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV3"].apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV4"].apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV5"].apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NotEqual"].apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["OneHot"].apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["PadV2"].apply(null,arguments)};var _Pow=Module["_Pow"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Pow"].apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Prelu"].apply(null,arguments)};var _Relu=Module["_Relu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu"].apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu6"].apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ResizeBilinear"].apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Reverse"].apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["RotateWithOffset"].apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Rsqrt"].apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ScatterNd"].apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["SelectV2"].apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sigmoid"].apply(null,arguments)};var _Sin=Module["_Sin"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sin"].apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Softmax"].apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sqrt"].apply(null,arguments)};var _Square=Module["_Square"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Square"].apply(null,arguments)};var _Sub=Module["_Sub"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sub"].apply(null,arguments)};var _Sum=Module["_Sum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sum"].apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tanh"].apply(null,arguments)};var _Tile=Module["_Tile"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tile"].apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Transpose"].apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["_FusedMatMul"].apply(null,arguments)};var _malloc=Module["_malloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["malloc"].apply(null,arguments)};var _free=Module["_free"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["free"].apply(null,arguments)};var ___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__em_js__initPthreadsJS"].apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__errno_location"].apply(null,arguments)};var _emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_get_global_libc"].apply(null,arguments)};var _memalign=Module["_memalign"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["memalign"].apply(null,arguments)};var ___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__pthread_tsd_run_dtors"].apply(null,arguments)};var _emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_current_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_register_main_browser_thread_id"].apply(null,arguments)};var _emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_browser_thread_id"].apply(null,arguments)};var _emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_0"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_1"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_2"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_xprintf_varargs"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_3"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_4"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_5"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_6"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_7"].apply(null,arguments)};var _emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_run_in_main_runtime_thread_js"].apply(null,arguments)};var _emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_queue_on_thread_"].apply(null,arguments)};var _emscripten_tls_init=Module["_emscripten_tls_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_tls_init"].apply(null,arguments)};var ___set_stack_limit=Module["___set_stack_limit"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__set_stack_limit"].apply(null,arguments)};var stackSave=Module["stackSave"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackSave"].apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackAlloc"].apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackRestore"].apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_vi"].apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_v"].apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_ii"].apply(null,arguments)};Module["asm"]=asm;if(!Object.getOwnPropertyDescriptor(Module,"intArrayFromString"))Module["intArrayFromString"]=function(){abort("'intArrayFromString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"intArrayToString"))Module["intArrayToString"]=function(){abort("'intArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ccall"))Module["ccall"]=function(){abort("'ccall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["cwrap"]=cwrap;if(!Object.getOwnPropertyDescriptor(Module,"setValue"))Module["setValue"]=function(){abort("'setValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getValue"))Module["getValue"]=function(){abort("'getValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocate"))Module["allocate"]=function(){abort("'allocate' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getMemory"))Module["getMemory"]=function(){abort("'getMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ArrayToString"))Module["UTF8ArrayToString"]=function(){abort("'UTF8ArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ToString"))Module["UTF8ToString"]=function(){abort("'UTF8ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8Array"))Module["stringToUTF8Array"]=function(){abort("'stringToUTF8Array' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8"))Module["stringToUTF8"]=function(){abort("'stringToUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF8"))Module["lengthBytesUTF8"]=function(){abort("'lengthBytesUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreRun"))Module["addOnPreRun"]=function(){abort("'addOnPreRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnInit"))Module["addOnInit"]=function(){abort("'addOnInit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreMain"))Module["addOnPreMain"]=function(){abort("'addOnPreMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnExit"))Module["addOnExit"]=function(){abort("'addOnExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPostRun"))Module["addOnPostRun"]=function(){abort("'addOnPostRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeStringToMemory"))Module["writeStringToMemory"]=function(){abort("'writeStringToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeArrayToMemory"))Module["writeArrayToMemory"]=function(){abort("'writeArrayToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeAsciiToMemory"))Module["writeAsciiToMemory"]=function(){abort("'writeAsciiToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addRunDependency"))Module["addRunDependency"]=function(){abort("'addRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"removeRunDependency"))Module["removeRunDependency"]=function(){abort("'removeRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createFolder"))Module["FS_createFolder"]=function(){abort("'FS_createFolder' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPath"))Module["FS_createPath"]=function(){abort("'FS_createPath' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDataFile"))Module["FS_createDataFile"]=function(){abort("'FS_createDataFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPreloadedFile"))Module["FS_createPreloadedFile"]=function(){abort("'FS_createPreloadedFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLazyFile"))Module["FS_createLazyFile"]=function(){abort("'FS_createLazyFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLink"))Module["FS_createLink"]=function(){abort("'FS_createLink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDevice"))Module["FS_createDevice"]=function(){abort("'FS_createDevice' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_unlink"))Module["FS_unlink"]=function(){abort("'FS_unlink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"dynamicAlloc"))Module["dynamicAlloc"]=function(){abort("'dynamicAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadDynamicLibrary"))Module["loadDynamicLibrary"]=function(){abort("'loadDynamicLibrary' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadWebAssemblyModule"))Module["loadWebAssemblyModule"]=function(){abort("'loadWebAssemblyModule' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getLEB"))Module["getLEB"]=function(){abort("'getLEB' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFunctionTables"))Module["getFunctionTables"]=function(){abort("'getFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"alignFunctionTables"))Module["alignFunctionTables"]=function(){abort("'alignFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"registerFunctions"))Module["registerFunctions"]=function(){abort("'registerFunctions' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addFunction"))Module["addFunction"]=function(){abort("'addFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"removeFunction"))Module["removeFunction"]=function(){abort("'removeFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFuncWrapper"))Module["getFuncWrapper"]=function(){abort("'getFuncWrapper' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"prettyPrint"))Module["prettyPrint"]=function(){abort("'prettyPrint' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"makeBigInt"))Module["makeBigInt"]=function(){abort("'makeBigInt' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"dynCall"))Module["dynCall"]=function(){abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getCompilerSetting"))Module["getCompilerSetting"]=function(){abort("'getCompilerSetting' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"print"))Module["print"]=function(){abort("'print' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"printErr"))Module["printErr"]=function(){abort("'printErr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getTempRet0"))Module["getTempRet0"]=function(){abort("'getTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setTempRet0"))Module["setTempRet0"]=function(){abort("'setTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"callMain"))Module["callMain"]=function(){abort("'callMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"abort"))Module["abort"]=function(){abort("'abort' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToNewUTF8"))Module["stringToNewUTF8"]=function(){abort("'stringToNewUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscripten_realloc_buffer"))Module["emscripten_realloc_buffer"]=function(){abort("'emscripten_realloc_buffer' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ENV"))Module["ENV"]=function(){abort("'ENV' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setjmpId"))Module["setjmpId"]=function(){abort("'setjmpId' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_CODES"))Module["ERRNO_CODES"]=function(){abort("'ERRNO_CODES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_MESSAGES"))Module["ERRNO_MESSAGES"]=function(){abort("'ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setErrNo"))Module["setErrNo"]=function(){abort("'setErrNo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"DNS"))Module["DNS"]=function(){abort("'DNS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GAI_ERRNO_MESSAGES"))Module["GAI_ERRNO_MESSAGES"]=function(){abort("'GAI_ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Protocols"))Module["Protocols"]=function(){abort("'Protocols' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Sockets"))Module["Sockets"]=function(){abort("'Sockets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UNWIND_CACHE"))Module["UNWIND_CACHE"]=function(){abort("'UNWIND_CACHE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readAsmConstArgs"))Module["readAsmConstArgs"]=function(){abort("'readAsmConstArgs' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_q"))Module["jstoi_q"]=function(){abort("'jstoi_q' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_s"))Module["jstoi_s"]=function(){abort("'jstoi_s' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"reallyNegative"))Module["reallyNegative"]=function(){abort("'reallyNegative' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"formatString"))Module["formatString"]=function(){abort("'formatString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH"))Module["PATH"]=function(){abort("'PATH' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH_FS"))Module["PATH_FS"]=function(){abort("'PATH_FS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SYSCALLS"))Module["SYSCALLS"]=function(){abort("'SYSCALLS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMmap2"))Module["syscallMmap2"]=function(){abort("'syscallMmap2' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMunmap"))Module["syscallMunmap"]=function(){abort("'syscallMunmap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"flush_NO_FILESYSTEM"))Module["flush_NO_FILESYSTEM"]=function(){abort("'flush_NO_FILESYSTEM' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"JSEvents"))Module["JSEvents"]=function(){abort("'JSEvents' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"specialHTMLTargets"))Module["specialHTMLTargets"]=function(){abort("'specialHTMLTargets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangle"))Module["demangle"]=function(){abort("'demangle' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangleAll"))Module["demangleAll"]=function(){abort("'demangleAll' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jsStackTrace"))Module["jsStackTrace"]=function(){abort("'jsStackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getEnvStrings"))Module["getEnvStrings"]=function(){abort("'getEnvStrings' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64"))Module["writeI53ToI64"]=function(){abort("'writeI53ToI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Clamped"))Module["writeI53ToI64Clamped"]=function(){abort("'writeI53ToI64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Signaling"))Module["writeI53ToI64Signaling"]=function(){abort("'writeI53ToI64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Clamped"))Module["writeI53ToU64Clamped"]=function(){abort("'writeI53ToU64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Signaling"))Module["writeI53ToU64Signaling"]=function(){abort("'writeI53ToU64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromI64"))Module["readI53FromI64"]=function(){abort("'readI53FromI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromU64"))Module["readI53FromU64"]=function(){abort("'readI53FromU64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertI32PairToI53"))Module["convertI32PairToI53"]=function(){abort("'convertI32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertU32PairToI53"))Module["convertU32PairToI53"]=function(){abort("'convertU32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Browser"))Module["Browser"]=function(){abort("'Browser' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GL"))Module["GL"]=function(){abort("'GL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGet"))Module["emscriptenWebGLGet"]=function(){abort("'emscriptenWebGLGet' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetTexPixelData"))Module["emscriptenWebGLGetTexPixelData"]=function(){abort("'emscriptenWebGLGetTexPixelData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetUniform"))Module["emscriptenWebGLGetUniform"]=function(){abort("'emscriptenWebGLGetUniform' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetVertexAttrib"))Module["emscriptenWebGLGetVertexAttrib"]=function(){abort("'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AL"))Module["AL"]=function(){abort("'AL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_unicode"))Module["SDL_unicode"]=function(){abort("'SDL_unicode' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_ttfContext"))Module["SDL_ttfContext"]=function(){abort("'SDL_ttfContext' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_audio"))Module["SDL_audio"]=function(){abort("'SDL_audio' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL"))Module["SDL"]=function(){abort("'SDL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_gfx"))Module["SDL_gfx"]=function(){abort("'SDL_gfx' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLUT"))Module["GLUT"]=function(){abort("'GLUT' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"EGL"))Module["EGL"]=function(){abort("'EGL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW_Window"))Module["GLFW_Window"]=function(){abort("'GLFW_Window' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW"))Module["GLFW"]=function(){abort("'GLFW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLEW"))Module["GLEW"]=function(){abort("'GLEW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"IDBStore"))Module["IDBStore"]=function(){abort("'IDBStore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"runAndAbortIfError"))Module["runAndAbortIfError"]=function(){abort("'runAndAbortIfError' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["PThread"]=PThread;if(!Object.getOwnPropertyDescriptor(Module,"establishStackSpace"))Module["establishStackSpace"]=function(){abort("'establishStackSpace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getNoExitRuntime"))Module["getNoExitRuntime"]=function(){abort("'getNoExitRuntime' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"resetPrototype"))Module["resetPrototype"]=function(){abort("'resetPrototype' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"warnOnce"))Module["warnOnce"]=function(){abort("'warnOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackSave"))Module["stackSave"]=function(){abort("'stackSave' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackRestore"))Module["stackRestore"]=function(){abort("'stackRestore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackAlloc"))Module["stackAlloc"]=function(){abort("'stackAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AsciiToString"))Module["AsciiToString"]=function(){abort("'AsciiToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToAscii"))Module["stringToAscii"]=function(){abort("'stringToAscii' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF16ToString"))Module["UTF16ToString"]=function(){abort("'UTF16ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF16"))Module["stringToUTF16"]=function(){abort("'stringToUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF16"))Module["lengthBytesUTF16"]=function(){abort("'lengthBytesUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF32ToString"))Module["UTF32ToString"]=function(){abort("'UTF32ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF32"))Module["stringToUTF32"]=function(){abort("'stringToUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF32"))Module["lengthBytesUTF32"]=function(){abort("'lengthBytesUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8"))Module["allocateUTF8"]=function(){abort("'allocateUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8OnStack"))Module["allocateUTF8OnStack"]=function(){abort("'allocateUTF8OnStack' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["writeStackCookie"]=writeStackCookie;Module["checkStackCookie"]=checkStackCookie;Module["abortStackOverflow"]=abortStackOverflow;Module["PThread"]=PThread;Module["_pthread_self"]=_pthread_self;Module["wasmMemory"]=wasmMemory;Module["ExitStatus"]=ExitStatus;if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NORMAL"))Object.defineProperty(Module,"ALLOC_NORMAL",{configurable:true,get:function(){abort("'ALLOC_NORMAL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_STACK"))Object.defineProperty(Module,"ALLOC_STACK",{configurable:true,get:function(){abort("'ALLOC_STACK' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_DYNAMIC"))Object.defineProperty(Module,"ALLOC_DYNAMIC",{configurable:true,get:function(){abort("'ALLOC_DYNAMIC' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NONE"))Object.defineProperty(Module,"ALLOC_NONE",{configurable:true,get:function(){abort("'ALLOC_NONE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}writeStackCookie();preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();assert(!Module["_main"],'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}checkStackCookie();}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}if(!ENVIRONMENT_IS_PTHREAD)noExitRuntime=true;if(!ENVIRONMENT_IS_PTHREAD)run(); - - - return WasmBackendModuleSimd - } - ); - })(); - module.exports = WasmBackendModuleSimd; - }); - - const wasmWorkerContents = 'var threadInfoStruct=0;var selfThreadId=0;var parentThreadId=0;var Module={};function assert(condition,text){if(!condition)abort("Assertion failed: "+text)}function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:selfThreadId})}var out=function(){throw"out() is not defined in worker.js."};var err=threadPrintErr;this.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);Module["wasmModule"]=null;receiveInstance(instance);return instance.exports};this.onmessage=function(e){try{if(e.data.cmd==="load"){Module["DYNAMIC_BASE"]=e.data.DYNAMIC_BASE;Module["DYNAMICTOP_PTR"]=e.data.DYNAMICTOP_PTR;Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob==="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}Module=WasmBackendModuleSimd(Module);postMessage({"cmd":"loaded"})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;threadInfoStruct=e.data.threadInfoStruct;Module["__register_pthread_ptr"](threadInfoStruct,0,0);selfThreadId=e.data.selfThreadId;parentThreadId=e.data.parentThreadId;var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;assert(threadInfoStruct);assert(selfThreadId);assert(parentThreadId);assert(top!=0);assert(max!=0);assert(top>max);Module["establishStackSpace"](top,max);Module["_emscripten_tls_init"]();Module["writeStackCookie"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].setThreadStatus(Module["_pthread_self"](),1);try{var result=Module["dynCall_ii"](e.data.start_routine,e.data.arg);Module["checkStackCookie"]();if(!Module["getNoExitRuntime"]())Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){Atomics.store(Module["HEAPU32"],threadInfoStruct+4>>2,ex instanceof Module["ExitStatus"]?ex.status:-2);Atomics.store(Module["HEAPU32"],threadInfoStruct+0>>2,1);if(typeof Module["_emscripten_futex_wake"]!=="function"){err("Thread Initialisation failed.");throw ex}Module["_emscripten_futex_wake"](threadInfoStruct+0,2147483647);if(!(ex instanceof Module["ExitStatus"]))throw ex}else{err("Pthread 0x"+threadInfoStruct.toString(16)+" completed its pthread main entry point with an unwind, keeping the pthread worker alive for asynchronous operation.")}}}else if(e.data.cmd==="cancel"){if(threadInfoStruct){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(threadInfoStruct){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex.stack)err(ex.stack);throw ex}};if(typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string"){self={location:{href:__filename}};var onmessage=this.onmessage;var nodeWorkerThreads=require("worker_threads");Worker=nodeWorkerThreads.Worker;var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var nodeFS=require("fs");var nodeRead=function(filename){return nodeFS.readFileSync(filename,"utf8")};function globalEval(x){global.require=require;global.Module=Module;eval.call(null,x)}importScripts=function(f){globalEval(nodeRead(f))};postMessage=function(msg){parentPort.postMessage(msg)};if(typeof performance==="undefined"){performance={now:function(){return Date.now()}}}}'; - - var tfjsBackendWasm = createCommonjsModule(function (module, exports) { - var WasmBackendModule = (function() { - var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; - if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; - return ( - function(WasmBackendModule) { - WasmBackendModule = WasmBackendModule || {}; - - var Module=typeof WasmBackendModule!=="undefined"?WasmBackendModule:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":146,"maximum":146+0,"element":"anyfunc"});var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023);}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var DYNAMIC_BASE=5254800,DYNAMICTOP_PTR=11760;var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":2147483648/WASM_PAGE_SIZE});}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;removeRunDependency();}addRunDependency();function receiveInstantiatedSource(output){receiveInstance(output["instance"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}__ATINIT__.push({func:function(){___wasm_call_ctors();}});function _abort(){abort();}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num);}function _emscripten_get_heap_size(){return HEAPU8.length}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=65536;var maxHeapSize=2147483648;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}var asmLibraryArg={"a":_abort,"e":_emscripten_memcpy_big,"f":_emscripten_resize_heap,"g":_fd_close,"d":_fd_seek,"c":_fd_write,"memory":wasmMemory,"b":_roundf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return (___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["h"]).apply(null,arguments)};var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["i"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["j"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["k"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["l"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["m"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["n"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["o"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["p"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["q"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["r"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["s"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["t"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["u"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["v"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["w"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["x"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["y"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["z"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["A"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["B"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["C"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["D"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["E"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["F"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["G"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["H"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["I"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["J"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["K"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["L"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["M"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["N"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["O"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["P"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["Q"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["R"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["S"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["T"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["U"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["V"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["W"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["X"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["Y"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["Z"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["_"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["$"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["aa"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["ba"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["ca"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["da"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["ea"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["fa"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["ga"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["ha"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["ia"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["ja"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["ka"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["la"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["ma"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["na"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["oa"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["pa"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["qa"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["ra"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["sa"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["ta"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["ua"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["va"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["wa"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["xa"]).apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){return (dynCall_vi=Module["dynCall_vi"]=Module["asm"]["ya"]).apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){return (dynCall_v=Module["dynCall_v"]=Module["asm"]["za"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}noExitRuntime=true;run(); - - - return WasmBackendModule - } - ); - })(); - module.exports = WasmBackendModule; - }); - + }); + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var tfjsBackendWasmThreadedSimd = createCommonjsModule(function (module, exports) { + var WasmBackendModuleSimd = (function() { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( + function(WasmBackendModuleSimd) { + WasmBackendModuleSimd = WasmBackendModuleSimd || {}; + + function GROWABLE_HEAP_I8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP8}function GROWABLE_HEAP_U8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU8}function GROWABLE_HEAP_I32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP32}function GROWABLE_HEAP_U32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPF64}var Module=typeof WasmBackendModuleSimd!=="undefined"?WasmBackendModuleSimd:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(Module["ENVIRONMENT"]){throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -s ENVIRONMENT=web or -s ENVIRONMENT=node)")}var ENVIRONMENT_IS_PTHREAD=Module["ENVIRONMENT_IS_PTHREAD"]||false;if(ENVIRONMENT_IS_PTHREAD){buffer=Module["buffer"];DYNAMIC_BASE=Module["DYNAMIC_BASE"];DYNAMICTOP_PTR=Module["DYNAMICTOP_PTR"];}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};var nodeWorkerThreads;try{nodeWorkerThreads=worker_threads;}catch(e){console.error('The "worker_threads" module is not supported in this node.js build - perhaps a newer version is needed?');throw e}Worker=nodeWorkerThreads.Worker;}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}if(ENVIRONMENT_IS_NODE){read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};}else{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}else{throw new Error("environment detection error")}if(ENVIRONMENT_IS_NODE){if(typeof performance==="undefined"){performance=perf_hooks.performance;}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(!Object.getOwnPropertyDescriptor(Module,"arguments"))Object.defineProperty(Module,"arguments",{configurable:true,get:function(){abort("Module.arguments has been replaced with plain arguments_");}});if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(!Object.getOwnPropertyDescriptor(Module,"thisProgram"))Object.defineProperty(Module,"thisProgram",{configurable:true,get:function(){abort("Module.thisProgram has been replaced with plain thisProgram");}});if(Module["quit"])quit_=Module["quit"];if(!Object.getOwnPropertyDescriptor(Module,"quit"))Object.defineProperty(Module,"quit",{configurable:true,get:function(){abort("Module.quit has been replaced with plain quit_");}});assert(typeof Module["memoryInitializerPrefixURL"]==="undefined","Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["pthreadMainPrefixURL"]==="undefined","Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["cdInitializerPrefixURL"]==="undefined","Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["filePackagePrefixURL"]==="undefined","Module.filePackagePrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["read"]==="undefined","Module.read option was removed (modify read_ in JS)");assert(typeof Module["readAsync"]==="undefined","Module.readAsync option was removed (modify readAsync in JS)");assert(typeof Module["readBinary"]==="undefined","Module.readBinary option was removed (modify readBinary in JS)");assert(typeof Module["setWindowTitle"]==="undefined","Module.setWindowTitle option was removed (modify setWindowTitle in JS)");assert(typeof Module["TOTAL_MEMORY"]==="undefined","Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");if(!Object.getOwnPropertyDescriptor(Module,"read"))Object.defineProperty(Module,"read",{configurable:true,get:function(){abort("Module.read has been replaced with plain read_");}});if(!Object.getOwnPropertyDescriptor(Module,"readAsync"))Object.defineProperty(Module,"readAsync",{configurable:true,get:function(){abort("Module.readAsync has been replaced with plain readAsync");}});if(!Object.getOwnPropertyDescriptor(Module,"readBinary"))Object.defineProperty(Module,"readBinary",{configurable:true,get:function(){abort("Module.readBinary has been replaced with plain readBinary");}});if(!Object.getOwnPropertyDescriptor(Module,"setWindowTitle"))Object.defineProperty(Module,"setWindowTitle",{configurable:true,get:function(){abort("Module.setWindowTitle has been replaced with plain setWindowTitle");}});assert(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER||ENVIRONMENT_IS_NODE,"Pthreads do not work in this environment yet (need Web Workers, or an alternative to them)");var stackSave;var stackRestore;var stackAlloc;stackSave=stackRestore=stackAlloc=function(){abort("cannot use the stack before compiled code is ready to run, and has provided stack access");};function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text);}}var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(!Object.getOwnPropertyDescriptor(Module,"wasmBinary"))Object.defineProperty(Module,"wasmBinary",{configurable:true,get:function(){abort("Module.wasmBinary has been replaced with plain wasmBinary");}});var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(!Object.getOwnPropertyDescriptor(Module,"noExitRuntime"))Object.defineProperty(Module,"noExitRuntime",{configurable:true,get:function(){abort("Module.noExitRuntime has been replaced with plain noExitRuntime");}});if(typeof WebAssembly!=="object"){abort("No WebAssembly support found. Build with -s WASM=0 to target JavaScript instead.");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":165,"maximum":165+0,"element":"anyfunc"});var wasmModule;var threadInfoStruct=0;var selfThreadId=0;var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;assert(returnType!=="array",'Return type should not be "array".');if(args){for(var i=0;i=endIdx)){var u0=heap[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heap[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heap[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2;}else{if((u0&248)!=240)warnOnce("Invalid UTF-8 leading byte 0x"+u0.toString(16)+" encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!");u0=(u0&7)<<18|u1<<12|u2<<6|heap[idx++]&63;}if(u0<65536){str+=String.fromCharCode(u0);}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023);}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;if(u>=2097152)warnOnce("Invalid Unicode code point 0x"+u.toString(16)+" encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).");heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){assert(typeof maxBytesToWrite=="number","stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");return stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4;}return len}function writeArrayToMemory(array,buffer){assert(array.length>=0,"writeArrayToMemory array must have a length (should be an array or typed array)");GROWABLE_HEAP_I8().set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var STACK_BASE=5256288,STACKTOP=STACK_BASE,STACK_MAX=13408,DYNAMIC_BASE=5256288,DYNAMICTOP_PTR=12480;assert(STACK_BASE%16===0,"stack must start aligned");assert(DYNAMIC_BASE%16===0,"heap must start aligned");if(ENVIRONMENT_IS_PTHREAD){STACK_MAX=STACKTOP=STACK_MAX=2147483647;}var TOTAL_STACK=5242880;if(Module["TOTAL_STACK"])assert(TOTAL_STACK===Module["TOTAL_STACK"],"the stack size can no longer be determined at runtime");var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||1073741824;if(!Object.getOwnPropertyDescriptor(Module,"INITIAL_MEMORY"))Object.defineProperty(Module,"INITIAL_MEMORY",{configurable:true,get:function(){abort("Module.INITIAL_MEMORY has been replaced with plain INITIAL_INITIAL_MEMORY");}});assert(INITIAL_INITIAL_MEMORY>=TOTAL_STACK,"INITIAL_MEMORY should be larger than TOTAL_STACK, was "+INITIAL_INITIAL_MEMORY+"! (TOTAL_STACK="+TOTAL_STACK+")");assert(typeof Int32Array!=="undefined"&&typeof Float64Array!=="undefined"&&Int32Array.prototype.subarray!==undefined&&Int32Array.prototype.set!==undefined,"JS engine does not provide full typed array support");if(ENVIRONMENT_IS_PTHREAD){wasmMemory=Module["wasmMemory"];buffer=Module["buffer"];}else{if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":1073741824/WASM_PAGE_SIZE,"shared":true});if(!(wasmMemory.buffer instanceof SharedArrayBuffer)){err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");if(ENVIRONMENT_IS_NODE){console.log("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)");}throw Error("bad memory")}}}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;assert(INITIAL_INITIAL_MEMORY%WASM_PAGE_SIZE===0);assert(65536%WASM_PAGE_SIZE===0);updateGlobalBufferAndViews(buffer);if(!ENVIRONMENT_IS_PTHREAD){GROWABLE_HEAP_I32()[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;}function writeStackCookie(){assert((STACK_MAX&3)==0);GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1]=34821223;GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2]=2310721022;GROWABLE_HEAP_I32()[0]=1668509029;}function checkStackCookie(){var cookie1=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1];var cookie2=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2];if(cookie1!=34821223||cookie2!=2310721022){abort("Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x"+cookie2.toString(16)+" "+cookie1.toString(16));}if(GROWABLE_HEAP_I32()[0]!==1668509029)abort("Runtime error: The application has corrupted its heap memory area (address zero)!");}function abortStackOverflow(allocSize){abort("Stack overflow! Attempted to allocate "+allocSize+" bytes on the stack, but stack has only "+(STACK_MAX-stackSave()+allocSize)+" bytes available!");}(function(){var h16=new Int16Array(1);var h8=new Int8Array(h16.buffer);h16[0]=25459;if(h8[0]!==115||h8[1]!==99)throw "Runtime error: expected the system to be little-endian!"})();function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;if(ENVIRONMENT_IS_PTHREAD)runtimeInitialized=true;function preRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){checkStackCookie();assert(!runtimeInitialized);runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__);}function preMain(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;callRuntimeCallbacks(__ATMAIN__);}function postRun(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}assert(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;var runDependencyTracking={};function addRunDependency(id){assert(!ENVIRONMENT_IS_PTHREAD,"addRunDependency cannot be used in a pthread worker");runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(!runDependencyTracking[id]);runDependencyTracking[id]=1;if(runDependencyWatcher===null&&typeof setInterval!=="undefined"){runDependencyWatcher=setInterval(function(){if(ABORT){clearInterval(runDependencyWatcher);runDependencyWatcher=null;return}var shown=false;for(var dep in runDependencyTracking){if(!shown){shown=true;err("still waiting on run dependencies:");}err("dependency: "+dep);}if(shown){err("(end of list)");}},1e4);}}else{err("warning: run dependency added without ID");}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(runDependencyTracking[id]);delete runDependencyTracking[id];}else{err("warning: run dependency removed without ID");}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}if(ENVIRONMENT_IS_PTHREAD)console.error("Pthread aborting at "+(new Error).stack);what+="";out(what);err(what);ABORT=true;var output="abort("+what+") at "+stackTrace();what=output;throw new WebAssembly.RuntimeError(what)}var FS={error:function(){abort("Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -s FORCE_FILESYSTEM=1");},init:function(){FS.error();},createDataFile:function(){FS.error();},createPreloadedFile:function(){FS.error();},createLazyFile:function(){FS.error();},open:function(){FS.error();},mkdev:function(){FS.error();},registerDevice:function(){FS.error();},analyzePath:function(){FS.error();},loadFilesFromDB:function(){FS.error();},ErrnoError:function ErrnoError(){FS.error();}};Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm-threaded-simd.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmModule=module;if(!ENVIRONMENT_IS_PTHREAD){var numWorkersToLoad=PThread.unusedWorkers.length;PThread.unusedWorkers.forEach(function(w){PThread.loadWasmModuleToWorker(w,function(){if(!--numWorkersToLoad)removeRunDependency("wasm-instantiate");});});}}if(!ENVIRONMENT_IS_PTHREAD){addRunDependency("wasm-instantiate");}var trueModule=Module;function receiveInstantiatedSource(output){assert(Module===trueModule,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");trueModule=null;receiveInstance(output["instance"],output["module"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}var ASM_CONSTS={};function initPthreadsJS(){PThread.initRuntime();}if(!ENVIRONMENT_IS_PTHREAD)__ATINIT__.push({func:function(){___wasm_call_ctors();}});function demangle(func){warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling");return func}function demangleAll(text){var regex=/\b_Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}var __pthread_ptr=0;var __pthread_is_main_runtime_thread=0;var __pthread_is_main_browser_thread=0;function __register_pthread_ptr(pthreadPtr,isMainBrowserThread,isMainRuntimeThread){pthreadPtr=pthreadPtr|0;isMainBrowserThread=isMainBrowserThread|0;isMainRuntimeThread=isMainRuntimeThread|0;__pthread_ptr=pthreadPtr;__pthread_is_main_browser_thread=isMainBrowserThread;__pthread_is_main_runtime_thread=isMainRuntimeThread;}Module["__register_pthread_ptr"]=__register_pthread_ptr;var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var __main_thread_futex_wait_address=13392;function _emscripten_futex_wake(addr,count){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0||count<0)return -28;if(count==0)return 0;if(count>=2147483647)count=Infinity;var mainThreadWaitAddress=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);var mainThreadWoken=0;if(mainThreadWaitAddress==addr){var loadedAddr=Atomics.compareExchange(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,mainThreadWaitAddress,0);if(loadedAddr==mainThreadWaitAddress){--count;mainThreadWoken=1;if(count<=0)return 1}}var ret=Atomics.notify(GROWABLE_HEAP_I32(),addr>>2,count);if(ret>=0)return ret+mainThreadWoken;throw "Atomics.notify returned an unexpected value "+ret}Module["_emscripten_futex_wake"]=_emscripten_futex_wake;function __kill_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _kill_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _kill_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];pthread.worker.terminate();PThread.freeThreadData(pthread);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(pthread.worker),1);pthread.worker.pthread=undefined;}function __cancel_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cancel_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cancel_thread!";var pthread=PThread.pthreads[pthread_ptr];pthread.worker.postMessage({"cmd":"cancel"});}function __cleanup_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cleanup_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cleanup_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];if(pthread){var worker=pthread.worker;PThread.returnWorkerToPool(worker);}}var PThread={MAIN_THREAD_ID:1,mainThreadInfo:{schedPolicy:0,schedPrio:0},unusedWorkers:[],runningWorkers:[],initRuntime:function(){__register_pthread_ptr(PThread.mainThreadBlock,!ENVIRONMENT_IS_WORKER,1);_emscripten_register_main_browser_thread_id(PThread.mainThreadBlock);},initMainThreadBlock:function(){assert(!ENVIRONMENT_IS_PTHREAD);var pthreadPoolSize=8;for(var i=0;i>2]=PThread.mainThreadBlock;var headPtr=PThread.mainThreadBlock+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var tlsMemory=12880;for(var i=0;i<128;++i)GROWABLE_HEAP_U32()[tlsMemory/4+i]=0;Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+104>>2,tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+40>>2,PThread.mainThreadBlock);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+44>>2,42);},initWorker:function(){},pthreads:{},exitHandlers:null,setThreadStatus:function(){},runExitHandlers:function(){if(PThread.exitHandlers!==null){while(PThread.exitHandlers.length>0){PThread.exitHandlers.pop()();}PThread.exitHandlers=null;}if(ENVIRONMENT_IS_PTHREAD&&threadInfoStruct)___pthread_tsd_run_dtors();},threadExit:function(exitCode){var tb=_pthread_self();if(tb){err("Pthread 0x"+tb.toString(16)+" exited.");Atomics.store(GROWABLE_HEAP_U32(),tb+4>>2,exitCode);Atomics.store(GROWABLE_HEAP_U32(),tb+0>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+60>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+64>>2,0);PThread.runExitHandlers();_emscripten_futex_wake(tb+0,2147483647);__register_pthread_ptr(0,0,0);threadInfoStruct=0;if(ENVIRONMENT_IS_PTHREAD){postMessage({"cmd":"exit"});}}},threadCancel:function(){PThread.runExitHandlers();Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+4>>2,-1);Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+0>>2,1);_emscripten_futex_wake(threadInfoStruct+0,2147483647);threadInfoStruct=selfThreadId=0;__register_pthread_ptr(0,0,0);postMessage({"cmd":"cancelDone"});},terminateAllThreads:function(){for(var t in PThread.pthreads){var pthread=PThread.pthreads[t];if(pthread&&pthread.worker){PThread.returnWorkerToPool(pthread.worker);}}PThread.pthreads={};for(var i=0;i>2];GROWABLE_HEAP_I32()[pthread.threadInfoStruct+104>>2]=0;_free(tlsMemory);_free(pthread.threadInfoStruct);}pthread.threadInfoStruct=0;if(pthread.allocatedOwnStack&&pthread.stackBase)_free(pthread.stackBase);pthread.stackBase=0;if(pthread.worker)pthread.worker.pthread=null;},returnWorkerToPool:function(worker){delete PThread.pthreads[worker.pthread.thread];PThread.unusedWorkers.push(worker);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);PThread.freeThreadData(worker.pthread);worker.pthread=undefined;},receiveObjectTransfer:function(data){},loadWasmModuleToWorker:function(worker,onFinishedLoading){worker.onmessage=function(e){var d=e["data"];var cmd=d["cmd"];if(worker.pthread)PThread.currentProxiedOperationCallerThread=worker.pthread.threadInfoStruct;if(d["targetThread"]&&d["targetThread"]!=_pthread_self()){var thread=PThread.pthreads[d.targetThread];if(thread){thread.worker.postMessage(e.data,d["transferList"]);}else{console.error('Internal error! Worker sent a message "'+cmd+'" to target pthread '+d["targetThread"]+", but that thread no longer exists!");}PThread.currentProxiedOperationCallerThread=undefined;return}if(cmd==="processQueuedMainThreadWork"){_emscripten_main_thread_process_queued_calls();}else if(cmd==="spawnThread"){__spawn_thread(e.data);}else if(cmd==="cleanupThread"){__cleanup_thread(d["thread"]);}else if(cmd==="killThread"){__kill_thread(d["thread"]);}else if(cmd==="cancelThread"){__cancel_thread(d["thread"]);}else if(cmd==="loaded"){worker.loaded=true;if(onFinishedLoading)onFinishedLoading(worker);if(worker.runPthread){worker.runPthread();delete worker.runPthread;}}else if(cmd==="print"){out("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="printErr"){err("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="alert"){alert("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="exit"){var detached=worker.pthread&&Atomics.load(GROWABLE_HEAP_U32(),worker.pthread.thread+68>>2);if(detached){PThread.returnWorkerToPool(worker);}}else if(cmd==="cancelDone"){PThread.returnWorkerToPool(worker);}else if(cmd==="objectTransfer"){PThread.receiveObjectTransfer(e.data);}else if(e.data.target==="setimmediate"){worker.postMessage(e.data);}else{err("worker sent an unknown command "+cmd);}PThread.currentProxiedOperationCallerThread=undefined;};worker.onerror=function(e){err("pthread sent an error! "+e.filename+":"+e.lineno+": "+e.message);};if(ENVIRONMENT_IS_NODE){worker.on("message",function(data){worker.onmessage({data:data});});worker.on("error",function(data){worker.onerror(data);});worker.on("exit",function(data){console.log("worker exited - TODO: update the worker queue?");});}assert(wasmMemory instanceof WebAssembly.Memory,"WebAssembly memory should have been loaded by now!");assert(wasmModule instanceof WebAssembly.Module,"WebAssembly Module should have been loaded by now!");worker.postMessage({"cmd":"load","urlOrBlob":Module["mainScriptUrlOrBlob"]||_scriptDir,"wasmMemory":wasmMemory,"wasmModule":wasmModule,"DYNAMIC_BASE":DYNAMIC_BASE,"DYNAMICTOP_PTR":DYNAMICTOP_PTR});},allocateUnusedWorker:function(){var pthreadMainJs=locateFile("tfjs-backend-wasm-threaded-simd.worker.js");PThread.unusedWorkers.push(new Worker(pthreadMainJs));},getNewWorker:function(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]);}if(PThread.unusedWorkers.length>0)return PThread.unusedWorkers.pop();else return null},busySpinWait:function(msecs){var t=performance.now()+msecs;while(performance.now()>2]=value;return value}function _atexit(func,arg){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(1,1,func,arg);warnOnce("atexit() called, but EXIT_RUNTIME is not set, so atexits() will not be called. set EXIT_RUNTIME to 1 (see the FAQ)");}function ___handle_stack_overflow(){abort("stack overflow");}function __emscripten_notify_thread_queue(targetThreadId,mainThreadId){if(targetThreadId==mainThreadId){postMessage({"cmd":"processQueuedMainThreadWork"});}else if(ENVIRONMENT_IS_PTHREAD){postMessage({"targetThread":targetThreadId,"cmd":"processThreadQueue"});}else{var pthread=PThread.pthreads[targetThreadId];var worker=pthread&&pthread.worker;if(!worker){err("Cannot send message to thread with ID "+targetThreadId+", unknown thread ID!");return}worker.postMessage({"cmd":"processThreadQueue"});}return 1}function _abort(){abort();}function _emscripten_conditional_set_current_thread_status(expectedStatus,newStatus){}function _emscripten_futex_wait(addr,val,timeout){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0)return -28;if(ENVIRONMENT_IS_WORKER){var ret=Atomics.wait(GROWABLE_HEAP_I32(),addr>>2,val,timeout);if(ret==="timed-out")return -73;if(ret==="not-equal")return -6;if(ret==="ok")return 0;throw "Atomics.wait returned an unexpected value "+ret}else{var loadedVal=Atomics.load(GROWABLE_HEAP_I32(),addr>>2);if(val!=loadedVal)return -6;var tNow=performance.now();var tEnd=tNow+timeout;Atomics.store(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,addr);var ourWaitAddress=addr;while(addr==ourWaitAddress){tNow=performance.now();if(tNow>tEnd){return -73}_emscripten_main_thread_process_queued_calls();addr=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);}return 0}}function _emscripten_is_main_browser_thread(){return __pthread_is_main_browser_thread|0}function _emscripten_is_main_runtime_thread(){return __pthread_is_main_runtime_thread|0}function _emscripten_memcpy_big(dest,src,num){GROWABLE_HEAP_U8().copyWithin(dest,src,src+num);}function _emscripten_proxy_to_main_thread_js(index,sync){var numCallArgs=arguments.length-2;if(numCallArgs>20-1)throw "emscripten_proxy_to_main_thread_js: Too many arguments "+numCallArgs+" to proxied function idx="+index+", maximum supported is "+(20-1)+"!";var stack=stackSave();var args=stackAlloc(numCallArgs*8);var b=args>>3;for(var i=0;i>3]);buf+=8;}else if(ch===105){buf=buf+3&~3;args.push(GROWABLE_HEAP_I32()[buf>>2]);buf+=4;}else abort("unexpected char in asm const signature "+ch);}return args}function _emscripten_receive_on_main_thread_js(index,numCallArgs,args){_emscripten_receive_on_main_thread_js_callArgs.length=numCallArgs;var b=args>>3;for(var i=0;i>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){console.error("emscripten_realloc_buffer: Attempted to grow heap from "+buffer.byteLength+" bytes to "+size+" bytes, but got error: "+e);}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();if(requestedSize<=oldSize){return false}var PAGE_MULTIPLE=65536;var maxHeapSize=1073741824;if(requestedSize>maxHeapSize){err("Cannot enlarge memory, asked to go up to "+requestedSize+" bytes, but the limit is "+maxHeapSize+" bytes!");return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}err("Failed to grow the heap from "+oldSize+" bytes to "+newSize+" bytes, not enough memory!");return false}var JSEvents={keyEvent:0,mouseEvent:0,wheelEvent:0,uiEvent:0,focusEvent:0,deviceOrientationEvent:0,deviceMotionEvent:0,fullscreenChangeEvent:0,pointerlockChangeEvent:0,visibilityChangeEvent:0,touchEvent:0,previousFullscreenElement:null,previousScreenX:null,previousScreenY:null,removeEventListenersRegistered:false,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i);}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[];},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){JSEvents.removeEventListenersRegistered=true;}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence>2]=eventTypeId;GROWABLE_HEAP_I32()[varargs+4>>2]=eventData;GROWABLE_HEAP_I32()[varargs+8>>2]=userData;_emscripten_async_queue_on_thread_(targetThread,637534208,eventHandlerFunc,eventData,varargs);stackRestore(stackTop);},getTargetThreadForEventCallback:function(targetThread){switch(targetThread){case 1:return 0;case 2:return PThread.currentProxiedOperationCallerThread;default:return targetThread}},getNodeNameForTarget:function(target){if(!target)return "";if(target==window)return "#window";if(target==screen)return "#screen";return target&&target.nodeName?target.nodeName:""},fullscreenEnabled:function(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+1;var cString=_malloc(length);stringToUTF8(jsString,cString,length);return cString}function _emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height){var stackTop=stackSave();var varargs=stackAlloc(12);var targetCanvasPtr=0;if(targetCanvas){targetCanvasPtr=stringToNewUTF8(targetCanvas);}GROWABLE_HEAP_I32()[varargs>>2]=targetCanvasPtr;GROWABLE_HEAP_I32()[varargs+4>>2]=width;GROWABLE_HEAP_I32()[varargs+8>>2]=height;_emscripten_async_queue_on_thread_(targetThread,657457152,0,targetCanvasPtr,varargs);stackRestore(stackTop);}function _emscripten_set_offscreencanvas_size_on_target_thread(targetThread,targetCanvas,width,height){targetCanvas=targetCanvas?UTF8ToString(targetCanvas):"";_emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height);}function __maybeCStringToJsString(cString){return cString>2?UTF8ToString(cString):cString}var specialHTMLTargets=[0,typeof document!=="undefined"?document:0,typeof window!=="undefined"?window:0];function __findEventTarget(target){target=__maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!=="undefined"?document.querySelector(target):undefined);return domElement}function __findCanvasEventTarget(target){return __findEventTarget(target)}function _emscripten_set_canvas_element_size_calling_thread(target,width,height){var canvas=__findCanvasEventTarget(target);if(!canvas)return -4;if(canvas.canvasSharedPtr){GROWABLE_HEAP_I32()[canvas.canvasSharedPtr>>2]=width;GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+4>>2]=height;}if(canvas.offscreenCanvas||!canvas.controlTransferredOffscreen){if(canvas.offscreenCanvas)canvas=canvas.offscreenCanvas;var autoResizeViewport=false;if(canvas.GLctxObject&&canvas.GLctxObject.GLctx){var prevViewport=canvas.GLctxObject.GLctx.getParameter(2978);autoResizeViewport=prevViewport[0]===0&&prevViewport[1]===0&&prevViewport[2]===canvas.width&&prevViewport[3]===canvas.height;}canvas.width=width;canvas.height=height;if(autoResizeViewport){canvas.GLctxObject.GLctx.viewport(0,0,width,height);}}else if(canvas.canvasSharedPtr){var targetThread=GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+8>>2];_emscripten_set_offscreencanvas_size_on_target_thread(targetThread,target,width,height);return 1}else{return -4}return 0}function _emscripten_set_canvas_element_size_main_thread(target,width,height){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(2,1,target,width,height);return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}function _emscripten_set_canvas_element_size(target,width,height){var canvas=__findCanvasEventTarget(target);if(canvas){return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}else{return _emscripten_set_canvas_element_size_main_thread(target,width,height)}}function _emscripten_set_current_thread_status(newStatus){}function _emscripten_set_thread_name(threadId,name){}function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=function(index,divisor){ext["vertexAttribDivisorANGLE"](index,divisor);};ctx["drawArraysInstanced"]=function(mode,first,count,primcount){ext["drawArraysInstancedANGLE"](mode,first,count,primcount);};ctx["drawElementsInstanced"]=function(mode,count,type,indices,primcount){ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);};return 1}}function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=function(){return ext["createVertexArrayOES"]()};ctx["deleteVertexArray"]=function(vao){ext["deleteVertexArrayOES"](vao);};ctx["bindVertexArray"]=function(vao){ext["bindVertexArrayOES"](vao);};ctx["isVertexArray"]=function(vao){return ext["isVertexArrayOES"](vao)};return 1}}function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=function(n,bufs){ext["drawBuffersWEBGL"](n,bufs);};return 1}}var GL={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:{},currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],programInfos:{},stringCache:{},unpackAlignment:4,init:function(){var miniTempFloatBuffer=new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);for(var i=0;i>2]:-1;source+=UTF8ToString(GROWABLE_HEAP_I32()[string+i*4>>2],len<0?undefined:len);}return source},createContext:function(canvas,webGLContextAttributes){var ctx=canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=_malloc(8);GROWABLE_HEAP_I32()[handle+4>>2]=_pthread_self();var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context);}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return !(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;_free(GL.contexts[contextHandle].handle);GL.contexts[contextHandle]=null;},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;__webgl_enable_ANGLE_instanced_arrays(GLctx);__webgl_enable_OES_vertex_array_object(GLctx);__webgl_enable_WEBGL_draw_buffers(GLctx);GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query");var automaticallyEnabledExtensions=["OES_texture_float","OES_texture_half_float","OES_standard_derivatives","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBGL_depth_texture","OES_element_index_uint","EXT_texture_filter_anisotropic","EXT_frag_depth","WEBGL_draw_buffers","ANGLE_instanced_arrays","OES_texture_float_linear","OES_texture_half_float_linear","EXT_blend_minmax","EXT_shader_texture_lod","EXT_texture_norm16","WEBGL_compressed_texture_pvrtc","EXT_color_buffer_half_float","WEBGL_color_buffer_float","EXT_sRGB","WEBGL_compressed_texture_etc1","EXT_disjoint_timer_query","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_astc","EXT_color_buffer_float","WEBGL_compressed_texture_s3tc_srgb","EXT_disjoint_timer_query_webgl2","WEBKIT_WEBGL_compressed_texture_pvrtc"];var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext);}});},populateUniformTable:function(program){var p=GL.programs[program];var ptable=GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,35718);for(var i=0;i>2;contextAttributes["alpha"]=!!GROWABLE_HEAP_I32()[a+(0>>2)];contextAttributes["depth"]=!!GROWABLE_HEAP_I32()[a+(4>>2)];contextAttributes["stencil"]=!!GROWABLE_HEAP_I32()[a+(8>>2)];contextAttributes["antialias"]=!!GROWABLE_HEAP_I32()[a+(12>>2)];contextAttributes["premultipliedAlpha"]=!!GROWABLE_HEAP_I32()[a+(16>>2)];contextAttributes["preserveDrawingBuffer"]=!!GROWABLE_HEAP_I32()[a+(20>>2)];var powerPreference=GROWABLE_HEAP_I32()[a+(24>>2)];contextAttributes["powerPreference"]=__emscripten_webgl_power_preferences[powerPreference];contextAttributes["failIfMajorPerformanceCaveat"]=!!GROWABLE_HEAP_I32()[a+(28>>2)];contextAttributes.majorVersion=GROWABLE_HEAP_I32()[a+(32>>2)];contextAttributes.minorVersion=GROWABLE_HEAP_I32()[a+(36>>2)];contextAttributes.enableExtensionsByDefault=GROWABLE_HEAP_I32()[a+(40>>2)];contextAttributes.explicitSwapControl=GROWABLE_HEAP_I32()[a+(44>>2)];contextAttributes.proxyContextToMainThread=GROWABLE_HEAP_I32()[a+(48>>2)];contextAttributes.renderViaOffscreenBackBuffer=GROWABLE_HEAP_I32()[a+(52>>2)];var canvas=__findCanvasEventTarget(target);if(!canvas){return -4}if(contextAttributes.explicitSwapControl){return -1}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}function _emscripten_webgl_create_context(a0,a1){return _emscripten_webgl_do_create_context(a0,a1)}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];assert(buffer);if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){assert(SYSCALLS.varargs!=undefined);SYSCALLS.varargs+=4;var ret=GROWABLE_HEAP_I32()[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){if(low>=0)assert(high===0);else assert(high===-1);return low}};function _fd_close(fd){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(3,1,fd);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(4,1,fd,offset_low,offset_high,whence,newOffset);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");}function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(5,1,fd,iov,iovcnt,pnum);var num=0;for(var i=0;i>2];var len=GROWABLE_HEAP_I32()[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _pthread_cleanup_pop(execute){var routine=PThread.exitHandlers.pop();if(execute)routine();}function _pthread_cleanup_push(routine,arg){if(PThread.exitHandlers===null){PThread.exitHandlers=[];}PThread.exitHandlers.push(function(){dynCall_vi(routine,arg);});}function __spawn_thread(threadParams){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _spawn_thread() can only ever be called from main application thread!";var worker=PThread.getNewWorker();if(worker.pthread!==undefined)throw "Internal error!";if(!threadParams.pthread_ptr)throw "Internal error, no pthread ptr!";PThread.runningWorkers.push(worker);var tlsMemory=_malloc(128*4);for(var i=0;i<128;++i){GROWABLE_HEAP_I32()[tlsMemory+i*4>>2]=0;}var stackHigh=threadParams.stackBase+threadParams.stackSize;var pthread=PThread.pthreads[threadParams.pthread_ptr]={worker:worker,stackBase:threadParams.stackBase,stackSize:threadParams.stackSize,allocatedOwnStack:threadParams.allocatedOwnStack,thread:threadParams.pthread_ptr,threadInfoStruct:threadParams.pthread_ptr};var tis=pthread.threadInfoStruct>>2;Atomics.store(GROWABLE_HEAP_U32(),tis+(0>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(4>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(8>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(68>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(104>>2),tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),tis+(48>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(40>>2),pthread.threadInfoStruct);Atomics.store(GROWABLE_HEAP_U32(),tis+(44>>2),42);Atomics.store(GROWABLE_HEAP_U32(),tis+(108>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(84>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(80>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+8>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+12>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+20>>2),threadParams.schedPolicy);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+24>>2),threadParams.schedPrio);var global_libc=_emscripten_get_global_libc();var global_locale=global_libc+40;Atomics.store(GROWABLE_HEAP_U32(),tis+(176>>2),global_locale);worker.pthread=pthread;var msg={"cmd":"run","start_routine":threadParams.startRoutine,"arg":threadParams.arg,"threadInfoStruct":threadParams.pthread_ptr,"selfThreadId":threadParams.pthread_ptr,"parentThreadId":threadParams.parent_pthread_ptr,"stackBase":threadParams.stackBase,"stackSize":threadParams.stackSize};worker.runPthread=function(){msg.time=performance.now();worker.postMessage(msg,threadParams.transferList);};if(worker.loaded){worker.runPthread();delete worker.runPthread;}}function _pthread_getschedparam(thread,policy,schedparam){if(!policy&&!schedparam)return ERRNO_CODES.EINVAL;if(!thread){err("pthread_getschedparam called with a null thread pointer!");return ERRNO_CODES.ESRCH}var self=GROWABLE_HEAP_I32()[thread+12>>2];if(self!==thread){err("pthread_getschedparam attempted on thread "+thread+", which does not point to a valid thread, or does not exist anymore!");return ERRNO_CODES.ESRCH}var schedPolicy=Atomics.load(GROWABLE_HEAP_U32(),thread+108+20>>2);var schedPrio=Atomics.load(GROWABLE_HEAP_U32(),thread+108+24>>2);if(policy)GROWABLE_HEAP_I32()[policy>>2]=schedPolicy;if(schedparam)GROWABLE_HEAP_I32()[schedparam>>2]=schedPrio;return 0}function _pthread_self(){return __pthread_ptr|0}Module["_pthread_self"]=_pthread_self;function _pthread_create(pthread_ptr,attr,start_routine,arg){if(typeof SharedArrayBuffer==="undefined"){err("Current environment does not support SharedArrayBuffer, pthreads are not available!");return 6}if(!pthread_ptr){err("pthread_create called with a null thread pointer!");return 28}var transferList=[];var error=0;if(ENVIRONMENT_IS_PTHREAD&&(transferList.length===0||error)){return _emscripten_sync_run_in_main_thread_4(687865856,pthread_ptr,attr,start_routine,arg)}var stackSize=0;var stackBase=0;var detached=0;var schedPolicy=0;var schedPrio=0;if(attr){stackSize=GROWABLE_HEAP_I32()[attr>>2];stackSize+=81920;stackBase=GROWABLE_HEAP_I32()[attr+8>>2];detached=GROWABLE_HEAP_I32()[attr+12>>2]!==0;var inheritSched=GROWABLE_HEAP_I32()[attr+16>>2]===0;if(inheritSched){var prevSchedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];var prevSchedPrio=GROWABLE_HEAP_I32()[attr+24>>2];var parentThreadPtr=PThread.currentProxiedOperationCallerThread?PThread.currentProxiedOperationCallerThread:_pthread_self();_pthread_getschedparam(parentThreadPtr,attr+20,attr+24);schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];GROWABLE_HEAP_I32()[attr+20>>2]=prevSchedPolicy;GROWABLE_HEAP_I32()[attr+24>>2]=prevSchedPrio;}else{schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];}}else{stackSize=2097152;}var allocatedOwnStack=stackBase==0;if(allocatedOwnStack){stackBase=_memalign(16,stackSize);}else{stackBase-=stackSize;assert(stackBase>0);}var threadInfoStruct=_malloc(232);for(var i=0;i<232>>2;++i)GROWABLE_HEAP_U32()[(threadInfoStruct>>2)+i]=0;GROWABLE_HEAP_I32()[pthread_ptr>>2]=threadInfoStruct;GROWABLE_HEAP_I32()[threadInfoStruct+12>>2]=threadInfoStruct;var headPtr=threadInfoStruct+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var threadParams={stackBase:stackBase,stackSize:stackSize,allocatedOwnStack:allocatedOwnStack,schedPolicy:schedPolicy,schedPrio:schedPrio,detached:detached,startRoutine:start_routine,pthread_ptr:threadInfoStruct,parent_pthread_ptr:_pthread_self(),arg:arg,transferList:transferList};if(ENVIRONMENT_IS_PTHREAD){threadParams.cmd="spawnThread";postMessage(threadParams,transferList);}else{__spawn_thread(threadParams);}return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}function _sysconf(name){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(6,1,name);switch(name){case 30:return 16384;case 85:var maxHeapSize=1073741824;return maxHeapSize/16384;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:case 79:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return -1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}setErrNo(28);return -1}if(!ENVIRONMENT_IS_PTHREAD)PThread.initMainThreadBlock();else PThread.initWorker();var GLctx;GL.init();var proxiedFunctionTable=[null,_atexit,_emscripten_set_canvas_element_size_main_thread,_fd_close,_fd_seek,_fd_write,_sysconf];var asmLibraryArg={"__assert_fail":___assert_fail,"__call_main":___call_main,"__handle_stack_overflow":___handle_stack_overflow,"_emscripten_notify_thread_queue":__emscripten_notify_thread_queue,"abort":_abort,"emscripten_conditional_set_current_thread_status":_emscripten_conditional_set_current_thread_status,"emscripten_futex_wait":_emscripten_futex_wait,"emscripten_futex_wake":_emscripten_futex_wake,"emscripten_get_now":_emscripten_get_now,"emscripten_is_main_browser_thread":_emscripten_is_main_browser_thread,"emscripten_is_main_runtime_thread":_emscripten_is_main_runtime_thread,"emscripten_memcpy_big":_emscripten_memcpy_big,"emscripten_receive_on_main_thread_js":_emscripten_receive_on_main_thread_js,"emscripten_resize_heap":_emscripten_resize_heap,"emscripten_set_canvas_element_size":_emscripten_set_canvas_element_size,"emscripten_set_current_thread_status":_emscripten_set_current_thread_status,"emscripten_set_thread_name":_emscripten_set_thread_name,"emscripten_webgl_create_context":_emscripten_webgl_create_context,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"initPthreadsJS":initPthreadsJS,"memory":wasmMemory||Module["wasmMemory"],"pthread_cleanup_pop":_pthread_cleanup_pop,"pthread_cleanup_push":_pthread_cleanup_push,"pthread_create":_pthread_create,"pthread_self":_pthread_self,"roundf":_roundf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__wasm_call_ctors"].apply(null,arguments)};var _init=Module["_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["init"].apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["register_tensor"].apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose_data"].apply(null,arguments)};var _dispose=Module["_dispose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose"].apply(null,arguments)};var _Abs=Module["_Abs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Abs"].apply(null,arguments)};var _Add=Module["_Add"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Add"].apply(null,arguments)};var _AddN=Module["_AddN"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AddN"].apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ArgMax"].apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AvgPool"].apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["BatchMatMul"].apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ClipByValue"].apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2D"].apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2DBackpropInput"].apply(null,arguments)};var _Cos=Module["_Cos"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Cos"].apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["CropAndResize"].apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["DepthwiseConv2dNative"].apply(null,arguments)};var _Div=Module["_Div"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Div"].apply(null,arguments)};var _Equal=Module["_Equal"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Equal"].apply(null,arguments)};var _Exp=Module["_Exp"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Exp"].apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FloorDiv"].apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedBatchNorm"].apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedConv2D"].apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedDepthwiseConv2D"].apply(null,arguments)};var _Gather=Module["_Gather"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Gather"].apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GatherNd"].apply(null,arguments)};var _Greater=Module["_Greater"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Greater"].apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GreaterEqual"].apply(null,arguments)};var _Less=Module["_Less"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Less"].apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LessEqual"].apply(null,arguments)};var _Log=Module["_Log"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Log"].apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LogicalAnd"].apply(null,arguments)};var _Max=Module["_Max"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Max"].apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["MaxPool"].apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Maximum"].apply(null,arguments)};var _Min=Module["_Min"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Min"].apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Minimum"].apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Multiply"].apply(null,arguments)};var _Negate=Module["_Negate"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Negate"].apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV3"].apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV4"].apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV5"].apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NotEqual"].apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["OneHot"].apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["PadV2"].apply(null,arguments)};var _Pow=Module["_Pow"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Pow"].apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Prelu"].apply(null,arguments)};var _Relu=Module["_Relu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu"].apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu6"].apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ResizeBilinear"].apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Reverse"].apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["RotateWithOffset"].apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Rsqrt"].apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ScatterNd"].apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["SelectV2"].apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sigmoid"].apply(null,arguments)};var _Sin=Module["_Sin"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sin"].apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Softmax"].apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sqrt"].apply(null,arguments)};var _Square=Module["_Square"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Square"].apply(null,arguments)};var _Sub=Module["_Sub"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sub"].apply(null,arguments)};var _Sum=Module["_Sum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sum"].apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tanh"].apply(null,arguments)};var _Tile=Module["_Tile"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tile"].apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Transpose"].apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["_FusedMatMul"].apply(null,arguments)};var _malloc=Module["_malloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["malloc"].apply(null,arguments)};var _free=Module["_free"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["free"].apply(null,arguments)};var ___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__em_js__initPthreadsJS"].apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__errno_location"].apply(null,arguments)};var _emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_get_global_libc"].apply(null,arguments)};var _memalign=Module["_memalign"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["memalign"].apply(null,arguments)};var ___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__pthread_tsd_run_dtors"].apply(null,arguments)};var _emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_current_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_register_main_browser_thread_id"].apply(null,arguments)};var _emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_browser_thread_id"].apply(null,arguments)};var _emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_0"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_1"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_2"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_xprintf_varargs"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_3"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_4"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_5"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_6"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_7"].apply(null,arguments)};var _emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_run_in_main_runtime_thread_js"].apply(null,arguments)};var _emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_queue_on_thread_"].apply(null,arguments)};var _emscripten_tls_init=Module["_emscripten_tls_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_tls_init"].apply(null,arguments)};var ___set_stack_limit=Module["___set_stack_limit"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__set_stack_limit"].apply(null,arguments)};var stackSave=Module["stackSave"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackSave"].apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackAlloc"].apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackRestore"].apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_vi"].apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_v"].apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_ii"].apply(null,arguments)};Module["asm"]=asm;if(!Object.getOwnPropertyDescriptor(Module,"intArrayFromString"))Module["intArrayFromString"]=function(){abort("'intArrayFromString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"intArrayToString"))Module["intArrayToString"]=function(){abort("'intArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ccall"))Module["ccall"]=function(){abort("'ccall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["cwrap"]=cwrap;if(!Object.getOwnPropertyDescriptor(Module,"setValue"))Module["setValue"]=function(){abort("'setValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getValue"))Module["getValue"]=function(){abort("'getValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocate"))Module["allocate"]=function(){abort("'allocate' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getMemory"))Module["getMemory"]=function(){abort("'getMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ArrayToString"))Module["UTF8ArrayToString"]=function(){abort("'UTF8ArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ToString"))Module["UTF8ToString"]=function(){abort("'UTF8ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8Array"))Module["stringToUTF8Array"]=function(){abort("'stringToUTF8Array' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8"))Module["stringToUTF8"]=function(){abort("'stringToUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF8"))Module["lengthBytesUTF8"]=function(){abort("'lengthBytesUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreRun"))Module["addOnPreRun"]=function(){abort("'addOnPreRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnInit"))Module["addOnInit"]=function(){abort("'addOnInit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreMain"))Module["addOnPreMain"]=function(){abort("'addOnPreMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnExit"))Module["addOnExit"]=function(){abort("'addOnExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPostRun"))Module["addOnPostRun"]=function(){abort("'addOnPostRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeStringToMemory"))Module["writeStringToMemory"]=function(){abort("'writeStringToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeArrayToMemory"))Module["writeArrayToMemory"]=function(){abort("'writeArrayToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeAsciiToMemory"))Module["writeAsciiToMemory"]=function(){abort("'writeAsciiToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addRunDependency"))Module["addRunDependency"]=function(){abort("'addRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"removeRunDependency"))Module["removeRunDependency"]=function(){abort("'removeRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createFolder"))Module["FS_createFolder"]=function(){abort("'FS_createFolder' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPath"))Module["FS_createPath"]=function(){abort("'FS_createPath' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDataFile"))Module["FS_createDataFile"]=function(){abort("'FS_createDataFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPreloadedFile"))Module["FS_createPreloadedFile"]=function(){abort("'FS_createPreloadedFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLazyFile"))Module["FS_createLazyFile"]=function(){abort("'FS_createLazyFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLink"))Module["FS_createLink"]=function(){abort("'FS_createLink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDevice"))Module["FS_createDevice"]=function(){abort("'FS_createDevice' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_unlink"))Module["FS_unlink"]=function(){abort("'FS_unlink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"dynamicAlloc"))Module["dynamicAlloc"]=function(){abort("'dynamicAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadDynamicLibrary"))Module["loadDynamicLibrary"]=function(){abort("'loadDynamicLibrary' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadWebAssemblyModule"))Module["loadWebAssemblyModule"]=function(){abort("'loadWebAssemblyModule' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getLEB"))Module["getLEB"]=function(){abort("'getLEB' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFunctionTables"))Module["getFunctionTables"]=function(){abort("'getFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"alignFunctionTables"))Module["alignFunctionTables"]=function(){abort("'alignFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"registerFunctions"))Module["registerFunctions"]=function(){abort("'registerFunctions' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addFunction"))Module["addFunction"]=function(){abort("'addFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"removeFunction"))Module["removeFunction"]=function(){abort("'removeFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFuncWrapper"))Module["getFuncWrapper"]=function(){abort("'getFuncWrapper' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"prettyPrint"))Module["prettyPrint"]=function(){abort("'prettyPrint' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"makeBigInt"))Module["makeBigInt"]=function(){abort("'makeBigInt' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"dynCall"))Module["dynCall"]=function(){abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getCompilerSetting"))Module["getCompilerSetting"]=function(){abort("'getCompilerSetting' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"print"))Module["print"]=function(){abort("'print' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"printErr"))Module["printErr"]=function(){abort("'printErr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getTempRet0"))Module["getTempRet0"]=function(){abort("'getTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setTempRet0"))Module["setTempRet0"]=function(){abort("'setTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"callMain"))Module["callMain"]=function(){abort("'callMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"abort"))Module["abort"]=function(){abort("'abort' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToNewUTF8"))Module["stringToNewUTF8"]=function(){abort("'stringToNewUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscripten_realloc_buffer"))Module["emscripten_realloc_buffer"]=function(){abort("'emscripten_realloc_buffer' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ENV"))Module["ENV"]=function(){abort("'ENV' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setjmpId"))Module["setjmpId"]=function(){abort("'setjmpId' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_CODES"))Module["ERRNO_CODES"]=function(){abort("'ERRNO_CODES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_MESSAGES"))Module["ERRNO_MESSAGES"]=function(){abort("'ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setErrNo"))Module["setErrNo"]=function(){abort("'setErrNo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"DNS"))Module["DNS"]=function(){abort("'DNS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GAI_ERRNO_MESSAGES"))Module["GAI_ERRNO_MESSAGES"]=function(){abort("'GAI_ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Protocols"))Module["Protocols"]=function(){abort("'Protocols' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Sockets"))Module["Sockets"]=function(){abort("'Sockets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UNWIND_CACHE"))Module["UNWIND_CACHE"]=function(){abort("'UNWIND_CACHE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readAsmConstArgs"))Module["readAsmConstArgs"]=function(){abort("'readAsmConstArgs' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_q"))Module["jstoi_q"]=function(){abort("'jstoi_q' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_s"))Module["jstoi_s"]=function(){abort("'jstoi_s' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"reallyNegative"))Module["reallyNegative"]=function(){abort("'reallyNegative' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"formatString"))Module["formatString"]=function(){abort("'formatString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH"))Module["PATH"]=function(){abort("'PATH' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH_FS"))Module["PATH_FS"]=function(){abort("'PATH_FS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SYSCALLS"))Module["SYSCALLS"]=function(){abort("'SYSCALLS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMmap2"))Module["syscallMmap2"]=function(){abort("'syscallMmap2' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMunmap"))Module["syscallMunmap"]=function(){abort("'syscallMunmap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"flush_NO_FILESYSTEM"))Module["flush_NO_FILESYSTEM"]=function(){abort("'flush_NO_FILESYSTEM' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"JSEvents"))Module["JSEvents"]=function(){abort("'JSEvents' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"specialHTMLTargets"))Module["specialHTMLTargets"]=function(){abort("'specialHTMLTargets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangle"))Module["demangle"]=function(){abort("'demangle' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangleAll"))Module["demangleAll"]=function(){abort("'demangleAll' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jsStackTrace"))Module["jsStackTrace"]=function(){abort("'jsStackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getEnvStrings"))Module["getEnvStrings"]=function(){abort("'getEnvStrings' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64"))Module["writeI53ToI64"]=function(){abort("'writeI53ToI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Clamped"))Module["writeI53ToI64Clamped"]=function(){abort("'writeI53ToI64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Signaling"))Module["writeI53ToI64Signaling"]=function(){abort("'writeI53ToI64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Clamped"))Module["writeI53ToU64Clamped"]=function(){abort("'writeI53ToU64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Signaling"))Module["writeI53ToU64Signaling"]=function(){abort("'writeI53ToU64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromI64"))Module["readI53FromI64"]=function(){abort("'readI53FromI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromU64"))Module["readI53FromU64"]=function(){abort("'readI53FromU64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertI32PairToI53"))Module["convertI32PairToI53"]=function(){abort("'convertI32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertU32PairToI53"))Module["convertU32PairToI53"]=function(){abort("'convertU32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Browser"))Module["Browser"]=function(){abort("'Browser' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GL"))Module["GL"]=function(){abort("'GL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGet"))Module["emscriptenWebGLGet"]=function(){abort("'emscriptenWebGLGet' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetTexPixelData"))Module["emscriptenWebGLGetTexPixelData"]=function(){abort("'emscriptenWebGLGetTexPixelData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetUniform"))Module["emscriptenWebGLGetUniform"]=function(){abort("'emscriptenWebGLGetUniform' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetVertexAttrib"))Module["emscriptenWebGLGetVertexAttrib"]=function(){abort("'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AL"))Module["AL"]=function(){abort("'AL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_unicode"))Module["SDL_unicode"]=function(){abort("'SDL_unicode' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_ttfContext"))Module["SDL_ttfContext"]=function(){abort("'SDL_ttfContext' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_audio"))Module["SDL_audio"]=function(){abort("'SDL_audio' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL"))Module["SDL"]=function(){abort("'SDL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_gfx"))Module["SDL_gfx"]=function(){abort("'SDL_gfx' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLUT"))Module["GLUT"]=function(){abort("'GLUT' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"EGL"))Module["EGL"]=function(){abort("'EGL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW_Window"))Module["GLFW_Window"]=function(){abort("'GLFW_Window' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW"))Module["GLFW"]=function(){abort("'GLFW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLEW"))Module["GLEW"]=function(){abort("'GLEW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"IDBStore"))Module["IDBStore"]=function(){abort("'IDBStore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"runAndAbortIfError"))Module["runAndAbortIfError"]=function(){abort("'runAndAbortIfError' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["PThread"]=PThread;if(!Object.getOwnPropertyDescriptor(Module,"establishStackSpace"))Module["establishStackSpace"]=function(){abort("'establishStackSpace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getNoExitRuntime"))Module["getNoExitRuntime"]=function(){abort("'getNoExitRuntime' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"resetPrototype"))Module["resetPrototype"]=function(){abort("'resetPrototype' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"warnOnce"))Module["warnOnce"]=function(){abort("'warnOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackSave"))Module["stackSave"]=function(){abort("'stackSave' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackRestore"))Module["stackRestore"]=function(){abort("'stackRestore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackAlloc"))Module["stackAlloc"]=function(){abort("'stackAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AsciiToString"))Module["AsciiToString"]=function(){abort("'AsciiToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToAscii"))Module["stringToAscii"]=function(){abort("'stringToAscii' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF16ToString"))Module["UTF16ToString"]=function(){abort("'UTF16ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF16"))Module["stringToUTF16"]=function(){abort("'stringToUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF16"))Module["lengthBytesUTF16"]=function(){abort("'lengthBytesUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF32ToString"))Module["UTF32ToString"]=function(){abort("'UTF32ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF32"))Module["stringToUTF32"]=function(){abort("'stringToUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF32"))Module["lengthBytesUTF32"]=function(){abort("'lengthBytesUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8"))Module["allocateUTF8"]=function(){abort("'allocateUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8OnStack"))Module["allocateUTF8OnStack"]=function(){abort("'allocateUTF8OnStack' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["writeStackCookie"]=writeStackCookie;Module["checkStackCookie"]=checkStackCookie;Module["abortStackOverflow"]=abortStackOverflow;Module["PThread"]=PThread;Module["_pthread_self"]=_pthread_self;Module["wasmMemory"]=wasmMemory;Module["ExitStatus"]=ExitStatus;if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NORMAL"))Object.defineProperty(Module,"ALLOC_NORMAL",{configurable:true,get:function(){abort("'ALLOC_NORMAL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_STACK"))Object.defineProperty(Module,"ALLOC_STACK",{configurable:true,get:function(){abort("'ALLOC_STACK' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_DYNAMIC"))Object.defineProperty(Module,"ALLOC_DYNAMIC",{configurable:true,get:function(){abort("'ALLOC_DYNAMIC' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NONE"))Object.defineProperty(Module,"ALLOC_NONE",{configurable:true,get:function(){abort("'ALLOC_NONE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}writeStackCookie();preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();assert(!Module["_main"],'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}checkStackCookie();}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}if(!ENVIRONMENT_IS_PTHREAD)noExitRuntime=true;if(!ENVIRONMENT_IS_PTHREAD)run(); + + + return WasmBackendModuleSimd + } + ); + })(); + module.exports = WasmBackendModuleSimd; + }); + + const wasmWorkerContents = 'var threadInfoStruct=0;var selfThreadId=0;var parentThreadId=0;var Module={};function assert(condition,text){if(!condition)abort("Assertion failed: "+text)}function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:selfThreadId})}var out=function(){throw"out() is not defined in worker.js."};var err=threadPrintErr;this.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);Module["wasmModule"]=null;receiveInstance(instance);return instance.exports};this.onmessage=function(e){try{if(e.data.cmd==="load"){Module["DYNAMIC_BASE"]=e.data.DYNAMIC_BASE;Module["DYNAMICTOP_PTR"]=e.data.DYNAMICTOP_PTR;Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob==="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}Module=WasmBackendModuleSimd(Module);postMessage({"cmd":"loaded"})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;threadInfoStruct=e.data.threadInfoStruct;Module["__register_pthread_ptr"](threadInfoStruct,0,0);selfThreadId=e.data.selfThreadId;parentThreadId=e.data.parentThreadId;var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;assert(threadInfoStruct);assert(selfThreadId);assert(parentThreadId);assert(top!=0);assert(max!=0);assert(top>max);Module["establishStackSpace"](top,max);Module["_emscripten_tls_init"]();Module["writeStackCookie"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].setThreadStatus(Module["_pthread_self"](),1);try{var result=Module["dynCall_ii"](e.data.start_routine,e.data.arg);Module["checkStackCookie"]();if(!Module["getNoExitRuntime"]())Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){Atomics.store(Module["HEAPU32"],threadInfoStruct+4>>2,ex instanceof Module["ExitStatus"]?ex.status:-2);Atomics.store(Module["HEAPU32"],threadInfoStruct+0>>2,1);if(typeof Module["_emscripten_futex_wake"]!=="function"){err("Thread Initialisation failed.");throw ex}Module["_emscripten_futex_wake"](threadInfoStruct+0,2147483647);if(!(ex instanceof Module["ExitStatus"]))throw ex}else{err("Pthread 0x"+threadInfoStruct.toString(16)+" completed its pthread main entry point with an unwind, keeping the pthread worker alive for asynchronous operation.")}}}else if(e.data.cmd==="cancel"){if(threadInfoStruct){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(threadInfoStruct){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex.stack)err(ex.stack);throw ex}};if(typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string"){self={location:{href:__filename}};var onmessage=this.onmessage;var nodeWorkerThreads=require("worker_threads");Worker=nodeWorkerThreads.Worker;var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var nodeFS=require("fs");var nodeRead=function(filename){return nodeFS.readFileSync(filename,"utf8")};function globalEval(x){global.require=require;global.Module=Module;eval.call(null,x)}importScripts=function(f){globalEval(nodeRead(f))};postMessage=function(msg){parentPort.postMessage(msg)};if(typeof performance==="undefined"){performance={now:function(){return Date.now()}}}}'; + + var tfjsBackendWasm = createCommonjsModule(function (module, exports) { + var WasmBackendModule = (function() { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( + function(WasmBackendModule) { + WasmBackendModule = WasmBackendModule || {}; + + var Module=typeof WasmBackendModule!=="undefined"?WasmBackendModule:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":146,"maximum":146+0,"element":"anyfunc"});var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023);}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var DYNAMIC_BASE=5254800,DYNAMICTOP_PTR=11760;var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":2147483648/WASM_PAGE_SIZE});}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;removeRunDependency();}addRunDependency();function receiveInstantiatedSource(output){receiveInstance(output["instance"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}__ATINIT__.push({func:function(){___wasm_call_ctors();}});function _abort(){abort();}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num);}function _emscripten_get_heap_size(){return HEAPU8.length}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=65536;var maxHeapSize=2147483648;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}var asmLibraryArg={"a":_abort,"e":_emscripten_memcpy_big,"f":_emscripten_resize_heap,"g":_fd_close,"d":_fd_seek,"c":_fd_write,"memory":wasmMemory,"b":_roundf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return (___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["h"]).apply(null,arguments)};var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["i"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["j"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["k"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["l"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["m"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["n"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["o"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["p"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["q"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["r"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["s"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["t"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["u"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["v"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["w"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["x"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["y"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["z"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["A"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["B"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["C"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["D"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["E"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["F"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["G"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["H"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["I"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["J"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["K"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["L"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["M"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["N"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["O"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["P"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["Q"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["R"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["S"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["T"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["U"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["V"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["W"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["X"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["Y"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["Z"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["_"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["$"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["aa"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["ba"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["ca"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["da"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["ea"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["fa"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["ga"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["ha"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["ia"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["ja"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["ka"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["la"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["ma"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["na"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["oa"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["pa"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["qa"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["ra"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["sa"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["ta"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["ua"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["va"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["wa"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["xa"]).apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){return (dynCall_vi=Module["dynCall_vi"]=Module["asm"]["ya"]).apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){return (dynCall_v=Module["dynCall_v"]=Module["asm"]["za"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}noExitRuntime=true;run(); + + + return WasmBackendModule + } + ); + })(); + module.exports = WasmBackendModule; + }); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -3294,9 +3276,8 @@ wasm = tfjsBackendWasmThreadedSimd(factoryConfig); wasm.mainScriptUrlOrBlob = new Blob([`var _scriptDir = undefined; var WasmBackendModuleSimd = ` + tfjsBackendWasmThreadedSimd.toString()], { type: 'text/javascript' }); - } - else if (simdSupported) { - wasm = tfjsBackendWasmSimd(factoryConfig); + // } else if (simdSupported) { + // wasm = wasmFactorySimd(factoryConfig); } else { wasm = tfjsBackendWasm(factoryConfig); @@ -3368,17 +3349,17 @@ } wasmPath = path; customFetch = usePlatformFetch; - } - + } + /** @license See the LICENSE file. */ // This code is auto-generated, do not modify this file! - const version = '0.0.0'; - - exports.BackendWasm = BackendWasm; - exports.setWasmPath = setWasmPath; - exports.version_wasm = version; - - Object.defineProperty(exports, '__esModule', { value: true }); - -}))); -//# sourceMappingURL=tf-backend-wasm.js.map + const version = '0.0.0'; + + exports.BackendWasm = BackendWasm; + exports.setWasmPath = setWasmPath; + exports.version_wasm = version; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); +//# sourceMappingURL=tf-backend-wasm.js.map From 1277909fe96e7189af61ea20deb42688338bce72 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 22 Jul 2020 13:41:37 -0400 Subject: [PATCH 18/70] add --- tfjs-backend-wasm/README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tfjs-backend-wasm/README.md b/tfjs-backend-wasm/README.md index 5cfbd204438..e9a85529874 100644 --- a/tfjs-backend-wasm/README.md +++ b/tfjs-backend-wasm/README.md @@ -110,12 +110,12 @@ JS backend, and ~5.3-7.7X slower than the WebGL backend. | MobileNet inference (ms) | WASM | WebGL | Plain JS | WASM + SIMD | WASM + SIMD + threads |--------------------------|-------|-------|----------|-------------|---------------------- -| iPhone X | 147.1 | 20.3 | 941.3 | N/A | -| iPhone XS | 140 | 18.1 | 426.4 | N/A | -| Pixel 3 | 266.2 | 77.3 | 2345.2 | N/A | -| Desktop Linux | 91.5 | 17.1 | 1049 | N/A | -| Desktop Windows | 123.1 | 41.6 | 1117 | 37.2 | -| Macbook Pro | 98.4 | 19.6 | 893.5 | 30.2 | +| iPhone X | 147.1 | 20.3 | 941.3 | N/A | N/A | +| iPhone XS | 140 | 18.1 | 426.4 | N/A | N/A | +| Pixel 3 | 266.2 | 77.3 | 2345.2 | N/A | N/A | +| Desktop Linux | 91.5 | 17.1 | 1049 | N/A | N/A | +| Desktop Windows | 123.1 | 41.6 | 1117 | 37.2 | N/A | +| Macbook Pro | 98.4 | 19.6 | 893.5 | 30.2 | 10.3 | @@ -130,12 +130,12 @@ the device). | Face Detector inference (ms) | WASM | WebGL | Plain JS | WASM + SIMD | WASM + SIMD + threads |------------------------------|------|-------|----------|-------------|---------------------- -| iPhone X | 22.4 | 13.5 | 318 | N/A | -| iPhone XS | 21.4 | 10.5 | 176.9 | N/A | -| Pixel 3 | 40.7 | 31.8 | 535.2 | N/A | -| Desktop Linux | 12.6 | 12.7 | 249.5 | N/A | -| Desktop Windows | 16.2 | 7.1 | 270.9 | 7.5 | -| Macbook Pro 15 2019 | 13.6 | 22.7 | 209.1 | 7.9 | +| iPhone X | 22.4 | 13.5 | 318 | N/A | N/A | +| iPhone XS | 21.4 | 10.5 | 176.9 | N/A | N/A | +| Pixel 3 | 40.7 | 31.8 | 535.2 | N/A | N/A | +| Desktop Linux | 12.6 | 12.7 | 249.5 | N/A | N/A | +| Desktop Windows | 16.2 | 7.1 | 270.9 | 7.5 | N/A | +| Macbook Pro 15 2019 | 13.6 | 22.7 | 209.1 | 7.9 | 4.0 | # FAQ From 5a9086764f573ec7d6b87d06aad5112ed8694e3f Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Wed, 22 Jul 2020 15:44:43 -0400 Subject: [PATCH 19/70] bench --- tfjs-backend-wasm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tfjs-backend-wasm/README.md b/tfjs-backend-wasm/README.md index e9a85529874..967e339dec3 100644 --- a/tfjs-backend-wasm/README.md +++ b/tfjs-backend-wasm/README.md @@ -113,7 +113,7 @@ JS backend, and ~5.3-7.7X slower than the WebGL backend. | iPhone X | 147.1 | 20.3 | 941.3 | N/A | N/A | | iPhone XS | 140 | 18.1 | 426.4 | N/A | N/A | | Pixel 3 | 266.2 | 77.3 | 2345.2 | N/A | N/A | -| Desktop Linux | 91.5 | 17.1 | 1049 | N/A | N/A | +| Desktop Linux | 91.5 | 17.1 | 1049 | 61.9 | 30.0 | | Desktop Windows | 123.1 | 41.6 | 1117 | 37.2 | N/A | | Macbook Pro | 98.4 | 19.6 | 893.5 | 30.2 | 10.3 | From c3c77ce30bb83e0769a9deccc98db922ade6d12e Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Fri, 24 Jul 2020 13:58:03 -0400 Subject: [PATCH 20/70] add thread --- tfjs-backend-wasm/src/cc/backend.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tfjs-backend-wasm/src/cc/backend.cc b/tfjs-backend-wasm/src/cc/backend.cc index 18e61790310..0bfadfef319 100644 --- a/tfjs-backend-wasm/src/cc/backend.cc +++ b/tfjs-backend-wasm/src/cc/backend.cc @@ -14,9 +14,11 @@ #ifdef __EMSCRIPTEN__ #include +#include #endif #include +#include #include #include #include @@ -48,7 +50,8 @@ TensorInfo &get_tensor_info_out(const size_t tensor_id) { } size_t xnn_operator_count = 0; -pthreadpool *threadpool = pthreadpool_create(4); +pthreadpool *threadpool = + pthreadpool_create(std::min(emscripten_num_logical_cores(), 4)); // Registers a disposal callback for a tensor id with a given callback function. void register_disposal_callback(const size_t tensor_id, From 06ce3f9bc2db8636f8fd4a6832bd7e7f2c1f15bf Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Tue, 28 Jul 2020 12:24:19 -0400 Subject: [PATCH 21/70] update --- e2e/benchmarks/tf-core.js | 510 +++++++++++++++++++++++--------------- 1 file changed, 311 insertions(+), 199 deletions(-) diff --git a/e2e/benchmarks/tf-core.js b/e2e/benchmarks/tf-core.js index 3490af9c005..2637d1e2b74 100644 --- a/e2e/benchmarks/tf-core.js +++ b/e2e/benchmarks/tf-core.js @@ -3430,6 +3430,9 @@ var Step = 'Step'; var FromPixels = 'FromPixels'; var RotateWithOffset = 'RotateWithOffset'; + var _FusedMatMul = '_FusedMatMul'; + var FusedConv2D = 'FusedConv2D'; + var FusedDepthwiseConv2D = 'FusedDepthwiseConv2D'; /** * @license @@ -6876,7 +6879,8 @@ var value = backend.cumsum(permutedX, permutedAxis, exclusive, reverse); save([$x]); if (permutation != null) { - value = transpose(value, permutation); + var reversePermutation = getUndoAxesPermutation(permutation); + value = transpose(value, reversePermutation); } return value; }; @@ -9676,6 +9680,11 @@ } } for (var i = 0; i < newIndices.length; i++) { + // Handle negative indices + var axisSize = inputShape[i]; + if (newIndices[i] < 0) { + newIndices[i] += axisSize; + } newIndices[i] = clamp(0, newIndices[i], inputShape[i]); } return newIndices; @@ -23547,28 +23556,6 @@ } var inTopKAsync = inTopKAsync_; - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // Whether we should call fused ops. - var shouldFuse = function (gradientDepth, activation) { - var gradientMode = gradientDepth > 0; - return !gradientMode || activation === 'linear'; - }; - /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -23586,26 +23573,25 @@ * ============================================================================= */ // Returns gradient for fused activation. - var getFusedDyActivation = function (dy, y, activation) { + function getFusedDyActivation(dy, y, activation) { if (activation == null || activation === 'linear') { return dy; } if (activation === 'relu') { return dy.mul(y.step()); } - throw new Error("Gradient for activation " + activation + " has not been " + - "implemented yet."); - }; + throw new Error("Cannot compute gradient for fused activation " + activation + "."); + } // Returns gradient for fused bias. - var getFusedBiasGradient = function (bias, dyActivation) { + function getFusedBiasGradient(bias, dyActivation) { var res = dyActivation; var reduceAxes = getReductionAxes(bias.shape, dyActivation.shape); if (reduceAxes.length > 0) { res = res.sum(reduceAxes); } return res.reshape(bias.shape); - }; - var applyActivation = function (x, activation, preluActivationWeights) { + } + function applyActivation(x, activation, preluActivationWeights) { if (activation === 'linear') { return x; } @@ -23622,130 +23608,29 @@ return prelu(x, preluActivationWeights); } throw new Error("Unknown fused activation " + activation + "."); + } + // Whether we should call fused ops. + var shouldFuse = function (gradientDepth, activation) { + var gradientMode = gradientDepth > 0; + return !gradientMode || activation === 'linear'; }; + /** - * Computes the dot product of two matrices with optional activation and bias. - * - * ```js - * const a = tf.tensor2d([-1, -2], [1, 2]); - * const b = tf.tensor2d([1, 2, 3, 4], [2, 2]); - * const bias = tf.tensor2d([1, 2], [1, 2]); + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * tf.fused.matMul({a, b, bias, activation: 'relu'}).print(); - * ``` + * http://www.apache.org/licenses/LICENSE-2.0 * - * @param obj An object with the following properties: - * - `a` First matrix in dot product operation. - * - `b` Second matrix in dot product operation. - * - `transposeA` If true, `a` is transposed before multiplication. - * - `transposeB` If true, `b` is transposed before multiplication. - * - `bias` Matrix to be added to the result. - * - `activation` Name of activation kernel (defaults to `linear`). - * - `preluActivationWeights` Tensor of prelu weights. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= */ - function fusedMatMul_(_a) { - var _b; - var a = _a.a, b = _a.b, _c = _a.transposeA, transposeA = _c === void 0 ? false : _c, _d = _a.transposeB, transposeB = _d === void 0 ? false : _d, bias = _a.bias, _e = _a.activation, activation = _e === void 0 ? 'linear' : _e, preluActivationWeights = _a.preluActivationWeights; - if (shouldFuse(ENGINE.state.gradientDepth, activation) === false) { - var result = matMul(a, b, transposeA, transposeB); - if (bias != null) { - result = add(result, bias); - } - return applyActivation(result, activation, preluActivationWeights); - } - var $a = convertToTensor(a, 'a', 'fused matMul'); - var $b = convertToTensor(b, 'b', 'fused matMul'); - _b = makeTypesMatch($a, $b), $a = _b[0], $b = _b[1]; - var innerShapeA = transposeA ? $a.shape[$a.rank - 2] : $a.shape[$a.rank - 1]; - var innerShapeB = transposeB ? $b.shape[$b.rank - 1] : $b.shape[$b.rank - 2]; - var outerShapeA = transposeA ? $a.shape[$a.rank - 1] : $a.shape[$a.rank - 2]; - var outerShapeB = transposeB ? $b.shape[$b.rank - 2] : $b.shape[$b.rank - 1]; - var outerDimsA = $a.shape.slice(0, -2); - var outerDimsB = $b.shape.slice(0, -2); - var batchDimA = sizeFromShape(outerDimsA); - var batchDimB = sizeFromShape(outerDimsB); - assert($a.rank >= 2 && $b.rank >= 2 && $a.rank === $b.rank, function () { - return "Error in fused matMul: inputs must have the same rank of at least " + - ("2, got ranks " + $a.rank + " and " + $b.rank + "."); - }); - assert(arraysEqual(outerDimsA, outerDimsB), function () { return "Error in fused matMul: outer dimensions (" + outerDimsA + ") and (" + - (outerDimsB + ") of Tensors with shapes " + $a.shape + " and ") + - ($b.shape + " must match."); }); - assert(innerShapeA === innerShapeB, function () { return "Error in fused matMul: inner shapes (" + innerShapeA + ") and (" + - (innerShapeB + ") of Tensors with shapes " + $a.shape + " and ") + - ($b.shape + " and transposeA=" + transposeA) + - (" and transposeB=" + transposeB + " must match."); }); - var outShape = $a.shape.slice(0, -2).concat([outerShapeA, outerShapeB]); - var a3D = transposeA ? $a.as3D(batchDimA, innerShapeA, outerShapeA) : - $a.as3D(batchDimA, outerShapeA, innerShapeA); - var b3D = transposeB ? $b.as3D(batchDimB, outerShapeB, innerShapeB) : - $b.as3D(batchDimB, innerShapeB, outerShapeB); - var $bias; - if (bias != null) { - $bias = convertToTensor(bias, 'bias', 'fused matMul'); - $bias = makeTypesMatch($bias, $a)[0]; - assertAndGetBroadcastShape(outShape, $bias.shape); - } - var $preluActivationWeights; - if (preluActivationWeights != null) { - $preluActivationWeights = convertToTensor(preluActivationWeights, 'prelu weights', 'fused matMul'); - } - var grad = function (dy, saved) { - var a3D = saved[0], b3D = saved[1], y = saved[2]; - var dyActivation = getFusedDyActivation(dy, y, activation); - var biasGradient = {}; - if (bias != null) { - biasGradient = { bias: function () { return getFusedBiasGradient($bias, dyActivation); } }; - } - if (!transposeA && !transposeB) { - return Object.assign({ - a: function () { return dyActivation.matMul(b3D, false, true); }, - b: function () { return a3D.matMul(dyActivation, true, false); } - }, biasGradient); - } - else if (!transposeA && transposeB) { - return Object.assign({ - a: function () { return dyActivation.matMul(b3D, false, false); }, - b: function () { return dyActivation.matMul(a3D, true, false); } - }, biasGradient); - } - else if (transposeA && !transposeB) { - return Object.assign({ - a: function () { return b3D.matMul(dyActivation, false, true); }, - b: function () { return a3D.matMul(dyActivation, false, false); } - }, biasGradient); - } - else { - return Object.assign({ - a: function () { return b3D.matMul(dyActivation, true, true); }, - b: function () { return dyActivation.matMul(a3D, true, true); } - }, biasGradient); - } - }; - var inputs = { a: a3D, b: b3D }; - if (bias != null) { - inputs.bias = $bias; - } - if (preluActivationWeights != null) { - inputs.preluActivationWeights = $preluActivationWeights; - } - var inputsToSave = [a3D, b3D]; - var outputsToSave = [true]; - var res = ENGINE.runKernelFunc(function (backend, save) { - var y = backend.fusedBatchMatMul({ - a: a3D, - b: b3D, - transposeA: transposeA, - transposeB: transposeB, - bias: $bias, - activation: activation, - preluActivationWeights: $preluActivationWeights - }); - save([a3D, b3D, y]); - return y; - }, inputs, grad, '_FusedMatMul', { transposeA: transposeA, transposeB: transposeB, activation: activation }, inputsToSave, outputsToSave); - return res.reshape(outShape); - } /** * Computes a 2D convolution over the input x, optionally fused with adding a * bias and applying an activation. @@ -23845,30 +23730,21 @@ $preluActivationWeights = convertToTensor(preluActivationWeights, 'prelu weights', 'fused conv2d'); } var grad = function (dy, saved) { - var _a = saved, $filter = _a[0], x4D = _a[1], y = _a[2]; + var _a = saved, $filter = _a[0], x4D = _a[1], y = _a[2], $bias = _a[3]; var dyActivation = getFusedDyActivation(dy, y, activation); assert(tupleValuesAreOne(dilations), function () { return 'Error in gradient of fused conv2D: ' + "dilation rates greater than 1 " + ("are not yet supported in gradients. Got dilations '" + dilations + "'"); }); - var biasGradient = {}; - if (bias != null) { - biasGradient = { bias: function () { return getFusedBiasGradient($bias, dyActivation); } }; + var xDer = conv2DBackpropInput(x4D.shape, dyActivation, $filter, strides, pad); + var filterDer = conv2DBackpropFilter(x4D, dyActivation, $filter.shape, strides, pad); + var der = [xDer, filterDer]; + if ($bias != null) { + var biasDer = getFusedBiasGradient($bias, dyActivation); + der.push(biasDer); } - return Object.assign({ - x: function () { return conv2DBackpropInput(x4D.shape, dyActivation, $filter, strides, pad); }, - filter: function () { return conv2DBackpropFilter(x4D, dyActivation, $filter.shape, strides, pad); } - }, biasGradient); + return der; }; - var inputs = { x: x4D, filter: $filter }; - if (bias != null) { - inputs.bias = $bias; - } - if (preluActivationWeights != null) { - inputs.preluActivationWeights = $preluActivationWeights; - } - var inputsToSave = [$filter, x4D]; - var outputsToSave = [true]; // Save the only output. - var res = ENGINE.runKernelFunc(function (backend, save) { + var forward = function (backend) { var res = backend.fusedConv2d({ input: x4D, filter: $filter, @@ -23877,14 +23753,58 @@ activation: activation, preluActivationWeights: $preluActivationWeights }); - save([$filter, x4D, res]); return res; - }, inputs, grad, 'FusedConv2D', { convInfo: convInfo, activation: activation }, inputsToSave, outputsToSave); - if (reshapedTo4D) { - return res.as3D(res.shape[1], res.shape[2], res.shape[3]); + }; + var inputs = { + x: x4D, + filter: $filter, + bias: $bias, + preluActivationWeights: $preluActivationWeights + }; + var attrs = { strides: strides, pad: pad, dataFormat: dataFormat, dilations: dilations, dimRoundingMode: dimRoundingMode, activation: activation }; + // Depending on the the params passed in we will have different number of + // inputs and thus a a different number of elements in the gradient. + if (bias == null) { + var customOp = customGrad(function (x4D, filter, save) { + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, FusedConv2D, attrs); + save([filter, x4D, res]); + if (reshapedTo4D) { + res = res.as3D(res.shape[1], res.shape[2], res.shape[3]); + } + return { value: res, gradFunc: grad }; + }); + return customOp(x4D, $filter); + } + else { + var customOpWithBias = customGrad(function (x4D, filter, bias, save) { + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, FusedConv2D, attrs); + save([filter, x4D, res, bias]); + if (reshapedTo4D) { + res = res.as3D(res.shape[1], res.shape[2], res.shape[3]); + } + return { value: res, gradFunc: grad }; + }); + return customOpWithBias(x4D, $filter, $bias); } - return res; } + var conv2d$1 = op({ fusedConv2d_: fusedConv2d_ }); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ /** * Computes depthwise 2D convolution, optionally fused with adding a * bias and applying an activation. @@ -23985,27 +23905,17 @@ assert(tupleValuesAreOne(dilations), function () { return 'Error in gradient of fused depthwiseConv2d: dilation rates ' + "greater than 1 are not yet supported. Got dilations " + ("'" + dilations + "'"); }); - var $filter = saved[0], x4D = saved[1], y = saved[2]; + var $filter = saved[0], x4D = saved[1], y = saved[2], bias = saved[3]; var dyActivation = getFusedDyActivation(dy, y, activation); - var biasGradient = {}; + var xDer = depthwiseConv2dNativeBackpropInput(x4D.shape, dyActivation, $filter, convInfo); + var filterDer = depthwiseConv2dNativeBackpropFilter(x4D, dyActivation, $filter.shape, convInfo); if (bias != null) { - biasGradient = { bias: function () { return getFusedBiasGradient($bias, dyActivation); } }; + var biasDer = getFusedBiasGradient($bias, dyActivation); + return [xDer, filterDer, biasDer]; } - return Object.assign({ - x: function () { return depthwiseConv2dNativeBackpropInput(x4D.shape, dyActivation, $filter, convInfo); }, - filter: function () { return depthwiseConv2dNativeBackpropFilter(x4D, dyActivation, $filter.shape, convInfo); }, - }, biasGradient); + return [xDer, filterDer]; }; - var inputs = { x: x4D, filter: $filter }; - if (bias != null) { - inputs.bias = $bias; - } - if (preluActivationWeights != null) { - inputs.preluActivationWeights = $preluActivationWeights; - } - var inputsToSave = [$filter, x4D]; - var outputsToSave = [true]; - var res = ENGINE.runKernelFunc(function (backend, save) { + var forward = function (backend) { var res = backend.fusedDepthwiseConv2D({ input: x4D, filter: $filter, @@ -24014,23 +23924,219 @@ activation: activation, preluActivationWeights: $preluActivationWeights }); - save([$filter, x4D, res]); return res; - }, inputs, grad, 'FusedDepthwiseConv2D', { convInfo: convInfo, activation: activation }, inputsToSave, outputsToSave); - if (reshapedTo4D) { - return res.as3D(res.shape[1], res.shape[2], res.shape[3]); + }; + var inputs = { + x: x4D, + filter: $filter, + bias: $bias, + preluActivationWeights: $preluActivationWeights + }; + var attrs = { strides: strides, pad: pad, dataFormat: dataFormat, dilations: dilations, dimRoundingMode: dimRoundingMode, activation: activation }; + // Depending on the the params passed in we will have different number of + // inputs and thus a a different number of elements in the gradient. + if (bias == null) { + var customOp = customGrad(function (x4D, filter, save) { + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, FusedDepthwiseConv2D, attrs); + save([filter, x4D, res]); + if (reshapedTo4D) { + res = res.as3D(res.shape[1], res.shape[2], res.shape[3]); + } + return { value: res, gradFunc: grad }; + }); + return customOp(x4D, $filter); + } + else { + var customOpWithBias = customGrad(function (x4D, filter, bias, save) { + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, FusedDepthwiseConv2D, attrs); + save([filter, x4D, res, bias]); + if (reshapedTo4D) { + res = res.as3D(res.shape[1], res.shape[2], res.shape[3]); + } + return { value: res, gradFunc: grad }; + }); + return customOpWithBias(x4D, $filter, $bias); } - return res; } - var matMul$1 = op({ fusedMatMul_: fusedMatMul_ }); - var conv2d$1 = op({ fusedConv2d_: fusedConv2d_ }); var depthwiseConv2d$1 = op({ fusedDepthwiseConv2d_: fusedDepthwiseConv2d_ }); + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the dot product of two matrices with optional activation and bias. + * + * ```js + * const a = tf.tensor2d([-1, -2], [1, 2]); + * const b = tf.tensor2d([1, 2, 3, 4], [2, 2]); + * const bias = tf.tensor2d([1, 2], [1, 2]); + * + * tf.fused.matMul({a, b, bias, activation: 'relu'}).print(); + * ``` + * + * @param obj An object with the following properties: + * - `a` First matrix in dot product operation. + * - `b` Second matrix in dot product operation. + * - `transposeA` If true, `a` is transposed before multiplication. + * - `transposeB` If true, `b` is transposed before multiplication. + * - `bias` Matrix to be added to the result. + * - `activation` Name of activation kernel (defaults to `linear`). + * - `preluActivationWeights` Tensor of prelu weights. + */ + function fusedMatMul_(_a) { + var _b; + var a = _a.a, b = _a.b, _c = _a.transposeA, transposeA = _c === void 0 ? false : _c, _d = _a.transposeB, transposeB = _d === void 0 ? false : _d, bias = _a.bias, _e = _a.activation, activation = _e === void 0 ? 'linear' : _e, preluActivationWeights = _a.preluActivationWeights; + if (shouldFuse(ENGINE.state.gradientDepth, activation) === false) { + var result = matMul(a, b, transposeA, transposeB); + if (bias != null) { + result = add(result, bias); + } + return applyActivation(result, activation, preluActivationWeights); + } + var $a = convertToTensor(a, 'a', 'fused matMul'); + var $b = convertToTensor(b, 'b', 'fused matMul'); + _b = makeTypesMatch($a, $b), $a = _b[0], $b = _b[1]; + var innerShapeA = transposeA ? $a.shape[$a.rank - 2] : $a.shape[$a.rank - 1]; + var innerShapeB = transposeB ? $b.shape[$b.rank - 1] : $b.shape[$b.rank - 2]; + var outerShapeA = transposeA ? $a.shape[$a.rank - 1] : $a.shape[$a.rank - 2]; + var outerShapeB = transposeB ? $b.shape[$b.rank - 2] : $b.shape[$b.rank - 1]; + var outerDimsA = $a.shape.slice(0, -2); + var outerDimsB = $b.shape.slice(0, -2); + var batchDimA = sizeFromShape(outerDimsA); + var batchDimB = sizeFromShape(outerDimsB); + assert($a.rank >= 2 && $b.rank >= 2 && $a.rank === $b.rank, function () { + return "Error in fused matMul: inputs must have the same rank of at least " + + ("2, got ranks " + $a.rank + " and " + $b.rank + "."); + }); + assert(arraysEqual(outerDimsA, outerDimsB), function () { return "Error in fused matMul: outer dimensions (" + outerDimsA + ") and (" + + (outerDimsB + ") of Tensors with shapes " + $a.shape + " and ") + + ($b.shape + " must match."); }); + assert(innerShapeA === innerShapeB, function () { return "Error in fused matMul: inner shapes (" + innerShapeA + ") and (" + + (innerShapeB + ") of Tensors with shapes " + $a.shape + " and ") + + ($b.shape + " and transposeA=" + transposeA) + + (" and transposeB=" + transposeB + " must match."); }); + var outShape = $a.shape.slice(0, -2).concat([outerShapeA, outerShapeB]); + var a3D = transposeA ? $a.as3D(batchDimA, innerShapeA, outerShapeA) : + $a.as3D(batchDimA, outerShapeA, innerShapeA); + var b3D = transposeB ? $b.as3D(batchDimB, outerShapeB, innerShapeB) : + $b.as3D(batchDimB, innerShapeB, outerShapeB); + var $bias; + if (bias != null) { + $bias = convertToTensor(bias, 'bias', 'fused matMul'); + $bias = makeTypesMatch($bias, $a)[0]; + assertAndGetBroadcastShape(outShape, $bias.shape); + } + var $preluActivationWeights; + if (preluActivationWeights != null) { + $preluActivationWeights = convertToTensor(preluActivationWeights, 'prelu weights', 'fused matMul'); + } + var grad = function (dy, saved) { + var a3D = saved[0], b3D = saved[1], y = saved[2], $bias = saved[3]; + // we reshape dy because the result of the forward is not + // necessarily going to be a 3d tensor due to a reshape done at the end of + // the customOp. + var dyActivation = getFusedDyActivation(reshape(dy, y.shape), y, activation); + var aDer; + var bDer; + if (!transposeA && !transposeB) { + aDer = matMul(dyActivation, b3D, false, true); + bDer = matMul(a3D, dyActivation, true, false); + } + else if (!transposeA && transposeB) { + aDer = matMul(dyActivation, b3D, false, false); + bDer = matMul(dyActivation, a3D, true, false); + } + else if (transposeA && !transposeB) { + aDer = matMul(b3D, dyActivation, false, true); + bDer = matMul(a3D, dyActivation, false, false); + } + else { + aDer = matMul(b3D, dyActivation, true, true); + bDer = matMul(dyActivation, a3D, true, true); + } + if (bias != null) { + var biasDer = getFusedBiasGradient($bias, dyActivation); + return [aDer, bDer, biasDer]; + } + else { + return [aDer, bDer]; + } + }; + var forward = function (backend) { + var y = backend.fusedBatchMatMul({ + a: a3D, + b: b3D, + transposeA: transposeA, + transposeB: transposeB, + bias: $bias, + activation: activation, + preluActivationWeights: $preluActivationWeights + }); + return y; + }; + var inputs = { + a: a3D, + b: b3D, + bias: $bias, + preluActivationWeights: $preluActivationWeights + }; + var attrs = { transposeA: transposeA, transposeB: transposeB, activation: activation }; + // Depending on the the params passed in we will have different number of + // inputs and thus a a different number of elements in the gradient. + if (bias == null) { + var customOp = customGrad(function (a3D, b3D, save) { + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, _FusedMatMul, attrs); + save([a3D, b3D, res]); + return { value: reshape(res, outShape), gradFunc: grad }; + }); + return customOp(a3D, b3D); + } + else { + var customOpWithBias = customGrad(function (a3D, b3D, $bias, save) { + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, _FusedMatMul, attrs); + save([a3D, b3D, res, $bias]); + return { value: reshape(res, outShape), gradFunc: grad }; + }); + return customOpWithBias(a3D, b3D, $bias); + } + } + var matMul$1 = op({ fusedMatMul_: fusedMatMul_ }); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var fused_ops = { __proto__: null, - matMul: matMul$1, conv2d: conv2d$1, - depthwiseConv2d: depthwiseConv2d$1 + depthwiseConv2d: depthwiseConv2d$1, + matMul: matMul$1 }; /** @@ -27987,6 +28093,10 @@ tupleValuesAreOne: tupleValuesAreOne, eitherStridesOrDilationsAreOne: eitherStridesOrDilationsAreOne, convertConv2DDataFormat: convertConv2DDataFormat, + getFusedDyActivation: getFusedDyActivation, + getFusedBiasGradient: getFusedBiasGradient, + applyActivation: applyActivation, + shouldFuse: shouldFuse, PARALLELIZE_THRESHOLD: PARALLELIZE_THRESHOLD, computeOptimalWindowSize: computeOptimalWindowSize, getImageCenter: getImageCenter, @@ -28001,7 +28111,6 @@ calculateShapes: calculateShapes, SELU_SCALEALPHA: SELU_SCALEALPHA, SELU_SCALE: SELU_SCALE, - shouldFuse: shouldFuse, ERF_P: ERF_P, ERF_A1: ERF_A1, ERF_A2: ERF_A2, @@ -31995,6 +32104,8 @@ exports.FloorDiv = FloorDiv; exports.FromPixels = FromPixels; exports.FusedBatchNorm = FusedBatchNorm; + exports.FusedConv2D = FusedConv2D; + exports.FusedDepthwiseConv2D = FusedDepthwiseConv2D; exports.GatherNd = GatherNd; exports.GatherV2 = GatherV2; exports.Greater = Greater; @@ -32090,6 +32201,7 @@ exports.UnsortedSegmentSum = UnsortedSegmentSum; exports.Variable = Variable; exports.ZerosLike = ZerosLike; + exports._FusedMatMul = _FusedMatMul; exports.abs = abs; exports.acos = acos; exports.acosh = acosh; From cce44fc7a14f7248e8044d439e76d5cb92eb531a Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Tue, 28 Jul 2020 13:23:34 -0400 Subject: [PATCH 22/70] update --- e2e/benchmarks/tf-backend-wasm.js | 492 ++++++++++++++---- .../tfjs-backend-wasm-threaded-simd.wasm | Bin 234393 -> 234537 bytes e2e/benchmarks/tfjs-backend-wasm.wasm | Bin 154794 -> 154795 bytes 3 files changed, 405 insertions(+), 87 deletions(-) diff --git a/e2e/benchmarks/tf-backend-wasm.js b/e2e/benchmarks/tf-backend-wasm.js index 8fbfd96702e..2148e7e9578 100644 --- a/e2e/benchmarks/tf-backend-wasm.js +++ b/e2e/benchmarks/tf-backend-wasm.js @@ -77,7 +77,7 @@ */ let wasmFusedMatMul; function setup(backend) { - wasmFusedMatMul = backend.wasm.cwrap('_FusedMatMul', null /* void */, [ + wasmFusedMatMul = backend.wasm.cwrap(tfjsCore._FusedMatMul, null /* void */, [ 'number', 'array', 'number', @@ -129,7 +129,7 @@ return out; } const fusedMatMulConfig = { - kernelName: '_FusedMatMul', + kernelName: tfjsCore._FusedMatMul, backendName: 'wasm', setupFunc: setup, kernelFunc: fusedBatchMatMul @@ -172,7 +172,23 @@ return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; } - const absConfig = createUnaryKernelConfig('Abs'); + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const absConfig = createUnaryKernelConfig(tfjsCore.Abs); /** * @license @@ -258,7 +274,7 @@ * ============================================================================= */ const supportsFullBroadcast = true; - const addConfig = createBinaryKernelConfig('Add', supportsFullBroadcast); + const addConfig = createBinaryKernelConfig(tfjsCore.Add, supportsFullBroadcast); /** * @license @@ -278,7 +294,7 @@ */ let wasmFunc; function setupFunc(backend) { - wasmFunc = backend.wasm.cwrap('AddN', null /* void */, [ + wasmFunc = backend.wasm.cwrap(tfjsCore.AddN, null /* void */, [ 'array', 'number', 'number', @@ -299,7 +315,7 @@ return out; } const addNConfig = { - kernelName: 'AddN', + kernelName: tfjsCore.AddN, backendName: 'wasm', setupFunc, kernelFunc: addn, @@ -353,7 +369,7 @@ */ let wasmTranspose; function setup$1(backend) { - wasmTranspose = backend.wasm.cwrap('Transpose', null /* void */, [ + wasmTranspose = backend.wasm.cwrap(tfjsCore.Transpose, null /* void */, [ 'number', 'array', 'number', @@ -424,7 +440,7 @@ return [newShape, newPerm]; } const transposeConfig = { - kernelName: 'Transpose', + kernelName: tfjsCore.Transpose, backendName: 'wasm', kernelFunc: transpose, setupFunc: setup$1, @@ -497,7 +513,7 @@ */ let wasmFunc$1; function setup$2(backend) { - wasmFunc$1 = backend.wasm.cwrap('ArgMax', null /* void */, [ + wasmFunc$1 = backend.wasm.cwrap(tfjsCore.ArgMax, null /* void */, [ 'number', 'number', 'number', @@ -559,7 +575,7 @@ */ let wasmAvgPool; function setup$3(backend) { - wasmAvgPool = backend.wasm.cwrap('AvgPool', null /* void */, [ + wasmAvgPool = backend.wasm.cwrap(tfjsCore.AvgPool, null /* void */, [ 'number', 'number', 'number', @@ -605,7 +621,7 @@ return out; } const avgPoolConfig = { - kernelName: 'AvgPool', + kernelName: tfjsCore.AvgPool, backendName: 'wasm', setupFunc: setup$3, kernelFunc: avgPool @@ -629,7 +645,7 @@ */ let wasmBatchMatMul; function setup$4(backend) { - wasmBatchMatMul = backend.wasm.cwrap('BatchMatMul', null /* void */, [ + wasmBatchMatMul = backend.wasm.cwrap(tfjsCore.BatchMatMul, null /* void */, [ 'number', 'array', 'number', @@ -661,7 +677,7 @@ return out; } const batchMatMulConfig = { - kernelName: 'BatchMatMul', + kernelName: tfjsCore.BatchMatMul, backendName: 'wasm', setupFunc: setup$4, kernelFunc: batchMatMul @@ -692,7 +708,7 @@ return out; } const castConfig = { - kernelName: 'Cast', + kernelName: tfjsCore.Cast, backendName: 'wasm', kernelFunc: cast, }; @@ -782,7 +798,7 @@ return out; } const concatConfig = { - kernelName: 'Concat', + kernelName: tfjsCore.Concat, backendName: 'wasm', kernelFunc: concat, }; @@ -805,7 +821,7 @@ */ let wasmConv2d; function setup$6(backend) { - wasmConv2d = backend.wasm.cwrap('Conv2D', null /* void */, [ + wasmConv2d = backend.wasm.cwrap(tfjsCore.Conv2D, null /* void */, [ 'number', 'number', 'number', @@ -858,7 +874,7 @@ return out; } const conv2DConfig = { - kernelName: 'Conv2D', + kernelName: tfjsCore.Conv2D, backendName: 'wasm', setupFunc: setup$6, kernelFunc: conv2d @@ -964,7 +980,7 @@ * limitations under the License. * ============================================================================= */ - const cosConfig = createUnaryKernelConfig('Cos'); + const cosConfig = createUnaryKernelConfig(tfjsCore.Cos); /** * @license @@ -990,7 +1006,7 @@ })(InterpolationMethod || (InterpolationMethod = {})); let wasmCropAndResize; function setup$8(backend) { - wasmCropAndResize = backend.wasm.cwrap('CropAndResize', null /*void*/, [ + wasmCropAndResize = backend.wasm.cwrap(tfjsCore.CropAndResize, null /*void*/, [ 'number', 'number', 'number', @@ -1054,7 +1070,7 @@ let wasmDepthwiseConv2d; function setup$9(backend) { wasmDepthwiseConv2d = - backend.wasm.cwrap('DepthwiseConv2dNative', null /* void */, [ + backend.wasm.cwrap(tfjsCore.DepthwiseConv2dNative, null /* void */, [ 'number', 'number', 'number', @@ -1107,7 +1123,7 @@ return out; } const depthwiseConv2DNativeConfig = { - kernelName: 'DepthwiseConv2dNative', + kernelName: tfjsCore.DepthwiseConv2dNative, backendName: 'wasm', setupFunc: setup$9, kernelFunc: depthwiseConv2d @@ -1130,12 +1146,44 @@ * ============================================================================= */ const supportsFullBroadcast$1 = true; - const divConfig = createBinaryKernelConfig('Div', supportsFullBroadcast$1); + const divConfig = createBinaryKernelConfig(tfjsCore.Div, supportsFullBroadcast$1); + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ const supportsFullBroadcast$2 = false; - const equalConfig = createBinaryKernelConfig('Equal', supportsFullBroadcast$2, 'bool'); + const equalConfig = createBinaryKernelConfig(tfjsCore.Equal, supportsFullBroadcast$2, 'bool'); - const expConfig = createUnaryKernelConfig('Exp'); + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const expConfig = createUnaryKernelConfig(tfjsCore.Exp); /** * @license @@ -1183,7 +1231,7 @@ * ============================================================================= */ const supportsFullBroadcast$3 = false; - const floorDivConfig = createBinaryKernelConfig('FloorDiv', supportsFullBroadcast$3); + const floorDivConfig = createBinaryKernelConfig(tfjsCore.FloorDiv, supportsFullBroadcast$3); /** * @license @@ -1203,7 +1251,7 @@ */ let wasmBatchNorm; function setup$a(backend) { - wasmBatchNorm = backend.wasm.cwrap('FusedBatchNorm', null /* void */, ['number', 'number', 'number', 'number', 'number', 'number', 'number']); + wasmBatchNorm = backend.wasm.cwrap(tfjsCore.FusedBatchNorm, null /* void */, ['number', 'number', 'number', 'number', 'number', 'number', 'number']); } function fusedBatchNorm(args) { const { backend, inputs, attrs } = args; @@ -1224,7 +1272,7 @@ return out; } const fusedBatchNormConfig = { - kernelName: 'FusedBatchNorm', + kernelName: tfjsCore.FusedBatchNorm, backendName: 'wasm', setupFunc: setup$a, kernelFunc: fusedBatchNorm @@ -1248,7 +1296,7 @@ */ let wasmFusedConv2d; function setup$b(backend) { - wasmFusedConv2d = backend.wasm.cwrap('FusedConv2D', null /* void */, [ + wasmFusedConv2d = backend.wasm.cwrap(tfjsCore.FusedConv2D, null /* void */, [ 'number', 'number', 'number', @@ -1275,13 +1323,14 @@ } function fusedConv2d(args) { const { inputs, attrs, backend } = args; - const { convInfo, activation } = attrs; + const { x, filter, bias, preluActivationWeights } = inputs; + const { strides, pad, dilations, dataFormat, dimRoundingMode, activation } = attrs; + const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode); const fusedActivation = FusableActivation[activation]; if (fusedActivation == null) { throw new Error(`${activation} activation not yet supported for FusedConv2D ` + `in the wasm backend.`); } - const { x, filter, bias, preluActivationWeights } = inputs; const xId = backend.dataIdMap.get(x.dataId).id; const filterId = backend.dataIdMap.get(filter.dataId).id; const outputChannels = convInfo.outChannels; @@ -1313,9 +1362,9 @@ const batchSize = convInfo.batchSize; const inHeight = convInfo.inHeight; const inWidth = convInfo.inWidth; - if (convInfo.dataFormat !== 'channelsLast') { + if (dataFormat !== 'NHWC') { throw new Error(`wasm backend FusedConv2D does not support dataFormat:'` + - `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + `${dataFormat}'. Please use 'NHWC'.`); } const out = backend.makeOutput(convInfo.outShape, 'float32'); const outId = backend.dataIdMap.get(out.dataId).id; @@ -1326,7 +1375,7 @@ return out; } const fusedConv2DConfig = { - kernelName: 'FusedConv2D', + kernelName: tfjsCore.FusedConv2D, backendName: 'wasm', setupFunc: setup$b, kernelFunc: fusedConv2d @@ -1351,7 +1400,7 @@ let wasmFusedDepthwiseConv2d; function setup$c(backend) { wasmFusedDepthwiseConv2d = - backend.wasm.cwrap('FusedDepthwiseConv2D', null /* void */, [ + backend.wasm.cwrap(tfjsCore.FusedDepthwiseConv2D, null /* void */, [ 'number', 'number', 'number', @@ -1378,13 +1427,14 @@ } function fusedDepthwiseConv2d(args) { const { inputs, attrs, backend } = args; - const { convInfo, activation } = attrs; + const { x, filter, bias, preluActivationWeights } = inputs; + const { strides, pad, dilations, dataFormat, dimRoundingMode, activation } = attrs; + const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode); const fusedActivation = FusableActivation[activation]; if (fusedActivation == null) { throw new Error(`${activation} activation not yet supported for FusedDepthwiseConv2D ` + `in the wasm backend.`); } - const { x, filter, bias, preluActivationWeights } = inputs; const xId = backend.dataIdMap.get(x.dataId).id; const filterId = backend.dataIdMap.get(filter.dataId).id; const outputChannels = convInfo.outChannels; @@ -1416,9 +1466,9 @@ const batchSize = convInfo.batchSize; const inHeight = convInfo.inHeight; const inWidth = convInfo.inWidth; - if (convInfo.dataFormat !== 'channelsLast') { + if (dataFormat !== 'NHWC') { throw new Error(`wasm backend FusedDepthwiseConv2D does not support dataFormat:'` + - `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + `${dataFormat}'. Please use 'NHWC'.`); } const out = backend.makeOutput(convInfo.outShape, 'float32'); const outId = backend.dataIdMap.get(out.dataId).id; @@ -1429,7 +1479,7 @@ return out; } const fusedDepthwiseConv2DConfig = { - kernelName: 'FusedDepthwiseConv2D', + kernelName: tfjsCore.FusedDepthwiseConv2D, backendName: 'wasm', setupFunc: setup$c, kernelFunc: fusedDepthwiseConv2d @@ -1453,7 +1503,7 @@ */ let wasmGatherNd; function setup$d(backend) { - wasmGatherNd = backend.wasm.cwrap('GatherNd', null /*void*/, [ + wasmGatherNd = backend.wasm.cwrap(tfjsCore.GatherNd, null /*void*/, [ 'number', 'number', 'number', @@ -1551,14 +1601,62 @@ kernelFunc: gatherV2 }; + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ const supportsFullBroadcast$4 = false; - const greaterConfig = createBinaryKernelConfig('Greater', supportsFullBroadcast$4, 'bool'); + const greaterConfig = createBinaryKernelConfig(tfjsCore.Greater, supportsFullBroadcast$4, 'bool'); + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ const supportsFullBroadcast$5 = false; - const greaterEqualConfig = createBinaryKernelConfig('GreaterEqual', supportsFullBroadcast$5, 'bool'); + const greaterEqualConfig = createBinaryKernelConfig(tfjsCore.GreaterEqual, supportsFullBroadcast$5, 'bool'); + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ const supportsFullBroadcast$6 = false; - const lessConfig = createBinaryKernelConfig('Less', supportsFullBroadcast$6, 'bool'); + const lessConfig = createBinaryKernelConfig(tfjsCore.Less, supportsFullBroadcast$6, 'bool'); /** * @license @@ -1577,12 +1675,44 @@ * ============================================================================= */ const supportsFullBroadcast$7 = false; - const lessEqualConfig = createBinaryKernelConfig('LessEqual', supportsFullBroadcast$7, 'bool'); + const lessEqualConfig = createBinaryKernelConfig(tfjsCore.LessEqual, supportsFullBroadcast$7, 'bool'); - const logConfig = createUnaryKernelConfig('Log'); + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const logConfig = createUnaryKernelConfig(tfjsCore.Log); + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ const supportsFullBroadcast$8 = false; - const logicalAndConfig = createBinaryKernelConfig('LogicalAnd', supportsFullBroadcast$8, 'bool'); + const logicalAndConfig = createBinaryKernelConfig(tfjsCore.LogicalAnd, supportsFullBroadcast$8, 'bool'); /** * @license @@ -1602,8 +1732,7 @@ */ let wasmMax; function setup$f(backend) { - wasmMax = - backend.wasm.cwrap('Max', null /*void*/, ['number, number, number']); + wasmMax = backend.wasm.cwrap(tfjsCore.Max, null /*void*/, ['number, number, number']); } function max(args) { const { backend, inputs, attrs } = args; @@ -1645,8 +1774,24 @@ kernelFunc: max }; + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ const supportsFullBroadcast$9 = false; - const maximumConfig = createBinaryKernelConfig('Maximum', supportsFullBroadcast$9); + const maximumConfig = createBinaryKernelConfig(tfjsCore.Maximum, supportsFullBroadcast$9); /** * @license @@ -1666,7 +1811,7 @@ */ let wasmMaxPool; function setup$g(backend) { - wasmMaxPool = backend.wasm.cwrap('MaxPool', null /* void */, [ + wasmMaxPool = backend.wasm.cwrap(tfjsCore.MaxPool, null /* void */, [ 'number', 'number', 'number', @@ -1714,7 +1859,7 @@ return out; } const maxPoolConfig = { - kernelName: 'MaxPool', + kernelName: tfjsCore.MaxPool, backendName: 'wasm', setupFunc: setup$g, kernelFunc: maxPool @@ -1738,8 +1883,7 @@ */ let wasmMin; function setup$h(backend) { - wasmMin = - backend.wasm.cwrap('Min', null /*void*/, ['number, number, number']); + wasmMin = backend.wasm.cwrap(tfjsCore.Min, null /*void*/, ['number, number, number']); } function min(args) { const { backend, inputs, attrs } = args; @@ -1785,8 +1929,24 @@ kernelFunc: min }; + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ const supportsFullBroadcast$a = false; - const minimumConfig = createBinaryKernelConfig('Minimum', supportsFullBroadcast$a); + const minimumConfig = createBinaryKernelConfig(tfjsCore.Minimum, supportsFullBroadcast$a); /** * @license @@ -1807,7 +1967,23 @@ const supportsFullBroadcast$b = true; const multiplyConfig = createBinaryKernelConfig(tfjsCore.Multiply, supportsFullBroadcast$b); - const negateConfig = createUnaryKernelConfig('Negate'); + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const negateConfig = createUnaryKernelConfig(tfjsCore.Negate); /** * @license @@ -1858,7 +2034,7 @@ */ let wasmFunc$2; function setup$i(backend) { - wasmFunc$2 = backend.wasm.cwrap('NonMaxSuppressionV3', 'number', // Result* + wasmFunc$2 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV3, 'number', // Result* [ 'number', 'number', @@ -1882,10 +2058,10 @@ return selectedIndicesTensor; } const nonMaxSuppressionV3Config = { - kernelName: 'NonMaxSuppressionV3', + kernelName: tfjsCore.NonMaxSuppressionV3, backendName: 'wasm', setupFunc: setup$i, - kernelFunc, + kernelFunc: kernelFunc, }; /** @@ -1955,7 +2131,7 @@ */ let wasmFunc$4; function setup$k(backend) { - wasmFunc$4 = backend.wasm.cwrap('NonMaxSuppressionV5', 'number', // Result* + wasmFunc$4 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV5, 'number', // Result* [ 'number', 'number', @@ -1981,14 +2157,30 @@ return [selectedIndicesTensor, selectedScoresTensor]; } const nonMaxSuppressionV5Config = { - kernelName: 'NonMaxSuppressionV5', + kernelName: tfjsCore.NonMaxSuppressionV5, backendName: 'wasm', setupFunc: setup$k, kernelFunc: kernelFunc$1, }; + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ const supportsFullBroadcast$c = false; - const notEqualConfig = createBinaryKernelConfig('NotEqual', supportsFullBroadcast$c, 'bool'); + const notEqualConfig = createBinaryKernelConfig(tfjsCore.NotEqual, supportsFullBroadcast$c, 'bool'); /** * @license @@ -2008,7 +2200,7 @@ */ let wasmOneHot; function setup$l(backend) { - wasmOneHot = backend.wasm.cwrap('OneHot', null /* void */, [ + wasmOneHot = backend.wasm.cwrap(tfjsCore.OneHot, null /* void */, [ 'number', 'number', 'number', @@ -2058,7 +2250,7 @@ return out; } const onesLikeConfig = { - kernelName: 'OnesLike', + kernelName: tfjsCore.OnesLike, backendName: 'wasm', kernelFunc: onesLike, }; @@ -2113,8 +2305,24 @@ setupFunc: setup$m }; + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ const supportsFullBroadcast$d = false; - const powConfig = createBinaryKernelConfig('Pow', supportsFullBroadcast$d); + const powConfig = createBinaryKernelConfig(tfjsCore.Pow, supportsFullBroadcast$d); /** * @license @@ -2134,7 +2342,7 @@ */ let wasmPrelu; function setup$n(backend) { - wasmPrelu = backend.wasm.cwrap('Prelu', null /* void */, [ + wasmPrelu = backend.wasm.cwrap(tfjsCore.Prelu, null /* void */, [ 'number', 'number', 'number' // out_id @@ -2151,15 +2359,47 @@ return out; } const preluConfig = { - kernelName: 'Prelu', + kernelName: tfjsCore.Prelu, backendName: 'wasm', setupFunc: setup$n, kernelFunc: prelu }; - const reluConfig = createUnaryKernelConfig('Relu'); + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const reluConfig = createUnaryKernelConfig(tfjsCore.Relu); - const relu6Config = createUnaryKernelConfig('Relu6'); + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const relu6Config = createUnaryKernelConfig(tfjsCore.Relu6); /** * @license @@ -2207,7 +2447,7 @@ */ let wasmResizeBilinear; function setup$o(backend) { - wasmResizeBilinear = backend.wasm.cwrap('ResizeBilinear', null /*void*/, [ + wasmResizeBilinear = backend.wasm.cwrap(tfjsCore.ResizeBilinear, null /*void*/, [ 'number', 'number', 'number', @@ -2359,7 +2599,23 @@ setupFunc: setup$q }; - const rsqrtConfig = createUnaryKernelConfig('Rsqrt'); + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const rsqrtConfig = createUnaryKernelConfig(tfjsCore.Rsqrt); /** * @license @@ -2379,7 +2635,7 @@ */ let wasmScatterNd; function setup$r(backend) { - wasmScatterNd = backend.wasm.cwrap('ScatterNd', null /*void*/, [ + wasmScatterNd = backend.wasm.cwrap(tfjsCore.ScatterNd, null /*void*/, [ 'number', 'number', 'number', @@ -2483,8 +2739,7 @@ */ let wasmFunc$5; function setup$t(backend) { - wasmFunc$5 = - backend.wasm.cwrap('Sigmoid', null /* void */, ['number', 'number']); + wasmFunc$5 = backend.wasm.cwrap(tfjsCore.Sigmoid, null /* void */, ['number', 'number']); } function sigmoid(args) { const { backend, inputs: { x } } = args; @@ -2505,7 +2760,23 @@ kernelFunc: sigmoid }; - const sinConfig = createUnaryKernelConfig('Sin'); + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const sinConfig = createUnaryKernelConfig(tfjsCore.Sin); /** * @license @@ -2606,7 +2877,7 @@ } } const sliceConfig = { - kernelName: 'Slice', + kernelName: tfjsCore.Slice, backendName: 'wasm', kernelFunc: slice, }; @@ -2629,7 +2900,7 @@ */ let wasmFunc$6; function setup$u(backend) { - wasmFunc$6 = backend.wasm.cwrap('Softmax', null /* void */, [ + wasmFunc$6 = backend.wasm.cwrap(tfjsCore.Softmax, null /* void */, [ 'number', 'number', 'number', @@ -2651,7 +2922,7 @@ return out; } const softmaxConfig = { - kernelName: 'Softmax', + kernelName: tfjsCore.Softmax, backendName: 'wasm', setupFunc: setup$u, kernelFunc: softmax @@ -2711,12 +2982,44 @@ * limitations under the License. * ============================================================================= */ - const sqrtConfig = createUnaryKernelConfig('Sqrt'); + const sqrtConfig = createUnaryKernelConfig(tfjsCore.Sqrt); - const squareConfig = createUnaryKernelConfig('Square'); + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const squareConfig = createUnaryKernelConfig(tfjsCore.Square); + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ const supportsFullBroadcast$e = true; - const subConfig = createBinaryKernelConfig('Sub', supportsFullBroadcast$e); + const subConfig = createBinaryKernelConfig(tfjsCore.Sub, supportsFullBroadcast$e); /** * @license @@ -2736,8 +3039,7 @@ */ let wasmSum; function setup$v(backend) { - wasmSum = - backend.wasm.cwrap('Sum', null /*void*/, ['number, number, number']); + wasmSum = backend.wasm.cwrap(tfjsCore.Sum, null /*void*/, ['number, number, number']); } function sum(args) { const { backend, inputs, attrs } = args; @@ -2784,7 +3086,23 @@ kernelFunc: sum }; - const tanhConfig = createUnaryKernelConfig('Tanh'); + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const tanhConfig = createUnaryKernelConfig(tfjsCore.Tanh); /** * @license @@ -2804,7 +3122,7 @@ */ let wasmTile; function setup$w(backend) { - wasmTile = backend.wasm.cwrap('Tile', null /* void */, [ + wasmTile = backend.wasm.cwrap(tfjsCore.Tile, null /* void */, [ 'number', 'array', 'number', @@ -2830,7 +3148,7 @@ return out; } const tileConfig = { - kernelName: 'Tile', + kernelName: tfjsCore.Tile, backendName: 'wasm', setupFunc: setup$w, kernelFunc: tile @@ -2905,7 +3223,7 @@ return out; } const zerosLikeConfig = { - kernelName: 'ZerosLike', + kernelName: tfjsCore.ZerosLike, backendName: 'wasm', kernelFunc: zerosLike, }; @@ -3060,7 +3378,7 @@ function(WasmBackendModuleSimd) { WasmBackendModuleSimd = WasmBackendModuleSimd || {}; - function GROWABLE_HEAP_I8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP8}function GROWABLE_HEAP_U8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU8}function GROWABLE_HEAP_I32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP32}function GROWABLE_HEAP_U32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPF64}var Module=typeof WasmBackendModuleSimd!=="undefined"?WasmBackendModuleSimd:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(Module["ENVIRONMENT"]){throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -s ENVIRONMENT=web or -s ENVIRONMENT=node)")}var ENVIRONMENT_IS_PTHREAD=Module["ENVIRONMENT_IS_PTHREAD"]||false;if(ENVIRONMENT_IS_PTHREAD){buffer=Module["buffer"];DYNAMIC_BASE=Module["DYNAMIC_BASE"];DYNAMICTOP_PTR=Module["DYNAMICTOP_PTR"];}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};var nodeWorkerThreads;try{nodeWorkerThreads=worker_threads;}catch(e){console.error('The "worker_threads" module is not supported in this node.js build - perhaps a newer version is needed?');throw e}Worker=nodeWorkerThreads.Worker;}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}if(ENVIRONMENT_IS_NODE){read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};}else{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}else{throw new Error("environment detection error")}if(ENVIRONMENT_IS_NODE){if(typeof performance==="undefined"){performance=perf_hooks.performance;}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(!Object.getOwnPropertyDescriptor(Module,"arguments"))Object.defineProperty(Module,"arguments",{configurable:true,get:function(){abort("Module.arguments has been replaced with plain arguments_");}});if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(!Object.getOwnPropertyDescriptor(Module,"thisProgram"))Object.defineProperty(Module,"thisProgram",{configurable:true,get:function(){abort("Module.thisProgram has been replaced with plain thisProgram");}});if(Module["quit"])quit_=Module["quit"];if(!Object.getOwnPropertyDescriptor(Module,"quit"))Object.defineProperty(Module,"quit",{configurable:true,get:function(){abort("Module.quit has been replaced with plain quit_");}});assert(typeof Module["memoryInitializerPrefixURL"]==="undefined","Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["pthreadMainPrefixURL"]==="undefined","Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["cdInitializerPrefixURL"]==="undefined","Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["filePackagePrefixURL"]==="undefined","Module.filePackagePrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["read"]==="undefined","Module.read option was removed (modify read_ in JS)");assert(typeof Module["readAsync"]==="undefined","Module.readAsync option was removed (modify readAsync in JS)");assert(typeof Module["readBinary"]==="undefined","Module.readBinary option was removed (modify readBinary in JS)");assert(typeof Module["setWindowTitle"]==="undefined","Module.setWindowTitle option was removed (modify setWindowTitle in JS)");assert(typeof Module["TOTAL_MEMORY"]==="undefined","Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");if(!Object.getOwnPropertyDescriptor(Module,"read"))Object.defineProperty(Module,"read",{configurable:true,get:function(){abort("Module.read has been replaced with plain read_");}});if(!Object.getOwnPropertyDescriptor(Module,"readAsync"))Object.defineProperty(Module,"readAsync",{configurable:true,get:function(){abort("Module.readAsync has been replaced with plain readAsync");}});if(!Object.getOwnPropertyDescriptor(Module,"readBinary"))Object.defineProperty(Module,"readBinary",{configurable:true,get:function(){abort("Module.readBinary has been replaced with plain readBinary");}});if(!Object.getOwnPropertyDescriptor(Module,"setWindowTitle"))Object.defineProperty(Module,"setWindowTitle",{configurable:true,get:function(){abort("Module.setWindowTitle has been replaced with plain setWindowTitle");}});assert(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER||ENVIRONMENT_IS_NODE,"Pthreads do not work in this environment yet (need Web Workers, or an alternative to them)");var stackSave;var stackRestore;var stackAlloc;stackSave=stackRestore=stackAlloc=function(){abort("cannot use the stack before compiled code is ready to run, and has provided stack access");};function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text);}}var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(!Object.getOwnPropertyDescriptor(Module,"wasmBinary"))Object.defineProperty(Module,"wasmBinary",{configurable:true,get:function(){abort("Module.wasmBinary has been replaced with plain wasmBinary");}});var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(!Object.getOwnPropertyDescriptor(Module,"noExitRuntime"))Object.defineProperty(Module,"noExitRuntime",{configurable:true,get:function(){abort("Module.noExitRuntime has been replaced with plain noExitRuntime");}});if(typeof WebAssembly!=="object"){abort("No WebAssembly support found. Build with -s WASM=0 to target JavaScript instead.");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":165,"maximum":165+0,"element":"anyfunc"});var wasmModule;var threadInfoStruct=0;var selfThreadId=0;var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;assert(returnType!=="array",'Return type should not be "array".');if(args){for(var i=0;i=endIdx)){var u0=heap[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heap[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heap[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2;}else{if((u0&248)!=240)warnOnce("Invalid UTF-8 leading byte 0x"+u0.toString(16)+" encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!");u0=(u0&7)<<18|u1<<12|u2<<6|heap[idx++]&63;}if(u0<65536){str+=String.fromCharCode(u0);}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023);}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;if(u>=2097152)warnOnce("Invalid Unicode code point 0x"+u.toString(16)+" encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).");heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){assert(typeof maxBytesToWrite=="number","stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");return stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4;}return len}function writeArrayToMemory(array,buffer){assert(array.length>=0,"writeArrayToMemory array must have a length (should be an array or typed array)");GROWABLE_HEAP_I8().set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var STACK_BASE=5256288,STACKTOP=STACK_BASE,STACK_MAX=13408,DYNAMIC_BASE=5256288,DYNAMICTOP_PTR=12480;assert(STACK_BASE%16===0,"stack must start aligned");assert(DYNAMIC_BASE%16===0,"heap must start aligned");if(ENVIRONMENT_IS_PTHREAD){STACK_MAX=STACKTOP=STACK_MAX=2147483647;}var TOTAL_STACK=5242880;if(Module["TOTAL_STACK"])assert(TOTAL_STACK===Module["TOTAL_STACK"],"the stack size can no longer be determined at runtime");var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||1073741824;if(!Object.getOwnPropertyDescriptor(Module,"INITIAL_MEMORY"))Object.defineProperty(Module,"INITIAL_MEMORY",{configurable:true,get:function(){abort("Module.INITIAL_MEMORY has been replaced with plain INITIAL_INITIAL_MEMORY");}});assert(INITIAL_INITIAL_MEMORY>=TOTAL_STACK,"INITIAL_MEMORY should be larger than TOTAL_STACK, was "+INITIAL_INITIAL_MEMORY+"! (TOTAL_STACK="+TOTAL_STACK+")");assert(typeof Int32Array!=="undefined"&&typeof Float64Array!=="undefined"&&Int32Array.prototype.subarray!==undefined&&Int32Array.prototype.set!==undefined,"JS engine does not provide full typed array support");if(ENVIRONMENT_IS_PTHREAD){wasmMemory=Module["wasmMemory"];buffer=Module["buffer"];}else{if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":1073741824/WASM_PAGE_SIZE,"shared":true});if(!(wasmMemory.buffer instanceof SharedArrayBuffer)){err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");if(ENVIRONMENT_IS_NODE){console.log("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)");}throw Error("bad memory")}}}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;assert(INITIAL_INITIAL_MEMORY%WASM_PAGE_SIZE===0);assert(65536%WASM_PAGE_SIZE===0);updateGlobalBufferAndViews(buffer);if(!ENVIRONMENT_IS_PTHREAD){GROWABLE_HEAP_I32()[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;}function writeStackCookie(){assert((STACK_MAX&3)==0);GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1]=34821223;GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2]=2310721022;GROWABLE_HEAP_I32()[0]=1668509029;}function checkStackCookie(){var cookie1=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1];var cookie2=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2];if(cookie1!=34821223||cookie2!=2310721022){abort("Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x"+cookie2.toString(16)+" "+cookie1.toString(16));}if(GROWABLE_HEAP_I32()[0]!==1668509029)abort("Runtime error: The application has corrupted its heap memory area (address zero)!");}function abortStackOverflow(allocSize){abort("Stack overflow! Attempted to allocate "+allocSize+" bytes on the stack, but stack has only "+(STACK_MAX-stackSave()+allocSize)+" bytes available!");}(function(){var h16=new Int16Array(1);var h8=new Int8Array(h16.buffer);h16[0]=25459;if(h8[0]!==115||h8[1]!==99)throw "Runtime error: expected the system to be little-endian!"})();function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;if(ENVIRONMENT_IS_PTHREAD)runtimeInitialized=true;function preRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){checkStackCookie();assert(!runtimeInitialized);runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__);}function preMain(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;callRuntimeCallbacks(__ATMAIN__);}function postRun(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}assert(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;var runDependencyTracking={};function addRunDependency(id){assert(!ENVIRONMENT_IS_PTHREAD,"addRunDependency cannot be used in a pthread worker");runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(!runDependencyTracking[id]);runDependencyTracking[id]=1;if(runDependencyWatcher===null&&typeof setInterval!=="undefined"){runDependencyWatcher=setInterval(function(){if(ABORT){clearInterval(runDependencyWatcher);runDependencyWatcher=null;return}var shown=false;for(var dep in runDependencyTracking){if(!shown){shown=true;err("still waiting on run dependencies:");}err("dependency: "+dep);}if(shown){err("(end of list)");}},1e4);}}else{err("warning: run dependency added without ID");}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(runDependencyTracking[id]);delete runDependencyTracking[id];}else{err("warning: run dependency removed without ID");}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}if(ENVIRONMENT_IS_PTHREAD)console.error("Pthread aborting at "+(new Error).stack);what+="";out(what);err(what);ABORT=true;var output="abort("+what+") at "+stackTrace();what=output;throw new WebAssembly.RuntimeError(what)}var FS={error:function(){abort("Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -s FORCE_FILESYSTEM=1");},init:function(){FS.error();},createDataFile:function(){FS.error();},createPreloadedFile:function(){FS.error();},createLazyFile:function(){FS.error();},open:function(){FS.error();},mkdev:function(){FS.error();},registerDevice:function(){FS.error();},analyzePath:function(){FS.error();},loadFilesFromDB:function(){FS.error();},ErrnoError:function ErrnoError(){FS.error();}};Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm-threaded-simd.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmModule=module;if(!ENVIRONMENT_IS_PTHREAD){var numWorkersToLoad=PThread.unusedWorkers.length;PThread.unusedWorkers.forEach(function(w){PThread.loadWasmModuleToWorker(w,function(){if(!--numWorkersToLoad)removeRunDependency("wasm-instantiate");});});}}if(!ENVIRONMENT_IS_PTHREAD){addRunDependency("wasm-instantiate");}var trueModule=Module;function receiveInstantiatedSource(output){assert(Module===trueModule,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");trueModule=null;receiveInstance(output["instance"],output["module"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}var ASM_CONSTS={};function initPthreadsJS(){PThread.initRuntime();}if(!ENVIRONMENT_IS_PTHREAD)__ATINIT__.push({func:function(){___wasm_call_ctors();}});function demangle(func){warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling");return func}function demangleAll(text){var regex=/\b_Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}var __pthread_ptr=0;var __pthread_is_main_runtime_thread=0;var __pthread_is_main_browser_thread=0;function __register_pthread_ptr(pthreadPtr,isMainBrowserThread,isMainRuntimeThread){pthreadPtr=pthreadPtr|0;isMainBrowserThread=isMainBrowserThread|0;isMainRuntimeThread=isMainRuntimeThread|0;__pthread_ptr=pthreadPtr;__pthread_is_main_browser_thread=isMainBrowserThread;__pthread_is_main_runtime_thread=isMainRuntimeThread;}Module["__register_pthread_ptr"]=__register_pthread_ptr;var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var __main_thread_futex_wait_address=13392;function _emscripten_futex_wake(addr,count){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0||count<0)return -28;if(count==0)return 0;if(count>=2147483647)count=Infinity;var mainThreadWaitAddress=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);var mainThreadWoken=0;if(mainThreadWaitAddress==addr){var loadedAddr=Atomics.compareExchange(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,mainThreadWaitAddress,0);if(loadedAddr==mainThreadWaitAddress){--count;mainThreadWoken=1;if(count<=0)return 1}}var ret=Atomics.notify(GROWABLE_HEAP_I32(),addr>>2,count);if(ret>=0)return ret+mainThreadWoken;throw "Atomics.notify returned an unexpected value "+ret}Module["_emscripten_futex_wake"]=_emscripten_futex_wake;function __kill_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _kill_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _kill_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];pthread.worker.terminate();PThread.freeThreadData(pthread);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(pthread.worker),1);pthread.worker.pthread=undefined;}function __cancel_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cancel_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cancel_thread!";var pthread=PThread.pthreads[pthread_ptr];pthread.worker.postMessage({"cmd":"cancel"});}function __cleanup_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cleanup_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cleanup_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];if(pthread){var worker=pthread.worker;PThread.returnWorkerToPool(worker);}}var PThread={MAIN_THREAD_ID:1,mainThreadInfo:{schedPolicy:0,schedPrio:0},unusedWorkers:[],runningWorkers:[],initRuntime:function(){__register_pthread_ptr(PThread.mainThreadBlock,!ENVIRONMENT_IS_WORKER,1);_emscripten_register_main_browser_thread_id(PThread.mainThreadBlock);},initMainThreadBlock:function(){assert(!ENVIRONMENT_IS_PTHREAD);var pthreadPoolSize=8;for(var i=0;i>2]=PThread.mainThreadBlock;var headPtr=PThread.mainThreadBlock+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var tlsMemory=12880;for(var i=0;i<128;++i)GROWABLE_HEAP_U32()[tlsMemory/4+i]=0;Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+104>>2,tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+40>>2,PThread.mainThreadBlock);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+44>>2,42);},initWorker:function(){},pthreads:{},exitHandlers:null,setThreadStatus:function(){},runExitHandlers:function(){if(PThread.exitHandlers!==null){while(PThread.exitHandlers.length>0){PThread.exitHandlers.pop()();}PThread.exitHandlers=null;}if(ENVIRONMENT_IS_PTHREAD&&threadInfoStruct)___pthread_tsd_run_dtors();},threadExit:function(exitCode){var tb=_pthread_self();if(tb){err("Pthread 0x"+tb.toString(16)+" exited.");Atomics.store(GROWABLE_HEAP_U32(),tb+4>>2,exitCode);Atomics.store(GROWABLE_HEAP_U32(),tb+0>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+60>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+64>>2,0);PThread.runExitHandlers();_emscripten_futex_wake(tb+0,2147483647);__register_pthread_ptr(0,0,0);threadInfoStruct=0;if(ENVIRONMENT_IS_PTHREAD){postMessage({"cmd":"exit"});}}},threadCancel:function(){PThread.runExitHandlers();Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+4>>2,-1);Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+0>>2,1);_emscripten_futex_wake(threadInfoStruct+0,2147483647);threadInfoStruct=selfThreadId=0;__register_pthread_ptr(0,0,0);postMessage({"cmd":"cancelDone"});},terminateAllThreads:function(){for(var t in PThread.pthreads){var pthread=PThread.pthreads[t];if(pthread&&pthread.worker){PThread.returnWorkerToPool(pthread.worker);}}PThread.pthreads={};for(var i=0;i>2];GROWABLE_HEAP_I32()[pthread.threadInfoStruct+104>>2]=0;_free(tlsMemory);_free(pthread.threadInfoStruct);}pthread.threadInfoStruct=0;if(pthread.allocatedOwnStack&&pthread.stackBase)_free(pthread.stackBase);pthread.stackBase=0;if(pthread.worker)pthread.worker.pthread=null;},returnWorkerToPool:function(worker){delete PThread.pthreads[worker.pthread.thread];PThread.unusedWorkers.push(worker);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);PThread.freeThreadData(worker.pthread);worker.pthread=undefined;},receiveObjectTransfer:function(data){},loadWasmModuleToWorker:function(worker,onFinishedLoading){worker.onmessage=function(e){var d=e["data"];var cmd=d["cmd"];if(worker.pthread)PThread.currentProxiedOperationCallerThread=worker.pthread.threadInfoStruct;if(d["targetThread"]&&d["targetThread"]!=_pthread_self()){var thread=PThread.pthreads[d.targetThread];if(thread){thread.worker.postMessage(e.data,d["transferList"]);}else{console.error('Internal error! Worker sent a message "'+cmd+'" to target pthread '+d["targetThread"]+", but that thread no longer exists!");}PThread.currentProxiedOperationCallerThread=undefined;return}if(cmd==="processQueuedMainThreadWork"){_emscripten_main_thread_process_queued_calls();}else if(cmd==="spawnThread"){__spawn_thread(e.data);}else if(cmd==="cleanupThread"){__cleanup_thread(d["thread"]);}else if(cmd==="killThread"){__kill_thread(d["thread"]);}else if(cmd==="cancelThread"){__cancel_thread(d["thread"]);}else if(cmd==="loaded"){worker.loaded=true;if(onFinishedLoading)onFinishedLoading(worker);if(worker.runPthread){worker.runPthread();delete worker.runPthread;}}else if(cmd==="print"){out("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="printErr"){err("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="alert"){alert("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="exit"){var detached=worker.pthread&&Atomics.load(GROWABLE_HEAP_U32(),worker.pthread.thread+68>>2);if(detached){PThread.returnWorkerToPool(worker);}}else if(cmd==="cancelDone"){PThread.returnWorkerToPool(worker);}else if(cmd==="objectTransfer"){PThread.receiveObjectTransfer(e.data);}else if(e.data.target==="setimmediate"){worker.postMessage(e.data);}else{err("worker sent an unknown command "+cmd);}PThread.currentProxiedOperationCallerThread=undefined;};worker.onerror=function(e){err("pthread sent an error! "+e.filename+":"+e.lineno+": "+e.message);};if(ENVIRONMENT_IS_NODE){worker.on("message",function(data){worker.onmessage({data:data});});worker.on("error",function(data){worker.onerror(data);});worker.on("exit",function(data){console.log("worker exited - TODO: update the worker queue?");});}assert(wasmMemory instanceof WebAssembly.Memory,"WebAssembly memory should have been loaded by now!");assert(wasmModule instanceof WebAssembly.Module,"WebAssembly Module should have been loaded by now!");worker.postMessage({"cmd":"load","urlOrBlob":Module["mainScriptUrlOrBlob"]||_scriptDir,"wasmMemory":wasmMemory,"wasmModule":wasmModule,"DYNAMIC_BASE":DYNAMIC_BASE,"DYNAMICTOP_PTR":DYNAMICTOP_PTR});},allocateUnusedWorker:function(){var pthreadMainJs=locateFile("tfjs-backend-wasm-threaded-simd.worker.js");PThread.unusedWorkers.push(new Worker(pthreadMainJs));},getNewWorker:function(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]);}if(PThread.unusedWorkers.length>0)return PThread.unusedWorkers.pop();else return null},busySpinWait:function(msecs){var t=performance.now()+msecs;while(performance.now()>2]=value;return value}function _atexit(func,arg){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(1,1,func,arg);warnOnce("atexit() called, but EXIT_RUNTIME is not set, so atexits() will not be called. set EXIT_RUNTIME to 1 (see the FAQ)");}function ___handle_stack_overflow(){abort("stack overflow");}function __emscripten_notify_thread_queue(targetThreadId,mainThreadId){if(targetThreadId==mainThreadId){postMessage({"cmd":"processQueuedMainThreadWork"});}else if(ENVIRONMENT_IS_PTHREAD){postMessage({"targetThread":targetThreadId,"cmd":"processThreadQueue"});}else{var pthread=PThread.pthreads[targetThreadId];var worker=pthread&&pthread.worker;if(!worker){err("Cannot send message to thread with ID "+targetThreadId+", unknown thread ID!");return}worker.postMessage({"cmd":"processThreadQueue"});}return 1}function _abort(){abort();}function _emscripten_conditional_set_current_thread_status(expectedStatus,newStatus){}function _emscripten_futex_wait(addr,val,timeout){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0)return -28;if(ENVIRONMENT_IS_WORKER){var ret=Atomics.wait(GROWABLE_HEAP_I32(),addr>>2,val,timeout);if(ret==="timed-out")return -73;if(ret==="not-equal")return -6;if(ret==="ok")return 0;throw "Atomics.wait returned an unexpected value "+ret}else{var loadedVal=Atomics.load(GROWABLE_HEAP_I32(),addr>>2);if(val!=loadedVal)return -6;var tNow=performance.now();var tEnd=tNow+timeout;Atomics.store(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,addr);var ourWaitAddress=addr;while(addr==ourWaitAddress){tNow=performance.now();if(tNow>tEnd){return -73}_emscripten_main_thread_process_queued_calls();addr=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);}return 0}}function _emscripten_is_main_browser_thread(){return __pthread_is_main_browser_thread|0}function _emscripten_is_main_runtime_thread(){return __pthread_is_main_runtime_thread|0}function _emscripten_memcpy_big(dest,src,num){GROWABLE_HEAP_U8().copyWithin(dest,src,src+num);}function _emscripten_proxy_to_main_thread_js(index,sync){var numCallArgs=arguments.length-2;if(numCallArgs>20-1)throw "emscripten_proxy_to_main_thread_js: Too many arguments "+numCallArgs+" to proxied function idx="+index+", maximum supported is "+(20-1)+"!";var stack=stackSave();var args=stackAlloc(numCallArgs*8);var b=args>>3;for(var i=0;i>3]);buf+=8;}else if(ch===105){buf=buf+3&~3;args.push(GROWABLE_HEAP_I32()[buf>>2]);buf+=4;}else abort("unexpected char in asm const signature "+ch);}return args}function _emscripten_receive_on_main_thread_js(index,numCallArgs,args){_emscripten_receive_on_main_thread_js_callArgs.length=numCallArgs;var b=args>>3;for(var i=0;i>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){console.error("emscripten_realloc_buffer: Attempted to grow heap from "+buffer.byteLength+" bytes to "+size+" bytes, but got error: "+e);}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();if(requestedSize<=oldSize){return false}var PAGE_MULTIPLE=65536;var maxHeapSize=1073741824;if(requestedSize>maxHeapSize){err("Cannot enlarge memory, asked to go up to "+requestedSize+" bytes, but the limit is "+maxHeapSize+" bytes!");return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}err("Failed to grow the heap from "+oldSize+" bytes to "+newSize+" bytes, not enough memory!");return false}var JSEvents={keyEvent:0,mouseEvent:0,wheelEvent:0,uiEvent:0,focusEvent:0,deviceOrientationEvent:0,deviceMotionEvent:0,fullscreenChangeEvent:0,pointerlockChangeEvent:0,visibilityChangeEvent:0,touchEvent:0,previousFullscreenElement:null,previousScreenX:null,previousScreenY:null,removeEventListenersRegistered:false,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i);}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[];},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){JSEvents.removeEventListenersRegistered=true;}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence>2]=eventTypeId;GROWABLE_HEAP_I32()[varargs+4>>2]=eventData;GROWABLE_HEAP_I32()[varargs+8>>2]=userData;_emscripten_async_queue_on_thread_(targetThread,637534208,eventHandlerFunc,eventData,varargs);stackRestore(stackTop);},getTargetThreadForEventCallback:function(targetThread){switch(targetThread){case 1:return 0;case 2:return PThread.currentProxiedOperationCallerThread;default:return targetThread}},getNodeNameForTarget:function(target){if(!target)return "";if(target==window)return "#window";if(target==screen)return "#screen";return target&&target.nodeName?target.nodeName:""},fullscreenEnabled:function(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+1;var cString=_malloc(length);stringToUTF8(jsString,cString,length);return cString}function _emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height){var stackTop=stackSave();var varargs=stackAlloc(12);var targetCanvasPtr=0;if(targetCanvas){targetCanvasPtr=stringToNewUTF8(targetCanvas);}GROWABLE_HEAP_I32()[varargs>>2]=targetCanvasPtr;GROWABLE_HEAP_I32()[varargs+4>>2]=width;GROWABLE_HEAP_I32()[varargs+8>>2]=height;_emscripten_async_queue_on_thread_(targetThread,657457152,0,targetCanvasPtr,varargs);stackRestore(stackTop);}function _emscripten_set_offscreencanvas_size_on_target_thread(targetThread,targetCanvas,width,height){targetCanvas=targetCanvas?UTF8ToString(targetCanvas):"";_emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height);}function __maybeCStringToJsString(cString){return cString>2?UTF8ToString(cString):cString}var specialHTMLTargets=[0,typeof document!=="undefined"?document:0,typeof window!=="undefined"?window:0];function __findEventTarget(target){target=__maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!=="undefined"?document.querySelector(target):undefined);return domElement}function __findCanvasEventTarget(target){return __findEventTarget(target)}function _emscripten_set_canvas_element_size_calling_thread(target,width,height){var canvas=__findCanvasEventTarget(target);if(!canvas)return -4;if(canvas.canvasSharedPtr){GROWABLE_HEAP_I32()[canvas.canvasSharedPtr>>2]=width;GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+4>>2]=height;}if(canvas.offscreenCanvas||!canvas.controlTransferredOffscreen){if(canvas.offscreenCanvas)canvas=canvas.offscreenCanvas;var autoResizeViewport=false;if(canvas.GLctxObject&&canvas.GLctxObject.GLctx){var prevViewport=canvas.GLctxObject.GLctx.getParameter(2978);autoResizeViewport=prevViewport[0]===0&&prevViewport[1]===0&&prevViewport[2]===canvas.width&&prevViewport[3]===canvas.height;}canvas.width=width;canvas.height=height;if(autoResizeViewport){canvas.GLctxObject.GLctx.viewport(0,0,width,height);}}else if(canvas.canvasSharedPtr){var targetThread=GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+8>>2];_emscripten_set_offscreencanvas_size_on_target_thread(targetThread,target,width,height);return 1}else{return -4}return 0}function _emscripten_set_canvas_element_size_main_thread(target,width,height){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(2,1,target,width,height);return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}function _emscripten_set_canvas_element_size(target,width,height){var canvas=__findCanvasEventTarget(target);if(canvas){return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}else{return _emscripten_set_canvas_element_size_main_thread(target,width,height)}}function _emscripten_set_current_thread_status(newStatus){}function _emscripten_set_thread_name(threadId,name){}function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=function(index,divisor){ext["vertexAttribDivisorANGLE"](index,divisor);};ctx["drawArraysInstanced"]=function(mode,first,count,primcount){ext["drawArraysInstancedANGLE"](mode,first,count,primcount);};ctx["drawElementsInstanced"]=function(mode,count,type,indices,primcount){ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);};return 1}}function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=function(){return ext["createVertexArrayOES"]()};ctx["deleteVertexArray"]=function(vao){ext["deleteVertexArrayOES"](vao);};ctx["bindVertexArray"]=function(vao){ext["bindVertexArrayOES"](vao);};ctx["isVertexArray"]=function(vao){return ext["isVertexArrayOES"](vao)};return 1}}function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=function(n,bufs){ext["drawBuffersWEBGL"](n,bufs);};return 1}}var GL={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:{},currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],programInfos:{},stringCache:{},unpackAlignment:4,init:function(){var miniTempFloatBuffer=new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);for(var i=0;i>2]:-1;source+=UTF8ToString(GROWABLE_HEAP_I32()[string+i*4>>2],len<0?undefined:len);}return source},createContext:function(canvas,webGLContextAttributes){var ctx=canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=_malloc(8);GROWABLE_HEAP_I32()[handle+4>>2]=_pthread_self();var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context);}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return !(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;_free(GL.contexts[contextHandle].handle);GL.contexts[contextHandle]=null;},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;__webgl_enable_ANGLE_instanced_arrays(GLctx);__webgl_enable_OES_vertex_array_object(GLctx);__webgl_enable_WEBGL_draw_buffers(GLctx);GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query");var automaticallyEnabledExtensions=["OES_texture_float","OES_texture_half_float","OES_standard_derivatives","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBGL_depth_texture","OES_element_index_uint","EXT_texture_filter_anisotropic","EXT_frag_depth","WEBGL_draw_buffers","ANGLE_instanced_arrays","OES_texture_float_linear","OES_texture_half_float_linear","EXT_blend_minmax","EXT_shader_texture_lod","EXT_texture_norm16","WEBGL_compressed_texture_pvrtc","EXT_color_buffer_half_float","WEBGL_color_buffer_float","EXT_sRGB","WEBGL_compressed_texture_etc1","EXT_disjoint_timer_query","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_astc","EXT_color_buffer_float","WEBGL_compressed_texture_s3tc_srgb","EXT_disjoint_timer_query_webgl2","WEBKIT_WEBGL_compressed_texture_pvrtc"];var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext);}});},populateUniformTable:function(program){var p=GL.programs[program];var ptable=GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,35718);for(var i=0;i>2;contextAttributes["alpha"]=!!GROWABLE_HEAP_I32()[a+(0>>2)];contextAttributes["depth"]=!!GROWABLE_HEAP_I32()[a+(4>>2)];contextAttributes["stencil"]=!!GROWABLE_HEAP_I32()[a+(8>>2)];contextAttributes["antialias"]=!!GROWABLE_HEAP_I32()[a+(12>>2)];contextAttributes["premultipliedAlpha"]=!!GROWABLE_HEAP_I32()[a+(16>>2)];contextAttributes["preserveDrawingBuffer"]=!!GROWABLE_HEAP_I32()[a+(20>>2)];var powerPreference=GROWABLE_HEAP_I32()[a+(24>>2)];contextAttributes["powerPreference"]=__emscripten_webgl_power_preferences[powerPreference];contextAttributes["failIfMajorPerformanceCaveat"]=!!GROWABLE_HEAP_I32()[a+(28>>2)];contextAttributes.majorVersion=GROWABLE_HEAP_I32()[a+(32>>2)];contextAttributes.minorVersion=GROWABLE_HEAP_I32()[a+(36>>2)];contextAttributes.enableExtensionsByDefault=GROWABLE_HEAP_I32()[a+(40>>2)];contextAttributes.explicitSwapControl=GROWABLE_HEAP_I32()[a+(44>>2)];contextAttributes.proxyContextToMainThread=GROWABLE_HEAP_I32()[a+(48>>2)];contextAttributes.renderViaOffscreenBackBuffer=GROWABLE_HEAP_I32()[a+(52>>2)];var canvas=__findCanvasEventTarget(target);if(!canvas){return -4}if(contextAttributes.explicitSwapControl){return -1}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}function _emscripten_webgl_create_context(a0,a1){return _emscripten_webgl_do_create_context(a0,a1)}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];assert(buffer);if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){assert(SYSCALLS.varargs!=undefined);SYSCALLS.varargs+=4;var ret=GROWABLE_HEAP_I32()[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){if(low>=0)assert(high===0);else assert(high===-1);return low}};function _fd_close(fd){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(3,1,fd);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(4,1,fd,offset_low,offset_high,whence,newOffset);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");}function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(5,1,fd,iov,iovcnt,pnum);var num=0;for(var i=0;i>2];var len=GROWABLE_HEAP_I32()[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _pthread_cleanup_pop(execute){var routine=PThread.exitHandlers.pop();if(execute)routine();}function _pthread_cleanup_push(routine,arg){if(PThread.exitHandlers===null){PThread.exitHandlers=[];}PThread.exitHandlers.push(function(){dynCall_vi(routine,arg);});}function __spawn_thread(threadParams){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _spawn_thread() can only ever be called from main application thread!";var worker=PThread.getNewWorker();if(worker.pthread!==undefined)throw "Internal error!";if(!threadParams.pthread_ptr)throw "Internal error, no pthread ptr!";PThread.runningWorkers.push(worker);var tlsMemory=_malloc(128*4);for(var i=0;i<128;++i){GROWABLE_HEAP_I32()[tlsMemory+i*4>>2]=0;}var stackHigh=threadParams.stackBase+threadParams.stackSize;var pthread=PThread.pthreads[threadParams.pthread_ptr]={worker:worker,stackBase:threadParams.stackBase,stackSize:threadParams.stackSize,allocatedOwnStack:threadParams.allocatedOwnStack,thread:threadParams.pthread_ptr,threadInfoStruct:threadParams.pthread_ptr};var tis=pthread.threadInfoStruct>>2;Atomics.store(GROWABLE_HEAP_U32(),tis+(0>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(4>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(8>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(68>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(104>>2),tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),tis+(48>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(40>>2),pthread.threadInfoStruct);Atomics.store(GROWABLE_HEAP_U32(),tis+(44>>2),42);Atomics.store(GROWABLE_HEAP_U32(),tis+(108>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(84>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(80>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+8>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+12>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+20>>2),threadParams.schedPolicy);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+24>>2),threadParams.schedPrio);var global_libc=_emscripten_get_global_libc();var global_locale=global_libc+40;Atomics.store(GROWABLE_HEAP_U32(),tis+(176>>2),global_locale);worker.pthread=pthread;var msg={"cmd":"run","start_routine":threadParams.startRoutine,"arg":threadParams.arg,"threadInfoStruct":threadParams.pthread_ptr,"selfThreadId":threadParams.pthread_ptr,"parentThreadId":threadParams.parent_pthread_ptr,"stackBase":threadParams.stackBase,"stackSize":threadParams.stackSize};worker.runPthread=function(){msg.time=performance.now();worker.postMessage(msg,threadParams.transferList);};if(worker.loaded){worker.runPthread();delete worker.runPthread;}}function _pthread_getschedparam(thread,policy,schedparam){if(!policy&&!schedparam)return ERRNO_CODES.EINVAL;if(!thread){err("pthread_getschedparam called with a null thread pointer!");return ERRNO_CODES.ESRCH}var self=GROWABLE_HEAP_I32()[thread+12>>2];if(self!==thread){err("pthread_getschedparam attempted on thread "+thread+", which does not point to a valid thread, or does not exist anymore!");return ERRNO_CODES.ESRCH}var schedPolicy=Atomics.load(GROWABLE_HEAP_U32(),thread+108+20>>2);var schedPrio=Atomics.load(GROWABLE_HEAP_U32(),thread+108+24>>2);if(policy)GROWABLE_HEAP_I32()[policy>>2]=schedPolicy;if(schedparam)GROWABLE_HEAP_I32()[schedparam>>2]=schedPrio;return 0}function _pthread_self(){return __pthread_ptr|0}Module["_pthread_self"]=_pthread_self;function _pthread_create(pthread_ptr,attr,start_routine,arg){if(typeof SharedArrayBuffer==="undefined"){err("Current environment does not support SharedArrayBuffer, pthreads are not available!");return 6}if(!pthread_ptr){err("pthread_create called with a null thread pointer!");return 28}var transferList=[];var error=0;if(ENVIRONMENT_IS_PTHREAD&&(transferList.length===0||error)){return _emscripten_sync_run_in_main_thread_4(687865856,pthread_ptr,attr,start_routine,arg)}var stackSize=0;var stackBase=0;var detached=0;var schedPolicy=0;var schedPrio=0;if(attr){stackSize=GROWABLE_HEAP_I32()[attr>>2];stackSize+=81920;stackBase=GROWABLE_HEAP_I32()[attr+8>>2];detached=GROWABLE_HEAP_I32()[attr+12>>2]!==0;var inheritSched=GROWABLE_HEAP_I32()[attr+16>>2]===0;if(inheritSched){var prevSchedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];var prevSchedPrio=GROWABLE_HEAP_I32()[attr+24>>2];var parentThreadPtr=PThread.currentProxiedOperationCallerThread?PThread.currentProxiedOperationCallerThread:_pthread_self();_pthread_getschedparam(parentThreadPtr,attr+20,attr+24);schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];GROWABLE_HEAP_I32()[attr+20>>2]=prevSchedPolicy;GROWABLE_HEAP_I32()[attr+24>>2]=prevSchedPrio;}else{schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];}}else{stackSize=2097152;}var allocatedOwnStack=stackBase==0;if(allocatedOwnStack){stackBase=_memalign(16,stackSize);}else{stackBase-=stackSize;assert(stackBase>0);}var threadInfoStruct=_malloc(232);for(var i=0;i<232>>2;++i)GROWABLE_HEAP_U32()[(threadInfoStruct>>2)+i]=0;GROWABLE_HEAP_I32()[pthread_ptr>>2]=threadInfoStruct;GROWABLE_HEAP_I32()[threadInfoStruct+12>>2]=threadInfoStruct;var headPtr=threadInfoStruct+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var threadParams={stackBase:stackBase,stackSize:stackSize,allocatedOwnStack:allocatedOwnStack,schedPolicy:schedPolicy,schedPrio:schedPrio,detached:detached,startRoutine:start_routine,pthread_ptr:threadInfoStruct,parent_pthread_ptr:_pthread_self(),arg:arg,transferList:transferList};if(ENVIRONMENT_IS_PTHREAD){threadParams.cmd="spawnThread";postMessage(threadParams,transferList);}else{__spawn_thread(threadParams);}return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}function _sysconf(name){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(6,1,name);switch(name){case 30:return 16384;case 85:var maxHeapSize=1073741824;return maxHeapSize/16384;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:case 79:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return -1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}setErrNo(28);return -1}if(!ENVIRONMENT_IS_PTHREAD)PThread.initMainThreadBlock();else PThread.initWorker();var GLctx;GL.init();var proxiedFunctionTable=[null,_atexit,_emscripten_set_canvas_element_size_main_thread,_fd_close,_fd_seek,_fd_write,_sysconf];var asmLibraryArg={"__assert_fail":___assert_fail,"__call_main":___call_main,"__handle_stack_overflow":___handle_stack_overflow,"_emscripten_notify_thread_queue":__emscripten_notify_thread_queue,"abort":_abort,"emscripten_conditional_set_current_thread_status":_emscripten_conditional_set_current_thread_status,"emscripten_futex_wait":_emscripten_futex_wait,"emscripten_futex_wake":_emscripten_futex_wake,"emscripten_get_now":_emscripten_get_now,"emscripten_is_main_browser_thread":_emscripten_is_main_browser_thread,"emscripten_is_main_runtime_thread":_emscripten_is_main_runtime_thread,"emscripten_memcpy_big":_emscripten_memcpy_big,"emscripten_receive_on_main_thread_js":_emscripten_receive_on_main_thread_js,"emscripten_resize_heap":_emscripten_resize_heap,"emscripten_set_canvas_element_size":_emscripten_set_canvas_element_size,"emscripten_set_current_thread_status":_emscripten_set_current_thread_status,"emscripten_set_thread_name":_emscripten_set_thread_name,"emscripten_webgl_create_context":_emscripten_webgl_create_context,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"initPthreadsJS":initPthreadsJS,"memory":wasmMemory||Module["wasmMemory"],"pthread_cleanup_pop":_pthread_cleanup_pop,"pthread_cleanup_push":_pthread_cleanup_push,"pthread_create":_pthread_create,"pthread_self":_pthread_self,"roundf":_roundf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__wasm_call_ctors"].apply(null,arguments)};var _init=Module["_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["init"].apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["register_tensor"].apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose_data"].apply(null,arguments)};var _dispose=Module["_dispose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose"].apply(null,arguments)};var _Abs=Module["_Abs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Abs"].apply(null,arguments)};var _Add=Module["_Add"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Add"].apply(null,arguments)};var _AddN=Module["_AddN"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AddN"].apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ArgMax"].apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AvgPool"].apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["BatchMatMul"].apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ClipByValue"].apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2D"].apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2DBackpropInput"].apply(null,arguments)};var _Cos=Module["_Cos"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Cos"].apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["CropAndResize"].apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["DepthwiseConv2dNative"].apply(null,arguments)};var _Div=Module["_Div"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Div"].apply(null,arguments)};var _Equal=Module["_Equal"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Equal"].apply(null,arguments)};var _Exp=Module["_Exp"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Exp"].apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FloorDiv"].apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedBatchNorm"].apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedConv2D"].apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedDepthwiseConv2D"].apply(null,arguments)};var _Gather=Module["_Gather"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Gather"].apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GatherNd"].apply(null,arguments)};var _Greater=Module["_Greater"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Greater"].apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GreaterEqual"].apply(null,arguments)};var _Less=Module["_Less"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Less"].apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LessEqual"].apply(null,arguments)};var _Log=Module["_Log"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Log"].apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LogicalAnd"].apply(null,arguments)};var _Max=Module["_Max"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Max"].apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["MaxPool"].apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Maximum"].apply(null,arguments)};var _Min=Module["_Min"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Min"].apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Minimum"].apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Multiply"].apply(null,arguments)};var _Negate=Module["_Negate"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Negate"].apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV3"].apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV4"].apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV5"].apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NotEqual"].apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["OneHot"].apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["PadV2"].apply(null,arguments)};var _Pow=Module["_Pow"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Pow"].apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Prelu"].apply(null,arguments)};var _Relu=Module["_Relu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu"].apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu6"].apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ResizeBilinear"].apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Reverse"].apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["RotateWithOffset"].apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Rsqrt"].apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ScatterNd"].apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["SelectV2"].apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sigmoid"].apply(null,arguments)};var _Sin=Module["_Sin"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sin"].apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Softmax"].apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sqrt"].apply(null,arguments)};var _Square=Module["_Square"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Square"].apply(null,arguments)};var _Sub=Module["_Sub"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sub"].apply(null,arguments)};var _Sum=Module["_Sum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sum"].apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tanh"].apply(null,arguments)};var _Tile=Module["_Tile"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tile"].apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Transpose"].apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["_FusedMatMul"].apply(null,arguments)};var _malloc=Module["_malloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["malloc"].apply(null,arguments)};var _free=Module["_free"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["free"].apply(null,arguments)};var ___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__em_js__initPthreadsJS"].apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__errno_location"].apply(null,arguments)};var _emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_get_global_libc"].apply(null,arguments)};var _memalign=Module["_memalign"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["memalign"].apply(null,arguments)};var ___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__pthread_tsd_run_dtors"].apply(null,arguments)};var _emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_current_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_register_main_browser_thread_id"].apply(null,arguments)};var _emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_browser_thread_id"].apply(null,arguments)};var _emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_0"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_1"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_2"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_xprintf_varargs"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_3"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_4"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_5"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_6"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_7"].apply(null,arguments)};var _emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_run_in_main_runtime_thread_js"].apply(null,arguments)};var _emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_queue_on_thread_"].apply(null,arguments)};var _emscripten_tls_init=Module["_emscripten_tls_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_tls_init"].apply(null,arguments)};var ___set_stack_limit=Module["___set_stack_limit"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__set_stack_limit"].apply(null,arguments)};var stackSave=Module["stackSave"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackSave"].apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackAlloc"].apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackRestore"].apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_vi"].apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_v"].apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_ii"].apply(null,arguments)};Module["asm"]=asm;if(!Object.getOwnPropertyDescriptor(Module,"intArrayFromString"))Module["intArrayFromString"]=function(){abort("'intArrayFromString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"intArrayToString"))Module["intArrayToString"]=function(){abort("'intArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ccall"))Module["ccall"]=function(){abort("'ccall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["cwrap"]=cwrap;if(!Object.getOwnPropertyDescriptor(Module,"setValue"))Module["setValue"]=function(){abort("'setValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getValue"))Module["getValue"]=function(){abort("'getValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocate"))Module["allocate"]=function(){abort("'allocate' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getMemory"))Module["getMemory"]=function(){abort("'getMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ArrayToString"))Module["UTF8ArrayToString"]=function(){abort("'UTF8ArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ToString"))Module["UTF8ToString"]=function(){abort("'UTF8ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8Array"))Module["stringToUTF8Array"]=function(){abort("'stringToUTF8Array' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8"))Module["stringToUTF8"]=function(){abort("'stringToUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF8"))Module["lengthBytesUTF8"]=function(){abort("'lengthBytesUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreRun"))Module["addOnPreRun"]=function(){abort("'addOnPreRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnInit"))Module["addOnInit"]=function(){abort("'addOnInit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreMain"))Module["addOnPreMain"]=function(){abort("'addOnPreMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnExit"))Module["addOnExit"]=function(){abort("'addOnExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPostRun"))Module["addOnPostRun"]=function(){abort("'addOnPostRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeStringToMemory"))Module["writeStringToMemory"]=function(){abort("'writeStringToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeArrayToMemory"))Module["writeArrayToMemory"]=function(){abort("'writeArrayToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeAsciiToMemory"))Module["writeAsciiToMemory"]=function(){abort("'writeAsciiToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addRunDependency"))Module["addRunDependency"]=function(){abort("'addRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"removeRunDependency"))Module["removeRunDependency"]=function(){abort("'removeRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createFolder"))Module["FS_createFolder"]=function(){abort("'FS_createFolder' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPath"))Module["FS_createPath"]=function(){abort("'FS_createPath' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDataFile"))Module["FS_createDataFile"]=function(){abort("'FS_createDataFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPreloadedFile"))Module["FS_createPreloadedFile"]=function(){abort("'FS_createPreloadedFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLazyFile"))Module["FS_createLazyFile"]=function(){abort("'FS_createLazyFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLink"))Module["FS_createLink"]=function(){abort("'FS_createLink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDevice"))Module["FS_createDevice"]=function(){abort("'FS_createDevice' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_unlink"))Module["FS_unlink"]=function(){abort("'FS_unlink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"dynamicAlloc"))Module["dynamicAlloc"]=function(){abort("'dynamicAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadDynamicLibrary"))Module["loadDynamicLibrary"]=function(){abort("'loadDynamicLibrary' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadWebAssemblyModule"))Module["loadWebAssemblyModule"]=function(){abort("'loadWebAssemblyModule' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getLEB"))Module["getLEB"]=function(){abort("'getLEB' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFunctionTables"))Module["getFunctionTables"]=function(){abort("'getFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"alignFunctionTables"))Module["alignFunctionTables"]=function(){abort("'alignFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"registerFunctions"))Module["registerFunctions"]=function(){abort("'registerFunctions' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addFunction"))Module["addFunction"]=function(){abort("'addFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"removeFunction"))Module["removeFunction"]=function(){abort("'removeFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFuncWrapper"))Module["getFuncWrapper"]=function(){abort("'getFuncWrapper' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"prettyPrint"))Module["prettyPrint"]=function(){abort("'prettyPrint' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"makeBigInt"))Module["makeBigInt"]=function(){abort("'makeBigInt' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"dynCall"))Module["dynCall"]=function(){abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getCompilerSetting"))Module["getCompilerSetting"]=function(){abort("'getCompilerSetting' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"print"))Module["print"]=function(){abort("'print' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"printErr"))Module["printErr"]=function(){abort("'printErr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getTempRet0"))Module["getTempRet0"]=function(){abort("'getTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setTempRet0"))Module["setTempRet0"]=function(){abort("'setTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"callMain"))Module["callMain"]=function(){abort("'callMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"abort"))Module["abort"]=function(){abort("'abort' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToNewUTF8"))Module["stringToNewUTF8"]=function(){abort("'stringToNewUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscripten_realloc_buffer"))Module["emscripten_realloc_buffer"]=function(){abort("'emscripten_realloc_buffer' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ENV"))Module["ENV"]=function(){abort("'ENV' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setjmpId"))Module["setjmpId"]=function(){abort("'setjmpId' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_CODES"))Module["ERRNO_CODES"]=function(){abort("'ERRNO_CODES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_MESSAGES"))Module["ERRNO_MESSAGES"]=function(){abort("'ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setErrNo"))Module["setErrNo"]=function(){abort("'setErrNo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"DNS"))Module["DNS"]=function(){abort("'DNS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GAI_ERRNO_MESSAGES"))Module["GAI_ERRNO_MESSAGES"]=function(){abort("'GAI_ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Protocols"))Module["Protocols"]=function(){abort("'Protocols' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Sockets"))Module["Sockets"]=function(){abort("'Sockets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UNWIND_CACHE"))Module["UNWIND_CACHE"]=function(){abort("'UNWIND_CACHE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readAsmConstArgs"))Module["readAsmConstArgs"]=function(){abort("'readAsmConstArgs' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_q"))Module["jstoi_q"]=function(){abort("'jstoi_q' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_s"))Module["jstoi_s"]=function(){abort("'jstoi_s' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"reallyNegative"))Module["reallyNegative"]=function(){abort("'reallyNegative' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"formatString"))Module["formatString"]=function(){abort("'formatString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH"))Module["PATH"]=function(){abort("'PATH' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH_FS"))Module["PATH_FS"]=function(){abort("'PATH_FS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SYSCALLS"))Module["SYSCALLS"]=function(){abort("'SYSCALLS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMmap2"))Module["syscallMmap2"]=function(){abort("'syscallMmap2' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMunmap"))Module["syscallMunmap"]=function(){abort("'syscallMunmap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"flush_NO_FILESYSTEM"))Module["flush_NO_FILESYSTEM"]=function(){abort("'flush_NO_FILESYSTEM' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"JSEvents"))Module["JSEvents"]=function(){abort("'JSEvents' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"specialHTMLTargets"))Module["specialHTMLTargets"]=function(){abort("'specialHTMLTargets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangle"))Module["demangle"]=function(){abort("'demangle' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangleAll"))Module["demangleAll"]=function(){abort("'demangleAll' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jsStackTrace"))Module["jsStackTrace"]=function(){abort("'jsStackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getEnvStrings"))Module["getEnvStrings"]=function(){abort("'getEnvStrings' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64"))Module["writeI53ToI64"]=function(){abort("'writeI53ToI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Clamped"))Module["writeI53ToI64Clamped"]=function(){abort("'writeI53ToI64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Signaling"))Module["writeI53ToI64Signaling"]=function(){abort("'writeI53ToI64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Clamped"))Module["writeI53ToU64Clamped"]=function(){abort("'writeI53ToU64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Signaling"))Module["writeI53ToU64Signaling"]=function(){abort("'writeI53ToU64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromI64"))Module["readI53FromI64"]=function(){abort("'readI53FromI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromU64"))Module["readI53FromU64"]=function(){abort("'readI53FromU64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertI32PairToI53"))Module["convertI32PairToI53"]=function(){abort("'convertI32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertU32PairToI53"))Module["convertU32PairToI53"]=function(){abort("'convertU32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Browser"))Module["Browser"]=function(){abort("'Browser' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GL"))Module["GL"]=function(){abort("'GL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGet"))Module["emscriptenWebGLGet"]=function(){abort("'emscriptenWebGLGet' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetTexPixelData"))Module["emscriptenWebGLGetTexPixelData"]=function(){abort("'emscriptenWebGLGetTexPixelData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetUniform"))Module["emscriptenWebGLGetUniform"]=function(){abort("'emscriptenWebGLGetUniform' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetVertexAttrib"))Module["emscriptenWebGLGetVertexAttrib"]=function(){abort("'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AL"))Module["AL"]=function(){abort("'AL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_unicode"))Module["SDL_unicode"]=function(){abort("'SDL_unicode' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_ttfContext"))Module["SDL_ttfContext"]=function(){abort("'SDL_ttfContext' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_audio"))Module["SDL_audio"]=function(){abort("'SDL_audio' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL"))Module["SDL"]=function(){abort("'SDL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_gfx"))Module["SDL_gfx"]=function(){abort("'SDL_gfx' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLUT"))Module["GLUT"]=function(){abort("'GLUT' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"EGL"))Module["EGL"]=function(){abort("'EGL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW_Window"))Module["GLFW_Window"]=function(){abort("'GLFW_Window' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW"))Module["GLFW"]=function(){abort("'GLFW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLEW"))Module["GLEW"]=function(){abort("'GLEW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"IDBStore"))Module["IDBStore"]=function(){abort("'IDBStore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"runAndAbortIfError"))Module["runAndAbortIfError"]=function(){abort("'runAndAbortIfError' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["PThread"]=PThread;if(!Object.getOwnPropertyDescriptor(Module,"establishStackSpace"))Module["establishStackSpace"]=function(){abort("'establishStackSpace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getNoExitRuntime"))Module["getNoExitRuntime"]=function(){abort("'getNoExitRuntime' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"resetPrototype"))Module["resetPrototype"]=function(){abort("'resetPrototype' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"warnOnce"))Module["warnOnce"]=function(){abort("'warnOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackSave"))Module["stackSave"]=function(){abort("'stackSave' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackRestore"))Module["stackRestore"]=function(){abort("'stackRestore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackAlloc"))Module["stackAlloc"]=function(){abort("'stackAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AsciiToString"))Module["AsciiToString"]=function(){abort("'AsciiToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToAscii"))Module["stringToAscii"]=function(){abort("'stringToAscii' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF16ToString"))Module["UTF16ToString"]=function(){abort("'UTF16ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF16"))Module["stringToUTF16"]=function(){abort("'stringToUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF16"))Module["lengthBytesUTF16"]=function(){abort("'lengthBytesUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF32ToString"))Module["UTF32ToString"]=function(){abort("'UTF32ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF32"))Module["stringToUTF32"]=function(){abort("'stringToUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF32"))Module["lengthBytesUTF32"]=function(){abort("'lengthBytesUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8"))Module["allocateUTF8"]=function(){abort("'allocateUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8OnStack"))Module["allocateUTF8OnStack"]=function(){abort("'allocateUTF8OnStack' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["writeStackCookie"]=writeStackCookie;Module["checkStackCookie"]=checkStackCookie;Module["abortStackOverflow"]=abortStackOverflow;Module["PThread"]=PThread;Module["_pthread_self"]=_pthread_self;Module["wasmMemory"]=wasmMemory;Module["ExitStatus"]=ExitStatus;if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NORMAL"))Object.defineProperty(Module,"ALLOC_NORMAL",{configurable:true,get:function(){abort("'ALLOC_NORMAL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_STACK"))Object.defineProperty(Module,"ALLOC_STACK",{configurable:true,get:function(){abort("'ALLOC_STACK' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_DYNAMIC"))Object.defineProperty(Module,"ALLOC_DYNAMIC",{configurable:true,get:function(){abort("'ALLOC_DYNAMIC' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NONE"))Object.defineProperty(Module,"ALLOC_NONE",{configurable:true,get:function(){abort("'ALLOC_NONE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}writeStackCookie();preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();assert(!Module["_main"],'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}checkStackCookie();}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}if(!ENVIRONMENT_IS_PTHREAD)noExitRuntime=true;if(!ENVIRONMENT_IS_PTHREAD)run(); + function GROWABLE_HEAP_I8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP8}function GROWABLE_HEAP_U8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU8}function GROWABLE_HEAP_I32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP32}function GROWABLE_HEAP_U32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPF64}var Module=typeof WasmBackendModuleSimd!=="undefined"?WasmBackendModuleSimd:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(Module["ENVIRONMENT"]){throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -s ENVIRONMENT=web or -s ENVIRONMENT=node)")}var ENVIRONMENT_IS_PTHREAD=Module["ENVIRONMENT_IS_PTHREAD"]||false;if(ENVIRONMENT_IS_PTHREAD){buffer=Module["buffer"];DYNAMIC_BASE=Module["DYNAMIC_BASE"];DYNAMICTOP_PTR=Module["DYNAMICTOP_PTR"];}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};var nodeWorkerThreads;try{nodeWorkerThreads=worker_threads;}catch(e){console.error('The "worker_threads" module is not supported in this node.js build - perhaps a newer version is needed?');throw e}Worker=nodeWorkerThreads.Worker;}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}if(ENVIRONMENT_IS_NODE){read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};}else{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}else{throw new Error("environment detection error")}if(ENVIRONMENT_IS_NODE){if(typeof performance==="undefined"){performance=perf_hooks.performance;}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(!Object.getOwnPropertyDescriptor(Module,"arguments"))Object.defineProperty(Module,"arguments",{configurable:true,get:function(){abort("Module.arguments has been replaced with plain arguments_");}});if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(!Object.getOwnPropertyDescriptor(Module,"thisProgram"))Object.defineProperty(Module,"thisProgram",{configurable:true,get:function(){abort("Module.thisProgram has been replaced with plain thisProgram");}});if(Module["quit"])quit_=Module["quit"];if(!Object.getOwnPropertyDescriptor(Module,"quit"))Object.defineProperty(Module,"quit",{configurable:true,get:function(){abort("Module.quit has been replaced with plain quit_");}});assert(typeof Module["memoryInitializerPrefixURL"]==="undefined","Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["pthreadMainPrefixURL"]==="undefined","Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["cdInitializerPrefixURL"]==="undefined","Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["filePackagePrefixURL"]==="undefined","Module.filePackagePrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["read"]==="undefined","Module.read option was removed (modify read_ in JS)");assert(typeof Module["readAsync"]==="undefined","Module.readAsync option was removed (modify readAsync in JS)");assert(typeof Module["readBinary"]==="undefined","Module.readBinary option was removed (modify readBinary in JS)");assert(typeof Module["setWindowTitle"]==="undefined","Module.setWindowTitle option was removed (modify setWindowTitle in JS)");assert(typeof Module["TOTAL_MEMORY"]==="undefined","Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");if(!Object.getOwnPropertyDescriptor(Module,"read"))Object.defineProperty(Module,"read",{configurable:true,get:function(){abort("Module.read has been replaced with plain read_");}});if(!Object.getOwnPropertyDescriptor(Module,"readAsync"))Object.defineProperty(Module,"readAsync",{configurable:true,get:function(){abort("Module.readAsync has been replaced with plain readAsync");}});if(!Object.getOwnPropertyDescriptor(Module,"readBinary"))Object.defineProperty(Module,"readBinary",{configurable:true,get:function(){abort("Module.readBinary has been replaced with plain readBinary");}});if(!Object.getOwnPropertyDescriptor(Module,"setWindowTitle"))Object.defineProperty(Module,"setWindowTitle",{configurable:true,get:function(){abort("Module.setWindowTitle has been replaced with plain setWindowTitle");}});assert(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER||ENVIRONMENT_IS_NODE,"Pthreads do not work in this environment yet (need Web Workers, or an alternative to them)");var stackSave;var stackRestore;var stackAlloc;stackSave=stackRestore=stackAlloc=function(){abort("cannot use the stack before compiled code is ready to run, and has provided stack access");};function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text);}}var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(!Object.getOwnPropertyDescriptor(Module,"wasmBinary"))Object.defineProperty(Module,"wasmBinary",{configurable:true,get:function(){abort("Module.wasmBinary has been replaced with plain wasmBinary");}});var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(!Object.getOwnPropertyDescriptor(Module,"noExitRuntime"))Object.defineProperty(Module,"noExitRuntime",{configurable:true,get:function(){abort("Module.noExitRuntime has been replaced with plain noExitRuntime");}});if(typeof WebAssembly!=="object"){abort("No WebAssembly support found. Build with -s WASM=0 to target JavaScript instead.");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":165,"maximum":165+0,"element":"anyfunc"});var wasmModule;var threadInfoStruct=0;var selfThreadId=0;var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;assert(returnType!=="array",'Return type should not be "array".');if(args){for(var i=0;i=endIdx)){var u0=heap[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heap[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heap[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2;}else{if((u0&248)!=240)warnOnce("Invalid UTF-8 leading byte 0x"+u0.toString(16)+" encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!");u0=(u0&7)<<18|u1<<12|u2<<6|heap[idx++]&63;}if(u0<65536){str+=String.fromCharCode(u0);}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023);}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;if(u>=2097152)warnOnce("Invalid Unicode code point 0x"+u.toString(16)+" encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).");heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){assert(typeof maxBytesToWrite=="number","stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");return stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4;}return len}function writeArrayToMemory(array,buffer){assert(array.length>=0,"writeArrayToMemory array must have a length (should be an array or typed array)");GROWABLE_HEAP_I8().set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var STACK_BASE=5256288,STACKTOP=STACK_BASE,STACK_MAX=13408,DYNAMIC_BASE=5256288,DYNAMICTOP_PTR=12480;assert(STACK_BASE%16===0,"stack must start aligned");assert(DYNAMIC_BASE%16===0,"heap must start aligned");if(ENVIRONMENT_IS_PTHREAD){STACK_MAX=STACKTOP=STACK_MAX=2147483647;}var TOTAL_STACK=5242880;if(Module["TOTAL_STACK"])assert(TOTAL_STACK===Module["TOTAL_STACK"],"the stack size can no longer be determined at runtime");var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||1073741824;if(!Object.getOwnPropertyDescriptor(Module,"INITIAL_MEMORY"))Object.defineProperty(Module,"INITIAL_MEMORY",{configurable:true,get:function(){abort("Module.INITIAL_MEMORY has been replaced with plain INITIAL_INITIAL_MEMORY");}});assert(INITIAL_INITIAL_MEMORY>=TOTAL_STACK,"INITIAL_MEMORY should be larger than TOTAL_STACK, was "+INITIAL_INITIAL_MEMORY+"! (TOTAL_STACK="+TOTAL_STACK+")");assert(typeof Int32Array!=="undefined"&&typeof Float64Array!=="undefined"&&Int32Array.prototype.subarray!==undefined&&Int32Array.prototype.set!==undefined,"JS engine does not provide full typed array support");if(ENVIRONMENT_IS_PTHREAD){wasmMemory=Module["wasmMemory"];buffer=Module["buffer"];}else{if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":1073741824/WASM_PAGE_SIZE,"shared":true});if(!(wasmMemory.buffer instanceof SharedArrayBuffer)){err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");if(ENVIRONMENT_IS_NODE){console.log("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)");}throw Error("bad memory")}}}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;assert(INITIAL_INITIAL_MEMORY%WASM_PAGE_SIZE===0);assert(65536%WASM_PAGE_SIZE===0);updateGlobalBufferAndViews(buffer);if(!ENVIRONMENT_IS_PTHREAD){GROWABLE_HEAP_I32()[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;}function writeStackCookie(){assert((STACK_MAX&3)==0);GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1]=34821223;GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2]=2310721022;GROWABLE_HEAP_I32()[0]=1668509029;}function checkStackCookie(){var cookie1=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1];var cookie2=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2];if(cookie1!=34821223||cookie2!=2310721022){abort("Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x"+cookie2.toString(16)+" "+cookie1.toString(16));}if(GROWABLE_HEAP_I32()[0]!==1668509029)abort("Runtime error: The application has corrupted its heap memory area (address zero)!");}function abortStackOverflow(allocSize){abort("Stack overflow! Attempted to allocate "+allocSize+" bytes on the stack, but stack has only "+(STACK_MAX-stackSave()+allocSize)+" bytes available!");}(function(){var h16=new Int16Array(1);var h8=new Int8Array(h16.buffer);h16[0]=25459;if(h8[0]!==115||h8[1]!==99)throw "Runtime error: expected the system to be little-endian!"})();function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;if(ENVIRONMENT_IS_PTHREAD)runtimeInitialized=true;function preRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){checkStackCookie();assert(!runtimeInitialized);runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__);}function preMain(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;callRuntimeCallbacks(__ATMAIN__);}function postRun(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}assert(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;var runDependencyTracking={};function addRunDependency(id){assert(!ENVIRONMENT_IS_PTHREAD,"addRunDependency cannot be used in a pthread worker");runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(!runDependencyTracking[id]);runDependencyTracking[id]=1;if(runDependencyWatcher===null&&typeof setInterval!=="undefined"){runDependencyWatcher=setInterval(function(){if(ABORT){clearInterval(runDependencyWatcher);runDependencyWatcher=null;return}var shown=false;for(var dep in runDependencyTracking){if(!shown){shown=true;err("still waiting on run dependencies:");}err("dependency: "+dep);}if(shown){err("(end of list)");}},1e4);}}else{err("warning: run dependency added without ID");}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(runDependencyTracking[id]);delete runDependencyTracking[id];}else{err("warning: run dependency removed without ID");}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}if(ENVIRONMENT_IS_PTHREAD)console.error("Pthread aborting at "+(new Error).stack);what+="";out(what);err(what);ABORT=true;var output="abort("+what+") at "+stackTrace();what=output;throw new WebAssembly.RuntimeError(what)}var FS={error:function(){abort("Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -s FORCE_FILESYSTEM=1");},init:function(){FS.error();},createDataFile:function(){FS.error();},createPreloadedFile:function(){FS.error();},createLazyFile:function(){FS.error();},open:function(){FS.error();},mkdev:function(){FS.error();},registerDevice:function(){FS.error();},analyzePath:function(){FS.error();},loadFilesFromDB:function(){FS.error();},ErrnoError:function ErrnoError(){FS.error();}};Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm-threaded-simd.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmModule=module;if(!ENVIRONMENT_IS_PTHREAD){var numWorkersToLoad=PThread.unusedWorkers.length;PThread.unusedWorkers.forEach(function(w){PThread.loadWasmModuleToWorker(w,function(){if(!--numWorkersToLoad)removeRunDependency("wasm-instantiate");});});}}if(!ENVIRONMENT_IS_PTHREAD){addRunDependency("wasm-instantiate");}var trueModule=Module;function receiveInstantiatedSource(output){assert(Module===trueModule,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");trueModule=null;receiveInstance(output["instance"],output["module"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}var ASM_CONSTS={};function initPthreadsJS(){PThread.initRuntime();}if(!ENVIRONMENT_IS_PTHREAD)__ATINIT__.push({func:function(){___wasm_call_ctors();}});function demangle(func){warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling");return func}function demangleAll(text){var regex=/\b_Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}var __pthread_ptr=0;var __pthread_is_main_runtime_thread=0;var __pthread_is_main_browser_thread=0;function __register_pthread_ptr(pthreadPtr,isMainBrowserThread,isMainRuntimeThread){pthreadPtr=pthreadPtr|0;isMainBrowserThread=isMainBrowserThread|0;isMainRuntimeThread=isMainRuntimeThread|0;__pthread_ptr=pthreadPtr;__pthread_is_main_browser_thread=isMainBrowserThread;__pthread_is_main_runtime_thread=isMainRuntimeThread;}Module["__register_pthread_ptr"]=__register_pthread_ptr;var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var __main_thread_futex_wait_address=13392;function _emscripten_futex_wake(addr,count){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0||count<0)return -28;if(count==0)return 0;if(count>=2147483647)count=Infinity;var mainThreadWaitAddress=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);var mainThreadWoken=0;if(mainThreadWaitAddress==addr){var loadedAddr=Atomics.compareExchange(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,mainThreadWaitAddress,0);if(loadedAddr==mainThreadWaitAddress){--count;mainThreadWoken=1;if(count<=0)return 1}}var ret=Atomics.notify(GROWABLE_HEAP_I32(),addr>>2,count);if(ret>=0)return ret+mainThreadWoken;throw "Atomics.notify returned an unexpected value "+ret}Module["_emscripten_futex_wake"]=_emscripten_futex_wake;function __kill_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _kill_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _kill_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];pthread.worker.terminate();PThread.freeThreadData(pthread);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(pthread.worker),1);pthread.worker.pthread=undefined;}function __cancel_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cancel_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cancel_thread!";var pthread=PThread.pthreads[pthread_ptr];pthread.worker.postMessage({"cmd":"cancel"});}function __cleanup_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cleanup_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cleanup_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];if(pthread){var worker=pthread.worker;PThread.returnWorkerToPool(worker);}}var PThread={MAIN_THREAD_ID:1,mainThreadInfo:{schedPolicy:0,schedPrio:0},unusedWorkers:[],runningWorkers:[],initRuntime:function(){__register_pthread_ptr(PThread.mainThreadBlock,!ENVIRONMENT_IS_WORKER,1);_emscripten_register_main_browser_thread_id(PThread.mainThreadBlock);},initMainThreadBlock:function(){assert(!ENVIRONMENT_IS_PTHREAD);var pthreadPoolSize=8;for(var i=0;i>2]=PThread.mainThreadBlock;var headPtr=PThread.mainThreadBlock+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var tlsMemory=12880;for(var i=0;i<128;++i)GROWABLE_HEAP_U32()[tlsMemory/4+i]=0;Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+104>>2,tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+40>>2,PThread.mainThreadBlock);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+44>>2,42);},initWorker:function(){},pthreads:{},exitHandlers:null,setThreadStatus:function(){},runExitHandlers:function(){if(PThread.exitHandlers!==null){while(PThread.exitHandlers.length>0){PThread.exitHandlers.pop()();}PThread.exitHandlers=null;}if(ENVIRONMENT_IS_PTHREAD&&threadInfoStruct)___pthread_tsd_run_dtors();},threadExit:function(exitCode){var tb=_pthread_self();if(tb){err("Pthread 0x"+tb.toString(16)+" exited.");Atomics.store(GROWABLE_HEAP_U32(),tb+4>>2,exitCode);Atomics.store(GROWABLE_HEAP_U32(),tb+0>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+60>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+64>>2,0);PThread.runExitHandlers();_emscripten_futex_wake(tb+0,2147483647);__register_pthread_ptr(0,0,0);threadInfoStruct=0;if(ENVIRONMENT_IS_PTHREAD){postMessage({"cmd":"exit"});}}},threadCancel:function(){PThread.runExitHandlers();Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+4>>2,-1);Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+0>>2,1);_emscripten_futex_wake(threadInfoStruct+0,2147483647);threadInfoStruct=selfThreadId=0;__register_pthread_ptr(0,0,0);postMessage({"cmd":"cancelDone"});},terminateAllThreads:function(){for(var t in PThread.pthreads){var pthread=PThread.pthreads[t];if(pthread&&pthread.worker){PThread.returnWorkerToPool(pthread.worker);}}PThread.pthreads={};for(var i=0;i>2];GROWABLE_HEAP_I32()[pthread.threadInfoStruct+104>>2]=0;_free(tlsMemory);_free(pthread.threadInfoStruct);}pthread.threadInfoStruct=0;if(pthread.allocatedOwnStack&&pthread.stackBase)_free(pthread.stackBase);pthread.stackBase=0;if(pthread.worker)pthread.worker.pthread=null;},returnWorkerToPool:function(worker){delete PThread.pthreads[worker.pthread.thread];PThread.unusedWorkers.push(worker);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);PThread.freeThreadData(worker.pthread);worker.pthread=undefined;},receiveObjectTransfer:function(data){},loadWasmModuleToWorker:function(worker,onFinishedLoading){worker.onmessage=function(e){var d=e["data"];var cmd=d["cmd"];if(worker.pthread)PThread.currentProxiedOperationCallerThread=worker.pthread.threadInfoStruct;if(d["targetThread"]&&d["targetThread"]!=_pthread_self()){var thread=PThread.pthreads[d.targetThread];if(thread){thread.worker.postMessage(e.data,d["transferList"]);}else{console.error('Internal error! Worker sent a message "'+cmd+'" to target pthread '+d["targetThread"]+", but that thread no longer exists!");}PThread.currentProxiedOperationCallerThread=undefined;return}if(cmd==="processQueuedMainThreadWork"){_emscripten_main_thread_process_queued_calls();}else if(cmd==="spawnThread"){__spawn_thread(e.data);}else if(cmd==="cleanupThread"){__cleanup_thread(d["thread"]);}else if(cmd==="killThread"){__kill_thread(d["thread"]);}else if(cmd==="cancelThread"){__cancel_thread(d["thread"]);}else if(cmd==="loaded"){worker.loaded=true;if(onFinishedLoading)onFinishedLoading(worker);if(worker.runPthread){worker.runPthread();delete worker.runPthread;}}else if(cmd==="print"){out("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="printErr"){err("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="alert"){alert("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="exit"){var detached=worker.pthread&&Atomics.load(GROWABLE_HEAP_U32(),worker.pthread.thread+68>>2);if(detached){PThread.returnWorkerToPool(worker);}}else if(cmd==="cancelDone"){PThread.returnWorkerToPool(worker);}else if(cmd==="objectTransfer"){PThread.receiveObjectTransfer(e.data);}else if(e.data.target==="setimmediate"){worker.postMessage(e.data);}else{err("worker sent an unknown command "+cmd);}PThread.currentProxiedOperationCallerThread=undefined;};worker.onerror=function(e){err("pthread sent an error! "+e.filename+":"+e.lineno+": "+e.message);};if(ENVIRONMENT_IS_NODE){worker.on("message",function(data){worker.onmessage({data:data});});worker.on("error",function(data){worker.onerror(data);});worker.on("exit",function(data){console.log("worker exited - TODO: update the worker queue?");});}assert(wasmMemory instanceof WebAssembly.Memory,"WebAssembly memory should have been loaded by now!");assert(wasmModule instanceof WebAssembly.Module,"WebAssembly Module should have been loaded by now!");worker.postMessage({"cmd":"load","urlOrBlob":Module["mainScriptUrlOrBlob"]||_scriptDir,"wasmMemory":wasmMemory,"wasmModule":wasmModule,"DYNAMIC_BASE":DYNAMIC_BASE,"DYNAMICTOP_PTR":DYNAMICTOP_PTR});},allocateUnusedWorker:function(){var pthreadMainJs=locateFile("tfjs-backend-wasm-threaded-simd.worker.js");PThread.unusedWorkers.push(new Worker(pthreadMainJs));},getNewWorker:function(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]);}if(PThread.unusedWorkers.length>0)return PThread.unusedWorkers.pop();else return null},busySpinWait:function(msecs){var t=performance.now()+msecs;while(performance.now()>2]=value;return value}function _atexit(func,arg){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(1,1,func,arg);warnOnce("atexit() called, but EXIT_RUNTIME is not set, so atexits() will not be called. set EXIT_RUNTIME to 1 (see the FAQ)");}function ___handle_stack_overflow(){abort("stack overflow");}function __emscripten_notify_thread_queue(targetThreadId,mainThreadId){if(targetThreadId==mainThreadId){postMessage({"cmd":"processQueuedMainThreadWork"});}else if(ENVIRONMENT_IS_PTHREAD){postMessage({"targetThread":targetThreadId,"cmd":"processThreadQueue"});}else{var pthread=PThread.pthreads[targetThreadId];var worker=pthread&&pthread.worker;if(!worker){err("Cannot send message to thread with ID "+targetThreadId+", unknown thread ID!");return}worker.postMessage({"cmd":"processThreadQueue"});}return 1}function _abort(){abort();}function _emscripten_conditional_set_current_thread_status(expectedStatus,newStatus){}function _emscripten_futex_wait(addr,val,timeout){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0)return -28;if(ENVIRONMENT_IS_WORKER){var ret=Atomics.wait(GROWABLE_HEAP_I32(),addr>>2,val,timeout);if(ret==="timed-out")return -73;if(ret==="not-equal")return -6;if(ret==="ok")return 0;throw "Atomics.wait returned an unexpected value "+ret}else{var loadedVal=Atomics.load(GROWABLE_HEAP_I32(),addr>>2);if(val!=loadedVal)return -6;var tNow=performance.now();var tEnd=tNow+timeout;Atomics.store(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,addr);var ourWaitAddress=addr;while(addr==ourWaitAddress){tNow=performance.now();if(tNow>tEnd){return -73}_emscripten_main_thread_process_queued_calls();addr=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);}return 0}}function _emscripten_is_main_browser_thread(){return __pthread_is_main_browser_thread|0}function _emscripten_is_main_runtime_thread(){return __pthread_is_main_runtime_thread|0}function _emscripten_memcpy_big(dest,src,num){GROWABLE_HEAP_U8().copyWithin(dest,src,src+num);}function _emscripten_num_logical_cores(){return navigator["hardwareConcurrency"]}function _emscripten_proxy_to_main_thread_js(index,sync){var numCallArgs=arguments.length-2;if(numCallArgs>20-1)throw "emscripten_proxy_to_main_thread_js: Too many arguments "+numCallArgs+" to proxied function idx="+index+", maximum supported is "+(20-1)+"!";var stack=stackSave();var args=stackAlloc(numCallArgs*8);var b=args>>3;for(var i=0;i>3]);buf+=8;}else if(ch===105){buf=buf+3&~3;args.push(GROWABLE_HEAP_I32()[buf>>2]);buf+=4;}else abort("unexpected char in asm const signature "+ch);}return args}function _emscripten_receive_on_main_thread_js(index,numCallArgs,args){_emscripten_receive_on_main_thread_js_callArgs.length=numCallArgs;var b=args>>3;for(var i=0;i>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){console.error("emscripten_realloc_buffer: Attempted to grow heap from "+buffer.byteLength+" bytes to "+size+" bytes, but got error: "+e);}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();if(requestedSize<=oldSize){return false}var PAGE_MULTIPLE=65536;var maxHeapSize=1073741824;if(requestedSize>maxHeapSize){err("Cannot enlarge memory, asked to go up to "+requestedSize+" bytes, but the limit is "+maxHeapSize+" bytes!");return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}err("Failed to grow the heap from "+oldSize+" bytes to "+newSize+" bytes, not enough memory!");return false}var JSEvents={keyEvent:0,mouseEvent:0,wheelEvent:0,uiEvent:0,focusEvent:0,deviceOrientationEvent:0,deviceMotionEvent:0,fullscreenChangeEvent:0,pointerlockChangeEvent:0,visibilityChangeEvent:0,touchEvent:0,previousFullscreenElement:null,previousScreenX:null,previousScreenY:null,removeEventListenersRegistered:false,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i);}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[];},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){JSEvents.removeEventListenersRegistered=true;}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence>2]=eventTypeId;GROWABLE_HEAP_I32()[varargs+4>>2]=eventData;GROWABLE_HEAP_I32()[varargs+8>>2]=userData;_emscripten_async_queue_on_thread_(targetThread,637534208,eventHandlerFunc,eventData,varargs);stackRestore(stackTop);},getTargetThreadForEventCallback:function(targetThread){switch(targetThread){case 1:return 0;case 2:return PThread.currentProxiedOperationCallerThread;default:return targetThread}},getNodeNameForTarget:function(target){if(!target)return "";if(target==window)return "#window";if(target==screen)return "#screen";return target&&target.nodeName?target.nodeName:""},fullscreenEnabled:function(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+1;var cString=_malloc(length);stringToUTF8(jsString,cString,length);return cString}function _emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height){var stackTop=stackSave();var varargs=stackAlloc(12);var targetCanvasPtr=0;if(targetCanvas){targetCanvasPtr=stringToNewUTF8(targetCanvas);}GROWABLE_HEAP_I32()[varargs>>2]=targetCanvasPtr;GROWABLE_HEAP_I32()[varargs+4>>2]=width;GROWABLE_HEAP_I32()[varargs+8>>2]=height;_emscripten_async_queue_on_thread_(targetThread,657457152,0,targetCanvasPtr,varargs);stackRestore(stackTop);}function _emscripten_set_offscreencanvas_size_on_target_thread(targetThread,targetCanvas,width,height){targetCanvas=targetCanvas?UTF8ToString(targetCanvas):"";_emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height);}function __maybeCStringToJsString(cString){return cString>2?UTF8ToString(cString):cString}var specialHTMLTargets=[0,typeof document!=="undefined"?document:0,typeof window!=="undefined"?window:0];function __findEventTarget(target){target=__maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!=="undefined"?document.querySelector(target):undefined);return domElement}function __findCanvasEventTarget(target){return __findEventTarget(target)}function _emscripten_set_canvas_element_size_calling_thread(target,width,height){var canvas=__findCanvasEventTarget(target);if(!canvas)return -4;if(canvas.canvasSharedPtr){GROWABLE_HEAP_I32()[canvas.canvasSharedPtr>>2]=width;GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+4>>2]=height;}if(canvas.offscreenCanvas||!canvas.controlTransferredOffscreen){if(canvas.offscreenCanvas)canvas=canvas.offscreenCanvas;var autoResizeViewport=false;if(canvas.GLctxObject&&canvas.GLctxObject.GLctx){var prevViewport=canvas.GLctxObject.GLctx.getParameter(2978);autoResizeViewport=prevViewport[0]===0&&prevViewport[1]===0&&prevViewport[2]===canvas.width&&prevViewport[3]===canvas.height;}canvas.width=width;canvas.height=height;if(autoResizeViewport){canvas.GLctxObject.GLctx.viewport(0,0,width,height);}}else if(canvas.canvasSharedPtr){var targetThread=GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+8>>2];_emscripten_set_offscreencanvas_size_on_target_thread(targetThread,target,width,height);return 1}else{return -4}return 0}function _emscripten_set_canvas_element_size_main_thread(target,width,height){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(2,1,target,width,height);return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}function _emscripten_set_canvas_element_size(target,width,height){var canvas=__findCanvasEventTarget(target);if(canvas){return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}else{return _emscripten_set_canvas_element_size_main_thread(target,width,height)}}function _emscripten_set_current_thread_status(newStatus){}function _emscripten_set_thread_name(threadId,name){}function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=function(index,divisor){ext["vertexAttribDivisorANGLE"](index,divisor);};ctx["drawArraysInstanced"]=function(mode,first,count,primcount){ext["drawArraysInstancedANGLE"](mode,first,count,primcount);};ctx["drawElementsInstanced"]=function(mode,count,type,indices,primcount){ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);};return 1}}function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=function(){return ext["createVertexArrayOES"]()};ctx["deleteVertexArray"]=function(vao){ext["deleteVertexArrayOES"](vao);};ctx["bindVertexArray"]=function(vao){ext["bindVertexArrayOES"](vao);};ctx["isVertexArray"]=function(vao){return ext["isVertexArrayOES"](vao)};return 1}}function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=function(n,bufs){ext["drawBuffersWEBGL"](n,bufs);};return 1}}var GL={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:{},currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],programInfos:{},stringCache:{},unpackAlignment:4,init:function(){var miniTempFloatBuffer=new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);for(var i=0;i>2]:-1;source+=UTF8ToString(GROWABLE_HEAP_I32()[string+i*4>>2],len<0?undefined:len);}return source},createContext:function(canvas,webGLContextAttributes){var ctx=canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=_malloc(8);GROWABLE_HEAP_I32()[handle+4>>2]=_pthread_self();var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context);}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return !(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;_free(GL.contexts[contextHandle].handle);GL.contexts[contextHandle]=null;},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;__webgl_enable_ANGLE_instanced_arrays(GLctx);__webgl_enable_OES_vertex_array_object(GLctx);__webgl_enable_WEBGL_draw_buffers(GLctx);GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query");var automaticallyEnabledExtensions=["OES_texture_float","OES_texture_half_float","OES_standard_derivatives","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBGL_depth_texture","OES_element_index_uint","EXT_texture_filter_anisotropic","EXT_frag_depth","WEBGL_draw_buffers","ANGLE_instanced_arrays","OES_texture_float_linear","OES_texture_half_float_linear","EXT_blend_minmax","EXT_shader_texture_lod","EXT_texture_norm16","WEBGL_compressed_texture_pvrtc","EXT_color_buffer_half_float","WEBGL_color_buffer_float","EXT_sRGB","WEBGL_compressed_texture_etc1","EXT_disjoint_timer_query","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_astc","EXT_color_buffer_float","WEBGL_compressed_texture_s3tc_srgb","EXT_disjoint_timer_query_webgl2","WEBKIT_WEBGL_compressed_texture_pvrtc"];var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext);}});},populateUniformTable:function(program){var p=GL.programs[program];var ptable=GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,35718);for(var i=0;i>2;contextAttributes["alpha"]=!!GROWABLE_HEAP_I32()[a+(0>>2)];contextAttributes["depth"]=!!GROWABLE_HEAP_I32()[a+(4>>2)];contextAttributes["stencil"]=!!GROWABLE_HEAP_I32()[a+(8>>2)];contextAttributes["antialias"]=!!GROWABLE_HEAP_I32()[a+(12>>2)];contextAttributes["premultipliedAlpha"]=!!GROWABLE_HEAP_I32()[a+(16>>2)];contextAttributes["preserveDrawingBuffer"]=!!GROWABLE_HEAP_I32()[a+(20>>2)];var powerPreference=GROWABLE_HEAP_I32()[a+(24>>2)];contextAttributes["powerPreference"]=__emscripten_webgl_power_preferences[powerPreference];contextAttributes["failIfMajorPerformanceCaveat"]=!!GROWABLE_HEAP_I32()[a+(28>>2)];contextAttributes.majorVersion=GROWABLE_HEAP_I32()[a+(32>>2)];contextAttributes.minorVersion=GROWABLE_HEAP_I32()[a+(36>>2)];contextAttributes.enableExtensionsByDefault=GROWABLE_HEAP_I32()[a+(40>>2)];contextAttributes.explicitSwapControl=GROWABLE_HEAP_I32()[a+(44>>2)];contextAttributes.proxyContextToMainThread=GROWABLE_HEAP_I32()[a+(48>>2)];contextAttributes.renderViaOffscreenBackBuffer=GROWABLE_HEAP_I32()[a+(52>>2)];var canvas=__findCanvasEventTarget(target);if(!canvas){return -4}if(contextAttributes.explicitSwapControl){return -1}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}function _emscripten_webgl_create_context(a0,a1){return _emscripten_webgl_do_create_context(a0,a1)}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];assert(buffer);if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){assert(SYSCALLS.varargs!=undefined);SYSCALLS.varargs+=4;var ret=GROWABLE_HEAP_I32()[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){if(low>=0)assert(high===0);else assert(high===-1);return low}};function _fd_close(fd){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(3,1,fd);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(4,1,fd,offset_low,offset_high,whence,newOffset);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");}function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(5,1,fd,iov,iovcnt,pnum);var num=0;for(var i=0;i>2];var len=GROWABLE_HEAP_I32()[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _pthread_cleanup_pop(execute){var routine=PThread.exitHandlers.pop();if(execute)routine();}function _pthread_cleanup_push(routine,arg){if(PThread.exitHandlers===null){PThread.exitHandlers=[];}PThread.exitHandlers.push(function(){dynCall_vi(routine,arg);});}function __spawn_thread(threadParams){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _spawn_thread() can only ever be called from main application thread!";var worker=PThread.getNewWorker();if(worker.pthread!==undefined)throw "Internal error!";if(!threadParams.pthread_ptr)throw "Internal error, no pthread ptr!";PThread.runningWorkers.push(worker);var tlsMemory=_malloc(128*4);for(var i=0;i<128;++i){GROWABLE_HEAP_I32()[tlsMemory+i*4>>2]=0;}var stackHigh=threadParams.stackBase+threadParams.stackSize;var pthread=PThread.pthreads[threadParams.pthread_ptr]={worker:worker,stackBase:threadParams.stackBase,stackSize:threadParams.stackSize,allocatedOwnStack:threadParams.allocatedOwnStack,thread:threadParams.pthread_ptr,threadInfoStruct:threadParams.pthread_ptr};var tis=pthread.threadInfoStruct>>2;Atomics.store(GROWABLE_HEAP_U32(),tis+(0>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(4>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(8>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(68>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(104>>2),tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),tis+(48>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(40>>2),pthread.threadInfoStruct);Atomics.store(GROWABLE_HEAP_U32(),tis+(44>>2),42);Atomics.store(GROWABLE_HEAP_U32(),tis+(108>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(84>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(80>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+8>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+12>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+20>>2),threadParams.schedPolicy);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+24>>2),threadParams.schedPrio);var global_libc=_emscripten_get_global_libc();var global_locale=global_libc+40;Atomics.store(GROWABLE_HEAP_U32(),tis+(176>>2),global_locale);worker.pthread=pthread;var msg={"cmd":"run","start_routine":threadParams.startRoutine,"arg":threadParams.arg,"threadInfoStruct":threadParams.pthread_ptr,"selfThreadId":threadParams.pthread_ptr,"parentThreadId":threadParams.parent_pthread_ptr,"stackBase":threadParams.stackBase,"stackSize":threadParams.stackSize};worker.runPthread=function(){msg.time=performance.now();worker.postMessage(msg,threadParams.transferList);};if(worker.loaded){worker.runPthread();delete worker.runPthread;}}function _pthread_getschedparam(thread,policy,schedparam){if(!policy&&!schedparam)return ERRNO_CODES.EINVAL;if(!thread){err("pthread_getschedparam called with a null thread pointer!");return ERRNO_CODES.ESRCH}var self=GROWABLE_HEAP_I32()[thread+12>>2];if(self!==thread){err("pthread_getschedparam attempted on thread "+thread+", which does not point to a valid thread, or does not exist anymore!");return ERRNO_CODES.ESRCH}var schedPolicy=Atomics.load(GROWABLE_HEAP_U32(),thread+108+20>>2);var schedPrio=Atomics.load(GROWABLE_HEAP_U32(),thread+108+24>>2);if(policy)GROWABLE_HEAP_I32()[policy>>2]=schedPolicy;if(schedparam)GROWABLE_HEAP_I32()[schedparam>>2]=schedPrio;return 0}function _pthread_self(){return __pthread_ptr|0}Module["_pthread_self"]=_pthread_self;function _pthread_create(pthread_ptr,attr,start_routine,arg){if(typeof SharedArrayBuffer==="undefined"){err("Current environment does not support SharedArrayBuffer, pthreads are not available!");return 6}if(!pthread_ptr){err("pthread_create called with a null thread pointer!");return 28}var transferList=[];var error=0;if(ENVIRONMENT_IS_PTHREAD&&(transferList.length===0||error)){return _emscripten_sync_run_in_main_thread_4(687865856,pthread_ptr,attr,start_routine,arg)}var stackSize=0;var stackBase=0;var detached=0;var schedPolicy=0;var schedPrio=0;if(attr){stackSize=GROWABLE_HEAP_I32()[attr>>2];stackSize+=81920;stackBase=GROWABLE_HEAP_I32()[attr+8>>2];detached=GROWABLE_HEAP_I32()[attr+12>>2]!==0;var inheritSched=GROWABLE_HEAP_I32()[attr+16>>2]===0;if(inheritSched){var prevSchedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];var prevSchedPrio=GROWABLE_HEAP_I32()[attr+24>>2];var parentThreadPtr=PThread.currentProxiedOperationCallerThread?PThread.currentProxiedOperationCallerThread:_pthread_self();_pthread_getschedparam(parentThreadPtr,attr+20,attr+24);schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];GROWABLE_HEAP_I32()[attr+20>>2]=prevSchedPolicy;GROWABLE_HEAP_I32()[attr+24>>2]=prevSchedPrio;}else{schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];}}else{stackSize=2097152;}var allocatedOwnStack=stackBase==0;if(allocatedOwnStack){stackBase=_memalign(16,stackSize);}else{stackBase-=stackSize;assert(stackBase>0);}var threadInfoStruct=_malloc(232);for(var i=0;i<232>>2;++i)GROWABLE_HEAP_U32()[(threadInfoStruct>>2)+i]=0;GROWABLE_HEAP_I32()[pthread_ptr>>2]=threadInfoStruct;GROWABLE_HEAP_I32()[threadInfoStruct+12>>2]=threadInfoStruct;var headPtr=threadInfoStruct+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var threadParams={stackBase:stackBase,stackSize:stackSize,allocatedOwnStack:allocatedOwnStack,schedPolicy:schedPolicy,schedPrio:schedPrio,detached:detached,startRoutine:start_routine,pthread_ptr:threadInfoStruct,parent_pthread_ptr:_pthread_self(),arg:arg,transferList:transferList};if(ENVIRONMENT_IS_PTHREAD){threadParams.cmd="spawnThread";postMessage(threadParams,transferList);}else{__spawn_thread(threadParams);}return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}function _sysconf(name){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(6,1,name);switch(name){case 30:return 16384;case 85:var maxHeapSize=1073741824;return maxHeapSize/16384;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:case 79:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return -1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}setErrNo(28);return -1}if(!ENVIRONMENT_IS_PTHREAD)PThread.initMainThreadBlock();else PThread.initWorker();var GLctx;GL.init();var proxiedFunctionTable=[null,_atexit,_emscripten_set_canvas_element_size_main_thread,_fd_close,_fd_seek,_fd_write,_sysconf];var asmLibraryArg={"__assert_fail":___assert_fail,"__call_main":___call_main,"__handle_stack_overflow":___handle_stack_overflow,"_emscripten_notify_thread_queue":__emscripten_notify_thread_queue,"abort":_abort,"emscripten_conditional_set_current_thread_status":_emscripten_conditional_set_current_thread_status,"emscripten_futex_wait":_emscripten_futex_wait,"emscripten_futex_wake":_emscripten_futex_wake,"emscripten_get_now":_emscripten_get_now,"emscripten_is_main_browser_thread":_emscripten_is_main_browser_thread,"emscripten_is_main_runtime_thread":_emscripten_is_main_runtime_thread,"emscripten_memcpy_big":_emscripten_memcpy_big,"emscripten_num_logical_cores":_emscripten_num_logical_cores,"emscripten_receive_on_main_thread_js":_emscripten_receive_on_main_thread_js,"emscripten_resize_heap":_emscripten_resize_heap,"emscripten_set_canvas_element_size":_emscripten_set_canvas_element_size,"emscripten_set_current_thread_status":_emscripten_set_current_thread_status,"emscripten_set_thread_name":_emscripten_set_thread_name,"emscripten_webgl_create_context":_emscripten_webgl_create_context,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"initPthreadsJS":initPthreadsJS,"memory":wasmMemory||Module["wasmMemory"],"pthread_cleanup_pop":_pthread_cleanup_pop,"pthread_cleanup_push":_pthread_cleanup_push,"pthread_create":_pthread_create,"pthread_self":_pthread_self,"roundf":_roundf,"sysconf":_sysconf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__wasm_call_ctors"].apply(null,arguments)};var _init=Module["_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["init"].apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["register_tensor"].apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose_data"].apply(null,arguments)};var _dispose=Module["_dispose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose"].apply(null,arguments)};var _Abs=Module["_Abs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Abs"].apply(null,arguments)};var _Add=Module["_Add"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Add"].apply(null,arguments)};var _AddN=Module["_AddN"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AddN"].apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ArgMax"].apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AvgPool"].apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["BatchMatMul"].apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ClipByValue"].apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2D"].apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2DBackpropInput"].apply(null,arguments)};var _Cos=Module["_Cos"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Cos"].apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["CropAndResize"].apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["DepthwiseConv2dNative"].apply(null,arguments)};var _Div=Module["_Div"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Div"].apply(null,arguments)};var _Equal=Module["_Equal"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Equal"].apply(null,arguments)};var _Exp=Module["_Exp"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Exp"].apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FloorDiv"].apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedBatchNorm"].apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedConv2D"].apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedDepthwiseConv2D"].apply(null,arguments)};var _Gather=Module["_Gather"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Gather"].apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GatherNd"].apply(null,arguments)};var _Greater=Module["_Greater"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Greater"].apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GreaterEqual"].apply(null,arguments)};var _Less=Module["_Less"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Less"].apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LessEqual"].apply(null,arguments)};var _Log=Module["_Log"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Log"].apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LogicalAnd"].apply(null,arguments)};var _Max=Module["_Max"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Max"].apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["MaxPool"].apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Maximum"].apply(null,arguments)};var _Min=Module["_Min"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Min"].apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Minimum"].apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Multiply"].apply(null,arguments)};var _Negate=Module["_Negate"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Negate"].apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV3"].apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV4"].apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV5"].apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NotEqual"].apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["OneHot"].apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["PadV2"].apply(null,arguments)};var _Pow=Module["_Pow"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Pow"].apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Prelu"].apply(null,arguments)};var _Relu=Module["_Relu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu"].apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu6"].apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ResizeBilinear"].apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Reverse"].apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["RotateWithOffset"].apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Rsqrt"].apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ScatterNd"].apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["SelectV2"].apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sigmoid"].apply(null,arguments)};var _Sin=Module["_Sin"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sin"].apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Softmax"].apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sqrt"].apply(null,arguments)};var _Square=Module["_Square"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Square"].apply(null,arguments)};var _Sub=Module["_Sub"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sub"].apply(null,arguments)};var _Sum=Module["_Sum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sum"].apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tanh"].apply(null,arguments)};var _Tile=Module["_Tile"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tile"].apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Transpose"].apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["_FusedMatMul"].apply(null,arguments)};var _malloc=Module["_malloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["malloc"].apply(null,arguments)};var _free=Module["_free"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["free"].apply(null,arguments)};var ___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__em_js__initPthreadsJS"].apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__errno_location"].apply(null,arguments)};var _emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_get_global_libc"].apply(null,arguments)};var _memalign=Module["_memalign"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["memalign"].apply(null,arguments)};var ___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__pthread_tsd_run_dtors"].apply(null,arguments)};var _emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_current_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_register_main_browser_thread_id"].apply(null,arguments)};var _emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_browser_thread_id"].apply(null,arguments)};var _emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_0"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_1"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_2"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_xprintf_varargs"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_3"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_4"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_5"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_6"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_7"].apply(null,arguments)};var _emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_run_in_main_runtime_thread_js"].apply(null,arguments)};var _emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_queue_on_thread_"].apply(null,arguments)};var _emscripten_tls_init=Module["_emscripten_tls_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_tls_init"].apply(null,arguments)};var ___set_stack_limit=Module["___set_stack_limit"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__set_stack_limit"].apply(null,arguments)};var stackSave=Module["stackSave"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackSave"].apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackAlloc"].apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackRestore"].apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_vi"].apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_v"].apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_ii"].apply(null,arguments)};Module["asm"]=asm;if(!Object.getOwnPropertyDescriptor(Module,"intArrayFromString"))Module["intArrayFromString"]=function(){abort("'intArrayFromString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"intArrayToString"))Module["intArrayToString"]=function(){abort("'intArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ccall"))Module["ccall"]=function(){abort("'ccall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["cwrap"]=cwrap;if(!Object.getOwnPropertyDescriptor(Module,"setValue"))Module["setValue"]=function(){abort("'setValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getValue"))Module["getValue"]=function(){abort("'getValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocate"))Module["allocate"]=function(){abort("'allocate' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getMemory"))Module["getMemory"]=function(){abort("'getMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ArrayToString"))Module["UTF8ArrayToString"]=function(){abort("'UTF8ArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ToString"))Module["UTF8ToString"]=function(){abort("'UTF8ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8Array"))Module["stringToUTF8Array"]=function(){abort("'stringToUTF8Array' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8"))Module["stringToUTF8"]=function(){abort("'stringToUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF8"))Module["lengthBytesUTF8"]=function(){abort("'lengthBytesUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreRun"))Module["addOnPreRun"]=function(){abort("'addOnPreRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnInit"))Module["addOnInit"]=function(){abort("'addOnInit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreMain"))Module["addOnPreMain"]=function(){abort("'addOnPreMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnExit"))Module["addOnExit"]=function(){abort("'addOnExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPostRun"))Module["addOnPostRun"]=function(){abort("'addOnPostRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeStringToMemory"))Module["writeStringToMemory"]=function(){abort("'writeStringToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeArrayToMemory"))Module["writeArrayToMemory"]=function(){abort("'writeArrayToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeAsciiToMemory"))Module["writeAsciiToMemory"]=function(){abort("'writeAsciiToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addRunDependency"))Module["addRunDependency"]=function(){abort("'addRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"removeRunDependency"))Module["removeRunDependency"]=function(){abort("'removeRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createFolder"))Module["FS_createFolder"]=function(){abort("'FS_createFolder' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPath"))Module["FS_createPath"]=function(){abort("'FS_createPath' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDataFile"))Module["FS_createDataFile"]=function(){abort("'FS_createDataFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPreloadedFile"))Module["FS_createPreloadedFile"]=function(){abort("'FS_createPreloadedFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLazyFile"))Module["FS_createLazyFile"]=function(){abort("'FS_createLazyFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLink"))Module["FS_createLink"]=function(){abort("'FS_createLink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDevice"))Module["FS_createDevice"]=function(){abort("'FS_createDevice' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_unlink"))Module["FS_unlink"]=function(){abort("'FS_unlink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"dynamicAlloc"))Module["dynamicAlloc"]=function(){abort("'dynamicAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadDynamicLibrary"))Module["loadDynamicLibrary"]=function(){abort("'loadDynamicLibrary' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadWebAssemblyModule"))Module["loadWebAssemblyModule"]=function(){abort("'loadWebAssemblyModule' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getLEB"))Module["getLEB"]=function(){abort("'getLEB' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFunctionTables"))Module["getFunctionTables"]=function(){abort("'getFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"alignFunctionTables"))Module["alignFunctionTables"]=function(){abort("'alignFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"registerFunctions"))Module["registerFunctions"]=function(){abort("'registerFunctions' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addFunction"))Module["addFunction"]=function(){abort("'addFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"removeFunction"))Module["removeFunction"]=function(){abort("'removeFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFuncWrapper"))Module["getFuncWrapper"]=function(){abort("'getFuncWrapper' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"prettyPrint"))Module["prettyPrint"]=function(){abort("'prettyPrint' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"makeBigInt"))Module["makeBigInt"]=function(){abort("'makeBigInt' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"dynCall"))Module["dynCall"]=function(){abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getCompilerSetting"))Module["getCompilerSetting"]=function(){abort("'getCompilerSetting' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"print"))Module["print"]=function(){abort("'print' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"printErr"))Module["printErr"]=function(){abort("'printErr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getTempRet0"))Module["getTempRet0"]=function(){abort("'getTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setTempRet0"))Module["setTempRet0"]=function(){abort("'setTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"callMain"))Module["callMain"]=function(){abort("'callMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"abort"))Module["abort"]=function(){abort("'abort' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToNewUTF8"))Module["stringToNewUTF8"]=function(){abort("'stringToNewUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscripten_realloc_buffer"))Module["emscripten_realloc_buffer"]=function(){abort("'emscripten_realloc_buffer' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ENV"))Module["ENV"]=function(){abort("'ENV' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setjmpId"))Module["setjmpId"]=function(){abort("'setjmpId' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_CODES"))Module["ERRNO_CODES"]=function(){abort("'ERRNO_CODES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_MESSAGES"))Module["ERRNO_MESSAGES"]=function(){abort("'ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setErrNo"))Module["setErrNo"]=function(){abort("'setErrNo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"DNS"))Module["DNS"]=function(){abort("'DNS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GAI_ERRNO_MESSAGES"))Module["GAI_ERRNO_MESSAGES"]=function(){abort("'GAI_ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Protocols"))Module["Protocols"]=function(){abort("'Protocols' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Sockets"))Module["Sockets"]=function(){abort("'Sockets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UNWIND_CACHE"))Module["UNWIND_CACHE"]=function(){abort("'UNWIND_CACHE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readAsmConstArgs"))Module["readAsmConstArgs"]=function(){abort("'readAsmConstArgs' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_q"))Module["jstoi_q"]=function(){abort("'jstoi_q' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_s"))Module["jstoi_s"]=function(){abort("'jstoi_s' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"reallyNegative"))Module["reallyNegative"]=function(){abort("'reallyNegative' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"formatString"))Module["formatString"]=function(){abort("'formatString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH"))Module["PATH"]=function(){abort("'PATH' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH_FS"))Module["PATH_FS"]=function(){abort("'PATH_FS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SYSCALLS"))Module["SYSCALLS"]=function(){abort("'SYSCALLS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMmap2"))Module["syscallMmap2"]=function(){abort("'syscallMmap2' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMunmap"))Module["syscallMunmap"]=function(){abort("'syscallMunmap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"flush_NO_FILESYSTEM"))Module["flush_NO_FILESYSTEM"]=function(){abort("'flush_NO_FILESYSTEM' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"JSEvents"))Module["JSEvents"]=function(){abort("'JSEvents' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"specialHTMLTargets"))Module["specialHTMLTargets"]=function(){abort("'specialHTMLTargets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangle"))Module["demangle"]=function(){abort("'demangle' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangleAll"))Module["demangleAll"]=function(){abort("'demangleAll' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jsStackTrace"))Module["jsStackTrace"]=function(){abort("'jsStackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getEnvStrings"))Module["getEnvStrings"]=function(){abort("'getEnvStrings' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64"))Module["writeI53ToI64"]=function(){abort("'writeI53ToI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Clamped"))Module["writeI53ToI64Clamped"]=function(){abort("'writeI53ToI64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Signaling"))Module["writeI53ToI64Signaling"]=function(){abort("'writeI53ToI64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Clamped"))Module["writeI53ToU64Clamped"]=function(){abort("'writeI53ToU64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Signaling"))Module["writeI53ToU64Signaling"]=function(){abort("'writeI53ToU64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromI64"))Module["readI53FromI64"]=function(){abort("'readI53FromI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromU64"))Module["readI53FromU64"]=function(){abort("'readI53FromU64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertI32PairToI53"))Module["convertI32PairToI53"]=function(){abort("'convertI32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertU32PairToI53"))Module["convertU32PairToI53"]=function(){abort("'convertU32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Browser"))Module["Browser"]=function(){abort("'Browser' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GL"))Module["GL"]=function(){abort("'GL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGet"))Module["emscriptenWebGLGet"]=function(){abort("'emscriptenWebGLGet' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetTexPixelData"))Module["emscriptenWebGLGetTexPixelData"]=function(){abort("'emscriptenWebGLGetTexPixelData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetUniform"))Module["emscriptenWebGLGetUniform"]=function(){abort("'emscriptenWebGLGetUniform' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetVertexAttrib"))Module["emscriptenWebGLGetVertexAttrib"]=function(){abort("'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AL"))Module["AL"]=function(){abort("'AL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_unicode"))Module["SDL_unicode"]=function(){abort("'SDL_unicode' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_ttfContext"))Module["SDL_ttfContext"]=function(){abort("'SDL_ttfContext' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_audio"))Module["SDL_audio"]=function(){abort("'SDL_audio' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL"))Module["SDL"]=function(){abort("'SDL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_gfx"))Module["SDL_gfx"]=function(){abort("'SDL_gfx' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLUT"))Module["GLUT"]=function(){abort("'GLUT' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"EGL"))Module["EGL"]=function(){abort("'EGL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW_Window"))Module["GLFW_Window"]=function(){abort("'GLFW_Window' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW"))Module["GLFW"]=function(){abort("'GLFW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLEW"))Module["GLEW"]=function(){abort("'GLEW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"IDBStore"))Module["IDBStore"]=function(){abort("'IDBStore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"runAndAbortIfError"))Module["runAndAbortIfError"]=function(){abort("'runAndAbortIfError' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["PThread"]=PThread;if(!Object.getOwnPropertyDescriptor(Module,"establishStackSpace"))Module["establishStackSpace"]=function(){abort("'establishStackSpace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getNoExitRuntime"))Module["getNoExitRuntime"]=function(){abort("'getNoExitRuntime' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"resetPrototype"))Module["resetPrototype"]=function(){abort("'resetPrototype' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"warnOnce"))Module["warnOnce"]=function(){abort("'warnOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackSave"))Module["stackSave"]=function(){abort("'stackSave' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackRestore"))Module["stackRestore"]=function(){abort("'stackRestore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackAlloc"))Module["stackAlloc"]=function(){abort("'stackAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AsciiToString"))Module["AsciiToString"]=function(){abort("'AsciiToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToAscii"))Module["stringToAscii"]=function(){abort("'stringToAscii' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF16ToString"))Module["UTF16ToString"]=function(){abort("'UTF16ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF16"))Module["stringToUTF16"]=function(){abort("'stringToUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF16"))Module["lengthBytesUTF16"]=function(){abort("'lengthBytesUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF32ToString"))Module["UTF32ToString"]=function(){abort("'UTF32ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF32"))Module["stringToUTF32"]=function(){abort("'stringToUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF32"))Module["lengthBytesUTF32"]=function(){abort("'lengthBytesUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8"))Module["allocateUTF8"]=function(){abort("'allocateUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8OnStack"))Module["allocateUTF8OnStack"]=function(){abort("'allocateUTF8OnStack' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["writeStackCookie"]=writeStackCookie;Module["checkStackCookie"]=checkStackCookie;Module["abortStackOverflow"]=abortStackOverflow;Module["PThread"]=PThread;Module["_pthread_self"]=_pthread_self;Module["wasmMemory"]=wasmMemory;Module["ExitStatus"]=ExitStatus;if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NORMAL"))Object.defineProperty(Module,"ALLOC_NORMAL",{configurable:true,get:function(){abort("'ALLOC_NORMAL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_STACK"))Object.defineProperty(Module,"ALLOC_STACK",{configurable:true,get:function(){abort("'ALLOC_STACK' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_DYNAMIC"))Object.defineProperty(Module,"ALLOC_DYNAMIC",{configurable:true,get:function(){abort("'ALLOC_DYNAMIC' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NONE"))Object.defineProperty(Module,"ALLOC_NONE",{configurable:true,get:function(){abort("'ALLOC_NONE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}writeStackCookie();preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();assert(!Module["_main"],'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}checkStackCookie();}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}if(!ENVIRONMENT_IS_PTHREAD)noExitRuntime=true;if(!ENVIRONMENT_IS_PTHREAD)run(); return WasmBackendModuleSimd diff --git a/e2e/benchmarks/tfjs-backend-wasm-threaded-simd.wasm b/e2e/benchmarks/tfjs-backend-wasm-threaded-simd.wasm index 4674086b3865c0ad51264aa3f8f7116550bdd8f7..779636fdfa58ca575ed1407406f200efecd34e0b 100644 GIT binary patch delta 12657 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 delta 39 vcmZ3zlXKNh&JDcmj9;4h*xUKo8MpJXGacn*^qhW0fXRiCVY`$d(?o9o`^5_| From ac8ed9bf29e0f745a752ee13d933629422403578 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Tue, 28 Jul 2020 15:31:30 -0400 Subject: [PATCH 23/70] pass in --- tfjs-backend-wasm/src/kernels/FusedDepthwiseConv2D.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tfjs-backend-wasm/src/kernels/FusedDepthwiseConv2D.ts b/tfjs-backend-wasm/src/kernels/FusedDepthwiseConv2D.ts index 8231ccc521b..c63bd970643 100644 --- a/tfjs-backend-wasm/src/kernels/FusedDepthwiseConv2D.ts +++ b/tfjs-backend-wasm/src/kernels/FusedDepthwiseConv2D.ts @@ -70,7 +70,7 @@ function fusedDepthwiseConv2d(args: { const convInfo = backend_util.computeConv2DInfo( (x as Tensor4D).shape, (filter as Tensor4D).shape, strides, dilations, - pad, dimRoundingMode); + pad, dimRoundingMode, true); const fusedActivation = FusableActivation[activation as {} as keyof typeof FusableActivation]; From f5348d83bdfcdc3968193f06afbfde3dff66742f Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Tue, 28 Jul 2020 16:22:45 -0400 Subject: [PATCH 24/70] fix --- tfjs-backend-wasm/src/cc/backend.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tfjs-backend-wasm/src/cc/backend.cc b/tfjs-backend-wasm/src/cc/backend.cc index 0bfadfef319..0ed68f1f0b2 100644 --- a/tfjs-backend-wasm/src/cc/backend.cc +++ b/tfjs-backend-wasm/src/cc/backend.cc @@ -50,8 +50,12 @@ TensorInfo &get_tensor_info_out(const size_t tensor_id) { } size_t xnn_operator_count = 0; -pthreadpool *threadpool = - pthreadpool_create(std::min(emscripten_num_logical_cores(), 4)); +int num_cores = 1; +#ifdef __EMSCRIPTEN__ +num_cores = emscripten_num_logical_cores(); +#endif + +pthreadpool *threadpool = pthreadpool_create(std::min(num_cores, 4)); // Registers a disposal callback for a tensor id with a given callback function. void register_disposal_callback(const size_t tensor_id, From 926d743fae38b16128510bf9bb05a4fb0571b10f Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Tue, 28 Jul 2020 17:23:48 -0400 Subject: [PATCH 25/70] numcores --- tfjs-backend-wasm/src/cc/backend.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tfjs-backend-wasm/src/cc/backend.cc b/tfjs-backend-wasm/src/cc/backend.cc index 0ed68f1f0b2..2257542a814 100644 --- a/tfjs-backend-wasm/src/cc/backend.cc +++ b/tfjs-backend-wasm/src/cc/backend.cc @@ -50,12 +50,14 @@ TensorInfo &get_tensor_info_out(const size_t tensor_id) { } size_t xnn_operator_count = 0; +#ifdef __EMSCRIPTEN_PTHREADS__ +int num_cores = emscripten_num_logical_cores() / 2; +#else int num_cores = 1; -#ifdef __EMSCRIPTEN__ -num_cores = emscripten_num_logical_cores(); #endif -pthreadpool *threadpool = pthreadpool_create(std::min(num_cores, 4)); +pthreadpool *threadpool = + pthreadpool_create(std::min(std::max(num_cores, 1), 4)); // Registers a disposal callback for a tensor id with a given callback function. void register_disposal_callback(const size_t tensor_id, From 7c02e0e8f886d4584986e06986043582fe5d6222 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Thu, 30 Jul 2020 08:53:42 -0400 Subject: [PATCH 26/70] fix --- tfjs-backend-wasm/src/cc/BUILD | 1 - 1 file changed, 1 deletion(-) diff --git a/tfjs-backend-wasm/src/cc/BUILD b/tfjs-backend-wasm/src/cc/BUILD index c4da0713cee..f1518dbb64f 100644 --- a/tfjs-backend-wasm/src/cc/BUILD +++ b/tfjs-backend-wasm/src/cc/BUILD @@ -45,7 +45,6 @@ cc_binary( "-s SIMD=1", "-s USE_PTHREADS=1", "-s PTHREAD_POOL_SIZE=4", - "-s ASSERTIONS=1", "-s INITIAL_MEMORY=1Gb", "-s MAXIMUM_MEMORY=1Gb", "-s PROXY_TO_PTHREAD=1", From c765acb58f16292c83c9bfac3413af54518f22c8 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Thu, 30 Jul 2020 09:07:24 -0400 Subject: [PATCH 27/70] update size --- e2e/benchmarks/tf-backend-wasm.js | 6 +++--- .../tfjs-backend-wasm-threaded-simd.wasm | Bin 234537 -> 229840 bytes e2e/benchmarks/tfjs-backend-wasm.wasm | Bin 154795 -> 154838 bytes .../tfjs-backend-wasm-threaded-simd.worker.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/e2e/benchmarks/tf-backend-wasm.js b/e2e/benchmarks/tf-backend-wasm.js index 2148e7e9578..f0355d21f91 100644 --- a/e2e/benchmarks/tf-backend-wasm.js +++ b/e2e/benchmarks/tf-backend-wasm.js @@ -1429,7 +1429,7 @@ const { inputs, attrs, backend } = args; const { x, filter, bias, preluActivationWeights } = inputs; const { strides, pad, dilations, dataFormat, dimRoundingMode, activation } = attrs; - const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode); + const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, true /* depthwise */); const fusedActivation = FusableActivation[activation]; if (fusedActivation == null) { throw new Error(`${activation} activation not yet supported for FusedDepthwiseConv2D ` + @@ -3378,7 +3378,7 @@ function(WasmBackendModuleSimd) { WasmBackendModuleSimd = WasmBackendModuleSimd || {}; - function GROWABLE_HEAP_I8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP8}function GROWABLE_HEAP_U8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU8}function GROWABLE_HEAP_I32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP32}function GROWABLE_HEAP_U32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPF64}var Module=typeof WasmBackendModuleSimd!=="undefined"?WasmBackendModuleSimd:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;if(Module["ENVIRONMENT"]){throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -s ENVIRONMENT=web or -s ENVIRONMENT=node)")}var ENVIRONMENT_IS_PTHREAD=Module["ENVIRONMENT_IS_PTHREAD"]||false;if(ENVIRONMENT_IS_PTHREAD){buffer=Module["buffer"];DYNAMIC_BASE=Module["DYNAMIC_BASE"];DYNAMICTOP_PTR=Module["DYNAMICTOP_PTR"];}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};var nodeWorkerThreads;try{nodeWorkerThreads=worker_threads;}catch(e){console.error('The "worker_threads" module is not supported in this node.js build - perhaps a newer version is needed?');throw e}Worker=nodeWorkerThreads.Worker;}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}if(ENVIRONMENT_IS_NODE){read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};}else{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}else{throw new Error("environment detection error")}if(ENVIRONMENT_IS_NODE){if(typeof performance==="undefined"){performance=perf_hooks.performance;}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(!Object.getOwnPropertyDescriptor(Module,"arguments"))Object.defineProperty(Module,"arguments",{configurable:true,get:function(){abort("Module.arguments has been replaced with plain arguments_");}});if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(!Object.getOwnPropertyDescriptor(Module,"thisProgram"))Object.defineProperty(Module,"thisProgram",{configurable:true,get:function(){abort("Module.thisProgram has been replaced with plain thisProgram");}});if(Module["quit"])quit_=Module["quit"];if(!Object.getOwnPropertyDescriptor(Module,"quit"))Object.defineProperty(Module,"quit",{configurable:true,get:function(){abort("Module.quit has been replaced with plain quit_");}});assert(typeof Module["memoryInitializerPrefixURL"]==="undefined","Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["pthreadMainPrefixURL"]==="undefined","Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["cdInitializerPrefixURL"]==="undefined","Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["filePackagePrefixURL"]==="undefined","Module.filePackagePrefixURL option was removed, use Module.locateFile instead");assert(typeof Module["read"]==="undefined","Module.read option was removed (modify read_ in JS)");assert(typeof Module["readAsync"]==="undefined","Module.readAsync option was removed (modify readAsync in JS)");assert(typeof Module["readBinary"]==="undefined","Module.readBinary option was removed (modify readBinary in JS)");assert(typeof Module["setWindowTitle"]==="undefined","Module.setWindowTitle option was removed (modify setWindowTitle in JS)");assert(typeof Module["TOTAL_MEMORY"]==="undefined","Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY");if(!Object.getOwnPropertyDescriptor(Module,"read"))Object.defineProperty(Module,"read",{configurable:true,get:function(){abort("Module.read has been replaced with plain read_");}});if(!Object.getOwnPropertyDescriptor(Module,"readAsync"))Object.defineProperty(Module,"readAsync",{configurable:true,get:function(){abort("Module.readAsync has been replaced with plain readAsync");}});if(!Object.getOwnPropertyDescriptor(Module,"readBinary"))Object.defineProperty(Module,"readBinary",{configurable:true,get:function(){abort("Module.readBinary has been replaced with plain readBinary");}});if(!Object.getOwnPropertyDescriptor(Module,"setWindowTitle"))Object.defineProperty(Module,"setWindowTitle",{configurable:true,get:function(){abort("Module.setWindowTitle has been replaced with plain setWindowTitle");}});assert(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER||ENVIRONMENT_IS_NODE,"Pthreads do not work in this environment yet (need Web Workers, or an alternative to them)");var stackSave;var stackRestore;var stackAlloc;stackSave=stackRestore=stackAlloc=function(){abort("cannot use the stack before compiled code is ready to run, and has provided stack access");};function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text);}}var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(!Object.getOwnPropertyDescriptor(Module,"wasmBinary"))Object.defineProperty(Module,"wasmBinary",{configurable:true,get:function(){abort("Module.wasmBinary has been replaced with plain wasmBinary");}});var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(!Object.getOwnPropertyDescriptor(Module,"noExitRuntime"))Object.defineProperty(Module,"noExitRuntime",{configurable:true,get:function(){abort("Module.noExitRuntime has been replaced with plain noExitRuntime");}});if(typeof WebAssembly!=="object"){abort("No WebAssembly support found. Build with -s WASM=0 to target JavaScript instead.");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":165,"maximum":165+0,"element":"anyfunc"});var wasmModule;var threadInfoStruct=0;var selfThreadId=0;var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;assert(returnType!=="array",'Return type should not be "array".');if(args){for(var i=0;i=endIdx)){var u0=heap[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heap[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heap[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2;}else{if((u0&248)!=240)warnOnce("Invalid UTF-8 leading byte 0x"+u0.toString(16)+" encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!");u0=(u0&7)<<18|u1<<12|u2<<6|heap[idx++]&63;}if(u0<65536){str+=String.fromCharCode(u0);}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023);}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;if(u>=2097152)warnOnce("Invalid Unicode code point 0x"+u.toString(16)+" encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).");heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){assert(typeof maxBytesToWrite=="number","stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!");return stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4;}return len}function writeArrayToMemory(array,buffer){assert(array.length>=0,"writeArrayToMemory array must have a length (should be an array or typed array)");GROWABLE_HEAP_I8().set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var STACK_BASE=5256288,STACKTOP=STACK_BASE,STACK_MAX=13408,DYNAMIC_BASE=5256288,DYNAMICTOP_PTR=12480;assert(STACK_BASE%16===0,"stack must start aligned");assert(DYNAMIC_BASE%16===0,"heap must start aligned");if(ENVIRONMENT_IS_PTHREAD){STACK_MAX=STACKTOP=STACK_MAX=2147483647;}var TOTAL_STACK=5242880;if(Module["TOTAL_STACK"])assert(TOTAL_STACK===Module["TOTAL_STACK"],"the stack size can no longer be determined at runtime");var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||1073741824;if(!Object.getOwnPropertyDescriptor(Module,"INITIAL_MEMORY"))Object.defineProperty(Module,"INITIAL_MEMORY",{configurable:true,get:function(){abort("Module.INITIAL_MEMORY has been replaced with plain INITIAL_INITIAL_MEMORY");}});assert(INITIAL_INITIAL_MEMORY>=TOTAL_STACK,"INITIAL_MEMORY should be larger than TOTAL_STACK, was "+INITIAL_INITIAL_MEMORY+"! (TOTAL_STACK="+TOTAL_STACK+")");assert(typeof Int32Array!=="undefined"&&typeof Float64Array!=="undefined"&&Int32Array.prototype.subarray!==undefined&&Int32Array.prototype.set!==undefined,"JS engine does not provide full typed array support");if(ENVIRONMENT_IS_PTHREAD){wasmMemory=Module["wasmMemory"];buffer=Module["buffer"];}else{if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":1073741824/WASM_PAGE_SIZE,"shared":true});if(!(wasmMemory.buffer instanceof SharedArrayBuffer)){err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");if(ENVIRONMENT_IS_NODE){console.log("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)");}throw Error("bad memory")}}}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;assert(INITIAL_INITIAL_MEMORY%WASM_PAGE_SIZE===0);assert(65536%WASM_PAGE_SIZE===0);updateGlobalBufferAndViews(buffer);if(!ENVIRONMENT_IS_PTHREAD){GROWABLE_HEAP_I32()[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;}function writeStackCookie(){assert((STACK_MAX&3)==0);GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1]=34821223;GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2]=2310721022;GROWABLE_HEAP_I32()[0]=1668509029;}function checkStackCookie(){var cookie1=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+1];var cookie2=GROWABLE_HEAP_U32()[(STACK_MAX>>2)+2];if(cookie1!=34821223||cookie2!=2310721022){abort("Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x"+cookie2.toString(16)+" "+cookie1.toString(16));}if(GROWABLE_HEAP_I32()[0]!==1668509029)abort("Runtime error: The application has corrupted its heap memory area (address zero)!");}function abortStackOverflow(allocSize){abort("Stack overflow! Attempted to allocate "+allocSize+" bytes on the stack, but stack has only "+(STACK_MAX-stackSave()+allocSize)+" bytes available!");}(function(){var h16=new Int16Array(1);var h8=new Int8Array(h16.buffer);h16[0]=25459;if(h8[0]!==115||h8[1]!==99)throw "Runtime error: expected the system to be little-endian!"})();function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;if(ENVIRONMENT_IS_PTHREAD)runtimeInitialized=true;function preRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){checkStackCookie();assert(!runtimeInitialized);runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__);}function preMain(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;callRuntimeCallbacks(__ATMAIN__);}function postRun(){checkStackCookie();if(ENVIRONMENT_IS_PTHREAD)return;if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}assert(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");assert(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;var runDependencyTracking={};function addRunDependency(id){assert(!ENVIRONMENT_IS_PTHREAD,"addRunDependency cannot be used in a pthread worker");runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(!runDependencyTracking[id]);runDependencyTracking[id]=1;if(runDependencyWatcher===null&&typeof setInterval!=="undefined"){runDependencyWatcher=setInterval(function(){if(ABORT){clearInterval(runDependencyWatcher);runDependencyWatcher=null;return}var shown=false;for(var dep in runDependencyTracking){if(!shown){shown=true;err("still waiting on run dependencies:");}err("dependency: "+dep);}if(shown){err("(end of list)");}},1e4);}}else{err("warning: run dependency added without ID");}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(id){assert(runDependencyTracking[id]);delete runDependencyTracking[id];}else{err("warning: run dependency removed without ID");}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}if(ENVIRONMENT_IS_PTHREAD)console.error("Pthread aborting at "+(new Error).stack);what+="";out(what);err(what);ABORT=true;var output="abort("+what+") at "+stackTrace();what=output;throw new WebAssembly.RuntimeError(what)}var FS={error:function(){abort("Filesystem support (FS) was not included. The problem is that you are using files from JS, but files were not used from C/C++, so filesystem support was not auto-included. You can force-include filesystem support with -s FORCE_FILESYSTEM=1");},init:function(){FS.error();},createDataFile:function(){FS.error();},createPreloadedFile:function(){FS.error();},createLazyFile:function(){FS.error();},open:function(){FS.error();},mkdev:function(){FS.error();},registerDevice:function(){FS.error();},analyzePath:function(){FS.error();},loadFilesFromDB:function(){FS.error();},ErrnoError:function ErrnoError(){FS.error();}};Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm-threaded-simd.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmModule=module;if(!ENVIRONMENT_IS_PTHREAD){var numWorkersToLoad=PThread.unusedWorkers.length;PThread.unusedWorkers.forEach(function(w){PThread.loadWasmModuleToWorker(w,function(){if(!--numWorkersToLoad)removeRunDependency("wasm-instantiate");});});}}if(!ENVIRONMENT_IS_PTHREAD){addRunDependency("wasm-instantiate");}var trueModule=Module;function receiveInstantiatedSource(output){assert(Module===trueModule,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?");trueModule=null;receiveInstance(output["instance"],output["module"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}var ASM_CONSTS={};function initPthreadsJS(){PThread.initRuntime();}if(!ENVIRONMENT_IS_PTHREAD)__ATINIT__.push({func:function(){___wasm_call_ctors();}});function demangle(func){warnOnce("warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling");return func}function demangleAll(text){var regex=/\b_Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}var __pthread_ptr=0;var __pthread_is_main_runtime_thread=0;var __pthread_is_main_browser_thread=0;function __register_pthread_ptr(pthreadPtr,isMainBrowserThread,isMainRuntimeThread){pthreadPtr=pthreadPtr|0;isMainBrowserThread=isMainBrowserThread|0;isMainRuntimeThread=isMainRuntimeThread|0;__pthread_ptr=pthreadPtr;__pthread_is_main_browser_thread=isMainBrowserThread;__pthread_is_main_runtime_thread=isMainRuntimeThread;}Module["__register_pthread_ptr"]=__register_pthread_ptr;var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var __main_thread_futex_wait_address=13392;function _emscripten_futex_wake(addr,count){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0||count<0)return -28;if(count==0)return 0;if(count>=2147483647)count=Infinity;var mainThreadWaitAddress=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);var mainThreadWoken=0;if(mainThreadWaitAddress==addr){var loadedAddr=Atomics.compareExchange(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,mainThreadWaitAddress,0);if(loadedAddr==mainThreadWaitAddress){--count;mainThreadWoken=1;if(count<=0)return 1}}var ret=Atomics.notify(GROWABLE_HEAP_I32(),addr>>2,count);if(ret>=0)return ret+mainThreadWoken;throw "Atomics.notify returned an unexpected value "+ret}Module["_emscripten_futex_wake"]=_emscripten_futex_wake;function __kill_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _kill_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _kill_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];pthread.worker.terminate();PThread.freeThreadData(pthread);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(pthread.worker),1);pthread.worker.pthread=undefined;}function __cancel_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cancel_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cancel_thread!";var pthread=PThread.pthreads[pthread_ptr];pthread.worker.postMessage({"cmd":"cancel"});}function __cleanup_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cleanup_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cleanup_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];if(pthread){var worker=pthread.worker;PThread.returnWorkerToPool(worker);}}var PThread={MAIN_THREAD_ID:1,mainThreadInfo:{schedPolicy:0,schedPrio:0},unusedWorkers:[],runningWorkers:[],initRuntime:function(){__register_pthread_ptr(PThread.mainThreadBlock,!ENVIRONMENT_IS_WORKER,1);_emscripten_register_main_browser_thread_id(PThread.mainThreadBlock);},initMainThreadBlock:function(){assert(!ENVIRONMENT_IS_PTHREAD);var pthreadPoolSize=8;for(var i=0;i>2]=PThread.mainThreadBlock;var headPtr=PThread.mainThreadBlock+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var tlsMemory=12880;for(var i=0;i<128;++i)GROWABLE_HEAP_U32()[tlsMemory/4+i]=0;Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+104>>2,tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+40>>2,PThread.mainThreadBlock);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+44>>2,42);},initWorker:function(){},pthreads:{},exitHandlers:null,setThreadStatus:function(){},runExitHandlers:function(){if(PThread.exitHandlers!==null){while(PThread.exitHandlers.length>0){PThread.exitHandlers.pop()();}PThread.exitHandlers=null;}if(ENVIRONMENT_IS_PTHREAD&&threadInfoStruct)___pthread_tsd_run_dtors();},threadExit:function(exitCode){var tb=_pthread_self();if(tb){err("Pthread 0x"+tb.toString(16)+" exited.");Atomics.store(GROWABLE_HEAP_U32(),tb+4>>2,exitCode);Atomics.store(GROWABLE_HEAP_U32(),tb+0>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+60>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+64>>2,0);PThread.runExitHandlers();_emscripten_futex_wake(tb+0,2147483647);__register_pthread_ptr(0,0,0);threadInfoStruct=0;if(ENVIRONMENT_IS_PTHREAD){postMessage({"cmd":"exit"});}}},threadCancel:function(){PThread.runExitHandlers();Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+4>>2,-1);Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+0>>2,1);_emscripten_futex_wake(threadInfoStruct+0,2147483647);threadInfoStruct=selfThreadId=0;__register_pthread_ptr(0,0,0);postMessage({"cmd":"cancelDone"});},terminateAllThreads:function(){for(var t in PThread.pthreads){var pthread=PThread.pthreads[t];if(pthread&&pthread.worker){PThread.returnWorkerToPool(pthread.worker);}}PThread.pthreads={};for(var i=0;i>2];GROWABLE_HEAP_I32()[pthread.threadInfoStruct+104>>2]=0;_free(tlsMemory);_free(pthread.threadInfoStruct);}pthread.threadInfoStruct=0;if(pthread.allocatedOwnStack&&pthread.stackBase)_free(pthread.stackBase);pthread.stackBase=0;if(pthread.worker)pthread.worker.pthread=null;},returnWorkerToPool:function(worker){delete PThread.pthreads[worker.pthread.thread];PThread.unusedWorkers.push(worker);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);PThread.freeThreadData(worker.pthread);worker.pthread=undefined;},receiveObjectTransfer:function(data){},loadWasmModuleToWorker:function(worker,onFinishedLoading){worker.onmessage=function(e){var d=e["data"];var cmd=d["cmd"];if(worker.pthread)PThread.currentProxiedOperationCallerThread=worker.pthread.threadInfoStruct;if(d["targetThread"]&&d["targetThread"]!=_pthread_self()){var thread=PThread.pthreads[d.targetThread];if(thread){thread.worker.postMessage(e.data,d["transferList"]);}else{console.error('Internal error! Worker sent a message "'+cmd+'" to target pthread '+d["targetThread"]+", but that thread no longer exists!");}PThread.currentProxiedOperationCallerThread=undefined;return}if(cmd==="processQueuedMainThreadWork"){_emscripten_main_thread_process_queued_calls();}else if(cmd==="spawnThread"){__spawn_thread(e.data);}else if(cmd==="cleanupThread"){__cleanup_thread(d["thread"]);}else if(cmd==="killThread"){__kill_thread(d["thread"]);}else if(cmd==="cancelThread"){__cancel_thread(d["thread"]);}else if(cmd==="loaded"){worker.loaded=true;if(onFinishedLoading)onFinishedLoading(worker);if(worker.runPthread){worker.runPthread();delete worker.runPthread;}}else if(cmd==="print"){out("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="printErr"){err("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="alert"){alert("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="exit"){var detached=worker.pthread&&Atomics.load(GROWABLE_HEAP_U32(),worker.pthread.thread+68>>2);if(detached){PThread.returnWorkerToPool(worker);}}else if(cmd==="cancelDone"){PThread.returnWorkerToPool(worker);}else if(cmd==="objectTransfer"){PThread.receiveObjectTransfer(e.data);}else if(e.data.target==="setimmediate"){worker.postMessage(e.data);}else{err("worker sent an unknown command "+cmd);}PThread.currentProxiedOperationCallerThread=undefined;};worker.onerror=function(e){err("pthread sent an error! "+e.filename+":"+e.lineno+": "+e.message);};if(ENVIRONMENT_IS_NODE){worker.on("message",function(data){worker.onmessage({data:data});});worker.on("error",function(data){worker.onerror(data);});worker.on("exit",function(data){console.log("worker exited - TODO: update the worker queue?");});}assert(wasmMemory instanceof WebAssembly.Memory,"WebAssembly memory should have been loaded by now!");assert(wasmModule instanceof WebAssembly.Module,"WebAssembly Module should have been loaded by now!");worker.postMessage({"cmd":"load","urlOrBlob":Module["mainScriptUrlOrBlob"]||_scriptDir,"wasmMemory":wasmMemory,"wasmModule":wasmModule,"DYNAMIC_BASE":DYNAMIC_BASE,"DYNAMICTOP_PTR":DYNAMICTOP_PTR});},allocateUnusedWorker:function(){var pthreadMainJs=locateFile("tfjs-backend-wasm-threaded-simd.worker.js");PThread.unusedWorkers.push(new Worker(pthreadMainJs));},getNewWorker:function(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]);}if(PThread.unusedWorkers.length>0)return PThread.unusedWorkers.pop();else return null},busySpinWait:function(msecs){var t=performance.now()+msecs;while(performance.now()>2]=value;return value}function _atexit(func,arg){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(1,1,func,arg);warnOnce("atexit() called, but EXIT_RUNTIME is not set, so atexits() will not be called. set EXIT_RUNTIME to 1 (see the FAQ)");}function ___handle_stack_overflow(){abort("stack overflow");}function __emscripten_notify_thread_queue(targetThreadId,mainThreadId){if(targetThreadId==mainThreadId){postMessage({"cmd":"processQueuedMainThreadWork"});}else if(ENVIRONMENT_IS_PTHREAD){postMessage({"targetThread":targetThreadId,"cmd":"processThreadQueue"});}else{var pthread=PThread.pthreads[targetThreadId];var worker=pthread&&pthread.worker;if(!worker){err("Cannot send message to thread with ID "+targetThreadId+", unknown thread ID!");return}worker.postMessage({"cmd":"processThreadQueue"});}return 1}function _abort(){abort();}function _emscripten_conditional_set_current_thread_status(expectedStatus,newStatus){}function _emscripten_futex_wait(addr,val,timeout){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0)return -28;if(ENVIRONMENT_IS_WORKER){var ret=Atomics.wait(GROWABLE_HEAP_I32(),addr>>2,val,timeout);if(ret==="timed-out")return -73;if(ret==="not-equal")return -6;if(ret==="ok")return 0;throw "Atomics.wait returned an unexpected value "+ret}else{var loadedVal=Atomics.load(GROWABLE_HEAP_I32(),addr>>2);if(val!=loadedVal)return -6;var tNow=performance.now();var tEnd=tNow+timeout;Atomics.store(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,addr);var ourWaitAddress=addr;while(addr==ourWaitAddress){tNow=performance.now();if(tNow>tEnd){return -73}_emscripten_main_thread_process_queued_calls();addr=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);}return 0}}function _emscripten_is_main_browser_thread(){return __pthread_is_main_browser_thread|0}function _emscripten_is_main_runtime_thread(){return __pthread_is_main_runtime_thread|0}function _emscripten_memcpy_big(dest,src,num){GROWABLE_HEAP_U8().copyWithin(dest,src,src+num);}function _emscripten_num_logical_cores(){return navigator["hardwareConcurrency"]}function _emscripten_proxy_to_main_thread_js(index,sync){var numCallArgs=arguments.length-2;if(numCallArgs>20-1)throw "emscripten_proxy_to_main_thread_js: Too many arguments "+numCallArgs+" to proxied function idx="+index+", maximum supported is "+(20-1)+"!";var stack=stackSave();var args=stackAlloc(numCallArgs*8);var b=args>>3;for(var i=0;i>3]);buf+=8;}else if(ch===105){buf=buf+3&~3;args.push(GROWABLE_HEAP_I32()[buf>>2]);buf+=4;}else abort("unexpected char in asm const signature "+ch);}return args}function _emscripten_receive_on_main_thread_js(index,numCallArgs,args){_emscripten_receive_on_main_thread_js_callArgs.length=numCallArgs;var b=args>>3;for(var i=0;i>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){console.error("emscripten_realloc_buffer: Attempted to grow heap from "+buffer.byteLength+" bytes to "+size+" bytes, but got error: "+e);}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();if(requestedSize<=oldSize){return false}var PAGE_MULTIPLE=65536;var maxHeapSize=1073741824;if(requestedSize>maxHeapSize){err("Cannot enlarge memory, asked to go up to "+requestedSize+" bytes, but the limit is "+maxHeapSize+" bytes!");return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}err("Failed to grow the heap from "+oldSize+" bytes to "+newSize+" bytes, not enough memory!");return false}var JSEvents={keyEvent:0,mouseEvent:0,wheelEvent:0,uiEvent:0,focusEvent:0,deviceOrientationEvent:0,deviceMotionEvent:0,fullscreenChangeEvent:0,pointerlockChangeEvent:0,visibilityChangeEvent:0,touchEvent:0,previousFullscreenElement:null,previousScreenX:null,previousScreenY:null,removeEventListenersRegistered:false,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i);}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[];},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){JSEvents.removeEventListenersRegistered=true;}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence>2]=eventTypeId;GROWABLE_HEAP_I32()[varargs+4>>2]=eventData;GROWABLE_HEAP_I32()[varargs+8>>2]=userData;_emscripten_async_queue_on_thread_(targetThread,637534208,eventHandlerFunc,eventData,varargs);stackRestore(stackTop);},getTargetThreadForEventCallback:function(targetThread){switch(targetThread){case 1:return 0;case 2:return PThread.currentProxiedOperationCallerThread;default:return targetThread}},getNodeNameForTarget:function(target){if(!target)return "";if(target==window)return "#window";if(target==screen)return "#screen";return target&&target.nodeName?target.nodeName:""},fullscreenEnabled:function(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+1;var cString=_malloc(length);stringToUTF8(jsString,cString,length);return cString}function _emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height){var stackTop=stackSave();var varargs=stackAlloc(12);var targetCanvasPtr=0;if(targetCanvas){targetCanvasPtr=stringToNewUTF8(targetCanvas);}GROWABLE_HEAP_I32()[varargs>>2]=targetCanvasPtr;GROWABLE_HEAP_I32()[varargs+4>>2]=width;GROWABLE_HEAP_I32()[varargs+8>>2]=height;_emscripten_async_queue_on_thread_(targetThread,657457152,0,targetCanvasPtr,varargs);stackRestore(stackTop);}function _emscripten_set_offscreencanvas_size_on_target_thread(targetThread,targetCanvas,width,height){targetCanvas=targetCanvas?UTF8ToString(targetCanvas):"";_emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height);}function __maybeCStringToJsString(cString){return cString>2?UTF8ToString(cString):cString}var specialHTMLTargets=[0,typeof document!=="undefined"?document:0,typeof window!=="undefined"?window:0];function __findEventTarget(target){target=__maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!=="undefined"?document.querySelector(target):undefined);return domElement}function __findCanvasEventTarget(target){return __findEventTarget(target)}function _emscripten_set_canvas_element_size_calling_thread(target,width,height){var canvas=__findCanvasEventTarget(target);if(!canvas)return -4;if(canvas.canvasSharedPtr){GROWABLE_HEAP_I32()[canvas.canvasSharedPtr>>2]=width;GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+4>>2]=height;}if(canvas.offscreenCanvas||!canvas.controlTransferredOffscreen){if(canvas.offscreenCanvas)canvas=canvas.offscreenCanvas;var autoResizeViewport=false;if(canvas.GLctxObject&&canvas.GLctxObject.GLctx){var prevViewport=canvas.GLctxObject.GLctx.getParameter(2978);autoResizeViewport=prevViewport[0]===0&&prevViewport[1]===0&&prevViewport[2]===canvas.width&&prevViewport[3]===canvas.height;}canvas.width=width;canvas.height=height;if(autoResizeViewport){canvas.GLctxObject.GLctx.viewport(0,0,width,height);}}else if(canvas.canvasSharedPtr){var targetThread=GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+8>>2];_emscripten_set_offscreencanvas_size_on_target_thread(targetThread,target,width,height);return 1}else{return -4}return 0}function _emscripten_set_canvas_element_size_main_thread(target,width,height){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(2,1,target,width,height);return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}function _emscripten_set_canvas_element_size(target,width,height){var canvas=__findCanvasEventTarget(target);if(canvas){return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}else{return _emscripten_set_canvas_element_size_main_thread(target,width,height)}}function _emscripten_set_current_thread_status(newStatus){}function _emscripten_set_thread_name(threadId,name){}function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=function(index,divisor){ext["vertexAttribDivisorANGLE"](index,divisor);};ctx["drawArraysInstanced"]=function(mode,first,count,primcount){ext["drawArraysInstancedANGLE"](mode,first,count,primcount);};ctx["drawElementsInstanced"]=function(mode,count,type,indices,primcount){ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);};return 1}}function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=function(){return ext["createVertexArrayOES"]()};ctx["deleteVertexArray"]=function(vao){ext["deleteVertexArrayOES"](vao);};ctx["bindVertexArray"]=function(vao){ext["bindVertexArrayOES"](vao);};ctx["isVertexArray"]=function(vao){return ext["isVertexArrayOES"](vao)};return 1}}function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=function(n,bufs){ext["drawBuffersWEBGL"](n,bufs);};return 1}}var GL={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:{},currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],programInfos:{},stringCache:{},unpackAlignment:4,init:function(){var miniTempFloatBuffer=new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);for(var i=0;i>2]:-1;source+=UTF8ToString(GROWABLE_HEAP_I32()[string+i*4>>2],len<0?undefined:len);}return source},createContext:function(canvas,webGLContextAttributes){var ctx=canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=_malloc(8);GROWABLE_HEAP_I32()[handle+4>>2]=_pthread_self();var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context);}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return !(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;_free(GL.contexts[contextHandle].handle);GL.contexts[contextHandle]=null;},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;__webgl_enable_ANGLE_instanced_arrays(GLctx);__webgl_enable_OES_vertex_array_object(GLctx);__webgl_enable_WEBGL_draw_buffers(GLctx);GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query");var automaticallyEnabledExtensions=["OES_texture_float","OES_texture_half_float","OES_standard_derivatives","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBGL_depth_texture","OES_element_index_uint","EXT_texture_filter_anisotropic","EXT_frag_depth","WEBGL_draw_buffers","ANGLE_instanced_arrays","OES_texture_float_linear","OES_texture_half_float_linear","EXT_blend_minmax","EXT_shader_texture_lod","EXT_texture_norm16","WEBGL_compressed_texture_pvrtc","EXT_color_buffer_half_float","WEBGL_color_buffer_float","EXT_sRGB","WEBGL_compressed_texture_etc1","EXT_disjoint_timer_query","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_astc","EXT_color_buffer_float","WEBGL_compressed_texture_s3tc_srgb","EXT_disjoint_timer_query_webgl2","WEBKIT_WEBGL_compressed_texture_pvrtc"];var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext);}});},populateUniformTable:function(program){var p=GL.programs[program];var ptable=GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,35718);for(var i=0;i>2;contextAttributes["alpha"]=!!GROWABLE_HEAP_I32()[a+(0>>2)];contextAttributes["depth"]=!!GROWABLE_HEAP_I32()[a+(4>>2)];contextAttributes["stencil"]=!!GROWABLE_HEAP_I32()[a+(8>>2)];contextAttributes["antialias"]=!!GROWABLE_HEAP_I32()[a+(12>>2)];contextAttributes["premultipliedAlpha"]=!!GROWABLE_HEAP_I32()[a+(16>>2)];contextAttributes["preserveDrawingBuffer"]=!!GROWABLE_HEAP_I32()[a+(20>>2)];var powerPreference=GROWABLE_HEAP_I32()[a+(24>>2)];contextAttributes["powerPreference"]=__emscripten_webgl_power_preferences[powerPreference];contextAttributes["failIfMajorPerformanceCaveat"]=!!GROWABLE_HEAP_I32()[a+(28>>2)];contextAttributes.majorVersion=GROWABLE_HEAP_I32()[a+(32>>2)];contextAttributes.minorVersion=GROWABLE_HEAP_I32()[a+(36>>2)];contextAttributes.enableExtensionsByDefault=GROWABLE_HEAP_I32()[a+(40>>2)];contextAttributes.explicitSwapControl=GROWABLE_HEAP_I32()[a+(44>>2)];contextAttributes.proxyContextToMainThread=GROWABLE_HEAP_I32()[a+(48>>2)];contextAttributes.renderViaOffscreenBackBuffer=GROWABLE_HEAP_I32()[a+(52>>2)];var canvas=__findCanvasEventTarget(target);if(!canvas){return -4}if(contextAttributes.explicitSwapControl){return -1}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}function _emscripten_webgl_create_context(a0,a1){return _emscripten_webgl_do_create_context(a0,a1)}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];assert(buffer);if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){assert(SYSCALLS.varargs!=undefined);SYSCALLS.varargs+=4;var ret=GROWABLE_HEAP_I32()[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){if(low>=0)assert(high===0);else assert(high===-1);return low}};function _fd_close(fd){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(3,1,fd);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(4,1,fd,offset_low,offset_high,whence,newOffset);abort("it should not be possible to operate on streams when !SYSCALLS_REQUIRE_FILESYSTEM");}function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(5,1,fd,iov,iovcnt,pnum);var num=0;for(var i=0;i>2];var len=GROWABLE_HEAP_I32()[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _pthread_cleanup_pop(execute){var routine=PThread.exitHandlers.pop();if(execute)routine();}function _pthread_cleanup_push(routine,arg){if(PThread.exitHandlers===null){PThread.exitHandlers=[];}PThread.exitHandlers.push(function(){dynCall_vi(routine,arg);});}function __spawn_thread(threadParams){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _spawn_thread() can only ever be called from main application thread!";var worker=PThread.getNewWorker();if(worker.pthread!==undefined)throw "Internal error!";if(!threadParams.pthread_ptr)throw "Internal error, no pthread ptr!";PThread.runningWorkers.push(worker);var tlsMemory=_malloc(128*4);for(var i=0;i<128;++i){GROWABLE_HEAP_I32()[tlsMemory+i*4>>2]=0;}var stackHigh=threadParams.stackBase+threadParams.stackSize;var pthread=PThread.pthreads[threadParams.pthread_ptr]={worker:worker,stackBase:threadParams.stackBase,stackSize:threadParams.stackSize,allocatedOwnStack:threadParams.allocatedOwnStack,thread:threadParams.pthread_ptr,threadInfoStruct:threadParams.pthread_ptr};var tis=pthread.threadInfoStruct>>2;Atomics.store(GROWABLE_HEAP_U32(),tis+(0>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(4>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(8>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(68>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(104>>2),tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),tis+(48>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(40>>2),pthread.threadInfoStruct);Atomics.store(GROWABLE_HEAP_U32(),tis+(44>>2),42);Atomics.store(GROWABLE_HEAP_U32(),tis+(108>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(84>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(80>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+8>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+12>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+20>>2),threadParams.schedPolicy);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+24>>2),threadParams.schedPrio);var global_libc=_emscripten_get_global_libc();var global_locale=global_libc+40;Atomics.store(GROWABLE_HEAP_U32(),tis+(176>>2),global_locale);worker.pthread=pthread;var msg={"cmd":"run","start_routine":threadParams.startRoutine,"arg":threadParams.arg,"threadInfoStruct":threadParams.pthread_ptr,"selfThreadId":threadParams.pthread_ptr,"parentThreadId":threadParams.parent_pthread_ptr,"stackBase":threadParams.stackBase,"stackSize":threadParams.stackSize};worker.runPthread=function(){msg.time=performance.now();worker.postMessage(msg,threadParams.transferList);};if(worker.loaded){worker.runPthread();delete worker.runPthread;}}function _pthread_getschedparam(thread,policy,schedparam){if(!policy&&!schedparam)return ERRNO_CODES.EINVAL;if(!thread){err("pthread_getschedparam called with a null thread pointer!");return ERRNO_CODES.ESRCH}var self=GROWABLE_HEAP_I32()[thread+12>>2];if(self!==thread){err("pthread_getschedparam attempted on thread "+thread+", which does not point to a valid thread, or does not exist anymore!");return ERRNO_CODES.ESRCH}var schedPolicy=Atomics.load(GROWABLE_HEAP_U32(),thread+108+20>>2);var schedPrio=Atomics.load(GROWABLE_HEAP_U32(),thread+108+24>>2);if(policy)GROWABLE_HEAP_I32()[policy>>2]=schedPolicy;if(schedparam)GROWABLE_HEAP_I32()[schedparam>>2]=schedPrio;return 0}function _pthread_self(){return __pthread_ptr|0}Module["_pthread_self"]=_pthread_self;function _pthread_create(pthread_ptr,attr,start_routine,arg){if(typeof SharedArrayBuffer==="undefined"){err("Current environment does not support SharedArrayBuffer, pthreads are not available!");return 6}if(!pthread_ptr){err("pthread_create called with a null thread pointer!");return 28}var transferList=[];var error=0;if(ENVIRONMENT_IS_PTHREAD&&(transferList.length===0||error)){return _emscripten_sync_run_in_main_thread_4(687865856,pthread_ptr,attr,start_routine,arg)}var stackSize=0;var stackBase=0;var detached=0;var schedPolicy=0;var schedPrio=0;if(attr){stackSize=GROWABLE_HEAP_I32()[attr>>2];stackSize+=81920;stackBase=GROWABLE_HEAP_I32()[attr+8>>2];detached=GROWABLE_HEAP_I32()[attr+12>>2]!==0;var inheritSched=GROWABLE_HEAP_I32()[attr+16>>2]===0;if(inheritSched){var prevSchedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];var prevSchedPrio=GROWABLE_HEAP_I32()[attr+24>>2];var parentThreadPtr=PThread.currentProxiedOperationCallerThread?PThread.currentProxiedOperationCallerThread:_pthread_self();_pthread_getschedparam(parentThreadPtr,attr+20,attr+24);schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];GROWABLE_HEAP_I32()[attr+20>>2]=prevSchedPolicy;GROWABLE_HEAP_I32()[attr+24>>2]=prevSchedPrio;}else{schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];}}else{stackSize=2097152;}var allocatedOwnStack=stackBase==0;if(allocatedOwnStack){stackBase=_memalign(16,stackSize);}else{stackBase-=stackSize;assert(stackBase>0);}var threadInfoStruct=_malloc(232);for(var i=0;i<232>>2;++i)GROWABLE_HEAP_U32()[(threadInfoStruct>>2)+i]=0;GROWABLE_HEAP_I32()[pthread_ptr>>2]=threadInfoStruct;GROWABLE_HEAP_I32()[threadInfoStruct+12>>2]=threadInfoStruct;var headPtr=threadInfoStruct+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var threadParams={stackBase:stackBase,stackSize:stackSize,allocatedOwnStack:allocatedOwnStack,schedPolicy:schedPolicy,schedPrio:schedPrio,detached:detached,startRoutine:start_routine,pthread_ptr:threadInfoStruct,parent_pthread_ptr:_pthread_self(),arg:arg,transferList:transferList};if(ENVIRONMENT_IS_PTHREAD){threadParams.cmd="spawnThread";postMessage(threadParams,transferList);}else{__spawn_thread(threadParams);}return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}function _sysconf(name){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(6,1,name);switch(name){case 30:return 16384;case 85:var maxHeapSize=1073741824;return maxHeapSize/16384;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:case 79:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return -1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}setErrNo(28);return -1}if(!ENVIRONMENT_IS_PTHREAD)PThread.initMainThreadBlock();else PThread.initWorker();var GLctx;GL.init();var proxiedFunctionTable=[null,_atexit,_emscripten_set_canvas_element_size_main_thread,_fd_close,_fd_seek,_fd_write,_sysconf];var asmLibraryArg={"__assert_fail":___assert_fail,"__call_main":___call_main,"__handle_stack_overflow":___handle_stack_overflow,"_emscripten_notify_thread_queue":__emscripten_notify_thread_queue,"abort":_abort,"emscripten_conditional_set_current_thread_status":_emscripten_conditional_set_current_thread_status,"emscripten_futex_wait":_emscripten_futex_wait,"emscripten_futex_wake":_emscripten_futex_wake,"emscripten_get_now":_emscripten_get_now,"emscripten_is_main_browser_thread":_emscripten_is_main_browser_thread,"emscripten_is_main_runtime_thread":_emscripten_is_main_runtime_thread,"emscripten_memcpy_big":_emscripten_memcpy_big,"emscripten_num_logical_cores":_emscripten_num_logical_cores,"emscripten_receive_on_main_thread_js":_emscripten_receive_on_main_thread_js,"emscripten_resize_heap":_emscripten_resize_heap,"emscripten_set_canvas_element_size":_emscripten_set_canvas_element_size,"emscripten_set_current_thread_status":_emscripten_set_current_thread_status,"emscripten_set_thread_name":_emscripten_set_thread_name,"emscripten_webgl_create_context":_emscripten_webgl_create_context,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"initPthreadsJS":initPthreadsJS,"memory":wasmMemory||Module["wasmMemory"],"pthread_cleanup_pop":_pthread_cleanup_pop,"pthread_cleanup_push":_pthread_cleanup_push,"pthread_create":_pthread_create,"pthread_self":_pthread_self,"roundf":_roundf,"sysconf":_sysconf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__wasm_call_ctors"].apply(null,arguments)};var _init=Module["_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["init"].apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["register_tensor"].apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose_data"].apply(null,arguments)};var _dispose=Module["_dispose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dispose"].apply(null,arguments)};var _Abs=Module["_Abs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Abs"].apply(null,arguments)};var _Add=Module["_Add"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Add"].apply(null,arguments)};var _AddN=Module["_AddN"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AddN"].apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ArgMax"].apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["AvgPool"].apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["BatchMatMul"].apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ClipByValue"].apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2D"].apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Conv2DBackpropInput"].apply(null,arguments)};var _Cos=Module["_Cos"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Cos"].apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["CropAndResize"].apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["DepthwiseConv2dNative"].apply(null,arguments)};var _Div=Module["_Div"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Div"].apply(null,arguments)};var _Equal=Module["_Equal"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Equal"].apply(null,arguments)};var _Exp=Module["_Exp"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Exp"].apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FloorDiv"].apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedBatchNorm"].apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedConv2D"].apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["FusedDepthwiseConv2D"].apply(null,arguments)};var _Gather=Module["_Gather"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Gather"].apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GatherNd"].apply(null,arguments)};var _Greater=Module["_Greater"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Greater"].apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["GreaterEqual"].apply(null,arguments)};var _Less=Module["_Less"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Less"].apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LessEqual"].apply(null,arguments)};var _Log=Module["_Log"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Log"].apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["LogicalAnd"].apply(null,arguments)};var _Max=Module["_Max"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Max"].apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["MaxPool"].apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Maximum"].apply(null,arguments)};var _Min=Module["_Min"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Min"].apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Minimum"].apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Multiply"].apply(null,arguments)};var _Negate=Module["_Negate"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Negate"].apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV3"].apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV4"].apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NonMaxSuppressionV5"].apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["NotEqual"].apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["OneHot"].apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["PadV2"].apply(null,arguments)};var _Pow=Module["_Pow"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Pow"].apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Prelu"].apply(null,arguments)};var _Relu=Module["_Relu"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu"].apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Relu6"].apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ResizeBilinear"].apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Reverse"].apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["RotateWithOffset"].apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Rsqrt"].apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["ScatterNd"].apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["SelectV2"].apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sigmoid"].apply(null,arguments)};var _Sin=Module["_Sin"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sin"].apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Softmax"].apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sqrt"].apply(null,arguments)};var _Square=Module["_Square"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Square"].apply(null,arguments)};var _Sub=Module["_Sub"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sub"].apply(null,arguments)};var _Sum=Module["_Sum"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Sum"].apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tanh"].apply(null,arguments)};var _Tile=Module["_Tile"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Tile"].apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["Transpose"].apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["_FusedMatMul"].apply(null,arguments)};var _malloc=Module["_malloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["malloc"].apply(null,arguments)};var _free=Module["_free"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["free"].apply(null,arguments)};var ___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__em_js__initPthreadsJS"].apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__errno_location"].apply(null,arguments)};var _emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_get_global_libc"].apply(null,arguments)};var _memalign=Module["_memalign"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["memalign"].apply(null,arguments)};var ___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__pthread_tsd_run_dtors"].apply(null,arguments)};var _emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_current_thread_process_queued_calls"].apply(null,arguments)};var _emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_register_main_browser_thread_id"].apply(null,arguments)};var _emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_main_browser_thread_id"].apply(null,arguments)};var _emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_0"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_1"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_2"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_xprintf_varargs"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_3"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_4"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_5"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_6"].apply(null,arguments)};var _emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_sync_run_in_main_thread_7"].apply(null,arguments)};var _emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_run_in_main_runtime_thread_js"].apply(null,arguments)};var _emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_async_queue_on_thread_"].apply(null,arguments)};var _emscripten_tls_init=Module["_emscripten_tls_init"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["emscripten_tls_init"].apply(null,arguments)};var ___set_stack_limit=Module["___set_stack_limit"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["__set_stack_limit"].apply(null,arguments)};var stackSave=Module["stackSave"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackSave"].apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackAlloc"].apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["stackRestore"].apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_vi"].apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_v"].apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){assert(runtimeInitialized,"you need to wait for the runtime to be ready (e.g. wait for main() to be called)");assert(!runtimeExited,"the runtime was exited (use NO_EXIT_RUNTIME to keep it alive after main() exits)");return Module["asm"]["dynCall_ii"].apply(null,arguments)};Module["asm"]=asm;if(!Object.getOwnPropertyDescriptor(Module,"intArrayFromString"))Module["intArrayFromString"]=function(){abort("'intArrayFromString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"intArrayToString"))Module["intArrayToString"]=function(){abort("'intArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ccall"))Module["ccall"]=function(){abort("'ccall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["cwrap"]=cwrap;if(!Object.getOwnPropertyDescriptor(Module,"setValue"))Module["setValue"]=function(){abort("'setValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getValue"))Module["getValue"]=function(){abort("'getValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocate"))Module["allocate"]=function(){abort("'allocate' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getMemory"))Module["getMemory"]=function(){abort("'getMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ArrayToString"))Module["UTF8ArrayToString"]=function(){abort("'UTF8ArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF8ToString"))Module["UTF8ToString"]=function(){abort("'UTF8ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8Array"))Module["stringToUTF8Array"]=function(){abort("'stringToUTF8Array' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF8"))Module["stringToUTF8"]=function(){abort("'stringToUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF8"))Module["lengthBytesUTF8"]=function(){abort("'lengthBytesUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreRun"))Module["addOnPreRun"]=function(){abort("'addOnPreRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnInit"))Module["addOnInit"]=function(){abort("'addOnInit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPreMain"))Module["addOnPreMain"]=function(){abort("'addOnPreMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnExit"))Module["addOnExit"]=function(){abort("'addOnExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addOnPostRun"))Module["addOnPostRun"]=function(){abort("'addOnPostRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeStringToMemory"))Module["writeStringToMemory"]=function(){abort("'writeStringToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeArrayToMemory"))Module["writeArrayToMemory"]=function(){abort("'writeArrayToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeAsciiToMemory"))Module["writeAsciiToMemory"]=function(){abort("'writeAsciiToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addRunDependency"))Module["addRunDependency"]=function(){abort("'addRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"removeRunDependency"))Module["removeRunDependency"]=function(){abort("'removeRunDependency' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createFolder"))Module["FS_createFolder"]=function(){abort("'FS_createFolder' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPath"))Module["FS_createPath"]=function(){abort("'FS_createPath' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDataFile"))Module["FS_createDataFile"]=function(){abort("'FS_createDataFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createPreloadedFile"))Module["FS_createPreloadedFile"]=function(){abort("'FS_createPreloadedFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLazyFile"))Module["FS_createLazyFile"]=function(){abort("'FS_createLazyFile' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createLink"))Module["FS_createLink"]=function(){abort("'FS_createLink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_createDevice"))Module["FS_createDevice"]=function(){abort("'FS_createDevice' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"FS_unlink"))Module["FS_unlink"]=function(){abort("'FS_unlink' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ). Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you");};if(!Object.getOwnPropertyDescriptor(Module,"dynamicAlloc"))Module["dynamicAlloc"]=function(){abort("'dynamicAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadDynamicLibrary"))Module["loadDynamicLibrary"]=function(){abort("'loadDynamicLibrary' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"loadWebAssemblyModule"))Module["loadWebAssemblyModule"]=function(){abort("'loadWebAssemblyModule' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getLEB"))Module["getLEB"]=function(){abort("'getLEB' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFunctionTables"))Module["getFunctionTables"]=function(){abort("'getFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"alignFunctionTables"))Module["alignFunctionTables"]=function(){abort("'alignFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"registerFunctions"))Module["registerFunctions"]=function(){abort("'registerFunctions' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"addFunction"))Module["addFunction"]=function(){abort("'addFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"removeFunction"))Module["removeFunction"]=function(){abort("'removeFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getFuncWrapper"))Module["getFuncWrapper"]=function(){abort("'getFuncWrapper' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"prettyPrint"))Module["prettyPrint"]=function(){abort("'prettyPrint' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"makeBigInt"))Module["makeBigInt"]=function(){abort("'makeBigInt' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"dynCall"))Module["dynCall"]=function(){abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getCompilerSetting"))Module["getCompilerSetting"]=function(){abort("'getCompilerSetting' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"print"))Module["print"]=function(){abort("'print' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"printErr"))Module["printErr"]=function(){abort("'printErr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getTempRet0"))Module["getTempRet0"]=function(){abort("'getTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setTempRet0"))Module["setTempRet0"]=function(){abort("'setTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"callMain"))Module["callMain"]=function(){abort("'callMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"abort"))Module["abort"]=function(){abort("'abort' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToNewUTF8"))Module["stringToNewUTF8"]=function(){abort("'stringToNewUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscripten_realloc_buffer"))Module["emscripten_realloc_buffer"]=function(){abort("'emscripten_realloc_buffer' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ENV"))Module["ENV"]=function(){abort("'ENV' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setjmpId"))Module["setjmpId"]=function(){abort("'setjmpId' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_CODES"))Module["ERRNO_CODES"]=function(){abort("'ERRNO_CODES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"ERRNO_MESSAGES"))Module["ERRNO_MESSAGES"]=function(){abort("'ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"setErrNo"))Module["setErrNo"]=function(){abort("'setErrNo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"DNS"))Module["DNS"]=function(){abort("'DNS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GAI_ERRNO_MESSAGES"))Module["GAI_ERRNO_MESSAGES"]=function(){abort("'GAI_ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Protocols"))Module["Protocols"]=function(){abort("'Protocols' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Sockets"))Module["Sockets"]=function(){abort("'Sockets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UNWIND_CACHE"))Module["UNWIND_CACHE"]=function(){abort("'UNWIND_CACHE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readAsmConstArgs"))Module["readAsmConstArgs"]=function(){abort("'readAsmConstArgs' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_q"))Module["jstoi_q"]=function(){abort("'jstoi_q' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jstoi_s"))Module["jstoi_s"]=function(){abort("'jstoi_s' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"reallyNegative"))Module["reallyNegative"]=function(){abort("'reallyNegative' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"formatString"))Module["formatString"]=function(){abort("'formatString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH"))Module["PATH"]=function(){abort("'PATH' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"PATH_FS"))Module["PATH_FS"]=function(){abort("'PATH_FS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SYSCALLS"))Module["SYSCALLS"]=function(){abort("'SYSCALLS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMmap2"))Module["syscallMmap2"]=function(){abort("'syscallMmap2' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"syscallMunmap"))Module["syscallMunmap"]=function(){abort("'syscallMunmap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"flush_NO_FILESYSTEM"))Module["flush_NO_FILESYSTEM"]=function(){abort("'flush_NO_FILESYSTEM' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"JSEvents"))Module["JSEvents"]=function(){abort("'JSEvents' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"specialHTMLTargets"))Module["specialHTMLTargets"]=function(){abort("'specialHTMLTargets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangle"))Module["demangle"]=function(){abort("'demangle' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"demangleAll"))Module["demangleAll"]=function(){abort("'demangleAll' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"jsStackTrace"))Module["jsStackTrace"]=function(){abort("'jsStackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackTrace"))Module["stackTrace"]=function(){abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getEnvStrings"))Module["getEnvStrings"]=function(){abort("'getEnvStrings' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64"))Module["writeI53ToI64"]=function(){abort("'writeI53ToI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Clamped"))Module["writeI53ToI64Clamped"]=function(){abort("'writeI53ToI64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToI64Signaling"))Module["writeI53ToI64Signaling"]=function(){abort("'writeI53ToI64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Clamped"))Module["writeI53ToU64Clamped"]=function(){abort("'writeI53ToU64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"writeI53ToU64Signaling"))Module["writeI53ToU64Signaling"]=function(){abort("'writeI53ToU64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromI64"))Module["readI53FromI64"]=function(){abort("'readI53FromI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"readI53FromU64"))Module["readI53FromU64"]=function(){abort("'readI53FromU64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertI32PairToI53"))Module["convertI32PairToI53"]=function(){abort("'convertI32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"convertU32PairToI53"))Module["convertU32PairToI53"]=function(){abort("'convertU32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"Browser"))Module["Browser"]=function(){abort("'Browser' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GL"))Module["GL"]=function(){abort("'GL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGet"))Module["emscriptenWebGLGet"]=function(){abort("'emscriptenWebGLGet' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetTexPixelData"))Module["emscriptenWebGLGetTexPixelData"]=function(){abort("'emscriptenWebGLGetTexPixelData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetUniform"))Module["emscriptenWebGLGetUniform"]=function(){abort("'emscriptenWebGLGetUniform' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"emscriptenWebGLGetVertexAttrib"))Module["emscriptenWebGLGetVertexAttrib"]=function(){abort("'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AL"))Module["AL"]=function(){abort("'AL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_unicode"))Module["SDL_unicode"]=function(){abort("'SDL_unicode' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_ttfContext"))Module["SDL_ttfContext"]=function(){abort("'SDL_ttfContext' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_audio"))Module["SDL_audio"]=function(){abort("'SDL_audio' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL"))Module["SDL"]=function(){abort("'SDL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"SDL_gfx"))Module["SDL_gfx"]=function(){abort("'SDL_gfx' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLUT"))Module["GLUT"]=function(){abort("'GLUT' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"EGL"))Module["EGL"]=function(){abort("'EGL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW_Window"))Module["GLFW_Window"]=function(){abort("'GLFW_Window' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLFW"))Module["GLFW"]=function(){abort("'GLFW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"GLEW"))Module["GLEW"]=function(){abort("'GLEW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"IDBStore"))Module["IDBStore"]=function(){abort("'IDBStore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"runAndAbortIfError"))Module["runAndAbortIfError"]=function(){abort("'runAndAbortIfError' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["PThread"]=PThread;if(!Object.getOwnPropertyDescriptor(Module,"establishStackSpace"))Module["establishStackSpace"]=function(){abort("'establishStackSpace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"getNoExitRuntime"))Module["getNoExitRuntime"]=function(){abort("'getNoExitRuntime' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"resetPrototype"))Module["resetPrototype"]=function(){abort("'resetPrototype' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"warnOnce"))Module["warnOnce"]=function(){abort("'warnOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackSave"))Module["stackSave"]=function(){abort("'stackSave' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackRestore"))Module["stackRestore"]=function(){abort("'stackRestore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stackAlloc"))Module["stackAlloc"]=function(){abort("'stackAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"AsciiToString"))Module["AsciiToString"]=function(){abort("'AsciiToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToAscii"))Module["stringToAscii"]=function(){abort("'stringToAscii' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF16ToString"))Module["UTF16ToString"]=function(){abort("'UTF16ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF16"))Module["stringToUTF16"]=function(){abort("'stringToUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF16"))Module["lengthBytesUTF16"]=function(){abort("'lengthBytesUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"UTF32ToString"))Module["UTF32ToString"]=function(){abort("'UTF32ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"stringToUTF32"))Module["stringToUTF32"]=function(){abort("'stringToUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"lengthBytesUTF32"))Module["lengthBytesUTF32"]=function(){abort("'lengthBytesUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8"))Module["allocateUTF8"]=function(){abort("'allocateUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};if(!Object.getOwnPropertyDescriptor(Module,"allocateUTF8OnStack"))Module["allocateUTF8OnStack"]=function(){abort("'allocateUTF8OnStack' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");};Module["writeStackCookie"]=writeStackCookie;Module["checkStackCookie"]=checkStackCookie;Module["abortStackOverflow"]=abortStackOverflow;Module["PThread"]=PThread;Module["_pthread_self"]=_pthread_self;Module["wasmMemory"]=wasmMemory;Module["ExitStatus"]=ExitStatus;if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NORMAL"))Object.defineProperty(Module,"ALLOC_NORMAL",{configurable:true,get:function(){abort("'ALLOC_NORMAL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_STACK"))Object.defineProperty(Module,"ALLOC_STACK",{configurable:true,get:function(){abort("'ALLOC_STACK' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_DYNAMIC"))Object.defineProperty(Module,"ALLOC_DYNAMIC",{configurable:true,get:function(){abort("'ALLOC_DYNAMIC' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});if(!Object.getOwnPropertyDescriptor(Module,"ALLOC_NONE"))Object.defineProperty(Module,"ALLOC_NONE",{configurable:true,get:function(){abort("'ALLOC_NONE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)");}});var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}writeStackCookie();preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();assert(!Module["_main"],'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]');postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}checkStackCookie();}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}if(!ENVIRONMENT_IS_PTHREAD)noExitRuntime=true;if(!ENVIRONMENT_IS_PTHREAD)run(); + function GROWABLE_HEAP_I8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP8}function GROWABLE_HEAP_U8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU8}function GROWABLE_HEAP_I32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP32}function GROWABLE_HEAP_U32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPF64}var Module=typeof WasmBackendModuleSimd!=="undefined"?WasmBackendModuleSimd:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var ENVIRONMENT_IS_PTHREAD=Module["ENVIRONMENT_IS_PTHREAD"]||false;if(ENVIRONMENT_IS_PTHREAD){buffer=Module["buffer"];DYNAMIC_BASE=Module["DYNAMIC_BASE"];DYNAMICTOP_PTR=Module["DYNAMICTOP_PTR"];}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};var nodeWorkerThreads;try{nodeWorkerThreads=worker_threads;}catch(e){console.error('The "worker_threads" module is not supported in this node.js build - perhaps a newer version is needed?');throw e}Worker=nodeWorkerThreads.Worker;}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}if(ENVIRONMENT_IS_NODE){read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};}else{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}if(ENVIRONMENT_IS_NODE){if(typeof performance==="undefined"){performance=perf_hooks.performance;}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":165,"maximum":165+0,"element":"anyfunc"});var wasmModule;var threadInfoStruct=0;var selfThreadId=0;var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx)){var u0=heap[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heap[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heap[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2;}else{u0=(u0&7)<<18|u1<<12|u2<<6|heap[idx++]&63;}if(u0<65536){str+=String.fromCharCode(u0);}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023);}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4;}return len}function writeArrayToMemory(array,buffer){GROWABLE_HEAP_I8().set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var DYNAMIC_BASE=5256288,DYNAMICTOP_PTR=12480;var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||1073741824;if(ENVIRONMENT_IS_PTHREAD){wasmMemory=Module["wasmMemory"];buffer=Module["buffer"];}else{if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":1073741824/WASM_PAGE_SIZE,"shared":true});if(!(wasmMemory.buffer instanceof SharedArrayBuffer)){err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");if(ENVIRONMENT_IS_NODE){console.log("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)");}throw Error("bad memory")}}}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);if(!ENVIRONMENT_IS_PTHREAD){GROWABLE_HEAP_I32()[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){if(ENVIRONMENT_IS_PTHREAD)return;callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){assert(!ENVIRONMENT_IS_PTHREAD,"addRunDependency cannot be used in a pthread worker");runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}if(ENVIRONMENT_IS_PTHREAD)console.error("Pthread aborting at "+(new Error).stack);what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm-threaded-simd.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmModule=module;if(!ENVIRONMENT_IS_PTHREAD){var numWorkersToLoad=PThread.unusedWorkers.length;PThread.unusedWorkers.forEach(function(w){PThread.loadWasmModuleToWorker(w,function(){if(!--numWorkersToLoad)removeRunDependency();});});}}if(!ENVIRONMENT_IS_PTHREAD){addRunDependency();}function receiveInstantiatedSource(output){receiveInstance(output["instance"],output["module"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}var ASM_CONSTS={};function initPthreadsJS(){PThread.initRuntime();}if(!ENVIRONMENT_IS_PTHREAD)__ATINIT__.push({func:function(){___wasm_call_ctors();}});var __pthread_ptr=0;var __pthread_is_main_runtime_thread=0;var __pthread_is_main_browser_thread=0;function __register_pthread_ptr(pthreadPtr,isMainBrowserThread,isMainRuntimeThread){pthreadPtr=pthreadPtr|0;isMainBrowserThread=isMainBrowserThread|0;isMainRuntimeThread=isMainRuntimeThread|0;__pthread_ptr=pthreadPtr;__pthread_is_main_browser_thread=isMainBrowserThread;__pthread_is_main_runtime_thread=isMainRuntimeThread;}Module["__register_pthread_ptr"]=__register_pthread_ptr;var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var __main_thread_futex_wait_address=13392;function _emscripten_futex_wake(addr,count){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0||count<0)return -28;if(count==0)return 0;if(count>=2147483647)count=Infinity;var mainThreadWaitAddress=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);var mainThreadWoken=0;if(mainThreadWaitAddress==addr){var loadedAddr=Atomics.compareExchange(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,mainThreadWaitAddress,0);if(loadedAddr==mainThreadWaitAddress){--count;mainThreadWoken=1;if(count<=0)return 1}}var ret=Atomics.notify(GROWABLE_HEAP_I32(),addr>>2,count);if(ret>=0)return ret+mainThreadWoken;throw "Atomics.notify returned an unexpected value "+ret}Module["_emscripten_futex_wake"]=_emscripten_futex_wake;function __kill_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _kill_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _kill_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];pthread.worker.terminate();PThread.freeThreadData(pthread);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(pthread.worker),1);pthread.worker.pthread=undefined;}function __cancel_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cancel_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cancel_thread!";var pthread=PThread.pthreads[pthread_ptr];pthread.worker.postMessage({"cmd":"cancel"});}function __cleanup_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cleanup_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cleanup_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];if(pthread){var worker=pthread.worker;PThread.returnWorkerToPool(worker);}}var PThread={MAIN_THREAD_ID:1,mainThreadInfo:{schedPolicy:0,schedPrio:0},unusedWorkers:[],runningWorkers:[],initRuntime:function(){__register_pthread_ptr(PThread.mainThreadBlock,!ENVIRONMENT_IS_WORKER,1);_emscripten_register_main_browser_thread_id(PThread.mainThreadBlock);},initMainThreadBlock:function(){var pthreadPoolSize=8;for(var i=0;i>2]=PThread.mainThreadBlock;var headPtr=PThread.mainThreadBlock+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var tlsMemory=12880;for(var i=0;i<128;++i)GROWABLE_HEAP_U32()[tlsMemory/4+i]=0;Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+104>>2,tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+40>>2,PThread.mainThreadBlock);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+44>>2,42);},initWorker:function(){},pthreads:{},exitHandlers:null,setThreadStatus:function(){},runExitHandlers:function(){if(PThread.exitHandlers!==null){while(PThread.exitHandlers.length>0){PThread.exitHandlers.pop()();}PThread.exitHandlers=null;}if(ENVIRONMENT_IS_PTHREAD&&threadInfoStruct)___pthread_tsd_run_dtors();},threadExit:function(exitCode){var tb=_pthread_self();if(tb){Atomics.store(GROWABLE_HEAP_U32(),tb+4>>2,exitCode);Atomics.store(GROWABLE_HEAP_U32(),tb+0>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+60>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+64>>2,0);PThread.runExitHandlers();_emscripten_futex_wake(tb+0,2147483647);__register_pthread_ptr(0,0,0);threadInfoStruct=0;if(ENVIRONMENT_IS_PTHREAD){postMessage({"cmd":"exit"});}}},threadCancel:function(){PThread.runExitHandlers();Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+4>>2,-1);Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+0>>2,1);_emscripten_futex_wake(threadInfoStruct+0,2147483647);threadInfoStruct=selfThreadId=0;__register_pthread_ptr(0,0,0);postMessage({"cmd":"cancelDone"});},terminateAllThreads:function(){for(var t in PThread.pthreads){var pthread=PThread.pthreads[t];if(pthread&&pthread.worker){PThread.returnWorkerToPool(pthread.worker);}}PThread.pthreads={};for(var i=0;i>2];GROWABLE_HEAP_I32()[pthread.threadInfoStruct+104>>2]=0;_free(tlsMemory);_free(pthread.threadInfoStruct);}pthread.threadInfoStruct=0;if(pthread.allocatedOwnStack&&pthread.stackBase)_free(pthread.stackBase);pthread.stackBase=0;if(pthread.worker)pthread.worker.pthread=null;},returnWorkerToPool:function(worker){delete PThread.pthreads[worker.pthread.thread];PThread.unusedWorkers.push(worker);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);PThread.freeThreadData(worker.pthread);worker.pthread=undefined;},receiveObjectTransfer:function(data){},loadWasmModuleToWorker:function(worker,onFinishedLoading){worker.onmessage=function(e){var d=e["data"];var cmd=d["cmd"];if(worker.pthread)PThread.currentProxiedOperationCallerThread=worker.pthread.threadInfoStruct;if(d["targetThread"]&&d["targetThread"]!=_pthread_self()){var thread=PThread.pthreads[d.targetThread];if(thread){thread.worker.postMessage(e.data,d["transferList"]);}else{console.error('Internal error! Worker sent a message "'+cmd+'" to target pthread '+d["targetThread"]+", but that thread no longer exists!");}PThread.currentProxiedOperationCallerThread=undefined;return}if(cmd==="processQueuedMainThreadWork"){_emscripten_main_thread_process_queued_calls();}else if(cmd==="spawnThread"){__spawn_thread(e.data);}else if(cmd==="cleanupThread"){__cleanup_thread(d["thread"]);}else if(cmd==="killThread"){__kill_thread(d["thread"]);}else if(cmd==="cancelThread"){__cancel_thread(d["thread"]);}else if(cmd==="loaded"){worker.loaded=true;if(onFinishedLoading)onFinishedLoading(worker);if(worker.runPthread){worker.runPthread();delete worker.runPthread;}}else if(cmd==="print"){out("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="printErr"){err("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="alert"){alert("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="exit"){var detached=worker.pthread&&Atomics.load(GROWABLE_HEAP_U32(),worker.pthread.thread+68>>2);if(detached){PThread.returnWorkerToPool(worker);}}else if(cmd==="cancelDone"){PThread.returnWorkerToPool(worker);}else if(cmd==="objectTransfer"){PThread.receiveObjectTransfer(e.data);}else if(e.data.target==="setimmediate"){worker.postMessage(e.data);}else{err("worker sent an unknown command "+cmd);}PThread.currentProxiedOperationCallerThread=undefined;};worker.onerror=function(e){err("pthread sent an error! "+e.filename+":"+e.lineno+": "+e.message);};if(ENVIRONMENT_IS_NODE){worker.on("message",function(data){worker.onmessage({data:data});});worker.on("error",function(data){worker.onerror(data);});worker.on("exit",function(data){console.log("worker exited - TODO: update the worker queue?");});}worker.postMessage({"cmd":"load","urlOrBlob":Module["mainScriptUrlOrBlob"]||_scriptDir,"wasmMemory":wasmMemory,"wasmModule":wasmModule,"DYNAMIC_BASE":DYNAMIC_BASE,"DYNAMICTOP_PTR":DYNAMICTOP_PTR});},allocateUnusedWorker:function(){var pthreadMainJs=locateFile("tfjs-backend-wasm-threaded-simd.worker.js");PThread.unusedWorkers.push(new Worker(pthreadMainJs));},getNewWorker:function(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]);}if(PThread.unusedWorkers.length>0)return PThread.unusedWorkers.pop();else return null},busySpinWait:function(msecs){var t=performance.now()+msecs;while(performance.now()>2]=value;return value}function _atexit(func,arg){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(1,1,func,arg);}function __emscripten_notify_thread_queue(targetThreadId,mainThreadId){if(targetThreadId==mainThreadId){postMessage({"cmd":"processQueuedMainThreadWork"});}else if(ENVIRONMENT_IS_PTHREAD){postMessage({"targetThread":targetThreadId,"cmd":"processThreadQueue"});}else{var pthread=PThread.pthreads[targetThreadId];var worker=pthread&&pthread.worker;if(!worker){return}worker.postMessage({"cmd":"processThreadQueue"});}return 1}function _abort(){abort();}function _emscripten_conditional_set_current_thread_status(expectedStatus,newStatus){}function _emscripten_futex_wait(addr,val,timeout){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0)return -28;if(ENVIRONMENT_IS_WORKER){var ret=Atomics.wait(GROWABLE_HEAP_I32(),addr>>2,val,timeout);if(ret==="timed-out")return -73;if(ret==="not-equal")return -6;if(ret==="ok")return 0;throw "Atomics.wait returned an unexpected value "+ret}else{var loadedVal=Atomics.load(GROWABLE_HEAP_I32(),addr>>2);if(val!=loadedVal)return -6;var tNow=performance.now();var tEnd=tNow+timeout;Atomics.store(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,addr);var ourWaitAddress=addr;while(addr==ourWaitAddress){tNow=performance.now();if(tNow>tEnd){return -73}_emscripten_main_thread_process_queued_calls();addr=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);}return 0}}function _emscripten_is_main_browser_thread(){return __pthread_is_main_browser_thread|0}function _emscripten_is_main_runtime_thread(){return __pthread_is_main_runtime_thread|0}function _emscripten_memcpy_big(dest,src,num){GROWABLE_HEAP_U8().copyWithin(dest,src,src+num);}function _emscripten_num_logical_cores(){return navigator["hardwareConcurrency"]}function _emscripten_proxy_to_main_thread_js(index,sync){var numCallArgs=arguments.length-2;var stack=stackSave();var args=stackAlloc(numCallArgs*8);var b=args>>3;for(var i=0;i>3]);buf+=8;}else{buf=buf+3&~3;args.push(GROWABLE_HEAP_I32()[buf>>2]);buf+=4;}}return args}function _emscripten_receive_on_main_thread_js(index,numCallArgs,args){_emscripten_receive_on_main_thread_js_callArgs.length=numCallArgs;var b=args>>3;for(var i=0;i>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();if(requestedSize<=oldSize){return false}var PAGE_MULTIPLE=65536;var maxHeapSize=1073741824;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var JSEvents={keyEvent:0,mouseEvent:0,wheelEvent:0,uiEvent:0,focusEvent:0,deviceOrientationEvent:0,deviceMotionEvent:0,fullscreenChangeEvent:0,pointerlockChangeEvent:0,visibilityChangeEvent:0,touchEvent:0,previousFullscreenElement:null,previousScreenX:null,previousScreenY:null,removeEventListenersRegistered:false,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i);}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[];},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){JSEvents.removeEventListenersRegistered=true;}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence>2]=eventTypeId;GROWABLE_HEAP_I32()[varargs+4>>2]=eventData;GROWABLE_HEAP_I32()[varargs+8>>2]=userData;_emscripten_async_queue_on_thread_(targetThread,637534208,eventHandlerFunc,eventData,varargs);stackRestore(stackTop);},getTargetThreadForEventCallback:function(targetThread){switch(targetThread){case 1:return 0;case 2:return PThread.currentProxiedOperationCallerThread;default:return targetThread}},getNodeNameForTarget:function(target){if(!target)return "";if(target==window)return "#window";if(target==screen)return "#screen";return target&&target.nodeName?target.nodeName:""},fullscreenEnabled:function(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+1;var cString=_malloc(length);stringToUTF8(jsString,cString,length);return cString}function _emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height){var stackTop=stackSave();var varargs=stackAlloc(12);var targetCanvasPtr=0;if(targetCanvas){targetCanvasPtr=stringToNewUTF8(targetCanvas);}GROWABLE_HEAP_I32()[varargs>>2]=targetCanvasPtr;GROWABLE_HEAP_I32()[varargs+4>>2]=width;GROWABLE_HEAP_I32()[varargs+8>>2]=height;_emscripten_async_queue_on_thread_(targetThread,657457152,0,targetCanvasPtr,varargs);stackRestore(stackTop);}function _emscripten_set_offscreencanvas_size_on_target_thread(targetThread,targetCanvas,width,height){targetCanvas=targetCanvas?UTF8ToString(targetCanvas):"";_emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height);}function __maybeCStringToJsString(cString){return cString>2?UTF8ToString(cString):cString}var specialHTMLTargets=[0,typeof document!=="undefined"?document:0,typeof window!=="undefined"?window:0];function __findEventTarget(target){target=__maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!=="undefined"?document.querySelector(target):undefined);return domElement}function __findCanvasEventTarget(target){return __findEventTarget(target)}function _emscripten_set_canvas_element_size_calling_thread(target,width,height){var canvas=__findCanvasEventTarget(target);if(!canvas)return -4;if(canvas.canvasSharedPtr){GROWABLE_HEAP_I32()[canvas.canvasSharedPtr>>2]=width;GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+4>>2]=height;}if(canvas.offscreenCanvas||!canvas.controlTransferredOffscreen){if(canvas.offscreenCanvas)canvas=canvas.offscreenCanvas;var autoResizeViewport=false;if(canvas.GLctxObject&&canvas.GLctxObject.GLctx){var prevViewport=canvas.GLctxObject.GLctx.getParameter(2978);autoResizeViewport=prevViewport[0]===0&&prevViewport[1]===0&&prevViewport[2]===canvas.width&&prevViewport[3]===canvas.height;}canvas.width=width;canvas.height=height;if(autoResizeViewport){canvas.GLctxObject.GLctx.viewport(0,0,width,height);}}else if(canvas.canvasSharedPtr){var targetThread=GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+8>>2];_emscripten_set_offscreencanvas_size_on_target_thread(targetThread,target,width,height);return 1}else{return -4}return 0}function _emscripten_set_canvas_element_size_main_thread(target,width,height){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(2,1,target,width,height);return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}function _emscripten_set_canvas_element_size(target,width,height){var canvas=__findCanvasEventTarget(target);if(canvas){return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}else{return _emscripten_set_canvas_element_size_main_thread(target,width,height)}}function _emscripten_set_current_thread_status(newStatus){}function _emscripten_set_thread_name(threadId,name){}function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=function(index,divisor){ext["vertexAttribDivisorANGLE"](index,divisor);};ctx["drawArraysInstanced"]=function(mode,first,count,primcount){ext["drawArraysInstancedANGLE"](mode,first,count,primcount);};ctx["drawElementsInstanced"]=function(mode,count,type,indices,primcount){ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);};return 1}}function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=function(){return ext["createVertexArrayOES"]()};ctx["deleteVertexArray"]=function(vao){ext["deleteVertexArrayOES"](vao);};ctx["bindVertexArray"]=function(vao){ext["bindVertexArrayOES"](vao);};ctx["isVertexArray"]=function(vao){return ext["isVertexArrayOES"](vao)};return 1}}function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=function(n,bufs){ext["drawBuffersWEBGL"](n,bufs);};return 1}}var GL={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:{},currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],programInfos:{},stringCache:{},unpackAlignment:4,init:function(){var miniTempFloatBuffer=new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);for(var i=0;i>2]:-1;source+=UTF8ToString(GROWABLE_HEAP_I32()[string+i*4>>2],len<0?undefined:len);}return source},createContext:function(canvas,webGLContextAttributes){var ctx=canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=_malloc(8);GROWABLE_HEAP_I32()[handle+4>>2]=_pthread_self();var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context);}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return !(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;_free(GL.contexts[contextHandle].handle);GL.contexts[contextHandle]=null;},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;__webgl_enable_ANGLE_instanced_arrays(GLctx);__webgl_enable_OES_vertex_array_object(GLctx);__webgl_enable_WEBGL_draw_buffers(GLctx);GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query");var automaticallyEnabledExtensions=["OES_texture_float","OES_texture_half_float","OES_standard_derivatives","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBGL_depth_texture","OES_element_index_uint","EXT_texture_filter_anisotropic","EXT_frag_depth","WEBGL_draw_buffers","ANGLE_instanced_arrays","OES_texture_float_linear","OES_texture_half_float_linear","EXT_blend_minmax","EXT_shader_texture_lod","EXT_texture_norm16","WEBGL_compressed_texture_pvrtc","EXT_color_buffer_half_float","WEBGL_color_buffer_float","EXT_sRGB","WEBGL_compressed_texture_etc1","EXT_disjoint_timer_query","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_astc","EXT_color_buffer_float","WEBGL_compressed_texture_s3tc_srgb","EXT_disjoint_timer_query_webgl2","WEBKIT_WEBGL_compressed_texture_pvrtc"];var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext);}});},populateUniformTable:function(program){var p=GL.programs[program];var ptable=GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,35718);for(var i=0;i>2;contextAttributes["alpha"]=!!GROWABLE_HEAP_I32()[a+(0>>2)];contextAttributes["depth"]=!!GROWABLE_HEAP_I32()[a+(4>>2)];contextAttributes["stencil"]=!!GROWABLE_HEAP_I32()[a+(8>>2)];contextAttributes["antialias"]=!!GROWABLE_HEAP_I32()[a+(12>>2)];contextAttributes["premultipliedAlpha"]=!!GROWABLE_HEAP_I32()[a+(16>>2)];contextAttributes["preserveDrawingBuffer"]=!!GROWABLE_HEAP_I32()[a+(20>>2)];var powerPreference=GROWABLE_HEAP_I32()[a+(24>>2)];contextAttributes["powerPreference"]=__emscripten_webgl_power_preferences[powerPreference];contextAttributes["failIfMajorPerformanceCaveat"]=!!GROWABLE_HEAP_I32()[a+(28>>2)];contextAttributes.majorVersion=GROWABLE_HEAP_I32()[a+(32>>2)];contextAttributes.minorVersion=GROWABLE_HEAP_I32()[a+(36>>2)];contextAttributes.enableExtensionsByDefault=GROWABLE_HEAP_I32()[a+(40>>2)];contextAttributes.explicitSwapControl=GROWABLE_HEAP_I32()[a+(44>>2)];contextAttributes.proxyContextToMainThread=GROWABLE_HEAP_I32()[a+(48>>2)];contextAttributes.renderViaOffscreenBackBuffer=GROWABLE_HEAP_I32()[a+(52>>2)];var canvas=__findCanvasEventTarget(target);if(!canvas){return -4}if(contextAttributes.explicitSwapControl){return -1}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}function _emscripten_webgl_create_context(a0,a1){return _emscripten_webgl_do_create_context(a0,a1)}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=GROWABLE_HEAP_I32()[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(3,1,fd);return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(4,1,fd,offset_low,offset_high,whence,newOffset)}function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(5,1,fd,iov,iovcnt,pnum);var num=0;for(var i=0;i>2];var len=GROWABLE_HEAP_I32()[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _pthread_cleanup_pop(execute){var routine=PThread.exitHandlers.pop();if(execute)routine();}function _pthread_cleanup_push(routine,arg){if(PThread.exitHandlers===null){PThread.exitHandlers=[];}PThread.exitHandlers.push(function(){dynCall_vi(routine,arg);});}function __spawn_thread(threadParams){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _spawn_thread() can only ever be called from main application thread!";var worker=PThread.getNewWorker();if(worker.pthread!==undefined)throw "Internal error!";if(!threadParams.pthread_ptr)throw "Internal error, no pthread ptr!";PThread.runningWorkers.push(worker);var tlsMemory=_malloc(128*4);for(var i=0;i<128;++i){GROWABLE_HEAP_I32()[tlsMemory+i*4>>2]=0;}var stackHigh=threadParams.stackBase+threadParams.stackSize;var pthread=PThread.pthreads[threadParams.pthread_ptr]={worker:worker,stackBase:threadParams.stackBase,stackSize:threadParams.stackSize,allocatedOwnStack:threadParams.allocatedOwnStack,thread:threadParams.pthread_ptr,threadInfoStruct:threadParams.pthread_ptr};var tis=pthread.threadInfoStruct>>2;Atomics.store(GROWABLE_HEAP_U32(),tis+(0>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(4>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(8>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(68>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(104>>2),tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),tis+(48>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(40>>2),pthread.threadInfoStruct);Atomics.store(GROWABLE_HEAP_U32(),tis+(44>>2),42);Atomics.store(GROWABLE_HEAP_U32(),tis+(108>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(84>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(80>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+8>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+12>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+20>>2),threadParams.schedPolicy);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+24>>2),threadParams.schedPrio);var global_libc=_emscripten_get_global_libc();var global_locale=global_libc+40;Atomics.store(GROWABLE_HEAP_U32(),tis+(176>>2),global_locale);worker.pthread=pthread;var msg={"cmd":"run","start_routine":threadParams.startRoutine,"arg":threadParams.arg,"threadInfoStruct":threadParams.pthread_ptr,"selfThreadId":threadParams.pthread_ptr,"parentThreadId":threadParams.parent_pthread_ptr,"stackBase":threadParams.stackBase,"stackSize":threadParams.stackSize};worker.runPthread=function(){msg.time=performance.now();worker.postMessage(msg,threadParams.transferList);};if(worker.loaded){worker.runPthread();delete worker.runPthread;}}function _pthread_getschedparam(thread,policy,schedparam){if(!policy&&!schedparam)return ERRNO_CODES.EINVAL;if(!thread){err("pthread_getschedparam called with a null thread pointer!");return ERRNO_CODES.ESRCH}var self=GROWABLE_HEAP_I32()[thread+12>>2];if(self!==thread){err("pthread_getschedparam attempted on thread "+thread+", which does not point to a valid thread, or does not exist anymore!");return ERRNO_CODES.ESRCH}var schedPolicy=Atomics.load(GROWABLE_HEAP_U32(),thread+108+20>>2);var schedPrio=Atomics.load(GROWABLE_HEAP_U32(),thread+108+24>>2);if(policy)GROWABLE_HEAP_I32()[policy>>2]=schedPolicy;if(schedparam)GROWABLE_HEAP_I32()[schedparam>>2]=schedPrio;return 0}function _pthread_self(){return __pthread_ptr|0}Module["_pthread_self"]=_pthread_self;function _pthread_create(pthread_ptr,attr,start_routine,arg){if(typeof SharedArrayBuffer==="undefined"){err("Current environment does not support SharedArrayBuffer, pthreads are not available!");return 6}if(!pthread_ptr){err("pthread_create called with a null thread pointer!");return 28}var transferList=[];var error=0;if(ENVIRONMENT_IS_PTHREAD&&(transferList.length===0||error)){return _emscripten_sync_run_in_main_thread_4(687865856,pthread_ptr,attr,start_routine,arg)}var stackSize=0;var stackBase=0;var detached=0;var schedPolicy=0;var schedPrio=0;if(attr){stackSize=GROWABLE_HEAP_I32()[attr>>2];stackSize+=81920;stackBase=GROWABLE_HEAP_I32()[attr+8>>2];detached=GROWABLE_HEAP_I32()[attr+12>>2]!==0;var inheritSched=GROWABLE_HEAP_I32()[attr+16>>2]===0;if(inheritSched){var prevSchedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];var prevSchedPrio=GROWABLE_HEAP_I32()[attr+24>>2];var parentThreadPtr=PThread.currentProxiedOperationCallerThread?PThread.currentProxiedOperationCallerThread:_pthread_self();_pthread_getschedparam(parentThreadPtr,attr+20,attr+24);schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];GROWABLE_HEAP_I32()[attr+20>>2]=prevSchedPolicy;GROWABLE_HEAP_I32()[attr+24>>2]=prevSchedPrio;}else{schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];}}else{stackSize=2097152;}var allocatedOwnStack=stackBase==0;if(allocatedOwnStack){stackBase=_memalign(16,stackSize);}else{stackBase-=stackSize;assert(stackBase>0);}var threadInfoStruct=_malloc(232);for(var i=0;i<232>>2;++i)GROWABLE_HEAP_U32()[(threadInfoStruct>>2)+i]=0;GROWABLE_HEAP_I32()[pthread_ptr>>2]=threadInfoStruct;GROWABLE_HEAP_I32()[threadInfoStruct+12>>2]=threadInfoStruct;var headPtr=threadInfoStruct+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var threadParams={stackBase:stackBase,stackSize:stackSize,allocatedOwnStack:allocatedOwnStack,schedPolicy:schedPolicy,schedPrio:schedPrio,detached:detached,startRoutine:start_routine,pthread_ptr:threadInfoStruct,parent_pthread_ptr:_pthread_self(),arg:arg,transferList:transferList};if(ENVIRONMENT_IS_PTHREAD){threadParams.cmd="spawnThread";postMessage(threadParams,transferList);}else{__spawn_thread(threadParams);}return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}function _sysconf(name){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(6,1,name);switch(name){case 30:return 16384;case 85:var maxHeapSize=1073741824;return maxHeapSize/16384;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:case 79:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return -1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}setErrNo(28);return -1}if(!ENVIRONMENT_IS_PTHREAD)PThread.initMainThreadBlock();else PThread.initWorker();var GLctx;GL.init();var proxiedFunctionTable=[null,_atexit,_emscripten_set_canvas_element_size_main_thread,_fd_close,_fd_seek,_fd_write,_sysconf];var asmLibraryArg={"e":___assert_fail,"r":___call_main,"w":__emscripten_notify_thread_queue,"a":_abort,"l":_emscripten_conditional_set_current_thread_status,"d":_emscripten_futex_wait,"c":_emscripten_futex_wake,"h":_emscripten_get_now,"g":_emscripten_is_main_browser_thread,"x":_emscripten_is_main_runtime_thread,"q":_emscripten_memcpy_big,"B":_emscripten_num_logical_cores,"t":_emscripten_receive_on_main_thread_js,"A":_emscripten_resize_heap,"u":_emscripten_set_canvas_element_size,"k":_emscripten_set_current_thread_status,"s":_emscripten_set_thread_name,"v":_emscripten_webgl_create_context,"m":_fd_close,"o":_fd_seek,"i":_fd_write,"p":initPthreadsJS,"memory":wasmMemory||Module["wasmMemory"],"y":_pthread_cleanup_pop,"z":_pthread_cleanup_push,"j":_pthread_create,"b":_pthread_self,"f":_roundf,"n":_sysconf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return (___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["C"]).apply(null,arguments)};var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["D"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["E"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["F"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["G"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["H"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["I"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["J"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["K"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["L"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["M"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["N"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["O"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["P"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["Q"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["R"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["S"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["T"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["U"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["V"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["W"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["X"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["Y"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["Z"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["_"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["$"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["aa"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["ba"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["ca"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["da"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["ea"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["fa"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["ga"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["ha"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["ia"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["ja"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["ka"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["la"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["ma"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["na"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["oa"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["pa"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["qa"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["ra"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["sa"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["ta"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["ua"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["va"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["wa"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["xa"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["ya"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["za"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["Aa"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["Ba"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["Ca"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["Da"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["Ea"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["Fa"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["Ga"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["Ha"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["Ia"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["Ja"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["Ka"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["La"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["Ma"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["Na"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["Oa"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["Pa"]).apply(null,arguments)};var ___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=function(){return (___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=Module["asm"]["Qa"]).apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){return (___errno_location=Module["___errno_location"]=Module["asm"]["Ra"]).apply(null,arguments)};var _emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=function(){return (_emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=Module["asm"]["Sa"]).apply(null,arguments)};var _memalign=Module["_memalign"]=function(){return (_memalign=Module["_memalign"]=Module["asm"]["Ta"]).apply(null,arguments)};var ___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=function(){return (___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=Module["asm"]["Ua"]).apply(null,arguments)};var _emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=function(){return (_emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=Module["asm"]["Va"]).apply(null,arguments)};var _emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=function(){return (_emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=Module["asm"]["Wa"]).apply(null,arguments)};var _emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=function(){return (_emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=Module["asm"]["Xa"]).apply(null,arguments)};var _emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=function(){return (_emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=Module["asm"]["Ya"]).apply(null,arguments)};var _emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=function(){return (_emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=Module["asm"]["Za"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=function(){return (_emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=Module["asm"]["_a"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=function(){return (_emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=Module["asm"]["$a"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=function(){return (_emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=Module["asm"]["ab"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=function(){return (_emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=Module["asm"]["bb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=function(){return (_emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=Module["asm"]["cb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=function(){return (_emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=Module["asm"]["db"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=function(){return (_emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=Module["asm"]["eb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=function(){return (_emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=Module["asm"]["fb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=function(){return (_emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=Module["asm"]["gb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=function(){return (_emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=Module["asm"]["hb"]).apply(null,arguments)};var _emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=function(){return (_emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=Module["asm"]["ib"]).apply(null,arguments)};var _emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=function(){return (_emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=Module["asm"]["jb"]).apply(null,arguments)};var _emscripten_tls_init=Module["_emscripten_tls_init"]=function(){return (_emscripten_tls_init=Module["_emscripten_tls_init"]=Module["asm"]["kb"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["lb"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["mb"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["nb"]).apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){return (dynCall_vi=Module["dynCall_vi"]=Module["asm"]["ob"]).apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){return (dynCall_v=Module["dynCall_v"]=Module["asm"]["pb"]).apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){return (dynCall_ii=Module["dynCall_ii"]=Module["asm"]["qb"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;Module["PThread"]=PThread;Module["PThread"]=PThread;Module["_pthread_self"]=_pthread_self;Module["wasmMemory"]=wasmMemory;Module["ExitStatus"]=ExitStatus;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}if(!ENVIRONMENT_IS_PTHREAD)noExitRuntime=true;if(!ENVIRONMENT_IS_PTHREAD)run(); return WasmBackendModuleSimd @@ -3388,7 +3388,7 @@ module.exports = WasmBackendModuleSimd; }); - const wasmWorkerContents = 'var threadInfoStruct=0;var selfThreadId=0;var parentThreadId=0;var Module={};function assert(condition,text){if(!condition)abort("Assertion failed: "+text)}function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:selfThreadId})}var out=function(){throw"out() is not defined in worker.js."};var err=threadPrintErr;this.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);Module["wasmModule"]=null;receiveInstance(instance);return instance.exports};this.onmessage=function(e){try{if(e.data.cmd==="load"){Module["DYNAMIC_BASE"]=e.data.DYNAMIC_BASE;Module["DYNAMICTOP_PTR"]=e.data.DYNAMICTOP_PTR;Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob==="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}Module=WasmBackendModuleSimd(Module);postMessage({"cmd":"loaded"})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;threadInfoStruct=e.data.threadInfoStruct;Module["__register_pthread_ptr"](threadInfoStruct,0,0);selfThreadId=e.data.selfThreadId;parentThreadId=e.data.parentThreadId;var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;assert(threadInfoStruct);assert(selfThreadId);assert(parentThreadId);assert(top!=0);assert(max!=0);assert(top>max);Module["establishStackSpace"](top,max);Module["_emscripten_tls_init"]();Module["writeStackCookie"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].setThreadStatus(Module["_pthread_self"](),1);try{var result=Module["dynCall_ii"](e.data.start_routine,e.data.arg);Module["checkStackCookie"]();if(!Module["getNoExitRuntime"]())Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){Atomics.store(Module["HEAPU32"],threadInfoStruct+4>>2,ex instanceof Module["ExitStatus"]?ex.status:-2);Atomics.store(Module["HEAPU32"],threadInfoStruct+0>>2,1);if(typeof Module["_emscripten_futex_wake"]!=="function"){err("Thread Initialisation failed.");throw ex}Module["_emscripten_futex_wake"](threadInfoStruct+0,2147483647);if(!(ex instanceof Module["ExitStatus"]))throw ex}else{err("Pthread 0x"+threadInfoStruct.toString(16)+" completed its pthread main entry point with an unwind, keeping the pthread worker alive for asynchronous operation.")}}}else if(e.data.cmd==="cancel"){if(threadInfoStruct){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(threadInfoStruct){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex.stack)err(ex.stack);throw ex}};if(typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string"){self={location:{href:__filename}};var onmessage=this.onmessage;var nodeWorkerThreads=require("worker_threads");Worker=nodeWorkerThreads.Worker;var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var nodeFS=require("fs");var nodeRead=function(filename){return nodeFS.readFileSync(filename,"utf8")};function globalEval(x){global.require=require;global.Module=Module;eval.call(null,x)}importScripts=function(f){globalEval(nodeRead(f))};postMessage=function(msg){parentPort.postMessage(msg)};if(typeof performance==="undefined"){performance={now:function(){return Date.now()}}}}'; + const wasmWorkerContents = 'var threadInfoStruct=0;var selfThreadId=0;var parentThreadId=0;var Module={};function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:selfThreadId})}var err=threadPrintErr;this.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);Module["wasmModule"]=null;receiveInstance(instance);return instance.exports};this.onmessage=function(e){try{if(e.data.cmd==="load"){Module["DYNAMIC_BASE"]=e.data.DYNAMIC_BASE;Module["DYNAMICTOP_PTR"]=e.data.DYNAMICTOP_PTR;Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob==="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}Module=WasmBackendModuleSimd(Module);postMessage({"cmd":"loaded"})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;threadInfoStruct=e.data.threadInfoStruct;Module["__register_pthread_ptr"](threadInfoStruct,0,0);selfThreadId=e.data.selfThreadId;parentThreadId=e.data.parentThreadId;var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["_emscripten_tls_init"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].setThreadStatus(Module["_pthread_self"](),1);try{var result=Module["dynCall_ii"](e.data.start_routine,e.data.arg);if(!Module["getNoExitRuntime"]())Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){Atomics.store(Module["HEAPU32"],threadInfoStruct+4>>2,ex instanceof Module["ExitStatus"]?ex.status:-2);Atomics.store(Module["HEAPU32"],threadInfoStruct+0>>2,1);Module["_emscripten_futex_wake"](threadInfoStruct+0,2147483647);if(!(ex instanceof Module["ExitStatus"]))throw ex}}}else if(e.data.cmd==="cancel"){if(threadInfoStruct){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(threadInfoStruct){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex.stack)err(ex.stack);throw ex}};if(typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string"){self={location:{href:__filename}};var onmessage=this.onmessage;var nodeWorkerThreads=require("worker_threads");Worker=nodeWorkerThreads.Worker;var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var nodeFS=require("fs");var nodeRead=function(filename){return nodeFS.readFileSync(filename,"utf8")};function globalEval(x){global.require=require;global.Module=Module;eval.call(null,x)}importScripts=function(f){globalEval(nodeRead(f))};postMessage=function(msg){parentPort.postMessage(msg)};if(typeof performance==="undefined"){performance={now:function(){return Date.now()}}}}'; var tfjsBackendWasm = createCommonjsModule(function (module, exports) { var WasmBackendModule = (function() { diff --git a/e2e/benchmarks/tfjs-backend-wasm-threaded-simd.wasm b/e2e/benchmarks/tfjs-backend-wasm-threaded-simd.wasm index 779636fdfa58ca575ed1407406f200efecd34e0b..1f1acc5fb4bea4767d6669bfe75d5c733d09a77e 100644 GIT binary patch delta 25034 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 delta 29363 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 QsY*U*P^SIZ6|&_21FQQmCjbBd diff --git a/e2e/benchmarks/tfjs-backend-wasm.wasm b/e2e/benchmarks/tfjs-backend-wasm.wasm index bfe8820fe5c7a1d516d7b6d6d7bfa4cded18ff59..d876cd489ce6aa24771103715f88a489a2c68081 100644 GIT binary patch delta 160 zcmZ3zlk?h6&JDcmOf%jz^RsW~XJY}DNy`+IG79fkoL)wwaQ+m6UAk!Od#?{-|ZJBNeFluan;L9|b&w-PX0RmVV x9Jicc;AZS)a6AK~x%z;@{XjfLlfm%`NP>yM@iUNS{SN{RjxSCza5Ejy1OQRJEu8=W delta 116 zcmcb%lXLY>&JDcmOkZC&^RsW~XJY}j OFgQLq#lX#UKobBV!6!HX diff --git a/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-threaded-simd.worker.ts b/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-threaded-simd.worker.ts index 720781df29d..16f4cc2f2b0 100644 --- a/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-threaded-simd.worker.ts +++ b/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-threaded-simd.worker.ts @@ -1 +1 @@ -export const wasmWorkerContents = 'var threadInfoStruct=0;var selfThreadId=0;var parentThreadId=0;var Module={};function assert(condition,text){if(!condition)abort("Assertion failed: "+text)}function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:selfThreadId})}var out=function(){throw"out() is not defined in worker.js."};var err=threadPrintErr;this.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);Module["wasmModule"]=null;receiveInstance(instance);return instance.exports};this.onmessage=function(e){try{if(e.data.cmd==="load"){Module["DYNAMIC_BASE"]=e.data.DYNAMIC_BASE;Module["DYNAMICTOP_PTR"]=e.data.DYNAMICTOP_PTR;Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob==="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}Module=WasmBackendModuleSimd(Module);postMessage({"cmd":"loaded"})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;threadInfoStruct=e.data.threadInfoStruct;Module["__register_pthread_ptr"](threadInfoStruct,0,0);selfThreadId=e.data.selfThreadId;parentThreadId=e.data.parentThreadId;var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;assert(threadInfoStruct);assert(selfThreadId);assert(parentThreadId);assert(top!=0);assert(max!=0);assert(top>max);Module["establishStackSpace"](top,max);Module["_emscripten_tls_init"]();Module["writeStackCookie"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].setThreadStatus(Module["_pthread_self"](),1);try{var result=Module["dynCall_ii"](e.data.start_routine,e.data.arg);Module["checkStackCookie"]();if(!Module["getNoExitRuntime"]())Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){Atomics.store(Module["HEAPU32"],threadInfoStruct+4>>2,ex instanceof Module["ExitStatus"]?ex.status:-2);Atomics.store(Module["HEAPU32"],threadInfoStruct+0>>2,1);if(typeof Module["_emscripten_futex_wake"]!=="function"){err("Thread Initialisation failed.");throw ex}Module["_emscripten_futex_wake"](threadInfoStruct+0,2147483647);if(!(ex instanceof Module["ExitStatus"]))throw ex}else{err("Pthread 0x"+threadInfoStruct.toString(16)+" completed its pthread main entry point with an unwind, keeping the pthread worker alive for asynchronous operation.")}}}else if(e.data.cmd==="cancel"){if(threadInfoStruct){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(threadInfoStruct){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex.stack)err(ex.stack);throw ex}};if(typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string"){self={location:{href:__filename}};var onmessage=this.onmessage;var nodeWorkerThreads=require("worker_threads");Worker=nodeWorkerThreads.Worker;var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var nodeFS=require("fs");var nodeRead=function(filename){return nodeFS.readFileSync(filename,"utf8")};function globalEval(x){global.require=require;global.Module=Module;eval.call(null,x)}importScripts=function(f){globalEval(nodeRead(f))};postMessage=function(msg){parentPort.postMessage(msg)};if(typeof performance==="undefined"){performance={now:function(){return Date.now()}}}}'; \ No newline at end of file +export const wasmWorkerContents = 'var threadInfoStruct=0;var selfThreadId=0;var parentThreadId=0;var Module={};function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:selfThreadId})}var err=threadPrintErr;this.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);Module["wasmModule"]=null;receiveInstance(instance);return instance.exports};this.onmessage=function(e){try{if(e.data.cmd==="load"){Module["DYNAMIC_BASE"]=e.data.DYNAMIC_BASE;Module["DYNAMICTOP_PTR"]=e.data.DYNAMICTOP_PTR;Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob==="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}Module=WasmBackendModuleSimd(Module);postMessage({"cmd":"loaded"})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;threadInfoStruct=e.data.threadInfoStruct;Module["__register_pthread_ptr"](threadInfoStruct,0,0);selfThreadId=e.data.selfThreadId;parentThreadId=e.data.parentThreadId;var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["_emscripten_tls_init"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].setThreadStatus(Module["_pthread_self"](),1);try{var result=Module["dynCall_ii"](e.data.start_routine,e.data.arg);if(!Module["getNoExitRuntime"]())Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){Atomics.store(Module["HEAPU32"],threadInfoStruct+4>>2,ex instanceof Module["ExitStatus"]?ex.status:-2);Atomics.store(Module["HEAPU32"],threadInfoStruct+0>>2,1);Module["_emscripten_futex_wake"](threadInfoStruct+0,2147483647);if(!(ex instanceof Module["ExitStatus"]))throw ex}}}else if(e.data.cmd==="cancel"){if(threadInfoStruct){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(threadInfoStruct){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex.stack)err(ex.stack);throw ex}};if(typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string"){self={location:{href:__filename}};var onmessage=this.onmessage;var nodeWorkerThreads=require("worker_threads");Worker=nodeWorkerThreads.Worker;var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var nodeFS=require("fs");var nodeRead=function(filename){return nodeFS.readFileSync(filename,"utf8")};function globalEval(x){global.require=require;global.Module=Module;eval.call(null,x)}importScripts=function(f){globalEval(nodeRead(f))};postMessage=function(msg){parentPort.postMessage(msg)};if(typeof performance==="undefined"){performance={now:function(){return Date.now()}}}}'; \ No newline at end of file From 2fc0b3d616b320a88a289cb72a653e8a75c2a81d Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Thu, 30 Jul 2020 10:01:25 -0400 Subject: [PATCH 28/70] poc --- e2e/benchmarks/index.html | 6 +- e2e/benchmarks/tf-backend-wasm.js | 3650 +++ e2e/benchmarks/tf-core.js | 32471 +++++++++++++++++++ e2e/benchmarks/tfjs-backend-wasm-simd.wasm | Bin 0 -> 214013 bytes e2e/benchmarks/tfjs-backend-wasm.wasm | Bin 0 -> 155531 bytes tfjs-backend-wasm/src/cc/BUILD | 2 + 6 files changed, 36127 insertions(+), 2 deletions(-) create mode 100644 e2e/benchmarks/tf-backend-wasm.js create mode 100644 e2e/benchmarks/tf-core.js create mode 100644 e2e/benchmarks/tfjs-backend-wasm-simd.wasm create mode 100644 e2e/benchmarks/tfjs-backend-wasm.wasm diff --git a/e2e/benchmarks/index.html b/e2e/benchmarks/index.html index 07dbdacf978..304a93ba2d0 100644 --- a/e2e/benchmarks/index.html +++ b/e2e/benchmarks/index.html @@ -85,12 +85,14 @@

    TensorFlow.js Model Benchmark

    - + + - + + diff --git a/e2e/benchmarks/tf-backend-wasm.js b/e2e/benchmarks/tf-backend-wasm.js new file mode 100644 index 00000000000..cce7987e732 --- /dev/null +++ b/e2e/benchmarks/tf-backend-wasm.js @@ -0,0 +1,3650 @@ +/** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tensorflow/tfjs-core'), require('path'), require('fs')) : + typeof define === 'function' && define.amd ? define(['exports', '@tensorflow/tfjs-core', 'path', 'fs'], factory) : + (global = global || self, factory((global.tf = global.tf || {}, global.tf.wasm = global.tf.wasm || {}), global.tf, global.path, global.fs)); +}(this, (function (exports, tfjsCore, path, fs) { 'use strict'; + + path = path && path.hasOwnProperty('default') ? path['default'] : path; + fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // This enum must align with the enum defined in cc/backend.h. + var CppDType; + (function (CppDType) { + CppDType[CppDType["float32"] = 0] = "float32"; + CppDType[CppDType["int32"] = 1] = "int32"; + CppDType[CppDType["bool"] = 2] = "bool"; + CppDType[CppDType["string"] = 3] = "string"; + CppDType[CppDType["complex64"] = 4] = "complex64"; + })(CppDType || (CppDType = {})); + // Must match enum in cc/fusable_activations.h. + var FusableActivation; + (function (FusableActivation) { + FusableActivation[FusableActivation["linear"] = 0] = "linear"; + FusableActivation[FusableActivation["relu"] = 1] = "relu"; + FusableActivation[FusableActivation["relu6"] = 2] = "relu6"; + FusableActivation[FusableActivation["prelu"] = 3] = "prelu"; + })(FusableActivation || (FusableActivation = {})); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFusedMatMul; + function setup(backend) { + wasmFusedMatMul = backend.wasm.cwrap(tfjsCore._FusedMatMul, null /* void */, [ + 'number', + 'array', + 'number', + 'number', + 'array', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number' // out_id + ]); + } + function fusedBatchMatMul(args) { + const { inputs, backend, attrs } = args; + const { a, b, bias, preluActivationWeights } = inputs; + if (a.dtype !== 'float32' || b.dtype !== 'float32') { + throw new Error(`_FusedMatMul for non non-float32 tensors not yet supported.`); + } + const { transposeA, transposeB, activation } = attrs; + const aId = backend.dataIdMap.get(a.dataId).id; + const bId = backend.dataIdMap.get(b.dataId).id; + let biasId = 0; + if (bias != null) { + const biasData = backend.dataIdMap.get(bias.dataId); + if (biasData.shape.length !== 1) { + throw new Error(`_FusedMatMul only supports rank-1 bias but got ` + + `rank ${biasData.shape.length}.`); + } + biasId = biasData.id; + } + const preluActivationWeightsId = preluActivationWeights == null ? + 0 : + backend.dataIdMap.get(preluActivationWeights.dataId).id; + const fusedActivation = FusableActivation[activation]; + if (fusedActivation == null) { + throw new Error(`${activation} activation not yet supported for FusedConv2D ` + + `in the wasm backend.`); + } + const leftDim = transposeA ? a.shape[2] : a.shape[1]; + const rightDim = transposeB ? b.shape[1] : b.shape[2]; + const batchDim = a.shape[0]; + const out = backend.makeOutput([batchDim, leftDim, rightDim], a.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); + const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); + wasmFusedMatMul(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, transposeA, transposeB, fusedActivation, biasId, preluActivationWeightsId, outId); + return out; + } + const fusedMatMulConfig = { + kernelName: tfjsCore._FusedMatMul, + backendName: 'wasm', + setupFunc: setup, + kernelFunc: fusedBatchMatMul + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function createUnaryKernelConfig(kernelName) { + let wasmFunc; + function setupFunc(backend) { + wasmFunc = + backend.wasm.cwrap(kernelName, null /* void */, ['number', 'number']); + } + function kernelFunc(args) { + const { backend, inputs: { x } } = args; + const xId = backend.dataIdMap.get(x.dataId).id; + const out = backend.makeOutput(x.shape, x.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(out.shape) === 0) { + return out; + } + wasmFunc(xId, outId); + return out; + } + return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const absConfig = createUnaryKernelConfig(tfjsCore.Abs); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function createBinaryKernelConfig(kernelName, supportsFullBroadcast, dtype) { + let wasmFunc; + function setupFunc(backend) { + wasmFunc = backend.wasm.cwrap(kernelName, null /* void */, [ + 'number', + 'array', + 'number', + 'number', + 'array', + 'number', + 'number', + 'number' // out_id + ]); + } + function kernelFunc(args) { + const { backend, inputs } = args; + const { a, b } = inputs; + const aId = backend.dataIdMap.get(a.dataId).id; + const bId = backend.dataIdMap.get(b.dataId).id; + const outputType = dtype != null ? dtype : a.dtype; + const newShape = tfjsCore.backend_util.assertAndGetBroadcastShape(a.shape, b.shape); + const out = backend.makeOutput(newShape, outputType); + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(newShape) === 0) { + return out; + } + const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); + const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); + const outId = backend.dataIdMap.get(out.dataId).id; + const kernelFunc = () => wasmFunc(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, CppDType[a.dtype], outId); + // Currently only some float operations support full broadcast. + if (supportsFullBroadcast && a.dtype === 'float32') { + kernelFunc(); + return out; + } + const aBroadcastDims = tfjsCore.backend_util.getBroadcastDims(a.shape, newShape); + const bBroadcastDims = tfjsCore.backend_util.getBroadcastDims(b.shape, newShape); + const loopsOverAllOfA = aBroadcastDims.every((v, i) => v === i); + const loopsOverAllOfB = bBroadcastDims.every((v, i) => v === i); + if (loopsOverAllOfA && loopsOverAllOfB) { + kernelFunc(); + return out; + } + else { + throw new Error(`Broadcasting along outer dims is not yet ` + + `supported for ${a.dtype} ${kernelName}.`); + } + } + return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast = true; + const addConfig = createBinaryKernelConfig(tfjsCore.Add, supportsFullBroadcast); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc; + function setupFunc(backend) { + wasmFunc = backend.wasm.cwrap(tfjsCore.AddN, null /* void */, [ + 'array', + 'number', + 'number', + 'number', + ]); + } + function addn(args) { + const { inputs, backend } = args; + const out = backend.makeOutput(inputs[0].shape, inputs[0].dtype); + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(out.shape) === 0) { + return out; + } + const inputIds = inputs.map(x => backend.dataIdMap.get(x.dataId).id); + const inputIdsBytes = new Uint8Array(new Int32Array(inputIds).buffer); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmFunc(inputIdsBytes, inputIds.length, CppDType[out.dtype], outId); + return out; + } + const addNConfig = { + kernelName: tfjsCore.AddN, + backendName: 'wasm', + setupFunc, + kernelFunc: addn, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function identity(args) { + const { inputs: { x }, backend } = args; + const out = backend.makeOutput(x.shape, x.dtype); + const inVals = backend.typedArrayFromHeap(x); + const outVals = backend.typedArrayFromHeap(out); + outVals.set(inVals); + return out; + } + const identityConfig = { + kernelName: tfjsCore.Identity, + backendName: 'wasm', + kernelFunc: identity, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmTranspose; + function setup$1(backend) { + wasmTranspose = backend.wasm.cwrap(tfjsCore.Transpose, null /* void */, [ + 'number', + 'array', + 'number', + 'number', + 'number', + 'array', + 'number', + ]); + } + function transpose(args) { + const { inputs, backend, attrs } = args; + // Reduce any dimensions with size one. Lower-rank transpose kernel performs + // better due to simpler memory access pattern. + const [reducedShape, perm] = removeOneSizeDims(inputs.x.shape, attrs.perm); + let permIsNoOp = true; + for (let i = 0; i < perm.length; i++) { + if (perm[i] !== i) { + permIsNoOp = false; + } + } + const outShape = computeOutShape(inputs.x.shape, attrs.perm); + const x = { + dataId: inputs.x.dataId, + shape: reducedShape, + dtype: inputs.x.dtype + }; + if (permIsNoOp) { + const cloned = identity({ inputs, backend }); + cloned.shape = outShape; + return cloned; + } + const out = backend.makeOutput(outShape, x.dtype); + const xId = backend.dataIdMap.get(x.dataId).id; + const outId = backend.dataIdMap.get(out.dataId).id; + const permBytes = new Uint8Array(new Int32Array(perm).buffer); + const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); + wasmTranspose(xId, xShapeBytes, x.shape.length, CppDType[x.dtype], outId, permBytes, perm.length); + return out; + } + function computeOutShape(inShape, perm) { + const outShape = new Array(inShape.length); + for (let i = 0; i < outShape.length; i++) { + outShape[i] = inShape[perm[i]]; + } + return outShape; + } + function removeOneSizeDims(shape, perm) { + const newShape = []; + const newPerm = []; + for (let i = 0; i < shape.length; ++i) { + if (shape[i] !== 1) { + newShape.push(shape[i]); + } + if (shape[perm[i]] !== 1) { + newPerm.push(perm[i]); + } + } + for (let i = 0; i < newPerm.length; ++i) { + let minValIdx = -1; + for (let j = 0; j < newPerm.length; ++j) { + if (newPerm[j] >= i && + (minValIdx === -1 || newPerm[minValIdx] > newPerm[j])) { + minValIdx = j; + } + } + newPerm[minValIdx] = i; + } + return [newShape, newPerm]; + } + const transposeConfig = { + kernelName: tfjsCore.Transpose, + backendName: 'wasm', + kernelFunc: transpose, + setupFunc: setup$1, + }; + + /** + * @license + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Compute permutation axes and do a transpose if necessary. + * + * Used by reduction ops. + * @param x input TensorInfo + * @param axis reduction axes + * @param backend wasm backend instance + */ + function permuteAxesAndTranspose(x, axis, backend) { + const xShape = x.shape; + const xRank = x.shape.length; + const originalAxes = tfjsCore.util.parseAxisParam(axis, xShape); + let axes = originalAxes; + const permutedAxes = tfjsCore.backend_util.getAxesPermutation(axes, xRank); + let xTransposed = null; + let inputWasTransposed = false; + if (permutedAxes != null) { + const newShape = new Array(xRank); + for (let i = 0; i < newShape.length; i++) { + newShape[i] = xShape[permutedAxes[i]]; + } + axes = tfjsCore.backend_util.getInnerMostAxes(axes.length, xRank); + xTransposed = + transpose({ inputs: { x }, attrs: { perm: permutedAxes }, backend }); + const xId = backend.dataIdMap.get(x.dataId).id; + const transposedId = backend.dataIdMap.get(xTransposed.dataId).id; + if (transposedId !== xId) { + inputWasTransposed = true; + } + } + return { transposed: xTransposed, originalAxes, axes, inputWasTransposed }; + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$1; + function setup$2(backend) { + wasmFunc$1 = backend.wasm.cwrap(tfjsCore.ArgMax, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number' // out_id + ]); + } + function argmax(args) { + const { backend, inputs, attrs } = args; + const { axis } = attrs; + const { x } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + let inputId = xId; + let input = x; + const { transposed, axes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); + if (inputWasTransposed) { + const transposedId = backend.dataIdMap.get(transposed.dataId).id; + if (transposedId !== xId) { + // transpose was not a no-op. We will need to dispose of this + // once we are done. + input = transposed; + inputId = transposedId; + } + } + const outShape = input.shape.slice(0, -1); + const out = backend.makeOutput(outShape, 'int32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const outerSize = tfjsCore.util.sizeFromShape(out.shape); + const innerSize = input.shape[axes[0]]; + wasmFunc$1(inputId, CppDType[input.dtype], outerSize, innerSize, outId); + if (inputWasTransposed) { + // dispose of the transposed tensor. + backend.disposeData(transposed.dataId); + } + return out; + } + const argMaxConfig = { + kernelName: tfjsCore.ArgMax, + backendName: 'wasm', + kernelFunc: argmax, + setupFunc: setup$2 + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmAvgPool; + function setup$3(backend) { + wasmAvgPool = backend.wasm.cwrap(tfjsCore.AvgPool, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function avgPool(args) { + const { inputs, attrs, backend } = args; + const x = inputs.x; + const xId = backend.dataIdMap.get(x.dataId).id; + const { filterSize, strides, pad, dimRoundingMode } = attrs; + const convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const channels = convInfo.inChannels; + if (convInfo.dataFormat !== 'channelsLast') { + throw new Error(`wasm backend does not support dataFormat:'` + + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + } + if (convInfo.dilationWidth !== 1 || convInfo.dilationHeight !== 1) { + throw new Error(`was backend only supports average pooling with dilation = [1, 1], ` + + `got [${convInfo.dilationHeight}, ${convInfo.dilationWidth}].`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmAvgPool(xId, x.shape[0], x.shape[1], x.shape[2], filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, strideHeight, strideWidth, channels, outId); + return out; + } + const avgPoolConfig = { + kernelName: tfjsCore.AvgPool, + backendName: 'wasm', + setupFunc: setup$3, + kernelFunc: avgPool + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmBatchMatMul; + function setup$4(backend) { + wasmBatchMatMul = backend.wasm.cwrap(tfjsCore.BatchMatMul, null /* void */, [ + 'number', + 'array', + 'number', + 'number', + 'array', + 'number', + 'number', + 'number', + 'number' // out_id + ]); + } + function batchMatMul(args) { + const { inputs, backend, attrs } = args; + const { a, b } = inputs; + if (a.dtype !== 'float32' || b.dtype !== 'float32') { + throw new Error(`BatchMatMul for non non-float32 tensors not yet supported.`); + } + const { transposeA, transposeB } = attrs; + const aId = backend.dataIdMap.get(a.dataId).id; + const bId = backend.dataIdMap.get(b.dataId).id; + const leftDim = transposeA ? a.shape[2] : a.shape[1]; + const rightDim = transposeB ? b.shape[1] : b.shape[2]; + const batchDim = a.shape[0]; + const out = backend.makeOutput([batchDim, leftDim, rightDim], a.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); + const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); + wasmBatchMatMul(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, transposeA, transposeB, outId); + return out; + } + const batchMatMulConfig = { + kernelName: tfjsCore.BatchMatMul, + backendName: 'wasm', + setupFunc: setup$4, + kernelFunc: batchMatMul + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function cast(args) { + const { inputs: { x }, attrs: { dtype }, backend } = args; + const out = backend.makeOutput(x.shape, dtype); + const inVals = backend.typedArrayFromHeap(x); + const outVals = backend.typedArrayFromHeap(out); + outVals.set(inVals); + return out; + } + const castConfig = { + kernelName: tfjsCore.Cast, + backendName: 'wasm', + kernelFunc: cast, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmClip; + function setup$5(backend) { + wasmClip = backend.wasm.cwrap(tfjsCore.ClipByValue, null /* void */, [ + 'number', + 'number', + 'number', + 'number' // out_id + ]); + } + function clip(args) { + const { inputs, backend, attrs } = args; + const { x } = inputs; + const { clipValueMin, clipValueMax } = attrs; + const xId = backend.dataIdMap.get(x.dataId).id; + const out = backend.makeOutput(x.shape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmClip(xId, clipValueMin, clipValueMax, outId); + return out; + } + const clipByValueConfig = { + kernelName: tfjsCore.ClipByValue, + backendName: 'wasm', + setupFunc: setup$5, + kernelFunc: clip + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function concat(args) { + const { inputs, backend } = args; + const axis = tfjsCore.util.parseAxisParam(args.attrs.axis, inputs[0].shape)[0]; + const outShape = tfjsCore.backend_util.computeOutShape(inputs.map(t => t.shape), axis); + const out = backend.makeOutput(outShape, inputs[0].dtype); + const batchDim = tfjsCore.util.sizeFromShape(inputs[0].shape.slice(0, axis)); + let sumInnerDims = 0; + const innerDims = inputs.map(input => { + const innerDim = tfjsCore.util.sizeFromShape(input.shape.slice(axis)); + sumInnerDims += innerDim; + return innerDim; + }); + const inVals = inputs.map(input => backend.typedArrayFromHeap(input)); + const outVals = backend.typedArrayFromHeap(out); + for (let b = 0; b < batchDim; b++) { + let outOffset = b * sumInnerDims; + for (let i = 0; i < inVals.length; i++) { + const innerDim = innerDims[i]; + const inOffset = b * innerDim; + const vals = inVals[i].subarray(inOffset, inOffset + innerDim); + outVals.set(vals, outOffset); + outOffset += innerDim; + } + } + return out; + } + const concatConfig = { + kernelName: tfjsCore.Concat, + backendName: 'wasm', + kernelFunc: concat, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmConv2d; + function setup$6(backend) { + wasmConv2d = backend.wasm.cwrap(tfjsCore.Conv2D, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function conv2d(args) { + const { inputs, attrs, backend } = args; + const { x, filter } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const filterId = backend.dataIdMap.get(filter.dataId).id; + const { strides, dilations, pad, dimRoundingMode, dataFormat } = attrs; + const $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat); + const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const dilationHeight = convInfo.dilationHeight; + const dilationWidth = convInfo.dilationWidth; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const inputChannels = convInfo.inChannels; + const outputChannels = convInfo.outChannels; + const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; + if (convInfo.dataFormat !== 'channelsLast') { + throw new Error(`wasm backend Conv2D does not support dataFormat:'` + + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmConv2d(xId, x.shape[0], x.shape[1], x.shape[2], filterId, filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); + return out; + } + const conv2DConfig = { + kernelName: tfjsCore.Conv2D, + backendName: 'wasm', + setupFunc: setup$6, + kernelFunc: conv2d + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmConv2DBackpropInput; + function setup$7(backend) { + wasmConv2DBackpropInput = backend.wasm.cwrap(tfjsCore.Conv2DBackpropInput, null, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function conv2DBackpropInput(args) { + const { backend, inputs, attrs } = args; + const { dy, filter } = inputs; + const { strides, pad, dataFormat, dimRoundingMode, inputShape } = attrs; + const dilations = 1; + const $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat); + const convInfo = tfjsCore.backend_util.computeConv2DInfo(inputShape, filter.shape, strides, dilations, pad, dimRoundingMode, false /* depthwise */, $dataFormat); + const { batchSize, filterHeight, filterWidth, inChannels, inHeight, inWidth, outChannels, outHeight, outWidth, strideHeight, strideWidth } = convInfo; + const topPad = filterHeight - 1 - convInfo.padInfo.top; + const leftPad = filterWidth - 1 - convInfo.padInfo.left; + const isChannelsLast = convInfo.dataFormat === 'channelsLast'; + const dxStrides = tfjsCore.util.computeStrides(convInfo.inShape); + const dyStrides = tfjsCore.util.computeStrides(dy.shape); + const [fltS0, fltS1, fltS2] = tfjsCore.util.computeStrides(filter.shape); + const xBatchStride = dxStrides[0]; + const xRowStride = isChannelsLast ? dxStrides[1] : dxStrides[2]; + const xColStride = isChannelsLast ? dxStrides[2] : 1; + const xChannelStride = isChannelsLast ? 1 : dxStrides[1]; + const yBatchStride = dyStrides[0]; + const yRowStride = isChannelsLast ? dyStrides[1] : dyStrides[2]; + const yColStride = isChannelsLast ? dyStrides[2] : 1; + const yChannelStride = isChannelsLast ? 1 : dyStrides[1]; + const out = backend.makeOutput(convInfo.inShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const dyId = backend.dataIdMap.get(dy.dataId).id; + const filterId = backend.dataIdMap.get(filter.dataId).id; + wasmConv2DBackpropInput(dyId, filterId, batchSize, filterHeight, filterWidth, inHeight, inWidth, inChannels, outHeight, outWidth, outChannels, strideHeight, strideWidth, topPad, leftPad, fltS0, fltS1, fltS2, xBatchStride, xRowStride, xColStride, xChannelStride, yBatchStride, yRowStride, yColStride, yChannelStride, outId); + return out; + } + const conv2DBackpropInputConfig = { + kernelName: tfjsCore.Conv2DBackpropInput, + backendName: 'wasm', + setupFunc: setup$7, + kernelFunc: conv2DBackpropInput + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const cosConfig = createUnaryKernelConfig(tfjsCore.Cos); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // Must match enum in CropAndResize.cc + var InterpolationMethod; + (function (InterpolationMethod) { + InterpolationMethod[InterpolationMethod["bilinear"] = 0] = "bilinear"; + InterpolationMethod[InterpolationMethod["nearest"] = 1] = "nearest"; + })(InterpolationMethod || (InterpolationMethod = {})); + let wasmCropAndResize; + function setup$8(backend) { + wasmCropAndResize = backend.wasm.cwrap(tfjsCore.CropAndResize, null /*void*/, [ + 'number', + 'number', + 'number', + 'number', + 'array', + 'number', + 'number', + 'number', + 'number', + 'number' // out id + ]); + } + function cropAndResize(args) { + const { backend, inputs, attrs } = args; + const { method, extrapolationValue, cropSize } = attrs; + const { image, boxes, boxInd } = inputs; + const numBoxes = boxes.shape[0]; + const [cropHeight, cropWidth] = cropSize; + const outShape = [numBoxes, cropHeight, cropWidth, image.shape[3]]; + let imagesData = backend.dataIdMap.get(image.dataId); + let castedData; + if (image.dtype !== 'float32') { + castedData = cast({ backend, inputs: { x: image }, attrs: { dtype: 'float32' } }); + imagesData = backend.dataIdMap.get(castedData.dataId); + } + const imagesId = imagesData.id; + const boxesId = backend.dataIdMap.get(boxes.dataId).id; + const boxIndId = backend.dataIdMap.get(boxInd.dataId).id; + const out = backend.makeOutput(outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const imagesShapeBytes = new Uint8Array(new Int32Array(image.shape).buffer); + wasmCropAndResize(imagesId, boxesId, boxIndId, numBoxes, imagesShapeBytes, cropHeight, cropWidth, InterpolationMethod[method], extrapolationValue, outId); + if (castedData != null) { + backend.disposeData(castedData.dataId); + } + return out; + } + const cropAndResizeConfig = { + kernelName: tfjsCore.CropAndResize, + backendName: 'wasm', + setupFunc: setup$8, + kernelFunc: cropAndResize + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmDepthwiseConv2d; + function setup$9(backend) { + wasmDepthwiseConv2d = + backend.wasm.cwrap(tfjsCore.DepthwiseConv2dNative, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function depthwiseConv2d(args) { + const { inputs, attrs, backend } = args; + const { x, filter } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const filterId = backend.dataIdMap.get(filter.dataId).id; + const { strides, dilations, pad, dimRoundingMode } = attrs; + const $dilations = dilations == null ? [1, 1] : dilations; + const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, $dilations, pad, dimRoundingMode, true /* depthwise */); + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const dilationHeight = convInfo.dilationHeight; + const dilationWidth = convInfo.dilationWidth; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const inputChannels = convInfo.inChannels; + const outputChannels = convInfo.outChannels; + const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; + if (convInfo.dataFormat !== 'channelsLast') { + throw new Error(`wasm backend DepthwiseConv2dNative does not support dataFormat:'` + + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmDepthwiseConv2d(xId, x.shape[0], x.shape[1], x.shape[2], filterId, filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); + return out; + } + const depthwiseConv2DNativeConfig = { + kernelName: tfjsCore.DepthwiseConv2dNative, + backendName: 'wasm', + setupFunc: setup$9, + kernelFunc: depthwiseConv2d + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$1 = true; + const divConfig = createBinaryKernelConfig(tfjsCore.Div, supportsFullBroadcast$1); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$2 = false; + const equalConfig = createBinaryKernelConfig(tfjsCore.Equal, supportsFullBroadcast$2, 'bool'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const expConfig = createUnaryKernelConfig(tfjsCore.Exp); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function fill(args) { + const { attrs: { shape, value, dtype }, backend } = args; + const out = backend.makeOutput(shape, dtype); + const outVals = backend.typedArrayFromHeap(out); + outVals.fill(value); + return out; + } + const fillConfig = { + kernelName: tfjsCore.Fill, + backendName: 'wasm', + kernelFunc: fill, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$3 = false; + const floorDivConfig = createBinaryKernelConfig(tfjsCore.FloorDiv, supportsFullBroadcast$3); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmBatchNorm; + function setup$a(backend) { + wasmBatchNorm = backend.wasm.cwrap(tfjsCore.FusedBatchNorm, null /* void */, ['number', 'number', 'number', 'number', 'number', 'number', 'number']); + } + function fusedBatchNorm(args) { + const { backend, inputs, attrs } = args; + const { varianceEpsilon } = attrs; + const { x, mean, variance, offset, scale } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const meanId = backend.dataIdMap.get(mean.dataId).id; + const varianceId = backend.dataIdMap.get(variance.dataId).id; + const offsetId = offset != null ? backend.dataIdMap.get(offset.dataId).id : 0; + const scaleId = scale != null ? backend.dataIdMap.get(scale.dataId).id : 0; + const out = backend.makeOutput(x.shape, x.dtype); + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(x.shape) === 0) { + return out; + } + const outId = backend.dataIdMap.get(out.dataId).id; + wasmBatchNorm(xId, meanId, varianceId, offsetId, scaleId, varianceEpsilon, outId); + return out; + } + const fusedBatchNormConfig = { + kernelName: tfjsCore.FusedBatchNorm, + backendName: 'wasm', + setupFunc: setup$a, + kernelFunc: fusedBatchNorm + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFusedConv2d; + function setup$b(backend) { + wasmFusedConv2d = backend.wasm.cwrap(tfjsCore.FusedConv2D, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function fusedConv2d(args) { + const { inputs, attrs, backend } = args; + const { x, filter, bias, preluActivationWeights } = inputs; + const { strides, pad, dilations, dataFormat, dimRoundingMode, activation } = attrs; + const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode); + const fusedActivation = FusableActivation[activation]; + if (fusedActivation == null) { + throw new Error(`${activation} activation not yet supported for FusedConv2D ` + + `in the wasm backend.`); + } + const xId = backend.dataIdMap.get(x.dataId).id; + const filterId = backend.dataIdMap.get(filter.dataId).id; + const outputChannels = convInfo.outChannels; + let biasId = 0; + if (bias != null) { + const biasData = backend.dataIdMap.get(bias.dataId); + if (biasData.shape.length !== 1) { + throw new Error(`FusedConv2D only supports rank-1 bias but got ` + + `rank ${biasData.shape.length}.`); + } + if (biasData.shape[0] !== outputChannels) { + throw new Error(`FusedConv2D bias shape (${biasData.shape}) does not ` + + `match the number of output channels (${outputChannels})`); + } + biasId = biasData.id; + } + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const dilationHeight = convInfo.dilationHeight; + const dilationWidth = convInfo.dilationWidth; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const inputChannels = convInfo.inChannels; + const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; + const batchSize = convInfo.batchSize; + const inHeight = convInfo.inHeight; + const inWidth = convInfo.inWidth; + if (dataFormat !== 'NHWC') { + throw new Error(`wasm backend FusedConv2D does not support dataFormat:'` + + `${dataFormat}'. Please use 'NHWC'.`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const preluActivationWeightsId = preluActivationWeights == null ? + 0 : + backend.dataIdMap.get(preluActivationWeights.dataId).id; + wasmFusedConv2d(xId, batchSize, inHeight, inWidth, filterId, filterHeight, filterWidth, biasId, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, fusedActivation, preluActivationWeightsId, outId); + return out; + } + const fusedConv2DConfig = { + kernelName: tfjsCore.FusedConv2D, + backendName: 'wasm', + setupFunc: setup$b, + kernelFunc: fusedConv2d + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFusedDepthwiseConv2d; + function setup$c(backend) { + wasmFusedDepthwiseConv2d = + backend.wasm.cwrap(tfjsCore.FusedDepthwiseConv2D, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function fusedDepthwiseConv2d(args) { + const { inputs, attrs, backend } = args; + const { x, filter, bias, preluActivationWeights } = inputs; + const { strides, pad, dilations, dataFormat, dimRoundingMode, activation } = attrs; + const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, true /* depthwise */); + const fusedActivation = FusableActivation[activation]; + if (fusedActivation == null) { + throw new Error(`${activation} activation not yet supported for FusedDepthwiseConv2D ` + + `in the wasm backend.`); + } + const xId = backend.dataIdMap.get(x.dataId).id; + const filterId = backend.dataIdMap.get(filter.dataId).id; + const outputChannels = convInfo.outChannels; + let biasId = 0; + if (bias != null) { + const biasData = backend.dataIdMap.get(bias.dataId); + if (biasData.shape.length !== 1) { + throw new Error(`FusedDepthwiseConv2D only supports rank-1 bias but got ` + + `rank ${biasData.shape.length}.`); + } + if (biasData.shape[0] !== outputChannels) { + throw new Error(`FusedDepthwiseConv2D bias shape (${biasData.shape}) does not ` + + `match the number of output channels (${outputChannels})`); + } + biasId = biasData.id; + } + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const dilationHeight = convInfo.dilationHeight; + const dilationWidth = convInfo.dilationWidth; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const inputChannels = convInfo.inChannels; + const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; + const batchSize = convInfo.batchSize; + const inHeight = convInfo.inHeight; + const inWidth = convInfo.inWidth; + if (dataFormat !== 'NHWC') { + throw new Error(`wasm backend FusedDepthwiseConv2D does not support dataFormat:'` + + `${dataFormat}'. Please use 'NHWC'.`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const preluActivationWeightsId = preluActivationWeights == null ? + 0 : + backend.dataIdMap.get(preluActivationWeights.dataId).id; + wasmFusedDepthwiseConv2d(xId, batchSize, inHeight, inWidth, filterId, filterHeight, filterWidth, biasId, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, fusedActivation, preluActivationWeightsId, outId); + return out; + } + const fusedDepthwiseConv2DConfig = { + kernelName: tfjsCore.FusedDepthwiseConv2D, + backendName: 'wasm', + setupFunc: setup$c, + kernelFunc: fusedDepthwiseConv2d + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmGatherNd; + function setup$d(backend) { + wasmGatherNd = backend.wasm.cwrap(tfjsCore.GatherNd, null /*void*/, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'array', + 'number' // outId + ]); + } + function gatherNd(args) { + const { backend, inputs } = args; + const { params, indices } = inputs; + const [resultShape, numSlices, sliceSize, strides] = tfjsCore.gather_util.prepareAndValidate(params, indices); + const out = backend.makeOutput(resultShape, params.dtype); + if (numSlices === 0) { + return out; + } + const indicesShape = indices.shape; + const sliceRank = indicesShape[indicesShape.length - 1]; + const xData = backend.dataIdMap.get(params.dataId); + const xId = xData.id; + const indicesData = backend.dataIdMap.get(indices.dataId); + const indicesId = indicesData.id; + const stridesBytes = new Uint8Array(new Int32Array(strides).buffer); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmGatherNd(xId, CppDType[params.dtype], indicesId, numSlices, sliceRank, sliceSize, stridesBytes, outId); + return out; + } + const gatherNdConfig = { + kernelName: tfjsCore.GatherNd, + backendName: 'wasm', + setupFunc: setup$d, + kernelFunc: gatherNd + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmGather; + function setup$e(backend) { + wasmGather = backend.wasm.cwrap('Gather', null /*void*/, [ + 'number', + 'number', + 'array', + 'number', + 'number', + 'number', + 'array', + 'number' // outId + ]); + } + function gatherV2(args) { + const { backend, inputs, attrs } = args; + const { x, indices } = inputs; + const { axis } = attrs; + const newShape = x.shape.slice(); + newShape[axis] = tfjsCore.util.sizeFromShape(indices.shape); + const stridesSize = x.shape.length - 1; + const out = backend.makeOutput(newShape, x.dtype); + if (tfjsCore.util.sizeFromShape(x.shape) === 0) { + return out; + } + const xData = backend.dataIdMap.get(x.dataId); + const xId = xData.id; + const indicesData = backend.dataIdMap.get(indices.dataId); + const indicesId = indicesData.id; + const outId = backend.dataIdMap.get(out.dataId).id; + const xStridesBytes = new Uint8Array(new Int32Array(tfjsCore.util.computeStrides(x.shape)).buffer); + const outStridesBytes = new Uint8Array(new Int32Array(tfjsCore.util.computeStrides(newShape)).buffer); + wasmGather(xId, CppDType[x.dtype], xStridesBytes, stridesSize, indicesId, axis, outStridesBytes, outId); + // reshape + const parsedAxis = tfjsCore.util.parseAxisParam(axis, x.shape)[0]; + const shapeInfo = tfjsCore.backend_util.segment_util.collectGatherOpShapeInfo(x, indices, parsedAxis); + out.shape = shapeInfo.outputShape; + return out; + } + const gatherV2Config = { + kernelName: tfjsCore.GatherV2, + backendName: 'wasm', + setupFunc: setup$e, + kernelFunc: gatherV2 + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$4 = false; + const greaterConfig = createBinaryKernelConfig(tfjsCore.Greater, supportsFullBroadcast$4, 'bool'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$5 = false; + const greaterEqualConfig = createBinaryKernelConfig(tfjsCore.GreaterEqual, supportsFullBroadcast$5, 'bool'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$6 = false; + const lessConfig = createBinaryKernelConfig(tfjsCore.Less, supportsFullBroadcast$6, 'bool'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$7 = false; + const lessEqualConfig = createBinaryKernelConfig(tfjsCore.LessEqual, supportsFullBroadcast$7, 'bool'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const logConfig = createUnaryKernelConfig(tfjsCore.Log); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$8 = false; + const logicalAndConfig = createBinaryKernelConfig(tfjsCore.LogicalAnd, supportsFullBroadcast$8, 'bool'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmMax; + function setup$f(backend) { + wasmMax = backend.wasm.cwrap(tfjsCore.Max, null /*void*/, ['number, number, number']); + } + function max(args) { + const { backend, inputs, attrs } = args; + const { reductionIndices: axis, keepDims } = attrs; + const { x } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + let inputId = xId; + let input = x; + const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); + if (inputWasTransposed) { + const transposedId = backend.dataIdMap.get(transposed.dataId).id; + input = transposed; + inputId = transposedId; + } + const inputRank = input.shape.length; + tfjsCore.backend_util.assertAxesAreInnerMostDims('max', axes, inputRank); + const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, axes); + const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); + const out = backend.makeOutput(outShape, x.dtype); + if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { + const outId = backend.dataIdMap.get(out.dataId).id; + wasmMax(inputId, reduceSize, outId); + } + if (inputWasTransposed) { + // dispose of the transposed tensor. + backend.disposeData(transposed.dataId); + } + if (keepDims) { + // reshape + const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); + out.shape = newShape; + } + return out; + } + const maxConfig = { + kernelName: tfjsCore.Max, + backendName: 'wasm', + setupFunc: setup$f, + kernelFunc: max + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$9 = false; + const maximumConfig = createBinaryKernelConfig(tfjsCore.Maximum, supportsFullBroadcast$9); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmMaxPool; + function setup$g(backend) { + wasmMaxPool = backend.wasm.cwrap(tfjsCore.MaxPool, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function maxPool(args) { + const { inputs, attrs, backend } = args; + const x = inputs.x; + const xId = backend.dataIdMap.get(x.dataId).id; + const { filterSize, strides, pad, dimRoundingMode } = attrs; + const convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const dilationHeight = convInfo.dilationHeight; + const dilationWidth = convInfo.dilationWidth; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const inputChannels = convInfo.inChannels; + const outputChannels = convInfo.outChannels; + if (convInfo.dataFormat !== 'channelsLast') { + throw new Error(`wasm backend does not support dataFormat:'` + + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmMaxPool(xId, x.shape[0], x.shape[1], x.shape[2], filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); + return out; + } + const maxPoolConfig = { + kernelName: tfjsCore.MaxPool, + backendName: 'wasm', + setupFunc: setup$g, + kernelFunc: maxPool + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmMin; + function setup$h(backend) { + wasmMin = backend.wasm.cwrap(tfjsCore.Min, null /*void*/, ['number, number, number']); + } + function min(args) { + const { backend, inputs, attrs } = args; + const { axis, keepDims } = attrs; + const { x } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + let inputId = xId; + let input = x; + const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); + if (inputWasTransposed) { + const transposedId = backend.dataIdMap.get(transposed.dataId).id; + if (transposedId !== xId) { + // transpose was not a no-op. We will need to dispose of this + // once we are done. + input = transposed; + inputId = transposedId; + } + } + const inputRank = input.shape.length; + tfjsCore.backend_util.assertAxesAreInnerMostDims('min', axes, inputRank); + const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, axes); + const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); + const out = backend.makeOutput(outShape, input.dtype); + if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { + const outId = backend.dataIdMap.get(out.dataId).id; + wasmMin(inputId, reduceSize, outId); + } + if (inputWasTransposed) { + // dispose of the transposed tensor. + backend.disposeData(transposed.dataId); + } + if (keepDims) { + // reshape + const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); + out.shape = newShape; + } + return out; + } + const minConfig = { + kernelName: tfjsCore.Min, + backendName: 'wasm', + setupFunc: setup$h, + kernelFunc: min + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$a = false; + const minimumConfig = createBinaryKernelConfig(tfjsCore.Minimum, supportsFullBroadcast$a); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$b = true; + const multiplyConfig = createBinaryKernelConfig(tfjsCore.Multiply, supportsFullBroadcast$b); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const negateConfig = createUnaryKernelConfig(tfjsCore.Negate); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Parse the result of the c++ method, which has the shape equivalent to + * `Result`. + */ + function parseResultStruct(backend, resOffset) { + const result = new Int32Array(backend.wasm.HEAPU8.buffer, resOffset, 4); + const pSelectedIndices = result[0]; + const selectedSize = result[1]; + const pSelectedScores = result[2]; + const pValidOutputs = result[3]; + // Since the result was allocated on the heap, we have to delete it. + backend.wasm._free(resOffset); + return { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs }; + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$2; + function setup$i(backend) { + wasmFunc$2 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV3, 'number', // Result* + [ + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function kernelFunc(args) { + const { backend, inputs, attrs } = args; + const { iouThreshold, maxOutputSize, scoreThreshold } = attrs; + const { boxes, scores } = inputs; + const boxesId = backend.dataIdMap.get(boxes.dataId).id; + const scoresId = backend.dataIdMap.get(scores.dataId).id; + const resOffset = wasmFunc$2(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold); + const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); + // Since we are not using scores for V3, we have to delete it from the heap. + backend.wasm._free(pSelectedScores); + backend.wasm._free(pValidOutputs); + const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); + return selectedIndicesTensor; + } + const nonMaxSuppressionV3Config = { + kernelName: tfjsCore.NonMaxSuppressionV3, + backendName: 'wasm', + setupFunc: setup$i, + kernelFunc: kernelFunc, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$3; + function setup$j(backend) { + wasmFunc$3 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV4, 'number', // Result* + [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'bool', + ]); + } + function nonMaxSuppressionV4(args) { + const { backend, inputs, attrs } = args; + const { iouThreshold, maxOutputSize, scoreThreshold, padToMaxOutputSize } = attrs; + const { boxes, scores } = inputs; + const boxesId = backend.dataIdMap.get(boxes.dataId).id; + const scoresId = backend.dataIdMap.get(scores.dataId).id; + const resOffset = wasmFunc$3(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize); + const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); + // Since we are not using scores for V4, we have to delete it from the heap. + backend.wasm._free(pSelectedScores); + const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); + const validOutputsTensor = backend.makeOutput([], 'int32', pValidOutputs); + return [selectedIndicesTensor, validOutputsTensor]; + } + const nonMaxSuppressionV4Config = { + kernelName: tfjsCore.NonMaxSuppressionV4, + backendName: 'wasm', + setupFunc: setup$j, + kernelFunc: nonMaxSuppressionV4, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$4; + function setup$k(backend) { + wasmFunc$4 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV5, 'number', // Result* + [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function kernelFunc$1(args) { + const { backend, inputs, attrs } = args; + const { iouThreshold, maxOutputSize, scoreThreshold, softNmsSigma } = attrs; + const { boxes, scores } = inputs; + const boxesId = backend.dataIdMap.get(boxes.dataId).id; + const scoresId = backend.dataIdMap.get(scores.dataId).id; + const resOffset = wasmFunc$4(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma); + const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); + // Since we are not using validOutputs for V5, we have to delete it from the + // heap. + backend.wasm._free(pValidOutputs); + const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); + const selectedScoresTensor = backend.makeOutput([selectedSize], 'float32', pSelectedScores); + return [selectedIndicesTensor, selectedScoresTensor]; + } + const nonMaxSuppressionV5Config = { + kernelName: tfjsCore.NonMaxSuppressionV5, + backendName: 'wasm', + setupFunc: setup$k, + kernelFunc: kernelFunc$1, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$c = false; + const notEqualConfig = createBinaryKernelConfig(tfjsCore.NotEqual, supportsFullBroadcast$c, 'bool'); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmOneHot; + function setup$l(backend) { + wasmOneHot = backend.wasm.cwrap(tfjsCore.OneHot, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number' // out_id + ]); + } + function oneHot(args) { + const { inputs, backend, attrs } = args; + const { indices } = inputs; + const { depth, onValue, offValue } = attrs; + const out = backend.makeOutput([...indices.shape, depth], 'int32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const indicesData = backend.dataIdMap.get(indices.dataId); + const indicesId = indicesData.id; + wasmOneHot(indicesId, depth, onValue, offValue, outId); + return out; + } + const oneHotConfig = { + kernelName: tfjsCore.OneHot, + backendName: 'wasm', + setupFunc: setup$l, + kernelFunc: oneHot, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function onesLike(args) { + const { inputs: { x }, backend } = args; + const out = backend.makeOutput(x.shape, x.dtype); + const outVals = backend.typedArrayFromHeap(out); + outVals.fill(1); + return out; + } + const onesLikeConfig = { + kernelName: tfjsCore.OnesLike, + backendName: 'wasm', + kernelFunc: onesLike, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmPadV2; + function setup$m(backend) { + wasmPadV2 = backend.wasm.cwrap(tfjsCore.PadV2, null /* void */, [ + 'number', + 'array', + 'number', + 'number', + 'array', + 'array', + 'number', + 'number', + ]); + } + function pad(args) { + const { inputs: { x }, backend, attrs: { paddings, constantValue } } = args; + const outShape = paddings.map((p, i) => p[0] /* beforePad */ + x.shape[i] + p[1] /* afterPad */); + const xId = backend.dataIdMap.get(x.dataId).id; + const out = backend.makeOutput(outShape, x.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); + const prePaddingsFlat = paddings.map(padTuple => padTuple[0]); + const postPaddingsFlat = paddings.map(padTuple => padTuple[1]); + const prePaddingsBytes = new Uint8Array(new Int32Array(prePaddingsFlat).buffer); + const postPaddingsBytes = new Uint8Array(new Int32Array(postPaddingsFlat).buffer); + wasmPadV2(xId, xShapeBytes, x.shape.length, CppDType[x.dtype], prePaddingsBytes, postPaddingsBytes, constantValue, outId); + return out; + } + const padV2Config = { + kernelName: tfjsCore.PadV2, + backendName: 'wasm', + kernelFunc: pad, + setupFunc: setup$m + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$d = false; + const powConfig = createBinaryKernelConfig(tfjsCore.Pow, supportsFullBroadcast$d); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmPrelu; + function setup$n(backend) { + wasmPrelu = backend.wasm.cwrap(tfjsCore.Prelu, null /* void */, [ + 'number', + 'number', + 'number' // out_id + ]); + } + function prelu(args) { + const { inputs, backend } = args; + const { x, alpha } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const weightsId = backend.dataIdMap.get(alpha.dataId).id; + const out = backend.makeOutput(x.shape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmPrelu(xId, weightsId, outId); + return out; + } + const preluConfig = { + kernelName: tfjsCore.Prelu, + backendName: 'wasm', + setupFunc: setup$n, + kernelFunc: prelu + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const reluConfig = createUnaryKernelConfig(tfjsCore.Relu); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const relu6Config = createUnaryKernelConfig(tfjsCore.Relu6); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function reshape(args) { + const { inputs, attrs } = args; + const { x } = inputs; + const { shape } = attrs; + return { dataId: x.dataId, shape, dtype: x.dtype }; + } + const reshapeConfig = { + kernelName: tfjsCore.Reshape, + backendName: 'wasm', + kernelFunc: reshape, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmResizeBilinear; + function setup$o(backend) { + wasmResizeBilinear = backend.wasm.cwrap(tfjsCore.ResizeBilinear, null /*void*/, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number' // outId + ]); + } + function resizeBilinear(args) { + const { backend, inputs, attrs } = args; + const { images } = inputs; + const { alignCorners, size } = attrs; + const [newHeight, newWidth] = size; + const [batch, oldHeight, oldWidth, numChannels] = images.shape; + const outShape = [batch, newHeight, newWidth, numChannels]; + let xData = backend.dataIdMap.get(images.dataId); + let castedData; + if (xData.dtype !== 'float32') { + castedData = + cast({ backend, inputs: { x: images }, attrs: { dtype: 'float32' } }); + xData = backend.dataIdMap.get(castedData.dataId); + } + const xId = xData.id; + const out = backend.makeOutput(outShape, 'float32'); + if (tfjsCore.util.sizeFromShape(images.shape) === 0) { + return out; + } + const outId = backend.dataIdMap.get(out.dataId).id; + wasmResizeBilinear(xId, batch, oldHeight, oldWidth, numChannels, newHeight, newWidth, alignCorners ? 1 : 0, outId); + if (castedData != null) { + backend.disposeData(castedData.dataId); + } + return out; + } + const resizeBilinearConfig = { + kernelName: tfjsCore.ResizeBilinear, + backendName: 'wasm', + setupFunc: setup$o, + kernelFunc: resizeBilinear + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmReverse; + function setup$p(backend) { + wasmReverse = backend.wasm.cwrap(tfjsCore.Reverse, null, [ + 'number', + 'array', + 'number', + 'array', + 'number', + 'number' // out_id + ]); + } + function reverse(args) { + const { inputs, backend, attrs } = args; + const { x } = inputs; + const { dims } = attrs; + const axes = tfjsCore.util.parseAxisParam(dims, x.shape); + if (x.shape.length === 0) { + return identity({ inputs: { x }, backend }); + } + const out = backend.makeOutput(x.shape, x.dtype); + const xId = backend.dataIdMap.get(x.dataId).id; + const outId = backend.dataIdMap.get(out.dataId).id; + const axesBytes = new Uint8Array(new Int32Array(axes).buffer); + const outShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); + wasmReverse(xId, axesBytes, axes.length, outShapeBytes, x.shape.length, outId); + return reshape({ inputs: { x: out }, attrs: { shape: x.shape }, backend }); + } + const reverseConfig = { + kernelName: tfjsCore.Reverse, + backendName: 'wasm', + kernelFunc: reverse, + setupFunc: setup$p + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmRotate; + function setup$q(backend) { + wasmRotate = backend.wasm.cwrap(tfjsCore.RotateWithOffset, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'array', + 'number', + 'number', + ]); + } + function rotateWithOffset(args) { + const { inputs, backend, attrs } = args; + const { image } = inputs; + const { radians, fillValue, center } = attrs; + const out = backend.makeOutput(image.shape, image.dtype); + const imageId = backend.dataIdMap.get(image.dataId).id; + const outId = backend.dataIdMap.get(out.dataId).id; + const [batch, imageHeight, imageWidth, numChannels] = image.shape; + const [centerX, centerY] = tfjsCore.backend_util.getImageCenter(center, imageHeight, imageWidth); + const fillIsBlack = fillValue === 0; + const fullOpacityValue = 255; + const fillValues = typeof fillValue === 'number' ? + [fillValue, fillValue, fillValue, fillIsBlack ? 0 : fullOpacityValue] : + [...fillValue, fullOpacityValue]; + const fillBytes = new Uint8Array(new Int32Array(fillValues).buffer); + wasmRotate(imageId, batch, imageHeight, imageWidth, numChannels, radians, centerX, centerY, fillBytes, fillValues.length, outId); + return out; + } + const rotateWithOffsetConfig = { + kernelName: tfjsCore.RotateWithOffset, + backendName: 'wasm', + kernelFunc: rotateWithOffset, + setupFunc: setup$q + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const rsqrtConfig = createUnaryKernelConfig(tfjsCore.Rsqrt); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmScatterNd; + function setup$r(backend) { + wasmScatterNd = backend.wasm.cwrap(tfjsCore.ScatterNd, null /*void*/, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'array', + 'number', + 'number' // outId + ]); + } + function scatterNd(args) { + const { backend, inputs, attrs } = args; + const { indices, updates } = inputs; + const { shape } = attrs; + const out = backend.makeOutput(shape, updates.dtype); + if (tfjsCore.util.sizeFromShape(shape) === 0) { + return out; + } + const { sliceRank, numUpdates, sliceSize, strides, outputSize } = tfjsCore.scatter_util.calculateShapes(updates, indices, shape); + const indicesData = backend.dataIdMap.get(indices.dataId); + const indicesId = indicesData.id; + const updatesData = backend.dataIdMap.get(updates.dataId); + const updatesId = updatesData.id; + const stridesBytes = new Uint8Array(new Int32Array(strides).buffer); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmScatterNd(indicesId, updatesId, CppDType[updates.dtype], sliceRank, numUpdates, sliceSize, stridesBytes, outputSize, outId); + return out; + } + const scatterNdConfig = { + kernelName: tfjsCore.ScatterNd, + backendName: 'wasm', + setupFunc: setup$r, + kernelFunc: scatterNd + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmSelect; + function setup$s(backend) { + wasmSelect = backend.wasm.cwrap(tfjsCore.SelectV2, null, [ + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function select(args) { + const { inputs, backend } = args; + const { condition, t, e } = inputs; + const conditionId = backend.dataIdMap.get(condition.dataId).id; + const tId = backend.dataIdMap.get(t.dataId).id; + const eId = backend.dataIdMap.get(e.dataId).id; + const out = backend.makeOutput(t.shape, t.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + const cRank = condition.shape.length; + const tRank = t.shape.length; + const offset = cRank === 0 || cRank > 1 || tRank === 1 ? + 1 : + tfjsCore.util.sizeFromShape(t.shape.slice(1)); + wasmSelect(conditionId, tId, eId, offset, outId); + return out; + } + const selectV2Config = { + kernelName: tfjsCore.SelectV2, + backendName: 'wasm', + kernelFunc: select, + setupFunc: setup$s + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$5; + function setup$t(backend) { + wasmFunc$5 = backend.wasm.cwrap(tfjsCore.Sigmoid, null /* void */, ['number', 'number']); + } + function sigmoid(args) { + const { backend, inputs: { x } } = args; + const xId = backend.dataIdMap.get(x.dataId).id; + const out = backend.makeOutput(x.shape, x.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(out.shape) === 0) { + return out; + } + wasmFunc$5(xId, outId); + return out; + } + const sigmoidConfig = { + kernelName: 'Sigmoid', + backendName: 'wasm', + setupFunc: setup$t, + kernelFunc: sigmoid + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const sinConfig = createUnaryKernelConfig(tfjsCore.Sin); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function slice(args) { + const { inputs: { x }, attrs: { begin, size }, backend } = args; + const [begin_, size_] = tfjsCore.slice_util.parseSliceParams(x, begin, size); + const isContinous = tfjsCore.slice_util.isSliceContinous(x.shape, begin_, size_); + const xVals = backend.typedArrayFromHeap(x); + const out = backend.makeOutput(size_, x.dtype); + const outVals = backend.typedArrayFromHeap(out); + const xStrides = tfjsCore.util.computeStrides(x.shape); + if (isContinous) { + const flatOffset = tfjsCore.slice_util.computeFlatOffset(begin_, xStrides); + outVals.set(xVals.subarray(flatOffset, flatOffset + tfjsCore.util.sizeFromShape(size_))); + return out; + } + const rank = x.shape.length; + if (rank === 2) { + slice2d(xVals, xStrides[0], outVals, begin_, size_); + } + else if (rank === 3) { + slice3d(xVals, xStrides[0], xStrides[1], outVals, begin_, size_); + } + else if (rank === 4) { + slice4d(xVals, xStrides[0], xStrides[1], xStrides[2], outVals, begin_, size_); + } + else { + genericSliceSlow(xVals, x, outVals, begin_, size_); + } + return out; + } + function slice2d(xVals, xStride, outVals, begin, size) { + let outOffset = 0; + const beginI = begin[0]; + const beginJ = begin[1]; + const endI = beginI + size[0]; + for (let i = beginI; i < endI; i++) { + const xOffset = i * xStride + beginJ; + outVals.set(xVals.subarray(xOffset, xOffset + size[1]), outOffset); + outOffset += size[1]; + } + } + function slice3d(xVals, xStride1, xStride2, outVals, begin, size) { + let outOffset = 0; + const beginI = begin[0]; + const beginJ = begin[1]; + const beginK = begin[2]; + const endI = beginI + size[0]; + const endJ = beginJ + size[1]; + for (let i = beginI; i < endI; i++) { + for (let j = beginJ; j < endJ; j++) { + const xOffset = i * xStride1 + j * xStride2 + beginK; + outVals.set(xVals.subarray(xOffset, xOffset + size[2]), outOffset); + outOffset += size[2]; + } + } + } + function slice4d(xVals, xStride1, xStride2, xStride3, outVals, begin, size) { + let outOffset = 0; + const beginI = begin[0]; + const beginJ = begin[1]; + const beginK = begin[2]; + const endI = beginI + size[0]; + const endJ = beginJ + size[1]; + const endK = beginK + size[2]; + const beginL = begin[3]; + for (let i = beginI; i < endI; i++) { + for (let j = beginJ; j < endJ; j++) { + for (let k = beginK; k < endK; k++) { + const xOffset = i * xStride1 + j * xStride2 + k * xStride3 + beginL; + outVals.set(xVals.subarray(xOffset, xOffset + size[3]), outOffset); + outOffset += size[3]; + } + } + } + } + function genericSliceSlow(xVals, xInfo, outVals, begin, size) { + const outBuf = tfjsCore.buffer(size, xInfo.dtype, outVals); + const xBuf = tfjsCore.buffer(xInfo.shape, xInfo.dtype, xVals); + for (let i = 0; i < outBuf.size; ++i) { + const loc = outBuf.indexToLoc(i); + const xLoc = loc.map((idx, j) => idx + begin[j]); + outVals[i] = xBuf.get(...xLoc); + } + } + const sliceConfig = { + kernelName: tfjsCore.Slice, + backendName: 'wasm', + kernelFunc: slice, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$6; + function setup$u(backend) { + wasmFunc$6 = backend.wasm.cwrap(tfjsCore.Softmax, null /* void */, [ + 'number', + 'number', + 'number', + 'number' // batch + ]); + } + function softmax(args) { + const { backend, inputs: { logits }, attrs: { dim } } = args; + const xId = backend.dataIdMap.get(logits.dataId).id; + const out = backend.makeOutput(logits.shape, logits.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + const channels = logits.shape[dim]; + const batch = tfjsCore.util.sizeFromShape(logits.shape) / channels; + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(out.shape) === 0) { + return out; + } + wasmFunc$6(xId, outId, channels, batch); + return out; + } + const softmaxConfig = { + kernelName: tfjsCore.Softmax, + backendName: 'wasm', + setupFunc: setup$u, + kernelFunc: softmax + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function split(args) { + const { inputs, attrs, backend } = args; + const { x } = inputs; + const { numOrSizeSplits, axis } = attrs; + const $axis = tfjsCore.util.parseAxisParam(axis, x.shape)[0]; + const splitSizes = tfjsCore.backend_util.prepareSplitSize(x, numOrSizeSplits, axis); + const begin = new Array(x.shape.length).fill(0); + const size = x.shape.slice(); + return splitSizes.map(s => { + const xSliceSize = [...size]; + xSliceSize[$axis] = s; + const xSlice = slice({ inputs: { x }, attrs: { begin, size: xSliceSize }, backend }); + begin[$axis] += s; + return xSlice; + }); + } + const splitVConfig = { + kernelName: tfjsCore.SplitV, + backendName: 'wasm', + kernelFunc: split + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const sqrtConfig = createUnaryKernelConfig(tfjsCore.Sqrt); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const squareConfig = createUnaryKernelConfig(tfjsCore.Square); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$e = true; + const subConfig = createBinaryKernelConfig(tfjsCore.Sub, supportsFullBroadcast$e); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmSum; + function setup$v(backend) { + wasmSum = backend.wasm.cwrap(tfjsCore.Sum, null /*void*/, ['number, number, number']); + } + function sum(args) { + const { backend, inputs, attrs } = args; + const { axis, keepDims } = attrs; + const { x } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + let inputId = xId; + let input = x; + const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); + let reductionAxes = axes; + if (inputWasTransposed) { + const transposedId = backend.dataIdMap.get(transposed.dataId).id; + if (transposedId !== xId) { + // transpose was not a no-op. We will need to dispose of this + // once we are done. + input = transposed; + inputId = transposedId; + reductionAxes = tfjsCore.backend_util.getInnerMostAxes(reductionAxes.length, input.shape.length); + } + } + tfjsCore.backend_util.assertAxesAreInnerMostDims('sum', reductionAxes, input.shape.length); + const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, reductionAxes); + const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); + const out = backend.makeOutput(outShape, input.dtype); + if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { + const outId = backend.dataIdMap.get(out.dataId).id; + wasmSum(inputId, reduceSize, outId); + } + if (inputWasTransposed) { + // dispose of the transposed tensor. + backend.disposeData(transposed.dataId); + } + if (keepDims) { + // reshape + const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); + out.shape = newShape; + } + return out; + } + const sumConfig = { + kernelName: tfjsCore.Sum, + backendName: 'wasm', + setupFunc: setup$v, + kernelFunc: sum + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const tanhConfig = createUnaryKernelConfig(tfjsCore.Tanh); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmTile; + function setup$w(backend) { + wasmTile = backend.wasm.cwrap(tfjsCore.Tile, null /* void */, [ + 'number', + 'array', + 'number', + 'array', + 'number', + 'number' // out_id + ]); + } + function tile(args) { + const { inputs, backend, attrs } = args; + const { x } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const { reps } = attrs; + const newShape = new Array(x.shape.length); + for (let i = 0; i < newShape.length; i++) { + newShape[i] = x.shape[i] * reps[i]; + } + const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); + const newShapeBytes = new Uint8Array(new Int32Array(newShape).buffer); + const out = backend.makeOutput(newShape, x.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmTile(xId, xShapeBytes, x.shape.length, newShapeBytes, newShape.length, CppDType[out.dtype], outId); + return out; + } + const tileConfig = { + kernelName: tfjsCore.Tile, + backendName: 'wasm', + setupFunc: setup$w, + kernelFunc: tile + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function unpack(args) { + const { inputs, backend, attrs } = args; + const { value } = inputs; + const { axis } = attrs; + const numOutputs = value.shape[axis]; + const rank = value.shape.length; + const outShape = new Array(rank - 1); + let outIndex = 0; + for (let i = 0; i < rank; i++) { + if (i !== axis) { + outShape[outIndex++] = value.shape[i]; + } + } + const outs = new Array(numOutputs); + const begin = new Array(rank).fill(0); + const size = value.shape.slice(); + size[axis] = 1; + for (let i = 0; i < outs.length; i++) { + begin[axis] = i; + outs[i] = slice({ inputs: { x: value }, attrs: { begin, size }, backend }); + } + return outs.map(({ dataId, dtype }) => ({ dataId, dtype, shape: outShape })); + } + const unpackConfig = { + kernelName: tfjsCore.Unpack, + backendName: 'wasm', + kernelFunc: unpack, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function zerosLike(args) { + const { inputs: { x }, backend } = args; + const out = backend.makeOutput(x.shape, x.dtype); + const outVals = backend.typedArrayFromHeap(out); + outVals.fill(0); + return out; + } + const zerosLikeConfig = { + kernelName: tfjsCore.ZerosLike, + backendName: 'wasm', + kernelFunc: zerosLike, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // List all kernel configs here + const kernelConfigs = [ + absConfig, + addConfig, + addNConfig, + argMaxConfig, + avgPoolConfig, + batchMatMulConfig, + castConfig, + clipByValueConfig, + concatConfig, + conv2DConfig, + conv2DBackpropInputConfig, + cosConfig, + cropAndResizeConfig, + depthwiseConv2DNativeConfig, + divConfig, + equalConfig, + expConfig, + fillConfig, + floorDivConfig, + fusedMatMulConfig, + fusedBatchNormConfig, + fusedConv2DConfig, + fusedDepthwiseConv2DConfig, + gatherNdConfig, + gatherV2Config, + greaterConfig, + greaterEqualConfig, + identityConfig, + lessConfig, + lessEqualConfig, + logConfig, + logicalAndConfig, + maxConfig, + maximumConfig, + maxPoolConfig, + minConfig, + minimumConfig, + multiplyConfig, + negateConfig, + nonMaxSuppressionV3Config, + nonMaxSuppressionV4Config, + nonMaxSuppressionV5Config, + notEqualConfig, + oneHotConfig, + onesLikeConfig, + padV2Config, + powConfig, + preluConfig, + reluConfig, + relu6Config, + reshapeConfig, + resizeBilinearConfig, + reverseConfig, + rotateWithOffsetConfig, + rsqrtConfig, + scatterNdConfig, + selectV2Config, + sigmoidConfig, + sinConfig, + sliceConfig, + softmaxConfig, + splitVConfig, + sqrtConfig, + squareConfig, + subConfig, + sumConfig, + tanhConfig, + tileConfig, + transposeConfig, + unpackConfig, + zerosLikeConfig + ]; + for (const kernelConfig of kernelConfigs) { + tfjsCore.registerKernel(kernelConfig); + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const ENV = tfjsCore.env(); + /** + * True if SIMD is supported. + */ + // From: https://github.com/GoogleChromeLabs/wasm-feature-detect + ENV.registerFlag('WASM_HAS_SIMD_SUPPORT', async () => WebAssembly.validate(new Uint8Array([ + 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, + 2, 1, 0, 10, 9, 1, 7, 0, 65, 0, 253, 15, 26, 11 + ]))); + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var tfjsBackendWasmSimd = createCommonjsModule(function (module, exports) { + var WasmBackendModuleSimd = (function() { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( + function(WasmBackendModuleSimd) { + WasmBackendModuleSimd = WasmBackendModuleSimd || {}; + + var Module=typeof WasmBackendModuleSimd!=="undefined"?WasmBackendModuleSimd:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":152,"maximum":152+0,"element":"anyfunc"});var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023);}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer);}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm-simd.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=exports["memory"];updateGlobalBufferAndViews(wasmMemory.buffer);removeRunDependency();}addRunDependency();function receiveInstantiatedSource(output){receiveInstance(output["instance"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}__ATINIT__.push();function _emscripten_notify_memory_growth(memoryIndex){updateGlobalBufferAndViews(wasmMemory.buffer);}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _exit(status){exit(status);}function _proc_exit(code){_exit(code);}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}var asmLibraryArg={"emscripten_notify_memory_growth":_emscripten_notify_memory_growth,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"proc_exit":_proc_exit,"roundf":_roundf};var asm=createWasm();Module["asm"]=asm;var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["init"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["register_tensor"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["dispose_data"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["dispose"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["Abs"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["Add"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["AddN"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["ArgMax"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["AvgPool"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["BatchMatMul"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["ClipByValue"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["Conv2D"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["Conv2DBackpropInput"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["Cos"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["CropAndResize"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["DepthwiseConv2dNative"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["Div"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["Equal"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["Exp"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["FloorDiv"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["FusedBatchNorm"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["FusedConv2D"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["FusedDepthwiseConv2D"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["Gather"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["GatherNd"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["Greater"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["GreaterEqual"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["Less"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["LessEqual"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["Log"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["LogicalAnd"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["Max"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["MaxPool"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["Maximum"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["Min"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["Minimum"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["Multiply"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["Negate"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["NonMaxSuppressionV3"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["NonMaxSuppressionV4"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["NonMaxSuppressionV5"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["NotEqual"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["OneHot"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["PadV2"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["Pow"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["Prelu"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["Relu"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["Relu6"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["ResizeBilinear"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["Reverse"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["RotateWithOffset"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["Rsqrt"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["ScatterNd"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["SelectV2"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["Sigmoid"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["Sin"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["Softmax"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["Sqrt"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["Square"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["Sub"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["Sum"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["Tanh"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["Tile"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["Transpose"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["_FusedMatMul"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["malloc"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["free"]).apply(null,arguments)};var __start=Module["__start"]=function(){return (__start=Module["__start"]=Module["asm"]["_start"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["stackSave"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["stackAlloc"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["stackRestore"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function callMain(args){var entryFunction=Module["__start"];try{entryFunction();var ret=0;exit(ret,true);}catch(e){if(e instanceof ExitStatus){return}else if(e=="unwind"){noExitRuntime=true;return}else{var toLog=e;if(e&&typeof e==="object"&&e.stack){toLog=[e,e.stack];}err("exception thrown: "+toLog);quit_(1,e);}}finally{}}function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;function exit(status,implicit){if(implicit&&noExitRuntime&&status===0){return}if(noExitRuntime);else{ABORT=true;if(Module["onExit"])Module["onExit"](status);}quit_(status,new ExitStatus(status));}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;noExitRuntime=true;run(); + + + return WasmBackendModuleSimd + } + ); + })(); + module.exports = WasmBackendModuleSimd; + }); + + var tfjsBackendWasm = createCommonjsModule(function (module, exports) { + var WasmBackendModule = (function() { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( + function(WasmBackendModule) { + WasmBackendModule = WasmBackendModule || {}; + + var Module=typeof WasmBackendModule!=="undefined"?WasmBackendModule:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":147,"maximum":147+0,"element":"anyfunc"});var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023);}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer);}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=exports["memory"];updateGlobalBufferAndViews(wasmMemory.buffer);removeRunDependency();}addRunDependency();function receiveInstantiatedSource(output){receiveInstance(output["instance"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}__ATINIT__.push();function _emscripten_notify_memory_growth(memoryIndex){updateGlobalBufferAndViews(wasmMemory.buffer);}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _exit(status){exit(status);}function _proc_exit(code){_exit(code);}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}var asmLibraryArg={"emscripten_notify_memory_growth":_emscripten_notify_memory_growth,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"proc_exit":_proc_exit,"roundf":_roundf};var asm=createWasm();Module["asm"]=asm;var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["init"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["register_tensor"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["dispose_data"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["dispose"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["Abs"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["Add"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["AddN"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["ArgMax"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["AvgPool"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["BatchMatMul"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["ClipByValue"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["Conv2D"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["Conv2DBackpropInput"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["Cos"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["CropAndResize"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["DepthwiseConv2dNative"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["Div"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["Equal"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["Exp"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["FloorDiv"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["FusedBatchNorm"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["FusedConv2D"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["FusedDepthwiseConv2D"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["Gather"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["GatherNd"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["Greater"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["GreaterEqual"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["Less"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["LessEqual"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["Log"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["LogicalAnd"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["Max"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["MaxPool"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["Maximum"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["Min"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["Minimum"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["Multiply"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["Negate"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["NonMaxSuppressionV3"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["NonMaxSuppressionV4"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["NonMaxSuppressionV5"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["NotEqual"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["OneHot"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["PadV2"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["Pow"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["Prelu"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["Relu"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["Relu6"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["ResizeBilinear"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["Reverse"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["RotateWithOffset"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["Rsqrt"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["ScatterNd"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["SelectV2"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["Sigmoid"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["Sin"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["Softmax"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["Sqrt"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["Square"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["Sub"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["Sum"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["Tanh"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["Tile"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["Transpose"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["_FusedMatMul"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["malloc"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["free"]).apply(null,arguments)};var __start=Module["__start"]=function(){return (__start=Module["__start"]=Module["asm"]["_start"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["stackSave"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["stackAlloc"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["stackRestore"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function callMain(args){var entryFunction=Module["__start"];try{entryFunction();var ret=0;exit(ret,true);}catch(e){if(e instanceof ExitStatus){return}else if(e=="unwind"){noExitRuntime=true;return}else{var toLog=e;if(e&&typeof e==="object"&&e.stack){toLog=[e,e.stack];}err("exception thrown: "+toLog);quit_(1,e);}}finally{}}function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;function exit(status,implicit){if(implicit&&noExitRuntime&&status===0){return}if(noExitRuntime);else{ABORT=true;if(Module["onExit"])Module["onExit"](status);}quit_(status,new ExitStatus(status));}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;noExitRuntime=true;run(); + + + return WasmBackendModule + } + ); + })(); + module.exports = WasmBackendModule; + }); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const WASM_PRIORITY = 2; + class BackendWasm extends tfjsCore.KernelBackend { + constructor(wasm) { + super(); + this.wasm = wasm; + // 0 is reserved for null data ids. + this.dataIdNextNumber = 1; + this.wasm.tfjs.init(); + this.dataIdMap = new tfjsCore.DataStorage(this, tfjsCore.engine()); + } + write(values, shape, dtype) { + const dataId = {}; + this.move(dataId, values, shape, dtype); + return dataId; + } + numDataIds() { + return this.dataIdMap.numDataIds(); + } + async time(f) { + const start = tfjsCore.util.now(); + f(); + const kernelMs = tfjsCore.util.now() - start; + return { kernelMs }; + } + move(dataId, values, shape, dtype) { + const id = this.dataIdNextNumber++; + if (dtype === 'string') { + const stringBytes = values; + this.dataIdMap.set(dataId, { id, stringBytes, shape, dtype, memoryOffset: null }); + return; + } + const size = tfjsCore.util.sizeFromShape(shape); + const numBytes = size * tfjsCore.util.bytesPerElement(dtype); + const memoryOffset = this.wasm._malloc(numBytes); + this.dataIdMap.set(dataId, { id, memoryOffset, shape, dtype }); + this.wasm.tfjs.registerTensor(id, size, memoryOffset); + if (values != null) { + this.wasm.HEAPU8.set(new Uint8Array(values.buffer, values.byteOffset, numBytes), memoryOffset); + } + } + async read(dataId) { + return this.readSync(dataId); + } + readSync(dataId) { + const { memoryOffset, dtype, shape, stringBytes } = this.dataIdMap.get(dataId); + if (dtype === 'string') { + return stringBytes; + } + const bytes = this.wasm.HEAPU8.slice(memoryOffset, memoryOffset + tfjsCore.util.sizeFromShape(shape) * tfjsCore.util.bytesPerElement(dtype)); + return typedArrayFromBuffer(bytes.buffer, dtype); + } + disposeData(dataId) { + const data = this.dataIdMap.get(dataId); + this.wasm._free(data.memoryOffset); + this.wasm.tfjs.disposeData(data.id); + this.dataIdMap.delete(dataId); + } + floatPrecision() { + return 32; + } + // Returns the memory offset of a tensor. Useful for debugging and unit + // testing. + getMemoryOffset(dataId) { + return this.dataIdMap.get(dataId).memoryOffset; + } + dispose() { + this.wasm.tfjs.dispose(); + this.wasm = null; + } + memory() { + return { unreliable: false }; + } + /** + * Make a tensor info for the output of an op. If `memoryOffset` is not + * present, this method allocates memory on the WASM heap. If `memoryOffset` + * is present, the memory was allocated elsewhere (in c++) and we just record + * the pointer where that memory lives. + */ + makeOutput(shape, dtype, memoryOffset) { + let dataId; + if (memoryOffset == null) { + dataId = this.write(null /* values */, shape, dtype); + } + else { + dataId = {}; + const id = this.dataIdNextNumber++; + this.dataIdMap.set(dataId, { id, memoryOffset, shape, dtype }); + const size = tfjsCore.util.sizeFromShape(shape); + this.wasm.tfjs.registerTensor(id, size, memoryOffset); + } + return { dataId, shape, dtype }; + } + typedArrayFromHeap({ shape, dtype, dataId }) { + const buffer = this.wasm.HEAPU8.buffer; + const { memoryOffset } = this.dataIdMap.get(dataId); + const size = tfjsCore.util.sizeFromShape(shape); + switch (dtype) { + case 'float32': + return new Float32Array(buffer, memoryOffset, size); + case 'int32': + return new Int32Array(buffer, memoryOffset, size); + case 'bool': + return new Uint8Array(buffer, memoryOffset, size); + default: + throw new Error(`Uknown dtype ${dtype}`); + } + } + } + tfjsCore.registerBackend('wasm', async () => { + const { wasm } = await init(); + return new BackendWasm(wasm); + }, WASM_PRIORITY); + function createInstantiateWasmFunc(path) { + // tslint:disable-next-line:no-any + return (imports, callback) => { + tfjsCore.util.fetch(path, { credentials: 'same-origin' }).then((response) => { + if (!response['ok']) { + imports.env.a(`failed to load wasm binary file at '${path}'`); + } + response.arrayBuffer().then(binary => { + WebAssembly.instantiate(binary, imports).then(output => { + callback(output.instance); + }); + }); + }); + return {}; + }; + } + /** + * Initializes the wasm module and creates the js <--> wasm bridge. + * + * NOTE: We wrap the wasm module in a object with property 'wasm' instead of + * returning Promise to avoid freezing Chrome (last tested + * in Chrome 76). + */ + async function init() { + const simdSupported = await tfjsCore.env().getAsync('WASM_HAS_SIMD_SUPPORT'); + return new Promise((resolve, reject) => { + const factoryConfig = {}; + factoryConfig.locateFile = (path, prefix) => { + if (path.endsWith('.wasm')) { + if (simdSupported) { + return prefix + 'tfjs-backend-wasm-simd.wasm'; + } + return prefix + 'tfjs-backend-wasm.wasm'; + } + if (wasmPath != null) { + if (path.endsWith('.wasm')) { + return wasmPath; + } + } + return prefix + path; + }; + if (wasmPath != null) { + // use wasm instantiateWasm override when system fetch is not available. + // For detail references + // https://github.com/emscripten-core/emscripten/blob/2bca083cbbd5a4133db61fbd74d04f7feecfa907/tests/manual_wasm_instantiate.html#L170 + if (customFetch) { + factoryConfig.instantiateWasm = createInstantiateWasmFunc(wasmPath); + } + } + // const wasm = simdSupported ? tfjsBackendWasmSimd(factoryConfig) : + // tfjsBackendWasm(factoryConfig); + const wasm = tfjsBackendWasm(factoryConfig); + + const voidReturnType = null; + // Using the tfjs namespace to avoid conflict with emscripten's API. + wasm.tfjs = { + init: wasm.cwrap('init', null, []), + registerTensor: wasm.cwrap('register_tensor', null, [ + 'number', + 'number', + 'number', + ]), + disposeData: wasm.cwrap('dispose_data', voidReturnType, ['number']), + dispose: wasm.cwrap('dispose', voidReturnType, []), + }; + let initialized = false; + wasm.onRuntimeInitialized = () => { + initialized = true; + initAborted = false; + resolve({ wasm }); + }; + wasm.onAbort = () => { + if (initialized) { + // Emscripten already called console.warn so no need to double log. + return; + } + if (initAborted) { + // Emscripten calls `onAbort` twice, resulting in double error + // messages. + return; + } + initAborted = true; + const rejectMsg = 'Make sure the server can serve the `.wasm` file relative to the ' + + 'bundled js file. For more details see https://github.com/tensorflow/tfjs/blob/master/tfjs-backend-wasm/README.md#using-bundlers'; + reject({ message: rejectMsg }); + }; + }); + } + function typedArrayFromBuffer(buffer, dtype) { + switch (dtype) { + case 'float32': + return new Float32Array(buffer); + case 'int32': + return new Int32Array(buffer); + case 'bool': + return new Uint8Array(buffer); + default: + throw new Error(`Unknown dtype ${dtype}`); + } + } + let wasmPath = null; + let initAborted = false; + let customFetch = false; + /** + * Sets the path to the `.wasm` file which will be fetched when the wasm + * backend is initialized. See + * https://github.com/tensorflow/tfjs/blob/master/tfjs-backend-wasm/README.md#using-bundlers + * for more details. + * @param path wasm file path or url + * @param usePlatformFetch optional boolean to use platform fetch to download + * the wasm file, default to false. + */ + /** @doc {heading: 'Environment', namespace: 'wasm'} */ + function setWasmPath(path, usePlatformFetch = false) { + if (initAborted) { + throw new Error('The WASM backend was already initialized. Make sure you call ' + + '`setWasmPath()` before you call `tf.setBackend()` or `tf.ready()`'); + } + wasmPath = path; + customFetch = usePlatformFetch; + } + + /** @license See the LICENSE file. */ + // This code is auto-generated, do not modify this file! + const version = '0.0.0'; + + exports.BackendWasm = BackendWasm; + exports.setWasmPath = setWasmPath; + exports.version_wasm = version; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); +//# sourceMappingURL=tf-backend-wasm.js.map diff --git a/e2e/benchmarks/tf-core.js b/e2e/benchmarks/tf-core.js new file mode 100644 index 00000000000..2637d1e2b74 --- /dev/null +++ b/e2e/benchmarks/tf-core.js @@ -0,0 +1,32471 @@ +/** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (global = global || self, factory(global.tf = global.tf || {})); +}(this, (function (exports) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + function __awaiter(thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + } + + function __generator(thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } + } + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // Expects flags from URL in the format ?tfjsflags=FLAG1:1,FLAG2:true. + var TENSORFLOWJS_FLAGS_PREFIX = 'tfjsflags'; + /** + * The environment contains evaluated flags as well as the registered platform. + * This is always used as a global singleton and can be retrieved with + * `tf.env()`. + */ + /** @doc {heading: 'Environment'} */ + var Environment = /** @class */ (function () { + // tslint:disable-next-line: no-any + function Environment(global) { + this.global = global; + this.flags = {}; + this.flagRegistry = {}; + this.urlFlags = {}; + this.populateURLFlags(); + } + Environment.prototype.setPlatform = function (platformName, platform) { + if (this.platform != null) { + console.warn("Platform " + this.platformName + " has already been set. " + + ("Overwriting the platform with " + platform + ".")); + } + this.platformName = platformName; + this.platform = platform; + }; + Environment.prototype.registerFlag = function (flagName, evaluationFn, setHook) { + this.flagRegistry[flagName] = { evaluationFn: evaluationFn, setHook: setHook }; + // Override the flag value from the URL. This has to happen here because the + // environment is initialized before flags get registered. + if (this.urlFlags[flagName] != null) { + var flagValue = this.urlFlags[flagName]; + console.warn("Setting feature override from URL " + flagName + ": " + flagValue + "."); + this.set(flagName, flagValue); + } + }; + Environment.prototype.getAsync = function (flagName) { + return __awaiter(this, void 0, void 0, function () { + var _a, _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + if (flagName in this.flags) { + return [2 /*return*/, this.flags[flagName]]; + } + _a = this.flags; + _b = flagName; + return [4 /*yield*/, this.evaluateFlag(flagName)]; + case 1: + _a[_b] = _c.sent(); + return [2 /*return*/, this.flags[flagName]]; + } + }); + }); + }; + Environment.prototype.get = function (flagName) { + if (flagName in this.flags) { + return this.flags[flagName]; + } + var flagValue = this.evaluateFlag(flagName); + if (flagValue instanceof Promise) { + throw new Error("Flag " + flagName + " cannot be synchronously evaluated. " + + "Please use getAsync() instead."); + } + this.flags[flagName] = flagValue; + return this.flags[flagName]; + }; + Environment.prototype.getNumber = function (flagName) { + return this.get(flagName); + }; + Environment.prototype.getBool = function (flagName) { + return this.get(flagName); + }; + Environment.prototype.getFlags = function () { + return this.flags; + }; + Object.defineProperty(Environment.prototype, "features", { + // For backwards compatibility. + get: function () { + return this.flags; + }, + enumerable: true, + configurable: true + }); + Environment.prototype.set = function (flagName, value) { + if (this.flagRegistry[flagName] == null) { + throw new Error("Cannot set flag " + flagName + " as it has not been registered."); + } + this.flags[flagName] = value; + if (this.flagRegistry[flagName].setHook != null) { + this.flagRegistry[flagName].setHook(value); + } + }; + Environment.prototype.evaluateFlag = function (flagName) { + if (this.flagRegistry[flagName] == null) { + throw new Error("Cannot evaluate flag '" + flagName + "': no evaluation function found."); + } + return this.flagRegistry[flagName].evaluationFn(); + }; + Environment.prototype.setFlags = function (flags) { + this.flags = Object.assign({}, flags); + }; + Environment.prototype.reset = function () { + this.flags = {}; + this.urlFlags = {}; + this.populateURLFlags(); + }; + Environment.prototype.populateURLFlags = function () { + var _this = this; + if (typeof this.global === 'undefined' || + typeof this.global.location === 'undefined' || + typeof this.global.location.search === 'undefined') { + return; + } + var urlParams = getQueryParams(this.global.location.search); + if (TENSORFLOWJS_FLAGS_PREFIX in urlParams) { + var keyValues = urlParams[TENSORFLOWJS_FLAGS_PREFIX].split(','); + keyValues.forEach(function (keyValue) { + var _a = keyValue.split(':'), key = _a[0], value = _a[1]; + _this.urlFlags[key] = parseValue(key, value); + }); + } + }; + return Environment; + }()); + function getQueryParams(queryString) { + var params = {}; + queryString.replace(/[?&]([^=?&]+)(?:=([^&]*))?/g, function (s) { + var t = []; + for (var _i = 1; _i < arguments.length; _i++) { + t[_i - 1] = arguments[_i]; + } + decodeParam(params, t[0], t[1]); + return t.join('='); + }); + return params; + } + function decodeParam(params, name, value) { + params[decodeURIComponent(name)] = decodeURIComponent(value || ''); + } + function parseValue(flagName, value) { + value = value.toLowerCase(); + if (value === 'true' || value === 'false') { + return value === 'true'; + } + else if ("" + +value === value) { + return +value; + } + throw new Error("Could not parse value flag value " + value + " for flag " + flagName + "."); + } + /** + * Returns the current environment (a global singleton). + * + * The environment object contains the evaluated feature values as well as the + * active platform. + */ + /** @doc {heading: 'Environment'} */ + function env() { + return exports.ENV; + } + exports.ENV = null; + function setEnvironmentGlobal(environment) { + exports.ENV = environment; + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // Note that the identifier globalNameSpace is scoped to this module, but will + // always resolve to the same global object regardless of how the module is + // resolved. + // tslint:disable-next-line:no-any + var globalNameSpace; + // tslint:disable-next-line:no-any + function getGlobalNamespace() { + if (globalNameSpace == null) { + // tslint:disable-next-line:no-any + var ns = void 0; + if (typeof (window) !== 'undefined') { + ns = window; + } + else if (typeof (global) !== 'undefined') { + ns = global; + } + else if (typeof (process) !== 'undefined') { + ns = process; + } + else if (typeof (self) !== 'undefined') { + ns = self; + } + else { + throw new Error('Could not find a global object'); + } + globalNameSpace = ns; + } + return globalNameSpace; + } + // tslint:disable-next-line:no-any + function getGlobalMap() { + var ns = getGlobalNamespace(); + if (ns._tfGlobals == null) { + ns._tfGlobals = new Map(); + } + return ns._tfGlobals; + } + /** + * Returns a globally accessible 'singleton' object. + * + * @param key the name of the object + * @param init a function to initialize to initialize this object + * the first time it is fetched. + */ + function getGlobal(key, init) { + var globalMap = getGlobalMap(); + if (globalMap.has(key)) { + return globalMap.get(key); + } + else { + var singleton = init(); + globalMap.set(key, singleton); + return globalMap.get(key); + } + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var kernelRegistry = getGlobal('kernelRegistry', function () { return new Map(); }); + var gradRegistry = getGlobal('gradRegistry', function () { return new Map(); }); + /** + * Returns the kernel function (code) associated with the provided names. + * + * @param kernelName The official name of the kernel. + * @param backendName The official name of the backend. + */ + function getKernel(kernelName, backendName) { + var key = makeKey(kernelName, backendName); + return kernelRegistry.get(key); + } + /** + * Returns the registered gradient info associated with the provided kernel. + * @param kernelName The official TF kernel name. + */ + function getGradient(kernelName) { + return gradRegistry.get(kernelName); + } + function getKernelsForBackend(backendName) { + var it = kernelRegistry.entries(); + var result = []; + while (true) { + var _a = it.next(), done = _a.done, value = _a.value; + if (done) { + break; + } + var key = value[0], config = value[1]; + var backend = key.split('_')[0]; + if (backend === backendName) { + result.push(config); + } + } + return result; + } + /** + * Registers the function (forward pass) for the kernel in a global registry. + * + * @param config A config object with the following properties: + * - `kernelName` The official name of the kernel. + * - `backendName` The official name of the backend. + * - `kernelFunc` The function to run during the forward pass of the kernel. + * - `setupFunc` Optional. Gets called once, after the backend initializes. + * - `disposeFunc` Optional. Gets called once, right before the backend is + * disposed. + */ + function registerKernel(config) { + var kernelName = config.kernelName, backendName = config.backendName; + var key = makeKey(kernelName, backendName); + if (kernelRegistry.has(key)) { + console.warn("The kernel '" + kernelName + "' for backend " + + ("'" + backendName + "' is already registered")); + } + kernelRegistry.set(key, config); + } + /** + * Registers a gradient function for a given kernel in the global registry, + * to be used during the back-propagation of that kernel. + * + * @param config An object with the following properties: + * - `kernelName` The name of the kernel that the gradient function is for. + * - `gradFunc` The function to run during back-propagation. + */ + function registerGradient(config) { + var kernelName = config.kernelName; + if (gradRegistry.has(kernelName)) { + // TODO (yassogba) after 3.0 assess whether we need to keep this gated + // to debug mode. + if (env().getBool('DEBUG')) { + console.warn("Overriding the gradient for '" + kernelName + "'"); + } + } + gradRegistry.set(kernelName, config); + } + /** + * Removes the kernel function from the registry. + * + * @param kernelName The official name of the kernel. + * @param backendName The official name of the backend. + * + */ + function unregisterKernel(kernelName, backendName) { + var key = makeKey(kernelName, backendName); + if (!kernelRegistry.has(key)) { + throw new Error("The kernel '" + kernelName + "' for backend " + + ("'" + backendName + "' is not registered")); + } + kernelRegistry.delete(key); + } + /** Removes the registered gradient from the global registry. */ + function unregisterGradient(kernelName) { + if (!gradRegistry.has(kernelName)) { + throw new Error("The gradient '" + kernelName + "' for backend is not registered"); + } + gradRegistry.delete(kernelName); + } + function makeKey(kernelName, backendName) { + return backendName + "_" + kernelName; + } + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Shuffles the array in-place using Fisher-Yates algorithm. + * + * ```js + * const a = [1, 2, 3, 4, 5]; + * tf.util.shuffle(a); + * console.log(a); + * ``` + * + * @param array The array to shuffle in-place. + */ + /** @doc {heading: 'Util', namespace: 'util'} */ + // tslint:disable-next-line:no-any + function shuffle(array) { + var counter = array.length; + var temp = 0; + var index = 0; + // While there are elements in the array + while (counter > 0) { + // Pick a random index + index = (Math.random() * counter) | 0; + // Decrease counter by 1 + counter--; + // And swap the last element with it + temp = array[counter]; + array[counter] = array[index]; + array[index] = temp; + } + } + /** Clamps a value to a specified range. */ + function clamp(min, x, max) { + return Math.max(min, Math.min(x, max)); + } + function nearestLargerEven(val) { + return val % 2 === 0 ? val : val + 1; + } + function sum(arr) { + var sum = 0; + for (var i = 0; i < arr.length; i++) { + sum += arr[i]; + } + return sum; + } + /** + * Returns a sample from a uniform [a, b) distribution. + * + * @param a The minimum support (inclusive). + * @param b The maximum support (exclusive). + * @return A pseudorandom number on the half-open interval [a,b). + */ + function randUniform(a, b) { + var r = Math.random(); + return (b * r) + (1 - r) * a; + } + /** Returns the squared Euclidean distance between two vectors. */ + function distSquared(a, b) { + var result = 0; + for (var i = 0; i < a.length; i++) { + var diff = Number(a[i]) - Number(b[i]); + result += diff * diff; + } + return result; + } + /** + * Asserts that the expression is true. Otherwise throws an error with the + * provided message. + * + * ```js + * const x = 2; + * tf.util.assert(x === 2, 'x is not 2'); + * ``` + * + * @param expr The expression to assert (as a boolean). + * @param msg A function that returns the message to report when throwing an + * error. We use a function for performance reasons. + */ + /** @doc {heading: 'Util', namespace: 'util'} */ + function assert(expr, msg) { + if (!expr) { + throw new Error(typeof msg === 'string' ? msg : msg()); + } + } + function assertShapesMatch(shapeA, shapeB, errorMessagePrefix) { + if (errorMessagePrefix === void 0) { errorMessagePrefix = ''; } + assert(arraysEqual(shapeA, shapeB), function () { return errorMessagePrefix + (" Shapes " + shapeA + " and " + shapeB + " must match"); }); + } + function assertNonNull(a) { + assert(a != null, function () { return "The input to the tensor constructor must be a non-null value."; }); + } + // NOTE: We explicitly type out what T extends instead of any so that + // util.flatten on a nested array of number doesn't try to infer T as a + // number[][], causing us to explicitly type util.flatten(). + /** + * Flattens an arbitrarily nested array. + * + * ```js + * const a = [[1, 2], [3, 4], [5, [6, [7]]]]; + * const flat = tf.util.flatten(a); + * console.log(flat); + * ``` + * + * @param arr The nested array to flatten. + * @param result The destination array which holds the elements. + * @param skipTypedArray If true, avoids flattening the typed arrays. Defaults + * to false. + */ + /** @doc {heading: 'Util', namespace: 'util'} */ + function flatten(arr, result, skipTypedArray) { + if (result === void 0) { result = []; } + if (skipTypedArray === void 0) { skipTypedArray = false; } + if (result == null) { + result = []; + } + if (Array.isArray(arr) || isTypedArray(arr) && !skipTypedArray) { + for (var i = 0; i < arr.length; ++i) { + flatten(arr[i], result, skipTypedArray); + } + } + else { + result.push(arr); + } + return result; + } + /** + * Returns the size (number of elements) of the tensor given its shape. + * + * ```js + * const shape = [3, 4, 2]; + * const size = tf.util.sizeFromShape(shape); + * console.log(size); + * ``` + */ + /** @doc {heading: 'Util', namespace: 'util'} */ + function sizeFromShape(shape) { + if (shape.length === 0) { + // Scalar. + return 1; + } + var size = shape[0]; + for (var i = 1; i < shape.length; i++) { + size *= shape[i]; + } + return size; + } + function isScalarShape(shape) { + return shape.length === 0; + } + function arraysEqual(n1, n2) { + if (n1 === n2) { + return true; + } + if (n1 == null || n2 == null) { + return false; + } + if (n1.length !== n2.length) { + return false; + } + for (var i = 0; i < n1.length; i++) { + if (n1[i] !== n2[i]) { + return false; + } + } + return true; + } + function isInt(a) { + return a % 1 === 0; + } + function tanh(x) { + // tslint:disable-next-line:no-any + if (Math.tanh != null) { + // tslint:disable-next-line:no-any + return Math.tanh(x); + } + if (x === Infinity) { + return 1; + } + else if (x === -Infinity) { + return -1; + } + else { + var e2x = Math.exp(2 * x); + return (e2x - 1) / (e2x + 1); + } + } + function sizeToSquarishShape(size) { + var width = Math.ceil(Math.sqrt(size)); + return [width, Math.ceil(size / width)]; + } + /** + * Creates a new array with randomized indicies to a given quantity. + * + * ```js + * const randomTen = tf.util.createShuffledIndices(10); + * console.log(randomTen); + * ``` + * + * @param number Quantity of how many shuffled indicies to create. + */ + /** @doc {heading: 'Util', namespace: 'util'} */ + function createShuffledIndices(n) { + var shuffledIndices = new Uint32Array(n); + for (var i = 0; i < n; ++i) { + shuffledIndices[i] = i; + } + shuffle(shuffledIndices); + return shuffledIndices; + } + function rightPad(a, size) { + if (size <= a.length) { + return a; + } + return a + ' '.repeat(size - a.length); + } + function repeatedTry(checkFn, delayFn, maxCounter) { + if (delayFn === void 0) { delayFn = function (counter) { return 0; }; } + return new Promise(function (resolve, reject) { + var tryCount = 0; + var tryFn = function () { + if (checkFn()) { + resolve(); + return; + } + tryCount++; + var nextBackoff = delayFn(tryCount); + if (maxCounter != null && tryCount >= maxCounter) { + reject(); + return; + } + setTimeout(tryFn, nextBackoff); + }; + tryFn(); + }); + } + /** + * Given the full size of the array and a shape that may contain -1 as the + * implicit dimension, returns the inferred shape where -1 is replaced. + * E.g. For shape=[2, -1, 3] and size=24, it will return [2, 4, 3]. + * + * @param shape The shape, which may contain -1 in some dimension. + * @param size The full size (number of elements) of the array. + * @return The inferred shape where -1 is replaced with the inferred size. + */ + function inferFromImplicitShape(shape, size) { + var shapeProd = 1; + var implicitIdx = -1; + for (var i = 0; i < shape.length; ++i) { + if (shape[i] >= 0) { + shapeProd *= shape[i]; + } + else if (shape[i] === -1) { + if (implicitIdx !== -1) { + throw Error("Shapes can only have 1 implicit size. " + + ("Found -1 at dim " + implicitIdx + " and dim " + i)); + } + implicitIdx = i; + } + else if (shape[i] < 0) { + throw Error("Shapes can not be < 0. Found " + shape[i] + " at dim " + i); + } + } + if (implicitIdx === -1) { + if (size > 0 && size !== shapeProd) { + throw Error("Size(" + size + ") must match the product of shape " + shape); + } + return shape; + } + if (shapeProd === 0) { + throw Error("Cannot infer the missing size in [" + shape + "] when " + + "there are 0 elements"); + } + if (size % shapeProd !== 0) { + throw Error("The implicit shape can't be a fractional number. " + + ("Got " + size + " / " + shapeProd)); + } + var newShape = shape.slice(); + newShape[implicitIdx] = size / shapeProd; + return newShape; + } + function parseAxisParam(axis, shape) { + var rank = shape.length; + // Normalize input + axis = axis == null ? shape.map(function (s, i) { return i; }) : [].concat(axis); + // Check for valid range + assert(axis.every(function (ax) { return ax >= -rank && ax < rank; }), function () { + return "All values in axis param must be in range [-" + rank + ", " + rank + ") but " + + ("got axis " + axis); + }); + // Check for only integers + assert(axis.every(function (ax) { return isInt(ax); }), function () { return "All values in axis param must be integers but " + + ("got axis " + axis); }); + // Handle negative axis. + return axis.map(function (a) { return a < 0 ? rank + a : a; }); + } + /** Reduces the shape by removing all dimensions of shape 1. */ + function squeezeShape(shape, axis) { + var newShape = []; + var keptDims = []; + var isEmptyArray = axis != null && Array.isArray(axis) && axis.length === 0; + var axes = (axis == null || isEmptyArray) ? + null : + parseAxisParam(axis, shape).sort(); + var j = 0; + for (var i = 0; i < shape.length; ++i) { + if (axes != null) { + if (axes[j] === i && shape[i] !== 1) { + throw new Error("Can't squeeze axis " + i + " since its dim '" + shape[i] + "' is not 1"); + } + if ((axes[j] == null || axes[j] > i) && shape[i] === 1) { + newShape.push(shape[i]); + keptDims.push(i); + } + if (axes[j] <= i) { + j++; + } + } + if (shape[i] !== 1) { + newShape.push(shape[i]); + keptDims.push(i); + } + } + return { newShape: newShape, keptDims: keptDims }; + } + function getTypedArrayFromDType(dtype, size) { + var values = null; + if (dtype == null || dtype === 'float32') { + values = new Float32Array(size); + } + else if (dtype === 'int32') { + values = new Int32Array(size); + } + else if (dtype === 'bool') { + values = new Uint8Array(size); + } + else { + throw new Error("Unknown data type " + dtype); + } + return values; + } + function getArrayFromDType(dtype, size) { + var values = null; + if (dtype == null || dtype === 'float32') { + values = new Float32Array(size); + } + else if (dtype === 'int32') { + values = new Int32Array(size); + } + else if (dtype === 'bool') { + values = new Uint8Array(size); + } + else if (dtype === 'string') { + values = new Array(size); + } + else { + throw new Error("Unknown data type " + dtype); + } + return values; + } + function checkConversionForErrors(vals, dtype) { + for (var i = 0; i < vals.length; i++) { + var num = vals[i]; + if (isNaN(num) || !isFinite(num)) { + throw Error("A tensor of type " + dtype + " being uploaded contains " + num + "."); + } + } + } + /** Returns true if the dtype is valid. */ + function isValidDtype(dtype) { + return dtype === 'bool' || dtype === 'complex64' || dtype === 'float32' || + dtype === 'int32' || dtype === 'string'; + } + /** + * Returns true if the new type can't encode the old type without loss of + * precision. + */ + function hasEncodingLoss(oldType, newType) { + if (newType === 'complex64') { + return false; + } + if (newType === 'float32' && oldType !== 'complex64') { + return false; + } + if (newType === 'int32' && oldType !== 'float32' && oldType !== 'complex64') { + return false; + } + if (newType === 'bool' && oldType === 'bool') { + return false; + } + return true; + } + function isTypedArray(a) { + return a instanceof Float32Array || a instanceof Int32Array || + a instanceof Uint8Array; + } + function bytesPerElement(dtype) { + if (dtype === 'float32' || dtype === 'int32') { + return 4; + } + else if (dtype === 'complex64') { + return 8; + } + else if (dtype === 'bool') { + return 1; + } + else { + throw new Error("Unknown dtype " + dtype); + } + } + /** + * Returns the approximate number of bytes allocated in the string array - 2 + * bytes per character. Computing the exact bytes for a native string in JS is + * not possible since it depends on the encoding of the html page that serves + * the website. + */ + function bytesFromStringArray(arr) { + if (arr == null) { + return 0; + } + var bytes = 0; + arr.forEach(function (x) { return bytes += x.length; }); + return bytes; + } + /** Returns true if the value is a string. */ + function isString(value) { + return typeof value === 'string' || value instanceof String; + } + function isBoolean(value) { + return typeof value === 'boolean'; + } + function isNumber(value) { + return typeof value === 'number'; + } + function inferDtype(values) { + if (Array.isArray(values)) { + return inferDtype(values[0]); + } + if (values instanceof Float32Array) { + return 'float32'; + } + else if (values instanceof Int32Array || values instanceof Uint8Array) { + return 'int32'; + } + else if (isNumber(values)) { + return 'float32'; + } + else if (isString(values)) { + return 'string'; + } + else if (isBoolean(values)) { + return 'bool'; + } + return 'float32'; + } + function isFunction(f) { + return !!(f && f.constructor && f.call && f.apply); + } + function nearestDivisor(size, start) { + for (var i = start; i < size; ++i) { + if (size % i === 0) { + return i; + } + } + return size; + } + function computeStrides(shape) { + var rank = shape.length; + if (rank < 2) { + return []; + } + // Last dimension has implicit stride of 1, thus having D-1 (instead of D) + // strides. + var strides = new Array(rank - 1); + strides[rank - 2] = shape[rank - 1]; + for (var i = rank - 3; i >= 0; --i) { + strides[i] = strides[i + 1] * shape[i + 1]; + } + return strides; + } + function toTypedArray(a, dtype) { + if (dtype === 'string') { + throw new Error('Cannot convert a string[] to a TypedArray'); + } + if (Array.isArray(a)) { + a = flatten(a); + } + if (env().getBool('DEBUG')) { + checkConversionForErrors(a, dtype); + } + if (noConversionNeeded(a, dtype)) { + return a; + } + if (dtype == null || dtype === 'float32' || dtype === 'complex64') { + return new Float32Array(a); + } + else if (dtype === 'int32') { + return new Int32Array(a); + } + else if (dtype === 'bool') { + var bool = new Uint8Array(a.length); + for (var i = 0; i < bool.length; ++i) { + if (Math.round(a[i]) !== 0) { + bool[i] = 1; + } + } + return bool; + } + else { + throw new Error("Unknown data type " + dtype); + } + } + function createNestedArray(offset, shape, a) { + var ret = new Array(); + if (shape.length === 1) { + var d = shape[0]; + for (var i = 0; i < d; i++) { + ret[i] = a[offset + i]; + } + } + else { + var d = shape[0]; + var rest = shape.slice(1); + var len = rest.reduce(function (acc, c) { return acc * c; }); + for (var i = 0; i < d; i++) { + ret[i] = createNestedArray(offset + i * len, rest, a); + } + } + return ret; + } + // Provide a nested array of TypedArray in given shape. + function toNestedArray(shape, a) { + if (shape.length === 0) { + // Scalar type should return a single number. + return a[0]; + } + var size = shape.reduce(function (acc, c) { return acc * c; }); + if (size === 0) { + // A tensor with shape zero should be turned into empty list. + return []; + } + if (size !== a.length) { + throw new Error("[" + shape + "] does not match the input size " + a.length + "."); + } + return createNestedArray(0, shape, a); + } + function noConversionNeeded(a, dtype) { + return (a instanceof Float32Array && dtype === 'float32') || + (a instanceof Int32Array && dtype === 'int32') || + (a instanceof Uint8Array && dtype === 'bool'); + } + function makeOnesTypedArray(size, dtype) { + var array = makeZerosTypedArray(size, dtype); + for (var i = 0; i < array.length; i++) { + array[i] = 1; + } + return array; + } + function makeZerosTypedArray(size, dtype) { + if (dtype == null || dtype === 'float32' || dtype === 'complex64') { + return new Float32Array(size); + } + else if (dtype === 'int32') { + return new Int32Array(size); + } + else if (dtype === 'bool') { + return new Uint8Array(size); + } + else { + throw new Error("Unknown data type " + dtype); + } + } + /** + * Make nested `TypedArray` filled with zeros. + * @param shape The shape information for the nested array. + * @param dtype dtype of the array element. + */ + function makeZerosNestedTypedArray(shape, dtype) { + var size = shape.reduce(function (prev, curr) { return prev * curr; }, 1); + if (dtype == null || dtype === 'float32') { + return toNestedArray(shape, new Float32Array(size)); + } + else if (dtype === 'int32') { + return toNestedArray(shape, new Int32Array(size)); + } + else if (dtype === 'bool') { + return toNestedArray(shape, new Uint8Array(size)); + } + else { + throw new Error("Unknown data type " + dtype); + } + } + /** + * Returns the current high-resolution time in milliseconds relative to an + * arbitrary time in the past. It works across different platforms (node.js, + * browsers). + * + * ```js + * console.log(tf.util.now()); + * ``` + */ + /** @doc {heading: 'Util', namespace: 'util'} */ + function now() { + return env().platform.now(); + } + function assertNonNegativeIntegerDimensions(shape) { + shape.forEach(function (dimSize) { + assert(Number.isInteger(dimSize) && dimSize >= 0, function () { + return "Tensor must have a shape comprised of positive integers but got " + + ("shape [" + shape + "]."); + }); + }); + } + /** + * Returns a platform-specific implementation of + * [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). + * + * If `fetch` is defined on the global object (`window`, `process`, etc.), + * `tf.util.fetch` returns that function. + * + * If not, `tf.util.fetch` returns a platform-specific solution. + * + * ```js + * const resource = await tf.util.fetch('https://unpkg.com/@tensorflow/tfjs'); + * // handle response + * ``` + */ + /** @doc {heading: 'Util'} */ + function fetch$1(path, requestInits) { + return env().platform.fetch(path, requestInits); + } + /** + * Encodes the provided string into bytes using the provided encoding scheme. + * + * @param s The string to encode. + * @param encoding The encoding scheme. Defaults to utf-8. + * + */ + /** @doc {heading: 'Util'} */ + function encodeString(s, encoding) { + if (encoding === void 0) { encoding = 'utf-8'; } + encoding = encoding || 'utf-8'; + return env().platform.encode(s, encoding); + } + /** + * Decodes the provided bytes into a string using the provided encoding scheme. + * @param bytes The bytes to decode. + * + * @param encoding The encoding scheme. Defaults to utf-8. + */ + /** @doc {heading: 'Util'} */ + function decodeString(bytes, encoding) { + if (encoding === void 0) { encoding = 'utf-8'; } + encoding = encoding || 'utf-8'; + return env().platform.decode(bytes, encoding); + } + /** + * Computes flat index for a given location (multidimentionsal index) in a + * Tensor/multidimensional array. + * + * @param locs Location in the tensor. + * @param rank Rank of the tensor. + * @param strides Tensor strides. + */ + function locToIndex(locs, rank, strides) { + if (rank === 0) { + return 0; + } + else if (rank === 1) { + return locs[0]; + } + var index = locs[locs.length - 1]; + for (var i = 0; i < locs.length - 1; ++i) { + index += strides[i] * locs[i]; + } + return index; + } + /** + * Computes the location (multidimensional index) in a tensor/multidimentional + * array for a given flat index. + * + * @param index Index in flat array. + * @param rank Rank of tensor. + * @param strides Strides of tensor. + */ + function indexToLoc(index, rank, strides) { + if (rank === 0) { + return []; + } + else if (rank === 1) { + return [index]; + } + var locs = new Array(rank); + for (var i = 0; i < locs.length - 1; ++i) { + locs[i] = Math.floor(index / strides[i]); + index -= locs[i] * strides[i]; + } + locs[locs.length - 1] = index; + return locs; + } + + var util = { + __proto__: null, + shuffle: shuffle, + clamp: clamp, + nearestLargerEven: nearestLargerEven, + sum: sum, + randUniform: randUniform, + distSquared: distSquared, + assert: assert, + assertShapesMatch: assertShapesMatch, + assertNonNull: assertNonNull, + flatten: flatten, + sizeFromShape: sizeFromShape, + isScalarShape: isScalarShape, + arraysEqual: arraysEqual, + isInt: isInt, + tanh: tanh, + sizeToSquarishShape: sizeToSquarishShape, + createShuffledIndices: createShuffledIndices, + rightPad: rightPad, + repeatedTry: repeatedTry, + inferFromImplicitShape: inferFromImplicitShape, + parseAxisParam: parseAxisParam, + squeezeShape: squeezeShape, + getTypedArrayFromDType: getTypedArrayFromDType, + getArrayFromDType: getArrayFromDType, + checkConversionForErrors: checkConversionForErrors, + isValidDtype: isValidDtype, + hasEncodingLoss: hasEncodingLoss, + isTypedArray: isTypedArray, + bytesPerElement: bytesPerElement, + bytesFromStringArray: bytesFromStringArray, + isString: isString, + isBoolean: isBoolean, + isNumber: isNumber, + inferDtype: inferDtype, + isFunction: isFunction, + nearestDivisor: nearestDivisor, + computeStrides: computeStrides, + toTypedArray: toTypedArray, + toNestedArray: toNestedArray, + makeOnesTypedArray: makeOnesTypedArray, + makeZerosTypedArray: makeZerosTypedArray, + makeZerosNestedTypedArray: makeZerosNestedTypedArray, + now: now, + assertNonNegativeIntegerDimensions: assertNonNegativeIntegerDimensions, + fetch: fetch$1, + encodeString: encodeString, + decodeString: decodeString, + locToIndex: locToIndex, + indexToLoc: indexToLoc + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var Profiler = /** @class */ (function () { + function Profiler(backendTimer, logger) { + this.backendTimer = backendTimer; + this.logger = logger; + if (logger == null) { + this.logger = new Logger(); + } + } + Profiler.prototype.profileKernel = function (kernelName, inputs, f) { + var _this = this; + var outputs; + var holdResultWrapperFn = function () { + outputs = f(); + }; + var timer = this.backendTimer.time(holdResultWrapperFn); + outputs.forEach(function (r) { + // Dangling promise here because we don't want to propagate up + // asynchronicity. + r.data().then(function (vals) { + checkComputationForErrors(vals, r.dtype, kernelName); + timer.then(function (timing) { + var extraInfo = ''; + if (timing.getExtraProfileInfo != null) { + extraInfo = timing.getExtraProfileInfo(); + } + _this.logger.logKernelProfile(kernelName, r, vals, timing.kernelMs, inputs, extraInfo); + }); + }); + }); + return outputs; + }; + return Profiler; + }()); + function checkComputationForErrors(vals, dtype, kernelName) { + if (dtype !== 'float32') { + // Only floating point computations will generate NaN values + return false; + } + for (var i = 0; i < vals.length; i++) { + var num = vals[i]; + if (isNaN(num) || !isFinite(num)) { + // Throwing custom exception so behavior is testable. + console.warn("Found " + num + " in the result of '" + kernelName + "'"); + return true; + } + } + return false; + } + var Logger = /** @class */ (function () { + function Logger() { + } + Logger.prototype.logKernelProfile = function (name, result, vals, timeMs, inputs, extraInfo) { + var time = typeof timeMs === 'number' ? rightPad(timeMs + "ms", 9) : + timeMs['error']; + var paddedName = rightPad(name, 25); + var rank = result.rank; + var size = result.size; + var shape = rightPad(result.shape.toString(), 14); + var inputShapesDescription = ''; + for (var name_1 in inputs) { + var input = inputs[name_1]; + // The input might be a non-tensor (e.g HTMLImageElement), in which case + // we claim the output shape as input shape. + var inputShape = input.shape || result.shape; + var inputRank = inputShape.length; + inputShapesDescription += + name_1 + ": " + inputRank + "D " + (inputRank > 0 ? inputShape : '') + " "; + } + console.log("%c" + paddedName + "\t%c" + time + "\t%c" + rank + "D " + shape + "\t%c" + size + "\t%c" + inputShapesDescription + "\t%c" + extraInfo, 'font-weight:bold', 'color:red', 'color:blue', 'color: orange', 'color: green', 'color: steelblue'); + }; + return Logger; + }()); + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes a list of TapeNodes that connect x to y, filtering everything else + * out and preserving the order of the original tape elements. + * + * @param tape The tape elements to filter. + * @param xs The input Tensors. + * @param y The output Tensor. + */ + function getFilteredNodesXToY(tape, xs, y) { + // Forward pass to compute all the nodes and Tensors that are transitively a + // function of x. + var tensorsFromX = {}; + var nodesFromX = {}; + for (var i = 0; i < xs.length; i++) { + tensorsFromX[xs[i].id] = true; + } + for (var i = 0; i < tape.length; i++) { + var node = tape[i]; + var nodeInputs = node.inputs; + for (var inputName in nodeInputs) { + var input = nodeInputs[inputName]; + var anyInputFromX = false; + for (var j = 0; j < xs.length; j++) { + if (tensorsFromX[input.id]) { + node.outputs.forEach(function (output) { return tensorsFromX[output.id] = true; }); + anyInputFromX = true; + nodesFromX[node.id] = true; + break; + } + } + if (anyInputFromX) { + break; + } + } + } + // Backward pass to find all of the nodes and Tensors that lead to y. + var tensorsLeadToY = {}; + tensorsLeadToY[y.id] = true; + var nodesToY = {}; + for (var i = tape.length - 1; i >= 0; i--) { + var node = tape[i]; + var nodeInputs = node.inputs; + // If any of the outputs lead to y, mark all of the inputs as leading to y. + for (var j = 0; j < node.outputs.length; j++) { + if (tensorsLeadToY[node.outputs[j].id]) { + for (var inputName in nodeInputs) { + tensorsLeadToY[nodeInputs[inputName].id] = true; + nodesToY[node.id] = true; + } + break; + } + } + } + // Return the paths that come from x and lead to y. + var filteredTape = []; + for (var i = 0; i < tape.length; i++) { + var node = tape[i]; + if (nodesFromX[node.id] && nodesToY[node.id]) { + // Prune the inputs from the node that aren't a function of x. + var prunedInputs = {}; + for (var inputName in node.inputs) { + var nodeInput = node.inputs[inputName]; + if (tensorsFromX[nodeInput.id]) { + prunedInputs[inputName] = nodeInput; + } + } + // Copy the node and overwrite inputsAndArgs to the pruned version. + var prunedNode = Object.assign({}, node); + prunedNode.inputs = prunedInputs; + prunedNode.outputs = node.outputs; + filteredTape.push(prunedNode); + } + } + return filteredTape; + } + /** + * Backpropagate gradients through the filtered TapeNodes. + * + * @param tensorAccumulatedGradientMap A map of Tensor to its gradient. This map + * is mutated by this method. + * @param filteredTape The filtered TapeNodes to backprop through. + */ + function backpropagateGradients(tensorAccumulatedGradientMap, filteredTape, tidy) { + var _loop_1 = function (i) { + var node = filteredTape[i]; + var dys = []; + node.outputs.forEach(function (o) { + var gradTensor = tensorAccumulatedGradientMap[o.id]; + if (gradTensor != null) { + dys.push(gradTensor); + } + else { + // This particular output is not in the back-propagation subgraph, so it + // does not affect the final output, thus we put null for its dy. + dys.push(null); + } + }); + if (node.gradient == null) { + throw new Error("Cannot compute gradient: gradient function not found " + + ("for " + node.kernelName + ".")); + } + // Backprop dy through this node and accumulate gradients over the inputs. + var inputGradients = node.gradient(dys); + var _loop_2 = function (inputName) { + if (!(inputName in inputGradients)) { + throw new Error("Cannot backprop through input " + inputName + ". " + + ("Available gradients found: " + Object.keys(inputGradients) + ".")); + } + // Call the gradient function. + var dx = tidy(function () { return inputGradients[inputName](); }); + if (dx.dtype !== 'float32') { + throw new Error("Error in gradient for op " + node.kernelName + ". The gradient of input " + + (inputName + " must have 'float32' dtype, but has '" + dx.dtype + "'")); + } + var x = node.inputs[inputName]; + if (!arraysEqual(dx.shape, x.shape)) { + throw new Error("Error in gradient for op " + node.kernelName + ". The gradient of input " + + ("'" + inputName + "' has shape '" + dx.shape + "', which does not match ") + + ("the shape of the input '" + x.shape + "'")); + } + if (tensorAccumulatedGradientMap[x.id] == null) { + tensorAccumulatedGradientMap[x.id] = dx; + } + else { + var curGradient = tensorAccumulatedGradientMap[x.id]; + tensorAccumulatedGradientMap[x.id] = curGradient.add(dx); + curGradient.dispose(); + } + }; + for (var inputName in node.inputs) { + _loop_2(inputName); + } + }; + // Walk the tape backward and keep a map of Tensor to its gradient. + for (var i = filteredTape.length - 1; i >= 0; i--) { + _loop_1(i); + } + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // Maximum number of values before we decide to show ellipsis. + var FORMAT_LIMIT_NUM_VALS = 20; + // Number of first and last values to show when displaying a, b,...,y, z. + var FORMAT_NUM_FIRST_LAST_VALS = 3; + // Number of significant digits to show. + var FORMAT_NUM_SIG_DIGITS = 7; + function tensorToString(vals, shape, dtype, verbose) { + var strides = computeStrides(shape); + var padPerCol = computeMaxSizePerColumn(vals, shape, dtype, strides); + var rank = shape.length; + var valsLines = subTensorToString(vals, shape, dtype, strides, padPerCol); + var lines = ['Tensor']; + if (verbose) { + lines.push(" dtype: " + dtype); + lines.push(" rank: " + rank); + lines.push(" shape: [" + shape + "]"); + lines.push(" values:"); + } + lines.push(valsLines.map(function (l) { return ' ' + l; }).join('\n')); + return lines.join('\n'); + } + function computeMaxSizePerColumn(vals, shape, dtype, strides) { + var n = sizeFromShape(shape); + var numCols = strides[strides.length - 1]; + var padPerCol = new Array(numCols).fill(0); + var rank = shape.length; + var valuesOrTuples = dtype === 'complex64' ? createComplexTuples(vals) : vals; + if (rank > 1) { + for (var row = 0; row < n / numCols; row++) { + var offset = row * numCols; + for (var j = 0; j < numCols; j++) { + padPerCol[j] = Math.max(padPerCol[j], valToString(valuesOrTuples[offset + j], 0, dtype).length); + } + } + } + return padPerCol; + } + function valToString(val, pad, dtype) { + var valStr; + if (Array.isArray(val)) { + valStr = parseFloat(val[0].toFixed(FORMAT_NUM_SIG_DIGITS)) + " + " + + (parseFloat(val[1].toFixed(FORMAT_NUM_SIG_DIGITS)) + "j"); + } + else if (isString(val)) { + valStr = "'" + val + "'"; + } + else if (dtype === 'bool') { + valStr = boolNumToString(val); + } + else { + valStr = parseFloat(val.toFixed(FORMAT_NUM_SIG_DIGITS)).toString(); + } + return rightPad(valStr, pad); + } + function boolNumToString(v) { + return v === 0 ? 'false' : 'true'; + } + function subTensorToString(vals, shape, dtype, strides, padPerCol, isLast) { + if (isLast === void 0) { isLast = true; } + var storagePerElement = dtype === 'complex64' ? 2 : 1; + var size = shape[0]; + var rank = shape.length; + if (rank === 0) { + if (dtype === 'complex64') { + var complexTuple = createComplexTuples(vals); + return [valToString(complexTuple[0], 0, dtype)]; + } + if (dtype === 'bool') { + return [boolNumToString(vals[0])]; + } + return [vals[0].toString()]; + } + if (rank === 1) { + if (size > FORMAT_LIMIT_NUM_VALS) { + var firstValsSize = FORMAT_NUM_FIRST_LAST_VALS * storagePerElement; + var firstVals = Array.from(vals.slice(0, firstValsSize)); + var lastVals = Array.from(vals.slice((size - FORMAT_NUM_FIRST_LAST_VALS) * storagePerElement, size * storagePerElement)); + if (dtype === 'complex64') { + firstVals = createComplexTuples(firstVals); + lastVals = createComplexTuples(lastVals); + } + return [ + '[' + + firstVals.map(function (x, i) { return valToString(x, padPerCol[i], dtype); }) + .join(', ') + + ', ..., ' + + lastVals + .map(function (x, i) { return valToString(x, padPerCol[size - FORMAT_NUM_FIRST_LAST_VALS + i], dtype); }) + .join(', ') + + ']' + ]; + } + var displayVals = dtype === 'complex64' ? createComplexTuples(vals) : + Array.from(vals); + return [ + '[' + + displayVals.map(function (x, i) { return valToString(x, padPerCol[i], dtype); }) + .join(', ') + + ']' + ]; + } + // The array is rank 2 or more. + var subshape = shape.slice(1); + var substrides = strides.slice(1); + var stride = strides[0] * storagePerElement; + var lines = []; + if (size > FORMAT_LIMIT_NUM_VALS) { + for (var i = 0; i < FORMAT_NUM_FIRST_LAST_VALS; i++) { + var start = i * stride; + var end = start + stride; + lines.push.apply(lines, subTensorToString(vals.slice(start, end), subshape, dtype, substrides, padPerCol, false /* isLast */)); + } + lines.push('...'); + for (var i = size - FORMAT_NUM_FIRST_LAST_VALS; i < size; i++) { + var start = i * stride; + var end = start + stride; + lines.push.apply(lines, subTensorToString(vals.slice(start, end), subshape, dtype, substrides, padPerCol, i === size - 1 /* isLast */)); + } + } + else { + for (var i = 0; i < size; i++) { + var start = i * stride; + var end = start + stride; + lines.push.apply(lines, subTensorToString(vals.slice(start, end), subshape, dtype, substrides, padPerCol, i === size - 1 /* isLast */)); + } + } + var sep = rank === 2 ? ',' : ''; + lines[0] = '[' + lines[0] + sep; + for (var i = 1; i < lines.length - 1; i++) { + lines[i] = ' ' + lines[i] + sep; + } + var newLineSep = ',\n'; + for (var i = 2; i < rank; i++) { + newLineSep += '\n'; + } + lines[lines.length - 1] = + ' ' + lines[lines.length - 1] + ']' + (isLast ? '' : newLineSep); + return lines; + } + function createComplexTuples(vals) { + var complexTuples = []; + for (var i = 0; i < vals.length; i += 2) { + complexTuples.push([vals[i], vals[i + 1]]); + } + return complexTuples; + } + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * A mutable object, similar to `tf.Tensor`, that allows users to set values + * at locations before converting to an immutable `tf.Tensor`. + * + * See `tf.buffer` for creating a tensor buffer. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + var TensorBuffer = /** @class */ (function () { + function TensorBuffer(shape, dtype, values) { + var _this = this; + this.dtype = dtype; + this.shape = shape.slice(); + this.size = sizeFromShape(shape); + if (values != null) { + var n_1 = values.length; + assert(n_1 === this.size, function () { return "Length of values '" + n_1 + "' does not match the size " + + ("inferred by the shape '" + _this.size + "'."); }); + } + if (dtype === 'complex64') { + throw new Error("complex64 dtype TensorBuffers are not supported. Please create " + + "a TensorBuffer for the real and imaginary parts separately and " + + "call tf.complex(real, imag)."); + } + this.values = values || getArrayFromDType(dtype, this.size); + this.strides = computeStrides(shape); + } + /** + * Sets a value in the buffer at a given location. + * + * @param value The value to set. + * @param locs The location indices. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + TensorBuffer.prototype.set = function (value) { + var _this = this; + var locs = []; + for (var _i = 1; _i < arguments.length; _i++) { + locs[_i - 1] = arguments[_i]; + } + if (locs.length === 0) { + locs = [0]; + } + assert(locs.length === this.rank, function () { return "The number of provided coordinates (" + locs.length + ") must " + + ("match the rank (" + _this.rank + ")"); }); + var index = this.locToIndex(locs); + this.values[index] = value; + }; + /** + * Returns the value in the buffer at the provided location. + * + * @param locs The location indices. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + TensorBuffer.prototype.get = function () { + var locs = []; + for (var _i = 0; _i < arguments.length; _i++) { + locs[_i] = arguments[_i]; + } + if (locs.length === 0) { + locs = [0]; + } + var i = 0; + for (var _a = 0, locs_1 = locs; _a < locs_1.length; _a++) { + var loc = locs_1[_a]; + if (loc < 0 || loc >= this.shape[i]) { + var msg = "Requested out of range element at " + locs + ". " + + (" Buffer shape=" + this.shape); + throw new Error(msg); + } + i++; + } + var index = locs[locs.length - 1]; + for (var i_1 = 0; i_1 < locs.length - 1; ++i_1) { + index += this.strides[i_1] * locs[i_1]; + } + return this.values[index]; + }; + TensorBuffer.prototype.locToIndex = function (locs) { + if (this.rank === 0) { + return 0; + } + else if (this.rank === 1) { + return locs[0]; + } + var index = locs[locs.length - 1]; + for (var i = 0; i < locs.length - 1; ++i) { + index += this.strides[i] * locs[i]; + } + return index; + }; + TensorBuffer.prototype.indexToLoc = function (index) { + if (this.rank === 0) { + return []; + } + else if (this.rank === 1) { + return [index]; + } + var locs = new Array(this.shape.length); + for (var i = 0; i < locs.length - 1; ++i) { + locs[i] = Math.floor(index / this.strides[i]); + index -= locs[i] * this.strides[i]; + } + locs[locs.length - 1] = index; + return locs; + }; + Object.defineProperty(TensorBuffer.prototype, "rank", { + get: function () { + return this.shape.length; + }, + enumerable: true, + configurable: true + }); + /** + * Creates an immutable `tf.Tensor` object from the buffer. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + TensorBuffer.prototype.toTensor = function () { + return trackerFn().makeTensor(this.values, this.shape, this.dtype); + }; + return TensorBuffer; + }()); + // For tracking tensor creation and disposal. + var trackerFn = null; + // Used by chaining methods to call into ops. + var opHandler = null; + /** + * An external consumer can register itself as the tensor tracker. This way + * the Tensor class can notify the tracker for every tensor created and + * disposed. + */ + function setTensorTracker(fn) { + trackerFn = fn; + } + /** + * An external consumer can register itself as the op handler. This way the + * Tensor class can have chaining methods that call into ops via the op + * handler. + */ + function setOpHandler(handler) { + opHandler = handler; + } + /** + * A `tf.Tensor` object represents an immutable, multidimensional array of + * numbers that has a shape and a data type. + * + * See `tf.tensor` for details on how to create a `tf.Tensor`. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + var Tensor = /** @class */ (function () { + function Tensor(shape, dtype, dataId, id) { + /** Whether this tensor has been globally kept. */ + this.kept = false; + this.isDisposedInternal = false; + this.shape = shape.slice(); + this.dtype = dtype || 'float32'; + this.size = sizeFromShape(shape); + this.strides = computeStrides(shape); + this.dataId = dataId; + this.id = id; + this.rankType = (this.rank < 5 ? this.rank.toString() : 'higher'); + } + Object.defineProperty(Tensor.prototype, "rank", { + get: function () { + return this.shape.length; + }, + enumerable: true, + configurable: true + }); + /** + * Returns a promise of `tf.TensorBuffer` that holds the underlying data. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.buffer = function () { + return __awaiter(this, void 0, void 0, function () { + var vals; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, this.data()]; + case 1: + vals = _a.sent(); + return [2 /*return*/, opHandler.buffer(this.shape, this.dtype, vals)]; + } + }); + }); + }; + /** Returns a `tf.TensorBuffer` that holds the underlying data. */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.bufferSync = function () { + return opHandler.buffer(this.shape, this.dtype, this.dataSync()); + }; + /** + * Returns the tensor data as a nested array. The transfer of data is done + * asynchronously. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.array = function () { + return __awaiter(this, void 0, void 0, function () { + var vals; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, this.data()]; + case 1: + vals = _a.sent(); + return [2 /*return*/, toNestedArray(this.shape, vals)]; + } + }); + }); + }; + /** + * Returns the tensor data as a nested array. The transfer of data is done + * synchronously. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.arraySync = function () { + return toNestedArray(this.shape, this.dataSync()); + }; + /** + * Asynchronously downloads the values from the `tf.Tensor`. Returns a + * promise of `TypedArray` that resolves when the computation has finished. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.data = function () { + return __awaiter(this, void 0, void 0, function () { + var data, bytes; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + this.throwIfDisposed(); + data = trackerFn().read(this.dataId); + if (!(this.dtype === 'string')) return [3 /*break*/, 2]; + return [4 /*yield*/, data]; + case 1: + bytes = _a.sent(); + try { + return [2 /*return*/, bytes.map(function (b) { return decodeString(b); })]; + } + catch (_b) { + throw new Error('Failed to decode the string bytes into utf-8. ' + + 'To get the original bytes, call tensor.bytes().'); + } + _a.label = 2; + case 2: return [2 /*return*/, data]; + } + }); + }); + }; + /** + * Synchronously downloads the values from the `tf.Tensor`. This blocks the + * UI thread until the values are ready, which can cause performance issues. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.dataSync = function () { + this.throwIfDisposed(); + var data = trackerFn().readSync(this.dataId); + if (this.dtype === 'string') { + try { + return data.map(function (b) { return decodeString(b); }); + } + catch (_a) { + throw new Error('Failed to decode the string bytes into utf-8. ' + + 'To get the original bytes, call tensor.bytes().'); + } + } + return data; + }; + /** Returns the underlying bytes of the tensor's data. */ + Tensor.prototype.bytes = function () { + return __awaiter(this, void 0, void 0, function () { + var data; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + this.throwIfDisposed(); + return [4 /*yield*/, trackerFn().read(this.dataId)]; + case 1: + data = _a.sent(); + if (this.dtype === 'string') { + return [2 /*return*/, data]; + } + else { + return [2 /*return*/, new Uint8Array(data.buffer)]; + } + } + }); + }); + }; + /** + * Disposes `tf.Tensor` from memory. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.dispose = function () { + if (this.isDisposed) { + return; + } + trackerFn().disposeTensor(this); + this.isDisposedInternal = true; + }; + Object.defineProperty(Tensor.prototype, "isDisposed", { + get: function () { + return this.isDisposedInternal; + }, + enumerable: true, + configurable: true + }); + Tensor.prototype.throwIfDisposed = function () { + if (this.isDisposed) { + throw new Error("Tensor is disposed."); + } + }; + /** + * Prints the `tf.Tensor`. See `tf.print` for details. + * + * @param verbose Whether to print verbose information about the tensor, + * including dtype and size. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.print = function (verbose) { + if (verbose === void 0) { verbose = false; } + return opHandler.print(this, verbose); + }; + /** Returns a copy of the tensor. See `tf.clone` for details. */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.clone = function () { + this.throwIfDisposed(); + return opHandler.clone(this); + }; + /** + * Returns a human-readable description of the tensor. Useful for logging. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Tensor.prototype.toString = function (verbose) { + if (verbose === void 0) { verbose = false; } + var vals = this.dataSync(); + return tensorToString(vals, this.shape, this.dtype, verbose); + }; + Tensor.prototype.cast = function (dtype) { + this.throwIfDisposed(); + return opHandler.cast(this, dtype); + }; + Tensor.prototype.variable = function (trainable, name, dtype) { + if (trainable === void 0) { trainable = true; } + this.throwIfDisposed(); + return trackerFn().makeVariable(this, trainable, name, dtype); + }; + return Tensor; + }()); + Object.defineProperty(Tensor, Symbol.hasInstance, { + value: function (instance) { + return !!instance && instance.dataId != null && instance.shape != null && + instance.dtype != null; + } + }); + /** + * A mutable `tf.Tensor`, useful for persisting state, e.g. for training. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + var Variable = /** @class */ (function (_super) { + __extends(Variable, _super); + function Variable(initialValue, trainable, name, tensorId) { + var _this = _super.call(this, initialValue.shape, initialValue.dtype, initialValue.dataId, tensorId) || this; + _this.trainable = trainable; + _this.name = name; + return _this; + } + /** + * Assign a new `tf.Tensor` to this variable. The new `tf.Tensor` must have + * the same shape and dtype as the old `tf.Tensor`. + * + * @param newValue New tensor to be assigned to this variable. + */ + /** @doc {heading: 'Tensors', subheading: 'Classes'} */ + Variable.prototype.assign = function (newValue) { + if (newValue.dtype !== this.dtype) { + throw new Error("dtype of the new value (" + newValue.dtype + ") and " + + ("previous value (" + this.dtype + ") must match")); + } + if (!arraysEqual(newValue.shape, this.shape)) { + throw new Error("shape of the new value (" + newValue.shape + ") and " + + ("previous value (" + this.shape + ") must match")); + } + trackerFn().disposeTensor(this); + this.dataId = newValue.dataId; + trackerFn().incRef(this, null /* backend */); + }; + Variable.prototype.dispose = function () { + trackerFn().disposeVariable(this); + this.isDisposedInternal = true; + }; + return Variable; + }(Tensor)); + Object.defineProperty(Variable, Symbol.hasInstance, { + value: function (instance) { + return instance instanceof Tensor && instance.assign != null && + instance.assign instanceof Function; + } + }); + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + (function (Rank) { + Rank["R0"] = "R0"; + Rank["R1"] = "R1"; + Rank["R2"] = "R2"; + Rank["R3"] = "R3"; + Rank["R4"] = "R4"; + Rank["R5"] = "R5"; + Rank["R6"] = "R6"; + })(exports.Rank || (exports.Rank = {})); + // Looks for upcasting types. Used, for example, in operations with mixed dtype + // inputs. + var UpcastInt32AndMap; + (function (UpcastInt32AndMap) { + UpcastInt32AndMap["float32"] = "float32"; + UpcastInt32AndMap["int32"] = "int32"; + UpcastInt32AndMap["bool"] = "int32"; + UpcastInt32AndMap["complex64"] = "complex64"; + })(UpcastInt32AndMap || (UpcastInt32AndMap = {})); + var UpcastBoolAndMap; + (function (UpcastBoolAndMap) { + UpcastBoolAndMap["float32"] = "float32"; + UpcastBoolAndMap["int32"] = "int32"; + UpcastBoolAndMap["bool"] = "bool"; + UpcastBoolAndMap["complex64"] = "complex64"; + })(UpcastBoolAndMap || (UpcastBoolAndMap = {})); + var UpcastFloat32AndMap; + (function (UpcastFloat32AndMap) { + UpcastFloat32AndMap["float32"] = "float32"; + UpcastFloat32AndMap["int32"] = "float32"; + UpcastFloat32AndMap["bool"] = "float32"; + UpcastFloat32AndMap["complex64"] = "complex64"; + })(UpcastFloat32AndMap || (UpcastFloat32AndMap = {})); + var UpcastComplex64AndMap; + (function (UpcastComplex64AndMap) { + UpcastComplex64AndMap["float32"] = "complex64"; + UpcastComplex64AndMap["int32"] = "complex64"; + UpcastComplex64AndMap["bool"] = "complex64"; + UpcastComplex64AndMap["complex64"] = "complex64"; + })(UpcastComplex64AndMap || (UpcastComplex64AndMap = {})); + var upcastTypeMap = { + 'float32': UpcastFloat32AndMap, + 'int32': UpcastInt32AndMap, + 'bool': UpcastBoolAndMap, + 'complex64': UpcastComplex64AndMap + }; + function upcastType(typeA, typeB) { + if (typeA === 'string' || typeB === 'string') { + if (typeA === 'string' && typeB === 'string') { + return 'string'; + } + throw new Error("Can not upcast " + typeA + " with " + typeB); + } + return upcastTypeMap[typeA][typeB]; + } + /** Returns the output type after summation. */ + function sumOutType(type) { + return upcastType(type, 'int32'); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function makeTypesMatch(a, b) { + if (a.dtype === b.dtype) { + return [a, b]; + } + var dtype = upcastType(a.dtype, b.dtype); + return [a.cast(dtype), b.cast(dtype)]; + } + function assertTypesMatch(a, b) { + assert(a.dtype === b.dtype, function () { return "The dtypes of the first(" + a.dtype + ") and" + + (" second(" + b.dtype + ") input must match"); }); + } + function isTensorInList(tensor, tensorList) { + return tensorList.some(function (x) { return x.id === tensor.id; }); + } + /** + * Extracts any `Tensor`s found within the provided object. + * + * @param container an object that may be a `Tensor` or may directly contain + * `Tensor`s, such as a `Tensor[]` or `{key: Tensor, ...}`. In general it + * is safe to pass any object here, except that `Promise`s are not + * supported. + * @returns An array of `Tensors` found within the passed object. If the + * argument is simply a `Tensor', a list containing that `Tensor` is + * returned. If the object is not a `Tensor` or does not + * contain `Tensors`, an empty list is returned. + */ + function getTensorsInContainer(result) { + var list = []; + var seen = new Set(); + walkTensorContainer(result, list, seen); + return list; + } + function walkTensorContainer(container, list, seen) { + if (container == null) { + return; + } + if (container instanceof Tensor) { + list.push(container); + return; + } + if (!isIterable(container)) { + return; + } + // Iteration over keys works also for arrays. + var iterable = container; + for (var k in iterable) { + var val = iterable[k]; + if (!seen.has(val)) { + seen.add(val); + walkTensorContainer(val, list, seen); + } + } + } + // tslint:disable-next-line:no-any + function isIterable(obj) { + return Array.isArray(obj) || typeof obj === 'object'; + } + + var tensor_util = { + __proto__: null, + makeTypesMatch: makeTypesMatch, + assertTypesMatch: assertTypesMatch, + isTensorInList: isTensorInList, + getTensorsInContainer: getTensorsInContainer + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var EngineState = /** @class */ (function () { + function EngineState() { + // Public since optimizers will use it. + this.registeredVariables = {}; + this.nextTapeNodeId = 0; + this.numBytes = 0; + this.numTensors = 0; + this.numStringTensors = 0; + this.numDataBuffers = 0; + // Number of nested tf.grad() statements when computing higher-order + // gradients. E.g. `1` for first-order gradients and `2` for second-order + // gradients. Used to track if the tape should be removed after a backprop. + this.gradientDepth = 0; + // Number of nested kernel calls. When kernel depth is greater than 1, we turn + // off the tape. + this.kernelDepth = 0; + this.scopeStack = []; + /** + * Keeps track of the number of data moves during a kernel execution. We + * maintain a stack since kernels can call other kernels, recursively. + */ + this.numDataMovesStack = []; + this.nextScopeId = 0; + this.tensorInfo = new WeakMap(); + this.profiling = false; + this.activeProfile = { newBytes: 0, newTensors: 0, peakBytes: 0, kernels: [], result: null }; + } + EngineState.prototype.dispose = function () { + for (var variableName in this.registeredVariables) { + this.registeredVariables[variableName].dispose(); + } + }; + return EngineState; + }()); + var Engine = /** @class */ (function () { + function Engine(ENV) { + this.ENV = ENV; + this.registry = {}; + this.registryFactory = {}; + this.pendingBackendInitId = 0; + this.state = new EngineState(); + } + Engine.prototype.ready = function () { + return __awaiter(this, void 0, void 0, function () { + var sortedBackends, i, backendName, success; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (this.pendingBackendInit != null) { + return [2 /*return*/, this.pendingBackendInit.then(function () { })]; + } + if (this.backendInstance != null) { + return [2 /*return*/]; + } + sortedBackends = this.getSortedBackends(); + i = 0; + _a.label = 1; + case 1: + if (!(i < sortedBackends.length)) return [3 /*break*/, 5]; + backendName = sortedBackends[i]; + return [4 /*yield*/, this.initializeBackend(backendName).success]; + case 2: + success = _a.sent(); + if (!success) return [3 /*break*/, 4]; + return [4 /*yield*/, this.setBackend(backendName)]; + case 3: + _a.sent(); + return [2 /*return*/]; + case 4: + i++; + return [3 /*break*/, 1]; + case 5: throw new Error("Could not initialize any backends, all backend initializations " + + "failed."); + } + }); + }); + }; + Object.defineProperty(Engine.prototype, "backend", { + get: function () { + if (this.pendingBackendInit != null) { + throw new Error("Backend '" + this.backendName + "' has not yet been initialized. Make " + + "sure to await tf.ready() or await tf.setBackend() before calling " + + "other methods"); + } + if (this.backendInstance == null) { + var _a = this.initializeBackendsAndReturnBest(), name_1 = _a.name, asyncInit = _a.asyncInit; + if (asyncInit) { + throw new Error("The highest priority backend '" + name_1 + "' has not yet been " + + "initialized. Make sure to await tf.ready() or " + + "await tf.setBackend() before calling other methods"); + } + this.setBackend(name_1); + } + return this.backendInstance; + }, + enumerable: true, + configurable: true + }); + Engine.prototype.backendNames = function () { + return Object.keys(this.registryFactory); + }; + Engine.prototype.findBackend = function (backendName) { + if (!(backendName in this.registry)) { + // If the backend hasn't been initialized but we have a registry entry for + // it, initialize it and return it. + if (backendName in this.registryFactory) { + var asyncInit = this.initializeBackend(backendName).asyncInit; + if (asyncInit) { + // Backend is not ready yet. + return null; + } + } + else { + return null; + } + } + return this.registry[backendName]; + }; + Engine.prototype.findBackendFactory = function (backendName) { + if (!(backendName in this.registryFactory)) { + return null; + } + return this.registryFactory[backendName].factory; + }; + Engine.prototype.registerBackend = function (backendName, factory, priority) { + if (priority === void 0) { priority = 1; } + if (backendName in this.registryFactory) { + console.warn(backendName + " backend was already registered. " + + "Reusing existing backend factory."); + return false; + } + this.registryFactory[backendName] = { factory: factory, priority: priority }; + return true; + }; + Engine.prototype.setBackend = function (backendName) { + return __awaiter(this, void 0, void 0, function () { + var _a, success, asyncInit, result, _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + if (this.registryFactory[backendName] == null) { + throw new Error("Backend name '" + backendName + "' not found in registry"); + } + this.backendName = backendName; + if (!(this.registry[backendName] == null)) return [3 /*break*/, 4]; + this.backendInstance = null; + _a = this.initializeBackend(backendName), success = _a.success, asyncInit = _a.asyncInit; + if (!asyncInit) return [3 /*break*/, 2]; + return [4 /*yield*/, success]; + case 1: + _b = _c.sent(); + return [3 /*break*/, 3]; + case 2: + _b = success; + _c.label = 3; + case 3: + result = _b; + if (!result) { + return [2 /*return*/, false]; + } + _c.label = 4; + case 4: + this.backendInstance = this.registry[backendName]; + this.setupRegisteredKernels(); + // Reset the profiler. + this.profiler = new Profiler(this.backendInstance); + return [2 /*return*/, true]; + } + }); + }); + }; + Engine.prototype.setupRegisteredKernels = function () { + var _this = this; + var kernels = getKernelsForBackend(this.backendName); + kernels.forEach(function (kernel) { + if (kernel.setupFunc != null) { + kernel.setupFunc(_this.backendInstance); + } + }); + }; + Engine.prototype.disposeRegisteredKernels = function (backendName) { + var _this = this; + var kernels = getKernelsForBackend(backendName); + kernels.forEach(function (kernel) { + if (kernel.disposeFunc != null) { + kernel.disposeFunc(_this.registry[backendName]); + } + }); + }; + /** + * Initializes a backend by looking up the backend name in the factory + * registry and calling the factory method. Returns a boolean representing + * whether the initialization of the backend suceeded. Throws an error if + * there is no backend in the factory registry. + */ + Engine.prototype.initializeBackend = function (backendName) { + var _this = this; + var registryFactoryEntry = this.registryFactory[backendName]; + if (registryFactoryEntry == null) { + throw new Error("Cannot initialize backend " + backendName + ", no registration found."); + } + try { + var backend = registryFactoryEntry.factory(); + // Test if the factory returns a promise. + if (Promise.resolve(backend) === backend) { + var promiseId_1 = ++this.pendingBackendInitId; + var success = backend + .then(function (backendInstance) { + // Outdated promise. Another backend was set in the meantime. + if (promiseId_1 < _this.pendingBackendInitId) { + return false; + } + _this.registry[backendName] = backendInstance; + _this.pendingBackendInit = null; + return true; + }) + .catch(function (err) { + // Outdated promise. Another backend was set in the meantime. + if (promiseId_1 < _this.pendingBackendInitId) { + return false; + } + _this.pendingBackendInit = null; + console.warn("Initialization of backend " + backendName + " failed"); + console.warn(err.stack || err.message); + return false; + }); + this.pendingBackendInit = success; + return { success: success, asyncInit: true }; + } + else { + this.registry[backendName] = backend; + return { success: true, asyncInit: false }; + } + } + catch (err) { + console.warn("Initialization of backend " + backendName + " failed"); + console.warn(err.stack || err.message); + return { success: false, asyncInit: false }; + } + }; + Engine.prototype.removeBackend = function (backendName) { + if (!(backendName in this.registryFactory)) { + throw new Error(backendName + " backend not found in registry"); + } + if (this.backendName === backendName && this.pendingBackendInit != null) { + // There is a pending promise of the backend we want to remove. Make it + // obsolete. + this.pendingBackendInitId++; + } + if (backendName in this.registry) { + this.disposeRegisteredKernels(backendName); + this.registry[backendName].dispose(); + delete this.registry[backendName]; + } + delete this.registryFactory[backendName]; + // Unset the backend if it is active. + if (this.backendName === backendName) { + this.pendingBackendInit = null; + this.backendName = null; + this.backendInstance = null; + } + }; + Engine.prototype.getSortedBackends = function () { + var _this = this; + if (Object.keys(this.registryFactory).length === 0) { + throw new Error('No backend found in registry.'); + } + return Object.keys(this.registryFactory).sort(function (a, b) { + // Highest priority comes first. + return _this.registryFactory[b].priority - + _this.registryFactory[a].priority; + }); + }; + Engine.prototype.initializeBackendsAndReturnBest = function () { + var sortedBackends = this.getSortedBackends(); + for (var i = 0; i < sortedBackends.length; i++) { + var backendName = sortedBackends[i]; + var _a = this.initializeBackend(backendName), success = _a.success, asyncInit = _a.asyncInit; + if (asyncInit || success) { + return { name: backendName, asyncInit: asyncInit }; + } + } + throw new Error("Could not initialize any backends, all backend initializations " + + "failed."); + }; + Engine.prototype.moveData = function (backend, dataId) { + var info = this.state.tensorInfo.get(dataId); + var srcBackend = info.backend; + var values = this.readSync(dataId); + // Delete the tensor from the old backend and move it to the new + // backend. + srcBackend.disposeData(dataId); + info.backend = backend; + backend.move(dataId, values, info.shape, info.dtype); + if (this.shouldCheckForMemLeaks()) { + // Track the number of moves during a kernel execution to correctly + // detect memory leaks. + this.state.numDataMovesStack[this.state.numDataMovesStack.length - 1]++; + } + }; + Engine.prototype.tidy = function (nameOrFn, fn) { + var _this = this; + var name = null; + if (fn == null) { + // Called with only 1 argument. + if (typeof nameOrFn !== 'function') { + throw new Error('Please provide a function to tidy()'); + } + fn = nameOrFn; + } + else { + // Called with 2 arguments. + if (typeof nameOrFn !== 'string' && !(nameOrFn instanceof String)) { + throw new Error('When calling with two arguments, the first argument ' + + 'to tidy() must be a string'); + } + if (typeof fn !== 'function') { + throw new Error('When calling with two arguments, the 2nd argument ' + + 'to tidy() must be a function'); + } + name = nameOrFn; + // TODO(nsthorat,smilkov): Do operation logging and performance + // profiling. + } + var result; + return this.scopedRun(function () { return _this.startScope(name); }, function () { return _this.endScope(result); }, function () { + result = fn(); + if (result instanceof Promise) { + console.error('Cannot return a Promise inside of tidy.'); + } + return result; + }); + }; + Engine.prototype.scopedRun = function (start, end, f) { + start(); + try { + var res = f(); + end(); + return res; + } + catch (ex) { + end(); + throw ex; + } + }; + Engine.prototype.nextTensorId = function () { + return Engine.nextTensorId++; + }; + Engine.prototype.nextVariableId = function () { + return Engine.nextVariableId++; + }; + /** + * This method is called instead of the public-facing tensor.clone() when + * saving a tensor for backwards pass. It makes sure to add the clone + * operation to the tape regardless of being called inside a kernel + * execution. + * + * This method will go away once all kernels are modularized since we won't + * need to turn off the tape inside runKernel(). + */ + Engine.prototype.clone = function (x) { + var y = this.makeTensorFromDataId(x.dataId, x.shape, x.dtype); + var inputs = { x: x }; + var grad = function (dy) { return ({ x: function () { return dy.toFloat(); } }); }; + var saved = []; + this.addTapeNode(this.state.activeScope.name, inputs, [y], grad, saved, {}); + return y; + }; + /** + * Execute a kernel with the given name and return the output tensor. + * + * @param kernelName The name of the kernel to execute. + * @param inputs A map of input names to tensors. + * @param attrs A map of attribute names to their values. An attribute is a + * primitive (non-tensor) input to the kernel. + * @param inputsToSave A list of tensors, inputs to save for the backprop + * computation. + * @param outputsToSave A list of booleans, specifying which output to save + * for the backprop computation. These are booleans since the output + * tensors are not visible to the user. + */ + Engine.prototype.runKernel = function (kernelName, inputs, attrs, inputsToSave, outputsToSave) { + var forwardFunc = null; + var backwardsFunc = null; + // Call runKernel as a stop-gap until we modularize all kernels. + // Once we modularize all kernels, we will remove the existing + // `runKernelFunc`. + return this.runKernelFunc(forwardFunc, inputs, backwardsFunc, kernelName, attrs, inputsToSave, outputsToSave); + }; + Engine.prototype.shouldCheckForMemLeaks = function () { + return this.ENV.getBool('IS_TEST'); + }; + Engine.prototype.checkKernelForMemLeak = function (kernelName, numDataIdsBefore, outInfos) { + var numDataIdsAfter = this.backend.numDataIds(); + // Count the number of data ids associated with the result of the kernel. + var numOutputDataIds = 0; + outInfos.forEach(function (info) { + // Complex numbers allocate 3 data ids, one for 'real', one for + // 'imaginary', and one for the container that holds the former two. + numOutputDataIds += (info.dtype === 'complex64' ? 3 : 1); + }); + // Account for the number of moves during kernel execution. A "data move" + // can happen in the middle of a kernel execution, placing a new (key,value) + // pair in the data storage. Since data moves have net zero effect (we + // always remove the data from the old backend), we have to cancel them out + // when detecting memory leaks. + var numMoves = this.state.numDataMovesStack[this.state.numDataMovesStack.length - 1]; + var dataIdsLeaked = numDataIdsAfter - numDataIdsBefore - numOutputDataIds - numMoves; + if (dataIdsLeaked > 0) { + throw new Error("Backend '" + this.backendName + "' has an internal memory leak " + + ("(" + dataIdsLeaked + " data ids) after running '" + kernelName + "'")); + } + }; + /** + * @deprecated Use `runKernel` for newly added kernels. Keep using this method + * only for kernels that are not yet fully modularized. + */ + Engine.prototype.runKernelFunc = function (forwardFunc, inputs, backwardsFunc, kernelName, attrs, inputsToSave, outputsToSave) { + var _this = this; + var outputs; + var saved = []; + var isTapeOn = this.isTapeOn(); + if (kernelName == null) { + kernelName = + this.state.activeScope != null ? this.state.activeScope.name : ''; + } + var startingBytecount = this.state.numBytes; + var startingNumTensors = this.state.numTensors; + if (this.shouldCheckForMemLeaks()) { + this.state.numDataMovesStack.push(0); + } + var kernelFunc; + var kernel = getKernel(kernelName, this.backendName); + var out; + if (kernel != null) { + kernelFunc = function () { + var numDataIdsBefore = _this.backend.numDataIds(); + out = kernel.kernelFunc({ inputs: inputs, attrs: attrs, backend: _this.backend }); + var outInfos = Array.isArray(out) ? out : [out]; + if (_this.shouldCheckForMemLeaks()) { + _this.checkKernelForMemLeak(kernelName, numDataIdsBefore, outInfos); + } + var outTensors = outInfos.map(function (_a) { + var dataId = _a.dataId, shape = _a.shape, dtype = _a.dtype; + return _this.makeTensorFromDataId(dataId, shape, dtype); + }); + // Save the inputs and outputs. + // Do not save unless we are recording to the tape. Otherwise it would + // cause a mem leak since we would never run backprop, which disposes + // the kept tensors. + if (isTapeOn) { + var tensorsToSave = _this.getTensorsForGradient(kernelName, inputs, outTensors); + if (tensorsToSave == null) { + // Fallback for ops that call runKernelFunc and pass in + // inputsToSave and outputsToSave. Currently this is the set of ops + // with kernel support in the WASM backend. Once those ops and + // respective gradients are modularised we can remove this path. + if (outputsToSave == null) { + outputsToSave = []; + } + var outsToSave = outTensors.filter(function (_, i) { return outputsToSave[i]; }); + tensorsToSave = (inputsToSave || []).slice().concat(outsToSave); + } + saved = _this.saveTensorsForBackwardMode(tensorsToSave); + } + return outTensors; + }; + } + else { + var saveFunc_1 = function (tensors) { + // Do not save unless we are recording to the tape. Otherwise it would + // cause a mem leak since we would never run backprop, which disposes + // the kept tensors. + if (!isTapeOn) { + return; + } + saved = tensors.map(function (tensor) { return _this.keep(_this.clone(tensor)); }); + }; + kernelFunc = function () { + var numDataIdsBefore = _this.backend.numDataIds(); + out = _this.tidy(function () { return forwardFunc(_this.backend, saveFunc_1); }); + var outs = (Array.isArray(out) ? out : [out]); + if (_this.shouldCheckForMemLeaks()) { + _this.checkKernelForMemLeak(kernelName, numDataIdsBefore, outs); + } + return outs; + }; + } + // Stop recording to a tape when running a kernel. + this.scopedRun(function () { return _this.state.kernelDepth++; }, function () { return _this.state.kernelDepth--; }, function () { + if (!_this.ENV.getBool('DEBUG')) { + outputs = kernelFunc(); + } + else { + outputs = _this.profiler.profileKernel(kernelName, inputs, function () { return kernelFunc(); }); + } + }); + if (isTapeOn) { + this.addTapeNode(kernelName, inputs, outputs, backwardsFunc, saved, attrs); + } + if (this.state.profiling) { + this.state.activeProfile.kernels.push({ + name: kernelName, + bytesAdded: this.state.numBytes - startingBytecount, + totalBytesSnapshot: this.state.numBytes, + tensorsAdded: this.state.numTensors - startingNumTensors, + totalTensorsSnapshot: this.state.numTensors, + inputShapes: Object.keys(inputs).map(function (key) { return inputs[key].shape; }), + outputShapes: outputs.map(function (item) { return item.shape; }) + }); + } + return (Array.isArray(out) ? outputs : outputs[0]); + }; + /** + * Saves tensors used in forward mode for use in backward mode. + * + * @param tensors the list of tensors to save. + */ + Engine.prototype.saveTensorsForBackwardMode = function (tensors) { + var _this = this; + var saved = tensors.map(function (tensor) { return _this.keep(_this.clone(tensor)); }); + return saved; + }; + /** + * Returns a list of tensors to save for a given gradient calculation. + * + * Returns undefined if their is no registered gradient for this kernel in the + * gradient registry. + * + * @param kernelName name of kernel to look up gradient for. + * @param inputs a map of input tensors. + * @param outputs an array of output tensors from forward mode of kernel. + */ + Engine.prototype.getTensorsForGradient = function (kernelName, inputs, outputs) { + var gradConfig = getGradient(kernelName); + if (gradConfig != null) { + var inputsToSave = gradConfig.inputsToSave || []; + var outputsToSave_1 = gradConfig.outputsToSave || []; + // If saveAllInputs is true, all inputs will be saved. Otherwise, inputs + // specified in inputsToSave will be saved. + var inputTensorsToSave = void 0; + if (gradConfig.saveAllInputs) { + assert(Array.isArray(inputs), function () { return 'saveAllInputs is true, expected inputs to be an array.'; }); + inputTensorsToSave = Object.keys(inputs).map(function (key) { return inputs[key]; }); + } + else { + inputTensorsToSave = inputsToSave.map(function (inputName) { return inputs[inputName]; }); + } + var outputTensorsToSave = outputs.filter(function (_, i) { return outputsToSave_1[i]; }); + return inputTensorsToSave.concat(outputTensorsToSave); + } + // TODO(yassogba) throw exception here once all runkernelFunc calls with + // inputsToSave/outputsToSave are removed + return null; + }; + /** + * Internal method used by public APIs for tensor creation. Makes a new + * tensor with the provided shape, dtype and values. It always + * creates a new data id and writes the values to the underlying backend. + */ + Engine.prototype.makeTensor = function (values, shape, dtype, backend) { + if (values == null) { + throw new Error('Values passed to engine.makeTensor() are null'); + } + dtype = dtype || 'float32'; + backend = backend || this.backend; + var backendVals = values; + if (dtype === 'string' && isString(values[0])) { + backendVals = values.map(function (d) { return encodeString(d); }); + } + var dataId = backend.write(backendVals, shape, dtype); + var t = new Tensor(shape, dtype, dataId, this.nextTensorId()); + this.incRef(t, backend); + // Count bytes for string tensors. + if (dtype === 'string') { + var info = this.state.tensorInfo.get(dataId); + var newBytes = bytesFromStringArray(backendVals); + this.state.numBytes += newBytes - info.bytes; + info.bytes = newBytes; + } + return t; + }; + /** + * Internal method used by backends. Makes a new tensor + * that is a wrapper around an existing data id. It doesn't create + * a new data id, only increments the ref count used in memory tracking. + */ + Engine.prototype.makeTensorFromDataId = function (dataId, shape, dtype, backend) { + dtype = dtype || 'float32'; + var t = new Tensor(shape, dtype, dataId, this.nextTensorId()); + this.incRef(t, backend); + return t; + }; + Engine.prototype.makeVariable = function (initialValue, trainable, name, dtype) { + if (trainable === void 0) { trainable = true; } + name = name || this.nextVariableId().toString(); + if (dtype != null && dtype !== initialValue.dtype) { + initialValue = initialValue.cast(dtype); + } + var v = new Variable(initialValue, trainable, name, this.nextTensorId()); + if (this.state.registeredVariables[v.name] != null) { + throw new Error("Variable with name " + v.name + " was already registered"); + } + this.state.registeredVariables[v.name] = v; + this.incRef(v, this.backend); + return v; + }; + Engine.prototype.incRef = function (a, backend) { + var refCount = this.state.tensorInfo.has(a.dataId) ? + this.state.tensorInfo.get(a.dataId).refCount : + 0; + this.state.numTensors++; + if (a.dtype === 'string') { + this.state.numStringTensors++; + } + if (refCount === 0) { + this.state.numDataBuffers++; + // Bytes for complex numbers are counted by their components. Bytes for + // string tensors are counted when writing values. + var bytes = 0; + if (a.dtype !== 'complex64' && a.dtype !== 'string') { + bytes = a.size * bytesPerElement(a.dtype); + } + this.state.tensorInfo.set(a.dataId, { + backend: backend || this.backend, + dtype: a.dtype, + shape: a.shape, + bytes: bytes, + refCount: 0 + }); + this.state.numBytes += bytes; + } + this.state.tensorInfo.get(a.dataId).refCount++; + if (!(a instanceof Variable)) { + this.track(a); + } + }; + Engine.prototype.disposeTensor = function (a) { + if (!this.state.tensorInfo.has(a.dataId)) { + return; + } + this.state.numTensors--; + if (a.dtype === 'string') { + this.state.numStringTensors--; + } + var info = this.state.tensorInfo.get(a.dataId); + var refCount = info.refCount; + if (refCount <= 1) { + // Don't count bytes for complex numbers as they are counted by their + // components. + if (a.dtype !== 'complex64') { + this.state.numBytes -= info.bytes; + } + this.state.numDataBuffers--; + info.backend.disposeData(a.dataId); + this.state.tensorInfo.delete(a.dataId); + } + else { + this.state.tensorInfo.get(a.dataId).refCount--; + } + // TODO(nsthorat): Construct an error and save the stack trace for + // debugging when in debug mode. Creating a stack trace is too expensive + // to do unconditionally. + }; + Engine.prototype.disposeVariables = function () { + for (var varName in this.state.registeredVariables) { + var v = this.state.registeredVariables[varName]; + this.disposeVariable(v); + } + }; + Engine.prototype.disposeVariable = function (v) { + this.disposeTensor(v); + if (this.state.registeredVariables[v.name] != null) { + delete this.state.registeredVariables[v.name]; + } + }; + Engine.prototype.memory = function () { + var info = this.backend.memory(); + info.numTensors = this.state.numTensors; + info.numDataBuffers = this.state.numDataBuffers; + info.numBytes = this.state.numBytes; + if (this.state.numStringTensors > 0) { + info.unreliable = true; + if (info.reasons == null) { + info.reasons = []; + } + info.reasons.push('Memory usage by string tensors is approximate ' + + '(2 bytes per character)'); + } + return info; + }; + Engine.prototype.profile = function (query) { + return __awaiter(this, void 0, void 0, function () { + var startBytes, startNumTensors, _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + this.state.profiling = true; + startBytes = this.state.numBytes; + startNumTensors = this.state.numTensors; + this.state.activeProfile.kernels = []; + _a = this.state.activeProfile; + return [4 /*yield*/, query()]; + case 1: + _a.result = _b.sent(); + this.state.profiling = false; + this.state.activeProfile.peakBytes = Math.max.apply(Math, this.state.activeProfile.kernels.map(function (d) { return d.totalBytesSnapshot; })); + this.state.activeProfile.newBytes = this.state.numBytes - startBytes; + this.state.activeProfile.newTensors = + this.state.numTensors - startNumTensors; + return [2 /*return*/, this.state.activeProfile]; + } + }); + }); + }; + Engine.prototype.isTapeOn = function () { + return this.state.gradientDepth > 0 && this.state.kernelDepth === 0; + }; + Engine.prototype.addTapeNode = function (kernelName, inputs, outputs, gradientsFunc, saved, attrs) { + var _this = this; + var tapeNode = { id: this.state.nextTapeNodeId++, kernelName: kernelName, inputs: inputs, outputs: outputs, saved: saved }; + var gradConfig = getGradient(kernelName); + if (gradConfig != null) { + gradientsFunc = gradConfig.gradFunc; + } + if (gradientsFunc != null) { + tapeNode.gradient = function (dys) { + // TODO(smilkov): To optimize back-prop, pass dys that are not used in + // the backprop graph to the user as null instead of zeros + dys = dys.map(function (dy, i) { + if (dy == null) { + var output = outputs[i]; + var vals = makeZerosTypedArray(output.size, output.dtype); + return _this.makeTensor(vals, output.shape, output.dtype); + } + return dy; + }); + // Grad functions of ops with single outputs expect a dy, while ops + // with multiple outputs expect dys (array of dy). + return gradientsFunc(dys.length > 1 ? dys : dys[0], saved, attrs); + }; + } + this.state.activeTape.push(tapeNode); + }; + Engine.prototype.keep = function (result) { + result.kept = true; + return result; + }; + Engine.prototype.startTape = function () { + if (this.state.gradientDepth === 0) { + this.state.activeTape = []; + } + this.state.gradientDepth++; + }; + Engine.prototype.endTape = function () { + this.state.gradientDepth--; + }; + /** + * Start a scope. Use this with endScope() to achieve the same functionality + * as scope() without the need for a function closure. + */ + Engine.prototype.startScope = function (name) { + var scopeInfo = { + track: [], + name: 'unnamed scope', + id: this.state.nextScopeId++ + }; + if (name) { + scopeInfo.name = name; + } + this.state.scopeStack.push(scopeInfo); + this.state.activeScope = scopeInfo; + }; + /** + * End a scope. Use this with startScope() to achieve the same functionality + * as scope() without the need for a function closure. + */ + Engine.prototype.endScope = function (result) { + var _this = this; + var tensorsToTrackInParent = getTensorsInContainer(result); + var tensorsToTrackInParentSet = new Set(tensorsToTrackInParent.map(function (t) { return t.id; })); + // Dispose the arrays tracked in this scope. + for (var i = 0; i < this.state.activeScope.track.length; i++) { + var tensor = this.state.activeScope.track[i]; + if (!tensor.kept && !tensorsToTrackInParentSet.has(tensor.id)) { + tensor.dispose(); + } + } + var oldScope = this.state.scopeStack.pop(); + this.state.activeScope = this.state.scopeStack.length === 0 ? + null : + this.state.scopeStack[this.state.scopeStack.length - 1]; + // Track the current result in the parent scope. + tensorsToTrackInParent.forEach(function (tensor) { + // Only track the tensor if was allocated in the inner scope and is not + // globally kept. + if (!tensor.kept && tensor.scopeId === oldScope.id) { + _this.track(tensor); + } + }); + }; + /** + * Returns gradients of `f` with respect to each of the `xs`. The gradients + * returned are of the same length as `xs`, but some might be null if `f` + * was not a function of that `x`. It also takes optional dy to multiply the + * gradient, which defaults to `1`. + */ + Engine.prototype.gradients = function (f, xs, dy, allowNoGradients) { + var _this = this; + if (allowNoGradients === void 0) { allowNoGradients = false; } + assert(xs.length > 0, function () { return 'gradients() received an empty list of xs.'; }); + if (dy != null && dy.dtype !== 'float32') { + throw new Error("dy must have 'float32' dtype, but has '" + dy.dtype + "'"); + } + var y = this.scopedRun(function () { return _this.startTape(); }, function () { return _this.endTape(); }, function () { return _this.tidy('forward', f); }); + assert(y instanceof Tensor, function () { return 'The result y returned by f() must be a tensor.'; }); + // Filter out the nodes that don't connect x => y. + var filteredTape = getFilteredNodesXToY(this.state.activeTape, xs, y); + if (!allowNoGradients && filteredTape.length === 0 && xs.length > 0) { + throw new Error('Cannot compute gradient of y=f(x) with respect to x. Make sure ' + + 'that the f you passed encloses all operations that lead from x ' + + 'to y.'); + } + return this.tidy('backward', function () { + var accumulatedGradientMap = {}; + accumulatedGradientMap[y.id] = (dy == null) ? ones(y.shape) : dy; + // Backprop gradients through the filtered nodes. + backpropagateGradients(accumulatedGradientMap, filteredTape, + // Pass the tidy function to avoid circular dep with `tape.ts`. + function (f) { return _this.tidy(f); }); + var grads = xs.map(function (x) { return accumulatedGradientMap[x.id]; }); + if (_this.state.gradientDepth === 0) { + // This means that we are not computing higher-order gradients + // and can clean up the tape. + _this.state.activeTape.forEach(function (node) { + for (var _i = 0, _a = node.saved; _i < _a.length; _i++) { + var tensor = _a[_i]; + tensor.dispose(); + } + }); + _this.state.activeTape = null; + } + return { value: y, grads: grads }; + }); + }; + Engine.prototype.customGrad = function (f) { + var _this = this; + assert(isFunction(f), function () { return 'The f passed in customGrad(f) must be a function.'; }); + return function () { + var inputs = []; + for (var _i = 0; _i < arguments.length; _i++) { + inputs[_i] = arguments[_i]; + } + assert(inputs.every(function (t) { return t instanceof Tensor; }), function () { return 'The args passed in customGrad(f)(x1, x2,...) must all be ' + + 'tensors'; }); + var res; + var inputMap = {}; + inputs.forEach(function (input, i) { + inputMap[i] = input; + }); + return _this.runKernelFunc(function (_, save) { + res = f.apply(void 0, inputs.concat([save])); + assert(res.value instanceof Tensor, function () { return 'The function f passed in customGrad(f) must return an ' + + 'object where `obj.value` is a tensor'; }); + assert(isFunction(res.gradFunc), function () { return 'The function f passed in customGrad(f) must return an ' + + 'object where `obj.gradFunc` is a function.'; }); + return res.value; + }, inputMap, function (dy, saved) { + var gradRes = res.gradFunc(dy, saved); + var grads = Array.isArray(gradRes) ? gradRes : [gradRes]; + assert(grads.length === inputs.length, function () { return 'The function f passed in customGrad(f) must return an ' + + 'object where `obj.gradFunc` is a function that returns ' + + 'the same number of tensors as inputs passed to f(...).'; }); + assert(grads.every(function (t) { return t instanceof Tensor; }), function () { return 'The function f passed in customGrad(f) must return an ' + + 'object where `obj.gradFunc` is a function that returns ' + + 'a list of only tensors.'; }); + var gradMap = {}; + grads.forEach(function (grad, i) { + gradMap[i] = function () { return grad; }; + }); + return gradMap; + }); + }; + }; + Engine.prototype.readSync = function (dataId) { + // Route the read to the correct backend. + var info = this.state.tensorInfo.get(dataId); + return info.backend.readSync(dataId); + }; + Engine.prototype.read = function (dataId) { + // Route the read to the correct backend. + var info = this.state.tensorInfo.get(dataId); + return info.backend.read(dataId); + }; + Engine.prototype.time = function (query) { + return __awaiter(this, void 0, void 0, function () { + var start, timingInfo; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + start = now(); + return [4 /*yield*/, this.backend.time(query)]; + case 1: + timingInfo = _a.sent(); + timingInfo.wallMs = now() - start; + return [2 /*return*/, timingInfo]; + } + }); + }); + }; + /** + * Tracks a Tensor in the current scope to be automatically cleaned up + * when the current scope ends, and returns the value. + * + * @param result The Tensor to track in the current scope. + */ + Engine.prototype.track = function (result) { + if (this.state.activeScope != null) { + result.scopeId = this.state.activeScope.id; + this.state.activeScope.track.push(result); + } + return result; + }; + Object.defineProperty(Engine.prototype, "registeredVariables", { + get: function () { + return this.state.registeredVariables; + }, + enumerable: true, + configurable: true + }); + /** + * Resets the engine state. Removes all backends but does not remove + * registered backend factories. + */ + Engine.prototype.reset = function () { + // Make any pending promise obsolete. + this.pendingBackendInitId++; + this.state.dispose(); + this.ENV.reset(); + this.state = new EngineState(); + for (var backendName in this.registry) { + this.disposeRegisteredKernels(backendName); + this.registry[backendName].dispose(); + delete this.registry[backendName]; + } + this.backendName = null; + this.backendInstance = null; + this.pendingBackendInit = null; + }; + Engine.nextTensorId = 0; + Engine.nextVariableId = 0; + return Engine; + }()); + function ones(shape) { + var values = makeOnesTypedArray(sizeFromShape(shape), 'float32'); + return ENGINE.makeTensor(values, shape, 'float32'); + } + function getOrMakeEngine() { + var ns = getGlobalNamespace(); + if (ns._tfengine == null) { + var environment = new Environment(ns); + ns._tfengine = new Engine(environment); + } + setEnvironmentGlobal(ns._tfengine.ENV); + // Tell the current tensor interface that the global engine is responsible + // for tracking. + setTensorTracker(function () { return ns._tfengine; }); + return ns._tfengine; + } + var ENGINE = getOrMakeEngine(); + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // tslint:disable-next-line:no-any + function _isNavigatorDefined() { + return typeof navigator !== 'undefined' && navigator != null; + } + function isMobile() { + if (_isNavigatorDefined()) { + // tslint:disable-next-line:no-any + var a = navigator.userAgent || navigator.vendor || window.opera; + // tslint:disable-next-line:max-line-length + return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i + .test(a) || + // tslint:disable-next-line:max-line-length + /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i + .test(a.substr(0, 4)); + } + return false; + } + function isBrowser() { + return (typeof window !== 'undefined' && window.document != null) || + //@ts-ignore + (typeof WorkerGlobalScope !== 'undefined'); + } + + var device_util = { + __proto__: null, + isMobile: isMobile, + isBrowser: isBrowser + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var ENV = env(); + /** + * This file contains environment-related flag registrations. + */ + /** Whether to enable debug mode. */ + ENV.registerFlag('DEBUG', function () { return false; }, function (debugValue) { + if (debugValue) { + console.warn('Debugging mode is ON. The output of every math call will ' + + 'be downloaded to CPU and checked for NaNs. ' + + 'This significantly impacts performance.'); + } + }); + /** Whether we are in a browser (as versus, say, node.js) environment. */ + ENV.registerFlag('IS_BROWSER', function () { return isBrowser(); }); + /** Whether we are in a browser (as versus, say, node.js) environment. */ + ENV.registerFlag('IS_NODE', function () { return (typeof process !== 'undefined') && + (typeof process.versions !== 'undefined') && + (typeof process.versions.node !== 'undefined'); }); + /** Whether this browser is Chrome. */ + ENV.registerFlag('IS_CHROME', function () { return typeof navigator !== 'undefined' && navigator != null && + navigator.userAgent != null && /Chrome/.test(navigator.userAgent) && + /Google Inc/.test(navigator.vendor); }); + /** + * True when the environment is "production" where we disable safety checks + * to gain performance. + */ + ENV.registerFlag('PROD', function () { return false; }); + /** + * Whether to do sanity checks when inferring a shape from user-provided + * values, used when creating a new tensor. + */ + ENV.registerFlag('TENSORLIKE_CHECK_SHAPE_CONSISTENCY', function () { return ENV.getBool('DEBUG'); }); + /** Whether deprecation warnings are enabled. */ + ENV.registerFlag('DEPRECATION_WARNINGS_ENABLED', function () { return true; }); + /** True if running unit tests. */ + ENV.registerFlag('IS_TEST', function () { return false; }); + + var Abs = 'Abs'; + var Acos = 'Acos'; + var Acosh = 'Acosh'; + var Add = 'Add'; + var AddN = 'AddN'; + var All = 'All'; + var Any = 'Any'; + var ArgMax = 'ArgMax'; + var ArgMin = 'ArgMin'; + var Asin = 'Asin'; + var Asinh = 'Asinh'; + var Atan = 'Atan'; + var Atanh = 'Atanh'; + var Atan2 = 'Atan2'; + var AvgPool = 'AvgPool'; + var AvgPoolBackprop = 'AvgPoolBackprop'; + var AvgPool3D = 'AvgPool3D'; + var AvgPool3DBackprop = 'AvgPool3DBackprop'; + var BatchMatMul = 'BatchMatMul'; + var BatchToSpaceND = 'BatchToSpaceND'; + var BroadcastTo = 'BroadcastTo'; + var Cast = 'Cast'; + var Ceil = 'Ceil'; + var ClipByValue = 'ClipByValue'; + var Complex = 'Complex'; + var Concat = 'Concat'; + var Conv2D = 'Conv2D'; + var Conv2DBackpropFilter = 'Conv2DBackpropFilter'; + var Conv2DBackpropInput = 'Conv2DBackpropInput'; + var Conv3D = 'Conv3D'; + var Conv3DBackpropFilterV2 = 'Conv3DBackpropFilterV2'; + var Conv3DBackpropInputV2 = 'Conv3DBackpropInputV2'; + var Cos = 'Cos'; + var Cosh = 'Cosh'; + var Cumsum = 'Cumsum'; + var CropAndResize = 'CropAndResize'; + var DepthToSpace = 'DepthToSpace'; + var DepthwiseConv2dNative = 'DepthwiseConv2dNative'; + var DepthwiseConv2dNativeBackpropFilter = 'DepthwiseConv2dNativeBackpropFilter'; + var DepthwiseConv2dNativeBackpropInput = 'DepthwiseConv2dNativeBackpropInput'; + var Diag = 'Diag'; + var Dilation2D = 'Dilation2D'; + var Dilation2DBackpropInput = 'Dilation2DBackpropInput'; + var Dilation2DBackpropFilter = 'Dilation2DBackpropFilter'; + var Div = 'Div'; + var Elu = 'Elu'; + var EluGrad = 'EluGrad'; + var Erf = 'Erf'; + var Equal = 'Equal'; + var Exp = 'Exp'; + var Expm1 = 'Expm1'; + var FFT = 'FFT'; + var Floor = 'Floor'; + var FloorDiv = 'FloorDiv'; + var Fill = 'Fill'; + var FusedBatchNorm = 'FusedBatchNorm'; + var GatherV2 = 'GatherV2'; + var GatherNd = 'GatherNd'; + var Greater = 'Greater'; + var GreaterEqual = 'GreaterEqual'; + var Identity = 'Identity'; + var IFFT = 'IFFT'; + var Imag = 'Imag'; + var IsFinite = 'IsFinite'; + var IsInf = 'IsInf'; + var IsNan = 'IsNan'; + var Less = 'Less'; + var LessEqual = 'LessEqual'; + var LinSpace = 'LinSpace'; + var Log = 'Log'; + var Log1p = 'Log1p'; + var LogicalAnd = 'LogicalAnd'; + var LogicalNot = 'LogicalNot'; + var LogicalOr = 'LogicalOr'; + var LogSoftmax = 'LogSoftmax'; + var LRN = 'LRN'; + var LRNBackprop = 'LRNBackprop'; + var Max = 'Max'; + var Maximum = 'Maximum'; + var MaxPool = 'MaxPool'; + var MaxPoolBackprop = 'MaxPoolBackprop'; + var MaxPool3D = 'MaxPool3D'; + var MaxPool3DBackprop = 'MaxPool3DBackprop'; + var MaxPoolWithArgmax = 'MaxPoolWithArgmax'; + var Mean = 'Mean'; + var Min = 'Min'; + var Minimum = 'Minimum'; + var Mod = 'Mod'; + var Multiply = 'Multiply'; + var Negate = 'Negate'; + var NotEqual = 'NotEqual'; + var NonMaxSuppressionV3 = 'NonMaxSuppressionV3'; + var NonMaxSuppressionV4 = 'NonMaxSuppressionV4'; + var NonMaxSuppressionV5 = 'NonMaxSuppressionV5'; + var OnesLike = 'OnesLike'; + var OneHot = 'OneHot'; + var PadV2 = 'PadV2'; + var Pool = 'Pool'; + var Pow = 'Pow'; + var Prelu = 'Prelu'; + var Prod = 'Prod'; + var Range = 'Range'; + var Real = 'Real'; + var Reciprocal = 'Reciprocal'; + var Relu = 'Relu'; + var Reshape = 'Reshape'; + var ResizeNearestNeighbor = 'ResizeNearestNeighbor'; + var ResizeNearestNeighborGrad = 'ResizeNearestNeighborGrad'; + var ResizeBilinear = 'ResizeBilinear'; + var ResizeBilinearGrad = 'ResizeBilinearGrad'; + var Relu6 = 'Relu6'; + var Reverse = 'Reverse'; + var Round = 'Round'; + var Rsqrt = 'Rsqrt'; + var ScatterNd = 'ScatterNd'; + var SelectV2 = 'SelectV2'; + var Selu = 'Selu'; + var Slice = 'Slice'; + var Sin = 'Sin'; + var Sinh = 'Sinh'; + var Sign = 'Sign'; + var Sigmoid = 'Sigmoid'; + var Softplus = 'Softplus'; + var Sqrt = 'Sqrt'; + var Sum = 'Sum'; + var SpaceToBatchND = 'SpaceToBatchND'; + var SplitV = 'SplitV'; + var Softmax = 'Softmax'; + var SquaredDifference = 'SquaredDifference'; + var Square = 'Square'; + var Sub = 'Sub'; + var SparseToDense = 'SparseToDense'; + var StridedSlice = 'StridedSlice'; + var Tan = 'Tan'; + var Tanh = 'Tanh'; + var Tile = 'Tile'; + var TopK = 'TopK'; + var Transpose = 'Transpose'; + var Unpack = 'Unpack'; + var UnsortedSegmentSum = 'UnsortedSegmentSum'; + var ZerosLike = 'ZerosLike'; + /** + * TensorFlow.js-only kernels + */ + var Step = 'Step'; + var FromPixels = 'FromPixels'; + var RotateWithOffset = 'RotateWithOffset'; + var _FusedMatMul = '_FusedMatMul'; + var FusedConv2D = 'FusedConv2D'; + var FusedDepthwiseConv2D = 'FusedDepthwiseConv2D'; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function inferShape(val, dtype) { + var firstElem = val; + if (isTypedArray(val)) { + return dtype === 'string' ? [] : [val.length]; + } + if (!Array.isArray(val)) { + return []; // Scalar. + } + var shape = []; + while (Array.isArray(firstElem) || + isTypedArray(firstElem) && dtype !== 'string') { + shape.push(firstElem.length); + firstElem = firstElem[0]; + } + if (Array.isArray(val) && + env().getBool('TENSORLIKE_CHECK_SHAPE_CONSISTENCY')) { + deepAssertShapeConsistency(val, shape, []); + } + return shape; + } + function deepAssertShapeConsistency(val, shape, indices) { + indices = indices || []; + if (!(Array.isArray(val)) && !isTypedArray(val)) { + assert(shape.length === 0, function () { return "Element arr[" + indices.join('][') + "] is a primitive, " + + ("but should be an array/TypedArray of " + shape[0] + " elements"); }); + return; + } + assert(shape.length > 0, function () { return "Element arr[" + indices.join('][') + "] should be a primitive, " + + ("but is an array of " + val.length + " elements"); }); + assert(val.length === shape[0], function () { return "Element arr[" + indices.join('][') + "] should have " + shape[0] + " " + + ("elements, but has " + val.length + " elements"); }); + var subShape = shape.slice(1); + for (var i = 0; i < val.length; ++i) { + deepAssertShapeConsistency(val[i], subShape, indices.concat(i)); + } + } + function assertDtype(expectedDtype, actualDType, argName, functionName) { + if (expectedDtype == null) { + return; + } + if (expectedDtype !== 'numeric' && expectedDtype !== actualDType || + expectedDtype === 'numeric' && actualDType === 'string') { + throw new Error("Argument '" + argName + "' passed to '" + functionName + "' must " + + ("be " + expectedDtype + " tensor, but got " + actualDType + " tensor")); + } + } + function convertToTensor(x, argName, functionName, parseAsDtype) { + if (parseAsDtype === void 0) { parseAsDtype = 'numeric'; } + if (x instanceof Tensor) { + assertDtype(parseAsDtype, x.dtype, argName, functionName); + return x; + } + var inferredDtype = inferDtype(x); + // If the user expects a bool/int/float, use that info to update the + // inferredDtype when it is not a string. + if (inferredDtype !== 'string' && + ['bool', 'int32', 'float32'].indexOf(parseAsDtype) >= 0) { + inferredDtype = parseAsDtype; + } + assertDtype(parseAsDtype, inferredDtype, argName, functionName); + if ((x == null) || + (!isTypedArray(x) && !Array.isArray(x) && typeof x !== 'number' && + typeof x !== 'boolean' && typeof x !== 'string')) { + var type = x == null ? 'null' : x.constructor.name; + throw new Error("Argument '" + argName + "' passed to '" + functionName + "' must be a " + + ("Tensor or TensorLike, but got '" + type + "'")); + } + var inferredShape = inferShape(x, inferredDtype); + if (!isTypedArray(x) && !Array.isArray(x)) { + x = [x]; + } + var skipTypedArray = true; + var values = inferredDtype !== 'string' ? + toTypedArray(x, inferredDtype) : + flatten(x, [], skipTypedArray); + return ENGINE.makeTensor(values, inferredShape, inferredDtype); + } + function convertToTensorArray(arg, argName, functionName, parseAsDtype) { + if (parseAsDtype === void 0) { parseAsDtype = 'numeric'; } + if (!Array.isArray(arg)) { + throw new Error("Argument " + argName + " passed to " + functionName + " must be a " + + '`Tensor[]` or `TensorLike[]`'); + } + var tensors = arg; + return tensors.map(function (t, i) { return convertToTensor(t, argName + "[" + i + "]", functionName); }, parseAsDtype); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Used for wrapping functions that perform math operations on + * Tensors. The function will be wrapped in a named scope that cleans all + * memory usage after the function is done. + */ + function op(f) { + var keys = Object.keys(f); + if (keys.length !== 1) { + throw new Error("Please provide an object with a single key " + + "(operation name) mapping to a function. Got an object with " + + (keys.length + " keys.")); + } + var opName = keys[0]; + var fn = f[opName]; + // Strip the underscore from the end of the function name. + if (opName.endsWith('_')) { + opName = opName.substring(0, opName.length - 1); + } + // tslint:disable-next-line:no-any + var f2 = function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + ENGINE.startScope(opName); + try { + var result = fn.apply(void 0, args); + if (result instanceof Promise) { + console.error('Cannot return a Promise inside of tidy.'); + } + ENGINE.endScope(result); + return result; + } + catch (ex) { + ENGINE.endScope(null); + throw ex; + } + }; + Object.defineProperty(f2, 'name', { value: opName, configurable: true }); + // tslint:disable-next-line:no-any + return f2; + } + + /** + * @license + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Casts a `tf.Tensor` to a new dtype. + * + * ```js + * const x = tf.tensor1d([1.5, 2.5, 3]); + * tf.cast(x, 'int32').print(); + * ``` + * @param x The input tensor to be casted. + * @param dtype The dtype to cast the input tensor to. + */ + /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ + function cast_(x, dtype) { + var $x = convertToTensor(x, 'x', 'cast'); + // Sanity checks. + if (!isValidDtype(dtype)) { + throw new Error("Failed to cast to unknown dtype " + dtype); + } + if (dtype === 'string' && $x.dtype !== 'string' || + dtype !== 'string' && $x.dtype === 'string') { + throw new Error('Only strings can be casted to strings'); + } + var inputs = { x: $x }; + var attrs = { dtype: dtype }; + return ENGINE.runKernelFunc(function (backend) { return backend.cast($x, dtype); }, inputs, null /* grad */, Cast, attrs); + } + var cast = op({ cast_: cast_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Multiplies two `tf.Tensor`s element-wise, A * B. Supports broadcasting. + * + * We also expose `tf.mulStrict` which has the same signature as this op and + * asserts that `a` and `b` are the same shape (does not broadcast). + * + * ```js + * const a = tf.tensor1d([1, 2, 3, 4]); + * const b = tf.tensor1d([2, 3, 4, 5]); + * + * a.mul(b).print(); // or tf.mul(a, b) + * ``` + * + * ```js + * // Broadcast mul a with b. + * const a = tf.tensor1d([1, 2, 3, 4]); + * const b = tf.scalar(5); + * + * a.mul(b).print(); // or tf.mul(a, b) + * ``` + * @param a The first tensor to multiply. + * @param b The second tensor to multiply. Must have the same dtype as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ + function mul_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'mul'); + var $b = convertToTensor(b, 'b', 'mul'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + var forward = function (backend, save) { + var res = backend.multiply($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Multiply); + } + var mul = op({ mul_: mul_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes step of the input `tf.Tensor` element-wise: `x > 0 ? 1 : alpha * x` + * + * ```js + * const x = tf.tensor1d([0, 2, -1, -3]); + * + * x.step(.5).print(); // or tf.step(x, .5) + * ``` + * @param x The input tensor. + * @param alpha The gradient when input is negative. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function step_(x, alpha) { + if (alpha === void 0) { alpha = 0.0; } + var $x = convertToTensor(x, 'x', 'step'); + var inputs = { x: $x }; + var attrs = { alpha: alpha }; + return ENGINE.runKernelFunc(function (backend) { return backend.step($x, alpha); }, inputs, null /* grad */, Step, attrs); + } + var step = op({ step_: step_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var absGradConfig = { + kernelName: Abs, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(dy, step(cast(x, 'float32'), -1)); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Divides two `tf.Tensor`s element-wise, A / B. Supports broadcasting. + * The result is rounded with floor function. + * + * + * ```js + * const a = tf.tensor1d([1, 4, 9, 16]); + * const b = tf.tensor1d([1, 2, 3, 4]); + * + * a.floorDiv(b).print(); // or tf.div(a, b) + * ``` + * + * ```js + * // Broadcast div a with b. + * const a = tf.tensor1d([2, 4, 6, 8]); + * const b = tf.scalar(2); + * + * a.floorDiv(b).print(); // or tf.floorDiv(a, b) + * ``` + * + * @param a The first tensor as the numerator. + * @param b The second tensor as the denominator. Must have the same dtype as + * `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ + function floorDiv_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'floorDiv'); + var $b = convertToTensor(b, 'b', 'floorDiv'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + var forward = function (backend, save) { + var res = backend.floorDiv($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, FloorDiv); + } + var floorDiv = op({ floorDiv_: floorDiv_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Divides two `tf.Tensor`s element-wise, A / B. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([1, 4, 9, 16]); + * const b = tf.tensor1d([1, 2, 3, 4]); + * + * a.div(b).print(); // or tf.div(a, b) + * ``` + * + * ```js + * // Broadcast div a with b. + * const a = tf.tensor1d([2, 4, 6, 8]); + * const b = tf.scalar(2); + * + * a.div(b).print(); // or tf.div(a, b) + * ``` + * + * @param a The first tensor as the numerator. + * @param b The second tensor as the denominator. Must have the same dtype as + * `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ + function div_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'div'); + var $b = convertToTensor(b, 'b', 'div'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + if ($a.dtype === 'int32' && $b.dtype === 'int32') { + return floorDiv($a, $b); + } + var forward = function (backend, save) { + var res = backend.realDivide($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + var attrs = {}; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Div, attrs); + } + var div = op({ div_: div_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes `-1 * x` element-wise. + * + * ```js + * const x = tf.tensor2d([1, 2, -2, 0], [2, 2]); + * + * x.neg().print(); // or tf.neg(x) + * ``` + * + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function neg_(x) { + var $x = convertToTensor(x, 'x', 'neg'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend) { return backend.neg($x); }, inputs, null /* grad */, Negate); + } + var neg = op({ neg_: neg_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** This is shared code across all tensor creation methods. */ + function makeTensor(values, shape, inferredShape, dtype) { + if (dtype == null) { + dtype = inferDtype(values); + } + if (dtype === 'complex64') { + throw new Error("Cannot construct a complex64 tensor directly. " + + "Please use tf.complex(real, imag)."); + } + if (!isTypedArray(values) && !Array.isArray(values) && + typeof values !== 'number' && typeof values !== 'boolean' && + typeof values !== 'string') { + throw new Error('values passed to tensor(values) must be a number/boolean/string or ' + + 'an array of numbers/booleans/strings, or a TypedArray'); + } + if (shape != null) { + assertNonNegativeIntegerDimensions(shape); + var providedSize_1 = sizeFromShape(shape); + var inferredSize_1 = sizeFromShape(inferredShape); + assert(providedSize_1 === inferredSize_1, function () { + return "Based on the provided shape, [" + shape + "], the tensor should have " + + (providedSize_1 + " values but has " + inferredSize_1); + }); + for (var i = 0; i < inferredShape.length; ++i) { + var inferred = inferredShape[i]; + var flatDimsDontMatch = i === inferredShape.length - 1 ? + inferred !== sizeFromShape(shape.slice(i)) : + true; + assert(inferredShape[i] === shape[i] || !flatDimsDontMatch, function () { return "Error creating a new Tensor. Inferred shape " + + ("(" + inferredShape + ") does not match the provided ") + + ("shape (" + shape + "). "); }); + } + } + if (!isTypedArray(values) && !Array.isArray(values)) { + values = [values]; + } + shape = shape || inferredShape; + values = dtype !== 'string' ? + toTypedArray(values, dtype) : + flatten(values, [], true); + return ENGINE.makeTensor(values, shape, dtype); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates rank-0 `tf.Tensor` (scalar) with the provided value and dtype. + * + * The same functionality can be achieved with `tf.tensor`, but in general + * we recommend using `tf.scalar` as it makes the code more readable. + * + * ```js + * tf.scalar(3.14).print(); + * ``` + * + * @param value The value of the scalar. + * @param dtype The data type. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function scalar(value, dtype) { + if (((isTypedArray(value) && dtype !== 'string') || Array.isArray(value)) && + dtype !== 'complex64') { + throw new Error('Error creating a new Scalar: value must be a primitive ' + + '(number|boolean|string)'); + } + if (dtype === 'string' && isTypedArray(value) && + !(value instanceof Uint8Array)) { + throw new Error('When making a scalar from encoded string, ' + + 'the value must be `Uint8Array`.'); + } + var shape = []; + var inferredShape = []; + return makeTensor(value, shape, inferredShape, dtype); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes square root of the input `tf.Tensor` element-wise: `y = sqrt(x)` + * + * ```js + * const x = tf.tensor1d([1, 2, 4, -1]); + * + * x.sqrt().print(); // or tf.sqrt(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function sqrt_(x) { + var $x = convertToTensor(x, 'x', 'sqrt'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.sqrt($x); + save([$x]); + return res; + }, inputs, null /* grad */, Sqrt); + } + var sqrt = op({ sqrt_: sqrt_ }); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes square of `x` element-wise: `x ^ 2` + * + * ```js + * const x = tf.tensor1d([1, 2, Math.sqrt(2), -1]); + * + * x.square().print(); // or tf.square(x) + * ``` + * @param x The input Tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function square_(x) { + var $x = convertToTensor(x, 'x', 'square'); + var attrs = {}; + var inputsToSave = [$x]; + var outputsToSave = []; + return ENGINE.runKernelFunc(function (backend, save) { + save([$x]); + return backend.square($x); + }, { x: $x }, null /* grad */, 'Square', attrs, inputsToSave, outputsToSave); + } + var square = op({ square_: square_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Subtracts two `tf.Tensor`s element-wise, A - B. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([10, 20, 30, 40]); + * const b = tf.tensor1d([1, 2, 3, 4]); + * + * a.sub(b).print(); // or tf.sub(a, b) + * ``` + * + * ```js + * // Broadcast subtract a with b. + * const a = tf.tensor1d([10, 20, 30, 40]); + * const b = tf.scalar(5); + * + * a.sub(b).print(); // or tf.sub(a, b) + * ``` + * @param a The first `tf.Tensor` to subtract from. + * @param b The second `tf.Tensor` to be subtracted. Must have the same dtype as + * `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ + function sub_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'sub'); + var $b = convertToTensor(b, 'b', 'sub'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + var forward = function (backend, save) { + var res = backend.subtract($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Sub); + } + var sub = op({ sub_: sub_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var acosGradConfig = { + kernelName: Acos, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { + x: function () { + var a = square(cast(x, 'float32')); + var b = sqrt(sub(scalar(1), a)); + return neg(div(dy, b)); + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var acoshGradConfig = { + kernelName: Acosh, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { + x: function () { + var a = sqrt(sub(square(cast(x, 'float32')), 1)); + return div(dy, a); + } + }; + } + }; + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the dimensions in the input shape that are broadcasted to + * produce the provided output shape. + * + * The returned dimensions are 0-indexed and sorted. An example: + * inShape = [4, 1, 3] + * outShape = [5, 4, 3, 3] + * result = [1]. Dimension 1 (2nd dimension of input) gets broadcasted 1 => 3. + */ + function getBroadcastDims(inShape, outShape) { + var inRank = inShape.length; + var dims = []; + for (var i = 0; i < inRank; i++) { + var dim = inRank - 1 - i; + var a = inShape[dim] || 1; + var b = outShape[outShape.length - 1 - i] || 1; + if (b > 1 && a === 1) { + dims.unshift(dim); + } + } + return dims; + } + /** + * Returns the axes in the output space that should be reduced to produce + * the input space. + */ + function getReductionAxes(inShape, outShape) { + var result = []; + for (var i = 0; i < outShape.length; i++) { + var inDim = inShape[inShape.length - i - 1]; + var outAxis = outShape.length - i - 1; + var outDim = outShape[outAxis]; + if (inDim == null || (inDim === 1 && outDim > 1)) { + result.unshift(outAxis); + } + } + return result; + } + function assertAndGetBroadcastShape(shapeA, shapeB) { + var result = []; + var l = Math.max(shapeA.length, shapeB.length); + for (var i = 0; i < l; i++) { + var a = shapeA[shapeA.length - i - 1]; + if (a == null) { + a = 1; + } + var b = shapeB[shapeB.length - i - 1]; + if (b == null) { + b = 1; + } + if (a === 1) { + result.unshift(b); + } + else if (b === 1) { + result.unshift(a); + } + else if (a !== b) { + var errMsg = "Operands could not be broadcast together with shapes " + + (shapeA + " and " + shapeB + "."); + throw Error(errMsg); + } + else { + result.unshift(a); + } + } + return result; + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var addGradConfig = { + kernelName: Add, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var outShape = assertAndGetBroadcastShape(a.shape, b.shape); + var derA = function () { + var res = dy; + var reduceAxes = getReductionAxes(a.shape, outShape); + if (reduceAxes.length > 0) { + res = res.sum(reduceAxes); + } + return res.reshape(a.shape); + }; + var derB = function () { + var res = dy; + var reduceAxes = getReductionAxes(b.shape, outShape); + if (reduceAxes.length > 0) { + res = res.sum(reduceAxes); + } + return res.reshape(b.shape); + }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var addNGradConfig = { + kernelName: AddN, + saveAllInputs: true, + gradFunc: function (dy, saved) { + var ders = {}; + saved.forEach(function (_, i) { + ders[i] = function () { return dy.clone(); }; + }); + return ders; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates a `tf.Tensor` with all elements set to 0 with the same shape as the + * given tensor. + * + * ```js + * const x = tf.tensor([1, 2]); + * tf.zerosLike(x).print(); + * ``` + * + * @param x The tensor of required shape. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function zerosLike_(x) { + var $x = convertToTensor(x, 'x', 'zerosLike'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend) { return backend.zerosLike($x); }, inputs, null /* grad */, ZerosLike); + } + var zerosLike = op({ zerosLike_: zerosLike_ }); + + /** + * @license + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var argMaxGradConfig = { + kernelName: ArgMax, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return zerosLike(x); } }; + } + }; + + /** + * @license + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var argMinGradConfig = { + kernelName: ArgMin, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return zerosLike(x); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var asinGradConfig = { + kernelName: Asin, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, sqrt(sub(scalar(1), square(cast(x, 'float32'))))); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Adds two `tf.Tensor`s element-wise, A + B. Supports broadcasting. + * + * + * ```js + * const a = tf.tensor1d([1, 2, 3, 4]); + * const b = tf.tensor1d([10, 20, 30, 40]); + * + * a.add(b).print(); // or tf.add(a, b) + * ``` + * + * ```js + * // Broadcast add a with b. + * const a = tf.scalar(5); + * const b = tf.tensor1d([10, 20, 30, 40]); + * + * a.add(b).print(); // or tf.add(a, b) + * ``` + * @param a The first `tf.Tensor` to add. + * @param b The second `tf.Tensor` to add. Must have the same type as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ + function add_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'add'); + var $b = convertToTensor(b, 'b', 'add'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + var forward = function (backend, save) { + var res = backend.add($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Add); + } + var add = op({ add_: add_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var asinhGradConfig = { + kernelName: Asinh, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { + x: function () { + var a = sqrt(add(scalar(1), square(cast(x, 'float32')))); + return div(dy, a); + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Reshapes a `tf.Tensor` to a given shape. + * + * Given an input tensor, returns a new tensor with the same values as the + * input tensor with shape `shape`. + * + * If one component of shape is the special value -1, the size of that + * dimension is computed so that the total size remains constant. In + * particular, a shape of [-1] flattens into 1-D. At most one component of + * shape can be -1. + * + * If shape is 1-D or higher, then the operation returns a tensor with shape + * shape filled with the values of tensor. In this case, the number of + * elements implied by shape must be the same as the number of elements in + * tensor. + * + * ```js + * const x = tf.tensor1d([1, 2, 3, 4]); + * x.reshape([2, 2]).print(); + * ``` + * + * @param x The input tensor to be reshaped. + * @param shape An array of integers defining the output tensor shape. + */ + /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ + function reshape_(x, shape) { + var $x = convertToTensor(x, 'x', 'reshape', null); + shape = inferFromImplicitShape(shape, $x.size); + assert($x.size === sizeFromShape(shape), function () { return 'new shape and old shape must have the same number of elements.'; }); + var inputs = { x: $x }; + var attrs = { shape: shape }; + var forward = function (backend, save) { + save([$x]); + return backend.reshape($x, shape); + }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Reshape, attrs); + } + var reshape = op({ reshape_: reshape_ }); + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns true if the axis specifies the inner most dimensions of the + * array. + */ + function axesAreInnerMostDims(axes, rank) { + for (var i = 0; i < axes.length; ++i) { + if (axes[axes.length - i - 1] !== rank - 1 - i) { + return false; + } + } + return true; + } + function combineLocations(outputLoc, reduceLoc, axes) { + var rank = outputLoc.length + reduceLoc.length; + var loc = []; + var outIdx = 0; + var reduceIdx = 0; + for (var dim = 0; dim < rank; dim++) { + if (axes.indexOf(dim) === -1) { + loc.push(outputLoc[outIdx++]); + } + else { + loc.push(reduceLoc[reduceIdx++]); + } + } + return loc; + } + function computeOutAndReduceShapes(aShape, axes) { + var outShape = []; + var rank = aShape.length; + for (var dim = 0; dim < rank; dim++) { + if (axes.indexOf(dim) === -1) { + outShape.push(aShape[dim]); + } + } + var reduceShape = axes.map(function (dim) { return aShape[dim]; }); + return [outShape, reduceShape]; + } + function expandShapeToKeepDim(shape, axes) { + var reduceSubShape = axes.map(function (x) { return 1; }); + return combineLocations(shape, reduceSubShape, axes); + } + function assertAxesAreInnerMostDims(msg, axes, rank) { + assert(axesAreInnerMostDims(axes, rank), function () { return msg + " supports only inner-most axes for now. " + + ("Got axes " + axes + " and rank-" + rank + " input."); }); + } + /** + * Returns the axes permutation to be used with `tf.transpose`, if such + * permutation is necessary. Otherwise it returns null. This method is used by + * operations that operate only on inner-most axes. + */ + function getAxesPermutation(axes, rank) { + if (axesAreInnerMostDims(axes, rank)) { + return null; + } + var result = []; + for (var i = 0; i < rank; ++i) { + if (axes.indexOf(i) === -1) { + result.push(i); + } + } + axes.forEach(function (axis) { return result.push(axis); }); + return result; + } + /** Returns the axes permutation that undoes the original permutation. */ + function getUndoAxesPermutation(axes) { + return axes.map(function (axis, i) { return [i, axis]; }) + .sort(function (a, b) { return a[1] - b[1]; }) + .map(function (x) { return x[0]; }); + } + function getInnerMostAxes(numAxes, rank) { + var res = []; + for (var i = rank - numAxes; i < rank; ++i) { + res.push(i); + } + return res; + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the sum of elements across dimensions of a `tf.Tensor`. + * + * Reduces the input along the dimensions given in `axes`. Unless `keepDims` + * is true, the rank of the `tf.Tensor` is reduced by 1 for each entry in + * `axes`. If `keepDims` is true, the reduced dimensions are retained with + * length 1. If axes has no entries, all dimensions are reduced, and a + * `tf.Tensor` with a single element is returned. + * + * ```js + * const x = tf.tensor1d([1, 2, 3]); + * + * x.sum().print(); // or tf.sum(x) + * ``` + * + * ```js + * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); + * + * const axis = 1; + * x.sum(axis).print(); // or tf.sum(x, axis) + * ``` + * + * @param x The input tensor to compute the sum over. If the dtype is `bool` + * it will be converted to `int32` and the output dtype will be `int32`. + * @param axis The dimension(s) to reduce. By default it reduces + * all dimensions. + * @param keepDims If true, retains reduced dimensions with size 1. + */ + /** @doc {heading: 'Operations', subheading: 'Reduction'} */ + function sum_(x, axis, keepDims) { + if (axis === void 0) { axis = null; } + if (keepDims === void 0) { keepDims = false; } + var $x = convertToTensor(x, 'x', 'sum'); + if ($x.dtype === 'bool') { + $x = $x.toInt(); + } + var forward = function (backend, save) { + save([$x]); + var axes = parseAxisParam(axis, $x.shape); + var permutation = getAxesPermutation(axes, $x.rank); + var reductionAxes = axes; + var permutedX = $x; + if (permutation != null) { + permutedX = $x.transpose(permutation); + reductionAxes = getInnerMostAxes(reductionAxes.length, $x.rank); + } + var value = backend.sum(permutedX, reductionAxes); + if (keepDims) { + var newShape = expandShapeToKeepDim(value.shape, axes); + value = value.reshape(newShape); + } + return value; + }; + var inputs = { x: $x }; + var attrs = { axis: axis, keepDims: keepDims }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Sum, attrs); + } + var sum$1 = op({ sum_: sum_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var atan2GradConfig = { + kernelName: Atan2, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var outShape = assertAndGetBroadcastShape(a.shape, b.shape); + var derA = function () { + var d = add(square(a), square(b)); + var res = mul(dy, div(b, d)); + var reduceAxes = getReductionAxes(a.shape, outShape); + if (reduceAxes.length > 0) { + res = sum$1(res, reduceAxes); + } + return reshape(res, a.shape); + }; + var derB = function () { + var d = add(square(a), square(b)); + var res = neg(mul(dy, div(a, d))); + var reduceAxes = getReductionAxes(b.shape, outShape); + if (reduceAxes.length > 0) { + res = sum$1(res, reduceAxes); + } + return reshape(res, b.shape); + }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var atanGradConfig = { + kernelName: Atan, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, add(square(cast(x, 'float32')), 1)); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var atanhGradConfig = { + kernelName: Atanh, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, sub(scalar(1), square(cast(x, 'float32')))); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * + * @param inputShape Input tensor shape is of the following dimensions: + * `[batch, height, width, inChannels]`. + * @param filterShape The filter shape is of the following dimensions: + * `[filterHeight, filterWidth, depth]`. + * @param strides The strides of the sliding window for each dimension of the + * input tensor: `[strideHeight, strideWidth]`. + * If `strides` is a single number, + * then `strideHeight == strideWidth`. + * @param pad The type of padding algorithm. + * - `same` and stride 1: output will be of same size as input, + * regardless of filter size. + * - `valid`: output will be smaller than input if filter is larger + * than 1*1x1. + * - For more info, see this guide: + * [https://www.tensorflow.org/api_guides/python/nn#Convolution]( + * https://www.tensorflow.org/api_guides/python/nn#Convolution) + * @param dataFormat The data format of the input and output data. + * Defaults to 'NHWC'. + * @param dilations The dilation rates: `[dilationHeight, dilationWidth]`. + * Defaults to `[1, 1]`. If `dilations` is a single number, then + * `dilationHeight == dilationWidth`. + */ + function computeDilation2DInfo(inputShape, filterShape, strides, pad, dataFormat, dilations) { + if (dataFormat === void 0) { dataFormat = 'NHWC'; } + // `computerConv2DInfo` require filterShape to be in the dimension of: + // `[filterHeight, filterWidth, depth, outDepth]`, dilation2d doesn't have + // outDepth, it should have the same depth as the input. + // Input shape: [batch, height, width, inChannels] + var inputChannels = inputShape[3]; + var $filterShape = filterShape.concat([inputChannels]); + var $dataFormat = convertConv2DDataFormat(dataFormat); + return computeConv2DInfo(inputShape, $filterShape, strides, dilations, pad, null /* roundingMode */, null /* depthWise */, $dataFormat); + } + function computePool2DInfo(inShape, filterSize, strides, dilations, pad, roundingMode, dataFormat) { + if (dataFormat === void 0) { dataFormat = 'channelsLast'; } + var _a = parseTupleParam(filterSize), filterHeight = _a[0], filterWidth = _a[1]; + var filterShape; + if (dataFormat === 'channelsLast') { + filterShape = [filterHeight, filterWidth, inShape[3], inShape[3]]; + } + else if (dataFormat === 'channelsFirst') { + filterShape = [filterHeight, filterWidth, inShape[1], inShape[1]]; + } + else { + throw new Error("Unknown dataFormat " + dataFormat); + } + return computeConv2DInfo(inShape, filterShape, strides, dilations, pad, roundingMode, false, dataFormat); + } + /** + * Computes the information for a forward pass of a pooling3D operation. + */ + function computePool3DInfo(inShape, filterSize, strides, dilations, pad, roundingMode, dataFormat) { + if (dataFormat === void 0) { dataFormat = 'NDHWC'; } + var _a = parse3TupleParam(filterSize), filterDepth = _a[0], filterHeight = _a[1], filterWidth = _a[2]; + var filterShape; + var $dataFormat; + if (dataFormat === 'NDHWC') { + $dataFormat = 'channelsLast'; + filterShape = + [filterDepth, filterHeight, filterWidth, inShape[4], inShape[4]]; + } + else if (dataFormat === 'NCDHW') { + $dataFormat = 'channelsFirst'; + filterShape = + [filterDepth, filterHeight, filterWidth, inShape[1], inShape[1]]; + } + else { + throw new Error("Unknown dataFormat " + dataFormat); + } + return computeConv3DInfo(inShape, filterShape, strides, dilations, pad, false, $dataFormat, roundingMode); + } + /** + * Computes the information for a forward pass of a convolution/pooling + * operation. + */ + function computeConv2DInfo(inShape, filterShape, strides, dilations, pad, roundingMode, depthwise, dataFormat) { + if (depthwise === void 0) { depthwise = false; } + if (dataFormat === void 0) { dataFormat = 'channelsLast'; } + var _a = [-1, -1, -1, -1], batchSize = _a[0], inHeight = _a[1], inWidth = _a[2], inChannels = _a[3]; + if (dataFormat === 'channelsLast') { + batchSize = inShape[0], inHeight = inShape[1], inWidth = inShape[2], inChannels = inShape[3]; + } + else if (dataFormat === 'channelsFirst') { + batchSize = inShape[0], inChannels = inShape[1], inHeight = inShape[2], inWidth = inShape[3]; + } + else { + throw new Error("Unknown dataFormat " + dataFormat); + } + var filterHeight = filterShape[0], filterWidth = filterShape[1], filterChannels = filterShape[3]; + var _b = parseTupleParam(strides), strideHeight = _b[0], strideWidth = _b[1]; + var _c = parseTupleParam(dilations), dilationHeight = _c[0], dilationWidth = _c[1]; + var effectiveFilterHeight = getEffectiveFilterSize(filterHeight, dilationHeight); + var effectiveFilterWidth = getEffectiveFilterSize(filterWidth, dilationWidth); + var _d = getPadAndOutInfo(pad, inHeight, inWidth, strideHeight, strideWidth, effectiveFilterHeight, effectiveFilterWidth, roundingMode, dataFormat), padInfo = _d.padInfo, outHeight = _d.outHeight, outWidth = _d.outWidth; + var outChannels = depthwise ? filterChannels * inChannels : filterChannels; + var outShape; + if (dataFormat === 'channelsFirst') { + outShape = [batchSize, outChannels, outHeight, outWidth]; + } + else if (dataFormat === 'channelsLast') { + outShape = [batchSize, outHeight, outWidth, outChannels]; + } + return { + batchSize: batchSize, + dataFormat: dataFormat, + inHeight: inHeight, + inWidth: inWidth, + inChannels: inChannels, + outHeight: outHeight, + outWidth: outWidth, + outChannels: outChannels, + padInfo: padInfo, + strideHeight: strideHeight, + strideWidth: strideWidth, + filterHeight: filterHeight, + filterWidth: filterWidth, + effectiveFilterHeight: effectiveFilterHeight, + effectiveFilterWidth: effectiveFilterWidth, + dilationHeight: dilationHeight, + dilationWidth: dilationWidth, + inShape: inShape, + outShape: outShape, + filterShape: filterShape + }; + } + /** + * Computes the information for a forward pass of a 3D convolution/pooling + * operation. + */ + function computeConv3DInfo(inShape, filterShape, strides, dilations, pad, depthwise, dataFormat, roundingMode) { + if (depthwise === void 0) { depthwise = false; } + if (dataFormat === void 0) { dataFormat = 'channelsLast'; } + var _a = [-1, -1, -1, -1, -1], batchSize = _a[0], inDepth = _a[1], inHeight = _a[2], inWidth = _a[3], inChannels = _a[4]; + if (dataFormat === 'channelsLast') { + batchSize = inShape[0], inDepth = inShape[1], inHeight = inShape[2], inWidth = inShape[3], inChannels = inShape[4]; + } + else if (dataFormat === 'channelsFirst') { + batchSize = inShape[0], inChannels = inShape[1], inDepth = inShape[2], inHeight = inShape[3], inWidth = inShape[4]; + } + else { + throw new Error("Unknown dataFormat " + dataFormat); + } + var filterDepth = filterShape[0], filterHeight = filterShape[1], filterWidth = filterShape[2], filterChannels = filterShape[4]; + var _b = parse3TupleParam(strides), strideDepth = _b[0], strideHeight = _b[1], strideWidth = _b[2]; + var _c = parse3TupleParam(dilations), dilationDepth = _c[0], dilationHeight = _c[1], dilationWidth = _c[2]; + var effectiveFilterDepth = getEffectiveFilterSize(filterDepth, dilationDepth); + var effectiveFilterHeight = getEffectiveFilterSize(filterHeight, dilationHeight); + var effectiveFilterWidth = getEffectiveFilterSize(filterWidth, dilationWidth); + var _d = get3DPadAndOutInfo(pad, inDepth, inHeight, inWidth, strideDepth, strideHeight, strideWidth, effectiveFilterDepth, effectiveFilterHeight, effectiveFilterWidth, roundingMode), padInfo = _d.padInfo, outDepth = _d.outDepth, outHeight = _d.outHeight, outWidth = _d.outWidth; + var outChannels = depthwise ? filterChannels * inChannels : filterChannels; + var outShape; + if (dataFormat === 'channelsFirst') { + outShape = [batchSize, outChannels, outDepth, outHeight, outWidth]; + } + else if (dataFormat === 'channelsLast') { + outShape = [batchSize, outDepth, outHeight, outWidth, outChannels]; + } + return { + batchSize: batchSize, + dataFormat: dataFormat, + inDepth: inDepth, + inHeight: inHeight, + inWidth: inWidth, + inChannels: inChannels, + outDepth: outDepth, + outHeight: outHeight, + outWidth: outWidth, + outChannels: outChannels, + padInfo: padInfo, + strideDepth: strideDepth, + strideHeight: strideHeight, + strideWidth: strideWidth, + filterDepth: filterDepth, + filterHeight: filterHeight, + filterWidth: filterWidth, + effectiveFilterDepth: effectiveFilterDepth, + effectiveFilterHeight: effectiveFilterHeight, + effectiveFilterWidth: effectiveFilterWidth, + dilationDepth: dilationDepth, + dilationHeight: dilationHeight, + dilationWidth: dilationWidth, + inShape: inShape, + outShape: outShape, + filterShape: filterShape + }; + } + function computeOutputShape2D(inShape, fieldSize, stride, zeroPad, roundingMode) { + if (zeroPad == null) { + zeroPad = computeDefaultPad(inShape, fieldSize, stride); + } + var inputRows = inShape[0]; + var inputCols = inShape[1]; + var outputRows = conditionalRound((inputRows - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); + assert(isInt(outputRows), function () { return "The output # of rows (" + outputRows + ") must be an integer. " + + "Change the stride and/or zero pad parameters"; }); + var outputCols = conditionalRound((inputCols - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); + assert(isInt(outputCols), function () { return "The output # of columns (" + outputCols + ") must be an integer. " + + "Change the stride and/or zero pad parameters"; }); + return [outputRows, outputCols]; + } + function computeOutputShape4D(inShape, fieldSize, outChannels, stride, zeroPad, roundingMode) { + if (zeroPad == null) { + zeroPad = computeDefaultPad(inShape, fieldSize, stride); + } + var inputDepth = inShape[0]; + var inputRows = inShape[1]; + var inputCols = inShape[2]; + var outputDepths = conditionalRound((inputDepth - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); + assert(isInt(outputDepths), function () { return "The output # of depths (" + outputDepths + ") must be an integer. " + + "Change the stride and/or zero pad parameters"; }); + var outputRows = conditionalRound((inputRows - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); + assert(isInt(outputRows), function () { return "The output # of rows (" + outputRows + ") must be an integer. " + + "Change the stride and/or zero pad parameters"; }); + var outputCols = conditionalRound((inputCols - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); + assert(isInt(outputCols), function () { return "The output # of columns (" + outputCols + ") must be an integer. " + + "Change the stride and/or zero pad parameters"; }); + return [outputDepths, outputRows, outputCols, outChannels]; + } + function computeDefaultPad(inputShape, fieldSize, stride, dilation) { + if (dilation === void 0) { dilation = 1; } + var effectiveFieldSize = getEffectiveFilterSize(fieldSize, dilation); + return Math.floor((inputShape[0] * (stride - 1) - stride + effectiveFieldSize) / 2); + } + function parseTupleParam(param) { + if (typeof param === 'number') { + return [param, param, param]; + } + if (param.length === 2) { + return [param[0], param[1], 1]; + } + return param; + } + function parse3TupleParam(param) { + return typeof param === 'number' ? [param, param, param] : param; + } + /* See https://www.tensorflow.org/api_docs/python/tf/nn/atrous_conv2d + * Atrous convolution is equivalent to standard convolution with upsampled + * filters with effective_filter_height = + * filter_height + (filter_height - 1) * (dilation - 1) + * and effective_filter_width = + * filter_width + (filter_width - 1) * (dilation - 1), + * produced by inserting dilation - 1 zeros along consecutive elements across + * the filters' spatial dimensions. + * When there is a dilation, this converts a filter dimension to the + * effective filter dimension, so it can be used in a standard convolution. + */ + function getEffectiveFilterSize(filterSize, dilation) { + if (dilation <= 1) { + return filterSize; + } + return filterSize + (filterSize - 1) * (dilation - 1); + } + function getPadAndOutInfo(pad, inHeight, inWidth, strideHeight, strideWidth, filterHeight, filterWidth, roundingMode, dataFormat) { + var padInfo; + var outHeight; + var outWidth; + if (typeof pad === 'number') { + var padType = (pad === 0) ? 'VALID' : 'NUMBER'; + padInfo = { top: pad, bottom: pad, left: pad, right: pad, type: padType }; + var outShape = computeOutputShape2D([inHeight, inWidth], filterHeight, strideHeight, pad, roundingMode); + outHeight = outShape[0]; + outWidth = outShape[1]; + } + else if (pad === 'same') { + outHeight = Math.ceil(inHeight / strideHeight); + outWidth = Math.ceil(inWidth / strideWidth); + var padAlongHeight = Math.max(0, (outHeight - 1) * strideHeight + filterHeight - inHeight); + var padAlongWidth = Math.max(0, (outWidth - 1) * strideWidth + filterWidth - inWidth); + var top_1 = Math.floor(padAlongHeight / 2); + var bottom = padAlongHeight - top_1; + var left = Math.floor(padAlongWidth / 2); + var right = padAlongWidth - left; + padInfo = { top: top_1, bottom: bottom, left: left, right: right, type: 'SAME' }; + } + else if (pad === 'valid') { + padInfo = { top: 0, bottom: 0, left: 0, right: 0, type: 'VALID' }; + outHeight = Math.ceil((inHeight - filterHeight + 1) / strideHeight); + outWidth = Math.ceil((inWidth - filterWidth + 1) / strideWidth); + } + else if (typeof pad === 'object') { + var top_2 = dataFormat === 'channelsLast' ? pad[1][0] : pad[2][0]; + var bottom = dataFormat === 'channelsLast' ? pad[1][1] : pad[2][1]; + var left = dataFormat === 'channelsLast' ? pad[2][0] : pad[3][0]; + var right = dataFormat === 'channelsLast' ? pad[2][1] : pad[3][1]; + var padType = (top_2 === 0 && bottom === 0 && left === 0 && right === 0) ? + 'VALID' : + 'EXPLICIT'; + padInfo = { top: top_2, bottom: bottom, left: left, right: right, type: padType }; + outHeight = conditionalRound((inHeight - filterHeight + top_2 + bottom) / strideHeight + 1, roundingMode); + outWidth = conditionalRound((inWidth - filterWidth + left + right) / strideWidth + 1, roundingMode); + } + else { + throw Error("Unknown padding parameter: " + pad); + } + return { padInfo: padInfo, outHeight: outHeight, outWidth: outWidth }; + } + function get3DPadAndOutInfo(pad, inDepth, inHeight, inWidth, strideDepth, strideHeight, strideWidth, filterDepth, filterHeight, filterWidth, roundingMode) { + var padInfo; + var outDepth; + var outHeight; + var outWidth; + if (typeof pad === 'number') { + var padType = (pad === 0) ? 'VALID' : 'NUMBER'; + padInfo = { + top: pad, + bottom: pad, + left: pad, + right: pad, + front: pad, + back: pad, + type: padType + }; + var outShape = computeOutputShape4D([inDepth, inHeight, inWidth, 1], filterDepth, 1, strideDepth, pad, roundingMode); + outDepth = outShape[0]; + outHeight = outShape[1]; + outWidth = outShape[2]; + } + else if (pad === 'same') { + outDepth = Math.ceil(inDepth / strideDepth); + outHeight = Math.ceil(inHeight / strideHeight); + outWidth = Math.ceil(inWidth / strideWidth); + var padAlongDepth = (outDepth - 1) * strideDepth + filterDepth - inDepth; + var padAlongHeight = (outHeight - 1) * strideHeight + filterHeight - inHeight; + var padAlongWidth = (outWidth - 1) * strideWidth + filterWidth - inWidth; + var front = Math.floor(padAlongDepth / 2); + var back = padAlongDepth - front; + var top_3 = Math.floor(padAlongHeight / 2); + var bottom = padAlongHeight - top_3; + var left = Math.floor(padAlongWidth / 2); + var right = padAlongWidth - left; + padInfo = { top: top_3, bottom: bottom, left: left, right: right, front: front, back: back, type: 'SAME' }; + } + else if (pad === 'valid') { + padInfo = { + top: 0, + bottom: 0, + left: 0, + right: 0, + front: 0, + back: 0, + type: 'VALID' + }; + outDepth = Math.ceil((inDepth - filterDepth + 1) / strideDepth); + outHeight = Math.ceil((inHeight - filterHeight + 1) / strideHeight); + outWidth = Math.ceil((inWidth - filterWidth + 1) / strideWidth); + } + else { + throw Error("Unknown padding parameter: " + pad); + } + return { padInfo: padInfo, outDepth: outDepth, outHeight: outHeight, outWidth: outWidth }; + } + /** + * Rounds a value depending on the rounding mode + * @param value + * @param roundingMode + */ + function conditionalRound(value, roundingMode) { + if (!roundingMode) { + return value; + } + switch (roundingMode) { + case 'round': + // used for Caffe Conv + return Math.round(value); + case 'ceil': + // used for Caffe Pool + return Math.ceil(value); + case 'floor': + return Math.floor(value); + default: + throw new Error("Unknown roundingMode " + roundingMode); + } + } + function tupleValuesAreOne(param) { + var _a = parseTupleParam(param), dimA = _a[0], dimB = _a[1], dimC = _a[2]; + return dimA === 1 && dimB === 1 && dimC === 1; + } + function eitherStridesOrDilationsAreOne(strides, dilations) { + return tupleValuesAreOne(strides) || tupleValuesAreOne(dilations); + } + /** + * Convert Conv2D dataFormat from 'NHWC'|'NCHW' to + * 'channelsLast'|'channelsFirst' + * @param dataFormat in 'NHWC'|'NCHW' mode + * @return dataFormat in 'channelsLast'|'channelsFirst' mode + * @throws unknown dataFormat + */ + function convertConv2DDataFormat(dataFormat) { + if (dataFormat === 'NHWC') { + return 'channelsLast'; + } + else if (dataFormat === 'NCHW') { + return 'channelsFirst'; + } + else { + throw new Error("Unknown dataFormat " + dataFormat); + } + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the backprop of a 3d avg pool. + * + * @param dy The dy error, of rank 5 of shape + * [batchSize, depth, height, width, channels]. + * assumed. + * @param input The original input image, of rank 5 or rank4 of shape + * [batchSize, depth, height, width, channels]. + * @param filterSize The filter size: + * `[filterDepth, filterHeight, filterWidth]`. + * `filterSize` is a single number, + * then `filterDepth == filterHeight == filterWidth`. + * @param strides The strides of the pooling: + * `[strideDepth, strideHeight, strideWidth]`. If + * `strides` is a single number, then `strideHeight == strideWidth`. + * @param dilations Deprecated, this field will be gone in v3.0.0. The dilation + * rates: `[dilationDepth, dilationHeight, dilationWidth]` + * in which we sample input values across the depth, height and width + * dimensions in dilated pooling. + * Defaults to `[1, 1, 1]`. If `dilations` is a single number, + * then `dilationDepth == dilationHeight == dilationWidth`. + * If it is greater than 1, then all values of `strides` must be 1. + * @param pad A string from: 'same', 'valid'. The type of padding algorithm + * used in the forward prop of the op. + * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The + * rounding mode used when computing output dimensions if pad is a + * number. If none is provided, it will not round and error if the output + * is of fractional size. + */ + function avgPool3dBackprop_(dy, input, filterSize, strides, dilations, pad, dimRoundingMode) { + if (dilations === void 0) { dilations = [1, 1, 1]; } + var $dy = convertToTensor(dy, 'dy', 'avgPool3dBackprop'); + var $input = convertToTensor(input, 'input', 'avgPool3dBackprop'); + var dy5D = $dy; + var input5D = $input; + var reshapedTo5D = false; + if ($input.rank === 4) { + reshapedTo5D = true; + dy5D = reshape($dy, [1, $dy.shape[0], $dy.shape[1], $dy.shape[2], $dy.shape[3]]); + input5D = reshape($input, [ + 1, $input.shape[0], $input.shape[1], $input.shape[2], $input.shape[3] + ]); + } + assert(dy5D.rank === 5, function () { return "Error in avgPool3dBackprop: dy must be rank 5 but got rank " + + (dy5D.rank + "."); }); + assert(input5D.rank === 5, function () { return "Error in avgPool3dBackprop: input must be rank 5 but got rank " + + (input5D.rank + "."); }); + assert(eitherStridesOrDilationsAreOne(strides, dilations), function () { return 'Error in avgPool3dBackprop: Either strides or dilations ' + + ("must be 1. Got strides " + strides + " and dilations '" + dilations + "'"); }); + if (dimRoundingMode != null) { + assert(isInt(pad), function () { return "Error in maxPool3dBackprop: pad must be an integer when " + + ("using, dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); + } + var forward = function (backend) { + var convInfo = computePool3DInfo(input5D.shape, filterSize, strides, dilations, pad, dimRoundingMode); + return backend.avgPool3dBackprop(dy5D, input5D, convInfo); + }; + var inputs = { dy: dy5D, input: input5D }; + var attrs = { filterSize: filterSize, strides: strides, dilations: dilations, pad: pad, dimRoundingMode: dimRoundingMode }; + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, AvgPool3DBackprop, attrs); + if (reshapedTo5D) { + return reshape(res, [res.shape[1], res.shape[2], res.shape[3], res.shape[4]]); + } + return res; + } + var avgPool3dBackprop = op({ avgPool3dBackprop_: avgPool3dBackprop_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var avgPool3DGradConfig = { + kernelName: AvgPool3D, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0]; + var _a = attrs, filterSize = _a.filterSize, strides = _a.strides, dilations = _a.dilations, pad = _a.pad, dimRoundingMode = _a.dimRoundingMode; + var $dilations = dilations == null ? [1, 1, 1] : dilations; + return { + x: function () { return avgPool3dBackprop(dy, x, filterSize, strides, $dilations, pad, dimRoundingMode); } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the backprop of an 2D avg pool. + * + * @param dy The dy error, of rank 4 or rank 3 of shape + * [batchSize, height, width, channels]. If rank 3, batch of 1 is + * assumed. + * @param input The input image, of rank 4 or rank 3 of shape + * [batchSize, height, width, channels]. If rank 3, batch of 1 is + * assumed. + * @param filterSize The filter size: `[filterHeight, filterWidth]`. If + * `filterSize` is a single number, then `filterHeight == filterWidth`. + * @param strides The strides of the pooling: `[strideHeight, strideWidth]`. If + * `strides` is a single number, then `strideHeight == strideWidth`. + * @param pad A string from: 'same', 'valid'. The type of padding algorithm + * used in the forward prop of the op. + */ + function avgPoolBackprop_(dy, input, filterSize, strides, pad) { + var $dy = convertToTensor(dy, 'dy', 'avgPoolBackprop'); + var $input = convertToTensor(input, 'input', 'avgPoolBackprop'); + assert($input.rank === $dy.rank, function () { return "Rank of input (" + $input.rank + ") does not match rank of dy (" + $dy.rank + ")"; }); + var input4D = $input; + var dy4D = $dy; + var reshapedTo4D = false; + if ($input.rank === 3) { + reshapedTo4D = true; + input4D = + reshape($input, [1, $input.shape[0], $input.shape[1], $input.shape[2]]); + dy4D = reshape($dy, [1, $dy.shape[0], $dy.shape[1], $dy.shape[2]]); + } + assert(dy4D.rank === 4, function () { return "Error in avgPoolBackprop: dy must be rank 4 but got rank " + + (dy4D.rank + "."); }); + assert(input4D.rank === 4, function () { return "Error in avgPoolBackprop: input must be rank 4 but got rank " + + (input4D.rank + "."); }); + var forward = function (backend) { + var convInfo = computePool2DInfo(input4D.shape, filterSize, strides, 1 /* dilations */, pad); + return backend.avgPoolBackprop(dy4D, input4D, convInfo); + }; + var inputs = { dy: dy4D, input: input4D }; + var attrs = { filterSize: filterSize, strides: strides, pad: pad }; + var res = ENGINE.runKernelFunc(forward, inputs, null, AvgPoolBackprop, attrs); + if (reshapedTo4D) { + return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); + } + return res; + } + var avgPoolBackprop = op({ avgPoolBackprop_: avgPoolBackprop_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var avgPoolGradConfig = { + kernelName: AvgPool, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0]; + var _a = attrs, filterSize = _a.filterSize, strides = _a.strides, pad = _a.pad; + return { + x: function () { return avgPoolBackprop(dy, x, filterSize, strides, pad); } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the dot product of two matrices, A * B. These must be matrices. + * + * ```js + * const a = tf.tensor2d([1, 2], [1, 2]); + * const b = tf.tensor2d([1, 2, 3, 4], [2, 2]); + * + * a.matMul(b).print(); // or tf.matMul(a, b) + * ``` + * @param a First matrix in dot product operation. + * @param b Second matrix in dot product operation. + * @param transposeA If true, `a` is transposed before multiplication. + * @param transposeB If true, `b` is transposed before multiplication. + */ + /** @doc {heading: 'Operations', subheading: 'Matrices'} */ + function matMul_(a, b, transposeA, transposeB) { + var _a; + if (transposeA === void 0) { transposeA = false; } + if (transposeB === void 0) { transposeB = false; } + var $a = convertToTensor(a, 'a', 'matMul'); + var $b = convertToTensor(b, 'b', 'matMul'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + assert($a.rank >= 2 && $b.rank >= 2 && $a.rank === $b.rank, function () { return "Error in matMul: inputs must have the same rank of at least 2, " + + ("got ranks " + $a.rank + " and " + $b.rank + "."); }); + var innerShapeA = transposeA ? $a.shape[$a.rank - 2] : $a.shape[$a.rank - 1]; + var innerShapeB = transposeB ? $b.shape[$b.rank - 1] : $b.shape[$b.rank - 2]; + var outerShapeA = transposeA ? $a.shape[$a.rank - 1] : $a.shape[$a.rank - 2]; + var outerShapeB = transposeB ? $b.shape[$b.rank - 2] : $b.shape[$b.rank - 1]; + var outerDimsA = $a.shape.slice(0, -2); + var outerDimsB = $b.shape.slice(0, -2); + var batchDimA = sizeFromShape(outerDimsA); + var batchDimB = sizeFromShape(outerDimsB); + assert(arraysEqual(outerDimsA, outerDimsB), function () { return "Error in matMul: outer dimensions (" + outerDimsA + ") and (" + + (outerDimsB + ") of Tensors with shapes " + $a.shape + " and ") + + ($b.shape + " must match."); }); + assert(innerShapeA === innerShapeB, function () { return "Error in matMul: inner shapes (" + innerShapeA + ") and (" + + (innerShapeB + ") of Tensors with shapes " + $a.shape + " and ") + + ($b.shape + " and transposeA=" + transposeA) + + (" and transposeB=" + transposeB + " must match."); }); + var outShape = $a.shape.slice(0, -2).concat([outerShapeA, outerShapeB]); + var a3D = transposeA ? reshape($a, [batchDimA, innerShapeA, outerShapeA]) : + reshape($a, [batchDimA, outerShapeA, innerShapeA]); + var b3D = transposeB ? reshape($b, [batchDimB, outerShapeB, innerShapeB]) : + reshape($b, [batchDimB, innerShapeB, outerShapeB]); + var forward = function (backend, save) { + save([a3D, b3D]); + return backend.batchMatMul(a3D, b3D, transposeA, transposeB); + }; + var inputs = { a: a3D, b: b3D }; + var attrs = { transposeA: transposeA, transposeB: transposeB }; + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, BatchMatMul, attrs); + return reshape(res, outShape); + } + var matMul = op({ matMul_: matMul_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var batchMatMulGradConfig = { + kernelName: BatchMatMul, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved, attrs) { + var _a = saved, a = _a[0], b = _a[1]; + var _b = attrs, transposeA = _b.transposeA, transposeB = _b.transposeB; + if (!transposeA && !transposeB) { + return { + a: function () { return matMul(dy, b, false, true); }, + b: function () { return matMul(a, dy, true, false); } + }; + } + else if (!transposeA && transposeB) { + return { + a: function () { return matMul(dy, b, false, false); }, + b: function () { return matMul(dy, a, true, false); } + }; + } + else if (transposeA && !transposeB) { + return { + a: function () { return matMul(b, dy, false, true); }, + b: function () { return matMul(a, dy, false, false); } + }; + } + else { + return { + a: function () { return matMul(b, dy, true, true); }, + b: function () { return matMul(dy, a, true, true); } + }; + } + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * This operation divides "spatial" dimensions `[1, ..., M]` of the input into + * a grid of blocks of shape `blockShape`, and interleaves these blocks with + * the "batch" dimension (0) such that in the output, the spatial + * dimensions `[1, ..., M]` correspond to the position within the grid, + * and the batch dimension combines both the position within a spatial block + * and the original batch position. Prior to division into blocks, + * the spatial dimensions of the input are optionally zero padded + * according to `paddings`. See below for a precise description. + * + * ```js + * const x = tf.tensor4d([1, 2, 3, 4], [1, 2, 2, 1]); + * const blockShape = [2, 2]; + * const paddings = [[0, 0], [0, 0]]; + * + * x.spaceToBatchND(blockShape, paddings).print(); + * ``` + * + * @param x A `tf.Tensor`. N-D with `x.shape` = `[batch] + spatialShape + + * remainingShape`, where spatialShape has `M` dimensions. + * @param blockShape A 1-D array. Must have shape `[M]`, all values must + * be >= 1. + * @param paddings A 2-D array. Must have shape `[M, 2]`, all values must be >= + * 0. `paddings[i] = [padStart, padEnd]` specifies the amount to zero-pad + * from input dimension `i + 1`, which corresponds to spatial dimension `i`. It + * is required that + * `(inputShape[i + 1] + padStart + padEnd) % blockShape[i] === 0` + * + * This operation is equivalent to the following steps: + * + * 1. Zero-pad the start and end of dimensions `[1, ..., M]` of the input + * according to `paddings` to produce `padded` of shape paddedShape. + * + * 2. Reshape `padded` to `reshapedPadded` of shape: + * `[batch] + [paddedShape[1] / blockShape[0], blockShape[0], ..., + * paddedShape[M] / blockShape[M-1], blockShape[M-1]] + remainingShape` + * + * 3. Permute dimensions of `reshapedPadded` to produce `permutedReshapedPadded` + * of shape: `blockShape + [batch] + [paddedShape[1] / blockShape[0], ..., + * paddedShape[M] / blockShape[M-1]] + remainingShape` + * + * 4. Reshape `permutedReshapedPadded` to flatten `blockShape` into the + * batch dimension, producing an output tensor of shape: + * `[batch * prod(blockShape)] + [paddedShape[1] / blockShape[0], ..., + * paddedShape[M] / blockShape[M-1]] + remainingShape` + */ + /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ + function spaceToBatchND_(x, blockShape, paddings) { + var $x = convertToTensor(x, 'x', 'spaceToBatchND'); + assert($x.rank >= 1 + blockShape.length, function () { return "input rank " + $x.rank + " should be > than [blockShape] " + blockShape.length; }); + assert(paddings.length === blockShape.length, function () { return "paddings.shape[0] " + paddings.length + " must be equal to [blockShape] " + blockShape.length; }); + assert($x.shape.reduce(function (a, b, i) { + if (i > 0 && i <= blockShape.length) { + return a && + ((b + paddings[i - 1][0] + paddings[i - 1][1]) % + blockShape[i - 1] === + 0); + } + return a; + }, true), function () { return "input spatial dimensions " + $x.shape.slice(1) + " with paddings " + paddings.toString() + " must be divisible by blockShapes " + blockShape.toString(); }); + var forward = function (backend) { + return backend.spaceToBatchND($x, blockShape, paddings); + }; + var inputs = { x: $x }; + var attrs = { blockShape: blockShape, paddings: paddings }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, SpaceToBatchND, attrs); + } + var spaceToBatchND = op({ spaceToBatchND_: spaceToBatchND_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var batchToSpaceNDGradConfig = { + kernelName: BatchToSpaceND, + gradFunc: function (dy, saved, attrs) { + var _a = attrs, blockShape = _a.blockShape, crops = _a.crops; + return { x: function () { return spaceToBatchND(dy, blockShape, crops); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var broadcastToGradConfig = { + kernelName: BroadcastTo, + gradFunc: function (dy, saved, attrs) { + var broadCastToAttrs = attrs; + var inputShape = broadCastToAttrs.inputShape; + var outputShape = broadCastToAttrs.shape; + var reps = Array.from(outputShape); + for (var i = inputShape.length - 1; i >= 0; i--) { + if (inputShape[i] === outputShape[i]) { + reps[i] = 1; + } + else if (inputShape[i] !== 1) { + throw new Error("broadcastTo(): [" + inputShape + "] cannot be broadcast to [" + outputShape + "]."); + } + } + var axes = []; + for (var i = 0; i < reps.length; i++) { + if (reps[i] > 1) { + axes.push(i); + } + } + return { x: function () { return sum$1(dy, axes, true /* keepDims */); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var castGradConfig = { + kernelName: Cast, + gradFunc: function (dy) { + return { x: function () { return dy.clone(); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var ceilGradConfig = { + kernelName: Ceil, + gradFunc: function (dy) { + // TODO(manrajgrover): Return null for gradients when backprop supports it. + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the truth value of (a >= b) element-wise. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([1, 2, 3]); + * const b = tf.tensor1d([2, 2, 2]); + * + * a.greaterEqual(b).print(); + * ``` + * + * @param a The first input tensor. + * @param b The second input tensor. Must have the same dtype as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function greaterEqual_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'greaterEqual'); + var $b = convertToTensor(b, 'b', 'greaterEqual'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + assertAndGetBroadcastShape($a.shape, $b.shape); + var forward = function (backend, save) { + var res = backend.greaterEqual($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, GreaterEqual); + } + var greaterEqual = op({ greaterEqual_: greaterEqual_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the truth value of (a <= b) element-wise. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([1, 2, 3]); + * const b = tf.tensor1d([2, 2, 2]); + * + * a.lessEqual(b).print(); + * ``` + * + * @param a The first input tensor. + * @param b The second input tensor. Must have the same dtype as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function lessEqual_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'lessEqual'); + var $b = convertToTensor(b, 'b', 'lessEqual'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + assertAndGetBroadcastShape($a.shape, $b.shape); + var forward = function (backend, save) { + var res = backend.lessEqual($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, LessEqual); + } + var lessEqual = op({ lessEqual_: lessEqual_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the truth value of `a AND b` element-wise. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([false, false, true, true], 'bool'); + * const b = tf.tensor1d([false, true, false, true], 'bool'); + * + * a.logicalAnd(b).print(); + * ``` + * + * @param a The first input tensor. Must be of dtype bool. + * @param b The second input tensor. Must be of dtype bool. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function logicalAnd_(a, b) { + var $a = convertToTensor(a, 'a', 'logicalAnd', 'bool'); + var $b = convertToTensor(b, 'b', 'logicalAnd', 'bool'); + assertAndGetBroadcastShape($a.shape, $b.shape); + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(function (backend) { return backend.logicalAnd($a, $b); }, inputs, null /* grad */, LogicalAnd); + } + var logicalAnd = op({ logicalAnd_: logicalAnd_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the elements, either `a` or `b` depending on the `condition`. + * + * If the condition is true, select from `a`, otherwise select from `b`. + * + * ```js + * const cond = tf.tensor1d([false, false, true], 'bool'); + * const a = tf.tensor1d([1 , 2, 3]); + * const b = tf.tensor1d([-1, -2, -3]); + * + * a.where(cond, b).print(); + * ``` + * + * @param condition The input condition. Must be of dtype bool. + * @param a If `condition` is rank 1, `a` may have a higher rank but + * its first dimension must match the size of `condition`. + * @param b A tensor with the same dtype as `a` and with shape that is + * compatible with `a`. + * @return A tensor with same dtype as `a` and `b`, and shape that is + * broadcastable from `a` and `b`. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function where_(condition, a, b) { + var $a = convertToTensor(a, 'a', 'where'); + var $b = convertToTensor(b, 'b', 'where'); + var $condition = convertToTensor(condition, 'condition', 'where', 'bool'); + // TODO: move this logic to forward function when the broadcastTo op is + // implemented in WASM. + // Find the broadcastable shape for $a and $b. + var broadcastShape = assertAndGetBroadcastShape($a.shape, $b.shape); + var $broadcastedA = $a.broadcastTo(broadcastShape); + var $broadcastedB = $b.broadcastTo(broadcastShape); + if ($condition.rank === 1) { + // If condition rank is 1, then the first dimension must match the size of + // condition. + assert($condition.shape[0] === $a.shape[0], function () { return 'The first dimension of `a` must match the size of `condition`.'; }); + } + if ($condition.rank !== 1) { + // A must have the same shape as condition. + assertShapesMatch($condition.shape, $broadcastedB.shape, 'Error in where: '); + } + var forward = function (backend, save) { + var res = backend.select($condition, $broadcastedA, $broadcastedB); + save([$condition]); + return res; + }; + var inputs = { + condition: $condition, + t: $broadcastedA, + e: $broadcastedB + }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, SelectV2); + } + var where = op({ where_: where_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var clipByValueGradConfig = { + kernelName: ClipByValue, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0]; + var _a = attrs, clipValueMin = _a.clipValueMin, clipValueMax = _a.clipValueMax; + return { + x: function () { return where(logicalAnd(greaterEqual(x, clipValueMin), lessEqual(x, clipValueMax)), dy, zerosLike(dy)); }, + }; + } + }; + + /** + * Prepare the split size array. When the input is a number, the axis is evenly + * divided among the split size. When the input contains the negative value, the + * rest of the axis is allocated toward that. + */ + function prepareSplitSize(x, numOrSizeSplits, axis) { + if (axis === void 0) { axis = 0; } + var splitSizes = []; + if (typeof (numOrSizeSplits) === 'number') { + assert(x.shape[axis] % numOrSizeSplits === 0, function () { return 'Number of splits must evenly divide the axis.'; }); + splitSizes = + new Array(numOrSizeSplits).fill(x.shape[axis] / numOrSizeSplits); + } + else { + var numOfNegs = numOrSizeSplits.reduce(function (count, value) { + if (value === -1) { + count += 1; + } + return count; + }, 0); + assert(numOfNegs <= 1, function () { return 'There should be only one negative value in split array.'; }); + var negIndex = numOrSizeSplits.indexOf(-1); + // Allow the number of split array to be -1, which indicates the rest + // of dimension is allocated to that split. + if (negIndex !== -1) { + var total = numOrSizeSplits.reduce(function (a, b) { return b > 0 ? a + b : a; }); + numOrSizeSplits[negIndex] = x.shape[axis] - total; + } + assert(x.shape[axis] === numOrSizeSplits.reduce(function (a, b) { return a + b; }), function () { return 'The sum of sizes must match the size of the axis dimension.'; }); + splitSizes = numOrSizeSplits; + } + return splitSizes; + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Splits a `tf.Tensor` into sub tensors. + * + * If `numOrSizeSplits` is a number, splits `x` along dimension `axis` + * into `numOrSizeSplits` smaller tensors. + * Requires that `numOrSizeSplits` evenly divides `x.shape[axis]`. + * + * If `numOrSizeSplits` is a number array, splits `x` into + * `numOrSizeSplits.length` pieces. The shape of the `i`-th piece has the + * same size as `x` except along dimension `axis` where the size is + * `numOrSizeSplits[i]`. + * + * ```js + * const x = tf.tensor2d([1, 2, 3, 4, 5, 6, 7, 8], [2, 4]); + * const [a, b] = tf.split(x, 2, 1); + * a.print(); + * b.print(); + * + * const [c, d, e] = tf.split(x, [1, 2, 1], 1); + * c.print(); + * d.print(); + * e.print(); + * ``` + * + * @param x The input tensor to split. + * @param numOrSizeSplits Either an integer indicating the number of + * splits along the axis or an array of integers containing the sizes of + * each output tensor along the axis. If a number then it must evenly divide + * `x.shape[axis]`; otherwise the sum of sizes must match `x.shape[axis]`. + * Can contain one -1 indicating that dimension is to be inferred. + * @param axis The dimension along which to split. Defaults to 0 (the first + * dim). + */ + /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ + function split_(x, numOrSizeSplits, axis) { + if (axis === void 0) { axis = 0; } + var $x = convertToTensor(x, 'x', 'split'); + var forward = function (backend, _) { + var $axis = parseAxisParam(axis, $x.shape)[0]; + var splitSizes = prepareSplitSize($x, numOrSizeSplits, $axis); + return backend.split($x, splitSizes, $axis); + }; + var inputs = { x: $x }; + var attr = { numOrSizeSplits: numOrSizeSplits, axis: axis }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, SplitV, attr); + } + var split = op({ split_: split_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var concatGradConfig = { + kernelName: Concat, + saveAllInputs: true, + gradFunc: function (dy, saved, attrs) { + var shapes = saved.map(function (t) { return t.shape; }); + var axis = attrs.axis; + var $axis = parseAxisParam(axis, saved[0].shape)[0]; + var sizeSplits = shapes.map(function (s) { return s[$axis]; }); + var derTensors = split(dy, sizeSplits, $axis); + return derTensors.map(function (t) { return function () { return t; }; }); + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the derivative of the filter of a 2D convolution. + * + * @param x The input tensor, of rank 4 or rank 3 of shape + * [batch, height, width, inChannels]. If rank 3, batch of 1 is assumed. + * @param dy The dy image, of rank 4 or rank 3, of shape + * [batch, height, width, outDepth]. If rank 3, batch of 1 is assumed. + * @param filterShape The shape of the filter, length 4, + * [filterHeight, filterWidth, inDepth, outDepth]. + * @param strides The strides of the convolution: [strideHeight, + * strideWidth]. + * @param pad A string from: 'same', 'valid'. The type of padding algorithm + * used in the forward prop of the op. + * @param dataFormat: An optional string from: "NHWC", "NCHW". Defaults to + * "NHWC". Specify the data format of the input and output data. With the + * default format "NHWC", the data is stored in the order of: [batch, + * height, width, channels]. + * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The + * rounding mode used when computing output dimensions if pad is a + * number. If none is provided, it will not round and error if the output + * is of fractional size. + */ + function conv2DBackpropFilter_(x, dy, filterShape, strides, pad, dataFormat, dimRoundingMode) { + if (dataFormat === void 0) { dataFormat = 'NHWC'; } + var x4D = x; + if (x.rank === 3) { + x4D = reshape(x, [1, x.shape[0], x.shape[1], x.shape[2]]); + } + var dy4D = dy; + if (dy4D.rank === 3) { + dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); + } + assert(x4D.rank === 4, function () { return "Error in conv2dDerFilter: input must be rank 4, but got shape " + + (x4D.shape + "."); }); + assert(dy4D.rank === 4, function () { return "Error in conv2dDerFilter: dy must be rank 4, but got shape " + + (dy4D.shape + "."); }); + assert(filterShape.length === 4, function () { return "Error in conv2dDerFilter: filterShape must be length 4, but got " + + (filterShape + "."); }); + var inDepth = dataFormat === 'NHWC' ? x4D.shape[3] : x4D.shape[1]; + var outDepth = dataFormat === 'NHWC' ? dy4D.shape[3] : dy4D.shape[1]; + assert(inDepth === filterShape[2], function () { return "Error in conv2dDerFilter: depth of input " + inDepth + ") must " + + ("match input depth in filter (" + filterShape[2] + "."); }); + assert(outDepth === filterShape[3], function () { return "Error in conv2dDerFilter: depth of dy (" + outDepth + ") must " + + ("match output depth for filter (" + filterShape[3] + ")."); }); + if (dimRoundingMode != null) { + assert(isInt(pad), function () { return "Error in conv2dDerFilter: pad must be an integer when using, " + + ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); + } + var forward = function (backend) { + var dilations = 1; + var $dataFormat = convertConv2DDataFormat(dataFormat); + var convInfo = computeConv2DInfo(x4D.shape, filterShape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); + return backend.conv2dDerFilter(x4D, dy4D, convInfo); + }; + var inputs = { x: x4D, dy: dy4D }; + var attrs = { strides: strides, pad: pad, dataFormat: dataFormat, dimRoundingMode: dimRoundingMode }; + return ENGINE.runKernelFunc(forward, inputs, null, Conv2DBackpropFilter, attrs); + } + var conv2DBackpropFilter = op({ conv2DBackpropFilter_: conv2DBackpropFilter_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the derivative of the input of a 2D convolution. + * + * @param xShape The shape of the input: [batch, height, width, inDepth]. + * If length of 3, batch of 1 is assumed. + * @param dy The derivative of the output, of rank 4 or rank 3 of shape + * `[batch, outHeight, outWidth, outDepth]`. If rank 3, batch of 1 is + * assumed. + * @param filter The filter, rank 4, of shape + * `[filterHeight, filterWidth, inDepth, outDepth]`. + * @param strides The strides of the convolution: `[strideHeight, + * strideWidth]`. + * @param pad The type of padding algorithm used: + * - `same` and stride 1: output will be of same size as input, + * regardless of filter size. + * - `valid`: output will be smaller than input if filter is larger + * than 1x1. + * @param dataFormat: An optional string from: "NHWC", "NCHW". Defaults to + * "NHWC". Specify the data format of the input and output data. With the + * default format "NHWC", the data is stored in the order of: [batch, + * height, width, channels]. + * @param dimRoundingMode The rounding mode used when computing output + * dimensions if pad is a number. If none is provided, it will not round + * and error if the output is of fractional size. + */ + function conv2DBackpropInput_(xShape, dy, filter, strides, pad, dataFormat, dimRoundingMode) { + if (dataFormat === void 0) { dataFormat = 'NHWC'; } + assert(xShape.length === dy.rank, function () { return "Length of inShape " + + ("(" + xShape.length + ") and rank of dy (" + dy.rank + ") must match"); }); + var xShape4D = xShape; + var dy4D = dy; + var reshapedTo4D = false; + if (dy.rank === 3) { + reshapedTo4D = true; + dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); + xShape4D = [1, xShape[0], xShape[1], xShape[2]]; + } + assert(xShape4D.length === 4, function () { + return "Error in conv2dDerInput: inShape must be length 4, but got length " + + (xShape4D.length + "."); + }); + assert(dy4D.rank === 4, function () { return "Error in conv2dDerInput: dy must be rank 4, but got " + + ("rank " + dy4D.rank); }); + assert(filter.rank === 4, function () { return "Error in conv2dDerInput: filter must be rank 4, but got " + + ("rank " + filter.rank); }); + var inDepth = dataFormat === 'NHWC' ? xShape4D[3] : xShape4D[1]; + var outDepth = dataFormat === 'NHWC' ? dy4D.shape[3] : dy4D.shape[1]; + assert(inDepth === filter.shape[2], function () { return "Error in conv2dDerInput: depth of input (" + inDepth + ") must " + + ("match input depth for filter " + filter.shape[2] + "."); }); + assert(outDepth === filter.shape[3], function () { return "Error in conv2dDerInput: depth of output (" + outDepth + ") must " + + ("match output depth for filter " + filter.shape[3] + "."); }); + if (dimRoundingMode != null) { + assert(isInt(pad), function () { return "Error in conv2dDerInput: pad must be an integer when using, " + + ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); + } + var forward = function (backend, save) { + var dilations = 1; + var $dataFormat = convertConv2DDataFormat(dataFormat); + var convInfo = computeConv2DInfo(xShape4D, filter.shape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); + var res = backend.conv2dDerInput(dy4D, filter, convInfo); + save([dy4D, filter]); + return res; + }; + var inputs = { dy: dy4D, filter: filter }; + var attrs = { strides: strides, pad: pad, dataFormat: dataFormat, dimRoundingMode: dimRoundingMode, inputShape: xShape4D }; + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, Conv2DBackpropInput, attrs); + if (reshapedTo4D) { + return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); + } + return res; + } + var conv2DBackpropInput = op({ conv2DBackpropInput_: conv2DBackpropInput_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var conv2DGradConfig = { + kernelName: Conv2D, + inputsToSave: ['x', 'filter'], + gradFunc: function (dy, saved, attrs) { + var _a = saved, x4D = _a[0], $filter = _a[1]; + var _b = attrs, dilations = _b.dilations, strides = _b.strides, pad = _b.pad, dataFormat = _b.dataFormat; + assert(tupleValuesAreOne(dilations), function () { return 'Error in gradient of conv2D: dilation rates greater than 1 ' + + ("are not yet supported in gradients. Got dilations '" + dilations + "'"); }); + return { + x: function () { + return conv2DBackpropInput(x4D.shape, dy, $filter, strides, pad, dataFormat); + }, + filter: function () { + return conv2DBackpropFilter(x4D, dy, $filter.shape, strides, pad, dataFormat); + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes a 2D convolution over the input x. + * + * @param x The input tensor, of rank 4 or rank 3, of shape + * `[batch, height, width, inChannels]`. If rank 3, batch of 1 is + * assumed. + * @param filter The filter, rank 4, of shape + * `[filterHeight, filterWidth, inDepth, outDepth]`. + * @param strides The strides of the convolution: `[strideHeight, + * strideWidth]`. + * @param pad The type of padding algorithm. + * - `same` and stride 1: output will be of same size as input, + * regardless of filter size. + * - `valid`: output will be smaller than input if filter is larger + * than 1x1. + * - For more info, see this guide: + * [https://www.tensorflow.org/api_guides/python/nn#Convolution]( + * https://www.tensorflow.org/api_guides/python/nn#Convolution) + * @param dataFormat: An optional string from: "NHWC", "NCHW". Defaults to + * "NHWC". Specify the data format of the input and output data. With the + * default format "NHWC", the data is stored in the order of: [batch, + * height, width, channels]. + * @param dilations The dilation rates: `[dilationHeight, dilationWidth]` + * in which we sample input values across the height and width dimensions + * in atrous convolution. Defaults to `[1, 1]`. If `dilations` is a single + * number, then `dilationHeight == dilationWidth`. If it is greater than + * 1, then all values of `strides` must be 1. + * @param dimRoundingMode The rounding mode used when computing output + * dimensions if pad is a number. If none is provided, it will not round + * and error if the output is of fractional size. + */ + /** @doc {heading: 'Operations', subheading: 'Convolution'} */ + function conv2d_(x, filter, strides, pad, dataFormat, dilations, dimRoundingMode) { + if (dataFormat === void 0) { dataFormat = 'NHWC'; } + if (dilations === void 0) { dilations = [1, 1]; } + var $x = convertToTensor(x, 'x', 'conv2d'); + var $filter = convertToTensor(filter, 'filter', 'conv2d'); + var x4D = $x; + var reshapedTo4D = false; + if ($x.rank === 3) { + reshapedTo4D = true; + x4D = reshape($x, [1, $x.shape[0], $x.shape[1], $x.shape[2]]); + } + assert(x4D.rank === 4, function () { return "Error in conv2d: input must be rank 4, but got rank " + x4D.rank + "."; }); + assert($filter.rank === 4, function () { return "Error in conv2d: filter must be rank 4, but got rank " + + ($filter.rank + "."); }); + if (dimRoundingMode != null) { + assert(isInt(pad), function () { return "Error in conv2d: pad must be an integer when using, " + + ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); + } + var inDepth = dataFormat === 'NHWC' ? x4D.shape[3] : x4D.shape[1]; + assert(inDepth === $filter.shape[2], function () { return "Error in conv2d: depth of input (" + inDepth + ") must match " + + ("input depth for filter " + $filter.shape[2] + "."); }); + assert(eitherStridesOrDilationsAreOne(strides, dilations), function () { return 'Error in conv2D: Either strides or dilations must be 1. ' + + ("Got strides " + strides + " and dilations '" + dilations + "'"); }); + var forward = function (backend, save) { + var $dataFormat = convertConv2DDataFormat(dataFormat); + var convInfo = computeConv2DInfo(x4D.shape, $filter.shape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); + var res = backend.conv2d(x4D, $filter, convInfo); + save([x4D, $filter]); + return res; + }; + var inputs = { x: x4D, filter: $filter }; + var attrs = { strides: strides, pad: pad, dataFormat: dataFormat, dilations: dilations, dimRoundingMode: dimRoundingMode }; + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, Conv2D, attrs); + if (reshapedTo4D) { + return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); + } + return res; + } + var conv2d = op({ conv2d_: conv2d_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var conv2DBackpropInputGradConfig = { + kernelName: Conv2DBackpropInput, + inputsToSave: ['dy', 'filter'], + gradFunc: function (ddx, saved, attrs) { + var _a = saved, dy = _a[0], filter = _a[1]; + var _b = attrs, strides = _b.strides, pad = _b.pad, dataFormat = _b.dataFormat, dimRoundingMode = _b.dimRoundingMode; + return { + dy: function () { return conv2d(ddx, filter, strides, pad, dataFormat, 1 /* dilations */, dimRoundingMode); }, + filter: function () { return conv2DBackpropFilter(ddx, dy, filter.shape, strides, pad, dataFormat, dimRoundingMode); } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the derivative of the filter of a 3D convolution. + * + * @param x The input tensor, of rank 5 or rank 4 of shape + * [batch, depth, height, width, inChannels]. If rank 4, batch of 1 is + * assumed. + * @param dy The dy image, of rank 5 or rank 4, of shape + * [batch, depth, height, width, outDepth]. If rank 4, batch of 1 is + * assumed. + * @param filterShape The shape of the filter, length 5, + * [filterDepth, filterHeight, filterWidth, inDepth, outDepth]. + * @param strides The strides of the convolution: [strideDepth, strideHeight, + * strideWidth]. + * @param pad A string from: 'same', 'valid'. The type of padding algorithm + * used in the forward prop of the op. + */ + function conv3DBackpropFilter_(x, dy, filterShape, strides, pad) { + var x5D = x; + if (x.rank === 4) { + x5D = reshape(x, [1, x.shape[0], x.shape[1], x.shape[2], x.shape[3]]); + } + var dy5D = dy; + if (dy5D.rank === 4) { + dy5D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2], dy.shape[3]]); + } + assert(x5D.rank === 5, function () { return "Error in conv3dDerFilter: input must be rank 5, but got shape " + + (x5D.shape + "."); }); + assert(dy5D.rank === 5, function () { return "Error in conv3dDerFilter: dy must be rank 5, but got shape " + + (dy5D.shape + "."); }); + assert(filterShape.length === 5, function () { return "Error in conv3dDerFilter: filterShape must be length 5, but got " + + (filterShape + "."); }); + assert(x5D.shape[4] === filterShape[3], function () { return "Error in conv3dDerFilter: depth of input " + x5D.shape[4] + ") must " + + ("match input depth in filter (" + filterShape[3] + "."); }); + assert(dy5D.shape[4] === filterShape[4], function () { return "Error in conv3dDerFilter: depth of dy (" + dy5D.shape[4] + ") must " + + ("match output depth for filter (" + filterShape[4] + ")."); }); + var forward = function (backend) { + var dilations = 1; + var convInfo = computeConv3DInfo(x5D.shape, filterShape, strides, dilations, pad); + return backend.conv3dDerFilter(x5D, dy5D, convInfo); + }; + var inputs = { x: x5D, y: dy5D }; + var attrs = { strides: strides, pad: pad }; + return ENGINE.runKernelFunc(forward, inputs, null, Conv3DBackpropFilterV2, attrs); + } + var conv3DBackpropFilter = op({ conv3DBackpropFilter_: conv3DBackpropFilter_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the derivative of the input of a 3D convolution. + * + * @param xShape The shape of the input: [batch, depth, height, width, + * in_channels]. If length of 4, batch of 1 is assumed. + * @param dy The derivative of the output, of rank 5 or rank 4 of shape + * `[batch, outDepth, outHeight, outWidth, in_channels]`. + * If rank 4, batch of 1 is assumed. + * @param filter The filter, rank 5, of shape + * `[filterDepth, filterHeight, filterWidth, inDepth, outDepth]`. + * @param strides The strides of the convolution: `[strideDepth, strideHeight, + * strideWidth]`. + * @param pad The type of padding algorithm used: + * - `same` and stride 1: output will be of same size as input, + * regardless of filter size. + * - `valid`: output will be smaller than input if filter is larger + * than 1x1. + */ + function conv3DBackpropInput_(xShape, dy, filter, strides, pad) { + assert(xShape.length === dy.rank, function () { return "Length of inShape " + + ("(" + xShape.length + ") and rank of dy (" + dy.rank + ") must match"); }); + var xShape5D = xShape; + var dy5D = dy; + var reshapedTo5D = false; + if (dy.rank === 4) { + reshapedTo5D = true; + dy5D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2], dy.shape[3]]); + xShape5D = [1, xShape[0], xShape[1], xShape[2], xShape[3]]; + } + var inDepth = xShape5D[4]; + var outDepth = dy5D.shape[4]; + assert(xShape5D.length === 5, function () { + return "Error in conv3dDerInput: inShape must be length 5, but got length " + + (xShape5D.length + "."); + }); + assert(dy5D.rank === 5, function () { return "Error in conv3dDerInput: dy must be rank 5, but got " + + ("rank " + dy5D.rank); }); + assert(filter.rank === 5, function () { return "Error in conv3dDerInput: filter must be rank 5, but got " + + ("rank " + filter.rank); }); + assert(inDepth === filter.shape[3], function () { return "Error in conv3dDerInput: depth of input (" + inDepth + ") must " + + ("match input depth for filter " + filter.shape[3] + "."); }); + assert(outDepth === filter.shape[4], function () { return "Error in conv3dDerInput: depth of output (" + outDepth + ") must " + + ("match output depth for filter " + filter.shape[4] + "."); }); + var forward = function (backend) { + var dilations = 1; + var convInfo = computeConv3DInfo(xShape5D, filter.shape, strides, dilations, pad); + return backend.conv3dDerInput(dy5D, filter, convInfo); + }; + var inputs = { dy: dy5D }; + var attrs = { pad: pad }; + var res = ENGINE.runKernelFunc(forward, inputs, null, Conv3DBackpropInputV2, attrs); + if (reshapedTo5D) { + return reshape(res, [res.shape[1], res.shape[2], res.shape[3], res.shape[4]]); + } + return res; + } + var conv3DBackpropInput = op({ conv3DBackpropInput_: conv3DBackpropInput_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var conv3DGradConfig = { + kernelName: Conv3D, + inputsToSave: ['x', 'filter'], + gradFunc: function (dy, saved, attrs) { + var _a = attrs, dilations = _a.dilations, strides = _a.strides, pad = _a.pad; + assert(tupleValuesAreOne(dilations), function () { + return 'Error in gradient of conv3D: dilation rates greater than 1 are ' + + ("not yet supported in gradients. Got dilations '" + dilations + "'"); + }); + var x5D = saved[0], $filter = saved[1]; + return { + x: function () { return conv3DBackpropInput(x5D.shape, dy, $filter, strides, pad); }, + filter: function () { return conv3DBackpropFilter(x5D, dy, $filter.shape, strides, pad); } + }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes sin of the input Tensor element-wise: `sin(x)` + * + * ```js + * const x = tf.tensor1d([0, Math.PI / 2, Math.PI * 3 / 4]); + * + * x.sin().print(); // or tf.sin(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function sin_(x) { + var $x = convertToTensor(x, 'x', 'sin'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.sin($x); + save([$x]); + return res; + }, inputs, null /* grad */, Sin); + } + var sin = op({ sin_: sin_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var cosGradConfig = { + kernelName: Cos, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(neg(sin(cast(x, 'float32'))), dy); } }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes hyperbolic sin of the input `tf.Tensor` element-wise: `sinh(x)` + * + * ```js + * const x = tf.tensor1d([0, 1, -1, .7]); + * + * x.sinh().print(); // or tf.sinh(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function sinh_(x) { + var $x = convertToTensor(x, 'x', 'sinh'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.sinh($x); + save([$x]); + return res; + }, inputs, null /* grad */, Sinh); + } + var sinh = op({ sinh_: sinh_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var coshGradConfig = { + kernelName: Cosh, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(sinh(cast(x, 'float32')), dy); } }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Transposes the `tf.Tensor`. Permutes the dimensions according to `perm`. + * + * The returned `tf.Tensor`'s dimension `i` will correspond to the input + * dimension `perm[i]`. If `perm` is not given, it is set to `[n-1...0]`, + * where `n` is the rank of the input `tf.Tensor`. Hence by default, this + * operation performs a regular matrix transpose on 2-D input `tf.Tensor`s. + * + * ```js + * const a = tf.tensor2d([1, 2, 3, 4, 5, 6], [2, 3]); + * + * a.transpose().print(); // or tf.transpose(a) + * ``` + * + * @param x The tensor to transpose. + * @param perm The permutation of the dimensions of a. + */ + /** @doc {heading: 'Operations', subheading: 'Matrices'} */ + function transpose_(x, perm) { + var $x = convertToTensor(x, 'x', 'transpose'); + if (perm == null) { + perm = $x.shape.map(function (s, i) { return i; }).reverse(); + } + assert($x.rank === perm.length, function () { return "Error in transpose: rank of input " + $x.rank + " " + + ("must match length of perm " + perm + "."); }); + perm.forEach(function (axis) { + assert(axis >= 0 && axis < $x.rank, function () { return "All entries in 'perm' must be between 0 and " + ($x.rank - 1) + + (" but got " + perm); }); + }); + if ($x.rank <= 1) { + return $x.clone(); + } + var inputs = { x: $x }; + var attrs = { perm: perm }; + return ENGINE.runKernelFunc(function (backend) { return backend.transpose($x, perm); }, inputs, null /* gradient */, Transpose, attrs); + } + var transpose = op({ transpose_: transpose_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the cumulative sum of a `tf.Tensor` along `axis`. + * + * ```js + * const x = tf.tensor([1, 2, 3, 4]); + * x.cumsum().print(); + * ``` + * ```js + * const x = tf.tensor([[1, 2], [3, 4]]); + * x.cumsum().print(); + * ``` + * + * @param x The input tensor to be summed. + * @param axis The axis along which to sum. Optional. Defaults to 0. + * @param exclusive Whether to perform exclusive cumulative sum. Optional. + * Defaults to false. If set to true then the sum of each tensor entry + * does not include its own value, but only the values previous to it + * along the specified axis. + * @param reverse Whether to sum in the opposite direction. Optional. + * Defaults to false. + */ + /** @doc {heading: 'Operations', subheading: 'Scan'} */ + function cumsum_(x, axis, exclusive, reverse) { + if (axis === void 0) { axis = 0; } + if (exclusive === void 0) { exclusive = false; } + if (reverse === void 0) { reverse = false; } + var $x = convertToTensor(x, 'x', 'cumsum'); + var forward = function (backend, save) { + var permutation = getAxesPermutation([axis], $x.rank); + var permutedX = $x; + if (permutation != null) { + permutedX = transpose($x, permutation); + } + var permutedAxis = getInnerMostAxes(1, $x.rank)[0]; + var value = backend.cumsum(permutedX, permutedAxis, exclusive, reverse); + save([$x]); + if (permutation != null) { + var reversePermutation = getUndoAxesPermutation(permutation); + value = transpose(value, reversePermutation); + } + return value; + }; + var inputs = { x: $x }; + var attrs = { axis: axis, exclusive: exclusive, reverse: reverse }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Cumsum, attrs); + } + var cumsum = op({ cumsum_: cumsum_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var cumsumGradConfig = { + kernelName: Cumsum, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0]; + var _a = attrs, axis = _a.axis, exclusive = _a.exclusive, reverse = _a.reverse; + return { + x: function () { + var permutation = getAxesPermutation([axis], x.rank); + var out = cumsum(dy, axis, exclusive, !reverse); + if (permutation != null) { + out = transpose(out, permutation); + } + return out; + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function depthwiseConv2dNativeBackpropFilter_(x, dy, filterShape, convInfo) { + var x4D = x; + if (x.rank === 3) { + x4D = reshape(x, [1, x.shape[0], x.shape[1], x.shape[2]]); + } + var dy4D = dy; + if (dy4D.rank === 3) { + dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); + } + var forward = function (backend) { + return backend.depthwiseConv2DDerFilter(x4D, dy4D, convInfo); + }; + var inputs = { x: x4D, dy: dy4D }; + return ENGINE.runKernelFunc(forward, inputs, null, DepthwiseConv2dNativeBackpropFilter); + } + var depthwiseConv2dNativeBackpropFilter = op({ depthwiseConv2dNativeBackpropFilter_: depthwiseConv2dNativeBackpropFilter_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function depthwiseConv2dNativeBackpropInput_(xShape, dy, filter, convInfo) { + var dy4D = dy; + var reshapedTo4D = false; + if (dy.rank === 3) { + reshapedTo4D = true; + dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); + } + var forward = function (backend) { + return backend.depthwiseConv2DDerInput(dy4D, filter, convInfo); + }; + var inputs = { dy: dy4D }; + var res = ENGINE.runKernelFunc(forward, inputs, null, DepthwiseConv2dNativeBackpropInput); + if (reshapedTo4D) { + return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); + } + return res; + } + var depthwiseConv2dNativeBackpropInput = op({ depthwiseConv2dNativeBackpropInput_: depthwiseConv2dNativeBackpropInput_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var depthwiseConv2dNativeGradConfig = { + kernelName: DepthwiseConv2dNative, + inputsToSave: ['x', 'filter'], + gradFunc: function (dy, saved, attrs) { + var _a = attrs, dilations = _a.dilations, strides = _a.strides, pad = _a.pad, dimRoundingMode = _a.dimRoundingMode; + var $dilations = dilations == null ? [1, 1] : dilations; + assert(tupleValuesAreOne($dilations), function () { return 'Error in gradient of depthwiseConv2dNative: dilation rates ' + + "greater than 1 are not yet supported. Got dilations " + + ("'" + $dilations + "'"); }); + var _b = saved, x = _b[0], filter = _b[1]; + assert(x.rank === 4, function () { return "Error in gradient of depthwiseConv2dNative: input must be " + + ("rank 4, but got rank " + x.rank + "."); }); + assert(filter.rank === 4, function () { return "Error in gradient of depthwiseConv2dNative: filter must be " + + ("rank 4, but got rank " + filter.rank + "."); }); + assert(x.shape[3] === filter.shape[2], function () { return "Error in gradient of depthwiseConv2d: number of input " + + ("channels (" + x.shape[3] + ") must match the inChannels dimension ") + + ("in filter " + filter.shape[2] + "."); }); + assert(eitherStridesOrDilationsAreOne(strides, $dilations), function () { return 'Error in gradient of depthwiseConv2d: Either strides or ' + + ("dilations must be 1. Got strides " + strides + " and dilations ") + + ("'" + $dilations + "'."); }); + if (dimRoundingMode != null) { + assert(isInt(pad), function () { + return "Error in depthwiseConv2d: pad must be an integer when using, " + + ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); + }); + } + var convInfo = computeConv2DInfo(x.shape, filter.shape, strides, $dilations, pad, dimRoundingMode, true /* depthwise */); + return { + x: function () { + return depthwiseConv2dNativeBackpropInput(x.shape, dy, filter, convInfo); + }, + filter: function () { + return depthwiseConv2dNativeBackpropFilter(x, dy, filter.shape, convInfo); + }, + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var dilation2dGradConfig = { + kernelName: Dilation2D, + inputsToSave: ['x', 'filter'], + gradFunc: function (dy, saved, attrs) { + var _a = saved, x = _a[0], filter = _a[1]; + var inputInputs = { x: x, filter: filter, dy: dy }; + var filterInputs = { x: x, filter: filter, dy: dy }; + return { + x: function () { return ENGINE.runKernel(Dilation2DBackpropInput, inputInputs, attrs); }, + filter: function () { return ENGINE.runKernel(Dilation2DBackpropFilter, filterInputs, attrs); } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var divGradConfig = { + kernelName: Div, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var outShape = assertAndGetBroadcastShape(a.shape, b.shape); + var derA = function () { + var res = div(dy, b.toFloat()); + var reduceAxes = getReductionAxes(a.shape, outShape); + if (reduceAxes.length > 0) { + return sum$1(res, reduceAxes).reshape(a.shape); + } + return res; + }; + var derB = function () { + var res = mul(dy, a.toFloat()); + var reduceAxes = getReductionAxes(b.shape, outShape); + if (reduceAxes.length > 0) { + res = reshape(sum$1(res, reduceAxes), b.shape); + } + var tmp = square(b); + return neg(div(res, tmp.toFloat())); + }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var eluGradConfig = { + kernelName: Elu, + outputsToSave: [true], + gradFunc: function (dy, saved) { + var y = saved[0]; + var backPropKernelFunc = function (backend) { + return backend.eluDer(dy, y); + }; + var inputs = { dy: dy, y: y }; + return { + x: function () { return ENGINE.runKernelFunc(backPropKernelFunc, inputs, null /* grad */, EluGrad); } + }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes exponential of the input `tf.Tensor` element-wise. `e ^ x` + * + * ```js + * const x = tf.tensor1d([1, 2, -3]); + * + * x.exp().print(); // or tf.exp(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function exp_(x) { + var $x = convertToTensor(x, 'x', 'exp'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.exp($x); + save([res]); + return res; + }, inputs, null /* grad */, Exp); + } + var exp = op({ exp_: exp_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var erfGradConfig = { + kernelName: Erf, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + var a = mul(exp(neg(square(x))), 2 / Math.sqrt(Math.PI)); + return { x: function () { return mul(dy, a); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var expGradConfig = { + kernelName: Exp, + outputsToSave: [true], + gradFunc: function (dy, saved) { + var y = saved[0]; + return { x: function () { return mul(dy, y); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var expm1GradConfig = { + kernelName: Expm1, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(dy, exp(x)); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var floorGradConfig = { + kernelName: Floor, + gradFunc: function (dy) { + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var floorDivGradConfig = { + kernelName: FloorDiv, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var outShape = assertAndGetBroadcastShape(a.shape, b.shape); + var derA = function () { + var res = dy.div(b.toFloat()); + var reduceAxes = getReductionAxes(a.shape, outShape); + if (reduceAxes.length > 0) { + return res.sum(reduceAxes).reshape(a.shape); + } + return res; + }; + var derB = function () { + var res = dy.mul(a.toFloat()); + var reduceAxes = getReductionAxes(b.shape, outShape); + if (reduceAxes.length > 0) { + res = res.sum(reduceAxes).reshape(b.shape); + } + var tmp = b.square(); + return res.div(tmp.toFloat()).neg(); + }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes reciprocal of square root of the input `tf.Tensor` element-wise: + * `y = 1 / sqrt(x)` + * + * ```js + * const x = tf.tensor1d([1, 2, 4, -1]); + * + * x.rsqrt().print(); // or tf.rsqrt(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function rsqrt_(x) { + var $x = convertToTensor(x, 'x', 'rsqrt'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.rsqrt($x); + save([$x]); + return res; + }, inputs, null /* grad */, Rsqrt); + } + var rsqrt = op({ rsqrt_: rsqrt_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Construct a tensor by repeating it the number of times given by reps. + * + * This operation creates a new tensor by replicating `input` `reps` + * times. The output tensor's i'th dimension has `input.shape[i] * + * reps[i]` elements, and the values of `input` are replicated + * `reps[i]` times along the i'th dimension. For example, tiling + * `[a, b, c, d]` by `[2]` produces `[a, b, c, d, a, b, c, d]`. + * + * ```js + * const a = tf.tensor1d([1, 2]); + * + * a.tile([2]).print(); // or a.tile([2]) + * ``` + * + * ```js + * const a = tf.tensor2d([1, 2, 3, 4], [2, 2]); + * + * a.tile([1, 2]).print(); // or a.tile([1, 2]) + * ``` + * @param x The tensor to tile. + * @param reps Determines the number of replications per dimension. + */ + /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ + function tile_(x, reps) { + var parseAs = null; + var $x = convertToTensor(x, 'x', 'tile', parseAs); + assert($x.rank === reps.length, function () { return "Error in transpose: rank of input " + $x.rank + " " + + ("must match length of reps " + reps + "."); }); + var forward = function (backend, save) { + var res = backend.tile($x, reps); + save([$x]); + return res; + }; + var inputsToSave = [$x]; + var inputs = { x: $x }; + var attrs = { reps: reps }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Tile, attrs, inputsToSave); + } + var tile = op({ tile_: tile_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var fusedBatchNormGradConfig = { + kernelName: FusedBatchNorm, + inputsToSave: ['x', 'mean', 'variance', 'scale'], + gradFunc: function (dy, saved, attrs) { + var varianceEpsilon = attrs.varianceEpsilon; + var x = saved[0], mean = saved[1], variance = saved[2], scale = saved[3]; + var scaleValue = scale == null ? scalar(1) : scale; + var reductionAxes = getReductionAxes(mean.shape, x.shape); + var tileShape = []; + if (mean.rank === 1) { + for (var i = 0; i < x.shape.length - 1; ++i) { + tileShape.push(x.shape[i]); + } + tileShape.push(1); + } + var xMinusMean = sub(x, mean); + var dyTimesScaleValue = mul(dy, scaleValue); + var oneOverSqrtVariance = rsqrt(add(variance, scalar(varianceEpsilon))); + var minusHalfRCube = mul(mul(mul(oneOverSqrtVariance, oneOverSqrtVariance), oneOverSqrtVariance), scalar(-0.5)); + var derX = function () { + if (mean.rank === 1) { + return reshape(mul(mul(dy, tile(oneOverSqrtVariance.as4D(1, 1, 1, mean.shape[0]), tileShape)), scaleValue), x.shape); + } + else { + return reshape(mul(mul(dy, oneOverSqrtVariance), scaleValue), x.shape); + } + }; + var derMean = function () { + var meanDer = mul(mul(oneOverSqrtVariance, scalar(-1)), dyTimesScaleValue); + if (mean.rank === 1) { + meanDer = sum$1(meanDer, reductionAxes); + } + return reshape(meanDer, mean.shape); + }; + var derVariance = function () { + var varianceDer = mul(mul(minusHalfRCube, xMinusMean), dyTimesScaleValue); + if (mean.rank === 1) { + varianceDer = sum$1(varianceDer, reductionAxes); + } + return reshape(varianceDer, mean.shape); + }; + var derScale = function () { + var xMinusMean2TimesRsqrt = mul(xMinusMean, oneOverSqrtVariance); + var scaleDer = mul(dy, xMinusMean2TimesRsqrt); + if (mean.rank === 1) { + scaleDer = sum$1(scaleDer, reductionAxes); + } + return reshape(scaleDer, mean.shape); + }; + var derOffset = function () { + var offsetDer = dy; + if (mean.rank === 1) { + offsetDer = sum$1(offsetDer, reductionAxes); + } + return reshape(offsetDer, mean.shape); + }; + return { + x: derX, + mean: derMean, + variance: derVariance, + scale: derScale, + offset: derOffset + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the sum along segments of a `tf.Tensor`. + * + * ```js + * const x = tf.tensor1d([1, 2, 3, 4]); + * const segmentIds = tf.tensor1d([1, 2, 0, 1], 'int32'); + * const numSegments = 3; + * + * x.unsortedSegmentSum(segmentIds, numSegments).print() + * //or tf.unsortedSegmentSum(x, segmentIds, numSegments) + * ``` + * @param x The `tf.Tensor` that will be summed along its segments. + * @param segmentIds A `tf.Tensor1D` whose rank is equal to the rank of `x`'s + * dimension along the `axis`. Maps each element of `x` to a segment. + * @param numSegments The number of distinct `segmentIds`. + */ + /** @doc {heading: 'Operations', subheading: 'Segment'} */ + function unsortedSegmentSum_(x, segmentIds, numSegments) { + var $x = convertToTensor(x, 'x', 'unsortedSegmentSum'); + var $segmentIds = convertToTensor(segmentIds, 'segmentIds', 'unsortedSegmentSum', 'int32'); + assert(isInt(numSegments), function () { return 'numSegments must be of dtype int'; }); + var inputs = { x: $x, segmentIds: $segmentIds }; + var attrs = { numSegments: numSegments }; + var forward = function (backend, save) { + var res = backend.unsortedSegmentSum($x, $segmentIds, numSegments); + save([$segmentIds]); + return res; + }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, UnsortedSegmentSum, attrs); + } + var unsortedSegmentSum = op({ unsortedSegmentSum_: unsortedSegmentSum_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var gatherGradConfig = { + kernelName: GatherV2, + inputsToSave: ['x', 'indices'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0], indices = saved[1]; + var axis = attrs.axis; + var parsedAxis = parseAxisParam(axis, x.shape)[0]; + var derX = function () { + var paramsShape = x.shape; + var indicesSize = indices.size; + var outerShape = paramsShape.slice(0, parsedAxis); + var outerDims = outerShape.length; + var innerShape = paramsShape.slice(axis, paramsShape.length).slice(1); + var innerDims = innerShape.length; + var outerAxesIndices = arrayRange(0, outerDims); + var innerAxesIndices = arrayRange(outerDims + 1, outerDims + 1 + innerDims); + var valuesShape = arrayConcat([outerShape, [indicesSize], innerShape]); + var values = reshape(dy, valuesShape); + var reshapedIndices = reshape(indices, [indicesSize]); + var transposeDims = arrayConcat([[outerDims], outerAxesIndices, innerAxesIndices]); + var valuesTranspose = transpose(values, transposeDims); + var paramsGrad = unsortedSegmentSum(valuesTranspose, reshapedIndices, x.shape[parsedAxis]); + var invertTransposeDims = getUndoAxesPermutation(transposeDims); + paramsGrad = transpose(paramsGrad, invertTransposeDims); + return paramsGrad; + }; + return { x: derX, indices: function () { return indices; } }; + } + }; + function arrayRange(start, stop) { + var result = []; + for (var i = start; i < stop; ++i) { + result.push(i); + } + return result; + } + function arrayConcat(arrays) { + var result = []; + for (var i = 0; i < arrays.length; ++i) { + for (var j = 0; j < arrays[i].length; ++j) { + result.push(arrays[i][j]); + } + } + return result; + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var greaterEqualGradConfig = { + kernelName: GreaterEqual, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + return { a: function () { return zerosLike(a); }, b: function () { return zerosLike(b); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var identityGradConfig = { + kernelName: Identity, + gradFunc: function (dy) { + return { x: function () { return dy.toFloat(); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var isFiniteGradConfig = { + kernelName: IsFinite, + gradFunc: function (dy) { + // TODO(nsthorat): Let gradients be null for cases where we want to stop + // backpropgation. + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var isInfGradConfig = { + kernelName: IsInf, + gradFunc: function (dy) { + // TODO(nsthorat): Let gradients be null for cases where we want to stop + // backpropgation. + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var isNanGradConfig = { + kernelName: IsNan, + gradFunc: function (dy) { + // TODO(nsthorat): Let gradients be null for cases where we want to stop + // backpropgation. + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var log1pGradConfig = { + kernelName: Log1p, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, add(x, 1)); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var logGradConfig = { + kernelName: Log, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, cast(x, 'float32')); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var logSoftmaxGradConfig = { + kernelName: LogSoftmax, + inputsToSave: [], + outputsToSave: [true], + gradFunc: function (dy, saved, attrs) { + var value = saved[0]; + var axis = attrs.axis; + return { + logits: function () { + var keepDims = true; + var softmax = value.exp(); + return dy.sub(dy.sum(axis, keepDims).mul(softmax)); + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function localResponseNormalizationBackprop_(x, y, dy, depthRadius, bias, alpha, beta) { + if (depthRadius === void 0) { depthRadius = 5; } + if (bias === void 0) { bias = 1; } + if (alpha === void 0) { alpha = 1; } + if (beta === void 0) { beta = 0.5; } + var forward = function (backend) { + return backend.LRNGrad(dy, x, y, depthRadius, bias, alpha, beta); + }; + var inputs = { x: x, y: y, dy: dy }; + var attrs = { depthRadius: depthRadius, bias: bias, alpha: alpha, beta: beta }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, LRNBackprop, attrs); + } + var localResponseNormalizationBackprop = op({ localResponseNormalizationBackprop_: localResponseNormalizationBackprop_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var lrnGradConfig = { + kernelName: LRN, + inputsToSave: ['x'], + outputsToSave: [true], + gradFunc: function (dy, saved, attrs) { + var _a = saved, x = _a[0], y = _a[1]; + var _b = attrs, depthRadius = _b.depthRadius, bias = _b.bias, alpha = _b.alpha, beta = _b.beta; + return { + x: function () { return localResponseNormalizationBackprop(x, y, dy, depthRadius, bias, alpha, beta); } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the truth value of (a == b) element-wise. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([1, 2, 3]); + * const b = tf.tensor1d([2, 2, 2]); + * + * a.equal(b).print(); + * ``` + * + * @param a The first input tensor. + * @param b The second input tensor. Must have the same dtype as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function equal_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'equal'); + var $b = convertToTensor(b, 'b', 'equal'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + assertAndGetBroadcastShape($a.shape, $b.shape); + var forward = function (backend) { return backend.equal($a, $b); }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null, Equal); + } + var equal = op({ equal_: equal_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Gradient helper function for the min and max operations. + */ + function gradForMinAndMax(dy, y, xOrig, origAxes, permutedAxes) { + if (y.rank < xOrig.rank) { + y = reshape(y, expandShapeToKeepDim(y.shape, origAxes)); + } + if (dy.rank < xOrig.rank) { + dy = reshape(dy, expandShapeToKeepDim(dy.shape, origAxes)); + } + return { + x: function () { + var dx = mul(dy, cast(equal(xOrig, y), dy.dtype)); + return permutedAxes == null ? dx : transpose(dx, permutedAxes); + } + }; + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var maxGradConfig = { + kernelName: Max, + inputsToSave: ['x'], + outputsToSave: [true], + gradFunc: function (dy, saved, attrs) { + var maxAttrs = attrs; + var reductionIndices = maxAttrs.reductionIndices; + var x = saved[0], y = saved[1]; + var origAxes = parseAxisParam(reductionIndices, x.shape); + var permutedAxes = getAxesPermutation(origAxes, x.rank); + var maxGrad = gradForMinAndMax(dy, y, x, origAxes, permutedAxes); + return { + x: function () { + var out = maxGrad['x'](); + if (permutedAxes != null) { + out = transpose(out); + } + return out; + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the truth value of (a < b) element-wise. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([1, 2, 3]); + * const b = tf.tensor1d([2, 2, 2]); + * + * a.less(b).print(); + * ``` + * @param a The first input tensor. + * @param b The second input tensor. Must have the same dtype as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function less_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'less'); + var $b = convertToTensor(b, 'b', 'less'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + assertAndGetBroadcastShape($a.shape, $b.shape); + var forward = function (backend) { return backend.less($a, $b); }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Less); + } + var less = op({ less_: less_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var maximumGradConfig = { + kernelName: Maximum, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var derA = function () { return mul(dy, cast(greaterEqual(a, b), 'float32')); }; + var derB = function () { return mul(dy, cast(less(a, b), 'float32')); }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the backprop of a 3d max pool. + * + * @param dy The dy error, of rank 5 of shape + * [batchSize, depth, height, width, channels]. + * assumed. + * @param input The original input image, of rank 5 or rank 4 of shape + * [batchSize, depth, height, width, channels]. + * @param output The original output image, of rank 5 of shape + * [batchSize, outDepth, outHeight, outWidth, channels]. + * @param filterSize The filter size: + * `[filterDepth, filterHeight, filterWidth]`. + * `filterSize` is a single number, + * then `filterDepth == filterHeight == filterWidth`. + * @param strides The strides of the pooling: + * `[strideDepth, strideHeight, strideWidth]`. If + * `strides` is a single number, then `strideHeight == strideWidth`. + * @param dilations Deprecated, this field will be gone in v3.0.0. + * The dilation rates: `[dilationDepth, dilationHeight, dilationWidth]` + * in which we sample input values across the depth, height and width + * dimensions in dilated pooling. + * Defaults to `[1, 1, 1]`. If `dilations` is a single number, + * then `dilationDepth == dilationHeight == dilationWidth`. + * If it is greater than 1, then all values of `strides` must be 1. + * @param pad A string from: 'same', 'valid'. The type of padding algorithm + * used in the forward prop of the op. + * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The + * rounding mode used when computing output dimensions if pad is a + * number. If none is provided, it will not round and error if the output + * is of fractional size. + */ + function maxPool3dBackprop_(dy, input, output, filterSize, strides, dilations, pad, dimRoundingMode) { + if (dilations === void 0) { dilations = [1, 1, 1]; } + var $dy = convertToTensor(dy, 'dy', 'maxPool3dBackprop'); + var $input = convertToTensor(input, 'input', 'maxPool3dBackprop'); + var $output = convertToTensor(output, 'output', 'maxPool3dBackprop'); + var dy5D = $dy; + var input5D = $input; + var output5D = $output; + var reshapedTo5D = false; + if ($input.rank === 4) { + reshapedTo5D = true; + dy5D = reshape($dy, [1, $dy.shape[0], $dy.shape[1], $dy.shape[2], $dy.shape[3]]); + input5D = reshape($input, [ + 1, $input.shape[0], $input.shape[1], $input.shape[2], $input.shape[3] + ]); + output5D = reshape($output, [ + 1, $output.shape[0], $output.shape[1], $output.shape[2], $output.shape[3] + ]); + } + assert(dy5D.rank === 5, function () { return "Error in maxPool3dBackprop: dy must be rank 5 but got rank " + + (dy5D.rank + "."); }); + assert(input5D.rank === 5, function () { return "Error in maxPool3dBackprop: input must be rank 5 but got rank " + + (input5D.rank + "."); }); + assert(output5D.rank === 5, function () { return "Error in maxPool3dBackprop: output must be rank 5 but got rank " + + (output5D.rank + "."); }); + assert(eitherStridesOrDilationsAreOne(strides, dilations), function () { return 'Error in maxPool3dBackprop: Either strides or dilations ' + + ("must be 1. Got strides " + strides + " and dilations '" + dilations + "'"); }); + if (dimRoundingMode != null) { + assert(isInt(pad), function () { return "Error in maxPool3dBackprop: pad must be an integer when " + + ("using, dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); + } + var forward = function (backend) { + var convInfo = computePool3DInfo(input5D.shape, filterSize, strides, dilations, pad, dimRoundingMode); + return backend.maxPool3dBackprop(dy5D, input5D, output5D, convInfo); + }; + var inputs = { dy: dy5D, input: input5D, output: output5D }; + var attrs = { filterSize: filterSize, strides: strides, dilations: dilations, pad: pad, dimRoundingMode: dimRoundingMode }; + var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, MaxPool3DBackprop, attrs); + if (reshapedTo5D) { + return reshape(res, [res.shape[1], res.shape[2], res.shape[3], res.shape[4]]); + } + return res; + } + var maxPool3dBackprop = op({ maxPool3dBackprop_: maxPool3dBackprop_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var maxPool3DGradConfig = { + kernelName: MaxPool3D, + inputsToSave: ['x'], + outputsToSave: [true], + gradFunc: function (dy, saved, attrs) { + var _a = saved, x = _a[0], y = _a[1]; + var _b = attrs, filterSize = _b.filterSize, strides = _b.strides, dilations = _b.dilations, pad = _b.pad, dimRoundingMode = _b.dimRoundingMode; + var $dilations = dilations == null ? [1, 1, 1] : dilations; + return { + x: function () { return maxPool3dBackprop(dy, x, y, filterSize, strides, $dilations, pad, dimRoundingMode); } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the backprop of a 2D max pool. + * + * @param dy The dy error, of rank 4 or rank 3 of shape + * [batchSize, height, width, channels]. If rank 3, batch of 1 is + * assumed. + * @param input The original input image, of rank 4, of shape + * [batchSize, height, width, channels]. + * @param output The original output image, of rank 4, of shape + * [batchSize, outHeight, outWidth, channels]. + * @param filterSize The filter size: `[filterHeight, filterWidth]`. If + * `filterSize` is a single number, then `filterHeight == filterWidth`. + * @param strides The strides of the pooling: `[strideHeight, strideWidth]`. If + * `strides` is a single number, then `strideHeight == strideWidth`. + * @param pad A string from: 'same', 'valid'. The type of padding algorithm + * used in the forward prop of the op. + * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The + * rounding mode used when computing output dimensions if pad is a + * number. If none is provided, it will not round and error if the output + * is of fractional size. + */ + function maxPoolBackprop_(dy, input, output, filterSize, strides, pad, dimRoundingMode) { + var $dy = convertToTensor(dy, 'dy', 'maxPoolBackprop'); + var $input = convertToTensor(input, 'input', 'maxPoolBackprop'); + var $output = convertToTensor(output, 'output', 'maxPoolBackprop'); + assert($input.rank === $dy.rank, function () { return "Rank of input (" + $input.rank + ") does not match rank of dy " + + ("(" + $dy.rank + ")"); }); + assert($dy.rank === 4, function () { return "Error in maxPoolBackprop: dy must be rank 4 but got rank " + + ($dy.rank + "."); }); + assert($input.rank === 4, function () { return "Error in maxPoolBackprop: input must be rank 4 but got rank " + + ($input.rank + "."); }); + if (dimRoundingMode != null) { + assert(isInt(pad), function () { return "Error in maxPoolBackprop: pad must be an integer when using, " + + ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); + } + var forward = function (backend) { + var convInfo = computePool2DInfo($input.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); + return backend.maxPoolBackprop($dy, $input, $output, convInfo); + }; + var inputs = { dy: $dy, input: $input, output: $output }; + var attrs = { filterSize: filterSize, strides: strides, pad: pad, dimRoundingMode: dimRoundingMode }; + return ENGINE.runKernelFunc(forward, inputs, null, MaxPoolBackprop, attrs); + } + var maxPoolBackprop = op({ maxPoolBackprop_: maxPoolBackprop_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var maxPoolGradConfig = { + kernelName: MaxPool, + inputsToSave: ['x'], + outputsToSave: [true], + gradFunc: function (dy, saved, attrs) { + var _a = saved, x = _a[0], y = _a[1]; + var _b = attrs, filterSize = _b.filterSize, strides = _b.strides, pad = _b.pad; + return { + x: function () { return maxPoolBackprop(dy, x, y, filterSize, strides, pad); } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var minGradConfig = { + kernelName: Min, + inputsToSave: ['x'], + outputsToSave: [true], + gradFunc: function (dy, saved, attrs) { + var minAttrs = attrs; + var axis = minAttrs.axis; + var x = saved[0], y = saved[1]; + var origAxes = parseAxisParam(axis, x.shape); + var permutedAxes = getAxesPermutation(origAxes, x.rank); + var minGrad = gradForMinAndMax(dy, y, x, origAxes, permutedAxes); + return { + x: function () { + var out = minGrad['x'](); + if (permutedAxes != null) { + out = transpose(out); + } + return out; + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the truth value of (a > b) element-wise. Supports broadcasting. + * + * ```js + * const a = tf.tensor1d([1, 2, 3]); + * const b = tf.tensor1d([2, 2, 2]); + * + * a.greater(b).print(); + * ``` + * + * @param a The first input tensor. + * @param b The second input tensor. Must have the same dtype as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function greater_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'greater'); + var $b = convertToTensor(b, 'b', 'greater'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + assertAndGetBroadcastShape($a.shape, $b.shape); + var forward = function (backend) { return backend.greater($a, $b); }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Greater); + } + var greater = op({ greater_: greater_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var minimumGradConfig = { + kernelName: Minimum, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var derA = function () { return mul(dy, cast(lessEqual(a, b), 'float32')); }; + var derB = function () { return mul(dy, cast(greater(a, b), 'float32')); }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes floor of input `tf.Tensor` element-wise: `floor(x)`. + * + * ```js + * const x = tf.tensor1d([.6, 1.1, -3.3]); + * + * x.floor().print(); // or tf.floor(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function floor_(x) { + var $x = convertToTensor(x, 'x', 'floor'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend) { return backend.floor($x); }, inputs, null /* grad */, Floor); + } + var floor = op({ floor_: floor_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var modGradConfig = { + kernelName: Mod, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var outShape = assertAndGetBroadcastShape(a.shape, b.shape); + var derA = function () { + var reduceAxes = getReductionAxes(a.shape, outShape); + if (reduceAxes.length > 0) { + return reshape(sum$1(dy, reduceAxes), a.shape); + } + return dy; + }; + var derB = function () { + var res = mul(dy, neg(floor(div(a, b)))); + var reduceAxes = getReductionAxes(b.shape, outShape); + if (reduceAxes.length > 0) { + return reshape(sum$1(res, reduceAxes), b.shape); + } + return res; + }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var multiplyGradConfig = { + kernelName: Multiply, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var outShape = assertAndGetBroadcastShape(a.shape, b.shape); + var derA = function () { + var res = mul(dy, cast(b, 'float32')); + var reduceAxes = getReductionAxes(a.shape, outShape); + if (reduceAxes.length > 0) { + return reshape(sum$1(res, reduceAxes), a.shape); + } + return res; + }; + var derB = function () { + var res = mul(dy, cast(a, 'float32')); + var reduceAxes = getReductionAxes(b.shape, outShape); + if (reduceAxes.length > 0) { + return reshape(sum$1(res, reduceAxes), b.shape); + } + return res; + }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var negateGradConfig = { + kernelName: Negate, + gradFunc: function (dy) { + return { x: function () { return neg(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Converts two real numbers to a complex number. + * + * Given a tensor `real` representing the real part of a complex number, and a + * tensor `imag` representing the imaginary part of a complex number, this + * operation returns complex numbers elementwise of the form [r0, i0, r1, i1], + * where r represents the real part and i represents the imag part. + * + * The input tensors real and imag must have the same shape. + * + * ```js + * const real = tf.tensor1d([2.25, 3.25]); + * const imag = tf.tensor1d([4.75, 5.75]); + * const complex = tf.complex(real, imag); + * + * complex.print(); + * ``` + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function complex_(real, imag) { + var $real = convertToTensor(real, 'real', 'complex'); + var $imag = convertToTensor(imag, 'imag', 'complex'); + assertShapesMatch($real.shape, $imag.shape, "real and imag shapes, " + $real.shape + " and " + $imag.shape + ", " + + "must match in call to tf.complex()."); + var forward = function (backend) { + return backend.complex($real, $imag); + }; + var inputs = { real: $real, imag: $imag }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Complex); + } + var complex = op({ complex_: complex_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates a `tf.Tensor` with all elements set to 0. + * + * ```js + * tf.zeros([2, 2]).print(); + * ``` + * + * @param shape An array of integers defining the output tensor shape. + * @param dtype The type of an element in the resulting tensor. Can + * be 'float32', 'int32' or 'bool'. Defaults to 'float'. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function zeros(shape, dtype) { + if (dtype === void 0) { dtype = 'float32'; } + if (dtype === 'complex64') { + var real = zeros(shape, 'float32'); + var imag = zeros(shape, 'float32'); + return complex(real, imag); + } + var values = makeZerosTypedArray(sizeFromShape(shape), dtype); + return ENGINE.makeTensor(values, shape, dtype); + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var oneHotGradConfig = { + kernelName: OneHot, + inputsToSave: ['indices'], + gradFunc: function (dy, saved) { + var indices = saved[0]; + return { indices: function () { return zeros(indices.shape, 'float32'); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var onesLikeGradConfig = { + kernelName: OnesLike, + gradFunc: function (dy) { + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var padV2GradConfig = { + kernelName: PadV2, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + // Pad introduces values around the original tensor, so the gradient + // slices the original shape out of the gradient. + var x = saved[0]; + var paddings = attrs.paddings; + var begin = paddings.map(function (p) { return p[0]; }); + return { x: function () { return dy.slice(begin, x.shape); } }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes natural logarithm of the input `tf.Tensor` element-wise: `ln(x)` + * + * ```js + * const x = tf.tensor1d([1, 2, Math.E]); + * + * x.log().print(); // or tf.log(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function log_(x) { + var $x = convertToTensor(x, 'x', 'log'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.log($x); + save([$x]); + return res; + }, inputs, null /* grad */, Log); + } + var log = op({ log_: log_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the power of one `tf.Tensor` to another. Supports broadcasting. + * + * Given a `tf.Tensor` x and a `tf.Tensor` y, this operation computes x^y for + * corresponding elements in x and y. The result's dtype will be the upcasted + * type of the `base` and `exp` dtypes. + * + * ```js + * const a = tf.tensor([[2, 3], [4, 5]]) + * const b = tf.tensor([[1, 2], [3, 0]]).toInt(); + * + * a.pow(b).print(); // or tf.pow(a, b) + * ``` + * + * ```js + * const a = tf.tensor([[1, 2], [3, 4]]) + * const b = tf.tensor(2).toInt(); + * + * a.pow(b).print(); // or tf.pow(a, b) + * ``` + * We also expose `powStrict` which has the same signature as this op and + * asserts that `base` and `exp` are the same shape (does not broadcast). + * + * @param base The base `tf.Tensor` to pow element-wise. + * @param exp The exponent `tf.Tensor` to pow element-wise. + */ + /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ + function pow_(base, exp) { + var _a; + var $base = convertToTensor(base, 'base', 'pow'); + var $exp = convertToTensor(exp, 'exp', 'pow'); + _a = makeTypesMatch($base, $exp), $base = _a[0], $exp = _a[1]; + var inputs = { a: $base, b: $exp }; + var forward = function (backend, save) { + var y = backend.pow($base, $exp); + save([$base, $exp, y]); + return y; + }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Pow); + } + var pow = op({ pow_: pow_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var powGradConfig = { + kernelName: Pow, + inputsToSave: ['a', 'b'], + outputsToSave: [true], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1], y = saved[2]; + var base = a; + var exp = b; + var outShape = assertAndGetBroadcastShape(base.shape, exp.shape); + var derBase = function () { + var expFloat = cast(exp, 'float32'); + var res = mul(dy, mul(expFloat, pow(base, sub(expFloat, scalar(1))))); + var reduceAxes = getReductionAxes(base.shape, outShape); + if (reduceAxes.length > 0) { + res = sum$1(res, reduceAxes); + } + return reshape(res, base.shape); + }; + var derExp = function () { + var condition = greater(base, 0); + var logBase = where(condition, log(base), zerosLike(base)); + var res = mul(dy, mul(y, logBase)); + var reduceAxes = getReductionAxes(exp.shape, outShape); + if (reduceAxes.length > 0) { + res = sum$1(res, reduceAxes); + } + return reshape(res, exp.shape); + }; + return { a: derBase, b: derExp }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var preluGradConfig = { + kernelName: Prelu, + inputsToSave: ['x', 'alpha'], + gradFunc: function (dy, saved) { + var x = saved[0], alpha = saved[1]; + var mask = greater(x, 0); + return { + x: function () { return where(mask, dy, mul(dy, alpha)); }, + alpha: function () { + var res = where(mask, zerosLike(dy), mul(dy, x)); + var reduceAxes = getReductionAxes(alpha.shape, dy.shape); + if (reduceAxes.length > 0) { + res = sum$1(res, reduceAxes); + } + return reshape(res, alpha.shape); + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var reciprocalGradConfig = { + kernelName: Reciprocal, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, neg(square(x))); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var relu6GradConfig = { + kernelName: Relu6, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + var mask = mul(lessEqual(x, 6), step(x)); + return { x: function () { return mul(dy, cast(mask, 'float32')); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var reluGradConfig = { + kernelName: Relu, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(dy, cast(step(x), 'float32')); } }; + } + }; + + /** + * @license + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var reshapeGradConfig = { + kernelName: Reshape, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return reshape(dy, x.shape); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var resizeBilinearGradConfig = { + kernelName: ResizeBilinear, + inputsToSave: ['images'], + gradFunc: function (dy, saved, attrs) { + var images = saved[0]; + var backPropKernelFunc = function (backend) { + var alignCorners = attrs.alignCorners; + return backend.resizeBilinearBackprop(dy, images, alignCorners); + }; + var inputs = { images: images }; + var imagesDer = function () { return ENGINE.runKernelFunc(backPropKernelFunc, inputs, null /* gradient */, ResizeBilinearGrad, attrs); }; + return { images: imagesDer }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var resizeNearestNeighborGradConfig = { + kernelName: ResizeNearestNeighbor, + inputsToSave: ['images'], + gradFunc: function (dy, saved, attrs) { + var images = saved[0]; + var backPropKernelFunc = function (backend) { + var alignCorners = attrs.alignCorners; + return backend.resizeNearestNeighborBackprop(dy, images, alignCorners); + }; + var inputs = { images: images }; + var imagesDer = function () { return ENGINE.runKernelFunc(backPropKernelFunc, inputs, null /* gradient */, ResizeNearestNeighborGrad, attrs); }; + return { images: imagesDer }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates a new tensor with the same values and shape as the specified + * tensor. + * + * ```js + * const x = tf.tensor([1, 2]); + * + * x.clone().print(); + * ``` + * + * @param x The tensor to clone. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function clone_(x) { + var $x = convertToTensor(x, 'x', 'clone', null); + var forward = function () { + return ENGINE.makeTensorFromDataId($x.dataId, $x.shape, $x.dtype); + }; + var inputs = { x: $x }; + // Note this op is called tf.identity in python. Hence the kernel name used + // here. + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Identity); + } + var clone = op({ clone_: clone_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Reverses a `tf.Tensor` along a specified axis. + * + * Also available are stricter rank-specific methods that assert that `x` is + * of the given rank: + * - `tf.reverse1d` + * - `tf.reverse2d` + * - `tf.reverse3d` + * - `tf.reverse4d` + * + * Except `tf.reverse1d` (which does not have axis param), all methods have + * same signature as this method. + * + * ```js + * const x = tf.tensor1d([1, 2, 3, 4]); + * + * x.reverse().print(); + * ``` + * + * ```js + * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); + * + * const axis = 1; + * x.reverse(axis).print(); + * ``` + * @param x The input tensor to be reversed. + * @param axis The set of dimensions to reverse. Must be in the + * range [-rank(x), rank(x)). Defaults to all axes. + */ + /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ + function reverse_(x, axis) { + var $x = convertToTensor(x, 'x', 'reverse'); + var forward = function (backend) { + var axes = parseAxisParam(axis, $x.shape); + if ($x.rank === 0) { + return clone($x); + } + var res = backend.reverse($x, axes); + return reshape(res, $x.shape); + }; + var inputs = { x: $x }; + var attrs = { dims: axis }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Reverse, attrs); + } + var reverse = op({ reverse_: reverse_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var reverseGradConfig = { + kernelName: Reverse, + gradFunc: function (dy, saved, attrs) { + var dims = attrs.dims; + var axes = parseAxisParam(dims, dy.shape); + return { x: function () { return reverse(dy, axes); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var roundGradConfig = { + kernelName: Round, + gradFunc: function (dy) { + // TODO(nsthorat): Let gradients be null for cases where we want to stop + // backpropgation. + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var rsqrtGradConfig = { + kernelName: Rsqrt, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return neg(div(dy, mul(pow(x, 1.5), 2))); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the truth value of `NOT x` element-wise. + * + * ```js + * const a = tf.tensor1d([false, true], 'bool'); + * + * a.logicalNot().print(); + * ``` + * + * @param x The input tensor. Must be of dtype 'bool'. + */ + /** @doc {heading: 'Operations', subheading: 'Logical'} */ + function logicalNot_(x) { + var $x = convertToTensor(x, 'x', 'logicalNot', 'bool'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend) { return backend.logicalNot($x); }, inputs, null /* grad */, LogicalNot); + } + var logicalNot = op({ logicalNot_: logicalNot_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var selectV2PoolGradConfig = { + kernelName: SelectV2, + inputsToSave: ['condition'], + gradFunc: function (dy, saved) { + var condition = saved[0]; + return { + // TODO(julianoks): Return null for condition gradient + // when backprop supports it. + condition: function () { return cast(zerosLike(condition), 'float32'); }, + t: function () { return mul(dy, cast(condition, dy.dtype)); }, + e: function () { return mul(dy, cast(logicalNot(condition), dy.dtype)); } + }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var SELU_SCALEALPHA = 1.7580993408473768599402175208123; + var SELU_SCALE = 1.0507009873554804934193349852946; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var seluGradConfig = { + kernelName: Selu, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { + x: function () { + var mask = greater(x, scalar(0)); + var scaleAlpha = scalar(SELU_SCALEALPHA); + var scale = scalar(SELU_SCALE); + var greaterThanZeroDer = mul(dy, scale); + var lessEqualZeroDer = mul(mul(dy, scaleAlpha), exp(cast(x, 'float32'))); + return where(mask, greaterThanZeroDer, lessEqualZeroDer); + } + }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var sigmoidGradConfig = { + kernelName: Sigmoid, + outputsToSave: [true], + gradFunc: function (dy, saved) { + var y = saved[0]; + return { x: function () { return mul(dy, mul(y, sub(scalar(1), y))); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var signGradConfig = { + kernelName: Sign, + gradFunc: function (dy) { + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes cos of the input `tf.Tensor` element-wise: `cos(x)` + * + * ```js + * const x = tf.tensor1d([0, Math.PI / 2, Math.PI * 3 / 4]); + * + * x.cos().print(); // or tf.cos(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function cos_(x) { + var $x = convertToTensor(x, 'x', 'cos'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.cos($x); + save([$x]); + return res; + }, inputs, null /* grad */, Cos); + } + var cos = op({ cos_: cos_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var sinGradConfig = { + kernelName: Sin, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(cos(cast(x, 'float32')), dy); } }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes hyperbolic cos of the input `tf.Tensor` element-wise: `cosh(x)` + * + * ```js + * const x = tf.tensor1d([0, 1, -1, .7]); + * + * x.cosh().print(); // or tf.cosh(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function cosh_(x) { + var $x = convertToTensor(x, 'x', 'cosh'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.cosh($x); + save([$x]); + return res; + }, inputs, null /* grad */, Cosh); + } + var cosh = op({ cosh_: cosh_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var sinhGradConfig = { + kernelName: Sinh, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(cosh(cast(x, 'float32')), dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Pads a `tf.Tensor` with a given value and paddings. + * + * This operation currently only implements the `CONSTANT` mode. + * + * Also available are stricter rank-specific methods with the same signature + * as this method that assert that `paddings` is of given length. + * - `tf.pad1d` + * - `tf.pad2d` + * - `tf.pad3d` + * - `tf.pad4d` + * + * ```js + * const x = tf.tensor1d([1, 2, 3, 4]); + * x.pad([[1, 2]]).print(); + * ``` + * @param x The tensor to pad. + * @param paddings An array of length `R` (the rank of the tensor), where + * each element is a length-2 tuple of ints `[padBefore, padAfter]`, + * specifying how much to pad along each dimension of the tensor. + * @param constantValue The pad value to use. Defaults to 0. + */ + /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ + function pad_(x, paddings, constantValue) { + if (constantValue === void 0) { constantValue = 0; } + var $x = convertToTensor(x, 'x', 'pad'); + if ($x.rank === 0) { + throw new Error('pad(scalar) is not defined. Pass non-scalar to pad'); + } + var forward = function (backend, save) { + save([$x]); + return backend.pad($x, paddings, constantValue); + }; + var attrs = { paddings: paddings, constantValue: constantValue }; + var inputs = { x: $x }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, PadV2, attrs); + } + var pad = op({ pad_: pad_ }); + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function assertParamsValid(input, begin, size) { + assert(input.rank === begin.length, function () { return "Error in slice" + input.rank + "D: Length of begin " + begin + " must " + + ("match the rank of the array (" + input.rank + ")."); }); + assert(input.rank === size.length, function () { return "Error in slice" + input.rank + "D: Length of size " + size + " must " + + ("match the rank of the array (" + input.rank + ")."); }); + var _loop_1 = function (i) { + assert(begin[i] + size[i] <= input.shape[i], function () { return "Error in slice" + input.rank + "D: begin[" + i + "] + size[" + i + "] " + + ("(" + (begin[i] + size[i]) + ") would overflow input.shape[" + i + "] (" + input.shape[i] + ")"); }); + }; + for (var i = 0; i < input.rank; ++i) { + _loop_1(i); + } + } + /** Converts a binary mask to an array of axes. Used in stridedSlice(). */ + function maskToAxes(mask) { + var axes = []; + var axis = 0; + while (mask > 0) { + if (mask & 1) { + axes.push(axis); + } + mask /= 2; + axis++; + } + return axes; + } + /** Computes the output shape given the strided slice params. */ + function computeOutShape(begin, end, strides) { + var size = []; + for (var axis = 0; axis < begin.length; axis++) { + size[axis] = Math.ceil((end[axis] - begin[axis]) / strides[axis]); + } + return size; + } + // Creates full selection at the elided dimensions. If the dimension matches + // the ellipsis mask, override the current stride value. Otherwise, insert. + function stridesWithElidedDims(strides, ellipsisInsertionIndex, numElidedAxes, inputShape) { + var newStrides = strides.slice(); + for (var i = newStrides.length; i < inputShape.length; i++) { + newStrides.push(1); + } + for (var i = 0; i < numElidedAxes; i++) { + if (i === 0) { + newStrides[ellipsisInsertionIndex] = 1; + } + else { + newStrides.splice(ellipsisInsertionIndex, 0 /* num elements to delete */, 1 /* element to add */); + newStrides.pop(); + } + } + return newStrides; + } + function unnormalizeAxis(ellipsisInsertionIndex, numElidedAxes, normalizedAxis) { + if (normalizedAxis <= ellipsisInsertionIndex) { + return normalizedAxis; + } + return normalizedAxis - (numElidedAxes - 1); + } + function getElidedAxes(numElidedAxes, ellipsisInsertionIndex) { + var elidedAxes = []; + for (var i = 0; i < numElidedAxes; i++) { + elidedAxes.push(ellipsisInsertionIndex + i); + } + return elidedAxes; + } + // Creates full selection at the elided dimensions. If the dimension matches + // the ellipsis mask, override the current start value. Otherwise, insert. + function startIndicesWithElidedDims(beginMask, ellipsisInsertionIndex, numElidedAxes, originalBegin, inputShape) { + var newIndices = inputShape.slice(); + var elidedAxes = getElidedAxes(numElidedAxes, ellipsisInsertionIndex); + for (var axis = 0; axis < newIndices.length; axis++) { + if (elidedAxes.indexOf(axis) > -1) { + newIndices[axis] = 0; + } + else { + var originalAxis = unnormalizeAxis(ellipsisInsertionIndex, numElidedAxes, axis); + var originalValue = originalBegin[originalAxis]; + if (beginMask & 1 << originalAxis) { + originalValue = 0; + } + newIndices[axis] = originalValue; + } + } + return newIndices; + } + // Creates full selection at the elided dimensions. If the dimension matches + // the ellipsis mask, override the current stop value. Otherwise, insert. + function stopIndicesWithElidedDims(endMask, ellipsisInsertionIndex, numElidedAxes, originalEnd, inputShape) { + var newIndices = inputShape.slice(); + var elidedAxes = getElidedAxes(numElidedAxes, ellipsisInsertionIndex); + for (var axis = 0; axis < newIndices.length; axis++) { + if (elidedAxes.indexOf(axis) > -1) { + newIndices[axis] = Number.MAX_SAFE_INTEGER; + } + else { + var originalAxis = unnormalizeAxis(ellipsisInsertionIndex, numElidedAxes, axis); + var originalValue = originalEnd[originalAxis]; + if (endMask & 1 << originalAxis) { + originalValue = Number.MAX_SAFE_INTEGER; + } + newIndices[axis] = originalValue; + } + } + for (var i = 0; i < newIndices.length; i++) { + // Handle negative indices + var axisSize = inputShape[i]; + if (newIndices[i] < 0) { + newIndices[i] += axisSize; + } + newIndices[i] = clamp(0, newIndices[i], inputShape[i]); + } + return newIndices; + } + function stridesForAxis(strides, axis, ellipsisMask) { + var stride = strides[axis]; + if (ellipsisMask & (1 << axis) || stride == null) { + stride = 1; + } + return stride; + } + function startForAxis(beginMask, startIndices, strides, inputShape, axis, ellipsisMask) { + // Begin with the specified index + var start = startIndices[axis]; + var stride = strides[axis] || 1; + // Check the axis bit from right of masked axes, or the begin index is not set + // for the axis. + if (beginMask & 1 << axis || ellipsisMask & 1 << axis || start == null) { + if (stride > 0) { + // Forward iteration - use the first element. These values will get + // clamped below (Note: We could have set them to 0 and axis_size-1, but + // use lowest() and max() to maintain symmetry with StopForAxis()) + start = Number.MIN_SAFE_INTEGER; + } + else { + // Backward iteration - use the last element. + start = Number.MAX_SAFE_INTEGER; + } + } + // Handle negative indices + var axisSize = inputShape[axis]; + if (start < 0) { + start += axisSize; + } + // Clamping + start = clamp(0, start, axisSize - 1); + return start; + } + function stopForAxis(endMask, stopIndices, strides, inputShape, axis, ellipsisMask) { + // Begin with the specified index + var stop = stopIndices[axis]; + var stride = strides[axis] || 1; + // Check the axis bit from right of masked axes, or if the stop index is not + // set for this axis. + if (endMask & (1 << axis) || ellipsisMask & (1 << axis) || stop == null) { + if (stride > 0) { + // Forward iteration - use the last element. These values will get + // clamped below + stop = Number.MAX_SAFE_INTEGER; + } + else { + // Backward iteration - use the first element. + stop = Number.MIN_SAFE_INTEGER; + } + } + // Handle negative indices + var axisSize = inputShape[axis]; + if (stop < 0) { + stop += axisSize; + } + // Clamping + // Because the end index points one past the last element, we need slightly + // different clamping ranges depending on the direction. + if (stride > 0) { + // Forward iteration + stop = clamp(0, stop, axisSize); + } + else { + // Backward iteration + stop = clamp(-1, stop, axisSize - 1); + } + return stop; + } + /** + * Returns true if the slice occupies a continous set of elements in the + * 'flat' space. + */ + function isSliceContinous(shape, begin, size) { + // Index of the first axis that has size > 1. + var firstNonOneAxis = size.length; + for (var i = 0; i < size.length; i++) { + if (size[i] > 1) { + firstNonOneAxis = i; + break; + } + } + for (var i = firstNonOneAxis + 1; i < size.length; i++) { + if (begin[i] > 0 || size[i] !== shape[i]) { + return false; + } + } + return true; + } + function computeFlatOffset(begin, strides) { + var flatOffset = begin.length > 0 ? begin[begin.length - 1] : 1; + for (var i = 0; i < begin.length - 1; i++) { + flatOffset += begin[i] * strides[i]; + } + return flatOffset; + } + function parseSliceParams(x, begin, size) { + // The following logic allows for more ergonomic calls. + var begin_; + if (typeof begin === 'number') { + begin_ = [begin].concat(new Array(x.rank - 1).fill(0)); + } + else if (begin.length < x.rank) { + begin_ = begin.concat(new Array(x.rank - begin.length).fill(0)); + } + else { + begin_ = begin.slice(); + } + begin_.forEach(function (d) { + assert(d !== -1, function () { return 'slice() does not support negative begin indexing.'; }); + }); + var size_; + if (size == null) { + size_ = new Array(x.rank).fill(-1); + } + else if (typeof size === 'number') { + size_ = [size].concat(new Array(x.rank - 1).fill(-1)); + } + else if (size.length < x.rank) { + size_ = size.concat(new Array(x.rank - size.length).fill(-1)); + } + else { + size_ = size; + } + size_ = size_.map(function (d, i) { + if (d >= 0) { + return d; + } + else { + assert(d === -1, function () { return "Negative size values should be exactly -1 but got " + + (d + " for the slice() size at index " + i + "."); }); + return x.shape[i] - begin_[i]; + } + }); + return [begin_, size_]; + } + + var slice_util = { + __proto__: null, + assertParamsValid: assertParamsValid, + maskToAxes: maskToAxes, + computeOutShape: computeOutShape, + stridesWithElidedDims: stridesWithElidedDims, + startIndicesWithElidedDims: startIndicesWithElidedDims, + stopIndicesWithElidedDims: stopIndicesWithElidedDims, + stridesForAxis: stridesForAxis, + startForAxis: startForAxis, + stopForAxis: stopForAxis, + isSliceContinous: isSliceContinous, + computeFlatOffset: computeFlatOffset, + parseSliceParams: parseSliceParams + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var sliceGradConfig = { + kernelName: Slice, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0]; + var _a = attrs, begin = _a.begin, size = _a.size; + var inputShape = x.shape; + var _b = parseSliceParams(x, begin, size), begin_ = _b[0], size_ = _b[1]; + // Create an Nx2 padding where the first column represents how many + // zeros are prepended (at start) for each dimension, and the second + // column indicates how many zeros are appended (at end). + // The number of zeros to append is the shape of the input + // elementwise-subtracted by both the begin vector and sizes vector. + var paddings = []; + for (var i = 0; i < dy.rank; i++) { + paddings.push([begin_[i], inputShape[i] - begin_[i] - size_[i]]); + } + return { x: function () { return pad(dy, paddings); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var softmaxGradConfig = { + kernelName: Softmax, + outputsToSave: [true], + gradFunc: function (dy, saved, attrs) { + var y = saved[0]; + var dim = attrs.dim; + var keepDims = true; + var dyTimesY = mul(dy, y); + return { + logits: function () { return sub(dyTimesY, mul(sum$1(dyTimesY, [dim], keepDims), y)); } + }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes sigmoid element-wise, `1 / (1 + exp(-x))` + * + * ```js + * const x = tf.tensor1d([0, -1, 2, -3]); + * + * x.sigmoid().print(); // or tf.sigmoid(x) + * ``` + * @param x The input tensor. + */ + /** @doc {heading: 'Operations', subheading: 'Basic math'} */ + function sigmoid_(x) { + var $x = convertToTensor(x, 'x', 'sigmoid'); + var inputs = { x: $x }; + return ENGINE.runKernelFunc(function (backend, save) { + var res = backend.sigmoid($x); + save([res]); + return res; + }, inputs, null /* grad */, Sigmoid); + } + var sigmoid = op({ sigmoid_: sigmoid_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var softplusGradConfig = { + kernelName: Softplus, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(dy, sigmoid(x)); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * This operation reshapes the "batch" dimension 0 into `M + 1` dimensions of + * shape `blockShape + [batch]`, interleaves these blocks back into the grid + * defined by the spatial dimensions `[1, ..., M]`, to obtain a result with + * the same rank as the input. The spatial dimensions of this intermediate + * result are then optionally cropped according to `crops` to produce the + * output. This is the reverse of `tf.spaceToBatchND`. See below for a precise + * description. + * + * ```js + * const x = tf.tensor4d([1, 2, 3, 4], [4, 1, 1, 1]); + * const blockShape = [2, 2]; + * const crops = [[0, 0], [0, 0]]; + * + * x.batchToSpaceND(blockShape, crops).print(); + * ``` + * + * @param x A `tf.Tensor`. N-D with `x.shape` = `[batch] + spatialShape + + * remainingShape`, where spatialShape has `M` dimensions. + * @param blockShape A 1-D array. Must have shape `[M]`, all values must + * be >= 1. + * @param crops A 2-D array. Must have shape `[M, 2]`, all values must be >= 0. + * `crops[i] = [cropStart, cropEnd]` specifies the amount to crop from input + * dimension `i + 1`, which corresponds to spatial dimension `i`. It is required + * that `cropStart[i] + cropEnd[i] <= blockShape[i] * inputShape[i + 1]` + * + * This operation is equivalent to the following steps: + * + * 1. Reshape `x` to `reshaped` of shape: `[blockShape[0], ..., + * blockShape[M-1], batch / prod(blockShape), x.shape[1], ..., + * x.shape[N-1]]` + * + * 2. Permute dimensions of `reshaped`to produce `permuted` of shape `[batch / + * prod(blockShape),x.shape[1], blockShape[0], ..., x.shape[M], + * blockShape[M-1],x.shape[M+1], ..., x.shape[N-1]]` + * + * 3. Reshape `permuted` to produce `reshapedPermuted` of shape `[batch / + * prod(blockShape),x.shape[1] * blockShape[0], ..., x.shape[M] * + * blockShape[M-1],x.shape[M+1], ..., x.shape[N-1]]` + * + * 4. Crop the start and end of dimensions `[1, ..., M]` of `reshapedPermuted` + * according to `crops` to produce the output of shape: `[batch / + * prod(blockShape),x.shape[1] * blockShape[0] - crops[0,0] - crops[0,1], + * ..., x.shape[M] * blockShape[M-1] - crops[M-1,0] - + * crops[M-1,1],x.shape[M+1], ..., x.shape[N-1]]` + */ + /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ + function batchToSpaceND_(x, blockShape, crops) { + var $x = convertToTensor(x, 'x', 'batchToSpaceND'); + var prod = blockShape.reduce(function (a, b) { return a * b; }); + assert($x.rank >= 1 + blockShape.length, function () { return "input rank is " + $x.rank + " but should be > than blockShape.length " + blockShape.length; }); + assert(crops.length === blockShape.length, function () { return "crops.length is " + crops.length + " but should be equal to blockShape.length " + blockShape.length; }); + assert($x.shape[0] % prod === 0, function () { return "input tensor batch is " + $x.shape[0] + " but is not divisible by the product of " + + ("the elements of blockShape " + blockShape.join(' * ') + " === " + prod); }); + var forward = function (backend) { + return backend.batchToSpaceND($x, blockShape, crops); + }; + var inputs = { x: $x }; + var attrs = { blockShape: blockShape, crops: crops }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, BatchToSpaceND, attrs); + } + var batchToSpaceND = op({ batchToSpaceND_: batchToSpaceND_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var spaceToBatchNDGradConfig = { + kernelName: SpaceToBatchND, + gradFunc: function (dy, saved, attrs) { + var _a = attrs, blockShape = _a.blockShape, paddings = _a.paddings; + return { x: function () { return batchToSpaceND(dy, blockShape, paddings); } }; + } + }; + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function assertParamsConsistent(shapes, axis) { + var rank = shapes[0].length; + shapes.forEach(function (shape, i) { + assert(shape.length === rank, function () { + return "Error in concat" + rank + "D: rank of tensors[" + i + "] must be the same " + + ("as the rank of the rest (" + rank + ")"); + }); + }); + assert(axis >= 0 && axis < rank, function () { return "Error in concat" + rank + "D: axis must be between 0 and " + (rank - 1) + "."; }); + var firstShape = shapes[0]; + shapes.forEach(function (shape, i) { + for (var r = 0; r < rank; r++) { + assert((r === axis) || (shape[r] === firstShape[r]), function () { return "Error in concat" + rank + "D: Shape of tensors[" + i + "] (" + shape + ") " + + ("does not match the shape of the rest (" + firstShape + ") ") + + ("along the non-concatenated axis " + i + "."); }); + } + }); + } + function computeOutShape$1(shapes, axis) { + var outputShape = shapes[0].slice(); + for (var i = 1; i < shapes.length; i++) { + outputShape[axis] += shapes[i][axis]; + } + return outputShape; + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates a `tf.Tensor` with the provided values, shape and dtype. + * + * ```js + * // Pass an array of values to create a vector. + * tf.tensor([1, 2, 3, 4]).print(); + * ``` + * + * ```js + * // Pass a nested array of values to make a matrix or a higher + * // dimensional tensor. + * tf.tensor([[1, 2], [3, 4]]).print(); + * ``` + * + * ```js + * // Pass a flat array and specify a shape yourself. + * tf.tensor([1, 2, 3, 4], [2, 2]).print(); + * ``` + * + * @param values The values of the tensor. Can be nested array of numbers, + * or a flat array, or a `TypedArray`. If the values are strings, + * they will be encoded as utf-8 and kept as `Uint8Array[]`. + * @param shape The shape of the tensor. Optional. If not provided, + * it is inferred from `values`. + * @param dtype The data type. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function tensor(values, shape, dtype) { + var inferredShape = inferShape(values, dtype); + return makeTensor(values, shape, inferredShape, dtype); + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Concatenates a list of `tf.Tensor`s along a given axis. + * + * The tensors ranks and types must match, and their sizes must match in all + * dimensions except `axis`. + * + * Also available are stricter rank-specific methods that assert that + * `tensors` are of the given rank: + * - `tf.concat1d` + * - `tf.concat2d` + * - `tf.concat3d` + * - `tf.concat4d` + * + * Except `tf.concat1d` (which does not have axis param), all methods have + * same signature as this method. + * + * ```js + * const a = tf.tensor1d([1, 2]); + * const b = tf.tensor1d([3, 4]); + * a.concat(b).print(); // or a.concat(b) + * ``` + * + * ```js + * const a = tf.tensor1d([1, 2]); + * const b = tf.tensor1d([3, 4]); + * const c = tf.tensor1d([5, 6]); + * tf.concat([a, b, c]).print(); + * ``` + * + * ```js + * const a = tf.tensor2d([[1, 2], [10, 20]]); + * const b = tf.tensor2d([[3, 4], [30, 40]]); + * const axis = 1; + * tf.concat([a, b], axis).print(); + * ``` + * @param tensors A list of tensors to concatenate. + * @param axis The axis to concate along. Defaults to 0 (the first dim). + */ + /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ + function concat_(tensors, axis) { + if (axis === void 0) { axis = 0; } + assert(tensors.length >= 1, function () { return 'Pass at least one tensor to concat'; }); + var $tensors = convertToTensorArray(tensors, 'tensors', 'concat'); + if ($tensors[0].dtype === 'complex64') { + $tensors.forEach(function (tensor) { + if (tensor.dtype !== 'complex64') { + throw new Error("Cannot concatenate complex64 tensors with a tensor\n with dtype " + tensor.dtype + ". "); + } + }); + } + var $axis = parseAxisParam(axis, $tensors[0].shape)[0]; + var outShape = computeOutShape$1($tensors.map(function (t) { return t.shape; }), $axis); + if (sizeFromShape(outShape) === 0) { + return tensor([], outShape); + } + // Keep only non-empty tensors (ignore tensors with 0 in their shape). + $tensors = $tensors.filter(function (t) { return t.size > 0; }); + if ($tensors.length === 1) { + return $tensors[0]; + } + var shapes = $tensors.map(function (t) { return t.shape; }); + assertParamsConsistent(shapes, $axis); + var forward = function (backend, save) { + var res = backend.concat($tensors, $axis); + save($tensors); + return res; + }; + var inputs = $tensors; + var attr = { axis: axis }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Concat, attr); + } + var concat = op({ concat_: concat_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var splitVGradConfig = { + kernelName: SplitV, + gradFunc: function (dy, saved, attrs) { + var axis = attrs.axis; + return { x: function () { return concat(dy, axis); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var sqrtGradConfig = { + kernelName: Sqrt, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, mul(sqrt(cast(x, 'float32')), 2)); } }; + } + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var squareGradConfig = { + kernelName: Square, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return mul(dy, mul(x.toFloat(), 2)); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var squaredDifferenceGradConfig = { + kernelName: SquaredDifference, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var two = scalar(2); + var derA = function () { return mul(dy, mul(two, sub(a, b))); }; + var derB = function () { return mul(dy, mul(two, sub(b, a))); }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var stepGradConfig = { + kernelName: Step, + gradFunc: function (dy) { + // TODO(manrajgrover): Return null for gradients when backprop supports + // it. + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var subGradConfig = { + kernelName: Sub, + inputsToSave: ['a', 'b'], + gradFunc: function (dy, saved) { + var a = saved[0], b = saved[1]; + var outShape = assertAndGetBroadcastShape(a.shape, b.shape); + var derA = function () { + var res = dy; + var reduceAxes = getReductionAxes(a.shape, outShape); + if (reduceAxes.length > 0) { + res = sum$1(res, reduceAxes); + } + return reshape(res, a.shape); + }; + var derB = function () { + var res = dy; + var reduceAxes = getReductionAxes(b.shape, outShape); + if (reduceAxes.length > 0) { + res = sum$1(res, reduceAxes); + } + return reshape(neg(res), b.shape); + }; + return { a: derA, b: derB }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates a `tf.Tensor` with all elements set to 1. + * + * ```js + * tf.ones([2, 2]).print(); + * ``` + * + * @param shape An array of integers defining the output tensor shape. + * @param dtype The type of an element in the resulting tensor. Defaults to + * 'float'. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function ones$1(shape, dtype) { + if (dtype === void 0) { dtype = 'float32'; } + if (dtype === 'complex64') { + var real = ones$1(shape, 'float32'); + var imag = zeros(shape, 'float32'); + return complex(real, imag); + } + var values = makeOnesTypedArray(sizeFromShape(shape), dtype); + return ENGINE.makeTensor(values, shape, dtype); + } + + /** + * @license + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var sumGradConfig = { + kernelName: Sum, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0]; + var expandedDyShape = x.shape.slice(); + var axis = attrs.axis; + var axes = parseAxisParam(axis, x.shape); + axes.forEach(function (axis) { + expandedDyShape[axis] = 1; + }); + var expandedDy = reshape(dy, expandedDyShape); + var derX = mul(expandedDy, ones$1(x.shape, 'float32')); + return { x: function () { return derX; } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var tanGradConfig = { + kernelName: Tan, + inputsToSave: ['x'], + gradFunc: function (dy, saved) { + var x = saved[0]; + return { x: function () { return div(dy, square(cos(x))); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var tanhGradConfig = { + kernelName: Tanh, + outputsToSave: [true], + gradFunc: function (dy, saved) { + var y = saved[0]; + return { x: function () { return mul(sub(scalar(1), square(y)), dy); } }; + } + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Extracts a slice from a `tf.Tensor` starting at coordinates `begin` + * and is of size `size`. + * + * Also available are stricter rank-specific methods with the same signature + * as this method that assert that `x` is of the given rank: + * - `tf.slice1d` + * - `tf.slice2d` + * - `tf.slice3d` + * - `tf.slice4d` + * + * ```js + * const x = tf.tensor1d([1, 2, 3, 4]); + * + * x.slice([1], [2]).print(); + * ``` + * + * ```js + * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); + * + * x.slice([1, 0], [1, 2]).print(); + * ``` + * @param x The input `tf.Tensor` to slice from. + * @param begin The coordinates to start the slice from. The length can be + * less than the rank of x - the rest of the axes will have implicit 0 as + * start. Can also be a single number, in which case it specifies the + * first axis. + * @param size The size of the slice. The length can be less than the rank of + * x - the rest of the axes will have implicit -1. A value of -1 requests + * the rest of the dimensions in the axis. Can also be a single number, + * in which case it specifies the size of the first axis. + */ + /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ + function slice_(x, begin, size) { + var $x = convertToTensor(x, 'x', 'slice'); + if ($x.rank === 0) { + throw new Error('Slicing scalar is not possible'); + } + var _a = parseSliceParams($x, begin, size), begin_ = _a[0], size_ = _a[1]; + assertParamsValid($x, begin_, size_); + var forward = function (backend, save) { + save([$x]); + return backend.slice($x, begin_, size_); + }; + var inputs = { x: $x }; + var attrs = { begin: begin, size: size }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Slice, attrs); + } + var slice = op({ slice_: slice_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var tileGradConfig = { + kernelName: Tile, + inputsToSave: ['x'], + gradFunc: function (dy, saved, attrs) { + var x = saved[0]; + var reps = attrs.reps; + var derX = function () { + var xGrad = zerosLike(x); + // TODO(cais): Maybe reduce memory footprint by avoiding repeated + // slicing. + if (x.rank === 1) { + for (var i = 0; i < reps[0]; ++i) { + xGrad = add(xGrad, slice(dy, [i * x.shape[0]], [x.shape[0]])); + } + } + else if (x.rank === 2) { + for (var i = 0; i < reps[0]; ++i) { + for (var j = 0; j < reps[1]; ++j) { + xGrad = add(xGrad, slice(dy, [i * x.shape[0], j * x.shape[1]], [ + x.shape[0], x.shape[1] + ])); + } + } + } + else if (x.rank === 3) { + for (var i = 0; i < reps[0]; ++i) { + for (var j = 0; j < reps[1]; ++j) { + for (var k = 0; k < reps[2]; ++k) { + xGrad = + add(xGrad, slice(dy, [i * x.shape[0], j * x.shape[1], k * x.shape[2]], [x.shape[0], x.shape[1], x.shape[2]])); + } + } + } + } + else if (x.rank === 4) { + for (var i = 0; i < reps[0]; ++i) { + for (var j = 0; j < reps[1]; ++j) { + for (var k = 0; k < reps[2]; ++k) { + for (var l = 0; l < reps[3]; ++l) { + xGrad = + add(xGrad, slice(dy, [ + i * x.shape[0], j * x.shape[1], k * x.shape[2], + l * x.shape[3] + ], [x.shape[0], x.shape[1], x.shape[2], x.shape[3]])); + } + } + } + } + } + else { + throw new Error("Gradient for tile operation is not implemented for rank-" + + (x.rank + " tensors yet.")); + } + return xGrad; + }; + return { x: derX }; + }, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var transposeGradConfig = { + kernelName: Transpose, + gradFunc: function (dy, saved, attrs) { + var transposeAttrs = attrs; + var perm = transposeAttrs.perm; + var undoPerm = getUndoAxesPermutation(perm); + return { x: function () { return transpose(dy, undoPerm); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns a `tf.Tensor` that has expanded rank, by inserting a dimension + * into the tensor's shape. + * + * ```js + * const x = tf.tensor1d([1, 2, 3, 4]); + * const axis = 1; + * x.expandDims(axis).print(); + * ``` + * + * @param x The input tensor whose dimensions to be expanded. + * @param axis The dimension index at which to insert shape of `1`. Defaults + * to 0 (the first dimension). + */ + /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ + function expandDims_(x, axis) { + if (axis === void 0) { axis = 0; } + var parseAs = null; + var $x = convertToTensor(x, 'x', 'expandDims', parseAs); + assert(axis <= $x.rank, function () { return 'Axis must be <= rank of the tensor'; }); + var newShape = $x.shape.slice(); + if (axis < 0) { + // Negative value is counted from the tail of rank. + assert(-($x.rank + 1) <= axis, function () { return "Axis must be in the interval [" + -($x.rank + 1) + ", " + $x.rank + "]"; }); + axis = $x.rank + axis + 1; + } + newShape.splice(axis, 0, 1); + return reshape($x, newShape); + } + var expandDims = op({ expandDims_: expandDims_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Stacks a list of rank-`R` `tf.Tensor`s into one rank-`(R+1)` `tf.Tensor`. + * + * ```js + * const a = tf.tensor1d([1, 2]); + * const b = tf.tensor1d([3, 4]); + * const c = tf.tensor1d([5, 6]); + * tf.stack([a, b, c]).print(); + * ``` + * + * @param tensors A list of tensor objects with the same shape and dtype. + * @param axis The axis to stack along. Defaults to 0 (the first dim). + */ + /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ + function stack_(tensors, axis) { + if (axis === void 0) { axis = 0; } + var $tensors = convertToTensorArray(tensors, 'tensors', 'stack'); + assert($tensors.length >= 1, function () { return 'Pass at least one tensor to tf.stack'; }); + if ($tensors.length === 1) { + return expandDims($tensors[0], axis); + } + var rank = $tensors[0].rank; + var shape = $tensors[0].shape; + var dtype = $tensors[0].dtype; + assert(axis <= rank, function () { return 'Axis must be <= rank of the tensor'; }); + $tensors.forEach(function (t) { + assertShapesMatch(shape, t.shape, 'All tensors passed to stack must have matching shapes'); + assert(dtype === t.dtype, function () { return 'All tensors passed to stack must have matching dtypes'; }); + }); + var expandedTensors = $tensors.map(function (t) { return expandDims(t, axis); }); + // Stack exists in the TensorFlow C++ API + // (https://www.tensorflow.org/api_docs/cc/class/tensorflow/ops/stack) but not + // in + // https://raw.githubusercontent.com/tensorflow/tensorflow/master/tensorflow/core/ops/ops.pbtxt. + // Therefore we are treating it like a high-level op rather than + // creating a dedicated stack kernel. + return concat(expandedTensors, axis); + } + var stack = op({ stack_: stack_ }); + + /** + * @license + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var unpackGradConfig = { + kernelName: Unpack, + gradFunc: function (dy, saved, attrs) { + var unpackAttrs = attrs; + var axis = unpackAttrs.axis; + return { value: function () { return stack(dy, axis); } }; + } + }; + + /** + * @license + * Copyright 2017 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var PARALLELIZE_THRESHOLD = 30; + function computeOptimalWindowSize(inSize) { + if (inSize <= PARALLELIZE_THRESHOLD) { + return inSize; + } + return nearestDivisor(inSize, Math.floor(Math.sqrt(inSize))); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function segOpComputeOptimalWindowSize(inSize, numSegments) { + var done = false; + var res; + if (inSize <= PARALLELIZE_THRESHOLD) { + res = inSize; + done = true; + } + else { + res = nearestDivisor(inSize, Math.floor(Math.sqrt(inSize))); + } + while (!done) { + if (res > numSegments || res === inSize) { + done = true; + } + else { + res = nearestDivisor(inSize, res + 1); + } + } + return res; + } + function computeOutShape$2(aShape, axis, numSegments) { + var outShape = []; + var rank = aShape.length; + for (var dim = 0; dim < rank; dim++) { + if (dim !== axis) { + outShape.push(aShape[dim]); + } + else { + outShape.push(numSegments); + } + } + return outShape; + } + function collectGatherOpShapeInfo(x, indices, axis) { + var dimSize = x.shape[axis]; + var outputShape = []; + var batchSize = 1; + var sliceSize = 1; + for (var i = 0; i < axis; i++) { + outputShape.push(x.shape[i]); + batchSize *= x.shape[i]; + } + for (var i = 0; i < indices.rank; i++) { + outputShape.push(indices.shape[i]); + } + for (var i = axis + 1; i < x.rank; i++) { + outputShape.push(x.shape[i]); + sliceSize *= x.shape[i]; + } + return { batchSize: batchSize, sliceSize: sliceSize, dimSize: dimSize, outputShape: outputShape }; + } + + var segment_util = { + __proto__: null, + segOpComputeOptimalWindowSize: segOpComputeOptimalWindowSize, + computeOutShape: computeOutShape$2, + collectGatherOpShapeInfo: collectGatherOpShapeInfo + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Gather slices from tensor `x`'s axis `axis` according to `indices`. + * + * ```js + * const x = tf.tensor1d([1, 2, 3, 4]); + * const indices = tf.tensor1d([1, 3, 3], 'int32'); + * + * x.gather(indices).print(); + * ``` + * + * ```js + * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); + * const indices = tf.tensor1d([1, 1, 0], 'int32'); + * + * x.gather(indices).print(); + * ``` + * @param x The input tensor whose slices to be gathered. + * @param indices The indices of the values to extract. + * @param axis The axis over which to select values. Defaults to 0. + */ + /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ + function gather_(x, indices, axis) { + if (axis === void 0) { axis = 0; } + var $x = convertToTensor(x, 'x', 'gather'); + var $indices = convertToTensor(indices, 'indices', 'gather', 'int32'); + var inputs = { x: $x, indices: $indices }; + var attrs = { axis: axis }; + var forward = function (backend, save) { + var parsedAxis = parseAxisParam(axis, $x.shape)[0]; + var shapeInfo = collectGatherOpShapeInfo($x, $indices, parsedAxis); + var res = backend.gather($x, $indices.flatten(), parsedAxis); + save([$x, $indices]); + return res.reshape(shapeInfo.outputShape); + }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, GatherV2, attrs); + } + var gather = op({ gather_: gather_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Returns the max of a and b (`a > b ? a : b`) element-wise. + * Supports broadcasting. + * + * We also expose `tf.maximumStrict` which has the same signature as this op and + * asserts that `a` and `b` are the same shape (does not broadcast). + * + * ```js + * const a = tf.tensor1d([1, 4, 3, 16]); + * const b = tf.tensor1d([1, 2, 9, 4]); + * + * a.maximum(b).print(); // or tf.maximum(a, b) + * ``` + * + * ```js + * // Broadcast maximum a with b. + * const a = tf.tensor1d([2, 4, 6, 8]); + * const b = tf.scalar(5); + * + * a.maximum(b).print(); // or tf.maximum(a, b) + * ``` + * + * @param a The first tensor. + * @param b The second tensor. Must have the same type as `a`. + */ + /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ + function maximum_(a, b) { + var _a; + var $a = convertToTensor(a, 'a', 'maximum'); + var $b = convertToTensor(b, 'b', 'maximum'); + _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; + if ($a.dtype === 'bool') { + $a = cast($a, 'int32'); + $b = cast($b, 'int32'); + } + assertAndGetBroadcastShape($a.shape, $b.shape); + var forward = function (backend, save) { + var res = backend.maximum($a, $b); + save([$a, $b]); + return res; + }; + var inputs = { a: $a, b: $b }; + return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Maximum); + } + var maximum = op({ maximum_: maximum_ }); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var unsortedSegmentSumGradConfig = { + kernelName: UnsortedSegmentSum, + inputsToSave: ['segmentIds'], + gradFunc: function (dy, saved) { + var segmentIds = saved[0]; + var derX = function () { + return gatherDropNegatives(dy, segmentIds); + }; + return { x: derX }; + } + }; + function gatherDropNegatives(x, indices) { + // Helper function for unsorted segment ops. Gathers params for + // positive segment ids and gathers 0 for inputs with negative segment id. + // Mirrors _GatherDropNegatives from tensorflow/python/ops/math_grad.py + var zeroClippedIndices = maximum(indices, zerosLike(indices)); + var gathered = gather(x, zeroClippedIndices); + var isPositive = greaterEqual(indices, scalar(0, 'int32')); + var numIters = gathered.rank - isPositive.rank; + for (var i = 0; i < numIters; ++i) { + isPositive = expandDims(isPositive, i + 1); + } + isPositive = logicalAnd(isPositive, ones$1(gathered.shape, 'bool')); + var zeroSlice = zerosLike(gathered); + return where(isPositive, gathered, zeroSlice); + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var zerosLikeGradConfig = { + kernelName: ZerosLike, + gradFunc: function (dy) { + return { x: function () { return zerosLike(dy); } }; + } + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // Export all kernel configs here so that the package can auto register them + var gradConfigs = [ + absGradConfig, + acosGradConfig, + acoshGradConfig, + addGradConfig, + addNGradConfig, + argMaxGradConfig, + argMinGradConfig, + asinGradConfig, + asinhGradConfig, + atan2GradConfig, + atanGradConfig, + atanhGradConfig, + avgPool3DGradConfig, + avgPoolGradConfig, + batchMatMulGradConfig, + batchToSpaceNDGradConfig, + broadcastToGradConfig, + castGradConfig, + ceilGradConfig, + clipByValueGradConfig, + concatGradConfig, + conv2DBackpropInputGradConfig, + conv2DGradConfig, + conv3DGradConfig, + cosGradConfig, + coshGradConfig, + cumsumGradConfig, + depthwiseConv2dNativeGradConfig, + dilation2dGradConfig, + divGradConfig, + eluGradConfig, + erfGradConfig, + expGradConfig, + expm1GradConfig, + floorDivGradConfig, + floorGradConfig, + fusedBatchNormGradConfig, + gatherGradConfig, + greaterEqualGradConfig, + identityGradConfig, + isFiniteGradConfig, + isInfGradConfig, + isNanGradConfig, + log1pGradConfig, + logGradConfig, + logSoftmaxGradConfig, + lrnGradConfig, + maxGradConfig, + maxGradConfig, + maximumGradConfig, + maxPool3DGradConfig, + maxPoolGradConfig, + minGradConfig, + minimumGradConfig, + modGradConfig, + multiplyGradConfig, + negateGradConfig, + oneHotGradConfig, + onesLikeGradConfig, + padV2GradConfig, + padV2GradConfig, + powGradConfig, + preluGradConfig, + reciprocalGradConfig, + relu6GradConfig, + reluGradConfig, + reshapeGradConfig, + resizeBilinearGradConfig, + resizeNearestNeighborGradConfig, + reverseGradConfig, + roundGradConfig, + rsqrtGradConfig, + selectV2PoolGradConfig, + seluGradConfig, + sigmoidGradConfig, + signGradConfig, + sinGradConfig, + sinhGradConfig, + sliceGradConfig, + softmaxGradConfig, + softplusGradConfig, + spaceToBatchNDGradConfig, + spaceToBatchNDGradConfig, + splitVGradConfig, + splitVGradConfig, + sqrtGradConfig, + squaredDifferenceGradConfig, + squareGradConfig, + stepGradConfig, + subGradConfig, + sumGradConfig, + tanGradConfig, + tanhGradConfig, + tileGradConfig, + transposeGradConfig, + unpackGradConfig, + unsortedSegmentSumGradConfig, + zerosLikeGradConfig + ]; + for (var _i = 0, gradConfigs_1 = gradConfigs; _i < gradConfigs_1.length; _i++) { + var gradientConfig = gradConfigs_1[_i]; + registerGradient(gradientConfig); + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var PlatformBrowser = /** @class */ (function () { + function PlatformBrowser() { + } + PlatformBrowser.prototype.fetch = function (path, init) { + return fetch(path, init); + }; + PlatformBrowser.prototype.now = function () { + return performance.now(); + }; + PlatformBrowser.prototype.encode = function (text, encoding) { + if (encoding !== 'utf-8' && encoding !== 'utf8') { + throw new Error("Browser's encoder only supports utf-8, but got " + encoding); + } + if (this.textEncoder == null) { + this.textEncoder = new TextEncoder(); + } + return this.textEncoder.encode(text); + }; + PlatformBrowser.prototype.decode = function (bytes, encoding) { + return new TextDecoder(encoding).decode(bytes); + }; + return PlatformBrowser; + }()); + if (env().get('IS_BROWSER')) { + env().setPlatform('browser', new PlatformBrowser()); + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // We are wrapping this within an object so it can be stubbed by Jasmine. + var getNodeFetch = { + // tslint:disable-next-line:no-require-imports + importFetch: function () { return require('node-fetch'); } + }; + var systemFetch; + var PlatformNode = /** @class */ (function () { + function PlatformNode() { + // tslint:disable-next-line:no-require-imports + this.util = require('util'); + // According to the spec, the built-in encoder can do only UTF-8 encoding. + // https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder/TextEncoder + this.textEncoder = new this.util.TextEncoder(); + } + PlatformNode.prototype.fetch = function (path, requestInits) { + if (env().global.fetch != null) { + return env().global.fetch(path, requestInits); + } + if (systemFetch == null) { + systemFetch = getNodeFetch.importFetch(); + } + return systemFetch(path, requestInits); + }; + PlatformNode.prototype.now = function () { + var time = process.hrtime(); + return time[0] * 1000 + time[1] / 1000000; + }; + PlatformNode.prototype.encode = function (text, encoding) { + if (encoding !== 'utf-8' && encoding !== 'utf8') { + throw new Error("Node built-in encoder only supports utf-8, but got " + encoding); + } + return this.textEncoder.encode(text); + }; + PlatformNode.prototype.decode = function (bytes, encoding) { + if (bytes.length === 0) { + return ''; + } + return new this.util.TextDecoder(encoding).decode(bytes); + }; + return PlatformNode; + }()); + if (env().get('IS_NODE')) { + env().setPlatform('node', new PlatformNode()); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /* Type definitions for exporting and importing of models. */ + /** + * A map from Tensor dtype to number of bytes per element of the Tensor. + */ + var DTYPE_VALUE_SIZE_MAP = { + 'float32': 4, + 'float16': 2, + 'int32': 4, + 'uint16': 2, + 'uint8': 1, + 'bool': 1, + 'complex64': 8 + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** Number of bytes reserved for the length of the string. (32bit integer). */ + var NUM_BYTES_STRING_LENGTH = 4; + /** + * Encode a map from names to weight values as an ArrayBuffer, along with an + * `Array` of `WeightsManifestEntry` as specification of the encoded weights. + * + * This function does not perform sharding. + * + * This function is the reverse of `decodeWeights`. + * + * @param tensors A map ("dict") from names to tensors. + * @param group Group to which the weights belong (optional). + * @returns A `Promise` of + * - A flat `ArrayBuffer` with all the binary values of the `Tensor`s + * concatenated. + * - An `Array` of `WeightManifestEntry`s, carrying information including + * tensor names, `dtype`s and shapes. + * @throws Error: on unsupported tensor `dtype`. + */ + function encodeWeights(tensors, group) { + return __awaiter(this, void 0, void 0, function () { + var specs, dataPromises, names, _loop_1, i, tensorValues; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + specs = []; + dataPromises = []; + names = Array.isArray(tensors) ? + tensors.map(function (tensor) { return tensor.name; }) : + Object.keys(tensors); + _loop_1 = function (i) { + var name_1 = names[i]; + var t = Array.isArray(tensors) ? tensors[i].tensor : tensors[name_1]; + if (t.dtype !== 'float32' && t.dtype !== 'int32' && t.dtype !== 'bool' && + t.dtype !== 'string' && t.dtype !== 'complex64') { + throw new Error("Unsupported dtype in weight '" + name_1 + "': " + t.dtype); + } + var spec = { name: name_1, shape: t.shape, dtype: t.dtype }; + if (t.dtype === 'string') { + var utf8bytes = new Promise(function (resolve) { return __awaiter(_this, void 0, void 0, function () { + var vals, totalNumBytes, bytes, offset, i_1, val, bytesOfLength; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, t.bytes()]; + case 1: + vals = _a.sent(); + totalNumBytes = vals.reduce(function (p, c) { return p + c.length; }, 0) + + NUM_BYTES_STRING_LENGTH * vals.length; + bytes = new Uint8Array(totalNumBytes); + offset = 0; + for (i_1 = 0; i_1 < vals.length; i_1++) { + val = vals[i_1]; + bytesOfLength = new Uint8Array(new Uint32Array([val.length]).buffer); + bytes.set(bytesOfLength, offset); + offset += NUM_BYTES_STRING_LENGTH; + bytes.set(val, offset); + offset += val.length; + } + resolve(bytes); + return [2 /*return*/]; + } + }); + }); }); + dataPromises.push(utf8bytes); + } + else { + dataPromises.push(t.data()); + } + if (group != null) { + spec.group = group; + } + specs.push(spec); + }; + for (i = 0; i < names.length; ++i) { + _loop_1(i); + } + return [4 /*yield*/, Promise.all(dataPromises)]; + case 1: + tensorValues = _a.sent(); + return [2 /*return*/, { data: concatenateTypedArrays(tensorValues), specs: specs }]; + } + }); + }); + } + /** + * Decode flat ArrayBuffer as weights. + * + * This function does not handle sharding. + * + * This function is the reverse of `encodeWeights`. + * + * @param buffer A flat ArrayBuffer carrying the binary values of the tensors + * concatenated in the order specified in `specs`. + * @param specs Specifications of the names, dtypes and shapes of the tensors + * whose value are encoded by `buffer`. + * @return A map from tensor name to tensor value, with the names corresponding + * to names in `specs`. + * @throws Error, if any of the tensors has unsupported dtype. + */ + function decodeWeights(buffer, specs) { + // TODO(adarob, cais): Support quantization. + var out = {}; + var float16Decode; + var offset = 0; + for (var _i = 0, specs_1 = specs; _i < specs_1.length; _i++) { + var spec = specs_1[_i]; + var name_2 = spec.name; + var dtype = spec.dtype; + var shape = spec.shape; + var size = sizeFromShape(shape); + var values = void 0; + if ('quantization' in spec) { + var quantization = spec.quantization; + if (quantization.dtype === 'uint8' || quantization.dtype === 'uint16') { + if (!('min' in quantization && 'scale' in quantization)) { + throw new Error("Weight " + spec.name + " with quantization " + quantization.dtype + " " + + "doesn't have corresponding metadata min and scale."); + } + } + else if (quantization.dtype === 'float16') { + if (dtype !== 'float32') { + throw new Error("Weight " + spec.name + " is quantized with " + quantization.dtype + " " + + ("which only supports weights of type float32 not " + dtype + ".")); + } + } + else { + throw new Error("Weight " + spec.name + " has unknown " + + ("quantization dtype " + quantization.dtype + ". ") + + "Supported quantization dtypes are: " + + "'uint8', 'uint16', and 'float16'."); + } + var quantizationSizeFactor = DTYPE_VALUE_SIZE_MAP[quantization.dtype]; + var byteBuffer = buffer.slice(offset, offset + size * quantizationSizeFactor); + var quantizedArray = (quantization.dtype === 'uint8') ? + new Uint8Array(byteBuffer) : + new Uint16Array(byteBuffer); + if (dtype === 'float32') { + if (quantization.dtype === 'uint8' || quantization.dtype === 'uint16') { + values = new Float32Array(quantizedArray.length); + for (var i = 0; i < quantizedArray.length; i++) { + var v = quantizedArray[i]; + values[i] = v * quantization.scale + quantization.min; + } + } + else if (quantization.dtype === 'float16') { + if (float16Decode === undefined) { + float16Decode = getFloat16Decoder(); + } + values = float16Decode(quantizedArray); + } + else { + throw new Error("Unsupported quantization type " + quantization.dtype + " " + + "for weight type float32."); + } + } + else if (dtype === 'int32') { + if (quantization.dtype !== 'uint8' && quantization.dtype !== 'uint16') { + throw new Error("Unsupported quantization type " + quantization.dtype + " " + + "for weight type int32."); + } + values = new Int32Array(quantizedArray.length); + for (var i = 0; i < quantizedArray.length; i++) { + var v = quantizedArray[i]; + values[i] = Math.round(v * quantization.scale + quantization.min); + } + } + else { + throw new Error("Unsupported dtype in weight '" + name_2 + "': " + dtype); + } + offset += size * quantizationSizeFactor; + } + else if (dtype === 'string') { + var size_1 = sizeFromShape(spec.shape); + values = []; + for (var i = 0; i < size_1; i++) { + var byteLength = new Uint32Array(buffer.slice(offset, offset + NUM_BYTES_STRING_LENGTH))[0]; + offset += NUM_BYTES_STRING_LENGTH; + var bytes = new Uint8Array(buffer.slice(offset, offset + byteLength)); + values.push(bytes); + offset += byteLength; + } + } + else { + var dtypeFactor = DTYPE_VALUE_SIZE_MAP[dtype]; + var byteBuffer = buffer.slice(offset, offset + size * dtypeFactor); + if (dtype === 'float32') { + values = new Float32Array(byteBuffer); + } + else if (dtype === 'int32') { + values = new Int32Array(byteBuffer); + } + else if (dtype === 'bool') { + values = new Uint8Array(byteBuffer); + } + else if (dtype === 'complex64') { + values = new Float32Array(byteBuffer); + var real = new Float32Array(values.length / 2); + var image = new Float32Array(values.length / 2); + for (var i = 0; i < real.length; i++) { + real[i] = values[i * 2]; + image[i] = values[i * 2 + 1]; + } + var realTensor = tensor(real, shape, 'float32'); + var imageTensor = tensor(image, shape, 'float32'); + out[name_2] = complex(realTensor, imageTensor); + } + else { + throw new Error("Unsupported dtype in weight '" + name_2 + "': " + dtype); + } + offset += size * dtypeFactor; + } + if (dtype !== 'complex64') { + out[name_2] = tensor(values, shape, dtype); + } + } + return out; + } + /** + * Concatenate TypedArrays into an ArrayBuffer. + */ + function concatenateTypedArrays(xs) { + // TODO(adarob, cais): Support quantization. + if (xs === null) { + throw new Error("Invalid input value: " + JSON.stringify(xs)); + } + var totalByteLength = 0; + // `normalizedXs` is here for this reason: a `TypedArray`'s `buffer' + // can have a different byte length from that of the `TypedArray` itself, + // for example, when the `TypedArray` is created from an offset in an + // `ArrayBuffer`. `normliazedXs` holds `TypedArray`s whose `buffer`s match + // the `TypedArray` in byte length. If an element of `xs` does not show + // this property, a new `TypedArray` that satisfy this property will be + // constructed and pushed into `normalizedXs`. + var normalizedXs = []; + xs.forEach(function (x) { + totalByteLength += x.byteLength; + // tslint:disable:no-any + normalizedXs.push(x.byteLength === x.buffer.byteLength ? x : + new x.constructor(x)); + if (!(x instanceof Float32Array || x instanceof Int32Array || + x instanceof Uint8Array)) { + throw new Error("Unsupported TypedArray subtype: " + x.constructor.name); + } + // tslint:enable:no-any + }); + var y = new Uint8Array(totalByteLength); + var offset = 0; + normalizedXs.forEach(function (x) { + y.set(new Uint8Array(x.buffer), offset); + offset += x.byteLength; + }); + return y.buffer; + } + // Use Buffer on Node.js instead of Blob/atob/btoa + var useNodeBuffer = typeof Buffer !== 'undefined' && + (typeof Blob === 'undefined' || typeof atob === 'undefined' || + typeof btoa === 'undefined'); + /** + * Calculate the byte length of a JavaScript string. + * + * Note that a JavaScript string can contain wide characters, therefore the + * length of the string is not necessarily equal to the byte length. + * + * @param str Input string. + * @returns Byte length. + */ + function stringByteLength(str) { + if (useNodeBuffer) { + return Buffer.byteLength(str); + } + return new Blob([str]).size; + } + /** + * Encode an ArrayBuffer as a base64 encoded string. + * + * @param buffer `ArrayBuffer` to be converted. + * @returns A string that base64-encodes `buffer`. + */ + function arrayBufferToBase64String(buffer) { + if (useNodeBuffer) { + return Buffer.from(buffer).toString('base64'); + } + var buf = new Uint8Array(buffer); + var s = ''; + for (var i = 0, l = buf.length; i < l; i++) { + s += String.fromCharCode(buf[i]); + } + return btoa(s); + } + /** + * Decode a base64 string as an ArrayBuffer. + * + * @param str Base64 string. + * @returns Decoded `ArrayBuffer`. + */ + function base64StringToArrayBuffer(str) { + if (useNodeBuffer) { + var buf = Buffer.from(str, 'base64'); + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + } + var s = atob(str); + var buffer = new Uint8Array(s.length); + for (var i = 0; i < s.length; ++i) { + buffer.set([s.charCodeAt(i)], i); + } + return buffer.buffer; + } + /** + * Concatenate a number of ArrayBuffers into one. + * + * @param buffers A number of array buffers to concatenate. + * @returns Result of concatenating `buffers` in order. + */ + function concatenateArrayBuffers(buffers) { + if (buffers.length === 1) { + return buffers[0]; + } + var totalByteLength = 0; + buffers.forEach(function (buffer) { + totalByteLength += buffer.byteLength; + }); + var temp = new Uint8Array(totalByteLength); + var offset = 0; + buffers.forEach(function (buffer) { + temp.set(new Uint8Array(buffer), offset); + offset += buffer.byteLength; + }); + return temp.buffer; + } + /** + * Get the basename of a path. + * + * Behaves in a way analogous to Linux's basename command. + * + * @param path + */ + function basename(path) { + var SEPARATOR = '/'; + path = path.trim(); + while (path.endsWith(SEPARATOR)) { + path = path.slice(0, path.length - 1); + } + var items = path.split(SEPARATOR); + return items[items.length - 1]; + } + /** + * Populate ModelArtifactsInfo fields for a model with JSON topology. + * @param modelArtifacts + * @returns A ModelArtifactsInfo object. + */ + function getModelArtifactsInfoForJSON(modelArtifacts) { + if (modelArtifacts.modelTopology instanceof ArrayBuffer) { + throw new Error('Expected JSON model topology, received ArrayBuffer.'); + } + return { + dateSaved: new Date(), + modelTopologyType: 'JSON', + modelTopologyBytes: modelArtifacts.modelTopology == null ? + 0 : + stringByteLength(JSON.stringify(modelArtifacts.modelTopology)), + weightSpecsBytes: modelArtifacts.weightSpecs == null ? + 0 : + stringByteLength(JSON.stringify(modelArtifacts.weightSpecs)), + weightDataBytes: modelArtifacts.weightData == null ? + 0 : + modelArtifacts.weightData.byteLength, + }; + } + /** + * Computes mantisa table for casting Float16 to Float32 + * See http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf + * + * @returns Uint32Array, 2048 mantissa lookup values. + */ + function computeFloat16MantisaTable() { + var convertMantissa = function (i) { + var m = i << 13; + var e = 0; + while ((m & 0x00800000) === 0) { + e -= 0x00800000; + m <<= 1; + } + m &= ~0x00800000; + e += 0x38800000; + return m | e; + }; + var mantisaTable = new Uint32Array(2048); + mantisaTable[0] = 0; + for (var i = 1; i < 1024; i++) { + mantisaTable[i] = convertMantissa(i); + } + for (var i = 1024; i < 2048; i++) { + mantisaTable[i] = 0x38000000 + ((i - 1024) << 13); + } + return mantisaTable; + } + /** + * Computes exponent table for casting Float16 to Float32 + * See http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf + * + * @returns Uint32Array, 64 exponent lookup values. + */ + function computeFloat16ExponentTable() { + var exponentTable = new Uint32Array(64); + exponentTable[0] = 0; + exponentTable[31] = 0x47800000; + exponentTable[32] = 0x80000000; + exponentTable[63] = 0xc7800000; + for (var i = 1; i < 31; i++) { + exponentTable[i] = i << 23; + } + for (var i = 33; i < 63; i++) { + exponentTable[i] = 0x80000000 + ((i - 32) << 23); + } + return exponentTable; + } + /** + * Computes offset table for casting Float16 to Float32 + * See http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf + * + * @returns Uint32Array, 6d offset values. + */ + function computeFloat16OffsetTable() { + var offsetTable = new Uint32Array(64); + for (var i = 0; i < 64; i++) { + offsetTable[i] = 1024; + } + offsetTable[0] = offsetTable[32] = 0; + return offsetTable; + } + /** + * Retrieve a Float16 decoder which will decode a ByteArray of Float16 values + * to a Float32Array. + * + * @returns Function (buffer: Uint16Array) => Float32Array which decodes + * the Uint16Array of Float16 bytes to a Float32Array. + */ + function getFloat16Decoder() { + // Algorithm is based off of + // http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf + // Cache lookup tables + var mantisaTable = computeFloat16MantisaTable(); + var exponentTable = computeFloat16ExponentTable(); + var offsetTable = computeFloat16OffsetTable(); + return function (quantizedArray) { + var buffer = new ArrayBuffer(4 * quantizedArray.length); + var bufferUint32View = new Uint32Array(buffer); + for (var index = 0; index < quantizedArray.length; index++) { + var float16Bits = quantizedArray[index]; + var float32Bits = mantisaTable[offsetTable[float16Bits >> 10] + (float16Bits & 0x3ff)] + + exponentTable[float16Bits >> 10]; + bufferUint32View[index] = float32Bits; + } + return new Float32Array(buffer); + }; + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var IORouterRegistry = /** @class */ (function () { + function IORouterRegistry() { + this.saveRouters = []; + this.loadRouters = []; + } + IORouterRegistry.getInstance = function () { + if (IORouterRegistry.instance == null) { + IORouterRegistry.instance = new IORouterRegistry(); + } + return IORouterRegistry.instance; + }; + /** + * Register a save-handler router. + * + * @param saveRouter A function that maps a URL-like string onto an instance + * of `IOHandler` with the `save` method defined or `null`. + */ + IORouterRegistry.registerSaveRouter = function (saveRouter) { + IORouterRegistry.getInstance().saveRouters.push(saveRouter); + }; + /** + * Register a load-handler router. + * + * @param loadRouter A function that maps a URL-like string onto an instance + * of `IOHandler` with the `load` method defined or `null`. + */ + IORouterRegistry.registerLoadRouter = function (loadRouter) { + IORouterRegistry.getInstance().loadRouters.push(loadRouter); + }; + /** + * Look up IOHandler for saving, given a URL-like string. + * + * @param url + * @returns If only one match is found, an instance of IOHandler with the + * `save` method defined. If no match is found, `null`. + * @throws Error, if more than one match is found. + */ + IORouterRegistry.getSaveHandlers = function (url) { + return IORouterRegistry.getHandlers(url, 'save'); + }; + /** + * Look up IOHandler for loading, given a URL-like string. + * + * @param url + * @param loadOptions Optional, custom load options. + * @returns All valid handlers for `url`, given the currently registered + * handler routers. + */ + IORouterRegistry.getLoadHandlers = function (url, loadOptions) { + return IORouterRegistry.getHandlers(url, 'load', loadOptions); + }; + IORouterRegistry.getHandlers = function (url, handlerType, loadOptions) { + var validHandlers = []; + var routers = handlerType === 'load' ? + IORouterRegistry.getInstance().loadRouters : + IORouterRegistry.getInstance().saveRouters; + routers.forEach(function (router) { + var handler = router(url, loadOptions); + if (handler !== null) { + validHandlers.push(handler); + } + }); + return validHandlers; + }; + return IORouterRegistry; + }()); + var registerSaveRouter = function (loudRouter) { + return IORouterRegistry.registerSaveRouter(loudRouter); + }; + var registerLoadRouter = function (loudRouter) { + return IORouterRegistry.registerLoadRouter(loudRouter); + }; + var getSaveHandlers = function (url) { + return IORouterRegistry.getSaveHandlers(url); + }; + var getLoadHandlers = function (url, loadOptions) { + return IORouterRegistry.getLoadHandlers(url, loadOptions); + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var URL_SCHEME_SUFFIX = '://'; + var ModelStoreManagerRegistry = /** @class */ (function () { + function ModelStoreManagerRegistry() { + this.managers = {}; + } + ModelStoreManagerRegistry.getInstance = function () { + if (ModelStoreManagerRegistry.instance == null) { + ModelStoreManagerRegistry.instance = new ModelStoreManagerRegistry(); + } + return ModelStoreManagerRegistry.instance; + }; + /** + * Register a save-handler router. + * + * @param saveRouter A function that maps a URL-like string onto an instance + * of `IOHandler` with the `save` method defined or `null`. + */ + ModelStoreManagerRegistry.registerManager = function (scheme, manager) { + assert(scheme != null, function () { return 'scheme must not be undefined or null.'; }); + if (scheme.endsWith(URL_SCHEME_SUFFIX)) { + scheme = scheme.slice(0, scheme.indexOf(URL_SCHEME_SUFFIX)); + } + assert(scheme.length > 0, function () { return 'scheme must not be an empty string.'; }); + var registry = ModelStoreManagerRegistry.getInstance(); + assert(registry.managers[scheme] == null, function () { return "A model store manager is already registered for scheme '" + scheme + "'."; }); + registry.managers[scheme] = manager; + }; + ModelStoreManagerRegistry.getManager = function (scheme) { + var manager = this.getInstance().managers[scheme]; + if (manager == null) { + throw new Error("Cannot find model manager for scheme '" + scheme + "'"); + } + return manager; + }; + ModelStoreManagerRegistry.getSchemes = function () { + return Object.keys(this.getInstance().managers); + }; + return ModelStoreManagerRegistry; + }()); + /** + * Helper method for parsing a URL string into a scheme and a path. + * + * @param url E.g., 'localstorage://my-model' + * @returns A dictionary with two fields: scheme and path. + * Scheme: e.g., 'localstorage' in the example above. + * Path: e.g., 'my-model' in the example above. + */ + function parseURL(url) { + if (url.indexOf(URL_SCHEME_SUFFIX) === -1) { + throw new Error("The url string provided does not contain a scheme. " + + "Supported schemes are: " + + ("" + ModelStoreManagerRegistry.getSchemes().join(','))); + } + return { + scheme: url.split(URL_SCHEME_SUFFIX)[0], + path: url.split(URL_SCHEME_SUFFIX)[1], + }; + } + function cloneModelInternal(sourceURL, destURL, deleteSource) { + if (deleteSource === void 0) { deleteSource = false; } + return __awaiter(this, void 0, void 0, function () { + var loadHandlers, loadHandler, saveHandlers, saveHandler, sourceScheme, sourcePath, sameMedium, modelArtifacts, saveResult; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + assert(sourceURL !== destURL, function () { return "Old path and new path are the same: '" + sourceURL + "'"; }); + loadHandlers = IORouterRegistry.getLoadHandlers(sourceURL); + assert(loadHandlers.length > 0, function () { return "Copying failed because no load handler is found for source URL " + sourceURL + "."; }); + assert(loadHandlers.length < 2, function () { return "Copying failed because more than one (" + loadHandlers.length + ") " + + ("load handlers for source URL " + sourceURL + "."); }); + loadHandler = loadHandlers[0]; + saveHandlers = IORouterRegistry.getSaveHandlers(destURL); + assert(saveHandlers.length > 0, function () { return "Copying failed because no save handler is found for destination " + + ("URL " + destURL + "."); }); + assert(saveHandlers.length < 2, function () { return "Copying failed because more than one (" + loadHandlers.length + ") " + + ("save handlers for destination URL " + destURL + "."); }); + saveHandler = saveHandlers[0]; + sourceScheme = parseURL(sourceURL).scheme; + sourcePath = parseURL(sourceURL).path; + sameMedium = sourceScheme === parseURL(sourceURL).scheme; + return [4 /*yield*/, loadHandler.load()]; + case 1: + modelArtifacts = _a.sent(); + if (!(deleteSource && sameMedium)) return [3 /*break*/, 3]; + return [4 /*yield*/, ModelStoreManagerRegistry.getManager(sourceScheme) + .removeModel(sourcePath)]; + case 2: + _a.sent(); + _a.label = 3; + case 3: return [4 /*yield*/, saveHandler.save(modelArtifacts)]; + case 4: + saveResult = _a.sent(); + if (!(deleteSource && !sameMedium)) return [3 /*break*/, 6]; + return [4 /*yield*/, ModelStoreManagerRegistry.getManager(sourceScheme) + .removeModel(sourcePath)]; + case 5: + _a.sent(); + _a.label = 6; + case 6: return [2 /*return*/, saveResult.modelArtifactsInfo]; + } + }); + }); + } + /** + * List all models stored in registered storage mediums. + * + * For a web browser environment, the registered mediums are Local Storage and + * IndexedDB. + * + * ```js + * // First create and save a model. + * const model = tf.sequential(); + * model.add(tf.layers.dense( + * {units: 1, inputShape: [10], activation: 'sigmoid'})); + * await model.save('localstorage://demo/management/model1'); + * + * // Then list existing models. + * console.log(JSON.stringify(await tf.io.listModels())); + * + * // Delete the model. + * await tf.io.removeModel('localstorage://demo/management/model1'); + * + * // List models again. + * console.log(JSON.stringify(await tf.io.listModels())); + * ``` + * + * @returns A `Promise` of a dictionary mapping URLs of existing models to + * their model artifacts info. URLs include medium-specific schemes, e.g., + * 'indexeddb://my/model/1'. Model artifacts info include type of the + * model's topology, byte sizes of the topology, weights, etc. + */ + /** + * @doc { + * heading: 'Models', + * subheading: 'Management', + * namespace: 'io', + * ignoreCI: true + * } + */ + function listModels() { + return __awaiter(this, void 0, void 0, function () { + var schemes, out, _i, schemes_1, scheme, schemeOut, path, url; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + schemes = ModelStoreManagerRegistry.getSchemes(); + out = {}; + _i = 0, schemes_1 = schemes; + _a.label = 1; + case 1: + if (!(_i < schemes_1.length)) return [3 /*break*/, 4]; + scheme = schemes_1[_i]; + return [4 /*yield*/, ModelStoreManagerRegistry.getManager(scheme).listModels()]; + case 2: + schemeOut = _a.sent(); + for (path in schemeOut) { + url = scheme + URL_SCHEME_SUFFIX + path; + out[url] = schemeOut[path]; + } + _a.label = 3; + case 3: + _i++; + return [3 /*break*/, 1]; + case 4: return [2 /*return*/, out]; + } + }); + }); + } + /** + * Remove a model specified by URL from a reigstered storage medium. + * + * ```js + * // First create and save a model. + * const model = tf.sequential(); + * model.add(tf.layers.dense( + * {units: 1, inputShape: [10], activation: 'sigmoid'})); + * await model.save('localstorage://demo/management/model1'); + * + * // Then list existing models. + * console.log(JSON.stringify(await tf.io.listModels())); + * + * // Delete the model. + * await tf.io.removeModel('localstorage://demo/management/model1'); + * + * // List models again. + * console.log(JSON.stringify(await tf.io.listModels())); + * ``` + * + * @param url A URL to a stored model, with a scheme prefix, e.g., + * 'localstorage://my-model-1', 'indexeddb://my/model/2'. + * @returns ModelArtifactsInfo of the deleted model (if and only if deletion + * is successful). + * @throws Error if deletion fails, e.g., if no model exists at `path`. + */ + /** + * @doc { + * heading: 'Models', + * subheading: 'Management', + * namespace: 'io', + * ignoreCI: true + * } + */ + function removeModel(url) { + return __awaiter(this, void 0, void 0, function () { + var schemeAndPath, manager; + return __generator(this, function (_a) { + schemeAndPath = parseURL(url); + manager = ModelStoreManagerRegistry.getManager(schemeAndPath.scheme); + return [2 /*return*/, manager.removeModel(schemeAndPath.path)]; + }); + }); + } + /** + * Copy a model from one URL to another. + * + * This function supports: + * + * 1. Copying within a storage medium, e.g., + * `tf.io.copyModel('localstorage://model-1', 'localstorage://model-2')` + * 2. Copying between two storage mediums, e.g., + * `tf.io.copyModel('localstorage://model-1', 'indexeddb://model-1')` + * + * ```js + * // First create and save a model. + * const model = tf.sequential(); + * model.add(tf.layers.dense( + * {units: 1, inputShape: [10], activation: 'sigmoid'})); + * await model.save('localstorage://demo/management/model1'); + * + * // Then list existing models. + * console.log(JSON.stringify(await tf.io.listModels())); + * + * // Copy the model, from Local Storage to IndexedDB. + * await tf.io.copyModel( + * 'localstorage://demo/management/model1', + * 'indexeddb://demo/management/model1'); + * + * // List models again. + * console.log(JSON.stringify(await tf.io.listModels())); + * + * // Remove both models. + * await tf.io.removeModel('localstorage://demo/management/model1'); + * await tf.io.removeModel('indexeddb://demo/management/model1'); + * ``` + * + * @param sourceURL Source URL of copying. + * @param destURL Destination URL of copying. + * @returns ModelArtifactsInfo of the copied model (if and only if copying + * is successful). + * @throws Error if copying fails, e.g., if no model exists at `sourceURL`, or + * if `oldPath` and `newPath` are identical. + */ + /** + * @doc { + * heading: 'Models', + * subheading: 'Management', + * namespace: 'io', + * ignoreCI: true + * } + */ + function copyModel(sourceURL, destURL) { + return __awaiter(this, void 0, void 0, function () { + var deleteSource; + return __generator(this, function (_a) { + deleteSource = false; + return [2 /*return*/, cloneModelInternal(sourceURL, destURL, deleteSource)]; + }); + }); + } + /** + * Move a model from one URL to another. + * + * This function supports: + * + * 1. Moving within a storage medium, e.g., + * `tf.io.moveModel('localstorage://model-1', 'localstorage://model-2')` + * 2. Moving between two storage mediums, e.g., + * `tf.io.moveModel('localstorage://model-1', 'indexeddb://model-1')` + * + * ```js + * // First create and save a model. + * const model = tf.sequential(); + * model.add(tf.layers.dense( + * {units: 1, inputShape: [10], activation: 'sigmoid'})); + * await model.save('localstorage://demo/management/model1'); + * + * // Then list existing models. + * console.log(JSON.stringify(await tf.io.listModels())); + * + * // Move the model, from Local Storage to IndexedDB. + * await tf.io.moveModel( + * 'localstorage://demo/management/model1', + * 'indexeddb://demo/management/model1'); + * + * // List models again. + * console.log(JSON.stringify(await tf.io.listModels())); + * + * // Remove the moved model. + * await tf.io.removeModel('indexeddb://demo/management/model1'); + * ``` + * + * @param sourceURL Source URL of moving. + * @param destURL Destination URL of moving. + * @returns ModelArtifactsInfo of the copied model (if and only if copying + * is successful). + * @throws Error if moving fails, e.g., if no model exists at `sourceURL`, or + * if `oldPath` and `newPath` are identical. + */ + /** + * @doc { + * heading: 'Models', + * subheading: 'Management', + * namespace: 'io', + * ignoreCI: true + * } + */ + function moveModel(sourceURL, destURL) { + return __awaiter(this, void 0, void 0, function () { + var deleteSource; + return __generator(this, function (_a) { + deleteSource = true; + return [2 /*return*/, cloneModelInternal(sourceURL, destURL, deleteSource)]; + }); + }); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var DATABASE_NAME = 'tensorflowjs'; + var DATABASE_VERSION = 1; + // Model data and ModelArtifactsInfo (metadata) are stored in two separate + // stores for efficient access of the list of stored models and their metadata. + // 1. The object store for model data: topology, weights and weight manifests. + var MODEL_STORE_NAME = 'models_store'; + // 2. The object store for ModelArtifactsInfo, including meta-information such + // as the type of topology (JSON vs binary), byte size of the topology, byte + // size of the weights, etc. + var INFO_STORE_NAME = 'model_info_store'; + function getIndexedDBFactory() { + if (!env().getBool('IS_BROWSER')) { + // TODO(cais): Add more info about what IOHandler subtypes are available. + // Maybe point to a doc page on the web and/or automatically determine + // the available IOHandlers and print them in the error message. + throw new Error('Failed to obtain IndexedDB factory because the current environment' + + 'is not a web browser.'); + } + // tslint:disable-next-line:no-any + var theWindow = typeof window === 'undefined' ? self : window; + var factory = theWindow.indexedDB || theWindow.mozIndexedDB || + theWindow.webkitIndexedDB || theWindow.msIndexedDB || + theWindow.shimIndexedDB; + if (factory == null) { + throw new Error('The current browser does not appear to support IndexedDB.'); + } + return factory; + } + function setUpDatabase(openRequest) { + var db = openRequest.result; + db.createObjectStore(MODEL_STORE_NAME, { keyPath: 'modelPath' }); + db.createObjectStore(INFO_STORE_NAME, { keyPath: 'modelPath' }); + } + /** + * IOHandler subclass: Browser IndexedDB. + * + * See the doc string of `browserIndexedDB` for more details. + */ + var BrowserIndexedDB = /** @class */ (function () { + function BrowserIndexedDB(modelPath) { + this.indexedDB = getIndexedDBFactory(); + if (modelPath == null || !modelPath) { + throw new Error('For IndexedDB, modelPath must not be null, undefined or empty.'); + } + this.modelPath = modelPath; + } + BrowserIndexedDB.prototype.save = function (modelArtifacts) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + // TODO(cais): Support saving GraphDef models. + if (modelArtifacts.modelTopology instanceof ArrayBuffer) { + throw new Error('BrowserLocalStorage.save() does not support saving model topology ' + + 'in binary formats yet.'); + } + return [2 /*return*/, this.databaseAction(this.modelPath, modelArtifacts)]; + }); + }); + }; + BrowserIndexedDB.prototype.load = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, this.databaseAction(this.modelPath)]; + }); + }); + }; + /** + * Perform database action to put model artifacts into or read model artifacts + * from IndexedDB object store. + * + * Whether the action is put or get depends on whether `modelArtifacts` is + * specified. If it is specified, the action will be put; otherwise the action + * will be get. + * + * @param modelPath A unique string path for the model. + * @param modelArtifacts If specified, it will be the model artifacts to be + * stored in IndexedDB. + * @returns A `Promise` of `SaveResult`, if the action is put, or a `Promise` + * of `ModelArtifacts`, if the action is get. + */ + BrowserIndexedDB.prototype.databaseAction = function (modelPath, modelArtifacts) { + var _this = this; + return new Promise(function (resolve, reject) { + var openRequest = _this.indexedDB.open(DATABASE_NAME, DATABASE_VERSION); + openRequest.onupgradeneeded = function () { return setUpDatabase(openRequest); }; + openRequest.onsuccess = function () { + var db = openRequest.result; + if (modelArtifacts == null) { + // Read model out from object store. + var modelTx = db.transaction(MODEL_STORE_NAME, 'readonly'); + var modelStore = modelTx.objectStore(MODEL_STORE_NAME); + var getRequest_1 = modelStore.get(_this.modelPath); + getRequest_1.onsuccess = function () { + if (getRequest_1.result == null) { + db.close(); + return reject(new Error("Cannot find model with path '" + _this.modelPath + "' " + + "in IndexedDB.")); + } + else { + resolve(getRequest_1.result.modelArtifacts); + } + }; + getRequest_1.onerror = function (error) { + db.close(); + return reject(getRequest_1.error); + }; + modelTx.oncomplete = function () { return db.close(); }; + } + else { + // Put model into object store. + var modelArtifactsInfo_1 = getModelArtifactsInfoForJSON(modelArtifacts); + // First, put ModelArtifactsInfo into info store. + var infoTx_1 = db.transaction(INFO_STORE_NAME, 'readwrite'); + var infoStore_1 = infoTx_1.objectStore(INFO_STORE_NAME); + var putInfoRequest_1 = infoStore_1.put({ modelPath: _this.modelPath, modelArtifactsInfo: modelArtifactsInfo_1 }); + var modelTx_1; + putInfoRequest_1.onsuccess = function () { + // Second, put model data into model store. + modelTx_1 = db.transaction(MODEL_STORE_NAME, 'readwrite'); + var modelStore = modelTx_1.objectStore(MODEL_STORE_NAME); + var putModelRequest = modelStore.put({ + modelPath: _this.modelPath, + modelArtifacts: modelArtifacts, + modelArtifactsInfo: modelArtifactsInfo_1 + }); + putModelRequest.onsuccess = function () { return resolve({ modelArtifactsInfo: modelArtifactsInfo_1 }); }; + putModelRequest.onerror = function (error) { + // If the put-model request fails, roll back the info entry as + // well. + infoStore_1 = infoTx_1.objectStore(INFO_STORE_NAME); + var deleteInfoRequest = infoStore_1.delete(_this.modelPath); + deleteInfoRequest.onsuccess = function () { + db.close(); + return reject(putModelRequest.error); + }; + deleteInfoRequest.onerror = function (error) { + db.close(); + return reject(putModelRequest.error); + }; + }; + }; + putInfoRequest_1.onerror = function (error) { + db.close(); + return reject(putInfoRequest_1.error); + }; + infoTx_1.oncomplete = function () { + if (modelTx_1 == null) { + db.close(); + } + else { + modelTx_1.oncomplete = function () { return db.close(); }; + } + }; + } + }; + openRequest.onerror = function (error) { return reject(openRequest.error); }; + }); + }; + BrowserIndexedDB.URL_SCHEME = 'indexeddb://'; + return BrowserIndexedDB; + }()); + var indexedDBRouter = function (url) { + if (!env().getBool('IS_BROWSER')) { + return null; + } + else { + if (!Array.isArray(url) && url.startsWith(BrowserIndexedDB.URL_SCHEME)) { + return browserIndexedDB(url.slice(BrowserIndexedDB.URL_SCHEME.length)); + } + else { + return null; + } + } + }; + IORouterRegistry.registerSaveRouter(indexedDBRouter); + IORouterRegistry.registerLoadRouter(indexedDBRouter); + /** + * Creates a browser IndexedDB IOHandler for saving and loading models. + * + * ```js + * const model = tf.sequential(); + * model.add( + * tf.layers.dense({units: 1, inputShape: [100], activation: 'sigmoid'})); + * + * const saveResult = await model.save('indexeddb://MyModel')); + * console.log(saveResult); + * ``` + * + * @param modelPath A unique identifier for the model to be saved. Must be a + * non-empty string. + * @returns An instance of `BrowserIndexedDB` (sublcass of `IOHandler`), + * which can be used with, e.g., `tf.Model.save`. + */ + function browserIndexedDB(modelPath) { + return new BrowserIndexedDB(modelPath); + } + function maybeStripScheme(key) { + return key.startsWith(BrowserIndexedDB.URL_SCHEME) ? + key.slice(BrowserIndexedDB.URL_SCHEME.length) : + key; + } + var BrowserIndexedDBManager = /** @class */ (function () { + function BrowserIndexedDBManager() { + this.indexedDB = getIndexedDBFactory(); + } + BrowserIndexedDBManager.prototype.listModels = function () { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + return [2 /*return*/, new Promise(function (resolve, reject) { + var openRequest = _this.indexedDB.open(DATABASE_NAME, DATABASE_VERSION); + openRequest.onupgradeneeded = function () { return setUpDatabase(openRequest); }; + openRequest.onsuccess = function () { + var db = openRequest.result; + var tx = db.transaction(INFO_STORE_NAME, 'readonly'); + var store = tx.objectStore(INFO_STORE_NAME); + // tslint:disable:max-line-length + // Need to cast `store` as `any` here because TypeScript's DOM + // library does not have the `getAll()` method even though the + // method is supported in the latest version of most mainstream + // browsers: + // https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/getAll + // tslint:enable:max-line-length + // tslint:disable-next-line:no-any + var getAllInfoRequest = store.getAll(); + getAllInfoRequest.onsuccess = function () { + var out = {}; + for (var _i = 0, _a = getAllInfoRequest.result; _i < _a.length; _i++) { + var item = _a[_i]; + out[item.modelPath] = item.modelArtifactsInfo; + } + resolve(out); + }; + getAllInfoRequest.onerror = function (error) { + db.close(); + return reject(getAllInfoRequest.error); + }; + tx.oncomplete = function () { return db.close(); }; + }; + openRequest.onerror = function (error) { return reject(openRequest.error); }; + })]; + }); + }); + }; + BrowserIndexedDBManager.prototype.removeModel = function (path) { + return __awaiter(this, void 0, void 0, function () { + var _this = this; + return __generator(this, function (_a) { + path = maybeStripScheme(path); + return [2 /*return*/, new Promise(function (resolve, reject) { + var openRequest = _this.indexedDB.open(DATABASE_NAME, DATABASE_VERSION); + openRequest.onupgradeneeded = function () { return setUpDatabase(openRequest); }; + openRequest.onsuccess = function () { + var db = openRequest.result; + var infoTx = db.transaction(INFO_STORE_NAME, 'readwrite'); + var infoStore = infoTx.objectStore(INFO_STORE_NAME); + var getInfoRequest = infoStore.get(path); + var modelTx; + getInfoRequest.onsuccess = function () { + if (getInfoRequest.result == null) { + db.close(); + return reject(new Error("Cannot find model with path '" + path + "' " + + "in IndexedDB.")); + } + else { + // First, delete the entry in the info store. + var deleteInfoRequest = infoStore.delete(path); + var deleteModelData_1 = function () { + // Second, delete the entry in the model store. + modelTx = db.transaction(MODEL_STORE_NAME, 'readwrite'); + var modelStore = modelTx.objectStore(MODEL_STORE_NAME); + var deleteModelRequest = modelStore.delete(path); + deleteModelRequest.onsuccess = function () { + return resolve(getInfoRequest.result.modelArtifactsInfo); + }; + deleteModelRequest.onerror = function (error) { + return reject(getInfoRequest.error); + }; + }; + // Proceed with deleting model data regardless of whether deletion + // of info data succeeds or not. + deleteInfoRequest.onsuccess = deleteModelData_1; + deleteInfoRequest.onerror = function (error) { + deleteModelData_1(); + db.close(); + return reject(getInfoRequest.error); + }; + } + }; + getInfoRequest.onerror = function (error) { + db.close(); + return reject(getInfoRequest.error); + }; + infoTx.oncomplete = function () { + if (modelTx == null) { + db.close(); + } + else { + modelTx.oncomplete = function () { return db.close(); }; + } + }; + }; + openRequest.onerror = function (error) { return reject(openRequest.error); }; + })]; + }); + }); + }; + return BrowserIndexedDBManager; + }()); + if (env().getBool('IS_BROWSER')) { + // Wrap the construction and registration, to guard against browsers that + // don't support Local Storage. + try { + ModelStoreManagerRegistry.registerManager(BrowserIndexedDB.URL_SCHEME, new BrowserIndexedDBManager()); + } + catch (err) { + } + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var PATH_SEPARATOR = '/'; + var PATH_PREFIX = 'tensorflowjs_models'; + var INFO_SUFFIX = 'info'; + var MODEL_TOPOLOGY_SUFFIX = 'model_topology'; + var WEIGHT_SPECS_SUFFIX = 'weight_specs'; + var WEIGHT_DATA_SUFFIX = 'weight_data'; + var MODEL_METADATA_SUFFIX = 'model_metadata'; + function getModelKeys(path) { + return { + info: [PATH_PREFIX, path, INFO_SUFFIX].join(PATH_SEPARATOR), + topology: [PATH_PREFIX, path, MODEL_TOPOLOGY_SUFFIX].join(PATH_SEPARATOR), + weightSpecs: [PATH_PREFIX, path, WEIGHT_SPECS_SUFFIX].join(PATH_SEPARATOR), + weightData: [PATH_PREFIX, path, WEIGHT_DATA_SUFFIX].join(PATH_SEPARATOR), + modelMetadata: [PATH_PREFIX, path, MODEL_METADATA_SUFFIX].join(PATH_SEPARATOR) + }; + } + /** + * Get model path from a local-storage key. + * + * E.g., 'tensorflowjs_models/my/model/1/info' --> 'my/model/1' + * + * @param key + */ + function getModelPathFromKey(key) { + var items = key.split(PATH_SEPARATOR); + if (items.length < 3) { + throw new Error("Invalid key format: " + key); + } + return items.slice(1, items.length - 1).join(PATH_SEPARATOR); + } + function maybeStripScheme$1(key) { + return key.startsWith(BrowserLocalStorage.URL_SCHEME) ? + key.slice(BrowserLocalStorage.URL_SCHEME.length) : + key; + } + /** + * IOHandler subclass: Browser Local Storage. + * + * See the doc string to `browserLocalStorage` for more details. + */ + var BrowserLocalStorage = /** @class */ (function () { + function BrowserLocalStorage(modelPath) { + if (!env().getBool('IS_BROWSER') || + typeof window === 'undefined' || + typeof window.localStorage === 'undefined') { + // TODO(cais): Add more info about what IOHandler subtypes are + // available. + // Maybe point to a doc page on the web and/or automatically determine + // the available IOHandlers and print them in the error message. + throw new Error('The current environment does not support local storage.'); + } + this.LS = window.localStorage; + if (modelPath == null || !modelPath) { + throw new Error('For local storage, modelPath must not be null, undefined or empty.'); + } + this.modelPath = modelPath; + this.keys = getModelKeys(this.modelPath); + } + /** + * Save model artifacts to browser local storage. + * + * See the documentation to `browserLocalStorage` for details on the saved + * artifacts. + * + * @param modelArtifacts The model artifacts to be stored. + * @returns An instance of SaveResult. + */ + BrowserLocalStorage.prototype.save = function (modelArtifacts) { + return __awaiter(this, void 0, void 0, function () { + var topology, weightSpecs, modelArtifactsInfo; + return __generator(this, function (_a) { + if (modelArtifacts.modelTopology instanceof ArrayBuffer) { + throw new Error('BrowserLocalStorage.save() does not support saving model topology ' + + 'in binary formats yet.'); + } + else { + topology = JSON.stringify(modelArtifacts.modelTopology); + weightSpecs = JSON.stringify(modelArtifacts.weightSpecs); + modelArtifactsInfo = getModelArtifactsInfoForJSON(modelArtifacts); + try { + this.LS.setItem(this.keys.info, JSON.stringify(modelArtifactsInfo)); + this.LS.setItem(this.keys.topology, topology); + this.LS.setItem(this.keys.weightSpecs, weightSpecs); + this.LS.setItem(this.keys.weightData, arrayBufferToBase64String(modelArtifacts.weightData)); + this.LS.setItem(this.keys.modelMetadata, JSON.stringify({ + format: modelArtifacts.format, + generatedBy: modelArtifacts.generatedBy, + convertedBy: modelArtifacts.convertedBy, + userDefinedMetadata: modelArtifacts.userDefinedMetadata + })); + return [2 /*return*/, { modelArtifactsInfo: modelArtifactsInfo }]; + } + catch (err) { + // If saving failed, clean up all items saved so far. + this.LS.removeItem(this.keys.info); + this.LS.removeItem(this.keys.topology); + this.LS.removeItem(this.keys.weightSpecs); + this.LS.removeItem(this.keys.weightData); + this.LS.removeItem(this.keys.modelMetadata); + throw new Error("Failed to save model '" + this.modelPath + "' to local storage: " + + "size quota being exceeded is a possible cause of this failure: " + + ("modelTopologyBytes=" + modelArtifactsInfo.modelTopologyBytes + ", ") + + ("weightSpecsBytes=" + modelArtifactsInfo.weightSpecsBytes + ", ") + + ("weightDataBytes=" + modelArtifactsInfo.weightDataBytes + ".")); + } + } + return [2 /*return*/]; + }); + }); + }; + /** + * Load a model from local storage. + * + * See the documentation to `browserLocalStorage` for details on the saved + * artifacts. + * + * @returns The loaded model (if loading succeeds). + */ + BrowserLocalStorage.prototype.load = function () { + return __awaiter(this, void 0, void 0, function () { + var info, out, topology, weightSpecs, metadataString, metadata, weightDataBase64; + return __generator(this, function (_a) { + info = JSON.parse(this.LS.getItem(this.keys.info)); + if (info == null) { + throw new Error("In local storage, there is no model with name '" + this.modelPath + "'"); + } + if (info.modelTopologyType !== 'JSON') { + throw new Error('BrowserLocalStorage does not support loading non-JSON model ' + + 'topology yet.'); + } + out = {}; + topology = JSON.parse(this.LS.getItem(this.keys.topology)); + if (topology == null) { + throw new Error("In local storage, the topology of model '" + this.modelPath + "' " + + "is missing."); + } + out.modelTopology = topology; + weightSpecs = JSON.parse(this.LS.getItem(this.keys.weightSpecs)); + if (weightSpecs == null) { + throw new Error("In local storage, the weight specs of model '" + this.modelPath + "' " + + "are missing."); + } + out.weightSpecs = weightSpecs; + metadataString = this.LS.getItem(this.keys.modelMetadata); + if (metadataString != null) { + metadata = JSON.parse(metadataString); + out.format = metadata['format']; + out.generatedBy = metadata['generatedBy']; + out.convertedBy = metadata['convertedBy']; + out.userDefinedMetadata = metadata['userDefinedMetadata']; + } + weightDataBase64 = this.LS.getItem(this.keys.weightData); + if (weightDataBase64 == null) { + throw new Error("In local storage, the binary weight values of model " + + ("'" + this.modelPath + "' are missing.")); + } + out.weightData = base64StringToArrayBuffer(weightDataBase64); + return [2 /*return*/, out]; + }); + }); + }; + BrowserLocalStorage.URL_SCHEME = 'localstorage://'; + return BrowserLocalStorage; + }()); + var localStorageRouter = function (url) { + if (!env().getBool('IS_BROWSER')) { + return null; + } + else { + if (!Array.isArray(url) && url.startsWith(BrowserLocalStorage.URL_SCHEME)) { + return browserLocalStorage(url.slice(BrowserLocalStorage.URL_SCHEME.length)); + } + else { + return null; + } + } + }; + IORouterRegistry.registerSaveRouter(localStorageRouter); + IORouterRegistry.registerLoadRouter(localStorageRouter); + /** + * Factory function for local storage IOHandler. + * + * This `IOHandler` supports both `save` and `load`. + * + * For each model's saved artifacts, four items are saved to local storage. + * - `${PATH_SEPARATOR}/${modelPath}/info`: Contains meta-info about the + * model, such as date saved, type of the topology, size in bytes, etc. + * - `${PATH_SEPARATOR}/${modelPath}/topology`: Model topology. For Keras- + * style models, this is a stringized JSON. + * - `${PATH_SEPARATOR}/${modelPath}/weight_specs`: Weight specs of the + * model, can be used to decode the saved binary weight values (see + * item below). + * - `${PATH_SEPARATOR}/${modelPath}/weight_data`: Concatenated binary + * weight values, stored as a base64-encoded string. + * + * Saving may throw an `Error` if the total size of the artifacts exceed the + * browser-specific quota. + * + * @param modelPath A unique identifier for the model to be saved. Must be a + * non-empty string. + * @returns An instance of `IOHandler`, which can be used with, e.g., + * `tf.Model.save`. + */ + function browserLocalStorage(modelPath) { + return new BrowserLocalStorage(modelPath); + } + var BrowserLocalStorageManager = /** @class */ (function () { + function BrowserLocalStorageManager() { + assert(env().getBool('IS_BROWSER'), function () { return 'Current environment is not a web browser'; }); + assert(typeof window === 'undefined' || + typeof window.localStorage !== 'undefined', function () { return 'Current browser does not appear to support localStorage'; }); + this.LS = window.localStorage; + } + BrowserLocalStorageManager.prototype.listModels = function () { + return __awaiter(this, void 0, void 0, function () { + var out, prefix, suffix, i, key, modelPath; + return __generator(this, function (_a) { + out = {}; + prefix = PATH_PREFIX + PATH_SEPARATOR; + suffix = PATH_SEPARATOR + INFO_SUFFIX; + for (i = 0; i < this.LS.length; ++i) { + key = this.LS.key(i); + if (key.startsWith(prefix) && key.endsWith(suffix)) { + modelPath = getModelPathFromKey(key); + out[modelPath] = JSON.parse(this.LS.getItem(key)); + } + } + return [2 /*return*/, out]; + }); + }); + }; + BrowserLocalStorageManager.prototype.removeModel = function (path) { + return __awaiter(this, void 0, void 0, function () { + var keys, info; + return __generator(this, function (_a) { + path = maybeStripScheme$1(path); + keys = getModelKeys(path); + if (this.LS.getItem(keys.info) == null) { + throw new Error("Cannot find model at path '" + path + "'"); + } + info = JSON.parse(this.LS.getItem(keys.info)); + this.LS.removeItem(keys.info); + this.LS.removeItem(keys.topology); + this.LS.removeItem(keys.weightSpecs); + this.LS.removeItem(keys.weightData); + return [2 /*return*/, info]; + }); + }); + }; + return BrowserLocalStorageManager; + }()); + if (env().getBool('IS_BROWSER')) { + // Wrap the construction and registration, to guard against browsers that + // don't support Local Storage. + try { + ModelStoreManagerRegistry.registerManager(BrowserLocalStorage.URL_SCHEME, new BrowserLocalStorageManager()); + } + catch (err) { + } + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var DEFAULT_FILE_NAME_PREFIX = 'model'; + var DEFAULT_JSON_EXTENSION_NAME = '.json'; + var DEFAULT_WEIGHT_DATA_EXTENSION_NAME = '.weights.bin'; + function defer(f) { + return new Promise(function (resolve) { return setTimeout(resolve); }).then(f); + } + var BrowserDownloads = /** @class */ (function () { + function BrowserDownloads(fileNamePrefix) { + if (!env().getBool('IS_BROWSER')) { + // TODO(cais): Provide info on what IOHandlers are available under the + // current environment. + throw new Error('browserDownloads() cannot proceed because the current environment ' + + 'is not a browser.'); + } + if (fileNamePrefix.startsWith(BrowserDownloads.URL_SCHEME)) { + fileNamePrefix = fileNamePrefix.slice(BrowserDownloads.URL_SCHEME.length); + } + if (fileNamePrefix == null || fileNamePrefix.length === 0) { + fileNamePrefix = DEFAULT_FILE_NAME_PREFIX; + } + this.modelTopologyFileName = fileNamePrefix + DEFAULT_JSON_EXTENSION_NAME; + this.weightDataFileName = + fileNamePrefix + DEFAULT_WEIGHT_DATA_EXTENSION_NAME; + } + BrowserDownloads.prototype.save = function (modelArtifacts) { + return __awaiter(this, void 0, void 0, function () { + var weightsURL, weightsManifest, modelTopologyAndWeightManifest, modelTopologyAndWeightManifestURL, jsonAnchor_1, weightDataAnchor_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (typeof (document) === 'undefined') { + throw new Error('Browser downloads are not supported in ' + + 'this environment since `document` is not present'); + } + weightsURL = window.URL.createObjectURL(new Blob([modelArtifacts.weightData], { type: 'application/octet-stream' })); + if (!(modelArtifacts.modelTopology instanceof ArrayBuffer)) return [3 /*break*/, 1]; + throw new Error('BrowserDownloads.save() does not support saving model topology ' + + 'in binary formats yet.'); + case 1: + weightsManifest = [{ + paths: ['./' + this.weightDataFileName], + weights: modelArtifacts.weightSpecs + }]; + modelTopologyAndWeightManifest = { + modelTopology: modelArtifacts.modelTopology, + format: modelArtifacts.format, + generatedBy: modelArtifacts.generatedBy, + convertedBy: modelArtifacts.convertedBy, + weightsManifest: weightsManifest + }; + modelTopologyAndWeightManifestURL = window.URL.createObjectURL(new Blob([JSON.stringify(modelTopologyAndWeightManifest)], { type: 'application/json' })); + jsonAnchor_1 = this.jsonAnchor == null ? document.createElement('a') : + this.jsonAnchor; + jsonAnchor_1.download = this.modelTopologyFileName; + jsonAnchor_1.href = modelTopologyAndWeightManifestURL; + // Trigger downloads by evoking a click event on the download anchors. + // When multiple downloads are started synchronously, Firefox will only + // save the last one. + return [4 /*yield*/, defer(function () { return jsonAnchor_1.dispatchEvent(new MouseEvent('click')); })]; + case 2: + // Trigger downloads by evoking a click event on the download anchors. + // When multiple downloads are started synchronously, Firefox will only + // save the last one. + _a.sent(); + if (!(modelArtifacts.weightData != null)) return [3 /*break*/, 4]; + weightDataAnchor_1 = this.weightDataAnchor == null ? + document.createElement('a') : + this.weightDataAnchor; + weightDataAnchor_1.download = this.weightDataFileName; + weightDataAnchor_1.href = weightsURL; + return [4 /*yield*/, defer(function () { return weightDataAnchor_1.dispatchEvent(new MouseEvent('click')); })]; + case 3: + _a.sent(); + _a.label = 4; + case 4: return [2 /*return*/, { modelArtifactsInfo: getModelArtifactsInfoForJSON(modelArtifacts) }]; + } + }); + }); + }; + BrowserDownloads.URL_SCHEME = 'downloads://'; + return BrowserDownloads; + }()); + var BrowserFiles = /** @class */ (function () { + function BrowserFiles(files) { + if (files == null || files.length < 1) { + throw new Error("When calling browserFiles, at least 1 file is required, " + + ("but received " + files)); + } + this.files = files; + } + BrowserFiles.prototype.load = function () { + return __awaiter(this, void 0, void 0, function () { + var jsonFile, weightFiles; + var _this = this; + return __generator(this, function (_a) { + jsonFile = this.files[0]; + weightFiles = this.files.slice(1); + return [2 /*return*/, new Promise(function (resolve, reject) { + var jsonReader = new FileReader(); + jsonReader.onload = function (event) { + // tslint:disable-next-line:no-any + var modelJSON = JSON.parse(event.target.result); + var modelTopology = modelJSON.modelTopology; + if (modelTopology == null) { + reject(new Error("modelTopology field is missing from file " + jsonFile.name)); + return; + } + if (weightFiles.length === 0) { + resolve({ modelTopology: modelTopology }); + } + var weightsManifest = modelJSON.weightsManifest; + if (weightsManifest == null) { + reject(new Error("weightManifest field is missing from file " + jsonFile.name)); + return; + } + var pathToFile; + try { + pathToFile = + _this.checkManifestAndWeightFiles(weightsManifest, weightFiles); + } + catch (err) { + reject(err); + return; + } + var weightSpecs = []; + var paths = []; + var perFileBuffers = []; + weightsManifest.forEach(function (weightsGroup) { + weightsGroup.paths.forEach(function (path) { + paths.push(path); + perFileBuffers.push(null); + }); + weightSpecs.push.apply(weightSpecs, weightsGroup.weights); + }); + weightsManifest.forEach(function (weightsGroup) { + weightsGroup.paths.forEach(function (path) { + var weightFileReader = new FileReader(); + weightFileReader.onload = function (event) { + // tslint:disable-next-line:no-any + var weightData = event.target.result; + var index = paths.indexOf(path); + perFileBuffers[index] = weightData; + if (perFileBuffers.indexOf(null) === -1) { + resolve({ + modelTopology: modelTopology, + weightSpecs: weightSpecs, + weightData: concatenateArrayBuffers(perFileBuffers), + format: modelJSON.format, + generatedBy: modelJSON.generatedBy, + convertedBy: modelJSON.convertedBy, + userDefinedMetadata: modelJSON.userDefinedMetadata + }); + } + }; + weightFileReader.onerror = function (error) { + return reject("Failed to weights data from file of path '" + path + "'."); + }; + weightFileReader.readAsArrayBuffer(pathToFile[path]); + }); + }); + }; + jsonReader.onerror = function (error) { return reject("Failed to read model topology and weights manifest JSON " + + ("from file '" + jsonFile.name + "'. BrowserFiles supports loading ") + + "Keras-style tf.Model artifacts only."); }; + jsonReader.readAsText(jsonFile); + })]; + }); + }); + }; + /** + * Check the compatibility between weights manifest and weight files. + */ + BrowserFiles.prototype.checkManifestAndWeightFiles = function (manifest, files) { + var basenames = []; + var fileNames = files.map(function (file) { return basename(file.name); }); + var pathToFile = {}; + for (var _i = 0, manifest_1 = manifest; _i < manifest_1.length; _i++) { + var group = manifest_1[_i]; + group.paths.forEach(function (path) { + var pathBasename = basename(path); + if (basenames.indexOf(pathBasename) !== -1) { + throw new Error("Duplicate file basename found in weights manifest: " + + ("'" + pathBasename + "'")); + } + basenames.push(pathBasename); + if (fileNames.indexOf(pathBasename) === -1) { + throw new Error("Weight file with basename '" + pathBasename + "' is not provided."); + } + else { + pathToFile[path] = files[fileNames.indexOf(pathBasename)]; + } + }); + } + if (basenames.length !== files.length) { + throw new Error("Mismatch in the number of files in weights manifest " + + ("(" + basenames.length + ") and the number of weight files provided ") + + ("(" + files.length + ").")); + } + return pathToFile; + }; + return BrowserFiles; + }()); + var browserDownloadsRouter = function (url) { + if (!env().getBool('IS_BROWSER')) { + return null; + } + else { + if (!Array.isArray(url) && url.startsWith(BrowserDownloads.URL_SCHEME)) { + return browserDownloads(url.slice(BrowserDownloads.URL_SCHEME.length)); + } + else { + return null; + } + } + }; + IORouterRegistry.registerSaveRouter(browserDownloadsRouter); + /** + * Creates an IOHandler that triggers file downloads from the browser. + * + * The returned `IOHandler` instance can be used as model exporting methods such + * as `tf.Model.save` and supports only saving. + * + * ```js + * const model = tf.sequential(); + * model.add(tf.layers.dense( + * {units: 1, inputShape: [10], activation: 'sigmoid'})); + * const saveResult = await model.save('downloads://mymodel'); + * // This will trigger downloading of two files: + * // 'mymodel.json' and 'mymodel.weights.bin'. + * console.log(saveResult); + * ``` + * + * @param fileNamePrefix Prefix name of the files to be downloaded. For use with + * `tf.Model`, `fileNamePrefix` should follow either of the following two + * formats: + * 1. `null` or `undefined`, in which case the default file + * names will be used: + * - 'model.json' for the JSON file containing the model topology and + * weights manifest. + * - 'model.weights.bin' for the binary file containing the binary weight + * values. + * 2. A single string or an Array of a single string, as the file name prefix. + * For example, if `'foo'` is provided, the downloaded JSON + * file and binary weights file will be named 'foo.json' and + * 'foo.weights.bin', respectively. + * @param config Additional configuration for triggering downloads. + * @returns An instance of `BrowserDownloads` `IOHandler`. + */ + /** + * @doc { + * heading: 'Models', + * subheading: 'Loading', + * namespace: 'io', + * ignoreCI: true + * } + */ + function browserDownloads(fileNamePrefix) { + if (fileNamePrefix === void 0) { fileNamePrefix = 'model'; } + return new BrowserDownloads(fileNamePrefix); + } + /** + * Creates an IOHandler that loads model artifacts from user-selected files. + * + * This method can be used for loading from files such as user-selected files + * in the browser. + * When used in conjunction with `tf.loadLayersModel`, an instance of + * `tf.LayersModel` (Keras-style) can be constructed from the loaded artifacts. + * + * ```js + * // Note: This code snippet won't run properly without the actual file input + * // elements in the HTML DOM. + * + * // Suppose there are two HTML file input (``) + * // elements. + * const uploadJSONInput = document.getElementById('upload-json'); + * const uploadWeightsInput = document.getElementById('upload-weights'); + * const model = await tf.loadLayersModel(tf.io.browserFiles( + * [uploadJSONInput.files[0], uploadWeightsInput.files[0]])); + * ``` + * + * @param files `File`s to load from. Currently, this function supports only + * loading from files that contain Keras-style models (i.e., `tf.Model`s), for + * which an `Array` of `File`s is expected (in that order): + * - A JSON file containing the model topology and weight manifest. + * - Optionally, One or more binary files containing the binary weights. + * These files must have names that match the paths in the `weightsManifest` + * contained by the aforementioned JSON file, or errors will be thrown + * during loading. These weights files have the same format as the ones + * generated by `tensorflowjs_converter` that comes with the `tensorflowjs` + * Python PIP package. If no weights files are provided, only the model + * topology will be loaded from the JSON file above. + * @returns An instance of `Files` `IOHandler`. + */ + /** + * @doc { + * heading: 'Models', + * subheading: 'Loading', + * namespace: 'io', + * ignoreCI: true + * } + */ + function browserFiles(files) { + return new BrowserFiles(files); + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Monitor Promise.all progress, fire onProgress callback function. + * + * @param promises Promise list going to be monitored + * @param onProgress Callback function. Fired when a promise resolved. + * @param startFraction Optional fraction start. Default to 0. + * @param endFraction Optional fraction end. Default to 1. + */ + function monitorPromisesProgress(promises, onProgress, startFraction, endFraction) { + checkPromises(promises); + startFraction = startFraction == null ? 0 : startFraction; + endFraction = endFraction == null ? 1 : endFraction; + checkFraction(startFraction, endFraction); + var resolvedPromise = 0; + var registerMonitor = function (promise) { + promise.then(function (value) { + var fraction = startFraction + + ++resolvedPromise / promises.length * (endFraction - startFraction); + // pass fraction as parameter to callback function. + onProgress(fraction); + return value; + }); + return promise; + }; + function checkPromises(promises) { + assert(promises != null && Array.isArray(promises) && promises.length > 0, function () { return 'promises must be a none empty array'; }); + } + function checkFraction(startFraction, endFraction) { + assert(startFraction >= 0 && startFraction <= 1, function () { return "Progress fraction must be in range [0, 1], but " + + ("got startFraction " + startFraction); }); + assert(endFraction >= 0 && endFraction <= 1, function () { return "Progress fraction must be in range [0, 1], but " + + ("got endFraction " + endFraction); }); + assert(endFraction >= startFraction, function () { return "startFraction must be no more than endFraction, but " + + ("got startFraction " + startFraction + " and endFraction ") + + ("" + endFraction); }); + } + return Promise.all(promises.map(registerMonitor)); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Reads binary weights data from a number of URLs. + * + * @param fetchURLs URLs to send the HTTP requests at, using `fetch` calls. + * @param requestOptions RequestInit (options) for the HTTP requests. + * @param fetchFunc Optional overriding value for the `window.fetch` function. + * @param onProgress Optional, progress callback function, fired periodically + * before the load is completed. + * @returns A `Promise` of an Array of `ArrayBuffer`. The Array has the same + * length as `fetchURLs`. + */ + function loadWeightsAsArrayBuffer(fetchURLs, loadOptions) { + return __awaiter(this, void 0, void 0, function () { + var fetchFunc, requests, fetchStartFraction, fetchEndFraction, responses, _a, bufferPromises, bufferStartFraction, bufferEndFraction, buffers, _b; + return __generator(this, function (_c) { + switch (_c.label) { + case 0: + if (loadOptions == null) { + loadOptions = {}; + } + fetchFunc = loadOptions.fetchFunc == null ? env().platform.fetch : + loadOptions.fetchFunc; + requests = fetchURLs.map(function (fetchURL) { + return fetchFunc(fetchURL, loadOptions.requestInit, { isBinary: true }); + }); + fetchStartFraction = 0; + fetchEndFraction = 0.5; + if (!(loadOptions.onProgress == null)) return [3 /*break*/, 2]; + return [4 /*yield*/, Promise.all(requests)]; + case 1: + _a = _c.sent(); + return [3 /*break*/, 4]; + case 2: return [4 /*yield*/, monitorPromisesProgress(requests, loadOptions.onProgress, fetchStartFraction, fetchEndFraction)]; + case 3: + _a = _c.sent(); + _c.label = 4; + case 4: + responses = _a; + bufferPromises = responses.map(function (response) { return response.arrayBuffer(); }); + bufferStartFraction = 0.5; + bufferEndFraction = 1; + if (!(loadOptions.onProgress == null)) return [3 /*break*/, 6]; + return [4 /*yield*/, Promise.all(bufferPromises)]; + case 5: + _b = _c.sent(); + return [3 /*break*/, 8]; + case 6: return [4 /*yield*/, monitorPromisesProgress(bufferPromises, loadOptions.onProgress, bufferStartFraction, bufferEndFraction)]; + case 7: + _b = _c.sent(); + _c.label = 8; + case 8: + buffers = _b; + return [2 /*return*/, buffers]; + } + }); + }); + } + /** + * Reads a weights manifest JSON configuration, fetches the weights and + * returns them as `Tensor`s. + * + * @param manifest The weights manifest JSON. + * @param filePathPrefix The path prefix for filenames given in the manifest. + * Defaults to the empty string. + * @param weightNames The names of the weights to be fetched. + */ + function loadWeights(manifest, filePathPrefix, weightNames, requestInit) { + if (filePathPrefix === void 0) { filePathPrefix = ''; } + return __awaiter(this, void 0, void 0, function () { + var fetchWeights, loadWeights; + return __generator(this, function (_a) { + fetchWeights = function (fetchUrls) { + return loadWeightsAsArrayBuffer(fetchUrls, { requestInit: requestInit }); + }; + loadWeights = weightsLoaderFactory(fetchWeights); + return [2 /*return*/, loadWeights(manifest, filePathPrefix, weightNames)]; + }); + }); + } + /** + * Creates a function, which reads a weights manifest JSON configuration, + * fetches the weight files using the specified function and returns them as + * `Tensor`s. + * + * ```js + * // example for creating a nodejs weight loader, which reads the weight files + * // from disk using fs.readFileSync + * + * import * as fs from 'fs' + * + * const fetchWeightsFromDisk = (filePaths: string[]) => + * filePaths.map(filePath => fs.readFileSync(filePath).buffer) + * + * const loadWeights = tf.io.weightsLoaderFactory(fetchWeightsFromDisk) + * + * const manifest = JSON.parse( + * fs.readFileSync('./my_model-weights_manifest').toString() + * ) + * const weightMap = await loadWeights(manifest, './') + * ``` + * @param fetchWeightsFunction The function used for fetching the weight files. + * @returns Weight loading function. + */ + function weightsLoaderFactory(fetchWeightsFunction) { + var _this = this; + return function (manifest, filePathPrefix, weightNames) { + if (filePathPrefix === void 0) { filePathPrefix = ''; } + return __awaiter(_this, void 0, void 0, function () { + var groupIndicesToFetchMap, groupWeightsToFetch, weightsFound, allManifestWeightNames, weightsNotFound, groupIndicesToFetch, fetchUrls, buffers, weightsTensorMap, bufferIndexOffset; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + groupIndicesToFetchMap = manifest.map(function () { return false; }); + groupWeightsToFetch = {}; + weightsFound = weightNames != null ? weightNames.map(function () { return false; }) : []; + allManifestWeightNames = []; + manifest.forEach(function (manifestGroupConfig, groupIndex) { + var groupOffset = 0; + manifestGroupConfig.weights.forEach(function (weightsEntry) { + var rawDtype = ('quantization' in weightsEntry) ? + weightsEntry.quantization.dtype : + weightsEntry.dtype; + var weightsBytes = DTYPE_VALUE_SIZE_MAP[rawDtype] * + sizeFromShape(weightsEntry.shape); + var enqueueWeightsForFetchingFn = function () { + groupIndicesToFetchMap[groupIndex] = true; + if (groupWeightsToFetch[groupIndex] == null) { + groupWeightsToFetch[groupIndex] = []; + } + groupWeightsToFetch[groupIndex].push({ + manifestEntry: weightsEntry, + groupOffset: groupOffset, + sizeBytes: weightsBytes + }); + }; + if (weightNames != null) { + weightNames.forEach(function (weightName, weightIndex) { + if (weightName === weightsEntry.name) { + enqueueWeightsForFetchingFn(); + weightsFound[weightIndex] = true; + } + }); + } + else { + enqueueWeightsForFetchingFn(); + } + allManifestWeightNames.push(weightsEntry.name); + groupOffset += weightsBytes; + }); + }); + if (!weightsFound.every(function (found) { return found; })) { + weightsNotFound = weightNames.filter(function (_, i) { return !weightsFound[i]; }); + throw new Error("Could not find weights in manifest with names: " + + (weightsNotFound.join(', ') + ". \n") + + "Manifest JSON has weights with names: " + + (allManifestWeightNames.join(', ') + ".")); + } + groupIndicesToFetch = groupIndicesToFetchMap.reduce(function (accumulator, shouldFetch, i) { + if (shouldFetch) { + accumulator.push(i); + } + return accumulator; + }, []); + fetchUrls = []; + groupIndicesToFetch.forEach(function (i) { + manifest[i].paths.forEach(function (filepath) { + var fetchUrl = filePathPrefix + + (!filePathPrefix.endsWith('/') ? '/' : '') + filepath; + fetchUrls.push(fetchUrl); + }); + }); + return [4 /*yield*/, fetchWeightsFunction(fetchUrls)]; + case 1: + buffers = _a.sent(); + weightsTensorMap = {}; + bufferIndexOffset = 0; + groupIndicesToFetch.forEach(function (i) { + var numBuffers = manifest[i].paths.length; + var groupBytes = 0; + for (var i_1 = 0; i_1 < numBuffers; i_1++) { + groupBytes += buffers[bufferIndexOffset + i_1].byteLength; + } + // Create a buffer for the whole group. + var groupBuffer = new ArrayBuffer(groupBytes); + var groupByteBuffer = new Uint8Array(groupBuffer); + var groupBufferOffset = 0; + for (var i_2 = 0; i_2 < numBuffers; i_2++) { + var buffer = new Uint8Array(buffers[bufferIndexOffset + i_2]); + groupByteBuffer.set(buffer, groupBufferOffset); + groupBufferOffset += buffer.byteLength; + } + var weightsEntries = groupWeightsToFetch[i]; + weightsEntries.forEach(function (weightsEntry) { + var byteBuffer = groupBuffer.slice(weightsEntry.groupOffset, weightsEntry.groupOffset + weightsEntry.sizeBytes); + var nameToTensorMap = decodeWeights(byteBuffer, [weightsEntry.manifestEntry]); + for (var name_1 in nameToTensorMap) { + weightsTensorMap[name_1] = nameToTensorMap[name_1]; + } + }); + bufferIndexOffset += numBuffers; + }); + return [2 /*return*/, weightsTensorMap]; + } + }); + }); + }; + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var OCTET_STREAM_MIME_TYPE = 'application/octet-stream'; + var JSON_TYPE = 'application/json'; + var HTTPRequest = /** @class */ (function () { + function HTTPRequest(path, loadOptions) { + this.DEFAULT_METHOD = 'POST'; + if (loadOptions == null) { + loadOptions = {}; + } + this.weightPathPrefix = loadOptions.weightPathPrefix; + this.onProgress = loadOptions.onProgress; + if (loadOptions.fetchFunc != null) { + assert(typeof loadOptions.fetchFunc === 'function', function () { return 'Must pass a function that matches the signature of ' + + '`fetch` (see ' + + 'https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)'; }); + this.fetch = loadOptions.fetchFunc; + } + else { + this.fetch = env().platform.fetch; + } + assert(path != null && path.length > 0, function () { return 'URL path for http must not be null, undefined or ' + + 'empty.'; }); + if (Array.isArray(path)) { + assert(path.length === 2, function () { return 'URL paths for http must have a length of 2, ' + + ("(actual length is " + path.length + ")."); }); + } + this.path = path; + if (loadOptions.requestInit != null && + loadOptions.requestInit.body != null) { + throw new Error('requestInit is expected to have no pre-existing body, but has one.'); + } + this.requestInit = loadOptions.requestInit || {}; + } + HTTPRequest.prototype.save = function (modelArtifacts) { + return __awaiter(this, void 0, void 0, function () { + var init, weightsManifest, modelTopologyAndWeightManifest, response; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (modelArtifacts.modelTopology instanceof ArrayBuffer) { + throw new Error('BrowserHTTPRequest.save() does not support saving model topology ' + + 'in binary formats yet.'); + } + init = Object.assign({ method: this.DEFAULT_METHOD }, this.requestInit); + init.body = new FormData(); + weightsManifest = [{ + paths: ['./model.weights.bin'], + weights: modelArtifacts.weightSpecs, + }]; + modelTopologyAndWeightManifest = { + modelTopology: modelArtifacts.modelTopology, + format: modelArtifacts.format, + generatedBy: modelArtifacts.generatedBy, + convertedBy: modelArtifacts.convertedBy, + userDefinedMetadata: modelArtifacts.userDefinedMetadata, + weightsManifest: weightsManifest + }; + init.body.append('model.json', new Blob([JSON.stringify(modelTopologyAndWeightManifest)], { type: JSON_TYPE }), 'model.json'); + if (modelArtifacts.weightData != null) { + init.body.append('model.weights.bin', new Blob([modelArtifacts.weightData], { type: OCTET_STREAM_MIME_TYPE }), 'model.weights.bin'); + } + return [4 /*yield*/, this.fetch(this.path, init)]; + case 1: + response = _a.sent(); + if (response.ok) { + return [2 /*return*/, { + modelArtifactsInfo: getModelArtifactsInfoForJSON(modelArtifacts), + responses: [response], + }]; + } + else { + throw new Error("BrowserHTTPRequest.save() failed due to HTTP response status " + + (response.status + ".")); + } + } + }); + }); + }; + /** + * Load model artifacts via HTTP request(s). + * + * See the documentation to `tf.io.http` for details on the saved + * artifacts. + * + * @returns The loaded model artifacts (if loading succeeds). + */ + HTTPRequest.prototype.load = function () { + return __awaiter(this, void 0, void 0, function () { + var modelConfigRequest, modelConfig, e_1, message, modelTopology, weightsManifest, generatedBy, convertedBy, format, userDefinedMetadata, weightSpecs, weightData, results; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, this.fetch(this.path, this.requestInit)]; + case 1: + modelConfigRequest = _a.sent(); + if (!modelConfigRequest.ok) { + throw new Error("Request to " + this.path + " failed with status code " + + (modelConfigRequest.status + ". Please verify this URL points to ") + + "the model JSON of the model to load."); + } + _a.label = 2; + case 2: + _a.trys.push([2, 4, , 5]); + return [4 /*yield*/, modelConfigRequest.json()]; + case 3: + modelConfig = _a.sent(); + return [3 /*break*/, 5]; + case 4: + e_1 = _a.sent(); + message = "Failed to parse model JSON of response from " + this.path + "."; + // TODO(nsthorat): Remove this after some time when we're comfortable that + // .pb files are mostly gone. + if (this.path.endsWith('.pb')) { + message += ' Your path contains a .pb file extension. ' + + 'Support for .pb models have been removed in TensorFlow.js 1.0 ' + + 'in favor of .json models. You can re-convert your Python ' + + 'TensorFlow model using the TensorFlow.js 1.0 conversion scripts ' + + 'or you can convert your.pb models with the \'pb2json\'' + + 'NPM script in the tensorflow/tfjs-converter repository.'; + } + else { + message += ' Please make sure the server is serving valid ' + + 'JSON for this request.'; + } + throw new Error(message); + case 5: + modelTopology = modelConfig.modelTopology; + weightsManifest = modelConfig.weightsManifest; + generatedBy = modelConfig.generatedBy; + convertedBy = modelConfig.convertedBy; + format = modelConfig.format; + userDefinedMetadata = modelConfig.userDefinedMetadata; + // We do not allow both modelTopology and weightsManifest to be missing. + if (modelTopology == null && weightsManifest == null) { + throw new Error("The JSON from HTTP path " + this.path + " contains neither model " + + "topology or manifest for weights."); + } + if (!(weightsManifest != null)) return [3 /*break*/, 7]; + return [4 /*yield*/, this.loadWeights(weightsManifest)]; + case 6: + results = _a.sent(); + weightSpecs = results[0], weightData = results[1]; + _a.label = 7; + case 7: return [2 /*return*/, { + modelTopology: modelTopology, + weightSpecs: weightSpecs, + weightData: weightData, + userDefinedMetadata: userDefinedMetadata, + generatedBy: generatedBy, + convertedBy: convertedBy, + format: format + }]; + } + }); + }); + }; + HTTPRequest.prototype.loadWeights = function (weightsManifest) { + return __awaiter(this, void 0, void 0, function () { + var weightPath, _a, prefix, suffix, pathPrefix, weightSpecs, _i, weightsManifest_1, entry, fetchURLs, buffers; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + weightPath = Array.isArray(this.path) ? this.path[1] : this.path; + _a = parseUrl(weightPath), prefix = _a[0], suffix = _a[1]; + pathPrefix = this.weightPathPrefix || prefix; + weightSpecs = []; + for (_i = 0, weightsManifest_1 = weightsManifest; _i < weightsManifest_1.length; _i++) { + entry = weightsManifest_1[_i]; + weightSpecs.push.apply(weightSpecs, entry.weights); + } + fetchURLs = []; + weightsManifest.forEach(function (weightsGroup) { + weightsGroup.paths.forEach(function (path) { + fetchURLs.push(pathPrefix + path + suffix); + }); + }); + return [4 /*yield*/, loadWeightsAsArrayBuffer(fetchURLs, { + requestInit: this.requestInit, + fetchFunc: this.fetch, + onProgress: this.onProgress + })]; + case 1: + buffers = _b.sent(); + return [2 /*return*/, [weightSpecs, concatenateArrayBuffers(buffers)]]; + } + }); + }); + }; + HTTPRequest.URL_SCHEME_REGEX = /^https?:\/\//; + return HTTPRequest; + }()); + /** + * Extract the prefix and suffix of the url, where the prefix is the path before + * the last file, and suffix is the search params after the last file. + * ``` + * const url = 'http://tfhub.dev/model/1/tensorflowjs_model.pb?tfjs-format=file' + * [prefix, suffix] = parseUrl(url) + * // prefix = 'http://tfhub.dev/model/1/' + * // suffix = '?tfjs-format=file' + * ``` + * @param url the model url to be parsed. + */ + function parseUrl(url) { + var lastSlash = url.lastIndexOf('/'); + var lastSearchParam = url.lastIndexOf('?'); + var prefix = url.substring(0, lastSlash); + var suffix = lastSearchParam > lastSlash ? url.substring(lastSearchParam) : ''; + return [prefix + '/', suffix]; + } + function isHTTPScheme(url) { + return url.match(HTTPRequest.URL_SCHEME_REGEX) != null; + } + var httpRouter = function (url, loadOptions) { + if (typeof fetch === 'undefined' && + (loadOptions == null || loadOptions.fetchFunc == null)) { + // `http` uses `fetch` or `node-fetch`, if one wants to use it in + // an environment that is not the browser or node they have to setup a + // global fetch polyfill. + return null; + } + else { + var isHTTP = true; + if (Array.isArray(url)) { + isHTTP = url.every(function (urlItem) { return isHTTPScheme(urlItem); }); + } + else { + isHTTP = isHTTPScheme(url); + } + if (isHTTP) { + return http(url, loadOptions); + } + } + return null; + }; + IORouterRegistry.registerSaveRouter(httpRouter); + IORouterRegistry.registerLoadRouter(httpRouter); + /** + * Creates an IOHandler subtype that sends model artifacts to HTTP server. + * + * An HTTP request of the `multipart/form-data` mime type will be sent to the + * `path` URL. The form data includes artifacts that represent the topology + * and/or weights of the model. In the case of Keras-style `tf.Model`, two + * blobs (files) exist in form-data: + * - A JSON file consisting of `modelTopology` and `weightsManifest`. + * - A binary weights file consisting of the concatenated weight values. + * These files are in the same format as the one generated by + * [tfjs_converter](https://js.tensorflow.org/tutorials/import-keras.html). + * + * The following code snippet exemplifies the client-side code that uses this + * function: + * + * ```js + * const model = tf.sequential(); + * model.add( + * tf.layers.dense({units: 1, inputShape: [100], activation: 'sigmoid'})); + * + * const saveResult = await model.save(tf.io.http( + * 'http://model-server:5000/upload', {requestInit: {method: 'PUT'}})); + * console.log(saveResult); + * ``` + * + * If the default `POST` method is to be used, without any custom parameters + * such as headers, you can simply pass an HTTP or HTTPS URL to `model.save`: + * + * ```js + * const saveResult = await model.save('http://model-server:5000/upload'); + * ``` + * + * The following GitHub Gist + * https://gist.github.com/dsmilkov/1b6046fd6132d7408d5257b0976f7864 + * implements a server based on [flask](https://github.com/pallets/flask) that + * can receive the request. Upon receiving the model artifacts via the requst, + * this particular server reconsistutes instances of [Keras + * Models](https://keras.io/models/model/) in memory. + * + * + * @param path A URL path to the model. + * Can be an absolute HTTP path (e.g., + * 'http://localhost:8000/model-upload)') or a relative path (e.g., + * './model-upload'). + * @param requestInit Request configurations to be used when sending + * HTTP request to server using `fetch`. It can contain fields such as + * `method`, `credentials`, `headers`, `mode`, etc. See + * https://developer.mozilla.org/en-US/docs/Web/API/Request/Request + * for more information. `requestInit` must not have a body, because the + * body will be set by TensorFlow.js. File blobs representing the model + * topology (filename: 'model.json') and the weights of the model (filename: + * 'model.weights.bin') will be appended to the body. If `requestInit` has a + * `body`, an Error will be thrown. + * @param loadOptions Optional configuration for the loading. It includes the + * following fields: + * - weightPathPrefix Optional, this specifies the path prefix for weight + * files, by default this is calculated from the path param. + * - fetchFunc Optional, custom `fetch` function. E.g., in Node.js, + * the `fetch` from node-fetch can be used here. + * - onProgress Optional, progress callback function, fired periodically + * before the load is completed. + * @returns An instance of `IOHandler`. + */ + /** + * @doc { + * heading: 'Models', + * subheading: 'Loading', + * namespace: 'io', + * ignoreCI: true + * } + */ + function http(path, loadOptions) { + return new HTTPRequest(path, loadOptions); + } + /** + * Deprecated. Use `tf.io.http`. + * @param path + * @param loadOptions + */ + function browserHTTPRequest(path, loadOptions) { + return http(path, loadOptions); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var PassthroughLoader = /** @class */ (function () { + function PassthroughLoader(modelArtifacts) { + this.modelArtifacts = modelArtifacts; + } + PassthroughLoader.prototype.load = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, this.modelArtifacts]; + }); + }); + }; + return PassthroughLoader; + }()); + var PassthroughSaver = /** @class */ (function () { + function PassthroughSaver(saveHandler) { + this.saveHandler = saveHandler; + } + PassthroughSaver.prototype.save = function (modelArtifacts) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + return [2 /*return*/, this.saveHandler(modelArtifacts)]; + }); + }); + }; + return PassthroughSaver; + }()); + /** + * Creates an IOHandler that loads model artifacts from memory. + * + * When used in conjunction with `tf.loadLayersModel`, an instance of + * `tf.LayersModel` (Keras-style) can be constructed from the loaded artifacts. + * + * ```js + * const model = await tf.loadLayersModel(tf.io.fromMemory( + * modelTopology, weightSpecs, weightData)); + * ``` + * + * @param modelArtifacts a object containing model topology (i.e., parsed from + * the JSON format). + * @param weightSpecs An array of `WeightsManifestEntry` objects describing the + * names, shapes, types, and quantization of the weight data. + * @param weightData A single `ArrayBuffer` containing the weight data, + * concatenated in the order described by the weightSpecs. + * @param trainingConfig Model training configuration. Optional. + * + * @returns A passthrough `IOHandler` that simply loads the provided data. + */ + function fromMemory(modelArtifacts, weightSpecs, weightData, trainingConfig) { + if (arguments.length === 1) { + var isModelArtifacts = modelArtifacts.modelTopology != null || + modelArtifacts.weightSpecs != null; + if (isModelArtifacts) { + return new PassthroughLoader(modelArtifacts); + } + else { + // Legacy support: with only modelTopology. + // TODO(cais): Remove this deprecated API. + console.warn('Please call tf.io.fromMemory() with only one argument. ' + + 'The argument should be of type ModelArtifacts. ' + + 'The multi-argument signature of tf.io.fromMemory() has been ' + + 'deprecated and will be removed in a future release.'); + return new PassthroughLoader({ modelTopology: modelArtifacts }); + } + } + else { + // Legacy support. + // TODO(cais): Remove this deprecated API. + console.warn('Please call tf.io.fromMemory() with only one argument. ' + + 'The argument should be of type ModelArtifacts. ' + + 'The multi-argument signature of tf.io.fromMemory() has been ' + + 'deprecated and will be removed in a future release.'); + return new PassthroughLoader({ + modelTopology: modelArtifacts, + weightSpecs: weightSpecs, + weightData: weightData, + trainingConfig: trainingConfig + }); + } + } + /** + * Creates an IOHandler that passes saved model artifacts to a callback. + * + * ```js + * function handleSave(artifacts) { + * // ... do something with the artifacts ... + * return {modelArtifactsInfo: {...}, ...}; + * } + * + * const saveResult = model.save(tf.io.withSaveHandler(handleSave)); + * ``` + * + * @param saveHandler A function that accepts a `ModelArtifacts` and returns a + * `SaveResult`. + */ + function withSaveHandler(saveHandler) { + return new PassthroughSaver(saveHandler); + } + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + + var io = { + __proto__: null, + browserFiles: browserFiles, + browserHTTPRequest: browserHTTPRequest, + concatenateArrayBuffers: concatenateArrayBuffers, + decodeWeights: decodeWeights, + encodeWeights: encodeWeights, + fromMemory: fromMemory, + getLoadHandlers: getLoadHandlers, + getModelArtifactsInfoForJSON: getModelArtifactsInfoForJSON, + getSaveHandlers: getSaveHandlers, + http: http, + isHTTPScheme: isHTTPScheme, + loadWeights: loadWeights, + registerLoadRouter: registerLoadRouter, + registerSaveRouter: registerSaveRouter, + weightsLoaderFactory: weightsLoaderFactory, + withSaveHandler: withSaveHandler, + copyModel: copyModel, + listModels: listModels, + moveModel: moveModel, + removeModel: removeModel + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates a one-hot `tf.Tensor`. The locations represented by `indices` take + * value `onValue` (defaults to 1), while all other locations take value + * `offValue` (defaults to 0). If `indices` is rank `R`, the output has rank + * `R+1` with the last axis of size `depth`. + * + * ```js + * tf.oneHot(tf.tensor1d([0, 1], 'int32'), 3).print(); + * ``` + * + * @param indices `tf.Tensor` of indices with dtype `int32`. + * @param depth The depth of the one hot dimension. + * @param onValue A number used to fill in the output when the index matches + * the location. + * @param offValue A number used to fill in the output when the index does + * not match the location. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function oneHot_(indices, depth, onValue, offValue) { + if (onValue === void 0) { onValue = 1; } + if (offValue === void 0) { offValue = 0; } + if (depth < 2) { + throw new Error("Error in oneHot: depth must be >=2, but it is " + depth); + } + var $indices = convertToTensor(indices, 'indices', 'oneHot', 'int32'); + var outShape = $indices.shape.concat([depth]); + var forward = function (backend, save) { + save([$indices]); + return reshape(backend.oneHot($indices.flatten(), depth, onValue, offValue), outShape); + }; + var inputs = { indices: $indices }; + var attrs = { depth: depth, onValue: onValue, offValue: offValue }; + return ENGINE.runKernelFunc(forward, inputs, null /* grad */, OneHot, attrs); + } + var oneHot = op({ oneHot_: oneHot_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Computes the confusion matrix from true labels and predicted labels. + * + * ```js + * const labels = tf.tensor1d([0, 1, 2, 1, 0], 'int32'); + * const predictions = tf.tensor1d([0, 2, 2, 1, 0], 'int32'); + * const numClasses = 3; + * const out = tf.math.confusionMatrix(labels, predictions, numClasses); + * out.print(); + * // Expected output matrix: + * // [[2, 0, 0], + * // [0, 1, 1], + * // [0, 0, 1]] + * ``` + * + * @param labels The target labels, assumed to be 0-based integers + * for the classes. The shape is `[numExamples]`, where + * `numExamples` is the number of examples included. + * @param predictions The predicted classes, assumed to be + * 0-based integers for the classes. Must have the same shape as `labels`. + * @param numClasses Number of all classes, as an integer. + * Its value must be larger than the largest element in `labels` and + * `predictions`. + * @returns The confusion matrix as a int32-type 2D tensor. The value at + * row `r` and column `c` is the number of times examples of actual class + * `r` were predicted as class `c`. + */ + /** @doc {heading: 'Operations', subheading: 'Evaluation'} */ + function confusionMatrix_(labels, predictions, numClasses) { + var $labels = convertToTensor(labels, 'labels', 'confusionMatrix'); + var $predictions = convertToTensor(predictions, 'predictions', 'confusionMatrix'); + assert(numClasses == null || numClasses > 0 && Number.isInteger(numClasses), function () { return "If provided, numClasses must be a positive integer, " + + ("but got " + numClasses); }); + assert($labels.rank === 1, function () { return "Expected the rank of labels to be 1, but got " + $labels.rank; }); + assert($predictions.rank === 1, function () { return "Expected the rank of predictions to be 1, " + + ("but got " + $predictions.rank); }); + assert($labels.shape[0] === $predictions.shape[0], function () { return "Mismatch in the number of examples: " + + ($labels.shape[0] + " vs. " + $predictions.shape[0] + ". ") + + "Labels and predictions should have the same number of elements."; }); + assert(numClasses > 0 && Number.isInteger(numClasses), function () { return "numClasses is required to be a positive integer, but got " + + ("" + numClasses); }); + // TODO(cais): In the future, if oneHot supports tensors inputs for + // `numClasses`, `confusionMatrix` can make `numClasses` optional. + var oneHotLabels = oneHot($labels.asType('int32'), numClasses); + var oneHotPredictions = oneHot($predictions.asType('int32'), numClasses); + var oneHotLabelsT = oneHotLabels.transpose(); + return oneHotLabelsT.matMul(oneHotPredictions).asType('int32'); + } + var confusionMatrix = op({ confusionMatrix_: confusionMatrix_ }); + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + + var math = { + __proto__: null, + confusionMatrix: confusionMatrix + }; + + /** + * @license + * Copyright 2018 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Creates rank-3 `tf.Tensor` with the provided values, shape and dtype. + * + * The same functionality can be achieved with `tf.tensor`, but in general + * we recommend using `tf.tensor3d` as it makes the code more readable. + * + * ```js + * // Pass a nested array. + * tf.tensor3d([[[1], [2]], [[3], [4]]]).print(); + * ``` + * ```js + * // Pass a flat array and specify a shape. + * tf.tensor3d([1, 2, 3, 4], [2, 2, 1]).print(); + * ``` + * + * @param values The values of the tensor. Can be nested array of numbers, + * or a flat array, or a `TypedArray`. + * @param shape The shape of the tensor. If not provided, it is inferred from + * `values`. + * @param dtype The data type. + */ + /** @doc {heading: 'Tensors', subheading: 'Creation'} */ + function tensor3d(values, shape, dtype) { + assertNonNull(values); + if (shape != null && shape.length !== 3) { + throw new Error('tensor3d() requires shape to have three numbers'); + } + var inferredShape = inferShape(values, dtype); + if (inferredShape.length !== 3 && inferredShape.length !== 1) { + throw new Error('tensor3d() requires values to be number[][][] or flat/TypedArray'); + } + if (inferredShape.length === 1 && shape == null) { + throw new Error('tensor3d() requires shape to be provided when `values` ' + + 'are a flat array'); + } + return makeTensor(values, shape, inferredShape, dtype); + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + var fromPixels2DContext; + /** + * Creates a `tf.Tensor` from an image. + * + * ```js + * const image = new ImageData(1, 1); + * image.data[0] = 100; + * image.data[1] = 150; + * image.data[2] = 200; + * image.data[3] = 255; + * + * tf.browser.fromPixels(image).print(); + * ``` + * + * @param pixels The input image to construct the tensor from. The + * supported image types are all 4-channel. You can also pass in an image + * object with following attributes: + * `{data: Uint8Array; width: number; height: number}` + * @param numChannels The number of channels of the output tensor. A + * numChannels value less than 4 allows you to ignore channels. Defaults to + * 3 (ignores alpha channel of input image). + */ + /** @doc {heading: 'Browser', namespace: 'browser', ignoreCI: true} */ + function fromPixels_(pixels, numChannels) { + if (numChannels === void 0) { numChannels = 3; } + // Sanity checks. + if (numChannels > 4) { + throw new Error('Cannot construct Tensor with more than 4 channels from pixels.'); + } + if (pixels == null) { + throw new Error('pixels passed to tf.browser.fromPixels() can not be null'); + } + var isPixelData = false; + var isImageData = false; + var isVideo = false; + var isImage = false; + var isCanvasLike = false; + if (pixels.data instanceof Uint8Array) { + isPixelData = true; + } + else if (typeof (ImageData) !== 'undefined' && pixels instanceof ImageData) { + isImageData = true; + } + else if (typeof (HTMLVideoElement) !== 'undefined' && + pixels instanceof HTMLVideoElement) { + isVideo = true; + } + else if (typeof (HTMLImageElement) !== 'undefined' && + pixels instanceof HTMLImageElement) { + isImage = true; + // tslint:disable-next-line: no-any + } + else if (pixels.getContext != null) { + isCanvasLike = true; + } + else { + throw new Error('pixels passed to tf.browser.fromPixels() must be either an ' + + "HTMLVideoElement, HTMLImageElement, HTMLCanvasElement, ImageData " + + "in browser, or OffscreenCanvas, ImageData in webworker" + + " or {data: Uint32Array, width: number, height: number}, " + + ("but was " + pixels.constructor.name)); + } + if (isVideo) { + var HAVE_CURRENT_DATA_READY_STATE = 2; + if (isVideo && + pixels.readyState < + HAVE_CURRENT_DATA_READY_STATE) { + throw new Error('The video element has not loaded data yet. Please wait for ' + + '`loadeddata` event on the

    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� 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

  • h`6##Z4- zo<67Xw+GDpYEGB^D@F_`p~&H9;=hdMeqIp+ipr^4dK#;u2)0|UL^Z+$o%QjebJY&C z=Y$ZZGaSntc_P(gST|WhO5rmat3oK8l#hDrYd*P)-#}~*u17~RCGITOHp-D~Ta8A| zDmZ!?&7P=&esO7Ppdip?9pXTW6xPPFYp!TtrR?`6ppZ5rRr zHXIvfOJ@5?w$?plZ;dlzt{$<^gM=SBOu$=jjH5TO^-?Nc2FsbDu?)t&r*2UQEu@VFGBaaIaplC7n4&o|Fa?Z{GSNYcgii_bj~rwqDm~FY~JHigD49Va{pPT zy8LeUMnqE4ObpFafZTx|--u*)o4fnQMn>pv=y%^!bl#p?_!BVgiW(xC!g@S|NEVv5pf|uYe_zR&zxF8XB3VVbE;ec>dI3c79=Y>omN5~V3 zgzLh6K}z_4)pxzv*T3t$Tjc$(dZ&u~|E~KLk^Xo6?}|JpCm+{!;?aG8hqtSWuXuCo zw#GM@An`cBH$W7N@5JI%F>+FIq9?G3ed0x4_x@ru#fV7V1)_(-8xebnp@_P=u&BQw R1}ncR3J+By*CSVN{@+HkvWox! literal 0 HcmV?d00001 diff --git a/e2e/benchmarks/tfjs-backend-wasm.wasm b/e2e/benchmarks/tfjs-backend-wasm.wasm new file mode 100644 index 0000000000000000000000000000000000000000..b341cf828d85e26051acde90e7c4aefe3d85ca0c GIT binary patch literal 155531 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 Date: Thu, 30 Jul 2020 10:20:24 -0400 Subject: [PATCH 29/70] clean --- tfjs-backend-wasm/scripts/build-wasm.sh | 5 +-- tfjs-backend-wasm/src/backend_wasm.ts | 20 ++++++---- tfjs-backend-wasm/src/cc/BUILD | 4 +- .../wasm-out/tfjs-backend-wasm-simd.d.ts | 39 ------------------- 4 files changed, 15 insertions(+), 53 deletions(-) delete mode 100644 tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-simd.d.ts diff --git a/tfjs-backend-wasm/scripts/build-wasm.sh b/tfjs-backend-wasm/scripts/build-wasm.sh index f0d846dceca..6aaf209d2dd 100755 --- a/tfjs-backend-wasm/scripts/build-wasm.sh +++ b/tfjs-backend-wasm/scripts/build-wasm.sh @@ -25,9 +25,8 @@ cp -f bazel-bin/src/cc/tfjs-backend-wasm.js \ wasm-out/ # SIMD build. -yarn bazel build -c opt //src/cc:tfjs-backend-wasm-simd.js --config=wasm --copt="-msimd128" -cp -f bazel-bin/src/cc/tfjs-backend-wasm-simd.js \ - bazel-bin/src/cc/tfjs-backend-wasm-simd.wasm \ +yarn bazel build -c opt //src/cc:tfjs-backend-wasm-simd.wasm --config=wasm --copt="-msimd128" +cp -f bazel-bin/src/cc/tfjs-backend-wasm-simd.wasm \ wasm-out/ mkdir -p dist diff --git a/tfjs-backend-wasm/src/backend_wasm.ts b/tfjs-backend-wasm/src/backend_wasm.ts index 0299073da66..31acefa7d2c 100644 --- a/tfjs-backend-wasm/src/backend_wasm.ts +++ b/tfjs-backend-wasm/src/backend_wasm.ts @@ -19,7 +19,6 @@ import './flags_wasm'; import {backend_util, BackendTimingInfo, DataStorage, DataType, engine, env, KernelBackend, registerBackend, TensorInfo, util} from '@tensorflow/tfjs-core'; import {BackendWasmModule, WasmFactoryConfig} from '../wasm-out/tfjs-backend-wasm'; -import wasmFactorySimd from '../wasm-out/tfjs-backend-wasm-simd.js'; import wasmFactory from '../wasm-out/tfjs-backend-wasm.js'; const WASM_PRIORITY = 2; @@ -206,13 +205,19 @@ export async function init(): Promise<{wasm: BackendWasmModule}> { const simdSupported = await env().getAsync('WASM_HAS_SIMD_SUPPORT'); return new Promise((resolve, reject) => { const factoryConfig: WasmFactoryConfig = {}; - if (wasmPath != null) { - factoryConfig.locateFile = (path, prefix) => { - if (path.endsWith('.wasm')) { + factoryConfig.locateFile = (path, prefix) => { + if (path.endsWith('.wasm')) { + if (wasmPath != null) { return wasmPath; } - return prefix + path; - }; + if (simdSupported) { + return prefix + 'tfjs-backend-wasm-simd.wasm'; + } + return prefix + 'tfjs-backend-wasm.wasm'; + } + return prefix + path; + }; + if (wasmPath != null) { // use wasm instantiateWasm override when system fetch is not available. // For detail references // https://github.com/emscripten-core/emscripten/blob/2bca083cbbd5a4133db61fbd74d04f7feecfa907/tests/manual_wasm_instantiate.html#L170 @@ -220,8 +225,7 @@ export async function init(): Promise<{wasm: BackendWasmModule}> { factoryConfig.instantiateWasm = createInstantiateWasmFunc(wasmPath); } } - const wasm = simdSupported ? wasmFactorySimd(factoryConfig) : - wasmFactory(factoryConfig); + const wasm = wasmFactory(factoryConfig); const voidReturnType: string = null; // Using the tfjs namespace to avoid conflict with emscripten's API. wasm.tfjs = { diff --git a/tfjs-backend-wasm/src/cc/BUILD b/tfjs-backend-wasm/src/cc/BUILD index 7c877fcaa76..26124198cd4 100644 --- a/tfjs-backend-wasm/src/cc/BUILD +++ b/tfjs-backend-wasm/src/cc/BUILD @@ -30,7 +30,7 @@ cc_binary( ) cc_binary( - name = "tfjs-backend-wasm-simd.js", + name = "tfjs-backend-wasm-simd.wasm", srcs = ["backend.cc"] + KERNELS_WITH_KEEPALIVE, linkopts = [ "-s ALLOW_MEMORY_GROWTH=1", @@ -40,8 +40,6 @@ cc_binary( "-s EXIT_RUNTIME=0", "-s EXPORTED_FUNCTIONS='[\"_malloc\", \"_free\"]'", "-s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'", - "-s MODULARIZE=1", - "-s EXPORT_NAME=WasmBackendModuleSimd", "-s MALLOC=emmalloc", "-s SIMD=1", "-s STANDALONE_WASM=1", diff --git a/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-simd.d.ts b/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-simd.d.ts deleted file mode 100644 index bfac84c58c8..00000000000 --- a/tfjs-backend-wasm/wasm-out/tfjs-backend-wasm-simd.d.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - -export interface BackendWasmModuleSimd extends EmscriptenModule { - onRuntimeInitialized: () => void; - onAbort: (msg: string) => void; - // Using the tfjs namespace to avoid conflict with emscripten's API. - tfjs: { - init(): void, - registerTensor(id: number, size: number, memoryOffset: number): void, - // Disposes the data behind the data bucket. - disposeData(id: number): void, - // Disposes the backend and all of its associated data. - dispose(): void, - } -} - -export interface WasmFactoryConfigSimd { - locateFile?(path: string, prefix: string): string; - instantiateWasm?: Function; -} - -declare var moduleFactory: (settings: WasmFactoryConfigSimd) => - BackendWasmModuleSimd; -export default moduleFactory; From 02b48907156f72472502b8733599b5ca9b68e5c8 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Thu, 30 Jul 2020 10:53:53 -0400 Subject: [PATCH 30/70] rm --- e2e/benchmarks/index.html | 6 +- e2e/benchmarks/tf-backend-wasm.js | 3650 --- e2e/benchmarks/tf-core.js | 32471 ------------------- e2e/benchmarks/tfjs-backend-wasm-simd.wasm | Bin 214013 -> 0 bytes e2e/benchmarks/tfjs-backend-wasm.wasm | Bin 155531 -> 0 bytes 5 files changed, 2 insertions(+), 36125 deletions(-) delete mode 100644 e2e/benchmarks/tf-backend-wasm.js delete mode 100644 e2e/benchmarks/tf-core.js delete mode 100644 e2e/benchmarks/tfjs-backend-wasm-simd.wasm delete mode 100644 e2e/benchmarks/tfjs-backend-wasm.wasm diff --git a/e2e/benchmarks/index.html b/e2e/benchmarks/index.html index 304a93ba2d0..07dbdacf978 100644 --- a/e2e/benchmarks/index.html +++ b/e2e/benchmarks/index.html @@ -85,14 +85,12 @@

    TensorFlow.js Model Benchmark

    - - + - - + diff --git a/e2e/benchmarks/tf-backend-wasm.js b/e2e/benchmarks/tf-backend-wasm.js deleted file mode 100644 index cce7987e732..00000000000 --- a/e2e/benchmarks/tf-backend-wasm.js +++ /dev/null @@ -1,3650 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tensorflow/tfjs-core'), require('path'), require('fs')) : - typeof define === 'function' && define.amd ? define(['exports', '@tensorflow/tfjs-core', 'path', 'fs'], factory) : - (global = global || self, factory((global.tf = global.tf || {}, global.tf.wasm = global.tf.wasm || {}), global.tf, global.path, global.fs)); -}(this, (function (exports, tfjsCore, path, fs) { 'use strict'; - - path = path && path.hasOwnProperty('default') ? path['default'] : path; - fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // This enum must align with the enum defined in cc/backend.h. - var CppDType; - (function (CppDType) { - CppDType[CppDType["float32"] = 0] = "float32"; - CppDType[CppDType["int32"] = 1] = "int32"; - CppDType[CppDType["bool"] = 2] = "bool"; - CppDType[CppDType["string"] = 3] = "string"; - CppDType[CppDType["complex64"] = 4] = "complex64"; - })(CppDType || (CppDType = {})); - // Must match enum in cc/fusable_activations.h. - var FusableActivation; - (function (FusableActivation) { - FusableActivation[FusableActivation["linear"] = 0] = "linear"; - FusableActivation[FusableActivation["relu"] = 1] = "relu"; - FusableActivation[FusableActivation["relu6"] = 2] = "relu6"; - FusableActivation[FusableActivation["prelu"] = 3] = "prelu"; - })(FusableActivation || (FusableActivation = {})); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFusedMatMul; - function setup(backend) { - wasmFusedMatMul = backend.wasm.cwrap(tfjsCore._FusedMatMul, null /* void */, [ - 'number', - 'array', - 'number', - 'number', - 'array', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number' // out_id - ]); - } - function fusedBatchMatMul(args) { - const { inputs, backend, attrs } = args; - const { a, b, bias, preluActivationWeights } = inputs; - if (a.dtype !== 'float32' || b.dtype !== 'float32') { - throw new Error(`_FusedMatMul for non non-float32 tensors not yet supported.`); - } - const { transposeA, transposeB, activation } = attrs; - const aId = backend.dataIdMap.get(a.dataId).id; - const bId = backend.dataIdMap.get(b.dataId).id; - let biasId = 0; - if (bias != null) { - const biasData = backend.dataIdMap.get(bias.dataId); - if (biasData.shape.length !== 1) { - throw new Error(`_FusedMatMul only supports rank-1 bias but got ` + - `rank ${biasData.shape.length}.`); - } - biasId = biasData.id; - } - const preluActivationWeightsId = preluActivationWeights == null ? - 0 : - backend.dataIdMap.get(preluActivationWeights.dataId).id; - const fusedActivation = FusableActivation[activation]; - if (fusedActivation == null) { - throw new Error(`${activation} activation not yet supported for FusedConv2D ` + - `in the wasm backend.`); - } - const leftDim = transposeA ? a.shape[2] : a.shape[1]; - const rightDim = transposeB ? b.shape[1] : b.shape[2]; - const batchDim = a.shape[0]; - const out = backend.makeOutput([batchDim, leftDim, rightDim], a.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); - const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); - wasmFusedMatMul(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, transposeA, transposeB, fusedActivation, biasId, preluActivationWeightsId, outId); - return out; - } - const fusedMatMulConfig = { - kernelName: tfjsCore._FusedMatMul, - backendName: 'wasm', - setupFunc: setup, - kernelFunc: fusedBatchMatMul - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function createUnaryKernelConfig(kernelName) { - let wasmFunc; - function setupFunc(backend) { - wasmFunc = - backend.wasm.cwrap(kernelName, null /* void */, ['number', 'number']); - } - function kernelFunc(args) { - const { backend, inputs: { x } } = args; - const xId = backend.dataIdMap.get(x.dataId).id; - const out = backend.makeOutput(x.shape, x.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(out.shape) === 0) { - return out; - } - wasmFunc(xId, outId); - return out; - } - return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const absConfig = createUnaryKernelConfig(tfjsCore.Abs); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function createBinaryKernelConfig(kernelName, supportsFullBroadcast, dtype) { - let wasmFunc; - function setupFunc(backend) { - wasmFunc = backend.wasm.cwrap(kernelName, null /* void */, [ - 'number', - 'array', - 'number', - 'number', - 'array', - 'number', - 'number', - 'number' // out_id - ]); - } - function kernelFunc(args) { - const { backend, inputs } = args; - const { a, b } = inputs; - const aId = backend.dataIdMap.get(a.dataId).id; - const bId = backend.dataIdMap.get(b.dataId).id; - const outputType = dtype != null ? dtype : a.dtype; - const newShape = tfjsCore.backend_util.assertAndGetBroadcastShape(a.shape, b.shape); - const out = backend.makeOutput(newShape, outputType); - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(newShape) === 0) { - return out; - } - const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); - const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); - const outId = backend.dataIdMap.get(out.dataId).id; - const kernelFunc = () => wasmFunc(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, CppDType[a.dtype], outId); - // Currently only some float operations support full broadcast. - if (supportsFullBroadcast && a.dtype === 'float32') { - kernelFunc(); - return out; - } - const aBroadcastDims = tfjsCore.backend_util.getBroadcastDims(a.shape, newShape); - const bBroadcastDims = tfjsCore.backend_util.getBroadcastDims(b.shape, newShape); - const loopsOverAllOfA = aBroadcastDims.every((v, i) => v === i); - const loopsOverAllOfB = bBroadcastDims.every((v, i) => v === i); - if (loopsOverAllOfA && loopsOverAllOfB) { - kernelFunc(); - return out; - } - else { - throw new Error(`Broadcasting along outer dims is not yet ` + - `supported for ${a.dtype} ${kernelName}.`); - } - } - return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast = true; - const addConfig = createBinaryKernelConfig(tfjsCore.Add, supportsFullBroadcast); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc; - function setupFunc(backend) { - wasmFunc = backend.wasm.cwrap(tfjsCore.AddN, null /* void */, [ - 'array', - 'number', - 'number', - 'number', - ]); - } - function addn(args) { - const { inputs, backend } = args; - const out = backend.makeOutput(inputs[0].shape, inputs[0].dtype); - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(out.shape) === 0) { - return out; - } - const inputIds = inputs.map(x => backend.dataIdMap.get(x.dataId).id); - const inputIdsBytes = new Uint8Array(new Int32Array(inputIds).buffer); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmFunc(inputIdsBytes, inputIds.length, CppDType[out.dtype], outId); - return out; - } - const addNConfig = { - kernelName: tfjsCore.AddN, - backendName: 'wasm', - setupFunc, - kernelFunc: addn, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function identity(args) { - const { inputs: { x }, backend } = args; - const out = backend.makeOutput(x.shape, x.dtype); - const inVals = backend.typedArrayFromHeap(x); - const outVals = backend.typedArrayFromHeap(out); - outVals.set(inVals); - return out; - } - const identityConfig = { - kernelName: tfjsCore.Identity, - backendName: 'wasm', - kernelFunc: identity, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmTranspose; - function setup$1(backend) { - wasmTranspose = backend.wasm.cwrap(tfjsCore.Transpose, null /* void */, [ - 'number', - 'array', - 'number', - 'number', - 'number', - 'array', - 'number', - ]); - } - function transpose(args) { - const { inputs, backend, attrs } = args; - // Reduce any dimensions with size one. Lower-rank transpose kernel performs - // better due to simpler memory access pattern. - const [reducedShape, perm] = removeOneSizeDims(inputs.x.shape, attrs.perm); - let permIsNoOp = true; - for (let i = 0; i < perm.length; i++) { - if (perm[i] !== i) { - permIsNoOp = false; - } - } - const outShape = computeOutShape(inputs.x.shape, attrs.perm); - const x = { - dataId: inputs.x.dataId, - shape: reducedShape, - dtype: inputs.x.dtype - }; - if (permIsNoOp) { - const cloned = identity({ inputs, backend }); - cloned.shape = outShape; - return cloned; - } - const out = backend.makeOutput(outShape, x.dtype); - const xId = backend.dataIdMap.get(x.dataId).id; - const outId = backend.dataIdMap.get(out.dataId).id; - const permBytes = new Uint8Array(new Int32Array(perm).buffer); - const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); - wasmTranspose(xId, xShapeBytes, x.shape.length, CppDType[x.dtype], outId, permBytes, perm.length); - return out; - } - function computeOutShape(inShape, perm) { - const outShape = new Array(inShape.length); - for (let i = 0; i < outShape.length; i++) { - outShape[i] = inShape[perm[i]]; - } - return outShape; - } - function removeOneSizeDims(shape, perm) { - const newShape = []; - const newPerm = []; - for (let i = 0; i < shape.length; ++i) { - if (shape[i] !== 1) { - newShape.push(shape[i]); - } - if (shape[perm[i]] !== 1) { - newPerm.push(perm[i]); - } - } - for (let i = 0; i < newPerm.length; ++i) { - let minValIdx = -1; - for (let j = 0; j < newPerm.length; ++j) { - if (newPerm[j] >= i && - (minValIdx === -1 || newPerm[minValIdx] > newPerm[j])) { - minValIdx = j; - } - } - newPerm[minValIdx] = i; - } - return [newShape, newPerm]; - } - const transposeConfig = { - kernelName: tfjsCore.Transpose, - backendName: 'wasm', - kernelFunc: transpose, - setupFunc: setup$1, - }; - - /** - * @license - * Copyright 2020 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Compute permutation axes and do a transpose if necessary. - * - * Used by reduction ops. - * @param x input TensorInfo - * @param axis reduction axes - * @param backend wasm backend instance - */ - function permuteAxesAndTranspose(x, axis, backend) { - const xShape = x.shape; - const xRank = x.shape.length; - const originalAxes = tfjsCore.util.parseAxisParam(axis, xShape); - let axes = originalAxes; - const permutedAxes = tfjsCore.backend_util.getAxesPermutation(axes, xRank); - let xTransposed = null; - let inputWasTransposed = false; - if (permutedAxes != null) { - const newShape = new Array(xRank); - for (let i = 0; i < newShape.length; i++) { - newShape[i] = xShape[permutedAxes[i]]; - } - axes = tfjsCore.backend_util.getInnerMostAxes(axes.length, xRank); - xTransposed = - transpose({ inputs: { x }, attrs: { perm: permutedAxes }, backend }); - const xId = backend.dataIdMap.get(x.dataId).id; - const transposedId = backend.dataIdMap.get(xTransposed.dataId).id; - if (transposedId !== xId) { - inputWasTransposed = true; - } - } - return { transposed: xTransposed, originalAxes, axes, inputWasTransposed }; - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$1; - function setup$2(backend) { - wasmFunc$1 = backend.wasm.cwrap(tfjsCore.ArgMax, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number' // out_id - ]); - } - function argmax(args) { - const { backend, inputs, attrs } = args; - const { axis } = attrs; - const { x } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - let inputId = xId; - let input = x; - const { transposed, axes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); - if (inputWasTransposed) { - const transposedId = backend.dataIdMap.get(transposed.dataId).id; - if (transposedId !== xId) { - // transpose was not a no-op. We will need to dispose of this - // once we are done. - input = transposed; - inputId = transposedId; - } - } - const outShape = input.shape.slice(0, -1); - const out = backend.makeOutput(outShape, 'int32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const outerSize = tfjsCore.util.sizeFromShape(out.shape); - const innerSize = input.shape[axes[0]]; - wasmFunc$1(inputId, CppDType[input.dtype], outerSize, innerSize, outId); - if (inputWasTransposed) { - // dispose of the transposed tensor. - backend.disposeData(transposed.dataId); - } - return out; - } - const argMaxConfig = { - kernelName: tfjsCore.ArgMax, - backendName: 'wasm', - kernelFunc: argmax, - setupFunc: setup$2 - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmAvgPool; - function setup$3(backend) { - wasmAvgPool = backend.wasm.cwrap(tfjsCore.AvgPool, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function avgPool(args) { - const { inputs, attrs, backend } = args; - const x = inputs.x; - const xId = backend.dataIdMap.get(x.dataId).id; - const { filterSize, strides, pad, dimRoundingMode } = attrs; - const convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const channels = convInfo.inChannels; - if (convInfo.dataFormat !== 'channelsLast') { - throw new Error(`wasm backend does not support dataFormat:'` + - `${convInfo.dataFormat}'. Please use 'channelsLast'.`); - } - if (convInfo.dilationWidth !== 1 || convInfo.dilationHeight !== 1) { - throw new Error(`was backend only supports average pooling with dilation = [1, 1], ` + - `got [${convInfo.dilationHeight}, ${convInfo.dilationWidth}].`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmAvgPool(xId, x.shape[0], x.shape[1], x.shape[2], filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, strideHeight, strideWidth, channels, outId); - return out; - } - const avgPoolConfig = { - kernelName: tfjsCore.AvgPool, - backendName: 'wasm', - setupFunc: setup$3, - kernelFunc: avgPool - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmBatchMatMul; - function setup$4(backend) { - wasmBatchMatMul = backend.wasm.cwrap(tfjsCore.BatchMatMul, null /* void */, [ - 'number', - 'array', - 'number', - 'number', - 'array', - 'number', - 'number', - 'number', - 'number' // out_id - ]); - } - function batchMatMul(args) { - const { inputs, backend, attrs } = args; - const { a, b } = inputs; - if (a.dtype !== 'float32' || b.dtype !== 'float32') { - throw new Error(`BatchMatMul for non non-float32 tensors not yet supported.`); - } - const { transposeA, transposeB } = attrs; - const aId = backend.dataIdMap.get(a.dataId).id; - const bId = backend.dataIdMap.get(b.dataId).id; - const leftDim = transposeA ? a.shape[2] : a.shape[1]; - const rightDim = transposeB ? b.shape[1] : b.shape[2]; - const batchDim = a.shape[0]; - const out = backend.makeOutput([batchDim, leftDim, rightDim], a.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); - const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); - wasmBatchMatMul(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, transposeA, transposeB, outId); - return out; - } - const batchMatMulConfig = { - kernelName: tfjsCore.BatchMatMul, - backendName: 'wasm', - setupFunc: setup$4, - kernelFunc: batchMatMul - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function cast(args) { - const { inputs: { x }, attrs: { dtype }, backend } = args; - const out = backend.makeOutput(x.shape, dtype); - const inVals = backend.typedArrayFromHeap(x); - const outVals = backend.typedArrayFromHeap(out); - outVals.set(inVals); - return out; - } - const castConfig = { - kernelName: tfjsCore.Cast, - backendName: 'wasm', - kernelFunc: cast, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmClip; - function setup$5(backend) { - wasmClip = backend.wasm.cwrap(tfjsCore.ClipByValue, null /* void */, [ - 'number', - 'number', - 'number', - 'number' // out_id - ]); - } - function clip(args) { - const { inputs, backend, attrs } = args; - const { x } = inputs; - const { clipValueMin, clipValueMax } = attrs; - const xId = backend.dataIdMap.get(x.dataId).id; - const out = backend.makeOutput(x.shape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmClip(xId, clipValueMin, clipValueMax, outId); - return out; - } - const clipByValueConfig = { - kernelName: tfjsCore.ClipByValue, - backendName: 'wasm', - setupFunc: setup$5, - kernelFunc: clip - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function concat(args) { - const { inputs, backend } = args; - const axis = tfjsCore.util.parseAxisParam(args.attrs.axis, inputs[0].shape)[0]; - const outShape = tfjsCore.backend_util.computeOutShape(inputs.map(t => t.shape), axis); - const out = backend.makeOutput(outShape, inputs[0].dtype); - const batchDim = tfjsCore.util.sizeFromShape(inputs[0].shape.slice(0, axis)); - let sumInnerDims = 0; - const innerDims = inputs.map(input => { - const innerDim = tfjsCore.util.sizeFromShape(input.shape.slice(axis)); - sumInnerDims += innerDim; - return innerDim; - }); - const inVals = inputs.map(input => backend.typedArrayFromHeap(input)); - const outVals = backend.typedArrayFromHeap(out); - for (let b = 0; b < batchDim; b++) { - let outOffset = b * sumInnerDims; - for (let i = 0; i < inVals.length; i++) { - const innerDim = innerDims[i]; - const inOffset = b * innerDim; - const vals = inVals[i].subarray(inOffset, inOffset + innerDim); - outVals.set(vals, outOffset); - outOffset += innerDim; - } - } - return out; - } - const concatConfig = { - kernelName: tfjsCore.Concat, - backendName: 'wasm', - kernelFunc: concat, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmConv2d; - function setup$6(backend) { - wasmConv2d = backend.wasm.cwrap(tfjsCore.Conv2D, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function conv2d(args) { - const { inputs, attrs, backend } = args; - const { x, filter } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - const filterId = backend.dataIdMap.get(filter.dataId).id; - const { strides, dilations, pad, dimRoundingMode, dataFormat } = attrs; - const $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat); - const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const dilationHeight = convInfo.dilationHeight; - const dilationWidth = convInfo.dilationWidth; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const inputChannels = convInfo.inChannels; - const outputChannels = convInfo.outChannels; - const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; - if (convInfo.dataFormat !== 'channelsLast') { - throw new Error(`wasm backend Conv2D does not support dataFormat:'` + - `${convInfo.dataFormat}'. Please use 'channelsLast'.`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmConv2d(xId, x.shape[0], x.shape[1], x.shape[2], filterId, filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); - return out; - } - const conv2DConfig = { - kernelName: tfjsCore.Conv2D, - backendName: 'wasm', - setupFunc: setup$6, - kernelFunc: conv2d - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmConv2DBackpropInput; - function setup$7(backend) { - wasmConv2DBackpropInput = backend.wasm.cwrap(tfjsCore.Conv2DBackpropInput, null, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function conv2DBackpropInput(args) { - const { backend, inputs, attrs } = args; - const { dy, filter } = inputs; - const { strides, pad, dataFormat, dimRoundingMode, inputShape } = attrs; - const dilations = 1; - const $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat); - const convInfo = tfjsCore.backend_util.computeConv2DInfo(inputShape, filter.shape, strides, dilations, pad, dimRoundingMode, false /* depthwise */, $dataFormat); - const { batchSize, filterHeight, filterWidth, inChannels, inHeight, inWidth, outChannels, outHeight, outWidth, strideHeight, strideWidth } = convInfo; - const topPad = filterHeight - 1 - convInfo.padInfo.top; - const leftPad = filterWidth - 1 - convInfo.padInfo.left; - const isChannelsLast = convInfo.dataFormat === 'channelsLast'; - const dxStrides = tfjsCore.util.computeStrides(convInfo.inShape); - const dyStrides = tfjsCore.util.computeStrides(dy.shape); - const [fltS0, fltS1, fltS2] = tfjsCore.util.computeStrides(filter.shape); - const xBatchStride = dxStrides[0]; - const xRowStride = isChannelsLast ? dxStrides[1] : dxStrides[2]; - const xColStride = isChannelsLast ? dxStrides[2] : 1; - const xChannelStride = isChannelsLast ? 1 : dxStrides[1]; - const yBatchStride = dyStrides[0]; - const yRowStride = isChannelsLast ? dyStrides[1] : dyStrides[2]; - const yColStride = isChannelsLast ? dyStrides[2] : 1; - const yChannelStride = isChannelsLast ? 1 : dyStrides[1]; - const out = backend.makeOutput(convInfo.inShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const dyId = backend.dataIdMap.get(dy.dataId).id; - const filterId = backend.dataIdMap.get(filter.dataId).id; - wasmConv2DBackpropInput(dyId, filterId, batchSize, filterHeight, filterWidth, inHeight, inWidth, inChannels, outHeight, outWidth, outChannels, strideHeight, strideWidth, topPad, leftPad, fltS0, fltS1, fltS2, xBatchStride, xRowStride, xColStride, xChannelStride, yBatchStride, yRowStride, yColStride, yChannelStride, outId); - return out; - } - const conv2DBackpropInputConfig = { - kernelName: tfjsCore.Conv2DBackpropInput, - backendName: 'wasm', - setupFunc: setup$7, - kernelFunc: conv2DBackpropInput - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const cosConfig = createUnaryKernelConfig(tfjsCore.Cos); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // Must match enum in CropAndResize.cc - var InterpolationMethod; - (function (InterpolationMethod) { - InterpolationMethod[InterpolationMethod["bilinear"] = 0] = "bilinear"; - InterpolationMethod[InterpolationMethod["nearest"] = 1] = "nearest"; - })(InterpolationMethod || (InterpolationMethod = {})); - let wasmCropAndResize; - function setup$8(backend) { - wasmCropAndResize = backend.wasm.cwrap(tfjsCore.CropAndResize, null /*void*/, [ - 'number', - 'number', - 'number', - 'number', - 'array', - 'number', - 'number', - 'number', - 'number', - 'number' // out id - ]); - } - function cropAndResize(args) { - const { backend, inputs, attrs } = args; - const { method, extrapolationValue, cropSize } = attrs; - const { image, boxes, boxInd } = inputs; - const numBoxes = boxes.shape[0]; - const [cropHeight, cropWidth] = cropSize; - const outShape = [numBoxes, cropHeight, cropWidth, image.shape[3]]; - let imagesData = backend.dataIdMap.get(image.dataId); - let castedData; - if (image.dtype !== 'float32') { - castedData = cast({ backend, inputs: { x: image }, attrs: { dtype: 'float32' } }); - imagesData = backend.dataIdMap.get(castedData.dataId); - } - const imagesId = imagesData.id; - const boxesId = backend.dataIdMap.get(boxes.dataId).id; - const boxIndId = backend.dataIdMap.get(boxInd.dataId).id; - const out = backend.makeOutput(outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const imagesShapeBytes = new Uint8Array(new Int32Array(image.shape).buffer); - wasmCropAndResize(imagesId, boxesId, boxIndId, numBoxes, imagesShapeBytes, cropHeight, cropWidth, InterpolationMethod[method], extrapolationValue, outId); - if (castedData != null) { - backend.disposeData(castedData.dataId); - } - return out; - } - const cropAndResizeConfig = { - kernelName: tfjsCore.CropAndResize, - backendName: 'wasm', - setupFunc: setup$8, - kernelFunc: cropAndResize - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmDepthwiseConv2d; - function setup$9(backend) { - wasmDepthwiseConv2d = - backend.wasm.cwrap(tfjsCore.DepthwiseConv2dNative, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function depthwiseConv2d(args) { - const { inputs, attrs, backend } = args; - const { x, filter } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - const filterId = backend.dataIdMap.get(filter.dataId).id; - const { strides, dilations, pad, dimRoundingMode } = attrs; - const $dilations = dilations == null ? [1, 1] : dilations; - const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, $dilations, pad, dimRoundingMode, true /* depthwise */); - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const dilationHeight = convInfo.dilationHeight; - const dilationWidth = convInfo.dilationWidth; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const inputChannels = convInfo.inChannels; - const outputChannels = convInfo.outChannels; - const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; - if (convInfo.dataFormat !== 'channelsLast') { - throw new Error(`wasm backend DepthwiseConv2dNative does not support dataFormat:'` + - `${convInfo.dataFormat}'. Please use 'channelsLast'.`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmDepthwiseConv2d(xId, x.shape[0], x.shape[1], x.shape[2], filterId, filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); - return out; - } - const depthwiseConv2DNativeConfig = { - kernelName: tfjsCore.DepthwiseConv2dNative, - backendName: 'wasm', - setupFunc: setup$9, - kernelFunc: depthwiseConv2d - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$1 = true; - const divConfig = createBinaryKernelConfig(tfjsCore.Div, supportsFullBroadcast$1); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$2 = false; - const equalConfig = createBinaryKernelConfig(tfjsCore.Equal, supportsFullBroadcast$2, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const expConfig = createUnaryKernelConfig(tfjsCore.Exp); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function fill(args) { - const { attrs: { shape, value, dtype }, backend } = args; - const out = backend.makeOutput(shape, dtype); - const outVals = backend.typedArrayFromHeap(out); - outVals.fill(value); - return out; - } - const fillConfig = { - kernelName: tfjsCore.Fill, - backendName: 'wasm', - kernelFunc: fill, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$3 = false; - const floorDivConfig = createBinaryKernelConfig(tfjsCore.FloorDiv, supportsFullBroadcast$3); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmBatchNorm; - function setup$a(backend) { - wasmBatchNorm = backend.wasm.cwrap(tfjsCore.FusedBatchNorm, null /* void */, ['number', 'number', 'number', 'number', 'number', 'number', 'number']); - } - function fusedBatchNorm(args) { - const { backend, inputs, attrs } = args; - const { varianceEpsilon } = attrs; - const { x, mean, variance, offset, scale } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - const meanId = backend.dataIdMap.get(mean.dataId).id; - const varianceId = backend.dataIdMap.get(variance.dataId).id; - const offsetId = offset != null ? backend.dataIdMap.get(offset.dataId).id : 0; - const scaleId = scale != null ? backend.dataIdMap.get(scale.dataId).id : 0; - const out = backend.makeOutput(x.shape, x.dtype); - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(x.shape) === 0) { - return out; - } - const outId = backend.dataIdMap.get(out.dataId).id; - wasmBatchNorm(xId, meanId, varianceId, offsetId, scaleId, varianceEpsilon, outId); - return out; - } - const fusedBatchNormConfig = { - kernelName: tfjsCore.FusedBatchNorm, - backendName: 'wasm', - setupFunc: setup$a, - kernelFunc: fusedBatchNorm - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFusedConv2d; - function setup$b(backend) { - wasmFusedConv2d = backend.wasm.cwrap(tfjsCore.FusedConv2D, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function fusedConv2d(args) { - const { inputs, attrs, backend } = args; - const { x, filter, bias, preluActivationWeights } = inputs; - const { strides, pad, dilations, dataFormat, dimRoundingMode, activation } = attrs; - const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode); - const fusedActivation = FusableActivation[activation]; - if (fusedActivation == null) { - throw new Error(`${activation} activation not yet supported for FusedConv2D ` + - `in the wasm backend.`); - } - const xId = backend.dataIdMap.get(x.dataId).id; - const filterId = backend.dataIdMap.get(filter.dataId).id; - const outputChannels = convInfo.outChannels; - let biasId = 0; - if (bias != null) { - const biasData = backend.dataIdMap.get(bias.dataId); - if (biasData.shape.length !== 1) { - throw new Error(`FusedConv2D only supports rank-1 bias but got ` + - `rank ${biasData.shape.length}.`); - } - if (biasData.shape[0] !== outputChannels) { - throw new Error(`FusedConv2D bias shape (${biasData.shape}) does not ` + - `match the number of output channels (${outputChannels})`); - } - biasId = biasData.id; - } - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const dilationHeight = convInfo.dilationHeight; - const dilationWidth = convInfo.dilationWidth; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const inputChannels = convInfo.inChannels; - const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; - const batchSize = convInfo.batchSize; - const inHeight = convInfo.inHeight; - const inWidth = convInfo.inWidth; - if (dataFormat !== 'NHWC') { - throw new Error(`wasm backend FusedConv2D does not support dataFormat:'` + - `${dataFormat}'. Please use 'NHWC'.`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const preluActivationWeightsId = preluActivationWeights == null ? - 0 : - backend.dataIdMap.get(preluActivationWeights.dataId).id; - wasmFusedConv2d(xId, batchSize, inHeight, inWidth, filterId, filterHeight, filterWidth, biasId, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, fusedActivation, preluActivationWeightsId, outId); - return out; - } - const fusedConv2DConfig = { - kernelName: tfjsCore.FusedConv2D, - backendName: 'wasm', - setupFunc: setup$b, - kernelFunc: fusedConv2d - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFusedDepthwiseConv2d; - function setup$c(backend) { - wasmFusedDepthwiseConv2d = - backend.wasm.cwrap(tfjsCore.FusedDepthwiseConv2D, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function fusedDepthwiseConv2d(args) { - const { inputs, attrs, backend } = args; - const { x, filter, bias, preluActivationWeights } = inputs; - const { strides, pad, dilations, dataFormat, dimRoundingMode, activation } = attrs; - const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, true /* depthwise */); - const fusedActivation = FusableActivation[activation]; - if (fusedActivation == null) { - throw new Error(`${activation} activation not yet supported for FusedDepthwiseConv2D ` + - `in the wasm backend.`); - } - const xId = backend.dataIdMap.get(x.dataId).id; - const filterId = backend.dataIdMap.get(filter.dataId).id; - const outputChannels = convInfo.outChannels; - let biasId = 0; - if (bias != null) { - const biasData = backend.dataIdMap.get(bias.dataId); - if (biasData.shape.length !== 1) { - throw new Error(`FusedDepthwiseConv2D only supports rank-1 bias but got ` + - `rank ${biasData.shape.length}.`); - } - if (biasData.shape[0] !== outputChannels) { - throw new Error(`FusedDepthwiseConv2D bias shape (${biasData.shape}) does not ` + - `match the number of output channels (${outputChannels})`); - } - biasId = biasData.id; - } - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const dilationHeight = convInfo.dilationHeight; - const dilationWidth = convInfo.dilationWidth; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const inputChannels = convInfo.inChannels; - const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; - const batchSize = convInfo.batchSize; - const inHeight = convInfo.inHeight; - const inWidth = convInfo.inWidth; - if (dataFormat !== 'NHWC') { - throw new Error(`wasm backend FusedDepthwiseConv2D does not support dataFormat:'` + - `${dataFormat}'. Please use 'NHWC'.`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const preluActivationWeightsId = preluActivationWeights == null ? - 0 : - backend.dataIdMap.get(preluActivationWeights.dataId).id; - wasmFusedDepthwiseConv2d(xId, batchSize, inHeight, inWidth, filterId, filterHeight, filterWidth, biasId, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, fusedActivation, preluActivationWeightsId, outId); - return out; - } - const fusedDepthwiseConv2DConfig = { - kernelName: tfjsCore.FusedDepthwiseConv2D, - backendName: 'wasm', - setupFunc: setup$c, - kernelFunc: fusedDepthwiseConv2d - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmGatherNd; - function setup$d(backend) { - wasmGatherNd = backend.wasm.cwrap(tfjsCore.GatherNd, null /*void*/, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'array', - 'number' // outId - ]); - } - function gatherNd(args) { - const { backend, inputs } = args; - const { params, indices } = inputs; - const [resultShape, numSlices, sliceSize, strides] = tfjsCore.gather_util.prepareAndValidate(params, indices); - const out = backend.makeOutput(resultShape, params.dtype); - if (numSlices === 0) { - return out; - } - const indicesShape = indices.shape; - const sliceRank = indicesShape[indicesShape.length - 1]; - const xData = backend.dataIdMap.get(params.dataId); - const xId = xData.id; - const indicesData = backend.dataIdMap.get(indices.dataId); - const indicesId = indicesData.id; - const stridesBytes = new Uint8Array(new Int32Array(strides).buffer); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmGatherNd(xId, CppDType[params.dtype], indicesId, numSlices, sliceRank, sliceSize, stridesBytes, outId); - return out; - } - const gatherNdConfig = { - kernelName: tfjsCore.GatherNd, - backendName: 'wasm', - setupFunc: setup$d, - kernelFunc: gatherNd - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmGather; - function setup$e(backend) { - wasmGather = backend.wasm.cwrap('Gather', null /*void*/, [ - 'number', - 'number', - 'array', - 'number', - 'number', - 'number', - 'array', - 'number' // outId - ]); - } - function gatherV2(args) { - const { backend, inputs, attrs } = args; - const { x, indices } = inputs; - const { axis } = attrs; - const newShape = x.shape.slice(); - newShape[axis] = tfjsCore.util.sizeFromShape(indices.shape); - const stridesSize = x.shape.length - 1; - const out = backend.makeOutput(newShape, x.dtype); - if (tfjsCore.util.sizeFromShape(x.shape) === 0) { - return out; - } - const xData = backend.dataIdMap.get(x.dataId); - const xId = xData.id; - const indicesData = backend.dataIdMap.get(indices.dataId); - const indicesId = indicesData.id; - const outId = backend.dataIdMap.get(out.dataId).id; - const xStridesBytes = new Uint8Array(new Int32Array(tfjsCore.util.computeStrides(x.shape)).buffer); - const outStridesBytes = new Uint8Array(new Int32Array(tfjsCore.util.computeStrides(newShape)).buffer); - wasmGather(xId, CppDType[x.dtype], xStridesBytes, stridesSize, indicesId, axis, outStridesBytes, outId); - // reshape - const parsedAxis = tfjsCore.util.parseAxisParam(axis, x.shape)[0]; - const shapeInfo = tfjsCore.backend_util.segment_util.collectGatherOpShapeInfo(x, indices, parsedAxis); - out.shape = shapeInfo.outputShape; - return out; - } - const gatherV2Config = { - kernelName: tfjsCore.GatherV2, - backendName: 'wasm', - setupFunc: setup$e, - kernelFunc: gatherV2 - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$4 = false; - const greaterConfig = createBinaryKernelConfig(tfjsCore.Greater, supportsFullBroadcast$4, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$5 = false; - const greaterEqualConfig = createBinaryKernelConfig(tfjsCore.GreaterEqual, supportsFullBroadcast$5, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$6 = false; - const lessConfig = createBinaryKernelConfig(tfjsCore.Less, supportsFullBroadcast$6, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$7 = false; - const lessEqualConfig = createBinaryKernelConfig(tfjsCore.LessEqual, supportsFullBroadcast$7, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const logConfig = createUnaryKernelConfig(tfjsCore.Log); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$8 = false; - const logicalAndConfig = createBinaryKernelConfig(tfjsCore.LogicalAnd, supportsFullBroadcast$8, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmMax; - function setup$f(backend) { - wasmMax = backend.wasm.cwrap(tfjsCore.Max, null /*void*/, ['number, number, number']); - } - function max(args) { - const { backend, inputs, attrs } = args; - const { reductionIndices: axis, keepDims } = attrs; - const { x } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - let inputId = xId; - let input = x; - const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); - if (inputWasTransposed) { - const transposedId = backend.dataIdMap.get(transposed.dataId).id; - input = transposed; - inputId = transposedId; - } - const inputRank = input.shape.length; - tfjsCore.backend_util.assertAxesAreInnerMostDims('max', axes, inputRank); - const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, axes); - const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); - const out = backend.makeOutput(outShape, x.dtype); - if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { - const outId = backend.dataIdMap.get(out.dataId).id; - wasmMax(inputId, reduceSize, outId); - } - if (inputWasTransposed) { - // dispose of the transposed tensor. - backend.disposeData(transposed.dataId); - } - if (keepDims) { - // reshape - const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); - out.shape = newShape; - } - return out; - } - const maxConfig = { - kernelName: tfjsCore.Max, - backendName: 'wasm', - setupFunc: setup$f, - kernelFunc: max - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$9 = false; - const maximumConfig = createBinaryKernelConfig(tfjsCore.Maximum, supportsFullBroadcast$9); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmMaxPool; - function setup$g(backend) { - wasmMaxPool = backend.wasm.cwrap(tfjsCore.MaxPool, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function maxPool(args) { - const { inputs, attrs, backend } = args; - const x = inputs.x; - const xId = backend.dataIdMap.get(x.dataId).id; - const { filterSize, strides, pad, dimRoundingMode } = attrs; - const convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const dilationHeight = convInfo.dilationHeight; - const dilationWidth = convInfo.dilationWidth; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const inputChannels = convInfo.inChannels; - const outputChannels = convInfo.outChannels; - if (convInfo.dataFormat !== 'channelsLast') { - throw new Error(`wasm backend does not support dataFormat:'` + - `${convInfo.dataFormat}'. Please use 'channelsLast'.`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmMaxPool(xId, x.shape[0], x.shape[1], x.shape[2], filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); - return out; - } - const maxPoolConfig = { - kernelName: tfjsCore.MaxPool, - backendName: 'wasm', - setupFunc: setup$g, - kernelFunc: maxPool - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmMin; - function setup$h(backend) { - wasmMin = backend.wasm.cwrap(tfjsCore.Min, null /*void*/, ['number, number, number']); - } - function min(args) { - const { backend, inputs, attrs } = args; - const { axis, keepDims } = attrs; - const { x } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - let inputId = xId; - let input = x; - const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); - if (inputWasTransposed) { - const transposedId = backend.dataIdMap.get(transposed.dataId).id; - if (transposedId !== xId) { - // transpose was not a no-op. We will need to dispose of this - // once we are done. - input = transposed; - inputId = transposedId; - } - } - const inputRank = input.shape.length; - tfjsCore.backend_util.assertAxesAreInnerMostDims('min', axes, inputRank); - const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, axes); - const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); - const out = backend.makeOutput(outShape, input.dtype); - if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { - const outId = backend.dataIdMap.get(out.dataId).id; - wasmMin(inputId, reduceSize, outId); - } - if (inputWasTransposed) { - // dispose of the transposed tensor. - backend.disposeData(transposed.dataId); - } - if (keepDims) { - // reshape - const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); - out.shape = newShape; - } - return out; - } - const minConfig = { - kernelName: tfjsCore.Min, - backendName: 'wasm', - setupFunc: setup$h, - kernelFunc: min - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$a = false; - const minimumConfig = createBinaryKernelConfig(tfjsCore.Minimum, supportsFullBroadcast$a); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$b = true; - const multiplyConfig = createBinaryKernelConfig(tfjsCore.Multiply, supportsFullBroadcast$b); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const negateConfig = createUnaryKernelConfig(tfjsCore.Negate); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Parse the result of the c++ method, which has the shape equivalent to - * `Result`. - */ - function parseResultStruct(backend, resOffset) { - const result = new Int32Array(backend.wasm.HEAPU8.buffer, resOffset, 4); - const pSelectedIndices = result[0]; - const selectedSize = result[1]; - const pSelectedScores = result[2]; - const pValidOutputs = result[3]; - // Since the result was allocated on the heap, we have to delete it. - backend.wasm._free(resOffset); - return { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs }; - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$2; - function setup$i(backend) { - wasmFunc$2 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV3, 'number', // Result* - [ - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function kernelFunc(args) { - const { backend, inputs, attrs } = args; - const { iouThreshold, maxOutputSize, scoreThreshold } = attrs; - const { boxes, scores } = inputs; - const boxesId = backend.dataIdMap.get(boxes.dataId).id; - const scoresId = backend.dataIdMap.get(scores.dataId).id; - const resOffset = wasmFunc$2(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold); - const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); - // Since we are not using scores for V3, we have to delete it from the heap. - backend.wasm._free(pSelectedScores); - backend.wasm._free(pValidOutputs); - const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); - return selectedIndicesTensor; - } - const nonMaxSuppressionV3Config = { - kernelName: tfjsCore.NonMaxSuppressionV3, - backendName: 'wasm', - setupFunc: setup$i, - kernelFunc: kernelFunc, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$3; - function setup$j(backend) { - wasmFunc$3 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV4, 'number', // Result* - [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'bool', - ]); - } - function nonMaxSuppressionV4(args) { - const { backend, inputs, attrs } = args; - const { iouThreshold, maxOutputSize, scoreThreshold, padToMaxOutputSize } = attrs; - const { boxes, scores } = inputs; - const boxesId = backend.dataIdMap.get(boxes.dataId).id; - const scoresId = backend.dataIdMap.get(scores.dataId).id; - const resOffset = wasmFunc$3(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize); - const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); - // Since we are not using scores for V4, we have to delete it from the heap. - backend.wasm._free(pSelectedScores); - const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); - const validOutputsTensor = backend.makeOutput([], 'int32', pValidOutputs); - return [selectedIndicesTensor, validOutputsTensor]; - } - const nonMaxSuppressionV4Config = { - kernelName: tfjsCore.NonMaxSuppressionV4, - backendName: 'wasm', - setupFunc: setup$j, - kernelFunc: nonMaxSuppressionV4, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$4; - function setup$k(backend) { - wasmFunc$4 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV5, 'number', // Result* - [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function kernelFunc$1(args) { - const { backend, inputs, attrs } = args; - const { iouThreshold, maxOutputSize, scoreThreshold, softNmsSigma } = attrs; - const { boxes, scores } = inputs; - const boxesId = backend.dataIdMap.get(boxes.dataId).id; - const scoresId = backend.dataIdMap.get(scores.dataId).id; - const resOffset = wasmFunc$4(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma); - const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); - // Since we are not using validOutputs for V5, we have to delete it from the - // heap. - backend.wasm._free(pValidOutputs); - const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); - const selectedScoresTensor = backend.makeOutput([selectedSize], 'float32', pSelectedScores); - return [selectedIndicesTensor, selectedScoresTensor]; - } - const nonMaxSuppressionV5Config = { - kernelName: tfjsCore.NonMaxSuppressionV5, - backendName: 'wasm', - setupFunc: setup$k, - kernelFunc: kernelFunc$1, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$c = false; - const notEqualConfig = createBinaryKernelConfig(tfjsCore.NotEqual, supportsFullBroadcast$c, 'bool'); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmOneHot; - function setup$l(backend) { - wasmOneHot = backend.wasm.cwrap(tfjsCore.OneHot, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number' // out_id - ]); - } - function oneHot(args) { - const { inputs, backend, attrs } = args; - const { indices } = inputs; - const { depth, onValue, offValue } = attrs; - const out = backend.makeOutput([...indices.shape, depth], 'int32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const indicesData = backend.dataIdMap.get(indices.dataId); - const indicesId = indicesData.id; - wasmOneHot(indicesId, depth, onValue, offValue, outId); - return out; - } - const oneHotConfig = { - kernelName: tfjsCore.OneHot, - backendName: 'wasm', - setupFunc: setup$l, - kernelFunc: oneHot, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function onesLike(args) { - const { inputs: { x }, backend } = args; - const out = backend.makeOutput(x.shape, x.dtype); - const outVals = backend.typedArrayFromHeap(out); - outVals.fill(1); - return out; - } - const onesLikeConfig = { - kernelName: tfjsCore.OnesLike, - backendName: 'wasm', - kernelFunc: onesLike, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmPadV2; - function setup$m(backend) { - wasmPadV2 = backend.wasm.cwrap(tfjsCore.PadV2, null /* void */, [ - 'number', - 'array', - 'number', - 'number', - 'array', - 'array', - 'number', - 'number', - ]); - } - function pad(args) { - const { inputs: { x }, backend, attrs: { paddings, constantValue } } = args; - const outShape = paddings.map((p, i) => p[0] /* beforePad */ + x.shape[i] + p[1] /* afterPad */); - const xId = backend.dataIdMap.get(x.dataId).id; - const out = backend.makeOutput(outShape, x.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); - const prePaddingsFlat = paddings.map(padTuple => padTuple[0]); - const postPaddingsFlat = paddings.map(padTuple => padTuple[1]); - const prePaddingsBytes = new Uint8Array(new Int32Array(prePaddingsFlat).buffer); - const postPaddingsBytes = new Uint8Array(new Int32Array(postPaddingsFlat).buffer); - wasmPadV2(xId, xShapeBytes, x.shape.length, CppDType[x.dtype], prePaddingsBytes, postPaddingsBytes, constantValue, outId); - return out; - } - const padV2Config = { - kernelName: tfjsCore.PadV2, - backendName: 'wasm', - kernelFunc: pad, - setupFunc: setup$m - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$d = false; - const powConfig = createBinaryKernelConfig(tfjsCore.Pow, supportsFullBroadcast$d); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmPrelu; - function setup$n(backend) { - wasmPrelu = backend.wasm.cwrap(tfjsCore.Prelu, null /* void */, [ - 'number', - 'number', - 'number' // out_id - ]); - } - function prelu(args) { - const { inputs, backend } = args; - const { x, alpha } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - const weightsId = backend.dataIdMap.get(alpha.dataId).id; - const out = backend.makeOutput(x.shape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmPrelu(xId, weightsId, outId); - return out; - } - const preluConfig = { - kernelName: tfjsCore.Prelu, - backendName: 'wasm', - setupFunc: setup$n, - kernelFunc: prelu - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const reluConfig = createUnaryKernelConfig(tfjsCore.Relu); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const relu6Config = createUnaryKernelConfig(tfjsCore.Relu6); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function reshape(args) { - const { inputs, attrs } = args; - const { x } = inputs; - const { shape } = attrs; - return { dataId: x.dataId, shape, dtype: x.dtype }; - } - const reshapeConfig = { - kernelName: tfjsCore.Reshape, - backendName: 'wasm', - kernelFunc: reshape, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmResizeBilinear; - function setup$o(backend) { - wasmResizeBilinear = backend.wasm.cwrap(tfjsCore.ResizeBilinear, null /*void*/, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number' // outId - ]); - } - function resizeBilinear(args) { - const { backend, inputs, attrs } = args; - const { images } = inputs; - const { alignCorners, size } = attrs; - const [newHeight, newWidth] = size; - const [batch, oldHeight, oldWidth, numChannels] = images.shape; - const outShape = [batch, newHeight, newWidth, numChannels]; - let xData = backend.dataIdMap.get(images.dataId); - let castedData; - if (xData.dtype !== 'float32') { - castedData = - cast({ backend, inputs: { x: images }, attrs: { dtype: 'float32' } }); - xData = backend.dataIdMap.get(castedData.dataId); - } - const xId = xData.id; - const out = backend.makeOutput(outShape, 'float32'); - if (tfjsCore.util.sizeFromShape(images.shape) === 0) { - return out; - } - const outId = backend.dataIdMap.get(out.dataId).id; - wasmResizeBilinear(xId, batch, oldHeight, oldWidth, numChannels, newHeight, newWidth, alignCorners ? 1 : 0, outId); - if (castedData != null) { - backend.disposeData(castedData.dataId); - } - return out; - } - const resizeBilinearConfig = { - kernelName: tfjsCore.ResizeBilinear, - backendName: 'wasm', - setupFunc: setup$o, - kernelFunc: resizeBilinear - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmReverse; - function setup$p(backend) { - wasmReverse = backend.wasm.cwrap(tfjsCore.Reverse, null, [ - 'number', - 'array', - 'number', - 'array', - 'number', - 'number' // out_id - ]); - } - function reverse(args) { - const { inputs, backend, attrs } = args; - const { x } = inputs; - const { dims } = attrs; - const axes = tfjsCore.util.parseAxisParam(dims, x.shape); - if (x.shape.length === 0) { - return identity({ inputs: { x }, backend }); - } - const out = backend.makeOutput(x.shape, x.dtype); - const xId = backend.dataIdMap.get(x.dataId).id; - const outId = backend.dataIdMap.get(out.dataId).id; - const axesBytes = new Uint8Array(new Int32Array(axes).buffer); - const outShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); - wasmReverse(xId, axesBytes, axes.length, outShapeBytes, x.shape.length, outId); - return reshape({ inputs: { x: out }, attrs: { shape: x.shape }, backend }); - } - const reverseConfig = { - kernelName: tfjsCore.Reverse, - backendName: 'wasm', - kernelFunc: reverse, - setupFunc: setup$p - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmRotate; - function setup$q(backend) { - wasmRotate = backend.wasm.cwrap(tfjsCore.RotateWithOffset, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'array', - 'number', - 'number', - ]); - } - function rotateWithOffset(args) { - const { inputs, backend, attrs } = args; - const { image } = inputs; - const { radians, fillValue, center } = attrs; - const out = backend.makeOutput(image.shape, image.dtype); - const imageId = backend.dataIdMap.get(image.dataId).id; - const outId = backend.dataIdMap.get(out.dataId).id; - const [batch, imageHeight, imageWidth, numChannels] = image.shape; - const [centerX, centerY] = tfjsCore.backend_util.getImageCenter(center, imageHeight, imageWidth); - const fillIsBlack = fillValue === 0; - const fullOpacityValue = 255; - const fillValues = typeof fillValue === 'number' ? - [fillValue, fillValue, fillValue, fillIsBlack ? 0 : fullOpacityValue] : - [...fillValue, fullOpacityValue]; - const fillBytes = new Uint8Array(new Int32Array(fillValues).buffer); - wasmRotate(imageId, batch, imageHeight, imageWidth, numChannels, radians, centerX, centerY, fillBytes, fillValues.length, outId); - return out; - } - const rotateWithOffsetConfig = { - kernelName: tfjsCore.RotateWithOffset, - backendName: 'wasm', - kernelFunc: rotateWithOffset, - setupFunc: setup$q - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const rsqrtConfig = createUnaryKernelConfig(tfjsCore.Rsqrt); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmScatterNd; - function setup$r(backend) { - wasmScatterNd = backend.wasm.cwrap(tfjsCore.ScatterNd, null /*void*/, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'array', - 'number', - 'number' // outId - ]); - } - function scatterNd(args) { - const { backend, inputs, attrs } = args; - const { indices, updates } = inputs; - const { shape } = attrs; - const out = backend.makeOutput(shape, updates.dtype); - if (tfjsCore.util.sizeFromShape(shape) === 0) { - return out; - } - const { sliceRank, numUpdates, sliceSize, strides, outputSize } = tfjsCore.scatter_util.calculateShapes(updates, indices, shape); - const indicesData = backend.dataIdMap.get(indices.dataId); - const indicesId = indicesData.id; - const updatesData = backend.dataIdMap.get(updates.dataId); - const updatesId = updatesData.id; - const stridesBytes = new Uint8Array(new Int32Array(strides).buffer); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmScatterNd(indicesId, updatesId, CppDType[updates.dtype], sliceRank, numUpdates, sliceSize, stridesBytes, outputSize, outId); - return out; - } - const scatterNdConfig = { - kernelName: tfjsCore.ScatterNd, - backendName: 'wasm', - setupFunc: setup$r, - kernelFunc: scatterNd - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmSelect; - function setup$s(backend) { - wasmSelect = backend.wasm.cwrap(tfjsCore.SelectV2, null, [ - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function select(args) { - const { inputs, backend } = args; - const { condition, t, e } = inputs; - const conditionId = backend.dataIdMap.get(condition.dataId).id; - const tId = backend.dataIdMap.get(t.dataId).id; - const eId = backend.dataIdMap.get(e.dataId).id; - const out = backend.makeOutput(t.shape, t.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - const cRank = condition.shape.length; - const tRank = t.shape.length; - const offset = cRank === 0 || cRank > 1 || tRank === 1 ? - 1 : - tfjsCore.util.sizeFromShape(t.shape.slice(1)); - wasmSelect(conditionId, tId, eId, offset, outId); - return out; - } - const selectV2Config = { - kernelName: tfjsCore.SelectV2, - backendName: 'wasm', - kernelFunc: select, - setupFunc: setup$s - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$5; - function setup$t(backend) { - wasmFunc$5 = backend.wasm.cwrap(tfjsCore.Sigmoid, null /* void */, ['number', 'number']); - } - function sigmoid(args) { - const { backend, inputs: { x } } = args; - const xId = backend.dataIdMap.get(x.dataId).id; - const out = backend.makeOutput(x.shape, x.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(out.shape) === 0) { - return out; - } - wasmFunc$5(xId, outId); - return out; - } - const sigmoidConfig = { - kernelName: 'Sigmoid', - backendName: 'wasm', - setupFunc: setup$t, - kernelFunc: sigmoid - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const sinConfig = createUnaryKernelConfig(tfjsCore.Sin); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function slice(args) { - const { inputs: { x }, attrs: { begin, size }, backend } = args; - const [begin_, size_] = tfjsCore.slice_util.parseSliceParams(x, begin, size); - const isContinous = tfjsCore.slice_util.isSliceContinous(x.shape, begin_, size_); - const xVals = backend.typedArrayFromHeap(x); - const out = backend.makeOutput(size_, x.dtype); - const outVals = backend.typedArrayFromHeap(out); - const xStrides = tfjsCore.util.computeStrides(x.shape); - if (isContinous) { - const flatOffset = tfjsCore.slice_util.computeFlatOffset(begin_, xStrides); - outVals.set(xVals.subarray(flatOffset, flatOffset + tfjsCore.util.sizeFromShape(size_))); - return out; - } - const rank = x.shape.length; - if (rank === 2) { - slice2d(xVals, xStrides[0], outVals, begin_, size_); - } - else if (rank === 3) { - slice3d(xVals, xStrides[0], xStrides[1], outVals, begin_, size_); - } - else if (rank === 4) { - slice4d(xVals, xStrides[0], xStrides[1], xStrides[2], outVals, begin_, size_); - } - else { - genericSliceSlow(xVals, x, outVals, begin_, size_); - } - return out; - } - function slice2d(xVals, xStride, outVals, begin, size) { - let outOffset = 0; - const beginI = begin[0]; - const beginJ = begin[1]; - const endI = beginI + size[0]; - for (let i = beginI; i < endI; i++) { - const xOffset = i * xStride + beginJ; - outVals.set(xVals.subarray(xOffset, xOffset + size[1]), outOffset); - outOffset += size[1]; - } - } - function slice3d(xVals, xStride1, xStride2, outVals, begin, size) { - let outOffset = 0; - const beginI = begin[0]; - const beginJ = begin[1]; - const beginK = begin[2]; - const endI = beginI + size[0]; - const endJ = beginJ + size[1]; - for (let i = beginI; i < endI; i++) { - for (let j = beginJ; j < endJ; j++) { - const xOffset = i * xStride1 + j * xStride2 + beginK; - outVals.set(xVals.subarray(xOffset, xOffset + size[2]), outOffset); - outOffset += size[2]; - } - } - } - function slice4d(xVals, xStride1, xStride2, xStride3, outVals, begin, size) { - let outOffset = 0; - const beginI = begin[0]; - const beginJ = begin[1]; - const beginK = begin[2]; - const endI = beginI + size[0]; - const endJ = beginJ + size[1]; - const endK = beginK + size[2]; - const beginL = begin[3]; - for (let i = beginI; i < endI; i++) { - for (let j = beginJ; j < endJ; j++) { - for (let k = beginK; k < endK; k++) { - const xOffset = i * xStride1 + j * xStride2 + k * xStride3 + beginL; - outVals.set(xVals.subarray(xOffset, xOffset + size[3]), outOffset); - outOffset += size[3]; - } - } - } - } - function genericSliceSlow(xVals, xInfo, outVals, begin, size) { - const outBuf = tfjsCore.buffer(size, xInfo.dtype, outVals); - const xBuf = tfjsCore.buffer(xInfo.shape, xInfo.dtype, xVals); - for (let i = 0; i < outBuf.size; ++i) { - const loc = outBuf.indexToLoc(i); - const xLoc = loc.map((idx, j) => idx + begin[j]); - outVals[i] = xBuf.get(...xLoc); - } - } - const sliceConfig = { - kernelName: tfjsCore.Slice, - backendName: 'wasm', - kernelFunc: slice, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$6; - function setup$u(backend) { - wasmFunc$6 = backend.wasm.cwrap(tfjsCore.Softmax, null /* void */, [ - 'number', - 'number', - 'number', - 'number' // batch - ]); - } - function softmax(args) { - const { backend, inputs: { logits }, attrs: { dim } } = args; - const xId = backend.dataIdMap.get(logits.dataId).id; - const out = backend.makeOutput(logits.shape, logits.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - const channels = logits.shape[dim]; - const batch = tfjsCore.util.sizeFromShape(logits.shape) / channels; - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(out.shape) === 0) { - return out; - } - wasmFunc$6(xId, outId, channels, batch); - return out; - } - const softmaxConfig = { - kernelName: tfjsCore.Softmax, - backendName: 'wasm', - setupFunc: setup$u, - kernelFunc: softmax - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function split(args) { - const { inputs, attrs, backend } = args; - const { x } = inputs; - const { numOrSizeSplits, axis } = attrs; - const $axis = tfjsCore.util.parseAxisParam(axis, x.shape)[0]; - const splitSizes = tfjsCore.backend_util.prepareSplitSize(x, numOrSizeSplits, axis); - const begin = new Array(x.shape.length).fill(0); - const size = x.shape.slice(); - return splitSizes.map(s => { - const xSliceSize = [...size]; - xSliceSize[$axis] = s; - const xSlice = slice({ inputs: { x }, attrs: { begin, size: xSliceSize }, backend }); - begin[$axis] += s; - return xSlice; - }); - } - const splitVConfig = { - kernelName: tfjsCore.SplitV, - backendName: 'wasm', - kernelFunc: split - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const sqrtConfig = createUnaryKernelConfig(tfjsCore.Sqrt); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const squareConfig = createUnaryKernelConfig(tfjsCore.Square); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$e = true; - const subConfig = createBinaryKernelConfig(tfjsCore.Sub, supportsFullBroadcast$e); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmSum; - function setup$v(backend) { - wasmSum = backend.wasm.cwrap(tfjsCore.Sum, null /*void*/, ['number, number, number']); - } - function sum(args) { - const { backend, inputs, attrs } = args; - const { axis, keepDims } = attrs; - const { x } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - let inputId = xId; - let input = x; - const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); - let reductionAxes = axes; - if (inputWasTransposed) { - const transposedId = backend.dataIdMap.get(transposed.dataId).id; - if (transposedId !== xId) { - // transpose was not a no-op. We will need to dispose of this - // once we are done. - input = transposed; - inputId = transposedId; - reductionAxes = tfjsCore.backend_util.getInnerMostAxes(reductionAxes.length, input.shape.length); - } - } - tfjsCore.backend_util.assertAxesAreInnerMostDims('sum', reductionAxes, input.shape.length); - const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, reductionAxes); - const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); - const out = backend.makeOutput(outShape, input.dtype); - if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { - const outId = backend.dataIdMap.get(out.dataId).id; - wasmSum(inputId, reduceSize, outId); - } - if (inputWasTransposed) { - // dispose of the transposed tensor. - backend.disposeData(transposed.dataId); - } - if (keepDims) { - // reshape - const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); - out.shape = newShape; - } - return out; - } - const sumConfig = { - kernelName: tfjsCore.Sum, - backendName: 'wasm', - setupFunc: setup$v, - kernelFunc: sum - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const tanhConfig = createUnaryKernelConfig(tfjsCore.Tanh); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmTile; - function setup$w(backend) { - wasmTile = backend.wasm.cwrap(tfjsCore.Tile, null /* void */, [ - 'number', - 'array', - 'number', - 'array', - 'number', - 'number' // out_id - ]); - } - function tile(args) { - const { inputs, backend, attrs } = args; - const { x } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - const { reps } = attrs; - const newShape = new Array(x.shape.length); - for (let i = 0; i < newShape.length; i++) { - newShape[i] = x.shape[i] * reps[i]; - } - const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); - const newShapeBytes = new Uint8Array(new Int32Array(newShape).buffer); - const out = backend.makeOutput(newShape, x.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmTile(xId, xShapeBytes, x.shape.length, newShapeBytes, newShape.length, CppDType[out.dtype], outId); - return out; - } - const tileConfig = { - kernelName: tfjsCore.Tile, - backendName: 'wasm', - setupFunc: setup$w, - kernelFunc: tile - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function unpack(args) { - const { inputs, backend, attrs } = args; - const { value } = inputs; - const { axis } = attrs; - const numOutputs = value.shape[axis]; - const rank = value.shape.length; - const outShape = new Array(rank - 1); - let outIndex = 0; - for (let i = 0; i < rank; i++) { - if (i !== axis) { - outShape[outIndex++] = value.shape[i]; - } - } - const outs = new Array(numOutputs); - const begin = new Array(rank).fill(0); - const size = value.shape.slice(); - size[axis] = 1; - for (let i = 0; i < outs.length; i++) { - begin[axis] = i; - outs[i] = slice({ inputs: { x: value }, attrs: { begin, size }, backend }); - } - return outs.map(({ dataId, dtype }) => ({ dataId, dtype, shape: outShape })); - } - const unpackConfig = { - kernelName: tfjsCore.Unpack, - backendName: 'wasm', - kernelFunc: unpack, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function zerosLike(args) { - const { inputs: { x }, backend } = args; - const out = backend.makeOutput(x.shape, x.dtype); - const outVals = backend.typedArrayFromHeap(out); - outVals.fill(0); - return out; - } - const zerosLikeConfig = { - kernelName: tfjsCore.ZerosLike, - backendName: 'wasm', - kernelFunc: zerosLike, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // List all kernel configs here - const kernelConfigs = [ - absConfig, - addConfig, - addNConfig, - argMaxConfig, - avgPoolConfig, - batchMatMulConfig, - castConfig, - clipByValueConfig, - concatConfig, - conv2DConfig, - conv2DBackpropInputConfig, - cosConfig, - cropAndResizeConfig, - depthwiseConv2DNativeConfig, - divConfig, - equalConfig, - expConfig, - fillConfig, - floorDivConfig, - fusedMatMulConfig, - fusedBatchNormConfig, - fusedConv2DConfig, - fusedDepthwiseConv2DConfig, - gatherNdConfig, - gatherV2Config, - greaterConfig, - greaterEqualConfig, - identityConfig, - lessConfig, - lessEqualConfig, - logConfig, - logicalAndConfig, - maxConfig, - maximumConfig, - maxPoolConfig, - minConfig, - minimumConfig, - multiplyConfig, - negateConfig, - nonMaxSuppressionV3Config, - nonMaxSuppressionV4Config, - nonMaxSuppressionV5Config, - notEqualConfig, - oneHotConfig, - onesLikeConfig, - padV2Config, - powConfig, - preluConfig, - reluConfig, - relu6Config, - reshapeConfig, - resizeBilinearConfig, - reverseConfig, - rotateWithOffsetConfig, - rsqrtConfig, - scatterNdConfig, - selectV2Config, - sigmoidConfig, - sinConfig, - sliceConfig, - softmaxConfig, - splitVConfig, - sqrtConfig, - squareConfig, - subConfig, - sumConfig, - tanhConfig, - tileConfig, - transposeConfig, - unpackConfig, - zerosLikeConfig - ]; - for (const kernelConfig of kernelConfigs) { - tfjsCore.registerKernel(kernelConfig); - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const ENV = tfjsCore.env(); - /** - * True if SIMD is supported. - */ - // From: https://github.com/GoogleChromeLabs/wasm-feature-detect - ENV.registerFlag('WASM_HAS_SIMD_SUPPORT', async () => WebAssembly.validate(new Uint8Array([ - 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, - 2, 1, 0, 10, 9, 1, 7, 0, 65, 0, 253, 15, 26, 11 - ]))); - - function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; - } - - var tfjsBackendWasmSimd = createCommonjsModule(function (module, exports) { - var WasmBackendModuleSimd = (function() { - var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; - if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; - return ( - function(WasmBackendModuleSimd) { - WasmBackendModuleSimd = WasmBackendModuleSimd || {}; - - var Module=typeof WasmBackendModuleSimd!=="undefined"?WasmBackendModuleSimd:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":152,"maximum":152+0,"element":"anyfunc"});var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023);}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer);}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm-simd.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=exports["memory"];updateGlobalBufferAndViews(wasmMemory.buffer);removeRunDependency();}addRunDependency();function receiveInstantiatedSource(output){receiveInstance(output["instance"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}__ATINIT__.push();function _emscripten_notify_memory_growth(memoryIndex){updateGlobalBufferAndViews(wasmMemory.buffer);}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _exit(status){exit(status);}function _proc_exit(code){_exit(code);}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}var asmLibraryArg={"emscripten_notify_memory_growth":_emscripten_notify_memory_growth,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"proc_exit":_proc_exit,"roundf":_roundf};var asm=createWasm();Module["asm"]=asm;var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["init"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["register_tensor"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["dispose_data"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["dispose"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["Abs"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["Add"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["AddN"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["ArgMax"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["AvgPool"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["BatchMatMul"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["ClipByValue"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["Conv2D"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["Conv2DBackpropInput"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["Cos"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["CropAndResize"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["DepthwiseConv2dNative"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["Div"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["Equal"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["Exp"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["FloorDiv"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["FusedBatchNorm"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["FusedConv2D"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["FusedDepthwiseConv2D"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["Gather"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["GatherNd"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["Greater"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["GreaterEqual"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["Less"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["LessEqual"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["Log"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["LogicalAnd"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["Max"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["MaxPool"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["Maximum"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["Min"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["Minimum"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["Multiply"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["Negate"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["NonMaxSuppressionV3"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["NonMaxSuppressionV4"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["NonMaxSuppressionV5"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["NotEqual"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["OneHot"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["PadV2"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["Pow"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["Prelu"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["Relu"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["Relu6"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["ResizeBilinear"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["Reverse"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["RotateWithOffset"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["Rsqrt"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["ScatterNd"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["SelectV2"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["Sigmoid"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["Sin"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["Softmax"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["Sqrt"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["Square"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["Sub"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["Sum"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["Tanh"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["Tile"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["Transpose"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["_FusedMatMul"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["malloc"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["free"]).apply(null,arguments)};var __start=Module["__start"]=function(){return (__start=Module["__start"]=Module["asm"]["_start"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["stackSave"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["stackAlloc"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["stackRestore"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function callMain(args){var entryFunction=Module["__start"];try{entryFunction();var ret=0;exit(ret,true);}catch(e){if(e instanceof ExitStatus){return}else if(e=="unwind"){noExitRuntime=true;return}else{var toLog=e;if(e&&typeof e==="object"&&e.stack){toLog=[e,e.stack];}err("exception thrown: "+toLog);quit_(1,e);}}finally{}}function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;function exit(status,implicit){if(implicit&&noExitRuntime&&status===0){return}if(noExitRuntime);else{ABORT=true;if(Module["onExit"])Module["onExit"](status);}quit_(status,new ExitStatus(status));}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;noExitRuntime=true;run(); - - - return WasmBackendModuleSimd - } - ); - })(); - module.exports = WasmBackendModuleSimd; - }); - - var tfjsBackendWasm = createCommonjsModule(function (module, exports) { - var WasmBackendModule = (function() { - var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; - if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; - return ( - function(WasmBackendModule) { - WasmBackendModule = WasmBackendModule || {}; - - var Module=typeof WasmBackendModule!=="undefined"?WasmBackendModule:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":147,"maximum":147+0,"element":"anyfunc"});var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023);}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer);}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=exports["memory"];updateGlobalBufferAndViews(wasmMemory.buffer);removeRunDependency();}addRunDependency();function receiveInstantiatedSource(output){receiveInstance(output["instance"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}__ATINIT__.push();function _emscripten_notify_memory_growth(memoryIndex){updateGlobalBufferAndViews(wasmMemory.buffer);}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _exit(status){exit(status);}function _proc_exit(code){_exit(code);}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}var asmLibraryArg={"emscripten_notify_memory_growth":_emscripten_notify_memory_growth,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"proc_exit":_proc_exit,"roundf":_roundf};var asm=createWasm();Module["asm"]=asm;var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["init"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["register_tensor"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["dispose_data"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["dispose"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["Abs"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["Add"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["AddN"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["ArgMax"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["AvgPool"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["BatchMatMul"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["ClipByValue"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["Conv2D"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["Conv2DBackpropInput"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["Cos"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["CropAndResize"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["DepthwiseConv2dNative"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["Div"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["Equal"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["Exp"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["FloorDiv"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["FusedBatchNorm"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["FusedConv2D"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["FusedDepthwiseConv2D"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["Gather"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["GatherNd"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["Greater"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["GreaterEqual"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["Less"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["LessEqual"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["Log"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["LogicalAnd"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["Max"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["MaxPool"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["Maximum"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["Min"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["Minimum"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["Multiply"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["Negate"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["NonMaxSuppressionV3"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["NonMaxSuppressionV4"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["NonMaxSuppressionV5"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["NotEqual"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["OneHot"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["PadV2"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["Pow"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["Prelu"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["Relu"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["Relu6"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["ResizeBilinear"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["Reverse"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["RotateWithOffset"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["Rsqrt"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["ScatterNd"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["SelectV2"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["Sigmoid"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["Sin"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["Softmax"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["Sqrt"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["Square"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["Sub"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["Sum"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["Tanh"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["Tile"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["Transpose"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["_FusedMatMul"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["malloc"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["free"]).apply(null,arguments)};var __start=Module["__start"]=function(){return (__start=Module["__start"]=Module["asm"]["_start"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["stackSave"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["stackAlloc"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["stackRestore"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function callMain(args){var entryFunction=Module["__start"];try{entryFunction();var ret=0;exit(ret,true);}catch(e){if(e instanceof ExitStatus){return}else if(e=="unwind"){noExitRuntime=true;return}else{var toLog=e;if(e&&typeof e==="object"&&e.stack){toLog=[e,e.stack];}err("exception thrown: "+toLog);quit_(1,e);}}finally{}}function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;function exit(status,implicit){if(implicit&&noExitRuntime&&status===0){return}if(noExitRuntime);else{ABORT=true;if(Module["onExit"])Module["onExit"](status);}quit_(status,new ExitStatus(status));}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;noExitRuntime=true;run(); - - - return WasmBackendModule - } - ); - })(); - module.exports = WasmBackendModule; - }); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const WASM_PRIORITY = 2; - class BackendWasm extends tfjsCore.KernelBackend { - constructor(wasm) { - super(); - this.wasm = wasm; - // 0 is reserved for null data ids. - this.dataIdNextNumber = 1; - this.wasm.tfjs.init(); - this.dataIdMap = new tfjsCore.DataStorage(this, tfjsCore.engine()); - } - write(values, shape, dtype) { - const dataId = {}; - this.move(dataId, values, shape, dtype); - return dataId; - } - numDataIds() { - return this.dataIdMap.numDataIds(); - } - async time(f) { - const start = tfjsCore.util.now(); - f(); - const kernelMs = tfjsCore.util.now() - start; - return { kernelMs }; - } - move(dataId, values, shape, dtype) { - const id = this.dataIdNextNumber++; - if (dtype === 'string') { - const stringBytes = values; - this.dataIdMap.set(dataId, { id, stringBytes, shape, dtype, memoryOffset: null }); - return; - } - const size = tfjsCore.util.sizeFromShape(shape); - const numBytes = size * tfjsCore.util.bytesPerElement(dtype); - const memoryOffset = this.wasm._malloc(numBytes); - this.dataIdMap.set(dataId, { id, memoryOffset, shape, dtype }); - this.wasm.tfjs.registerTensor(id, size, memoryOffset); - if (values != null) { - this.wasm.HEAPU8.set(new Uint8Array(values.buffer, values.byteOffset, numBytes), memoryOffset); - } - } - async read(dataId) { - return this.readSync(dataId); - } - readSync(dataId) { - const { memoryOffset, dtype, shape, stringBytes } = this.dataIdMap.get(dataId); - if (dtype === 'string') { - return stringBytes; - } - const bytes = this.wasm.HEAPU8.slice(memoryOffset, memoryOffset + tfjsCore.util.sizeFromShape(shape) * tfjsCore.util.bytesPerElement(dtype)); - return typedArrayFromBuffer(bytes.buffer, dtype); - } - disposeData(dataId) { - const data = this.dataIdMap.get(dataId); - this.wasm._free(data.memoryOffset); - this.wasm.tfjs.disposeData(data.id); - this.dataIdMap.delete(dataId); - } - floatPrecision() { - return 32; - } - // Returns the memory offset of a tensor. Useful for debugging and unit - // testing. - getMemoryOffset(dataId) { - return this.dataIdMap.get(dataId).memoryOffset; - } - dispose() { - this.wasm.tfjs.dispose(); - this.wasm = null; - } - memory() { - return { unreliable: false }; - } - /** - * Make a tensor info for the output of an op. If `memoryOffset` is not - * present, this method allocates memory on the WASM heap. If `memoryOffset` - * is present, the memory was allocated elsewhere (in c++) and we just record - * the pointer where that memory lives. - */ - makeOutput(shape, dtype, memoryOffset) { - let dataId; - if (memoryOffset == null) { - dataId = this.write(null /* values */, shape, dtype); - } - else { - dataId = {}; - const id = this.dataIdNextNumber++; - this.dataIdMap.set(dataId, { id, memoryOffset, shape, dtype }); - const size = tfjsCore.util.sizeFromShape(shape); - this.wasm.tfjs.registerTensor(id, size, memoryOffset); - } - return { dataId, shape, dtype }; - } - typedArrayFromHeap({ shape, dtype, dataId }) { - const buffer = this.wasm.HEAPU8.buffer; - const { memoryOffset } = this.dataIdMap.get(dataId); - const size = tfjsCore.util.sizeFromShape(shape); - switch (dtype) { - case 'float32': - return new Float32Array(buffer, memoryOffset, size); - case 'int32': - return new Int32Array(buffer, memoryOffset, size); - case 'bool': - return new Uint8Array(buffer, memoryOffset, size); - default: - throw new Error(`Uknown dtype ${dtype}`); - } - } - } - tfjsCore.registerBackend('wasm', async () => { - const { wasm } = await init(); - return new BackendWasm(wasm); - }, WASM_PRIORITY); - function createInstantiateWasmFunc(path) { - // tslint:disable-next-line:no-any - return (imports, callback) => { - tfjsCore.util.fetch(path, { credentials: 'same-origin' }).then((response) => { - if (!response['ok']) { - imports.env.a(`failed to load wasm binary file at '${path}'`); - } - response.arrayBuffer().then(binary => { - WebAssembly.instantiate(binary, imports).then(output => { - callback(output.instance); - }); - }); - }); - return {}; - }; - } - /** - * Initializes the wasm module and creates the js <--> wasm bridge. - * - * NOTE: We wrap the wasm module in a object with property 'wasm' instead of - * returning Promise to avoid freezing Chrome (last tested - * in Chrome 76). - */ - async function init() { - const simdSupported = await tfjsCore.env().getAsync('WASM_HAS_SIMD_SUPPORT'); - return new Promise((resolve, reject) => { - const factoryConfig = {}; - factoryConfig.locateFile = (path, prefix) => { - if (path.endsWith('.wasm')) { - if (simdSupported) { - return prefix + 'tfjs-backend-wasm-simd.wasm'; - } - return prefix + 'tfjs-backend-wasm.wasm'; - } - if (wasmPath != null) { - if (path.endsWith('.wasm')) { - return wasmPath; - } - } - return prefix + path; - }; - if (wasmPath != null) { - // use wasm instantiateWasm override when system fetch is not available. - // For detail references - // https://github.com/emscripten-core/emscripten/blob/2bca083cbbd5a4133db61fbd74d04f7feecfa907/tests/manual_wasm_instantiate.html#L170 - if (customFetch) { - factoryConfig.instantiateWasm = createInstantiateWasmFunc(wasmPath); - } - } - // const wasm = simdSupported ? tfjsBackendWasmSimd(factoryConfig) : - // tfjsBackendWasm(factoryConfig); - const wasm = tfjsBackendWasm(factoryConfig); - - const voidReturnType = null; - // Using the tfjs namespace to avoid conflict with emscripten's API. - wasm.tfjs = { - init: wasm.cwrap('init', null, []), - registerTensor: wasm.cwrap('register_tensor', null, [ - 'number', - 'number', - 'number', - ]), - disposeData: wasm.cwrap('dispose_data', voidReturnType, ['number']), - dispose: wasm.cwrap('dispose', voidReturnType, []), - }; - let initialized = false; - wasm.onRuntimeInitialized = () => { - initialized = true; - initAborted = false; - resolve({ wasm }); - }; - wasm.onAbort = () => { - if (initialized) { - // Emscripten already called console.warn so no need to double log. - return; - } - if (initAborted) { - // Emscripten calls `onAbort` twice, resulting in double error - // messages. - return; - } - initAborted = true; - const rejectMsg = 'Make sure the server can serve the `.wasm` file relative to the ' + - 'bundled js file. For more details see https://github.com/tensorflow/tfjs/blob/master/tfjs-backend-wasm/README.md#using-bundlers'; - reject({ message: rejectMsg }); - }; - }); - } - function typedArrayFromBuffer(buffer, dtype) { - switch (dtype) { - case 'float32': - return new Float32Array(buffer); - case 'int32': - return new Int32Array(buffer); - case 'bool': - return new Uint8Array(buffer); - default: - throw new Error(`Unknown dtype ${dtype}`); - } - } - let wasmPath = null; - let initAborted = false; - let customFetch = false; - /** - * Sets the path to the `.wasm` file which will be fetched when the wasm - * backend is initialized. See - * https://github.com/tensorflow/tfjs/blob/master/tfjs-backend-wasm/README.md#using-bundlers - * for more details. - * @param path wasm file path or url - * @param usePlatformFetch optional boolean to use platform fetch to download - * the wasm file, default to false. - */ - /** @doc {heading: 'Environment', namespace: 'wasm'} */ - function setWasmPath(path, usePlatformFetch = false) { - if (initAborted) { - throw new Error('The WASM backend was already initialized. Make sure you call ' + - '`setWasmPath()` before you call `tf.setBackend()` or `tf.ready()`'); - } - wasmPath = path; - customFetch = usePlatformFetch; - } - - /** @license See the LICENSE file. */ - // This code is auto-generated, do not modify this file! - const version = '0.0.0'; - - exports.BackendWasm = BackendWasm; - exports.setWasmPath = setWasmPath; - exports.version_wasm = version; - - Object.defineProperty(exports, '__esModule', { value: true }); - -}))); -//# sourceMappingURL=tf-backend-wasm.js.map diff --git a/e2e/benchmarks/tf-core.js b/e2e/benchmarks/tf-core.js deleted file mode 100644 index 2637d1e2b74..00000000000 --- a/e2e/benchmarks/tf-core.js +++ /dev/null @@ -1,32471 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (global = global || self, factory(global.tf = global.tf || {})); -}(this, (function (exports) { 'use strict'; - - /*! ***************************************************************************** - Copyright (c) Microsoft Corporation. All rights reserved. - Licensed under the Apache License, Version 2.0 (the "License"); you may not use - this file except in compliance with the License. You may obtain a copy of the - License at http://www.apache.org/licenses/LICENSE-2.0 - - THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED - WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, - MERCHANTABLITY OR NON-INFRINGEMENT. - - See the Apache Version 2.0 License for specific language governing permissions - and limitations under the License. - ***************************************************************************** */ - /* global Reflect, Promise */ - - var extendStatics = function(d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - - function __extends(d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - } - - function __awaiter(thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); - } - - function __generator(thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } - } - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // Expects flags from URL in the format ?tfjsflags=FLAG1:1,FLAG2:true. - var TENSORFLOWJS_FLAGS_PREFIX = 'tfjsflags'; - /** - * The environment contains evaluated flags as well as the registered platform. - * This is always used as a global singleton and can be retrieved with - * `tf.env()`. - */ - /** @doc {heading: 'Environment'} */ - var Environment = /** @class */ (function () { - // tslint:disable-next-line: no-any - function Environment(global) { - this.global = global; - this.flags = {}; - this.flagRegistry = {}; - this.urlFlags = {}; - this.populateURLFlags(); - } - Environment.prototype.setPlatform = function (platformName, platform) { - if (this.platform != null) { - console.warn("Platform " + this.platformName + " has already been set. " + - ("Overwriting the platform with " + platform + ".")); - } - this.platformName = platformName; - this.platform = platform; - }; - Environment.prototype.registerFlag = function (flagName, evaluationFn, setHook) { - this.flagRegistry[flagName] = { evaluationFn: evaluationFn, setHook: setHook }; - // Override the flag value from the URL. This has to happen here because the - // environment is initialized before flags get registered. - if (this.urlFlags[flagName] != null) { - var flagValue = this.urlFlags[flagName]; - console.warn("Setting feature override from URL " + flagName + ": " + flagValue + "."); - this.set(flagName, flagValue); - } - }; - Environment.prototype.getAsync = function (flagName) { - return __awaiter(this, void 0, void 0, function () { - var _a, _b; - return __generator(this, function (_c) { - switch (_c.label) { - case 0: - if (flagName in this.flags) { - return [2 /*return*/, this.flags[flagName]]; - } - _a = this.flags; - _b = flagName; - return [4 /*yield*/, this.evaluateFlag(flagName)]; - case 1: - _a[_b] = _c.sent(); - return [2 /*return*/, this.flags[flagName]]; - } - }); - }); - }; - Environment.prototype.get = function (flagName) { - if (flagName in this.flags) { - return this.flags[flagName]; - } - var flagValue = this.evaluateFlag(flagName); - if (flagValue instanceof Promise) { - throw new Error("Flag " + flagName + " cannot be synchronously evaluated. " + - "Please use getAsync() instead."); - } - this.flags[flagName] = flagValue; - return this.flags[flagName]; - }; - Environment.prototype.getNumber = function (flagName) { - return this.get(flagName); - }; - Environment.prototype.getBool = function (flagName) { - return this.get(flagName); - }; - Environment.prototype.getFlags = function () { - return this.flags; - }; - Object.defineProperty(Environment.prototype, "features", { - // For backwards compatibility. - get: function () { - return this.flags; - }, - enumerable: true, - configurable: true - }); - Environment.prototype.set = function (flagName, value) { - if (this.flagRegistry[flagName] == null) { - throw new Error("Cannot set flag " + flagName + " as it has not been registered."); - } - this.flags[flagName] = value; - if (this.flagRegistry[flagName].setHook != null) { - this.flagRegistry[flagName].setHook(value); - } - }; - Environment.prototype.evaluateFlag = function (flagName) { - if (this.flagRegistry[flagName] == null) { - throw new Error("Cannot evaluate flag '" + flagName + "': no evaluation function found."); - } - return this.flagRegistry[flagName].evaluationFn(); - }; - Environment.prototype.setFlags = function (flags) { - this.flags = Object.assign({}, flags); - }; - Environment.prototype.reset = function () { - this.flags = {}; - this.urlFlags = {}; - this.populateURLFlags(); - }; - Environment.prototype.populateURLFlags = function () { - var _this = this; - if (typeof this.global === 'undefined' || - typeof this.global.location === 'undefined' || - typeof this.global.location.search === 'undefined') { - return; - } - var urlParams = getQueryParams(this.global.location.search); - if (TENSORFLOWJS_FLAGS_PREFIX in urlParams) { - var keyValues = urlParams[TENSORFLOWJS_FLAGS_PREFIX].split(','); - keyValues.forEach(function (keyValue) { - var _a = keyValue.split(':'), key = _a[0], value = _a[1]; - _this.urlFlags[key] = parseValue(key, value); - }); - } - }; - return Environment; - }()); - function getQueryParams(queryString) { - var params = {}; - queryString.replace(/[?&]([^=?&]+)(?:=([^&]*))?/g, function (s) { - var t = []; - for (var _i = 1; _i < arguments.length; _i++) { - t[_i - 1] = arguments[_i]; - } - decodeParam(params, t[0], t[1]); - return t.join('='); - }); - return params; - } - function decodeParam(params, name, value) { - params[decodeURIComponent(name)] = decodeURIComponent(value || ''); - } - function parseValue(flagName, value) { - value = value.toLowerCase(); - if (value === 'true' || value === 'false') { - return value === 'true'; - } - else if ("" + +value === value) { - return +value; - } - throw new Error("Could not parse value flag value " + value + " for flag " + flagName + "."); - } - /** - * Returns the current environment (a global singleton). - * - * The environment object contains the evaluated feature values as well as the - * active platform. - */ - /** @doc {heading: 'Environment'} */ - function env() { - return exports.ENV; - } - exports.ENV = null; - function setEnvironmentGlobal(environment) { - exports.ENV = environment; - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // Note that the identifier globalNameSpace is scoped to this module, but will - // always resolve to the same global object regardless of how the module is - // resolved. - // tslint:disable-next-line:no-any - var globalNameSpace; - // tslint:disable-next-line:no-any - function getGlobalNamespace() { - if (globalNameSpace == null) { - // tslint:disable-next-line:no-any - var ns = void 0; - if (typeof (window) !== 'undefined') { - ns = window; - } - else if (typeof (global) !== 'undefined') { - ns = global; - } - else if (typeof (process) !== 'undefined') { - ns = process; - } - else if (typeof (self) !== 'undefined') { - ns = self; - } - else { - throw new Error('Could not find a global object'); - } - globalNameSpace = ns; - } - return globalNameSpace; - } - // tslint:disable-next-line:no-any - function getGlobalMap() { - var ns = getGlobalNamespace(); - if (ns._tfGlobals == null) { - ns._tfGlobals = new Map(); - } - return ns._tfGlobals; - } - /** - * Returns a globally accessible 'singleton' object. - * - * @param key the name of the object - * @param init a function to initialize to initialize this object - * the first time it is fetched. - */ - function getGlobal(key, init) { - var globalMap = getGlobalMap(); - if (globalMap.has(key)) { - return globalMap.get(key); - } - else { - var singleton = init(); - globalMap.set(key, singleton); - return globalMap.get(key); - } - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var kernelRegistry = getGlobal('kernelRegistry', function () { return new Map(); }); - var gradRegistry = getGlobal('gradRegistry', function () { return new Map(); }); - /** - * Returns the kernel function (code) associated with the provided names. - * - * @param kernelName The official name of the kernel. - * @param backendName The official name of the backend. - */ - function getKernel(kernelName, backendName) { - var key = makeKey(kernelName, backendName); - return kernelRegistry.get(key); - } - /** - * Returns the registered gradient info associated with the provided kernel. - * @param kernelName The official TF kernel name. - */ - function getGradient(kernelName) { - return gradRegistry.get(kernelName); - } - function getKernelsForBackend(backendName) { - var it = kernelRegistry.entries(); - var result = []; - while (true) { - var _a = it.next(), done = _a.done, value = _a.value; - if (done) { - break; - } - var key = value[0], config = value[1]; - var backend = key.split('_')[0]; - if (backend === backendName) { - result.push(config); - } - } - return result; - } - /** - * Registers the function (forward pass) for the kernel in a global registry. - * - * @param config A config object with the following properties: - * - `kernelName` The official name of the kernel. - * - `backendName` The official name of the backend. - * - `kernelFunc` The function to run during the forward pass of the kernel. - * - `setupFunc` Optional. Gets called once, after the backend initializes. - * - `disposeFunc` Optional. Gets called once, right before the backend is - * disposed. - */ - function registerKernel(config) { - var kernelName = config.kernelName, backendName = config.backendName; - var key = makeKey(kernelName, backendName); - if (kernelRegistry.has(key)) { - console.warn("The kernel '" + kernelName + "' for backend " + - ("'" + backendName + "' is already registered")); - } - kernelRegistry.set(key, config); - } - /** - * Registers a gradient function for a given kernel in the global registry, - * to be used during the back-propagation of that kernel. - * - * @param config An object with the following properties: - * - `kernelName` The name of the kernel that the gradient function is for. - * - `gradFunc` The function to run during back-propagation. - */ - function registerGradient(config) { - var kernelName = config.kernelName; - if (gradRegistry.has(kernelName)) { - // TODO (yassogba) after 3.0 assess whether we need to keep this gated - // to debug mode. - if (env().getBool('DEBUG')) { - console.warn("Overriding the gradient for '" + kernelName + "'"); - } - } - gradRegistry.set(kernelName, config); - } - /** - * Removes the kernel function from the registry. - * - * @param kernelName The official name of the kernel. - * @param backendName The official name of the backend. - * - */ - function unregisterKernel(kernelName, backendName) { - var key = makeKey(kernelName, backendName); - if (!kernelRegistry.has(key)) { - throw new Error("The kernel '" + kernelName + "' for backend " + - ("'" + backendName + "' is not registered")); - } - kernelRegistry.delete(key); - } - /** Removes the registered gradient from the global registry. */ - function unregisterGradient(kernelName) { - if (!gradRegistry.has(kernelName)) { - throw new Error("The gradient '" + kernelName + "' for backend is not registered"); - } - gradRegistry.delete(kernelName); - } - function makeKey(kernelName, backendName) { - return backendName + "_" + kernelName; - } - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Shuffles the array in-place using Fisher-Yates algorithm. - * - * ```js - * const a = [1, 2, 3, 4, 5]; - * tf.util.shuffle(a); - * console.log(a); - * ``` - * - * @param array The array to shuffle in-place. - */ - /** @doc {heading: 'Util', namespace: 'util'} */ - // tslint:disable-next-line:no-any - function shuffle(array) { - var counter = array.length; - var temp = 0; - var index = 0; - // While there are elements in the array - while (counter > 0) { - // Pick a random index - index = (Math.random() * counter) | 0; - // Decrease counter by 1 - counter--; - // And swap the last element with it - temp = array[counter]; - array[counter] = array[index]; - array[index] = temp; - } - } - /** Clamps a value to a specified range. */ - function clamp(min, x, max) { - return Math.max(min, Math.min(x, max)); - } - function nearestLargerEven(val) { - return val % 2 === 0 ? val : val + 1; - } - function sum(arr) { - var sum = 0; - for (var i = 0; i < arr.length; i++) { - sum += arr[i]; - } - return sum; - } - /** - * Returns a sample from a uniform [a, b) distribution. - * - * @param a The minimum support (inclusive). - * @param b The maximum support (exclusive). - * @return A pseudorandom number on the half-open interval [a,b). - */ - function randUniform(a, b) { - var r = Math.random(); - return (b * r) + (1 - r) * a; - } - /** Returns the squared Euclidean distance between two vectors. */ - function distSquared(a, b) { - var result = 0; - for (var i = 0; i < a.length; i++) { - var diff = Number(a[i]) - Number(b[i]); - result += diff * diff; - } - return result; - } - /** - * Asserts that the expression is true. Otherwise throws an error with the - * provided message. - * - * ```js - * const x = 2; - * tf.util.assert(x === 2, 'x is not 2'); - * ``` - * - * @param expr The expression to assert (as a boolean). - * @param msg A function that returns the message to report when throwing an - * error. We use a function for performance reasons. - */ - /** @doc {heading: 'Util', namespace: 'util'} */ - function assert(expr, msg) { - if (!expr) { - throw new Error(typeof msg === 'string' ? msg : msg()); - } - } - function assertShapesMatch(shapeA, shapeB, errorMessagePrefix) { - if (errorMessagePrefix === void 0) { errorMessagePrefix = ''; } - assert(arraysEqual(shapeA, shapeB), function () { return errorMessagePrefix + (" Shapes " + shapeA + " and " + shapeB + " must match"); }); - } - function assertNonNull(a) { - assert(a != null, function () { return "The input to the tensor constructor must be a non-null value."; }); - } - // NOTE: We explicitly type out what T extends instead of any so that - // util.flatten on a nested array of number doesn't try to infer T as a - // number[][], causing us to explicitly type util.flatten(). - /** - * Flattens an arbitrarily nested array. - * - * ```js - * const a = [[1, 2], [3, 4], [5, [6, [7]]]]; - * const flat = tf.util.flatten(a); - * console.log(flat); - * ``` - * - * @param arr The nested array to flatten. - * @param result The destination array which holds the elements. - * @param skipTypedArray If true, avoids flattening the typed arrays. Defaults - * to false. - */ - /** @doc {heading: 'Util', namespace: 'util'} */ - function flatten(arr, result, skipTypedArray) { - if (result === void 0) { result = []; } - if (skipTypedArray === void 0) { skipTypedArray = false; } - if (result == null) { - result = []; - } - if (Array.isArray(arr) || isTypedArray(arr) && !skipTypedArray) { - for (var i = 0; i < arr.length; ++i) { - flatten(arr[i], result, skipTypedArray); - } - } - else { - result.push(arr); - } - return result; - } - /** - * Returns the size (number of elements) of the tensor given its shape. - * - * ```js - * const shape = [3, 4, 2]; - * const size = tf.util.sizeFromShape(shape); - * console.log(size); - * ``` - */ - /** @doc {heading: 'Util', namespace: 'util'} */ - function sizeFromShape(shape) { - if (shape.length === 0) { - // Scalar. - return 1; - } - var size = shape[0]; - for (var i = 1; i < shape.length; i++) { - size *= shape[i]; - } - return size; - } - function isScalarShape(shape) { - return shape.length === 0; - } - function arraysEqual(n1, n2) { - if (n1 === n2) { - return true; - } - if (n1 == null || n2 == null) { - return false; - } - if (n1.length !== n2.length) { - return false; - } - for (var i = 0; i < n1.length; i++) { - if (n1[i] !== n2[i]) { - return false; - } - } - return true; - } - function isInt(a) { - return a % 1 === 0; - } - function tanh(x) { - // tslint:disable-next-line:no-any - if (Math.tanh != null) { - // tslint:disable-next-line:no-any - return Math.tanh(x); - } - if (x === Infinity) { - return 1; - } - else if (x === -Infinity) { - return -1; - } - else { - var e2x = Math.exp(2 * x); - return (e2x - 1) / (e2x + 1); - } - } - function sizeToSquarishShape(size) { - var width = Math.ceil(Math.sqrt(size)); - return [width, Math.ceil(size / width)]; - } - /** - * Creates a new array with randomized indicies to a given quantity. - * - * ```js - * const randomTen = tf.util.createShuffledIndices(10); - * console.log(randomTen); - * ``` - * - * @param number Quantity of how many shuffled indicies to create. - */ - /** @doc {heading: 'Util', namespace: 'util'} */ - function createShuffledIndices(n) { - var shuffledIndices = new Uint32Array(n); - for (var i = 0; i < n; ++i) { - shuffledIndices[i] = i; - } - shuffle(shuffledIndices); - return shuffledIndices; - } - function rightPad(a, size) { - if (size <= a.length) { - return a; - } - return a + ' '.repeat(size - a.length); - } - function repeatedTry(checkFn, delayFn, maxCounter) { - if (delayFn === void 0) { delayFn = function (counter) { return 0; }; } - return new Promise(function (resolve, reject) { - var tryCount = 0; - var tryFn = function () { - if (checkFn()) { - resolve(); - return; - } - tryCount++; - var nextBackoff = delayFn(tryCount); - if (maxCounter != null && tryCount >= maxCounter) { - reject(); - return; - } - setTimeout(tryFn, nextBackoff); - }; - tryFn(); - }); - } - /** - * Given the full size of the array and a shape that may contain -1 as the - * implicit dimension, returns the inferred shape where -1 is replaced. - * E.g. For shape=[2, -1, 3] and size=24, it will return [2, 4, 3]. - * - * @param shape The shape, which may contain -1 in some dimension. - * @param size The full size (number of elements) of the array. - * @return The inferred shape where -1 is replaced with the inferred size. - */ - function inferFromImplicitShape(shape, size) { - var shapeProd = 1; - var implicitIdx = -1; - for (var i = 0; i < shape.length; ++i) { - if (shape[i] >= 0) { - shapeProd *= shape[i]; - } - else if (shape[i] === -1) { - if (implicitIdx !== -1) { - throw Error("Shapes can only have 1 implicit size. " + - ("Found -1 at dim " + implicitIdx + " and dim " + i)); - } - implicitIdx = i; - } - else if (shape[i] < 0) { - throw Error("Shapes can not be < 0. Found " + shape[i] + " at dim " + i); - } - } - if (implicitIdx === -1) { - if (size > 0 && size !== shapeProd) { - throw Error("Size(" + size + ") must match the product of shape " + shape); - } - return shape; - } - if (shapeProd === 0) { - throw Error("Cannot infer the missing size in [" + shape + "] when " + - "there are 0 elements"); - } - if (size % shapeProd !== 0) { - throw Error("The implicit shape can't be a fractional number. " + - ("Got " + size + " / " + shapeProd)); - } - var newShape = shape.slice(); - newShape[implicitIdx] = size / shapeProd; - return newShape; - } - function parseAxisParam(axis, shape) { - var rank = shape.length; - // Normalize input - axis = axis == null ? shape.map(function (s, i) { return i; }) : [].concat(axis); - // Check for valid range - assert(axis.every(function (ax) { return ax >= -rank && ax < rank; }), function () { - return "All values in axis param must be in range [-" + rank + ", " + rank + ") but " + - ("got axis " + axis); - }); - // Check for only integers - assert(axis.every(function (ax) { return isInt(ax); }), function () { return "All values in axis param must be integers but " + - ("got axis " + axis); }); - // Handle negative axis. - return axis.map(function (a) { return a < 0 ? rank + a : a; }); - } - /** Reduces the shape by removing all dimensions of shape 1. */ - function squeezeShape(shape, axis) { - var newShape = []; - var keptDims = []; - var isEmptyArray = axis != null && Array.isArray(axis) && axis.length === 0; - var axes = (axis == null || isEmptyArray) ? - null : - parseAxisParam(axis, shape).sort(); - var j = 0; - for (var i = 0; i < shape.length; ++i) { - if (axes != null) { - if (axes[j] === i && shape[i] !== 1) { - throw new Error("Can't squeeze axis " + i + " since its dim '" + shape[i] + "' is not 1"); - } - if ((axes[j] == null || axes[j] > i) && shape[i] === 1) { - newShape.push(shape[i]); - keptDims.push(i); - } - if (axes[j] <= i) { - j++; - } - } - if (shape[i] !== 1) { - newShape.push(shape[i]); - keptDims.push(i); - } - } - return { newShape: newShape, keptDims: keptDims }; - } - function getTypedArrayFromDType(dtype, size) { - var values = null; - if (dtype == null || dtype === 'float32') { - values = new Float32Array(size); - } - else if (dtype === 'int32') { - values = new Int32Array(size); - } - else if (dtype === 'bool') { - values = new Uint8Array(size); - } - else { - throw new Error("Unknown data type " + dtype); - } - return values; - } - function getArrayFromDType(dtype, size) { - var values = null; - if (dtype == null || dtype === 'float32') { - values = new Float32Array(size); - } - else if (dtype === 'int32') { - values = new Int32Array(size); - } - else if (dtype === 'bool') { - values = new Uint8Array(size); - } - else if (dtype === 'string') { - values = new Array(size); - } - else { - throw new Error("Unknown data type " + dtype); - } - return values; - } - function checkConversionForErrors(vals, dtype) { - for (var i = 0; i < vals.length; i++) { - var num = vals[i]; - if (isNaN(num) || !isFinite(num)) { - throw Error("A tensor of type " + dtype + " being uploaded contains " + num + "."); - } - } - } - /** Returns true if the dtype is valid. */ - function isValidDtype(dtype) { - return dtype === 'bool' || dtype === 'complex64' || dtype === 'float32' || - dtype === 'int32' || dtype === 'string'; - } - /** - * Returns true if the new type can't encode the old type without loss of - * precision. - */ - function hasEncodingLoss(oldType, newType) { - if (newType === 'complex64') { - return false; - } - if (newType === 'float32' && oldType !== 'complex64') { - return false; - } - if (newType === 'int32' && oldType !== 'float32' && oldType !== 'complex64') { - return false; - } - if (newType === 'bool' && oldType === 'bool') { - return false; - } - return true; - } - function isTypedArray(a) { - return a instanceof Float32Array || a instanceof Int32Array || - a instanceof Uint8Array; - } - function bytesPerElement(dtype) { - if (dtype === 'float32' || dtype === 'int32') { - return 4; - } - else if (dtype === 'complex64') { - return 8; - } - else if (dtype === 'bool') { - return 1; - } - else { - throw new Error("Unknown dtype " + dtype); - } - } - /** - * Returns the approximate number of bytes allocated in the string array - 2 - * bytes per character. Computing the exact bytes for a native string in JS is - * not possible since it depends on the encoding of the html page that serves - * the website. - */ - function bytesFromStringArray(arr) { - if (arr == null) { - return 0; - } - var bytes = 0; - arr.forEach(function (x) { return bytes += x.length; }); - return bytes; - } - /** Returns true if the value is a string. */ - function isString(value) { - return typeof value === 'string' || value instanceof String; - } - function isBoolean(value) { - return typeof value === 'boolean'; - } - function isNumber(value) { - return typeof value === 'number'; - } - function inferDtype(values) { - if (Array.isArray(values)) { - return inferDtype(values[0]); - } - if (values instanceof Float32Array) { - return 'float32'; - } - else if (values instanceof Int32Array || values instanceof Uint8Array) { - return 'int32'; - } - else if (isNumber(values)) { - return 'float32'; - } - else if (isString(values)) { - return 'string'; - } - else if (isBoolean(values)) { - return 'bool'; - } - return 'float32'; - } - function isFunction(f) { - return !!(f && f.constructor && f.call && f.apply); - } - function nearestDivisor(size, start) { - for (var i = start; i < size; ++i) { - if (size % i === 0) { - return i; - } - } - return size; - } - function computeStrides(shape) { - var rank = shape.length; - if (rank < 2) { - return []; - } - // Last dimension has implicit stride of 1, thus having D-1 (instead of D) - // strides. - var strides = new Array(rank - 1); - strides[rank - 2] = shape[rank - 1]; - for (var i = rank - 3; i >= 0; --i) { - strides[i] = strides[i + 1] * shape[i + 1]; - } - return strides; - } - function toTypedArray(a, dtype) { - if (dtype === 'string') { - throw new Error('Cannot convert a string[] to a TypedArray'); - } - if (Array.isArray(a)) { - a = flatten(a); - } - if (env().getBool('DEBUG')) { - checkConversionForErrors(a, dtype); - } - if (noConversionNeeded(a, dtype)) { - return a; - } - if (dtype == null || dtype === 'float32' || dtype === 'complex64') { - return new Float32Array(a); - } - else if (dtype === 'int32') { - return new Int32Array(a); - } - else if (dtype === 'bool') { - var bool = new Uint8Array(a.length); - for (var i = 0; i < bool.length; ++i) { - if (Math.round(a[i]) !== 0) { - bool[i] = 1; - } - } - return bool; - } - else { - throw new Error("Unknown data type " + dtype); - } - } - function createNestedArray(offset, shape, a) { - var ret = new Array(); - if (shape.length === 1) { - var d = shape[0]; - for (var i = 0; i < d; i++) { - ret[i] = a[offset + i]; - } - } - else { - var d = shape[0]; - var rest = shape.slice(1); - var len = rest.reduce(function (acc, c) { return acc * c; }); - for (var i = 0; i < d; i++) { - ret[i] = createNestedArray(offset + i * len, rest, a); - } - } - return ret; - } - // Provide a nested array of TypedArray in given shape. - function toNestedArray(shape, a) { - if (shape.length === 0) { - // Scalar type should return a single number. - return a[0]; - } - var size = shape.reduce(function (acc, c) { return acc * c; }); - if (size === 0) { - // A tensor with shape zero should be turned into empty list. - return []; - } - if (size !== a.length) { - throw new Error("[" + shape + "] does not match the input size " + a.length + "."); - } - return createNestedArray(0, shape, a); - } - function noConversionNeeded(a, dtype) { - return (a instanceof Float32Array && dtype === 'float32') || - (a instanceof Int32Array && dtype === 'int32') || - (a instanceof Uint8Array && dtype === 'bool'); - } - function makeOnesTypedArray(size, dtype) { - var array = makeZerosTypedArray(size, dtype); - for (var i = 0; i < array.length; i++) { - array[i] = 1; - } - return array; - } - function makeZerosTypedArray(size, dtype) { - if (dtype == null || dtype === 'float32' || dtype === 'complex64') { - return new Float32Array(size); - } - else if (dtype === 'int32') { - return new Int32Array(size); - } - else if (dtype === 'bool') { - return new Uint8Array(size); - } - else { - throw new Error("Unknown data type " + dtype); - } - } - /** - * Make nested `TypedArray` filled with zeros. - * @param shape The shape information for the nested array. - * @param dtype dtype of the array element. - */ - function makeZerosNestedTypedArray(shape, dtype) { - var size = shape.reduce(function (prev, curr) { return prev * curr; }, 1); - if (dtype == null || dtype === 'float32') { - return toNestedArray(shape, new Float32Array(size)); - } - else if (dtype === 'int32') { - return toNestedArray(shape, new Int32Array(size)); - } - else if (dtype === 'bool') { - return toNestedArray(shape, new Uint8Array(size)); - } - else { - throw new Error("Unknown data type " + dtype); - } - } - /** - * Returns the current high-resolution time in milliseconds relative to an - * arbitrary time in the past. It works across different platforms (node.js, - * browsers). - * - * ```js - * console.log(tf.util.now()); - * ``` - */ - /** @doc {heading: 'Util', namespace: 'util'} */ - function now() { - return env().platform.now(); - } - function assertNonNegativeIntegerDimensions(shape) { - shape.forEach(function (dimSize) { - assert(Number.isInteger(dimSize) && dimSize >= 0, function () { - return "Tensor must have a shape comprised of positive integers but got " + - ("shape [" + shape + "]."); - }); - }); - } - /** - * Returns a platform-specific implementation of - * [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). - * - * If `fetch` is defined on the global object (`window`, `process`, etc.), - * `tf.util.fetch` returns that function. - * - * If not, `tf.util.fetch` returns a platform-specific solution. - * - * ```js - * const resource = await tf.util.fetch('https://unpkg.com/@tensorflow/tfjs'); - * // handle response - * ``` - */ - /** @doc {heading: 'Util'} */ - function fetch$1(path, requestInits) { - return env().platform.fetch(path, requestInits); - } - /** - * Encodes the provided string into bytes using the provided encoding scheme. - * - * @param s The string to encode. - * @param encoding The encoding scheme. Defaults to utf-8. - * - */ - /** @doc {heading: 'Util'} */ - function encodeString(s, encoding) { - if (encoding === void 0) { encoding = 'utf-8'; } - encoding = encoding || 'utf-8'; - return env().platform.encode(s, encoding); - } - /** - * Decodes the provided bytes into a string using the provided encoding scheme. - * @param bytes The bytes to decode. - * - * @param encoding The encoding scheme. Defaults to utf-8. - */ - /** @doc {heading: 'Util'} */ - function decodeString(bytes, encoding) { - if (encoding === void 0) { encoding = 'utf-8'; } - encoding = encoding || 'utf-8'; - return env().platform.decode(bytes, encoding); - } - /** - * Computes flat index for a given location (multidimentionsal index) in a - * Tensor/multidimensional array. - * - * @param locs Location in the tensor. - * @param rank Rank of the tensor. - * @param strides Tensor strides. - */ - function locToIndex(locs, rank, strides) { - if (rank === 0) { - return 0; - } - else if (rank === 1) { - return locs[0]; - } - var index = locs[locs.length - 1]; - for (var i = 0; i < locs.length - 1; ++i) { - index += strides[i] * locs[i]; - } - return index; - } - /** - * Computes the location (multidimensional index) in a tensor/multidimentional - * array for a given flat index. - * - * @param index Index in flat array. - * @param rank Rank of tensor. - * @param strides Strides of tensor. - */ - function indexToLoc(index, rank, strides) { - if (rank === 0) { - return []; - } - else if (rank === 1) { - return [index]; - } - var locs = new Array(rank); - for (var i = 0; i < locs.length - 1; ++i) { - locs[i] = Math.floor(index / strides[i]); - index -= locs[i] * strides[i]; - } - locs[locs.length - 1] = index; - return locs; - } - - var util = { - __proto__: null, - shuffle: shuffle, - clamp: clamp, - nearestLargerEven: nearestLargerEven, - sum: sum, - randUniform: randUniform, - distSquared: distSquared, - assert: assert, - assertShapesMatch: assertShapesMatch, - assertNonNull: assertNonNull, - flatten: flatten, - sizeFromShape: sizeFromShape, - isScalarShape: isScalarShape, - arraysEqual: arraysEqual, - isInt: isInt, - tanh: tanh, - sizeToSquarishShape: sizeToSquarishShape, - createShuffledIndices: createShuffledIndices, - rightPad: rightPad, - repeatedTry: repeatedTry, - inferFromImplicitShape: inferFromImplicitShape, - parseAxisParam: parseAxisParam, - squeezeShape: squeezeShape, - getTypedArrayFromDType: getTypedArrayFromDType, - getArrayFromDType: getArrayFromDType, - checkConversionForErrors: checkConversionForErrors, - isValidDtype: isValidDtype, - hasEncodingLoss: hasEncodingLoss, - isTypedArray: isTypedArray, - bytesPerElement: bytesPerElement, - bytesFromStringArray: bytesFromStringArray, - isString: isString, - isBoolean: isBoolean, - isNumber: isNumber, - inferDtype: inferDtype, - isFunction: isFunction, - nearestDivisor: nearestDivisor, - computeStrides: computeStrides, - toTypedArray: toTypedArray, - toNestedArray: toNestedArray, - makeOnesTypedArray: makeOnesTypedArray, - makeZerosTypedArray: makeZerosTypedArray, - makeZerosNestedTypedArray: makeZerosNestedTypedArray, - now: now, - assertNonNegativeIntegerDimensions: assertNonNegativeIntegerDimensions, - fetch: fetch$1, - encodeString: encodeString, - decodeString: decodeString, - locToIndex: locToIndex, - indexToLoc: indexToLoc - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var Profiler = /** @class */ (function () { - function Profiler(backendTimer, logger) { - this.backendTimer = backendTimer; - this.logger = logger; - if (logger == null) { - this.logger = new Logger(); - } - } - Profiler.prototype.profileKernel = function (kernelName, inputs, f) { - var _this = this; - var outputs; - var holdResultWrapperFn = function () { - outputs = f(); - }; - var timer = this.backendTimer.time(holdResultWrapperFn); - outputs.forEach(function (r) { - // Dangling promise here because we don't want to propagate up - // asynchronicity. - r.data().then(function (vals) { - checkComputationForErrors(vals, r.dtype, kernelName); - timer.then(function (timing) { - var extraInfo = ''; - if (timing.getExtraProfileInfo != null) { - extraInfo = timing.getExtraProfileInfo(); - } - _this.logger.logKernelProfile(kernelName, r, vals, timing.kernelMs, inputs, extraInfo); - }); - }); - }); - return outputs; - }; - return Profiler; - }()); - function checkComputationForErrors(vals, dtype, kernelName) { - if (dtype !== 'float32') { - // Only floating point computations will generate NaN values - return false; - } - for (var i = 0; i < vals.length; i++) { - var num = vals[i]; - if (isNaN(num) || !isFinite(num)) { - // Throwing custom exception so behavior is testable. - console.warn("Found " + num + " in the result of '" + kernelName + "'"); - return true; - } - } - return false; - } - var Logger = /** @class */ (function () { - function Logger() { - } - Logger.prototype.logKernelProfile = function (name, result, vals, timeMs, inputs, extraInfo) { - var time = typeof timeMs === 'number' ? rightPad(timeMs + "ms", 9) : - timeMs['error']; - var paddedName = rightPad(name, 25); - var rank = result.rank; - var size = result.size; - var shape = rightPad(result.shape.toString(), 14); - var inputShapesDescription = ''; - for (var name_1 in inputs) { - var input = inputs[name_1]; - // The input might be a non-tensor (e.g HTMLImageElement), in which case - // we claim the output shape as input shape. - var inputShape = input.shape || result.shape; - var inputRank = inputShape.length; - inputShapesDescription += - name_1 + ": " + inputRank + "D " + (inputRank > 0 ? inputShape : '') + " "; - } - console.log("%c" + paddedName + "\t%c" + time + "\t%c" + rank + "D " + shape + "\t%c" + size + "\t%c" + inputShapesDescription + "\t%c" + extraInfo, 'font-weight:bold', 'color:red', 'color:blue', 'color: orange', 'color: green', 'color: steelblue'); - }; - return Logger; - }()); - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes a list of TapeNodes that connect x to y, filtering everything else - * out and preserving the order of the original tape elements. - * - * @param tape The tape elements to filter. - * @param xs The input Tensors. - * @param y The output Tensor. - */ - function getFilteredNodesXToY(tape, xs, y) { - // Forward pass to compute all the nodes and Tensors that are transitively a - // function of x. - var tensorsFromX = {}; - var nodesFromX = {}; - for (var i = 0; i < xs.length; i++) { - tensorsFromX[xs[i].id] = true; - } - for (var i = 0; i < tape.length; i++) { - var node = tape[i]; - var nodeInputs = node.inputs; - for (var inputName in nodeInputs) { - var input = nodeInputs[inputName]; - var anyInputFromX = false; - for (var j = 0; j < xs.length; j++) { - if (tensorsFromX[input.id]) { - node.outputs.forEach(function (output) { return tensorsFromX[output.id] = true; }); - anyInputFromX = true; - nodesFromX[node.id] = true; - break; - } - } - if (anyInputFromX) { - break; - } - } - } - // Backward pass to find all of the nodes and Tensors that lead to y. - var tensorsLeadToY = {}; - tensorsLeadToY[y.id] = true; - var nodesToY = {}; - for (var i = tape.length - 1; i >= 0; i--) { - var node = tape[i]; - var nodeInputs = node.inputs; - // If any of the outputs lead to y, mark all of the inputs as leading to y. - for (var j = 0; j < node.outputs.length; j++) { - if (tensorsLeadToY[node.outputs[j].id]) { - for (var inputName in nodeInputs) { - tensorsLeadToY[nodeInputs[inputName].id] = true; - nodesToY[node.id] = true; - } - break; - } - } - } - // Return the paths that come from x and lead to y. - var filteredTape = []; - for (var i = 0; i < tape.length; i++) { - var node = tape[i]; - if (nodesFromX[node.id] && nodesToY[node.id]) { - // Prune the inputs from the node that aren't a function of x. - var prunedInputs = {}; - for (var inputName in node.inputs) { - var nodeInput = node.inputs[inputName]; - if (tensorsFromX[nodeInput.id]) { - prunedInputs[inputName] = nodeInput; - } - } - // Copy the node and overwrite inputsAndArgs to the pruned version. - var prunedNode = Object.assign({}, node); - prunedNode.inputs = prunedInputs; - prunedNode.outputs = node.outputs; - filteredTape.push(prunedNode); - } - } - return filteredTape; - } - /** - * Backpropagate gradients through the filtered TapeNodes. - * - * @param tensorAccumulatedGradientMap A map of Tensor to its gradient. This map - * is mutated by this method. - * @param filteredTape The filtered TapeNodes to backprop through. - */ - function backpropagateGradients(tensorAccumulatedGradientMap, filteredTape, tidy) { - var _loop_1 = function (i) { - var node = filteredTape[i]; - var dys = []; - node.outputs.forEach(function (o) { - var gradTensor = tensorAccumulatedGradientMap[o.id]; - if (gradTensor != null) { - dys.push(gradTensor); - } - else { - // This particular output is not in the back-propagation subgraph, so it - // does not affect the final output, thus we put null for its dy. - dys.push(null); - } - }); - if (node.gradient == null) { - throw new Error("Cannot compute gradient: gradient function not found " + - ("for " + node.kernelName + ".")); - } - // Backprop dy through this node and accumulate gradients over the inputs. - var inputGradients = node.gradient(dys); - var _loop_2 = function (inputName) { - if (!(inputName in inputGradients)) { - throw new Error("Cannot backprop through input " + inputName + ". " + - ("Available gradients found: " + Object.keys(inputGradients) + ".")); - } - // Call the gradient function. - var dx = tidy(function () { return inputGradients[inputName](); }); - if (dx.dtype !== 'float32') { - throw new Error("Error in gradient for op " + node.kernelName + ". The gradient of input " + - (inputName + " must have 'float32' dtype, but has '" + dx.dtype + "'")); - } - var x = node.inputs[inputName]; - if (!arraysEqual(dx.shape, x.shape)) { - throw new Error("Error in gradient for op " + node.kernelName + ". The gradient of input " + - ("'" + inputName + "' has shape '" + dx.shape + "', which does not match ") + - ("the shape of the input '" + x.shape + "'")); - } - if (tensorAccumulatedGradientMap[x.id] == null) { - tensorAccumulatedGradientMap[x.id] = dx; - } - else { - var curGradient = tensorAccumulatedGradientMap[x.id]; - tensorAccumulatedGradientMap[x.id] = curGradient.add(dx); - curGradient.dispose(); - } - }; - for (var inputName in node.inputs) { - _loop_2(inputName); - } - }; - // Walk the tape backward and keep a map of Tensor to its gradient. - for (var i = filteredTape.length - 1; i >= 0; i--) { - _loop_1(i); - } - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // Maximum number of values before we decide to show ellipsis. - var FORMAT_LIMIT_NUM_VALS = 20; - // Number of first and last values to show when displaying a, b,...,y, z. - var FORMAT_NUM_FIRST_LAST_VALS = 3; - // Number of significant digits to show. - var FORMAT_NUM_SIG_DIGITS = 7; - function tensorToString(vals, shape, dtype, verbose) { - var strides = computeStrides(shape); - var padPerCol = computeMaxSizePerColumn(vals, shape, dtype, strides); - var rank = shape.length; - var valsLines = subTensorToString(vals, shape, dtype, strides, padPerCol); - var lines = ['Tensor']; - if (verbose) { - lines.push(" dtype: " + dtype); - lines.push(" rank: " + rank); - lines.push(" shape: [" + shape + "]"); - lines.push(" values:"); - } - lines.push(valsLines.map(function (l) { return ' ' + l; }).join('\n')); - return lines.join('\n'); - } - function computeMaxSizePerColumn(vals, shape, dtype, strides) { - var n = sizeFromShape(shape); - var numCols = strides[strides.length - 1]; - var padPerCol = new Array(numCols).fill(0); - var rank = shape.length; - var valuesOrTuples = dtype === 'complex64' ? createComplexTuples(vals) : vals; - if (rank > 1) { - for (var row = 0; row < n / numCols; row++) { - var offset = row * numCols; - for (var j = 0; j < numCols; j++) { - padPerCol[j] = Math.max(padPerCol[j], valToString(valuesOrTuples[offset + j], 0, dtype).length); - } - } - } - return padPerCol; - } - function valToString(val, pad, dtype) { - var valStr; - if (Array.isArray(val)) { - valStr = parseFloat(val[0].toFixed(FORMAT_NUM_SIG_DIGITS)) + " + " + - (parseFloat(val[1].toFixed(FORMAT_NUM_SIG_DIGITS)) + "j"); - } - else if (isString(val)) { - valStr = "'" + val + "'"; - } - else if (dtype === 'bool') { - valStr = boolNumToString(val); - } - else { - valStr = parseFloat(val.toFixed(FORMAT_NUM_SIG_DIGITS)).toString(); - } - return rightPad(valStr, pad); - } - function boolNumToString(v) { - return v === 0 ? 'false' : 'true'; - } - function subTensorToString(vals, shape, dtype, strides, padPerCol, isLast) { - if (isLast === void 0) { isLast = true; } - var storagePerElement = dtype === 'complex64' ? 2 : 1; - var size = shape[0]; - var rank = shape.length; - if (rank === 0) { - if (dtype === 'complex64') { - var complexTuple = createComplexTuples(vals); - return [valToString(complexTuple[0], 0, dtype)]; - } - if (dtype === 'bool') { - return [boolNumToString(vals[0])]; - } - return [vals[0].toString()]; - } - if (rank === 1) { - if (size > FORMAT_LIMIT_NUM_VALS) { - var firstValsSize = FORMAT_NUM_FIRST_LAST_VALS * storagePerElement; - var firstVals = Array.from(vals.slice(0, firstValsSize)); - var lastVals = Array.from(vals.slice((size - FORMAT_NUM_FIRST_LAST_VALS) * storagePerElement, size * storagePerElement)); - if (dtype === 'complex64') { - firstVals = createComplexTuples(firstVals); - lastVals = createComplexTuples(lastVals); - } - return [ - '[' + - firstVals.map(function (x, i) { return valToString(x, padPerCol[i], dtype); }) - .join(', ') + - ', ..., ' + - lastVals - .map(function (x, i) { return valToString(x, padPerCol[size - FORMAT_NUM_FIRST_LAST_VALS + i], dtype); }) - .join(', ') + - ']' - ]; - } - var displayVals = dtype === 'complex64' ? createComplexTuples(vals) : - Array.from(vals); - return [ - '[' + - displayVals.map(function (x, i) { return valToString(x, padPerCol[i], dtype); }) - .join(', ') + - ']' - ]; - } - // The array is rank 2 or more. - var subshape = shape.slice(1); - var substrides = strides.slice(1); - var stride = strides[0] * storagePerElement; - var lines = []; - if (size > FORMAT_LIMIT_NUM_VALS) { - for (var i = 0; i < FORMAT_NUM_FIRST_LAST_VALS; i++) { - var start = i * stride; - var end = start + stride; - lines.push.apply(lines, subTensorToString(vals.slice(start, end), subshape, dtype, substrides, padPerCol, false /* isLast */)); - } - lines.push('...'); - for (var i = size - FORMAT_NUM_FIRST_LAST_VALS; i < size; i++) { - var start = i * stride; - var end = start + stride; - lines.push.apply(lines, subTensorToString(vals.slice(start, end), subshape, dtype, substrides, padPerCol, i === size - 1 /* isLast */)); - } - } - else { - for (var i = 0; i < size; i++) { - var start = i * stride; - var end = start + stride; - lines.push.apply(lines, subTensorToString(vals.slice(start, end), subshape, dtype, substrides, padPerCol, i === size - 1 /* isLast */)); - } - } - var sep = rank === 2 ? ',' : ''; - lines[0] = '[' + lines[0] + sep; - for (var i = 1; i < lines.length - 1; i++) { - lines[i] = ' ' + lines[i] + sep; - } - var newLineSep = ',\n'; - for (var i = 2; i < rank; i++) { - newLineSep += '\n'; - } - lines[lines.length - 1] = - ' ' + lines[lines.length - 1] + ']' + (isLast ? '' : newLineSep); - return lines; - } - function createComplexTuples(vals) { - var complexTuples = []; - for (var i = 0; i < vals.length; i += 2) { - complexTuples.push([vals[i], vals[i + 1]]); - } - return complexTuples; - } - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * A mutable object, similar to `tf.Tensor`, that allows users to set values - * at locations before converting to an immutable `tf.Tensor`. - * - * See `tf.buffer` for creating a tensor buffer. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - var TensorBuffer = /** @class */ (function () { - function TensorBuffer(shape, dtype, values) { - var _this = this; - this.dtype = dtype; - this.shape = shape.slice(); - this.size = sizeFromShape(shape); - if (values != null) { - var n_1 = values.length; - assert(n_1 === this.size, function () { return "Length of values '" + n_1 + "' does not match the size " + - ("inferred by the shape '" + _this.size + "'."); }); - } - if (dtype === 'complex64') { - throw new Error("complex64 dtype TensorBuffers are not supported. Please create " + - "a TensorBuffer for the real and imaginary parts separately and " + - "call tf.complex(real, imag)."); - } - this.values = values || getArrayFromDType(dtype, this.size); - this.strides = computeStrides(shape); - } - /** - * Sets a value in the buffer at a given location. - * - * @param value The value to set. - * @param locs The location indices. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - TensorBuffer.prototype.set = function (value) { - var _this = this; - var locs = []; - for (var _i = 1; _i < arguments.length; _i++) { - locs[_i - 1] = arguments[_i]; - } - if (locs.length === 0) { - locs = [0]; - } - assert(locs.length === this.rank, function () { return "The number of provided coordinates (" + locs.length + ") must " + - ("match the rank (" + _this.rank + ")"); }); - var index = this.locToIndex(locs); - this.values[index] = value; - }; - /** - * Returns the value in the buffer at the provided location. - * - * @param locs The location indices. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - TensorBuffer.prototype.get = function () { - var locs = []; - for (var _i = 0; _i < arguments.length; _i++) { - locs[_i] = arguments[_i]; - } - if (locs.length === 0) { - locs = [0]; - } - var i = 0; - for (var _a = 0, locs_1 = locs; _a < locs_1.length; _a++) { - var loc = locs_1[_a]; - if (loc < 0 || loc >= this.shape[i]) { - var msg = "Requested out of range element at " + locs + ". " + - (" Buffer shape=" + this.shape); - throw new Error(msg); - } - i++; - } - var index = locs[locs.length - 1]; - for (var i_1 = 0; i_1 < locs.length - 1; ++i_1) { - index += this.strides[i_1] * locs[i_1]; - } - return this.values[index]; - }; - TensorBuffer.prototype.locToIndex = function (locs) { - if (this.rank === 0) { - return 0; - } - else if (this.rank === 1) { - return locs[0]; - } - var index = locs[locs.length - 1]; - for (var i = 0; i < locs.length - 1; ++i) { - index += this.strides[i] * locs[i]; - } - return index; - }; - TensorBuffer.prototype.indexToLoc = function (index) { - if (this.rank === 0) { - return []; - } - else if (this.rank === 1) { - return [index]; - } - var locs = new Array(this.shape.length); - for (var i = 0; i < locs.length - 1; ++i) { - locs[i] = Math.floor(index / this.strides[i]); - index -= locs[i] * this.strides[i]; - } - locs[locs.length - 1] = index; - return locs; - }; - Object.defineProperty(TensorBuffer.prototype, "rank", { - get: function () { - return this.shape.length; - }, - enumerable: true, - configurable: true - }); - /** - * Creates an immutable `tf.Tensor` object from the buffer. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - TensorBuffer.prototype.toTensor = function () { - return trackerFn().makeTensor(this.values, this.shape, this.dtype); - }; - return TensorBuffer; - }()); - // For tracking tensor creation and disposal. - var trackerFn = null; - // Used by chaining methods to call into ops. - var opHandler = null; - /** - * An external consumer can register itself as the tensor tracker. This way - * the Tensor class can notify the tracker for every tensor created and - * disposed. - */ - function setTensorTracker(fn) { - trackerFn = fn; - } - /** - * An external consumer can register itself as the op handler. This way the - * Tensor class can have chaining methods that call into ops via the op - * handler. - */ - function setOpHandler(handler) { - opHandler = handler; - } - /** - * A `tf.Tensor` object represents an immutable, multidimensional array of - * numbers that has a shape and a data type. - * - * See `tf.tensor` for details on how to create a `tf.Tensor`. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - var Tensor = /** @class */ (function () { - function Tensor(shape, dtype, dataId, id) { - /** Whether this tensor has been globally kept. */ - this.kept = false; - this.isDisposedInternal = false; - this.shape = shape.slice(); - this.dtype = dtype || 'float32'; - this.size = sizeFromShape(shape); - this.strides = computeStrides(shape); - this.dataId = dataId; - this.id = id; - this.rankType = (this.rank < 5 ? this.rank.toString() : 'higher'); - } - Object.defineProperty(Tensor.prototype, "rank", { - get: function () { - return this.shape.length; - }, - enumerable: true, - configurable: true - }); - /** - * Returns a promise of `tf.TensorBuffer` that holds the underlying data. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.buffer = function () { - return __awaiter(this, void 0, void 0, function () { - var vals; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.data()]; - case 1: - vals = _a.sent(); - return [2 /*return*/, opHandler.buffer(this.shape, this.dtype, vals)]; - } - }); - }); - }; - /** Returns a `tf.TensorBuffer` that holds the underlying data. */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.bufferSync = function () { - return opHandler.buffer(this.shape, this.dtype, this.dataSync()); - }; - /** - * Returns the tensor data as a nested array. The transfer of data is done - * asynchronously. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.array = function () { - return __awaiter(this, void 0, void 0, function () { - var vals; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.data()]; - case 1: - vals = _a.sent(); - return [2 /*return*/, toNestedArray(this.shape, vals)]; - } - }); - }); - }; - /** - * Returns the tensor data as a nested array. The transfer of data is done - * synchronously. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.arraySync = function () { - return toNestedArray(this.shape, this.dataSync()); - }; - /** - * Asynchronously downloads the values from the `tf.Tensor`. Returns a - * promise of `TypedArray` that resolves when the computation has finished. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.data = function () { - return __awaiter(this, void 0, void 0, function () { - var data, bytes; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - this.throwIfDisposed(); - data = trackerFn().read(this.dataId); - if (!(this.dtype === 'string')) return [3 /*break*/, 2]; - return [4 /*yield*/, data]; - case 1: - bytes = _a.sent(); - try { - return [2 /*return*/, bytes.map(function (b) { return decodeString(b); })]; - } - catch (_b) { - throw new Error('Failed to decode the string bytes into utf-8. ' + - 'To get the original bytes, call tensor.bytes().'); - } - _a.label = 2; - case 2: return [2 /*return*/, data]; - } - }); - }); - }; - /** - * Synchronously downloads the values from the `tf.Tensor`. This blocks the - * UI thread until the values are ready, which can cause performance issues. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.dataSync = function () { - this.throwIfDisposed(); - var data = trackerFn().readSync(this.dataId); - if (this.dtype === 'string') { - try { - return data.map(function (b) { return decodeString(b); }); - } - catch (_a) { - throw new Error('Failed to decode the string bytes into utf-8. ' + - 'To get the original bytes, call tensor.bytes().'); - } - } - return data; - }; - /** Returns the underlying bytes of the tensor's data. */ - Tensor.prototype.bytes = function () { - return __awaiter(this, void 0, void 0, function () { - var data; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - this.throwIfDisposed(); - return [4 /*yield*/, trackerFn().read(this.dataId)]; - case 1: - data = _a.sent(); - if (this.dtype === 'string') { - return [2 /*return*/, data]; - } - else { - return [2 /*return*/, new Uint8Array(data.buffer)]; - } - } - }); - }); - }; - /** - * Disposes `tf.Tensor` from memory. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.dispose = function () { - if (this.isDisposed) { - return; - } - trackerFn().disposeTensor(this); - this.isDisposedInternal = true; - }; - Object.defineProperty(Tensor.prototype, "isDisposed", { - get: function () { - return this.isDisposedInternal; - }, - enumerable: true, - configurable: true - }); - Tensor.prototype.throwIfDisposed = function () { - if (this.isDisposed) { - throw new Error("Tensor is disposed."); - } - }; - /** - * Prints the `tf.Tensor`. See `tf.print` for details. - * - * @param verbose Whether to print verbose information about the tensor, - * including dtype and size. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.print = function (verbose) { - if (verbose === void 0) { verbose = false; } - return opHandler.print(this, verbose); - }; - /** Returns a copy of the tensor. See `tf.clone` for details. */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.clone = function () { - this.throwIfDisposed(); - return opHandler.clone(this); - }; - /** - * Returns a human-readable description of the tensor. Useful for logging. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.toString = function (verbose) { - if (verbose === void 0) { verbose = false; } - var vals = this.dataSync(); - return tensorToString(vals, this.shape, this.dtype, verbose); - }; - Tensor.prototype.cast = function (dtype) { - this.throwIfDisposed(); - return opHandler.cast(this, dtype); - }; - Tensor.prototype.variable = function (trainable, name, dtype) { - if (trainable === void 0) { trainable = true; } - this.throwIfDisposed(); - return trackerFn().makeVariable(this, trainable, name, dtype); - }; - return Tensor; - }()); - Object.defineProperty(Tensor, Symbol.hasInstance, { - value: function (instance) { - return !!instance && instance.dataId != null && instance.shape != null && - instance.dtype != null; - } - }); - /** - * A mutable `tf.Tensor`, useful for persisting state, e.g. for training. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - var Variable = /** @class */ (function (_super) { - __extends(Variable, _super); - function Variable(initialValue, trainable, name, tensorId) { - var _this = _super.call(this, initialValue.shape, initialValue.dtype, initialValue.dataId, tensorId) || this; - _this.trainable = trainable; - _this.name = name; - return _this; - } - /** - * Assign a new `tf.Tensor` to this variable. The new `tf.Tensor` must have - * the same shape and dtype as the old `tf.Tensor`. - * - * @param newValue New tensor to be assigned to this variable. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Variable.prototype.assign = function (newValue) { - if (newValue.dtype !== this.dtype) { - throw new Error("dtype of the new value (" + newValue.dtype + ") and " + - ("previous value (" + this.dtype + ") must match")); - } - if (!arraysEqual(newValue.shape, this.shape)) { - throw new Error("shape of the new value (" + newValue.shape + ") and " + - ("previous value (" + this.shape + ") must match")); - } - trackerFn().disposeTensor(this); - this.dataId = newValue.dataId; - trackerFn().incRef(this, null /* backend */); - }; - Variable.prototype.dispose = function () { - trackerFn().disposeVariable(this); - this.isDisposedInternal = true; - }; - return Variable; - }(Tensor)); - Object.defineProperty(Variable, Symbol.hasInstance, { - value: function (instance) { - return instance instanceof Tensor && instance.assign != null && - instance.assign instanceof Function; - } - }); - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - (function (Rank) { - Rank["R0"] = "R0"; - Rank["R1"] = "R1"; - Rank["R2"] = "R2"; - Rank["R3"] = "R3"; - Rank["R4"] = "R4"; - Rank["R5"] = "R5"; - Rank["R6"] = "R6"; - })(exports.Rank || (exports.Rank = {})); - // Looks for upcasting types. Used, for example, in operations with mixed dtype - // inputs. - var UpcastInt32AndMap; - (function (UpcastInt32AndMap) { - UpcastInt32AndMap["float32"] = "float32"; - UpcastInt32AndMap["int32"] = "int32"; - UpcastInt32AndMap["bool"] = "int32"; - UpcastInt32AndMap["complex64"] = "complex64"; - })(UpcastInt32AndMap || (UpcastInt32AndMap = {})); - var UpcastBoolAndMap; - (function (UpcastBoolAndMap) { - UpcastBoolAndMap["float32"] = "float32"; - UpcastBoolAndMap["int32"] = "int32"; - UpcastBoolAndMap["bool"] = "bool"; - UpcastBoolAndMap["complex64"] = "complex64"; - })(UpcastBoolAndMap || (UpcastBoolAndMap = {})); - var UpcastFloat32AndMap; - (function (UpcastFloat32AndMap) { - UpcastFloat32AndMap["float32"] = "float32"; - UpcastFloat32AndMap["int32"] = "float32"; - UpcastFloat32AndMap["bool"] = "float32"; - UpcastFloat32AndMap["complex64"] = "complex64"; - })(UpcastFloat32AndMap || (UpcastFloat32AndMap = {})); - var UpcastComplex64AndMap; - (function (UpcastComplex64AndMap) { - UpcastComplex64AndMap["float32"] = "complex64"; - UpcastComplex64AndMap["int32"] = "complex64"; - UpcastComplex64AndMap["bool"] = "complex64"; - UpcastComplex64AndMap["complex64"] = "complex64"; - })(UpcastComplex64AndMap || (UpcastComplex64AndMap = {})); - var upcastTypeMap = { - 'float32': UpcastFloat32AndMap, - 'int32': UpcastInt32AndMap, - 'bool': UpcastBoolAndMap, - 'complex64': UpcastComplex64AndMap - }; - function upcastType(typeA, typeB) { - if (typeA === 'string' || typeB === 'string') { - if (typeA === 'string' && typeB === 'string') { - return 'string'; - } - throw new Error("Can not upcast " + typeA + " with " + typeB); - } - return upcastTypeMap[typeA][typeB]; - } - /** Returns the output type after summation. */ - function sumOutType(type) { - return upcastType(type, 'int32'); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function makeTypesMatch(a, b) { - if (a.dtype === b.dtype) { - return [a, b]; - } - var dtype = upcastType(a.dtype, b.dtype); - return [a.cast(dtype), b.cast(dtype)]; - } - function assertTypesMatch(a, b) { - assert(a.dtype === b.dtype, function () { return "The dtypes of the first(" + a.dtype + ") and" + - (" second(" + b.dtype + ") input must match"); }); - } - function isTensorInList(tensor, tensorList) { - return tensorList.some(function (x) { return x.id === tensor.id; }); - } - /** - * Extracts any `Tensor`s found within the provided object. - * - * @param container an object that may be a `Tensor` or may directly contain - * `Tensor`s, such as a `Tensor[]` or `{key: Tensor, ...}`. In general it - * is safe to pass any object here, except that `Promise`s are not - * supported. - * @returns An array of `Tensors` found within the passed object. If the - * argument is simply a `Tensor', a list containing that `Tensor` is - * returned. If the object is not a `Tensor` or does not - * contain `Tensors`, an empty list is returned. - */ - function getTensorsInContainer(result) { - var list = []; - var seen = new Set(); - walkTensorContainer(result, list, seen); - return list; - } - function walkTensorContainer(container, list, seen) { - if (container == null) { - return; - } - if (container instanceof Tensor) { - list.push(container); - return; - } - if (!isIterable(container)) { - return; - } - // Iteration over keys works also for arrays. - var iterable = container; - for (var k in iterable) { - var val = iterable[k]; - if (!seen.has(val)) { - seen.add(val); - walkTensorContainer(val, list, seen); - } - } - } - // tslint:disable-next-line:no-any - function isIterable(obj) { - return Array.isArray(obj) || typeof obj === 'object'; - } - - var tensor_util = { - __proto__: null, - makeTypesMatch: makeTypesMatch, - assertTypesMatch: assertTypesMatch, - isTensorInList: isTensorInList, - getTensorsInContainer: getTensorsInContainer - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var EngineState = /** @class */ (function () { - function EngineState() { - // Public since optimizers will use it. - this.registeredVariables = {}; - this.nextTapeNodeId = 0; - this.numBytes = 0; - this.numTensors = 0; - this.numStringTensors = 0; - this.numDataBuffers = 0; - // Number of nested tf.grad() statements when computing higher-order - // gradients. E.g. `1` for first-order gradients and `2` for second-order - // gradients. Used to track if the tape should be removed after a backprop. - this.gradientDepth = 0; - // Number of nested kernel calls. When kernel depth is greater than 1, we turn - // off the tape. - this.kernelDepth = 0; - this.scopeStack = []; - /** - * Keeps track of the number of data moves during a kernel execution. We - * maintain a stack since kernels can call other kernels, recursively. - */ - this.numDataMovesStack = []; - this.nextScopeId = 0; - this.tensorInfo = new WeakMap(); - this.profiling = false; - this.activeProfile = { newBytes: 0, newTensors: 0, peakBytes: 0, kernels: [], result: null }; - } - EngineState.prototype.dispose = function () { - for (var variableName in this.registeredVariables) { - this.registeredVariables[variableName].dispose(); - } - }; - return EngineState; - }()); - var Engine = /** @class */ (function () { - function Engine(ENV) { - this.ENV = ENV; - this.registry = {}; - this.registryFactory = {}; - this.pendingBackendInitId = 0; - this.state = new EngineState(); - } - Engine.prototype.ready = function () { - return __awaiter(this, void 0, void 0, function () { - var sortedBackends, i, backendName, success; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (this.pendingBackendInit != null) { - return [2 /*return*/, this.pendingBackendInit.then(function () { })]; - } - if (this.backendInstance != null) { - return [2 /*return*/]; - } - sortedBackends = this.getSortedBackends(); - i = 0; - _a.label = 1; - case 1: - if (!(i < sortedBackends.length)) return [3 /*break*/, 5]; - backendName = sortedBackends[i]; - return [4 /*yield*/, this.initializeBackend(backendName).success]; - case 2: - success = _a.sent(); - if (!success) return [3 /*break*/, 4]; - return [4 /*yield*/, this.setBackend(backendName)]; - case 3: - _a.sent(); - return [2 /*return*/]; - case 4: - i++; - return [3 /*break*/, 1]; - case 5: throw new Error("Could not initialize any backends, all backend initializations " + - "failed."); - } - }); - }); - }; - Object.defineProperty(Engine.prototype, "backend", { - get: function () { - if (this.pendingBackendInit != null) { - throw new Error("Backend '" + this.backendName + "' has not yet been initialized. Make " + - "sure to await tf.ready() or await tf.setBackend() before calling " + - "other methods"); - } - if (this.backendInstance == null) { - var _a = this.initializeBackendsAndReturnBest(), name_1 = _a.name, asyncInit = _a.asyncInit; - if (asyncInit) { - throw new Error("The highest priority backend '" + name_1 + "' has not yet been " + - "initialized. Make sure to await tf.ready() or " + - "await tf.setBackend() before calling other methods"); - } - this.setBackend(name_1); - } - return this.backendInstance; - }, - enumerable: true, - configurable: true - }); - Engine.prototype.backendNames = function () { - return Object.keys(this.registryFactory); - }; - Engine.prototype.findBackend = function (backendName) { - if (!(backendName in this.registry)) { - // If the backend hasn't been initialized but we have a registry entry for - // it, initialize it and return it. - if (backendName in this.registryFactory) { - var asyncInit = this.initializeBackend(backendName).asyncInit; - if (asyncInit) { - // Backend is not ready yet. - return null; - } - } - else { - return null; - } - } - return this.registry[backendName]; - }; - Engine.prototype.findBackendFactory = function (backendName) { - if (!(backendName in this.registryFactory)) { - return null; - } - return this.registryFactory[backendName].factory; - }; - Engine.prototype.registerBackend = function (backendName, factory, priority) { - if (priority === void 0) { priority = 1; } - if (backendName in this.registryFactory) { - console.warn(backendName + " backend was already registered. " + - "Reusing existing backend factory."); - return false; - } - this.registryFactory[backendName] = { factory: factory, priority: priority }; - return true; - }; - Engine.prototype.setBackend = function (backendName) { - return __awaiter(this, void 0, void 0, function () { - var _a, success, asyncInit, result, _b; - return __generator(this, function (_c) { - switch (_c.label) { - case 0: - if (this.registryFactory[backendName] == null) { - throw new Error("Backend name '" + backendName + "' not found in registry"); - } - this.backendName = backendName; - if (!(this.registry[backendName] == null)) return [3 /*break*/, 4]; - this.backendInstance = null; - _a = this.initializeBackend(backendName), success = _a.success, asyncInit = _a.asyncInit; - if (!asyncInit) return [3 /*break*/, 2]; - return [4 /*yield*/, success]; - case 1: - _b = _c.sent(); - return [3 /*break*/, 3]; - case 2: - _b = success; - _c.label = 3; - case 3: - result = _b; - if (!result) { - return [2 /*return*/, false]; - } - _c.label = 4; - case 4: - this.backendInstance = this.registry[backendName]; - this.setupRegisteredKernels(); - // Reset the profiler. - this.profiler = new Profiler(this.backendInstance); - return [2 /*return*/, true]; - } - }); - }); - }; - Engine.prototype.setupRegisteredKernels = function () { - var _this = this; - var kernels = getKernelsForBackend(this.backendName); - kernels.forEach(function (kernel) { - if (kernel.setupFunc != null) { - kernel.setupFunc(_this.backendInstance); - } - }); - }; - Engine.prototype.disposeRegisteredKernels = function (backendName) { - var _this = this; - var kernels = getKernelsForBackend(backendName); - kernels.forEach(function (kernel) { - if (kernel.disposeFunc != null) { - kernel.disposeFunc(_this.registry[backendName]); - } - }); - }; - /** - * Initializes a backend by looking up the backend name in the factory - * registry and calling the factory method. Returns a boolean representing - * whether the initialization of the backend suceeded. Throws an error if - * there is no backend in the factory registry. - */ - Engine.prototype.initializeBackend = function (backendName) { - var _this = this; - var registryFactoryEntry = this.registryFactory[backendName]; - if (registryFactoryEntry == null) { - throw new Error("Cannot initialize backend " + backendName + ", no registration found."); - } - try { - var backend = registryFactoryEntry.factory(); - // Test if the factory returns a promise. - if (Promise.resolve(backend) === backend) { - var promiseId_1 = ++this.pendingBackendInitId; - var success = backend - .then(function (backendInstance) { - // Outdated promise. Another backend was set in the meantime. - if (promiseId_1 < _this.pendingBackendInitId) { - return false; - } - _this.registry[backendName] = backendInstance; - _this.pendingBackendInit = null; - return true; - }) - .catch(function (err) { - // Outdated promise. Another backend was set in the meantime. - if (promiseId_1 < _this.pendingBackendInitId) { - return false; - } - _this.pendingBackendInit = null; - console.warn("Initialization of backend " + backendName + " failed"); - console.warn(err.stack || err.message); - return false; - }); - this.pendingBackendInit = success; - return { success: success, asyncInit: true }; - } - else { - this.registry[backendName] = backend; - return { success: true, asyncInit: false }; - } - } - catch (err) { - console.warn("Initialization of backend " + backendName + " failed"); - console.warn(err.stack || err.message); - return { success: false, asyncInit: false }; - } - }; - Engine.prototype.removeBackend = function (backendName) { - if (!(backendName in this.registryFactory)) { - throw new Error(backendName + " backend not found in registry"); - } - if (this.backendName === backendName && this.pendingBackendInit != null) { - // There is a pending promise of the backend we want to remove. Make it - // obsolete. - this.pendingBackendInitId++; - } - if (backendName in this.registry) { - this.disposeRegisteredKernels(backendName); - this.registry[backendName].dispose(); - delete this.registry[backendName]; - } - delete this.registryFactory[backendName]; - // Unset the backend if it is active. - if (this.backendName === backendName) { - this.pendingBackendInit = null; - this.backendName = null; - this.backendInstance = null; - } - }; - Engine.prototype.getSortedBackends = function () { - var _this = this; - if (Object.keys(this.registryFactory).length === 0) { - throw new Error('No backend found in registry.'); - } - return Object.keys(this.registryFactory).sort(function (a, b) { - // Highest priority comes first. - return _this.registryFactory[b].priority - - _this.registryFactory[a].priority; - }); - }; - Engine.prototype.initializeBackendsAndReturnBest = function () { - var sortedBackends = this.getSortedBackends(); - for (var i = 0; i < sortedBackends.length; i++) { - var backendName = sortedBackends[i]; - var _a = this.initializeBackend(backendName), success = _a.success, asyncInit = _a.asyncInit; - if (asyncInit || success) { - return { name: backendName, asyncInit: asyncInit }; - } - } - throw new Error("Could not initialize any backends, all backend initializations " + - "failed."); - }; - Engine.prototype.moveData = function (backend, dataId) { - var info = this.state.tensorInfo.get(dataId); - var srcBackend = info.backend; - var values = this.readSync(dataId); - // Delete the tensor from the old backend and move it to the new - // backend. - srcBackend.disposeData(dataId); - info.backend = backend; - backend.move(dataId, values, info.shape, info.dtype); - if (this.shouldCheckForMemLeaks()) { - // Track the number of moves during a kernel execution to correctly - // detect memory leaks. - this.state.numDataMovesStack[this.state.numDataMovesStack.length - 1]++; - } - }; - Engine.prototype.tidy = function (nameOrFn, fn) { - var _this = this; - var name = null; - if (fn == null) { - // Called with only 1 argument. - if (typeof nameOrFn !== 'function') { - throw new Error('Please provide a function to tidy()'); - } - fn = nameOrFn; - } - else { - // Called with 2 arguments. - if (typeof nameOrFn !== 'string' && !(nameOrFn instanceof String)) { - throw new Error('When calling with two arguments, the first argument ' + - 'to tidy() must be a string'); - } - if (typeof fn !== 'function') { - throw new Error('When calling with two arguments, the 2nd argument ' + - 'to tidy() must be a function'); - } - name = nameOrFn; - // TODO(nsthorat,smilkov): Do operation logging and performance - // profiling. - } - var result; - return this.scopedRun(function () { return _this.startScope(name); }, function () { return _this.endScope(result); }, function () { - result = fn(); - if (result instanceof Promise) { - console.error('Cannot return a Promise inside of tidy.'); - } - return result; - }); - }; - Engine.prototype.scopedRun = function (start, end, f) { - start(); - try { - var res = f(); - end(); - return res; - } - catch (ex) { - end(); - throw ex; - } - }; - Engine.prototype.nextTensorId = function () { - return Engine.nextTensorId++; - }; - Engine.prototype.nextVariableId = function () { - return Engine.nextVariableId++; - }; - /** - * This method is called instead of the public-facing tensor.clone() when - * saving a tensor for backwards pass. It makes sure to add the clone - * operation to the tape regardless of being called inside a kernel - * execution. - * - * This method will go away once all kernels are modularized since we won't - * need to turn off the tape inside runKernel(). - */ - Engine.prototype.clone = function (x) { - var y = this.makeTensorFromDataId(x.dataId, x.shape, x.dtype); - var inputs = { x: x }; - var grad = function (dy) { return ({ x: function () { return dy.toFloat(); } }); }; - var saved = []; - this.addTapeNode(this.state.activeScope.name, inputs, [y], grad, saved, {}); - return y; - }; - /** - * Execute a kernel with the given name and return the output tensor. - * - * @param kernelName The name of the kernel to execute. - * @param inputs A map of input names to tensors. - * @param attrs A map of attribute names to their values. An attribute is a - * primitive (non-tensor) input to the kernel. - * @param inputsToSave A list of tensors, inputs to save for the backprop - * computation. - * @param outputsToSave A list of booleans, specifying which output to save - * for the backprop computation. These are booleans since the output - * tensors are not visible to the user. - */ - Engine.prototype.runKernel = function (kernelName, inputs, attrs, inputsToSave, outputsToSave) { - var forwardFunc = null; - var backwardsFunc = null; - // Call runKernel as a stop-gap until we modularize all kernels. - // Once we modularize all kernels, we will remove the existing - // `runKernelFunc`. - return this.runKernelFunc(forwardFunc, inputs, backwardsFunc, kernelName, attrs, inputsToSave, outputsToSave); - }; - Engine.prototype.shouldCheckForMemLeaks = function () { - return this.ENV.getBool('IS_TEST'); - }; - Engine.prototype.checkKernelForMemLeak = function (kernelName, numDataIdsBefore, outInfos) { - var numDataIdsAfter = this.backend.numDataIds(); - // Count the number of data ids associated with the result of the kernel. - var numOutputDataIds = 0; - outInfos.forEach(function (info) { - // Complex numbers allocate 3 data ids, one for 'real', one for - // 'imaginary', and one for the container that holds the former two. - numOutputDataIds += (info.dtype === 'complex64' ? 3 : 1); - }); - // Account for the number of moves during kernel execution. A "data move" - // can happen in the middle of a kernel execution, placing a new (key,value) - // pair in the data storage. Since data moves have net zero effect (we - // always remove the data from the old backend), we have to cancel them out - // when detecting memory leaks. - var numMoves = this.state.numDataMovesStack[this.state.numDataMovesStack.length - 1]; - var dataIdsLeaked = numDataIdsAfter - numDataIdsBefore - numOutputDataIds - numMoves; - if (dataIdsLeaked > 0) { - throw new Error("Backend '" + this.backendName + "' has an internal memory leak " + - ("(" + dataIdsLeaked + " data ids) after running '" + kernelName + "'")); - } - }; - /** - * @deprecated Use `runKernel` for newly added kernels. Keep using this method - * only for kernels that are not yet fully modularized. - */ - Engine.prototype.runKernelFunc = function (forwardFunc, inputs, backwardsFunc, kernelName, attrs, inputsToSave, outputsToSave) { - var _this = this; - var outputs; - var saved = []; - var isTapeOn = this.isTapeOn(); - if (kernelName == null) { - kernelName = - this.state.activeScope != null ? this.state.activeScope.name : ''; - } - var startingBytecount = this.state.numBytes; - var startingNumTensors = this.state.numTensors; - if (this.shouldCheckForMemLeaks()) { - this.state.numDataMovesStack.push(0); - } - var kernelFunc; - var kernel = getKernel(kernelName, this.backendName); - var out; - if (kernel != null) { - kernelFunc = function () { - var numDataIdsBefore = _this.backend.numDataIds(); - out = kernel.kernelFunc({ inputs: inputs, attrs: attrs, backend: _this.backend }); - var outInfos = Array.isArray(out) ? out : [out]; - if (_this.shouldCheckForMemLeaks()) { - _this.checkKernelForMemLeak(kernelName, numDataIdsBefore, outInfos); - } - var outTensors = outInfos.map(function (_a) { - var dataId = _a.dataId, shape = _a.shape, dtype = _a.dtype; - return _this.makeTensorFromDataId(dataId, shape, dtype); - }); - // Save the inputs and outputs. - // Do not save unless we are recording to the tape. Otherwise it would - // cause a mem leak since we would never run backprop, which disposes - // the kept tensors. - if (isTapeOn) { - var tensorsToSave = _this.getTensorsForGradient(kernelName, inputs, outTensors); - if (tensorsToSave == null) { - // Fallback for ops that call runKernelFunc and pass in - // inputsToSave and outputsToSave. Currently this is the set of ops - // with kernel support in the WASM backend. Once those ops and - // respective gradients are modularised we can remove this path. - if (outputsToSave == null) { - outputsToSave = []; - } - var outsToSave = outTensors.filter(function (_, i) { return outputsToSave[i]; }); - tensorsToSave = (inputsToSave || []).slice().concat(outsToSave); - } - saved = _this.saveTensorsForBackwardMode(tensorsToSave); - } - return outTensors; - }; - } - else { - var saveFunc_1 = function (tensors) { - // Do not save unless we are recording to the tape. Otherwise it would - // cause a mem leak since we would never run backprop, which disposes - // the kept tensors. - if (!isTapeOn) { - return; - } - saved = tensors.map(function (tensor) { return _this.keep(_this.clone(tensor)); }); - }; - kernelFunc = function () { - var numDataIdsBefore = _this.backend.numDataIds(); - out = _this.tidy(function () { return forwardFunc(_this.backend, saveFunc_1); }); - var outs = (Array.isArray(out) ? out : [out]); - if (_this.shouldCheckForMemLeaks()) { - _this.checkKernelForMemLeak(kernelName, numDataIdsBefore, outs); - } - return outs; - }; - } - // Stop recording to a tape when running a kernel. - this.scopedRun(function () { return _this.state.kernelDepth++; }, function () { return _this.state.kernelDepth--; }, function () { - if (!_this.ENV.getBool('DEBUG')) { - outputs = kernelFunc(); - } - else { - outputs = _this.profiler.profileKernel(kernelName, inputs, function () { return kernelFunc(); }); - } - }); - if (isTapeOn) { - this.addTapeNode(kernelName, inputs, outputs, backwardsFunc, saved, attrs); - } - if (this.state.profiling) { - this.state.activeProfile.kernels.push({ - name: kernelName, - bytesAdded: this.state.numBytes - startingBytecount, - totalBytesSnapshot: this.state.numBytes, - tensorsAdded: this.state.numTensors - startingNumTensors, - totalTensorsSnapshot: this.state.numTensors, - inputShapes: Object.keys(inputs).map(function (key) { return inputs[key].shape; }), - outputShapes: outputs.map(function (item) { return item.shape; }) - }); - } - return (Array.isArray(out) ? outputs : outputs[0]); - }; - /** - * Saves tensors used in forward mode for use in backward mode. - * - * @param tensors the list of tensors to save. - */ - Engine.prototype.saveTensorsForBackwardMode = function (tensors) { - var _this = this; - var saved = tensors.map(function (tensor) { return _this.keep(_this.clone(tensor)); }); - return saved; - }; - /** - * Returns a list of tensors to save for a given gradient calculation. - * - * Returns undefined if their is no registered gradient for this kernel in the - * gradient registry. - * - * @param kernelName name of kernel to look up gradient for. - * @param inputs a map of input tensors. - * @param outputs an array of output tensors from forward mode of kernel. - */ - Engine.prototype.getTensorsForGradient = function (kernelName, inputs, outputs) { - var gradConfig = getGradient(kernelName); - if (gradConfig != null) { - var inputsToSave = gradConfig.inputsToSave || []; - var outputsToSave_1 = gradConfig.outputsToSave || []; - // If saveAllInputs is true, all inputs will be saved. Otherwise, inputs - // specified in inputsToSave will be saved. - var inputTensorsToSave = void 0; - if (gradConfig.saveAllInputs) { - assert(Array.isArray(inputs), function () { return 'saveAllInputs is true, expected inputs to be an array.'; }); - inputTensorsToSave = Object.keys(inputs).map(function (key) { return inputs[key]; }); - } - else { - inputTensorsToSave = inputsToSave.map(function (inputName) { return inputs[inputName]; }); - } - var outputTensorsToSave = outputs.filter(function (_, i) { return outputsToSave_1[i]; }); - return inputTensorsToSave.concat(outputTensorsToSave); - } - // TODO(yassogba) throw exception here once all runkernelFunc calls with - // inputsToSave/outputsToSave are removed - return null; - }; - /** - * Internal method used by public APIs for tensor creation. Makes a new - * tensor with the provided shape, dtype and values. It always - * creates a new data id and writes the values to the underlying backend. - */ - Engine.prototype.makeTensor = function (values, shape, dtype, backend) { - if (values == null) { - throw new Error('Values passed to engine.makeTensor() are null'); - } - dtype = dtype || 'float32'; - backend = backend || this.backend; - var backendVals = values; - if (dtype === 'string' && isString(values[0])) { - backendVals = values.map(function (d) { return encodeString(d); }); - } - var dataId = backend.write(backendVals, shape, dtype); - var t = new Tensor(shape, dtype, dataId, this.nextTensorId()); - this.incRef(t, backend); - // Count bytes for string tensors. - if (dtype === 'string') { - var info = this.state.tensorInfo.get(dataId); - var newBytes = bytesFromStringArray(backendVals); - this.state.numBytes += newBytes - info.bytes; - info.bytes = newBytes; - } - return t; - }; - /** - * Internal method used by backends. Makes a new tensor - * that is a wrapper around an existing data id. It doesn't create - * a new data id, only increments the ref count used in memory tracking. - */ - Engine.prototype.makeTensorFromDataId = function (dataId, shape, dtype, backend) { - dtype = dtype || 'float32'; - var t = new Tensor(shape, dtype, dataId, this.nextTensorId()); - this.incRef(t, backend); - return t; - }; - Engine.prototype.makeVariable = function (initialValue, trainable, name, dtype) { - if (trainable === void 0) { trainable = true; } - name = name || this.nextVariableId().toString(); - if (dtype != null && dtype !== initialValue.dtype) { - initialValue = initialValue.cast(dtype); - } - var v = new Variable(initialValue, trainable, name, this.nextTensorId()); - if (this.state.registeredVariables[v.name] != null) { - throw new Error("Variable with name " + v.name + " was already registered"); - } - this.state.registeredVariables[v.name] = v; - this.incRef(v, this.backend); - return v; - }; - Engine.prototype.incRef = function (a, backend) { - var refCount = this.state.tensorInfo.has(a.dataId) ? - this.state.tensorInfo.get(a.dataId).refCount : - 0; - this.state.numTensors++; - if (a.dtype === 'string') { - this.state.numStringTensors++; - } - if (refCount === 0) { - this.state.numDataBuffers++; - // Bytes for complex numbers are counted by their components. Bytes for - // string tensors are counted when writing values. - var bytes = 0; - if (a.dtype !== 'complex64' && a.dtype !== 'string') { - bytes = a.size * bytesPerElement(a.dtype); - } - this.state.tensorInfo.set(a.dataId, { - backend: backend || this.backend, - dtype: a.dtype, - shape: a.shape, - bytes: bytes, - refCount: 0 - }); - this.state.numBytes += bytes; - } - this.state.tensorInfo.get(a.dataId).refCount++; - if (!(a instanceof Variable)) { - this.track(a); - } - }; - Engine.prototype.disposeTensor = function (a) { - if (!this.state.tensorInfo.has(a.dataId)) { - return; - } - this.state.numTensors--; - if (a.dtype === 'string') { - this.state.numStringTensors--; - } - var info = this.state.tensorInfo.get(a.dataId); - var refCount = info.refCount; - if (refCount <= 1) { - // Don't count bytes for complex numbers as they are counted by their - // components. - if (a.dtype !== 'complex64') { - this.state.numBytes -= info.bytes; - } - this.state.numDataBuffers--; - info.backend.disposeData(a.dataId); - this.state.tensorInfo.delete(a.dataId); - } - else { - this.state.tensorInfo.get(a.dataId).refCount--; - } - // TODO(nsthorat): Construct an error and save the stack trace for - // debugging when in debug mode. Creating a stack trace is too expensive - // to do unconditionally. - }; - Engine.prototype.disposeVariables = function () { - for (var varName in this.state.registeredVariables) { - var v = this.state.registeredVariables[varName]; - this.disposeVariable(v); - } - }; - Engine.prototype.disposeVariable = function (v) { - this.disposeTensor(v); - if (this.state.registeredVariables[v.name] != null) { - delete this.state.registeredVariables[v.name]; - } - }; - Engine.prototype.memory = function () { - var info = this.backend.memory(); - info.numTensors = this.state.numTensors; - info.numDataBuffers = this.state.numDataBuffers; - info.numBytes = this.state.numBytes; - if (this.state.numStringTensors > 0) { - info.unreliable = true; - if (info.reasons == null) { - info.reasons = []; - } - info.reasons.push('Memory usage by string tensors is approximate ' + - '(2 bytes per character)'); - } - return info; - }; - Engine.prototype.profile = function (query) { - return __awaiter(this, void 0, void 0, function () { - var startBytes, startNumTensors, _a; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: - this.state.profiling = true; - startBytes = this.state.numBytes; - startNumTensors = this.state.numTensors; - this.state.activeProfile.kernels = []; - _a = this.state.activeProfile; - return [4 /*yield*/, query()]; - case 1: - _a.result = _b.sent(); - this.state.profiling = false; - this.state.activeProfile.peakBytes = Math.max.apply(Math, this.state.activeProfile.kernels.map(function (d) { return d.totalBytesSnapshot; })); - this.state.activeProfile.newBytes = this.state.numBytes - startBytes; - this.state.activeProfile.newTensors = - this.state.numTensors - startNumTensors; - return [2 /*return*/, this.state.activeProfile]; - } - }); - }); - }; - Engine.prototype.isTapeOn = function () { - return this.state.gradientDepth > 0 && this.state.kernelDepth === 0; - }; - Engine.prototype.addTapeNode = function (kernelName, inputs, outputs, gradientsFunc, saved, attrs) { - var _this = this; - var tapeNode = { id: this.state.nextTapeNodeId++, kernelName: kernelName, inputs: inputs, outputs: outputs, saved: saved }; - var gradConfig = getGradient(kernelName); - if (gradConfig != null) { - gradientsFunc = gradConfig.gradFunc; - } - if (gradientsFunc != null) { - tapeNode.gradient = function (dys) { - // TODO(smilkov): To optimize back-prop, pass dys that are not used in - // the backprop graph to the user as null instead of zeros - dys = dys.map(function (dy, i) { - if (dy == null) { - var output = outputs[i]; - var vals = makeZerosTypedArray(output.size, output.dtype); - return _this.makeTensor(vals, output.shape, output.dtype); - } - return dy; - }); - // Grad functions of ops with single outputs expect a dy, while ops - // with multiple outputs expect dys (array of dy). - return gradientsFunc(dys.length > 1 ? dys : dys[0], saved, attrs); - }; - } - this.state.activeTape.push(tapeNode); - }; - Engine.prototype.keep = function (result) { - result.kept = true; - return result; - }; - Engine.prototype.startTape = function () { - if (this.state.gradientDepth === 0) { - this.state.activeTape = []; - } - this.state.gradientDepth++; - }; - Engine.prototype.endTape = function () { - this.state.gradientDepth--; - }; - /** - * Start a scope. Use this with endScope() to achieve the same functionality - * as scope() without the need for a function closure. - */ - Engine.prototype.startScope = function (name) { - var scopeInfo = { - track: [], - name: 'unnamed scope', - id: this.state.nextScopeId++ - }; - if (name) { - scopeInfo.name = name; - } - this.state.scopeStack.push(scopeInfo); - this.state.activeScope = scopeInfo; - }; - /** - * End a scope. Use this with startScope() to achieve the same functionality - * as scope() without the need for a function closure. - */ - Engine.prototype.endScope = function (result) { - var _this = this; - var tensorsToTrackInParent = getTensorsInContainer(result); - var tensorsToTrackInParentSet = new Set(tensorsToTrackInParent.map(function (t) { return t.id; })); - // Dispose the arrays tracked in this scope. - for (var i = 0; i < this.state.activeScope.track.length; i++) { - var tensor = this.state.activeScope.track[i]; - if (!tensor.kept && !tensorsToTrackInParentSet.has(tensor.id)) { - tensor.dispose(); - } - } - var oldScope = this.state.scopeStack.pop(); - this.state.activeScope = this.state.scopeStack.length === 0 ? - null : - this.state.scopeStack[this.state.scopeStack.length - 1]; - // Track the current result in the parent scope. - tensorsToTrackInParent.forEach(function (tensor) { - // Only track the tensor if was allocated in the inner scope and is not - // globally kept. - if (!tensor.kept && tensor.scopeId === oldScope.id) { - _this.track(tensor); - } - }); - }; - /** - * Returns gradients of `f` with respect to each of the `xs`. The gradients - * returned are of the same length as `xs`, but some might be null if `f` - * was not a function of that `x`. It also takes optional dy to multiply the - * gradient, which defaults to `1`. - */ - Engine.prototype.gradients = function (f, xs, dy, allowNoGradients) { - var _this = this; - if (allowNoGradients === void 0) { allowNoGradients = false; } - assert(xs.length > 0, function () { return 'gradients() received an empty list of xs.'; }); - if (dy != null && dy.dtype !== 'float32') { - throw new Error("dy must have 'float32' dtype, but has '" + dy.dtype + "'"); - } - var y = this.scopedRun(function () { return _this.startTape(); }, function () { return _this.endTape(); }, function () { return _this.tidy('forward', f); }); - assert(y instanceof Tensor, function () { return 'The result y returned by f() must be a tensor.'; }); - // Filter out the nodes that don't connect x => y. - var filteredTape = getFilteredNodesXToY(this.state.activeTape, xs, y); - if (!allowNoGradients && filteredTape.length === 0 && xs.length > 0) { - throw new Error('Cannot compute gradient of y=f(x) with respect to x. Make sure ' + - 'that the f you passed encloses all operations that lead from x ' + - 'to y.'); - } - return this.tidy('backward', function () { - var accumulatedGradientMap = {}; - accumulatedGradientMap[y.id] = (dy == null) ? ones(y.shape) : dy; - // Backprop gradients through the filtered nodes. - backpropagateGradients(accumulatedGradientMap, filteredTape, - // Pass the tidy function to avoid circular dep with `tape.ts`. - function (f) { return _this.tidy(f); }); - var grads = xs.map(function (x) { return accumulatedGradientMap[x.id]; }); - if (_this.state.gradientDepth === 0) { - // This means that we are not computing higher-order gradients - // and can clean up the tape. - _this.state.activeTape.forEach(function (node) { - for (var _i = 0, _a = node.saved; _i < _a.length; _i++) { - var tensor = _a[_i]; - tensor.dispose(); - } - }); - _this.state.activeTape = null; - } - return { value: y, grads: grads }; - }); - }; - Engine.prototype.customGrad = function (f) { - var _this = this; - assert(isFunction(f), function () { return 'The f passed in customGrad(f) must be a function.'; }); - return function () { - var inputs = []; - for (var _i = 0; _i < arguments.length; _i++) { - inputs[_i] = arguments[_i]; - } - assert(inputs.every(function (t) { return t instanceof Tensor; }), function () { return 'The args passed in customGrad(f)(x1, x2,...) must all be ' + - 'tensors'; }); - var res; - var inputMap = {}; - inputs.forEach(function (input, i) { - inputMap[i] = input; - }); - return _this.runKernelFunc(function (_, save) { - res = f.apply(void 0, inputs.concat([save])); - assert(res.value instanceof Tensor, function () { return 'The function f passed in customGrad(f) must return an ' + - 'object where `obj.value` is a tensor'; }); - assert(isFunction(res.gradFunc), function () { return 'The function f passed in customGrad(f) must return an ' + - 'object where `obj.gradFunc` is a function.'; }); - return res.value; - }, inputMap, function (dy, saved) { - var gradRes = res.gradFunc(dy, saved); - var grads = Array.isArray(gradRes) ? gradRes : [gradRes]; - assert(grads.length === inputs.length, function () { return 'The function f passed in customGrad(f) must return an ' + - 'object where `obj.gradFunc` is a function that returns ' + - 'the same number of tensors as inputs passed to f(...).'; }); - assert(grads.every(function (t) { return t instanceof Tensor; }), function () { return 'The function f passed in customGrad(f) must return an ' + - 'object where `obj.gradFunc` is a function that returns ' + - 'a list of only tensors.'; }); - var gradMap = {}; - grads.forEach(function (grad, i) { - gradMap[i] = function () { return grad; }; - }); - return gradMap; - }); - }; - }; - Engine.prototype.readSync = function (dataId) { - // Route the read to the correct backend. - var info = this.state.tensorInfo.get(dataId); - return info.backend.readSync(dataId); - }; - Engine.prototype.read = function (dataId) { - // Route the read to the correct backend. - var info = this.state.tensorInfo.get(dataId); - return info.backend.read(dataId); - }; - Engine.prototype.time = function (query) { - return __awaiter(this, void 0, void 0, function () { - var start, timingInfo; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - start = now(); - return [4 /*yield*/, this.backend.time(query)]; - case 1: - timingInfo = _a.sent(); - timingInfo.wallMs = now() - start; - return [2 /*return*/, timingInfo]; - } - }); - }); - }; - /** - * Tracks a Tensor in the current scope to be automatically cleaned up - * when the current scope ends, and returns the value. - * - * @param result The Tensor to track in the current scope. - */ - Engine.prototype.track = function (result) { - if (this.state.activeScope != null) { - result.scopeId = this.state.activeScope.id; - this.state.activeScope.track.push(result); - } - return result; - }; - Object.defineProperty(Engine.prototype, "registeredVariables", { - get: function () { - return this.state.registeredVariables; - }, - enumerable: true, - configurable: true - }); - /** - * Resets the engine state. Removes all backends but does not remove - * registered backend factories. - */ - Engine.prototype.reset = function () { - // Make any pending promise obsolete. - this.pendingBackendInitId++; - this.state.dispose(); - this.ENV.reset(); - this.state = new EngineState(); - for (var backendName in this.registry) { - this.disposeRegisteredKernels(backendName); - this.registry[backendName].dispose(); - delete this.registry[backendName]; - } - this.backendName = null; - this.backendInstance = null; - this.pendingBackendInit = null; - }; - Engine.nextTensorId = 0; - Engine.nextVariableId = 0; - return Engine; - }()); - function ones(shape) { - var values = makeOnesTypedArray(sizeFromShape(shape), 'float32'); - return ENGINE.makeTensor(values, shape, 'float32'); - } - function getOrMakeEngine() { - var ns = getGlobalNamespace(); - if (ns._tfengine == null) { - var environment = new Environment(ns); - ns._tfengine = new Engine(environment); - } - setEnvironmentGlobal(ns._tfengine.ENV); - // Tell the current tensor interface that the global engine is responsible - // for tracking. - setTensorTracker(function () { return ns._tfengine; }); - return ns._tfengine; - } - var ENGINE = getOrMakeEngine(); - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // tslint:disable-next-line:no-any - function _isNavigatorDefined() { - return typeof navigator !== 'undefined' && navigator != null; - } - function isMobile() { - if (_isNavigatorDefined()) { - // tslint:disable-next-line:no-any - var a = navigator.userAgent || navigator.vendor || window.opera; - // tslint:disable-next-line:max-line-length - return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i - .test(a) || - // tslint:disable-next-line:max-line-length - /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i - .test(a.substr(0, 4)); - } - return false; - } - function isBrowser() { - return (typeof window !== 'undefined' && window.document != null) || - //@ts-ignore - (typeof WorkerGlobalScope !== 'undefined'); - } - - var device_util = { - __proto__: null, - isMobile: isMobile, - isBrowser: isBrowser - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var ENV = env(); - /** - * This file contains environment-related flag registrations. - */ - /** Whether to enable debug mode. */ - ENV.registerFlag('DEBUG', function () { return false; }, function (debugValue) { - if (debugValue) { - console.warn('Debugging mode is ON. The output of every math call will ' + - 'be downloaded to CPU and checked for NaNs. ' + - 'This significantly impacts performance.'); - } - }); - /** Whether we are in a browser (as versus, say, node.js) environment. */ - ENV.registerFlag('IS_BROWSER', function () { return isBrowser(); }); - /** Whether we are in a browser (as versus, say, node.js) environment. */ - ENV.registerFlag('IS_NODE', function () { return (typeof process !== 'undefined') && - (typeof process.versions !== 'undefined') && - (typeof process.versions.node !== 'undefined'); }); - /** Whether this browser is Chrome. */ - ENV.registerFlag('IS_CHROME', function () { return typeof navigator !== 'undefined' && navigator != null && - navigator.userAgent != null && /Chrome/.test(navigator.userAgent) && - /Google Inc/.test(navigator.vendor); }); - /** - * True when the environment is "production" where we disable safety checks - * to gain performance. - */ - ENV.registerFlag('PROD', function () { return false; }); - /** - * Whether to do sanity checks when inferring a shape from user-provided - * values, used when creating a new tensor. - */ - ENV.registerFlag('TENSORLIKE_CHECK_SHAPE_CONSISTENCY', function () { return ENV.getBool('DEBUG'); }); - /** Whether deprecation warnings are enabled. */ - ENV.registerFlag('DEPRECATION_WARNINGS_ENABLED', function () { return true; }); - /** True if running unit tests. */ - ENV.registerFlag('IS_TEST', function () { return false; }); - - var Abs = 'Abs'; - var Acos = 'Acos'; - var Acosh = 'Acosh'; - var Add = 'Add'; - var AddN = 'AddN'; - var All = 'All'; - var Any = 'Any'; - var ArgMax = 'ArgMax'; - var ArgMin = 'ArgMin'; - var Asin = 'Asin'; - var Asinh = 'Asinh'; - var Atan = 'Atan'; - var Atanh = 'Atanh'; - var Atan2 = 'Atan2'; - var AvgPool = 'AvgPool'; - var AvgPoolBackprop = 'AvgPoolBackprop'; - var AvgPool3D = 'AvgPool3D'; - var AvgPool3DBackprop = 'AvgPool3DBackprop'; - var BatchMatMul = 'BatchMatMul'; - var BatchToSpaceND = 'BatchToSpaceND'; - var BroadcastTo = 'BroadcastTo'; - var Cast = 'Cast'; - var Ceil = 'Ceil'; - var ClipByValue = 'ClipByValue'; - var Complex = 'Complex'; - var Concat = 'Concat'; - var Conv2D = 'Conv2D'; - var Conv2DBackpropFilter = 'Conv2DBackpropFilter'; - var Conv2DBackpropInput = 'Conv2DBackpropInput'; - var Conv3D = 'Conv3D'; - var Conv3DBackpropFilterV2 = 'Conv3DBackpropFilterV2'; - var Conv3DBackpropInputV2 = 'Conv3DBackpropInputV2'; - var Cos = 'Cos'; - var Cosh = 'Cosh'; - var Cumsum = 'Cumsum'; - var CropAndResize = 'CropAndResize'; - var DepthToSpace = 'DepthToSpace'; - var DepthwiseConv2dNative = 'DepthwiseConv2dNative'; - var DepthwiseConv2dNativeBackpropFilter = 'DepthwiseConv2dNativeBackpropFilter'; - var DepthwiseConv2dNativeBackpropInput = 'DepthwiseConv2dNativeBackpropInput'; - var Diag = 'Diag'; - var Dilation2D = 'Dilation2D'; - var Dilation2DBackpropInput = 'Dilation2DBackpropInput'; - var Dilation2DBackpropFilter = 'Dilation2DBackpropFilter'; - var Div = 'Div'; - var Elu = 'Elu'; - var EluGrad = 'EluGrad'; - var Erf = 'Erf'; - var Equal = 'Equal'; - var Exp = 'Exp'; - var Expm1 = 'Expm1'; - var FFT = 'FFT'; - var Floor = 'Floor'; - var FloorDiv = 'FloorDiv'; - var Fill = 'Fill'; - var FusedBatchNorm = 'FusedBatchNorm'; - var GatherV2 = 'GatherV2'; - var GatherNd = 'GatherNd'; - var Greater = 'Greater'; - var GreaterEqual = 'GreaterEqual'; - var Identity = 'Identity'; - var IFFT = 'IFFT'; - var Imag = 'Imag'; - var IsFinite = 'IsFinite'; - var IsInf = 'IsInf'; - var IsNan = 'IsNan'; - var Less = 'Less'; - var LessEqual = 'LessEqual'; - var LinSpace = 'LinSpace'; - var Log = 'Log'; - var Log1p = 'Log1p'; - var LogicalAnd = 'LogicalAnd'; - var LogicalNot = 'LogicalNot'; - var LogicalOr = 'LogicalOr'; - var LogSoftmax = 'LogSoftmax'; - var LRN = 'LRN'; - var LRNBackprop = 'LRNBackprop'; - var Max = 'Max'; - var Maximum = 'Maximum'; - var MaxPool = 'MaxPool'; - var MaxPoolBackprop = 'MaxPoolBackprop'; - var MaxPool3D = 'MaxPool3D'; - var MaxPool3DBackprop = 'MaxPool3DBackprop'; - var MaxPoolWithArgmax = 'MaxPoolWithArgmax'; - var Mean = 'Mean'; - var Min = 'Min'; - var Minimum = 'Minimum'; - var Mod = 'Mod'; - var Multiply = 'Multiply'; - var Negate = 'Negate'; - var NotEqual = 'NotEqual'; - var NonMaxSuppressionV3 = 'NonMaxSuppressionV3'; - var NonMaxSuppressionV4 = 'NonMaxSuppressionV4'; - var NonMaxSuppressionV5 = 'NonMaxSuppressionV5'; - var OnesLike = 'OnesLike'; - var OneHot = 'OneHot'; - var PadV2 = 'PadV2'; - var Pool = 'Pool'; - var Pow = 'Pow'; - var Prelu = 'Prelu'; - var Prod = 'Prod'; - var Range = 'Range'; - var Real = 'Real'; - var Reciprocal = 'Reciprocal'; - var Relu = 'Relu'; - var Reshape = 'Reshape'; - var ResizeNearestNeighbor = 'ResizeNearestNeighbor'; - var ResizeNearestNeighborGrad = 'ResizeNearestNeighborGrad'; - var ResizeBilinear = 'ResizeBilinear'; - var ResizeBilinearGrad = 'ResizeBilinearGrad'; - var Relu6 = 'Relu6'; - var Reverse = 'Reverse'; - var Round = 'Round'; - var Rsqrt = 'Rsqrt'; - var ScatterNd = 'ScatterNd'; - var SelectV2 = 'SelectV2'; - var Selu = 'Selu'; - var Slice = 'Slice'; - var Sin = 'Sin'; - var Sinh = 'Sinh'; - var Sign = 'Sign'; - var Sigmoid = 'Sigmoid'; - var Softplus = 'Softplus'; - var Sqrt = 'Sqrt'; - var Sum = 'Sum'; - var SpaceToBatchND = 'SpaceToBatchND'; - var SplitV = 'SplitV'; - var Softmax = 'Softmax'; - var SquaredDifference = 'SquaredDifference'; - var Square = 'Square'; - var Sub = 'Sub'; - var SparseToDense = 'SparseToDense'; - var StridedSlice = 'StridedSlice'; - var Tan = 'Tan'; - var Tanh = 'Tanh'; - var Tile = 'Tile'; - var TopK = 'TopK'; - var Transpose = 'Transpose'; - var Unpack = 'Unpack'; - var UnsortedSegmentSum = 'UnsortedSegmentSum'; - var ZerosLike = 'ZerosLike'; - /** - * TensorFlow.js-only kernels - */ - var Step = 'Step'; - var FromPixels = 'FromPixels'; - var RotateWithOffset = 'RotateWithOffset'; - var _FusedMatMul = '_FusedMatMul'; - var FusedConv2D = 'FusedConv2D'; - var FusedDepthwiseConv2D = 'FusedDepthwiseConv2D'; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function inferShape(val, dtype) { - var firstElem = val; - if (isTypedArray(val)) { - return dtype === 'string' ? [] : [val.length]; - } - if (!Array.isArray(val)) { - return []; // Scalar. - } - var shape = []; - while (Array.isArray(firstElem) || - isTypedArray(firstElem) && dtype !== 'string') { - shape.push(firstElem.length); - firstElem = firstElem[0]; - } - if (Array.isArray(val) && - env().getBool('TENSORLIKE_CHECK_SHAPE_CONSISTENCY')) { - deepAssertShapeConsistency(val, shape, []); - } - return shape; - } - function deepAssertShapeConsistency(val, shape, indices) { - indices = indices || []; - if (!(Array.isArray(val)) && !isTypedArray(val)) { - assert(shape.length === 0, function () { return "Element arr[" + indices.join('][') + "] is a primitive, " + - ("but should be an array/TypedArray of " + shape[0] + " elements"); }); - return; - } - assert(shape.length > 0, function () { return "Element arr[" + indices.join('][') + "] should be a primitive, " + - ("but is an array of " + val.length + " elements"); }); - assert(val.length === shape[0], function () { return "Element arr[" + indices.join('][') + "] should have " + shape[0] + " " + - ("elements, but has " + val.length + " elements"); }); - var subShape = shape.slice(1); - for (var i = 0; i < val.length; ++i) { - deepAssertShapeConsistency(val[i], subShape, indices.concat(i)); - } - } - function assertDtype(expectedDtype, actualDType, argName, functionName) { - if (expectedDtype == null) { - return; - } - if (expectedDtype !== 'numeric' && expectedDtype !== actualDType || - expectedDtype === 'numeric' && actualDType === 'string') { - throw new Error("Argument '" + argName + "' passed to '" + functionName + "' must " + - ("be " + expectedDtype + " tensor, but got " + actualDType + " tensor")); - } - } - function convertToTensor(x, argName, functionName, parseAsDtype) { - if (parseAsDtype === void 0) { parseAsDtype = 'numeric'; } - if (x instanceof Tensor) { - assertDtype(parseAsDtype, x.dtype, argName, functionName); - return x; - } - var inferredDtype = inferDtype(x); - // If the user expects a bool/int/float, use that info to update the - // inferredDtype when it is not a string. - if (inferredDtype !== 'string' && - ['bool', 'int32', 'float32'].indexOf(parseAsDtype) >= 0) { - inferredDtype = parseAsDtype; - } - assertDtype(parseAsDtype, inferredDtype, argName, functionName); - if ((x == null) || - (!isTypedArray(x) && !Array.isArray(x) && typeof x !== 'number' && - typeof x !== 'boolean' && typeof x !== 'string')) { - var type = x == null ? 'null' : x.constructor.name; - throw new Error("Argument '" + argName + "' passed to '" + functionName + "' must be a " + - ("Tensor or TensorLike, but got '" + type + "'")); - } - var inferredShape = inferShape(x, inferredDtype); - if (!isTypedArray(x) && !Array.isArray(x)) { - x = [x]; - } - var skipTypedArray = true; - var values = inferredDtype !== 'string' ? - toTypedArray(x, inferredDtype) : - flatten(x, [], skipTypedArray); - return ENGINE.makeTensor(values, inferredShape, inferredDtype); - } - function convertToTensorArray(arg, argName, functionName, parseAsDtype) { - if (parseAsDtype === void 0) { parseAsDtype = 'numeric'; } - if (!Array.isArray(arg)) { - throw new Error("Argument " + argName + " passed to " + functionName + " must be a " + - '`Tensor[]` or `TensorLike[]`'); - } - var tensors = arg; - return tensors.map(function (t, i) { return convertToTensor(t, argName + "[" + i + "]", functionName); }, parseAsDtype); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Used for wrapping functions that perform math operations on - * Tensors. The function will be wrapped in a named scope that cleans all - * memory usage after the function is done. - */ - function op(f) { - var keys = Object.keys(f); - if (keys.length !== 1) { - throw new Error("Please provide an object with a single key " + - "(operation name) mapping to a function. Got an object with " + - (keys.length + " keys.")); - } - var opName = keys[0]; - var fn = f[opName]; - // Strip the underscore from the end of the function name. - if (opName.endsWith('_')) { - opName = opName.substring(0, opName.length - 1); - } - // tslint:disable-next-line:no-any - var f2 = function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - ENGINE.startScope(opName); - try { - var result = fn.apply(void 0, args); - if (result instanceof Promise) { - console.error('Cannot return a Promise inside of tidy.'); - } - ENGINE.endScope(result); - return result; - } - catch (ex) { - ENGINE.endScope(null); - throw ex; - } - }; - Object.defineProperty(f2, 'name', { value: opName, configurable: true }); - // tslint:disable-next-line:no-any - return f2; - } - - /** - * @license - * Copyright 2020 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Casts a `tf.Tensor` to a new dtype. - * - * ```js - * const x = tf.tensor1d([1.5, 2.5, 3]); - * tf.cast(x, 'int32').print(); - * ``` - * @param x The input tensor to be casted. - * @param dtype The dtype to cast the input tensor to. - */ - /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ - function cast_(x, dtype) { - var $x = convertToTensor(x, 'x', 'cast'); - // Sanity checks. - if (!isValidDtype(dtype)) { - throw new Error("Failed to cast to unknown dtype " + dtype); - } - if (dtype === 'string' && $x.dtype !== 'string' || - dtype !== 'string' && $x.dtype === 'string') { - throw new Error('Only strings can be casted to strings'); - } - var inputs = { x: $x }; - var attrs = { dtype: dtype }; - return ENGINE.runKernelFunc(function (backend) { return backend.cast($x, dtype); }, inputs, null /* grad */, Cast, attrs); - } - var cast = op({ cast_: cast_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Multiplies two `tf.Tensor`s element-wise, A * B. Supports broadcasting. - * - * We also expose `tf.mulStrict` which has the same signature as this op and - * asserts that `a` and `b` are the same shape (does not broadcast). - * - * ```js - * const a = tf.tensor1d([1, 2, 3, 4]); - * const b = tf.tensor1d([2, 3, 4, 5]); - * - * a.mul(b).print(); // or tf.mul(a, b) - * ``` - * - * ```js - * // Broadcast mul a with b. - * const a = tf.tensor1d([1, 2, 3, 4]); - * const b = tf.scalar(5); - * - * a.mul(b).print(); // or tf.mul(a, b) - * ``` - * @param a The first tensor to multiply. - * @param b The second tensor to multiply. Must have the same dtype as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ - function mul_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'mul'); - var $b = convertToTensor(b, 'b', 'mul'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - var forward = function (backend, save) { - var res = backend.multiply($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Multiply); - } - var mul = op({ mul_: mul_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes step of the input `tf.Tensor` element-wise: `x > 0 ? 1 : alpha * x` - * - * ```js - * const x = tf.tensor1d([0, 2, -1, -3]); - * - * x.step(.5).print(); // or tf.step(x, .5) - * ``` - * @param x The input tensor. - * @param alpha The gradient when input is negative. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function step_(x, alpha) { - if (alpha === void 0) { alpha = 0.0; } - var $x = convertToTensor(x, 'x', 'step'); - var inputs = { x: $x }; - var attrs = { alpha: alpha }; - return ENGINE.runKernelFunc(function (backend) { return backend.step($x, alpha); }, inputs, null /* grad */, Step, attrs); - } - var step = op({ step_: step_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var absGradConfig = { - kernelName: Abs, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(dy, step(cast(x, 'float32'), -1)); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Divides two `tf.Tensor`s element-wise, A / B. Supports broadcasting. - * The result is rounded with floor function. - * - * - * ```js - * const a = tf.tensor1d([1, 4, 9, 16]); - * const b = tf.tensor1d([1, 2, 3, 4]); - * - * a.floorDiv(b).print(); // or tf.div(a, b) - * ``` - * - * ```js - * // Broadcast div a with b. - * const a = tf.tensor1d([2, 4, 6, 8]); - * const b = tf.scalar(2); - * - * a.floorDiv(b).print(); // or tf.floorDiv(a, b) - * ``` - * - * @param a The first tensor as the numerator. - * @param b The second tensor as the denominator. Must have the same dtype as - * `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ - function floorDiv_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'floorDiv'); - var $b = convertToTensor(b, 'b', 'floorDiv'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - var forward = function (backend, save) { - var res = backend.floorDiv($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, FloorDiv); - } - var floorDiv = op({ floorDiv_: floorDiv_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Divides two `tf.Tensor`s element-wise, A / B. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([1, 4, 9, 16]); - * const b = tf.tensor1d([1, 2, 3, 4]); - * - * a.div(b).print(); // or tf.div(a, b) - * ``` - * - * ```js - * // Broadcast div a with b. - * const a = tf.tensor1d([2, 4, 6, 8]); - * const b = tf.scalar(2); - * - * a.div(b).print(); // or tf.div(a, b) - * ``` - * - * @param a The first tensor as the numerator. - * @param b The second tensor as the denominator. Must have the same dtype as - * `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ - function div_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'div'); - var $b = convertToTensor(b, 'b', 'div'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - if ($a.dtype === 'int32' && $b.dtype === 'int32') { - return floorDiv($a, $b); - } - var forward = function (backend, save) { - var res = backend.realDivide($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - var attrs = {}; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Div, attrs); - } - var div = op({ div_: div_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes `-1 * x` element-wise. - * - * ```js - * const x = tf.tensor2d([1, 2, -2, 0], [2, 2]); - * - * x.neg().print(); // or tf.neg(x) - * ``` - * - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function neg_(x) { - var $x = convertToTensor(x, 'x', 'neg'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend) { return backend.neg($x); }, inputs, null /* grad */, Negate); - } - var neg = op({ neg_: neg_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** This is shared code across all tensor creation methods. */ - function makeTensor(values, shape, inferredShape, dtype) { - if (dtype == null) { - dtype = inferDtype(values); - } - if (dtype === 'complex64') { - throw new Error("Cannot construct a complex64 tensor directly. " + - "Please use tf.complex(real, imag)."); - } - if (!isTypedArray(values) && !Array.isArray(values) && - typeof values !== 'number' && typeof values !== 'boolean' && - typeof values !== 'string') { - throw new Error('values passed to tensor(values) must be a number/boolean/string or ' + - 'an array of numbers/booleans/strings, or a TypedArray'); - } - if (shape != null) { - assertNonNegativeIntegerDimensions(shape); - var providedSize_1 = sizeFromShape(shape); - var inferredSize_1 = sizeFromShape(inferredShape); - assert(providedSize_1 === inferredSize_1, function () { - return "Based on the provided shape, [" + shape + "], the tensor should have " + - (providedSize_1 + " values but has " + inferredSize_1); - }); - for (var i = 0; i < inferredShape.length; ++i) { - var inferred = inferredShape[i]; - var flatDimsDontMatch = i === inferredShape.length - 1 ? - inferred !== sizeFromShape(shape.slice(i)) : - true; - assert(inferredShape[i] === shape[i] || !flatDimsDontMatch, function () { return "Error creating a new Tensor. Inferred shape " + - ("(" + inferredShape + ") does not match the provided ") + - ("shape (" + shape + "). "); }); - } - } - if (!isTypedArray(values) && !Array.isArray(values)) { - values = [values]; - } - shape = shape || inferredShape; - values = dtype !== 'string' ? - toTypedArray(values, dtype) : - flatten(values, [], true); - return ENGINE.makeTensor(values, shape, dtype); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates rank-0 `tf.Tensor` (scalar) with the provided value and dtype. - * - * The same functionality can be achieved with `tf.tensor`, but in general - * we recommend using `tf.scalar` as it makes the code more readable. - * - * ```js - * tf.scalar(3.14).print(); - * ``` - * - * @param value The value of the scalar. - * @param dtype The data type. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function scalar(value, dtype) { - if (((isTypedArray(value) && dtype !== 'string') || Array.isArray(value)) && - dtype !== 'complex64') { - throw new Error('Error creating a new Scalar: value must be a primitive ' + - '(number|boolean|string)'); - } - if (dtype === 'string' && isTypedArray(value) && - !(value instanceof Uint8Array)) { - throw new Error('When making a scalar from encoded string, ' + - 'the value must be `Uint8Array`.'); - } - var shape = []; - var inferredShape = []; - return makeTensor(value, shape, inferredShape, dtype); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes square root of the input `tf.Tensor` element-wise: `y = sqrt(x)` - * - * ```js - * const x = tf.tensor1d([1, 2, 4, -1]); - * - * x.sqrt().print(); // or tf.sqrt(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function sqrt_(x) { - var $x = convertToTensor(x, 'x', 'sqrt'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.sqrt($x); - save([$x]); - return res; - }, inputs, null /* grad */, Sqrt); - } - var sqrt = op({ sqrt_: sqrt_ }); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes square of `x` element-wise: `x ^ 2` - * - * ```js - * const x = tf.tensor1d([1, 2, Math.sqrt(2), -1]); - * - * x.square().print(); // or tf.square(x) - * ``` - * @param x The input Tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function square_(x) { - var $x = convertToTensor(x, 'x', 'square'); - var attrs = {}; - var inputsToSave = [$x]; - var outputsToSave = []; - return ENGINE.runKernelFunc(function (backend, save) { - save([$x]); - return backend.square($x); - }, { x: $x }, null /* grad */, 'Square', attrs, inputsToSave, outputsToSave); - } - var square = op({ square_: square_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Subtracts two `tf.Tensor`s element-wise, A - B. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([10, 20, 30, 40]); - * const b = tf.tensor1d([1, 2, 3, 4]); - * - * a.sub(b).print(); // or tf.sub(a, b) - * ``` - * - * ```js - * // Broadcast subtract a with b. - * const a = tf.tensor1d([10, 20, 30, 40]); - * const b = tf.scalar(5); - * - * a.sub(b).print(); // or tf.sub(a, b) - * ``` - * @param a The first `tf.Tensor` to subtract from. - * @param b The second `tf.Tensor` to be subtracted. Must have the same dtype as - * `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ - function sub_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'sub'); - var $b = convertToTensor(b, 'b', 'sub'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - var forward = function (backend, save) { - var res = backend.subtract($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Sub); - } - var sub = op({ sub_: sub_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var acosGradConfig = { - kernelName: Acos, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { - x: function () { - var a = square(cast(x, 'float32')); - var b = sqrt(sub(scalar(1), a)); - return neg(div(dy, b)); - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var acoshGradConfig = { - kernelName: Acosh, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { - x: function () { - var a = sqrt(sub(square(cast(x, 'float32')), 1)); - return div(dy, a); - } - }; - } - }; - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the dimensions in the input shape that are broadcasted to - * produce the provided output shape. - * - * The returned dimensions are 0-indexed and sorted. An example: - * inShape = [4, 1, 3] - * outShape = [5, 4, 3, 3] - * result = [1]. Dimension 1 (2nd dimension of input) gets broadcasted 1 => 3. - */ - function getBroadcastDims(inShape, outShape) { - var inRank = inShape.length; - var dims = []; - for (var i = 0; i < inRank; i++) { - var dim = inRank - 1 - i; - var a = inShape[dim] || 1; - var b = outShape[outShape.length - 1 - i] || 1; - if (b > 1 && a === 1) { - dims.unshift(dim); - } - } - return dims; - } - /** - * Returns the axes in the output space that should be reduced to produce - * the input space. - */ - function getReductionAxes(inShape, outShape) { - var result = []; - for (var i = 0; i < outShape.length; i++) { - var inDim = inShape[inShape.length - i - 1]; - var outAxis = outShape.length - i - 1; - var outDim = outShape[outAxis]; - if (inDim == null || (inDim === 1 && outDim > 1)) { - result.unshift(outAxis); - } - } - return result; - } - function assertAndGetBroadcastShape(shapeA, shapeB) { - var result = []; - var l = Math.max(shapeA.length, shapeB.length); - for (var i = 0; i < l; i++) { - var a = shapeA[shapeA.length - i - 1]; - if (a == null) { - a = 1; - } - var b = shapeB[shapeB.length - i - 1]; - if (b == null) { - b = 1; - } - if (a === 1) { - result.unshift(b); - } - else if (b === 1) { - result.unshift(a); - } - else if (a !== b) { - var errMsg = "Operands could not be broadcast together with shapes " + - (shapeA + " and " + shapeB + "."); - throw Error(errMsg); - } - else { - result.unshift(a); - } - } - return result; - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var addGradConfig = { - kernelName: Add, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var outShape = assertAndGetBroadcastShape(a.shape, b.shape); - var derA = function () { - var res = dy; - var reduceAxes = getReductionAxes(a.shape, outShape); - if (reduceAxes.length > 0) { - res = res.sum(reduceAxes); - } - return res.reshape(a.shape); - }; - var derB = function () { - var res = dy; - var reduceAxes = getReductionAxes(b.shape, outShape); - if (reduceAxes.length > 0) { - res = res.sum(reduceAxes); - } - return res.reshape(b.shape); - }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var addNGradConfig = { - kernelName: AddN, - saveAllInputs: true, - gradFunc: function (dy, saved) { - var ders = {}; - saved.forEach(function (_, i) { - ders[i] = function () { return dy.clone(); }; - }); - return ders; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates a `tf.Tensor` with all elements set to 0 with the same shape as the - * given tensor. - * - * ```js - * const x = tf.tensor([1, 2]); - * tf.zerosLike(x).print(); - * ``` - * - * @param x The tensor of required shape. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function zerosLike_(x) { - var $x = convertToTensor(x, 'x', 'zerosLike'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend) { return backend.zerosLike($x); }, inputs, null /* grad */, ZerosLike); - } - var zerosLike = op({ zerosLike_: zerosLike_ }); - - /** - * @license - * Copyright 2020 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var argMaxGradConfig = { - kernelName: ArgMax, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return zerosLike(x); } }; - } - }; - - /** - * @license - * Copyright 2020 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var argMinGradConfig = { - kernelName: ArgMin, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return zerosLike(x); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var asinGradConfig = { - kernelName: Asin, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, sqrt(sub(scalar(1), square(cast(x, 'float32'))))); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Adds two `tf.Tensor`s element-wise, A + B. Supports broadcasting. - * - * - * ```js - * const a = tf.tensor1d([1, 2, 3, 4]); - * const b = tf.tensor1d([10, 20, 30, 40]); - * - * a.add(b).print(); // or tf.add(a, b) - * ``` - * - * ```js - * // Broadcast add a with b. - * const a = tf.scalar(5); - * const b = tf.tensor1d([10, 20, 30, 40]); - * - * a.add(b).print(); // or tf.add(a, b) - * ``` - * @param a The first `tf.Tensor` to add. - * @param b The second `tf.Tensor` to add. Must have the same type as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ - function add_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'add'); - var $b = convertToTensor(b, 'b', 'add'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - var forward = function (backend, save) { - var res = backend.add($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Add); - } - var add = op({ add_: add_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var asinhGradConfig = { - kernelName: Asinh, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { - x: function () { - var a = sqrt(add(scalar(1), square(cast(x, 'float32')))); - return div(dy, a); - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Reshapes a `tf.Tensor` to a given shape. - * - * Given an input tensor, returns a new tensor with the same values as the - * input tensor with shape `shape`. - * - * If one component of shape is the special value -1, the size of that - * dimension is computed so that the total size remains constant. In - * particular, a shape of [-1] flattens into 1-D. At most one component of - * shape can be -1. - * - * If shape is 1-D or higher, then the operation returns a tensor with shape - * shape filled with the values of tensor. In this case, the number of - * elements implied by shape must be the same as the number of elements in - * tensor. - * - * ```js - * const x = tf.tensor1d([1, 2, 3, 4]); - * x.reshape([2, 2]).print(); - * ``` - * - * @param x The input tensor to be reshaped. - * @param shape An array of integers defining the output tensor shape. - */ - /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ - function reshape_(x, shape) { - var $x = convertToTensor(x, 'x', 'reshape', null); - shape = inferFromImplicitShape(shape, $x.size); - assert($x.size === sizeFromShape(shape), function () { return 'new shape and old shape must have the same number of elements.'; }); - var inputs = { x: $x }; - var attrs = { shape: shape }; - var forward = function (backend, save) { - save([$x]); - return backend.reshape($x, shape); - }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Reshape, attrs); - } - var reshape = op({ reshape_: reshape_ }); - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns true if the axis specifies the inner most dimensions of the - * array. - */ - function axesAreInnerMostDims(axes, rank) { - for (var i = 0; i < axes.length; ++i) { - if (axes[axes.length - i - 1] !== rank - 1 - i) { - return false; - } - } - return true; - } - function combineLocations(outputLoc, reduceLoc, axes) { - var rank = outputLoc.length + reduceLoc.length; - var loc = []; - var outIdx = 0; - var reduceIdx = 0; - for (var dim = 0; dim < rank; dim++) { - if (axes.indexOf(dim) === -1) { - loc.push(outputLoc[outIdx++]); - } - else { - loc.push(reduceLoc[reduceIdx++]); - } - } - return loc; - } - function computeOutAndReduceShapes(aShape, axes) { - var outShape = []; - var rank = aShape.length; - for (var dim = 0; dim < rank; dim++) { - if (axes.indexOf(dim) === -1) { - outShape.push(aShape[dim]); - } - } - var reduceShape = axes.map(function (dim) { return aShape[dim]; }); - return [outShape, reduceShape]; - } - function expandShapeToKeepDim(shape, axes) { - var reduceSubShape = axes.map(function (x) { return 1; }); - return combineLocations(shape, reduceSubShape, axes); - } - function assertAxesAreInnerMostDims(msg, axes, rank) { - assert(axesAreInnerMostDims(axes, rank), function () { return msg + " supports only inner-most axes for now. " + - ("Got axes " + axes + " and rank-" + rank + " input."); }); - } - /** - * Returns the axes permutation to be used with `tf.transpose`, if such - * permutation is necessary. Otherwise it returns null. This method is used by - * operations that operate only on inner-most axes. - */ - function getAxesPermutation(axes, rank) { - if (axesAreInnerMostDims(axes, rank)) { - return null; - } - var result = []; - for (var i = 0; i < rank; ++i) { - if (axes.indexOf(i) === -1) { - result.push(i); - } - } - axes.forEach(function (axis) { return result.push(axis); }); - return result; - } - /** Returns the axes permutation that undoes the original permutation. */ - function getUndoAxesPermutation(axes) { - return axes.map(function (axis, i) { return [i, axis]; }) - .sort(function (a, b) { return a[1] - b[1]; }) - .map(function (x) { return x[0]; }); - } - function getInnerMostAxes(numAxes, rank) { - var res = []; - for (var i = rank - numAxes; i < rank; ++i) { - res.push(i); - } - return res; - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the sum of elements across dimensions of a `tf.Tensor`. - * - * Reduces the input along the dimensions given in `axes`. Unless `keepDims` - * is true, the rank of the `tf.Tensor` is reduced by 1 for each entry in - * `axes`. If `keepDims` is true, the reduced dimensions are retained with - * length 1. If axes has no entries, all dimensions are reduced, and a - * `tf.Tensor` with a single element is returned. - * - * ```js - * const x = tf.tensor1d([1, 2, 3]); - * - * x.sum().print(); // or tf.sum(x) - * ``` - * - * ```js - * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); - * - * const axis = 1; - * x.sum(axis).print(); // or tf.sum(x, axis) - * ``` - * - * @param x The input tensor to compute the sum over. If the dtype is `bool` - * it will be converted to `int32` and the output dtype will be `int32`. - * @param axis The dimension(s) to reduce. By default it reduces - * all dimensions. - * @param keepDims If true, retains reduced dimensions with size 1. - */ - /** @doc {heading: 'Operations', subheading: 'Reduction'} */ - function sum_(x, axis, keepDims) { - if (axis === void 0) { axis = null; } - if (keepDims === void 0) { keepDims = false; } - var $x = convertToTensor(x, 'x', 'sum'); - if ($x.dtype === 'bool') { - $x = $x.toInt(); - } - var forward = function (backend, save) { - save([$x]); - var axes = parseAxisParam(axis, $x.shape); - var permutation = getAxesPermutation(axes, $x.rank); - var reductionAxes = axes; - var permutedX = $x; - if (permutation != null) { - permutedX = $x.transpose(permutation); - reductionAxes = getInnerMostAxes(reductionAxes.length, $x.rank); - } - var value = backend.sum(permutedX, reductionAxes); - if (keepDims) { - var newShape = expandShapeToKeepDim(value.shape, axes); - value = value.reshape(newShape); - } - return value; - }; - var inputs = { x: $x }; - var attrs = { axis: axis, keepDims: keepDims }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Sum, attrs); - } - var sum$1 = op({ sum_: sum_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var atan2GradConfig = { - kernelName: Atan2, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var outShape = assertAndGetBroadcastShape(a.shape, b.shape); - var derA = function () { - var d = add(square(a), square(b)); - var res = mul(dy, div(b, d)); - var reduceAxes = getReductionAxes(a.shape, outShape); - if (reduceAxes.length > 0) { - res = sum$1(res, reduceAxes); - } - return reshape(res, a.shape); - }; - var derB = function () { - var d = add(square(a), square(b)); - var res = neg(mul(dy, div(a, d))); - var reduceAxes = getReductionAxes(b.shape, outShape); - if (reduceAxes.length > 0) { - res = sum$1(res, reduceAxes); - } - return reshape(res, b.shape); - }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var atanGradConfig = { - kernelName: Atan, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, add(square(cast(x, 'float32')), 1)); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var atanhGradConfig = { - kernelName: Atanh, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, sub(scalar(1), square(cast(x, 'float32')))); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * - * @param inputShape Input tensor shape is of the following dimensions: - * `[batch, height, width, inChannels]`. - * @param filterShape The filter shape is of the following dimensions: - * `[filterHeight, filterWidth, depth]`. - * @param strides The strides of the sliding window for each dimension of the - * input tensor: `[strideHeight, strideWidth]`. - * If `strides` is a single number, - * then `strideHeight == strideWidth`. - * @param pad The type of padding algorithm. - * - `same` and stride 1: output will be of same size as input, - * regardless of filter size. - * - `valid`: output will be smaller than input if filter is larger - * than 1*1x1. - * - For more info, see this guide: - * [https://www.tensorflow.org/api_guides/python/nn#Convolution]( - * https://www.tensorflow.org/api_guides/python/nn#Convolution) - * @param dataFormat The data format of the input and output data. - * Defaults to 'NHWC'. - * @param dilations The dilation rates: `[dilationHeight, dilationWidth]`. - * Defaults to `[1, 1]`. If `dilations` is a single number, then - * `dilationHeight == dilationWidth`. - */ - function computeDilation2DInfo(inputShape, filterShape, strides, pad, dataFormat, dilations) { - if (dataFormat === void 0) { dataFormat = 'NHWC'; } - // `computerConv2DInfo` require filterShape to be in the dimension of: - // `[filterHeight, filterWidth, depth, outDepth]`, dilation2d doesn't have - // outDepth, it should have the same depth as the input. - // Input shape: [batch, height, width, inChannels] - var inputChannels = inputShape[3]; - var $filterShape = filterShape.concat([inputChannels]); - var $dataFormat = convertConv2DDataFormat(dataFormat); - return computeConv2DInfo(inputShape, $filterShape, strides, dilations, pad, null /* roundingMode */, null /* depthWise */, $dataFormat); - } - function computePool2DInfo(inShape, filterSize, strides, dilations, pad, roundingMode, dataFormat) { - if (dataFormat === void 0) { dataFormat = 'channelsLast'; } - var _a = parseTupleParam(filterSize), filterHeight = _a[0], filterWidth = _a[1]; - var filterShape; - if (dataFormat === 'channelsLast') { - filterShape = [filterHeight, filterWidth, inShape[3], inShape[3]]; - } - else if (dataFormat === 'channelsFirst') { - filterShape = [filterHeight, filterWidth, inShape[1], inShape[1]]; - } - else { - throw new Error("Unknown dataFormat " + dataFormat); - } - return computeConv2DInfo(inShape, filterShape, strides, dilations, pad, roundingMode, false, dataFormat); - } - /** - * Computes the information for a forward pass of a pooling3D operation. - */ - function computePool3DInfo(inShape, filterSize, strides, dilations, pad, roundingMode, dataFormat) { - if (dataFormat === void 0) { dataFormat = 'NDHWC'; } - var _a = parse3TupleParam(filterSize), filterDepth = _a[0], filterHeight = _a[1], filterWidth = _a[2]; - var filterShape; - var $dataFormat; - if (dataFormat === 'NDHWC') { - $dataFormat = 'channelsLast'; - filterShape = - [filterDepth, filterHeight, filterWidth, inShape[4], inShape[4]]; - } - else if (dataFormat === 'NCDHW') { - $dataFormat = 'channelsFirst'; - filterShape = - [filterDepth, filterHeight, filterWidth, inShape[1], inShape[1]]; - } - else { - throw new Error("Unknown dataFormat " + dataFormat); - } - return computeConv3DInfo(inShape, filterShape, strides, dilations, pad, false, $dataFormat, roundingMode); - } - /** - * Computes the information for a forward pass of a convolution/pooling - * operation. - */ - function computeConv2DInfo(inShape, filterShape, strides, dilations, pad, roundingMode, depthwise, dataFormat) { - if (depthwise === void 0) { depthwise = false; } - if (dataFormat === void 0) { dataFormat = 'channelsLast'; } - var _a = [-1, -1, -1, -1], batchSize = _a[0], inHeight = _a[1], inWidth = _a[2], inChannels = _a[3]; - if (dataFormat === 'channelsLast') { - batchSize = inShape[0], inHeight = inShape[1], inWidth = inShape[2], inChannels = inShape[3]; - } - else if (dataFormat === 'channelsFirst') { - batchSize = inShape[0], inChannels = inShape[1], inHeight = inShape[2], inWidth = inShape[3]; - } - else { - throw new Error("Unknown dataFormat " + dataFormat); - } - var filterHeight = filterShape[0], filterWidth = filterShape[1], filterChannels = filterShape[3]; - var _b = parseTupleParam(strides), strideHeight = _b[0], strideWidth = _b[1]; - var _c = parseTupleParam(dilations), dilationHeight = _c[0], dilationWidth = _c[1]; - var effectiveFilterHeight = getEffectiveFilterSize(filterHeight, dilationHeight); - var effectiveFilterWidth = getEffectiveFilterSize(filterWidth, dilationWidth); - var _d = getPadAndOutInfo(pad, inHeight, inWidth, strideHeight, strideWidth, effectiveFilterHeight, effectiveFilterWidth, roundingMode, dataFormat), padInfo = _d.padInfo, outHeight = _d.outHeight, outWidth = _d.outWidth; - var outChannels = depthwise ? filterChannels * inChannels : filterChannels; - var outShape; - if (dataFormat === 'channelsFirst') { - outShape = [batchSize, outChannels, outHeight, outWidth]; - } - else if (dataFormat === 'channelsLast') { - outShape = [batchSize, outHeight, outWidth, outChannels]; - } - return { - batchSize: batchSize, - dataFormat: dataFormat, - inHeight: inHeight, - inWidth: inWidth, - inChannels: inChannels, - outHeight: outHeight, - outWidth: outWidth, - outChannels: outChannels, - padInfo: padInfo, - strideHeight: strideHeight, - strideWidth: strideWidth, - filterHeight: filterHeight, - filterWidth: filterWidth, - effectiveFilterHeight: effectiveFilterHeight, - effectiveFilterWidth: effectiveFilterWidth, - dilationHeight: dilationHeight, - dilationWidth: dilationWidth, - inShape: inShape, - outShape: outShape, - filterShape: filterShape - }; - } - /** - * Computes the information for a forward pass of a 3D convolution/pooling - * operation. - */ - function computeConv3DInfo(inShape, filterShape, strides, dilations, pad, depthwise, dataFormat, roundingMode) { - if (depthwise === void 0) { depthwise = false; } - if (dataFormat === void 0) { dataFormat = 'channelsLast'; } - var _a = [-1, -1, -1, -1, -1], batchSize = _a[0], inDepth = _a[1], inHeight = _a[2], inWidth = _a[3], inChannels = _a[4]; - if (dataFormat === 'channelsLast') { - batchSize = inShape[0], inDepth = inShape[1], inHeight = inShape[2], inWidth = inShape[3], inChannels = inShape[4]; - } - else if (dataFormat === 'channelsFirst') { - batchSize = inShape[0], inChannels = inShape[1], inDepth = inShape[2], inHeight = inShape[3], inWidth = inShape[4]; - } - else { - throw new Error("Unknown dataFormat " + dataFormat); - } - var filterDepth = filterShape[0], filterHeight = filterShape[1], filterWidth = filterShape[2], filterChannels = filterShape[4]; - var _b = parse3TupleParam(strides), strideDepth = _b[0], strideHeight = _b[1], strideWidth = _b[2]; - var _c = parse3TupleParam(dilations), dilationDepth = _c[0], dilationHeight = _c[1], dilationWidth = _c[2]; - var effectiveFilterDepth = getEffectiveFilterSize(filterDepth, dilationDepth); - var effectiveFilterHeight = getEffectiveFilterSize(filterHeight, dilationHeight); - var effectiveFilterWidth = getEffectiveFilterSize(filterWidth, dilationWidth); - var _d = get3DPadAndOutInfo(pad, inDepth, inHeight, inWidth, strideDepth, strideHeight, strideWidth, effectiveFilterDepth, effectiveFilterHeight, effectiveFilterWidth, roundingMode), padInfo = _d.padInfo, outDepth = _d.outDepth, outHeight = _d.outHeight, outWidth = _d.outWidth; - var outChannels = depthwise ? filterChannels * inChannels : filterChannels; - var outShape; - if (dataFormat === 'channelsFirst') { - outShape = [batchSize, outChannels, outDepth, outHeight, outWidth]; - } - else if (dataFormat === 'channelsLast') { - outShape = [batchSize, outDepth, outHeight, outWidth, outChannels]; - } - return { - batchSize: batchSize, - dataFormat: dataFormat, - inDepth: inDepth, - inHeight: inHeight, - inWidth: inWidth, - inChannels: inChannels, - outDepth: outDepth, - outHeight: outHeight, - outWidth: outWidth, - outChannels: outChannels, - padInfo: padInfo, - strideDepth: strideDepth, - strideHeight: strideHeight, - strideWidth: strideWidth, - filterDepth: filterDepth, - filterHeight: filterHeight, - filterWidth: filterWidth, - effectiveFilterDepth: effectiveFilterDepth, - effectiveFilterHeight: effectiveFilterHeight, - effectiveFilterWidth: effectiveFilterWidth, - dilationDepth: dilationDepth, - dilationHeight: dilationHeight, - dilationWidth: dilationWidth, - inShape: inShape, - outShape: outShape, - filterShape: filterShape - }; - } - function computeOutputShape2D(inShape, fieldSize, stride, zeroPad, roundingMode) { - if (zeroPad == null) { - zeroPad = computeDefaultPad(inShape, fieldSize, stride); - } - var inputRows = inShape[0]; - var inputCols = inShape[1]; - var outputRows = conditionalRound((inputRows - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); - assert(isInt(outputRows), function () { return "The output # of rows (" + outputRows + ") must be an integer. " + - "Change the stride and/or zero pad parameters"; }); - var outputCols = conditionalRound((inputCols - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); - assert(isInt(outputCols), function () { return "The output # of columns (" + outputCols + ") must be an integer. " + - "Change the stride and/or zero pad parameters"; }); - return [outputRows, outputCols]; - } - function computeOutputShape4D(inShape, fieldSize, outChannels, stride, zeroPad, roundingMode) { - if (zeroPad == null) { - zeroPad = computeDefaultPad(inShape, fieldSize, stride); - } - var inputDepth = inShape[0]; - var inputRows = inShape[1]; - var inputCols = inShape[2]; - var outputDepths = conditionalRound((inputDepth - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); - assert(isInt(outputDepths), function () { return "The output # of depths (" + outputDepths + ") must be an integer. " + - "Change the stride and/or zero pad parameters"; }); - var outputRows = conditionalRound((inputRows - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); - assert(isInt(outputRows), function () { return "The output # of rows (" + outputRows + ") must be an integer. " + - "Change the stride and/or zero pad parameters"; }); - var outputCols = conditionalRound((inputCols - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); - assert(isInt(outputCols), function () { return "The output # of columns (" + outputCols + ") must be an integer. " + - "Change the stride and/or zero pad parameters"; }); - return [outputDepths, outputRows, outputCols, outChannels]; - } - function computeDefaultPad(inputShape, fieldSize, stride, dilation) { - if (dilation === void 0) { dilation = 1; } - var effectiveFieldSize = getEffectiveFilterSize(fieldSize, dilation); - return Math.floor((inputShape[0] * (stride - 1) - stride + effectiveFieldSize) / 2); - } - function parseTupleParam(param) { - if (typeof param === 'number') { - return [param, param, param]; - } - if (param.length === 2) { - return [param[0], param[1], 1]; - } - return param; - } - function parse3TupleParam(param) { - return typeof param === 'number' ? [param, param, param] : param; - } - /* See https://www.tensorflow.org/api_docs/python/tf/nn/atrous_conv2d - * Atrous convolution is equivalent to standard convolution with upsampled - * filters with effective_filter_height = - * filter_height + (filter_height - 1) * (dilation - 1) - * and effective_filter_width = - * filter_width + (filter_width - 1) * (dilation - 1), - * produced by inserting dilation - 1 zeros along consecutive elements across - * the filters' spatial dimensions. - * When there is a dilation, this converts a filter dimension to the - * effective filter dimension, so it can be used in a standard convolution. - */ - function getEffectiveFilterSize(filterSize, dilation) { - if (dilation <= 1) { - return filterSize; - } - return filterSize + (filterSize - 1) * (dilation - 1); - } - function getPadAndOutInfo(pad, inHeight, inWidth, strideHeight, strideWidth, filterHeight, filterWidth, roundingMode, dataFormat) { - var padInfo; - var outHeight; - var outWidth; - if (typeof pad === 'number') { - var padType = (pad === 0) ? 'VALID' : 'NUMBER'; - padInfo = { top: pad, bottom: pad, left: pad, right: pad, type: padType }; - var outShape = computeOutputShape2D([inHeight, inWidth], filterHeight, strideHeight, pad, roundingMode); - outHeight = outShape[0]; - outWidth = outShape[1]; - } - else if (pad === 'same') { - outHeight = Math.ceil(inHeight / strideHeight); - outWidth = Math.ceil(inWidth / strideWidth); - var padAlongHeight = Math.max(0, (outHeight - 1) * strideHeight + filterHeight - inHeight); - var padAlongWidth = Math.max(0, (outWidth - 1) * strideWidth + filterWidth - inWidth); - var top_1 = Math.floor(padAlongHeight / 2); - var bottom = padAlongHeight - top_1; - var left = Math.floor(padAlongWidth / 2); - var right = padAlongWidth - left; - padInfo = { top: top_1, bottom: bottom, left: left, right: right, type: 'SAME' }; - } - else if (pad === 'valid') { - padInfo = { top: 0, bottom: 0, left: 0, right: 0, type: 'VALID' }; - outHeight = Math.ceil((inHeight - filterHeight + 1) / strideHeight); - outWidth = Math.ceil((inWidth - filterWidth + 1) / strideWidth); - } - else if (typeof pad === 'object') { - var top_2 = dataFormat === 'channelsLast' ? pad[1][0] : pad[2][0]; - var bottom = dataFormat === 'channelsLast' ? pad[1][1] : pad[2][1]; - var left = dataFormat === 'channelsLast' ? pad[2][0] : pad[3][0]; - var right = dataFormat === 'channelsLast' ? pad[2][1] : pad[3][1]; - var padType = (top_2 === 0 && bottom === 0 && left === 0 && right === 0) ? - 'VALID' : - 'EXPLICIT'; - padInfo = { top: top_2, bottom: bottom, left: left, right: right, type: padType }; - outHeight = conditionalRound((inHeight - filterHeight + top_2 + bottom) / strideHeight + 1, roundingMode); - outWidth = conditionalRound((inWidth - filterWidth + left + right) / strideWidth + 1, roundingMode); - } - else { - throw Error("Unknown padding parameter: " + pad); - } - return { padInfo: padInfo, outHeight: outHeight, outWidth: outWidth }; - } - function get3DPadAndOutInfo(pad, inDepth, inHeight, inWidth, strideDepth, strideHeight, strideWidth, filterDepth, filterHeight, filterWidth, roundingMode) { - var padInfo; - var outDepth; - var outHeight; - var outWidth; - if (typeof pad === 'number') { - var padType = (pad === 0) ? 'VALID' : 'NUMBER'; - padInfo = { - top: pad, - bottom: pad, - left: pad, - right: pad, - front: pad, - back: pad, - type: padType - }; - var outShape = computeOutputShape4D([inDepth, inHeight, inWidth, 1], filterDepth, 1, strideDepth, pad, roundingMode); - outDepth = outShape[0]; - outHeight = outShape[1]; - outWidth = outShape[2]; - } - else if (pad === 'same') { - outDepth = Math.ceil(inDepth / strideDepth); - outHeight = Math.ceil(inHeight / strideHeight); - outWidth = Math.ceil(inWidth / strideWidth); - var padAlongDepth = (outDepth - 1) * strideDepth + filterDepth - inDepth; - var padAlongHeight = (outHeight - 1) * strideHeight + filterHeight - inHeight; - var padAlongWidth = (outWidth - 1) * strideWidth + filterWidth - inWidth; - var front = Math.floor(padAlongDepth / 2); - var back = padAlongDepth - front; - var top_3 = Math.floor(padAlongHeight / 2); - var bottom = padAlongHeight - top_3; - var left = Math.floor(padAlongWidth / 2); - var right = padAlongWidth - left; - padInfo = { top: top_3, bottom: bottom, left: left, right: right, front: front, back: back, type: 'SAME' }; - } - else if (pad === 'valid') { - padInfo = { - top: 0, - bottom: 0, - left: 0, - right: 0, - front: 0, - back: 0, - type: 'VALID' - }; - outDepth = Math.ceil((inDepth - filterDepth + 1) / strideDepth); - outHeight = Math.ceil((inHeight - filterHeight + 1) / strideHeight); - outWidth = Math.ceil((inWidth - filterWidth + 1) / strideWidth); - } - else { - throw Error("Unknown padding parameter: " + pad); - } - return { padInfo: padInfo, outDepth: outDepth, outHeight: outHeight, outWidth: outWidth }; - } - /** - * Rounds a value depending on the rounding mode - * @param value - * @param roundingMode - */ - function conditionalRound(value, roundingMode) { - if (!roundingMode) { - return value; - } - switch (roundingMode) { - case 'round': - // used for Caffe Conv - return Math.round(value); - case 'ceil': - // used for Caffe Pool - return Math.ceil(value); - case 'floor': - return Math.floor(value); - default: - throw new Error("Unknown roundingMode " + roundingMode); - } - } - function tupleValuesAreOne(param) { - var _a = parseTupleParam(param), dimA = _a[0], dimB = _a[1], dimC = _a[2]; - return dimA === 1 && dimB === 1 && dimC === 1; - } - function eitherStridesOrDilationsAreOne(strides, dilations) { - return tupleValuesAreOne(strides) || tupleValuesAreOne(dilations); - } - /** - * Convert Conv2D dataFormat from 'NHWC'|'NCHW' to - * 'channelsLast'|'channelsFirst' - * @param dataFormat in 'NHWC'|'NCHW' mode - * @return dataFormat in 'channelsLast'|'channelsFirst' mode - * @throws unknown dataFormat - */ - function convertConv2DDataFormat(dataFormat) { - if (dataFormat === 'NHWC') { - return 'channelsLast'; - } - else if (dataFormat === 'NCHW') { - return 'channelsFirst'; - } - else { - throw new Error("Unknown dataFormat " + dataFormat); - } - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the backprop of a 3d avg pool. - * - * @param dy The dy error, of rank 5 of shape - * [batchSize, depth, height, width, channels]. - * assumed. - * @param input The original input image, of rank 5 or rank4 of shape - * [batchSize, depth, height, width, channels]. - * @param filterSize The filter size: - * `[filterDepth, filterHeight, filterWidth]`. - * `filterSize` is a single number, - * then `filterDepth == filterHeight == filterWidth`. - * @param strides The strides of the pooling: - * `[strideDepth, strideHeight, strideWidth]`. If - * `strides` is a single number, then `strideHeight == strideWidth`. - * @param dilations Deprecated, this field will be gone in v3.0.0. The dilation - * rates: `[dilationDepth, dilationHeight, dilationWidth]` - * in which we sample input values across the depth, height and width - * dimensions in dilated pooling. - * Defaults to `[1, 1, 1]`. If `dilations` is a single number, - * then `dilationDepth == dilationHeight == dilationWidth`. - * If it is greater than 1, then all values of `strides` must be 1. - * @param pad A string from: 'same', 'valid'. The type of padding algorithm - * used in the forward prop of the op. - * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The - * rounding mode used when computing output dimensions if pad is a - * number. If none is provided, it will not round and error if the output - * is of fractional size. - */ - function avgPool3dBackprop_(dy, input, filterSize, strides, dilations, pad, dimRoundingMode) { - if (dilations === void 0) { dilations = [1, 1, 1]; } - var $dy = convertToTensor(dy, 'dy', 'avgPool3dBackprop'); - var $input = convertToTensor(input, 'input', 'avgPool3dBackprop'); - var dy5D = $dy; - var input5D = $input; - var reshapedTo5D = false; - if ($input.rank === 4) { - reshapedTo5D = true; - dy5D = reshape($dy, [1, $dy.shape[0], $dy.shape[1], $dy.shape[2], $dy.shape[3]]); - input5D = reshape($input, [ - 1, $input.shape[0], $input.shape[1], $input.shape[2], $input.shape[3] - ]); - } - assert(dy5D.rank === 5, function () { return "Error in avgPool3dBackprop: dy must be rank 5 but got rank " + - (dy5D.rank + "."); }); - assert(input5D.rank === 5, function () { return "Error in avgPool3dBackprop: input must be rank 5 but got rank " + - (input5D.rank + "."); }); - assert(eitherStridesOrDilationsAreOne(strides, dilations), function () { return 'Error in avgPool3dBackprop: Either strides or dilations ' + - ("must be 1. Got strides " + strides + " and dilations '" + dilations + "'"); }); - if (dimRoundingMode != null) { - assert(isInt(pad), function () { return "Error in maxPool3dBackprop: pad must be an integer when " + - ("using, dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); - } - var forward = function (backend) { - var convInfo = computePool3DInfo(input5D.shape, filterSize, strides, dilations, pad, dimRoundingMode); - return backend.avgPool3dBackprop(dy5D, input5D, convInfo); - }; - var inputs = { dy: dy5D, input: input5D }; - var attrs = { filterSize: filterSize, strides: strides, dilations: dilations, pad: pad, dimRoundingMode: dimRoundingMode }; - var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, AvgPool3DBackprop, attrs); - if (reshapedTo5D) { - return reshape(res, [res.shape[1], res.shape[2], res.shape[3], res.shape[4]]); - } - return res; - } - var avgPool3dBackprop = op({ avgPool3dBackprop_: avgPool3dBackprop_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var avgPool3DGradConfig = { - kernelName: AvgPool3D, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0]; - var _a = attrs, filterSize = _a.filterSize, strides = _a.strides, dilations = _a.dilations, pad = _a.pad, dimRoundingMode = _a.dimRoundingMode; - var $dilations = dilations == null ? [1, 1, 1] : dilations; - return { - x: function () { return avgPool3dBackprop(dy, x, filterSize, strides, $dilations, pad, dimRoundingMode); } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the backprop of an 2D avg pool. - * - * @param dy The dy error, of rank 4 or rank 3 of shape - * [batchSize, height, width, channels]. If rank 3, batch of 1 is - * assumed. - * @param input The input image, of rank 4 or rank 3 of shape - * [batchSize, height, width, channels]. If rank 3, batch of 1 is - * assumed. - * @param filterSize The filter size: `[filterHeight, filterWidth]`. If - * `filterSize` is a single number, then `filterHeight == filterWidth`. - * @param strides The strides of the pooling: `[strideHeight, strideWidth]`. If - * `strides` is a single number, then `strideHeight == strideWidth`. - * @param pad A string from: 'same', 'valid'. The type of padding algorithm - * used in the forward prop of the op. - */ - function avgPoolBackprop_(dy, input, filterSize, strides, pad) { - var $dy = convertToTensor(dy, 'dy', 'avgPoolBackprop'); - var $input = convertToTensor(input, 'input', 'avgPoolBackprop'); - assert($input.rank === $dy.rank, function () { return "Rank of input (" + $input.rank + ") does not match rank of dy (" + $dy.rank + ")"; }); - var input4D = $input; - var dy4D = $dy; - var reshapedTo4D = false; - if ($input.rank === 3) { - reshapedTo4D = true; - input4D = - reshape($input, [1, $input.shape[0], $input.shape[1], $input.shape[2]]); - dy4D = reshape($dy, [1, $dy.shape[0], $dy.shape[1], $dy.shape[2]]); - } - assert(dy4D.rank === 4, function () { return "Error in avgPoolBackprop: dy must be rank 4 but got rank " + - (dy4D.rank + "."); }); - assert(input4D.rank === 4, function () { return "Error in avgPoolBackprop: input must be rank 4 but got rank " + - (input4D.rank + "."); }); - var forward = function (backend) { - var convInfo = computePool2DInfo(input4D.shape, filterSize, strides, 1 /* dilations */, pad); - return backend.avgPoolBackprop(dy4D, input4D, convInfo); - }; - var inputs = { dy: dy4D, input: input4D }; - var attrs = { filterSize: filterSize, strides: strides, pad: pad }; - var res = ENGINE.runKernelFunc(forward, inputs, null, AvgPoolBackprop, attrs); - if (reshapedTo4D) { - return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); - } - return res; - } - var avgPoolBackprop = op({ avgPoolBackprop_: avgPoolBackprop_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var avgPoolGradConfig = { - kernelName: AvgPool, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0]; - var _a = attrs, filterSize = _a.filterSize, strides = _a.strides, pad = _a.pad; - return { - x: function () { return avgPoolBackprop(dy, x, filterSize, strides, pad); } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the dot product of two matrices, A * B. These must be matrices. - * - * ```js - * const a = tf.tensor2d([1, 2], [1, 2]); - * const b = tf.tensor2d([1, 2, 3, 4], [2, 2]); - * - * a.matMul(b).print(); // or tf.matMul(a, b) - * ``` - * @param a First matrix in dot product operation. - * @param b Second matrix in dot product operation. - * @param transposeA If true, `a` is transposed before multiplication. - * @param transposeB If true, `b` is transposed before multiplication. - */ - /** @doc {heading: 'Operations', subheading: 'Matrices'} */ - function matMul_(a, b, transposeA, transposeB) { - var _a; - if (transposeA === void 0) { transposeA = false; } - if (transposeB === void 0) { transposeB = false; } - var $a = convertToTensor(a, 'a', 'matMul'); - var $b = convertToTensor(b, 'b', 'matMul'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - assert($a.rank >= 2 && $b.rank >= 2 && $a.rank === $b.rank, function () { return "Error in matMul: inputs must have the same rank of at least 2, " + - ("got ranks " + $a.rank + " and " + $b.rank + "."); }); - var innerShapeA = transposeA ? $a.shape[$a.rank - 2] : $a.shape[$a.rank - 1]; - var innerShapeB = transposeB ? $b.shape[$b.rank - 1] : $b.shape[$b.rank - 2]; - var outerShapeA = transposeA ? $a.shape[$a.rank - 1] : $a.shape[$a.rank - 2]; - var outerShapeB = transposeB ? $b.shape[$b.rank - 2] : $b.shape[$b.rank - 1]; - var outerDimsA = $a.shape.slice(0, -2); - var outerDimsB = $b.shape.slice(0, -2); - var batchDimA = sizeFromShape(outerDimsA); - var batchDimB = sizeFromShape(outerDimsB); - assert(arraysEqual(outerDimsA, outerDimsB), function () { return "Error in matMul: outer dimensions (" + outerDimsA + ") and (" + - (outerDimsB + ") of Tensors with shapes " + $a.shape + " and ") + - ($b.shape + " must match."); }); - assert(innerShapeA === innerShapeB, function () { return "Error in matMul: inner shapes (" + innerShapeA + ") and (" + - (innerShapeB + ") of Tensors with shapes " + $a.shape + " and ") + - ($b.shape + " and transposeA=" + transposeA) + - (" and transposeB=" + transposeB + " must match."); }); - var outShape = $a.shape.slice(0, -2).concat([outerShapeA, outerShapeB]); - var a3D = transposeA ? reshape($a, [batchDimA, innerShapeA, outerShapeA]) : - reshape($a, [batchDimA, outerShapeA, innerShapeA]); - var b3D = transposeB ? reshape($b, [batchDimB, outerShapeB, innerShapeB]) : - reshape($b, [batchDimB, innerShapeB, outerShapeB]); - var forward = function (backend, save) { - save([a3D, b3D]); - return backend.batchMatMul(a3D, b3D, transposeA, transposeB); - }; - var inputs = { a: a3D, b: b3D }; - var attrs = { transposeA: transposeA, transposeB: transposeB }; - var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, BatchMatMul, attrs); - return reshape(res, outShape); - } - var matMul = op({ matMul_: matMul_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var batchMatMulGradConfig = { - kernelName: BatchMatMul, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved, attrs) { - var _a = saved, a = _a[0], b = _a[1]; - var _b = attrs, transposeA = _b.transposeA, transposeB = _b.transposeB; - if (!transposeA && !transposeB) { - return { - a: function () { return matMul(dy, b, false, true); }, - b: function () { return matMul(a, dy, true, false); } - }; - } - else if (!transposeA && transposeB) { - return { - a: function () { return matMul(dy, b, false, false); }, - b: function () { return matMul(dy, a, true, false); } - }; - } - else if (transposeA && !transposeB) { - return { - a: function () { return matMul(b, dy, false, true); }, - b: function () { return matMul(a, dy, false, false); } - }; - } - else { - return { - a: function () { return matMul(b, dy, true, true); }, - b: function () { return matMul(dy, a, true, true); } - }; - } - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * This operation divides "spatial" dimensions `[1, ..., M]` of the input into - * a grid of blocks of shape `blockShape`, and interleaves these blocks with - * the "batch" dimension (0) such that in the output, the spatial - * dimensions `[1, ..., M]` correspond to the position within the grid, - * and the batch dimension combines both the position within a spatial block - * and the original batch position. Prior to division into blocks, - * the spatial dimensions of the input are optionally zero padded - * according to `paddings`. See below for a precise description. - * - * ```js - * const x = tf.tensor4d([1, 2, 3, 4], [1, 2, 2, 1]); - * const blockShape = [2, 2]; - * const paddings = [[0, 0], [0, 0]]; - * - * x.spaceToBatchND(blockShape, paddings).print(); - * ``` - * - * @param x A `tf.Tensor`. N-D with `x.shape` = `[batch] + spatialShape + - * remainingShape`, where spatialShape has `M` dimensions. - * @param blockShape A 1-D array. Must have shape `[M]`, all values must - * be >= 1. - * @param paddings A 2-D array. Must have shape `[M, 2]`, all values must be >= - * 0. `paddings[i] = [padStart, padEnd]` specifies the amount to zero-pad - * from input dimension `i + 1`, which corresponds to spatial dimension `i`. It - * is required that - * `(inputShape[i + 1] + padStart + padEnd) % blockShape[i] === 0` - * - * This operation is equivalent to the following steps: - * - * 1. Zero-pad the start and end of dimensions `[1, ..., M]` of the input - * according to `paddings` to produce `padded` of shape paddedShape. - * - * 2. Reshape `padded` to `reshapedPadded` of shape: - * `[batch] + [paddedShape[1] / blockShape[0], blockShape[0], ..., - * paddedShape[M] / blockShape[M-1], blockShape[M-1]] + remainingShape` - * - * 3. Permute dimensions of `reshapedPadded` to produce `permutedReshapedPadded` - * of shape: `blockShape + [batch] + [paddedShape[1] / blockShape[0], ..., - * paddedShape[M] / blockShape[M-1]] + remainingShape` - * - * 4. Reshape `permutedReshapedPadded` to flatten `blockShape` into the - * batch dimension, producing an output tensor of shape: - * `[batch * prod(blockShape)] + [paddedShape[1] / blockShape[0], ..., - * paddedShape[M] / blockShape[M-1]] + remainingShape` - */ - /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ - function spaceToBatchND_(x, blockShape, paddings) { - var $x = convertToTensor(x, 'x', 'spaceToBatchND'); - assert($x.rank >= 1 + blockShape.length, function () { return "input rank " + $x.rank + " should be > than [blockShape] " + blockShape.length; }); - assert(paddings.length === blockShape.length, function () { return "paddings.shape[0] " + paddings.length + " must be equal to [blockShape] " + blockShape.length; }); - assert($x.shape.reduce(function (a, b, i) { - if (i > 0 && i <= blockShape.length) { - return a && - ((b + paddings[i - 1][0] + paddings[i - 1][1]) % - blockShape[i - 1] === - 0); - } - return a; - }, true), function () { return "input spatial dimensions " + $x.shape.slice(1) + " with paddings " + paddings.toString() + " must be divisible by blockShapes " + blockShape.toString(); }); - var forward = function (backend) { - return backend.spaceToBatchND($x, blockShape, paddings); - }; - var inputs = { x: $x }; - var attrs = { blockShape: blockShape, paddings: paddings }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, SpaceToBatchND, attrs); - } - var spaceToBatchND = op({ spaceToBatchND_: spaceToBatchND_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var batchToSpaceNDGradConfig = { - kernelName: BatchToSpaceND, - gradFunc: function (dy, saved, attrs) { - var _a = attrs, blockShape = _a.blockShape, crops = _a.crops; - return { x: function () { return spaceToBatchND(dy, blockShape, crops); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var broadcastToGradConfig = { - kernelName: BroadcastTo, - gradFunc: function (dy, saved, attrs) { - var broadCastToAttrs = attrs; - var inputShape = broadCastToAttrs.inputShape; - var outputShape = broadCastToAttrs.shape; - var reps = Array.from(outputShape); - for (var i = inputShape.length - 1; i >= 0; i--) { - if (inputShape[i] === outputShape[i]) { - reps[i] = 1; - } - else if (inputShape[i] !== 1) { - throw new Error("broadcastTo(): [" + inputShape + "] cannot be broadcast to [" + outputShape + "]."); - } - } - var axes = []; - for (var i = 0; i < reps.length; i++) { - if (reps[i] > 1) { - axes.push(i); - } - } - return { x: function () { return sum$1(dy, axes, true /* keepDims */); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var castGradConfig = { - kernelName: Cast, - gradFunc: function (dy) { - return { x: function () { return dy.clone(); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var ceilGradConfig = { - kernelName: Ceil, - gradFunc: function (dy) { - // TODO(manrajgrover): Return null for gradients when backprop supports it. - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the truth value of (a >= b) element-wise. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([1, 2, 3]); - * const b = tf.tensor1d([2, 2, 2]); - * - * a.greaterEqual(b).print(); - * ``` - * - * @param a The first input tensor. - * @param b The second input tensor. Must have the same dtype as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function greaterEqual_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'greaterEqual'); - var $b = convertToTensor(b, 'b', 'greaterEqual'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - assertAndGetBroadcastShape($a.shape, $b.shape); - var forward = function (backend, save) { - var res = backend.greaterEqual($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, GreaterEqual); - } - var greaterEqual = op({ greaterEqual_: greaterEqual_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the truth value of (a <= b) element-wise. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([1, 2, 3]); - * const b = tf.tensor1d([2, 2, 2]); - * - * a.lessEqual(b).print(); - * ``` - * - * @param a The first input tensor. - * @param b The second input tensor. Must have the same dtype as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function lessEqual_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'lessEqual'); - var $b = convertToTensor(b, 'b', 'lessEqual'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - assertAndGetBroadcastShape($a.shape, $b.shape); - var forward = function (backend, save) { - var res = backend.lessEqual($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, LessEqual); - } - var lessEqual = op({ lessEqual_: lessEqual_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the truth value of `a AND b` element-wise. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([false, false, true, true], 'bool'); - * const b = tf.tensor1d([false, true, false, true], 'bool'); - * - * a.logicalAnd(b).print(); - * ``` - * - * @param a The first input tensor. Must be of dtype bool. - * @param b The second input tensor. Must be of dtype bool. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function logicalAnd_(a, b) { - var $a = convertToTensor(a, 'a', 'logicalAnd', 'bool'); - var $b = convertToTensor(b, 'b', 'logicalAnd', 'bool'); - assertAndGetBroadcastShape($a.shape, $b.shape); - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(function (backend) { return backend.logicalAnd($a, $b); }, inputs, null /* grad */, LogicalAnd); - } - var logicalAnd = op({ logicalAnd_: logicalAnd_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the elements, either `a` or `b` depending on the `condition`. - * - * If the condition is true, select from `a`, otherwise select from `b`. - * - * ```js - * const cond = tf.tensor1d([false, false, true], 'bool'); - * const a = tf.tensor1d([1 , 2, 3]); - * const b = tf.tensor1d([-1, -2, -3]); - * - * a.where(cond, b).print(); - * ``` - * - * @param condition The input condition. Must be of dtype bool. - * @param a If `condition` is rank 1, `a` may have a higher rank but - * its first dimension must match the size of `condition`. - * @param b A tensor with the same dtype as `a` and with shape that is - * compatible with `a`. - * @return A tensor with same dtype as `a` and `b`, and shape that is - * broadcastable from `a` and `b`. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function where_(condition, a, b) { - var $a = convertToTensor(a, 'a', 'where'); - var $b = convertToTensor(b, 'b', 'where'); - var $condition = convertToTensor(condition, 'condition', 'where', 'bool'); - // TODO: move this logic to forward function when the broadcastTo op is - // implemented in WASM. - // Find the broadcastable shape for $a and $b. - var broadcastShape = assertAndGetBroadcastShape($a.shape, $b.shape); - var $broadcastedA = $a.broadcastTo(broadcastShape); - var $broadcastedB = $b.broadcastTo(broadcastShape); - if ($condition.rank === 1) { - // If condition rank is 1, then the first dimension must match the size of - // condition. - assert($condition.shape[0] === $a.shape[0], function () { return 'The first dimension of `a` must match the size of `condition`.'; }); - } - if ($condition.rank !== 1) { - // A must have the same shape as condition. - assertShapesMatch($condition.shape, $broadcastedB.shape, 'Error in where: '); - } - var forward = function (backend, save) { - var res = backend.select($condition, $broadcastedA, $broadcastedB); - save([$condition]); - return res; - }; - var inputs = { - condition: $condition, - t: $broadcastedA, - e: $broadcastedB - }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, SelectV2); - } - var where = op({ where_: where_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var clipByValueGradConfig = { - kernelName: ClipByValue, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0]; - var _a = attrs, clipValueMin = _a.clipValueMin, clipValueMax = _a.clipValueMax; - return { - x: function () { return where(logicalAnd(greaterEqual(x, clipValueMin), lessEqual(x, clipValueMax)), dy, zerosLike(dy)); }, - }; - } - }; - - /** - * Prepare the split size array. When the input is a number, the axis is evenly - * divided among the split size. When the input contains the negative value, the - * rest of the axis is allocated toward that. - */ - function prepareSplitSize(x, numOrSizeSplits, axis) { - if (axis === void 0) { axis = 0; } - var splitSizes = []; - if (typeof (numOrSizeSplits) === 'number') { - assert(x.shape[axis] % numOrSizeSplits === 0, function () { return 'Number of splits must evenly divide the axis.'; }); - splitSizes = - new Array(numOrSizeSplits).fill(x.shape[axis] / numOrSizeSplits); - } - else { - var numOfNegs = numOrSizeSplits.reduce(function (count, value) { - if (value === -1) { - count += 1; - } - return count; - }, 0); - assert(numOfNegs <= 1, function () { return 'There should be only one negative value in split array.'; }); - var negIndex = numOrSizeSplits.indexOf(-1); - // Allow the number of split array to be -1, which indicates the rest - // of dimension is allocated to that split. - if (negIndex !== -1) { - var total = numOrSizeSplits.reduce(function (a, b) { return b > 0 ? a + b : a; }); - numOrSizeSplits[negIndex] = x.shape[axis] - total; - } - assert(x.shape[axis] === numOrSizeSplits.reduce(function (a, b) { return a + b; }), function () { return 'The sum of sizes must match the size of the axis dimension.'; }); - splitSizes = numOrSizeSplits; - } - return splitSizes; - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Splits a `tf.Tensor` into sub tensors. - * - * If `numOrSizeSplits` is a number, splits `x` along dimension `axis` - * into `numOrSizeSplits` smaller tensors. - * Requires that `numOrSizeSplits` evenly divides `x.shape[axis]`. - * - * If `numOrSizeSplits` is a number array, splits `x` into - * `numOrSizeSplits.length` pieces. The shape of the `i`-th piece has the - * same size as `x` except along dimension `axis` where the size is - * `numOrSizeSplits[i]`. - * - * ```js - * const x = tf.tensor2d([1, 2, 3, 4, 5, 6, 7, 8], [2, 4]); - * const [a, b] = tf.split(x, 2, 1); - * a.print(); - * b.print(); - * - * const [c, d, e] = tf.split(x, [1, 2, 1], 1); - * c.print(); - * d.print(); - * e.print(); - * ``` - * - * @param x The input tensor to split. - * @param numOrSizeSplits Either an integer indicating the number of - * splits along the axis or an array of integers containing the sizes of - * each output tensor along the axis. If a number then it must evenly divide - * `x.shape[axis]`; otherwise the sum of sizes must match `x.shape[axis]`. - * Can contain one -1 indicating that dimension is to be inferred. - * @param axis The dimension along which to split. Defaults to 0 (the first - * dim). - */ - /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ - function split_(x, numOrSizeSplits, axis) { - if (axis === void 0) { axis = 0; } - var $x = convertToTensor(x, 'x', 'split'); - var forward = function (backend, _) { - var $axis = parseAxisParam(axis, $x.shape)[0]; - var splitSizes = prepareSplitSize($x, numOrSizeSplits, $axis); - return backend.split($x, splitSizes, $axis); - }; - var inputs = { x: $x }; - var attr = { numOrSizeSplits: numOrSizeSplits, axis: axis }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, SplitV, attr); - } - var split = op({ split_: split_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var concatGradConfig = { - kernelName: Concat, - saveAllInputs: true, - gradFunc: function (dy, saved, attrs) { - var shapes = saved.map(function (t) { return t.shape; }); - var axis = attrs.axis; - var $axis = parseAxisParam(axis, saved[0].shape)[0]; - var sizeSplits = shapes.map(function (s) { return s[$axis]; }); - var derTensors = split(dy, sizeSplits, $axis); - return derTensors.map(function (t) { return function () { return t; }; }); - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the derivative of the filter of a 2D convolution. - * - * @param x The input tensor, of rank 4 or rank 3 of shape - * [batch, height, width, inChannels]. If rank 3, batch of 1 is assumed. - * @param dy The dy image, of rank 4 or rank 3, of shape - * [batch, height, width, outDepth]. If rank 3, batch of 1 is assumed. - * @param filterShape The shape of the filter, length 4, - * [filterHeight, filterWidth, inDepth, outDepth]. - * @param strides The strides of the convolution: [strideHeight, - * strideWidth]. - * @param pad A string from: 'same', 'valid'. The type of padding algorithm - * used in the forward prop of the op. - * @param dataFormat: An optional string from: "NHWC", "NCHW". Defaults to - * "NHWC". Specify the data format of the input and output data. With the - * default format "NHWC", the data is stored in the order of: [batch, - * height, width, channels]. - * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The - * rounding mode used when computing output dimensions if pad is a - * number. If none is provided, it will not round and error if the output - * is of fractional size. - */ - function conv2DBackpropFilter_(x, dy, filterShape, strides, pad, dataFormat, dimRoundingMode) { - if (dataFormat === void 0) { dataFormat = 'NHWC'; } - var x4D = x; - if (x.rank === 3) { - x4D = reshape(x, [1, x.shape[0], x.shape[1], x.shape[2]]); - } - var dy4D = dy; - if (dy4D.rank === 3) { - dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); - } - assert(x4D.rank === 4, function () { return "Error in conv2dDerFilter: input must be rank 4, but got shape " + - (x4D.shape + "."); }); - assert(dy4D.rank === 4, function () { return "Error in conv2dDerFilter: dy must be rank 4, but got shape " + - (dy4D.shape + "."); }); - assert(filterShape.length === 4, function () { return "Error in conv2dDerFilter: filterShape must be length 4, but got " + - (filterShape + "."); }); - var inDepth = dataFormat === 'NHWC' ? x4D.shape[3] : x4D.shape[1]; - var outDepth = dataFormat === 'NHWC' ? dy4D.shape[3] : dy4D.shape[1]; - assert(inDepth === filterShape[2], function () { return "Error in conv2dDerFilter: depth of input " + inDepth + ") must " + - ("match input depth in filter (" + filterShape[2] + "."); }); - assert(outDepth === filterShape[3], function () { return "Error in conv2dDerFilter: depth of dy (" + outDepth + ") must " + - ("match output depth for filter (" + filterShape[3] + ")."); }); - if (dimRoundingMode != null) { - assert(isInt(pad), function () { return "Error in conv2dDerFilter: pad must be an integer when using, " + - ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); - } - var forward = function (backend) { - var dilations = 1; - var $dataFormat = convertConv2DDataFormat(dataFormat); - var convInfo = computeConv2DInfo(x4D.shape, filterShape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); - return backend.conv2dDerFilter(x4D, dy4D, convInfo); - }; - var inputs = { x: x4D, dy: dy4D }; - var attrs = { strides: strides, pad: pad, dataFormat: dataFormat, dimRoundingMode: dimRoundingMode }; - return ENGINE.runKernelFunc(forward, inputs, null, Conv2DBackpropFilter, attrs); - } - var conv2DBackpropFilter = op({ conv2DBackpropFilter_: conv2DBackpropFilter_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the derivative of the input of a 2D convolution. - * - * @param xShape The shape of the input: [batch, height, width, inDepth]. - * If length of 3, batch of 1 is assumed. - * @param dy The derivative of the output, of rank 4 or rank 3 of shape - * `[batch, outHeight, outWidth, outDepth]`. If rank 3, batch of 1 is - * assumed. - * @param filter The filter, rank 4, of shape - * `[filterHeight, filterWidth, inDepth, outDepth]`. - * @param strides The strides of the convolution: `[strideHeight, - * strideWidth]`. - * @param pad The type of padding algorithm used: - * - `same` and stride 1: output will be of same size as input, - * regardless of filter size. - * - `valid`: output will be smaller than input if filter is larger - * than 1x1. - * @param dataFormat: An optional string from: "NHWC", "NCHW". Defaults to - * "NHWC". Specify the data format of the input and output data. With the - * default format "NHWC", the data is stored in the order of: [batch, - * height, width, channels]. - * @param dimRoundingMode The rounding mode used when computing output - * dimensions if pad is a number. If none is provided, it will not round - * and error if the output is of fractional size. - */ - function conv2DBackpropInput_(xShape, dy, filter, strides, pad, dataFormat, dimRoundingMode) { - if (dataFormat === void 0) { dataFormat = 'NHWC'; } - assert(xShape.length === dy.rank, function () { return "Length of inShape " + - ("(" + xShape.length + ") and rank of dy (" + dy.rank + ") must match"); }); - var xShape4D = xShape; - var dy4D = dy; - var reshapedTo4D = false; - if (dy.rank === 3) { - reshapedTo4D = true; - dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); - xShape4D = [1, xShape[0], xShape[1], xShape[2]]; - } - assert(xShape4D.length === 4, function () { - return "Error in conv2dDerInput: inShape must be length 4, but got length " + - (xShape4D.length + "."); - }); - assert(dy4D.rank === 4, function () { return "Error in conv2dDerInput: dy must be rank 4, but got " + - ("rank " + dy4D.rank); }); - assert(filter.rank === 4, function () { return "Error in conv2dDerInput: filter must be rank 4, but got " + - ("rank " + filter.rank); }); - var inDepth = dataFormat === 'NHWC' ? xShape4D[3] : xShape4D[1]; - var outDepth = dataFormat === 'NHWC' ? dy4D.shape[3] : dy4D.shape[1]; - assert(inDepth === filter.shape[2], function () { return "Error in conv2dDerInput: depth of input (" + inDepth + ") must " + - ("match input depth for filter " + filter.shape[2] + "."); }); - assert(outDepth === filter.shape[3], function () { return "Error in conv2dDerInput: depth of output (" + outDepth + ") must " + - ("match output depth for filter " + filter.shape[3] + "."); }); - if (dimRoundingMode != null) { - assert(isInt(pad), function () { return "Error in conv2dDerInput: pad must be an integer when using, " + - ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); - } - var forward = function (backend, save) { - var dilations = 1; - var $dataFormat = convertConv2DDataFormat(dataFormat); - var convInfo = computeConv2DInfo(xShape4D, filter.shape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); - var res = backend.conv2dDerInput(dy4D, filter, convInfo); - save([dy4D, filter]); - return res; - }; - var inputs = { dy: dy4D, filter: filter }; - var attrs = { strides: strides, pad: pad, dataFormat: dataFormat, dimRoundingMode: dimRoundingMode, inputShape: xShape4D }; - var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, Conv2DBackpropInput, attrs); - if (reshapedTo4D) { - return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); - } - return res; - } - var conv2DBackpropInput = op({ conv2DBackpropInput_: conv2DBackpropInput_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var conv2DGradConfig = { - kernelName: Conv2D, - inputsToSave: ['x', 'filter'], - gradFunc: function (dy, saved, attrs) { - var _a = saved, x4D = _a[0], $filter = _a[1]; - var _b = attrs, dilations = _b.dilations, strides = _b.strides, pad = _b.pad, dataFormat = _b.dataFormat; - assert(tupleValuesAreOne(dilations), function () { return 'Error in gradient of conv2D: dilation rates greater than 1 ' + - ("are not yet supported in gradients. Got dilations '" + dilations + "'"); }); - return { - x: function () { - return conv2DBackpropInput(x4D.shape, dy, $filter, strides, pad, dataFormat); - }, - filter: function () { - return conv2DBackpropFilter(x4D, dy, $filter.shape, strides, pad, dataFormat); - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes a 2D convolution over the input x. - * - * @param x The input tensor, of rank 4 or rank 3, of shape - * `[batch, height, width, inChannels]`. If rank 3, batch of 1 is - * assumed. - * @param filter The filter, rank 4, of shape - * `[filterHeight, filterWidth, inDepth, outDepth]`. - * @param strides The strides of the convolution: `[strideHeight, - * strideWidth]`. - * @param pad The type of padding algorithm. - * - `same` and stride 1: output will be of same size as input, - * regardless of filter size. - * - `valid`: output will be smaller than input if filter is larger - * than 1x1. - * - For more info, see this guide: - * [https://www.tensorflow.org/api_guides/python/nn#Convolution]( - * https://www.tensorflow.org/api_guides/python/nn#Convolution) - * @param dataFormat: An optional string from: "NHWC", "NCHW". Defaults to - * "NHWC". Specify the data format of the input and output data. With the - * default format "NHWC", the data is stored in the order of: [batch, - * height, width, channels]. - * @param dilations The dilation rates: `[dilationHeight, dilationWidth]` - * in which we sample input values across the height and width dimensions - * in atrous convolution. Defaults to `[1, 1]`. If `dilations` is a single - * number, then `dilationHeight == dilationWidth`. If it is greater than - * 1, then all values of `strides` must be 1. - * @param dimRoundingMode The rounding mode used when computing output - * dimensions if pad is a number. If none is provided, it will not round - * and error if the output is of fractional size. - */ - /** @doc {heading: 'Operations', subheading: 'Convolution'} */ - function conv2d_(x, filter, strides, pad, dataFormat, dilations, dimRoundingMode) { - if (dataFormat === void 0) { dataFormat = 'NHWC'; } - if (dilations === void 0) { dilations = [1, 1]; } - var $x = convertToTensor(x, 'x', 'conv2d'); - var $filter = convertToTensor(filter, 'filter', 'conv2d'); - var x4D = $x; - var reshapedTo4D = false; - if ($x.rank === 3) { - reshapedTo4D = true; - x4D = reshape($x, [1, $x.shape[0], $x.shape[1], $x.shape[2]]); - } - assert(x4D.rank === 4, function () { return "Error in conv2d: input must be rank 4, but got rank " + x4D.rank + "."; }); - assert($filter.rank === 4, function () { return "Error in conv2d: filter must be rank 4, but got rank " + - ($filter.rank + "."); }); - if (dimRoundingMode != null) { - assert(isInt(pad), function () { return "Error in conv2d: pad must be an integer when using, " + - ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); - } - var inDepth = dataFormat === 'NHWC' ? x4D.shape[3] : x4D.shape[1]; - assert(inDepth === $filter.shape[2], function () { return "Error in conv2d: depth of input (" + inDepth + ") must match " + - ("input depth for filter " + $filter.shape[2] + "."); }); - assert(eitherStridesOrDilationsAreOne(strides, dilations), function () { return 'Error in conv2D: Either strides or dilations must be 1. ' + - ("Got strides " + strides + " and dilations '" + dilations + "'"); }); - var forward = function (backend, save) { - var $dataFormat = convertConv2DDataFormat(dataFormat); - var convInfo = computeConv2DInfo(x4D.shape, $filter.shape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); - var res = backend.conv2d(x4D, $filter, convInfo); - save([x4D, $filter]); - return res; - }; - var inputs = { x: x4D, filter: $filter }; - var attrs = { strides: strides, pad: pad, dataFormat: dataFormat, dilations: dilations, dimRoundingMode: dimRoundingMode }; - var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, Conv2D, attrs); - if (reshapedTo4D) { - return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); - } - return res; - } - var conv2d = op({ conv2d_: conv2d_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var conv2DBackpropInputGradConfig = { - kernelName: Conv2DBackpropInput, - inputsToSave: ['dy', 'filter'], - gradFunc: function (ddx, saved, attrs) { - var _a = saved, dy = _a[0], filter = _a[1]; - var _b = attrs, strides = _b.strides, pad = _b.pad, dataFormat = _b.dataFormat, dimRoundingMode = _b.dimRoundingMode; - return { - dy: function () { return conv2d(ddx, filter, strides, pad, dataFormat, 1 /* dilations */, dimRoundingMode); }, - filter: function () { return conv2DBackpropFilter(ddx, dy, filter.shape, strides, pad, dataFormat, dimRoundingMode); } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the derivative of the filter of a 3D convolution. - * - * @param x The input tensor, of rank 5 or rank 4 of shape - * [batch, depth, height, width, inChannels]. If rank 4, batch of 1 is - * assumed. - * @param dy The dy image, of rank 5 or rank 4, of shape - * [batch, depth, height, width, outDepth]. If rank 4, batch of 1 is - * assumed. - * @param filterShape The shape of the filter, length 5, - * [filterDepth, filterHeight, filterWidth, inDepth, outDepth]. - * @param strides The strides of the convolution: [strideDepth, strideHeight, - * strideWidth]. - * @param pad A string from: 'same', 'valid'. The type of padding algorithm - * used in the forward prop of the op. - */ - function conv3DBackpropFilter_(x, dy, filterShape, strides, pad) { - var x5D = x; - if (x.rank === 4) { - x5D = reshape(x, [1, x.shape[0], x.shape[1], x.shape[2], x.shape[3]]); - } - var dy5D = dy; - if (dy5D.rank === 4) { - dy5D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2], dy.shape[3]]); - } - assert(x5D.rank === 5, function () { return "Error in conv3dDerFilter: input must be rank 5, but got shape " + - (x5D.shape + "."); }); - assert(dy5D.rank === 5, function () { return "Error in conv3dDerFilter: dy must be rank 5, but got shape " + - (dy5D.shape + "."); }); - assert(filterShape.length === 5, function () { return "Error in conv3dDerFilter: filterShape must be length 5, but got " + - (filterShape + "."); }); - assert(x5D.shape[4] === filterShape[3], function () { return "Error in conv3dDerFilter: depth of input " + x5D.shape[4] + ") must " + - ("match input depth in filter (" + filterShape[3] + "."); }); - assert(dy5D.shape[4] === filterShape[4], function () { return "Error in conv3dDerFilter: depth of dy (" + dy5D.shape[4] + ") must " + - ("match output depth for filter (" + filterShape[4] + ")."); }); - var forward = function (backend) { - var dilations = 1; - var convInfo = computeConv3DInfo(x5D.shape, filterShape, strides, dilations, pad); - return backend.conv3dDerFilter(x5D, dy5D, convInfo); - }; - var inputs = { x: x5D, y: dy5D }; - var attrs = { strides: strides, pad: pad }; - return ENGINE.runKernelFunc(forward, inputs, null, Conv3DBackpropFilterV2, attrs); - } - var conv3DBackpropFilter = op({ conv3DBackpropFilter_: conv3DBackpropFilter_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the derivative of the input of a 3D convolution. - * - * @param xShape The shape of the input: [batch, depth, height, width, - * in_channels]. If length of 4, batch of 1 is assumed. - * @param dy The derivative of the output, of rank 5 or rank 4 of shape - * `[batch, outDepth, outHeight, outWidth, in_channels]`. - * If rank 4, batch of 1 is assumed. - * @param filter The filter, rank 5, of shape - * `[filterDepth, filterHeight, filterWidth, inDepth, outDepth]`. - * @param strides The strides of the convolution: `[strideDepth, strideHeight, - * strideWidth]`. - * @param pad The type of padding algorithm used: - * - `same` and stride 1: output will be of same size as input, - * regardless of filter size. - * - `valid`: output will be smaller than input if filter is larger - * than 1x1. - */ - function conv3DBackpropInput_(xShape, dy, filter, strides, pad) { - assert(xShape.length === dy.rank, function () { return "Length of inShape " + - ("(" + xShape.length + ") and rank of dy (" + dy.rank + ") must match"); }); - var xShape5D = xShape; - var dy5D = dy; - var reshapedTo5D = false; - if (dy.rank === 4) { - reshapedTo5D = true; - dy5D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2], dy.shape[3]]); - xShape5D = [1, xShape[0], xShape[1], xShape[2], xShape[3]]; - } - var inDepth = xShape5D[4]; - var outDepth = dy5D.shape[4]; - assert(xShape5D.length === 5, function () { - return "Error in conv3dDerInput: inShape must be length 5, but got length " + - (xShape5D.length + "."); - }); - assert(dy5D.rank === 5, function () { return "Error in conv3dDerInput: dy must be rank 5, but got " + - ("rank " + dy5D.rank); }); - assert(filter.rank === 5, function () { return "Error in conv3dDerInput: filter must be rank 5, but got " + - ("rank " + filter.rank); }); - assert(inDepth === filter.shape[3], function () { return "Error in conv3dDerInput: depth of input (" + inDepth + ") must " + - ("match input depth for filter " + filter.shape[3] + "."); }); - assert(outDepth === filter.shape[4], function () { return "Error in conv3dDerInput: depth of output (" + outDepth + ") must " + - ("match output depth for filter " + filter.shape[4] + "."); }); - var forward = function (backend) { - var dilations = 1; - var convInfo = computeConv3DInfo(xShape5D, filter.shape, strides, dilations, pad); - return backend.conv3dDerInput(dy5D, filter, convInfo); - }; - var inputs = { dy: dy5D }; - var attrs = { pad: pad }; - var res = ENGINE.runKernelFunc(forward, inputs, null, Conv3DBackpropInputV2, attrs); - if (reshapedTo5D) { - return reshape(res, [res.shape[1], res.shape[2], res.shape[3], res.shape[4]]); - } - return res; - } - var conv3DBackpropInput = op({ conv3DBackpropInput_: conv3DBackpropInput_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var conv3DGradConfig = { - kernelName: Conv3D, - inputsToSave: ['x', 'filter'], - gradFunc: function (dy, saved, attrs) { - var _a = attrs, dilations = _a.dilations, strides = _a.strides, pad = _a.pad; - assert(tupleValuesAreOne(dilations), function () { - return 'Error in gradient of conv3D: dilation rates greater than 1 are ' + - ("not yet supported in gradients. Got dilations '" + dilations + "'"); - }); - var x5D = saved[0], $filter = saved[1]; - return { - x: function () { return conv3DBackpropInput(x5D.shape, dy, $filter, strides, pad); }, - filter: function () { return conv3DBackpropFilter(x5D, dy, $filter.shape, strides, pad); } - }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes sin of the input Tensor element-wise: `sin(x)` - * - * ```js - * const x = tf.tensor1d([0, Math.PI / 2, Math.PI * 3 / 4]); - * - * x.sin().print(); // or tf.sin(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function sin_(x) { - var $x = convertToTensor(x, 'x', 'sin'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.sin($x); - save([$x]); - return res; - }, inputs, null /* grad */, Sin); - } - var sin = op({ sin_: sin_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var cosGradConfig = { - kernelName: Cos, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(neg(sin(cast(x, 'float32'))), dy); } }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes hyperbolic sin of the input `tf.Tensor` element-wise: `sinh(x)` - * - * ```js - * const x = tf.tensor1d([0, 1, -1, .7]); - * - * x.sinh().print(); // or tf.sinh(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function sinh_(x) { - var $x = convertToTensor(x, 'x', 'sinh'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.sinh($x); - save([$x]); - return res; - }, inputs, null /* grad */, Sinh); - } - var sinh = op({ sinh_: sinh_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var coshGradConfig = { - kernelName: Cosh, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(sinh(cast(x, 'float32')), dy); } }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Transposes the `tf.Tensor`. Permutes the dimensions according to `perm`. - * - * The returned `tf.Tensor`'s dimension `i` will correspond to the input - * dimension `perm[i]`. If `perm` is not given, it is set to `[n-1...0]`, - * where `n` is the rank of the input `tf.Tensor`. Hence by default, this - * operation performs a regular matrix transpose on 2-D input `tf.Tensor`s. - * - * ```js - * const a = tf.tensor2d([1, 2, 3, 4, 5, 6], [2, 3]); - * - * a.transpose().print(); // or tf.transpose(a) - * ``` - * - * @param x The tensor to transpose. - * @param perm The permutation of the dimensions of a. - */ - /** @doc {heading: 'Operations', subheading: 'Matrices'} */ - function transpose_(x, perm) { - var $x = convertToTensor(x, 'x', 'transpose'); - if (perm == null) { - perm = $x.shape.map(function (s, i) { return i; }).reverse(); - } - assert($x.rank === perm.length, function () { return "Error in transpose: rank of input " + $x.rank + " " + - ("must match length of perm " + perm + "."); }); - perm.forEach(function (axis) { - assert(axis >= 0 && axis < $x.rank, function () { return "All entries in 'perm' must be between 0 and " + ($x.rank - 1) + - (" but got " + perm); }); - }); - if ($x.rank <= 1) { - return $x.clone(); - } - var inputs = { x: $x }; - var attrs = { perm: perm }; - return ENGINE.runKernelFunc(function (backend) { return backend.transpose($x, perm); }, inputs, null /* gradient */, Transpose, attrs); - } - var transpose = op({ transpose_: transpose_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the cumulative sum of a `tf.Tensor` along `axis`. - * - * ```js - * const x = tf.tensor([1, 2, 3, 4]); - * x.cumsum().print(); - * ``` - * ```js - * const x = tf.tensor([[1, 2], [3, 4]]); - * x.cumsum().print(); - * ``` - * - * @param x The input tensor to be summed. - * @param axis The axis along which to sum. Optional. Defaults to 0. - * @param exclusive Whether to perform exclusive cumulative sum. Optional. - * Defaults to false. If set to true then the sum of each tensor entry - * does not include its own value, but only the values previous to it - * along the specified axis. - * @param reverse Whether to sum in the opposite direction. Optional. - * Defaults to false. - */ - /** @doc {heading: 'Operations', subheading: 'Scan'} */ - function cumsum_(x, axis, exclusive, reverse) { - if (axis === void 0) { axis = 0; } - if (exclusive === void 0) { exclusive = false; } - if (reverse === void 0) { reverse = false; } - var $x = convertToTensor(x, 'x', 'cumsum'); - var forward = function (backend, save) { - var permutation = getAxesPermutation([axis], $x.rank); - var permutedX = $x; - if (permutation != null) { - permutedX = transpose($x, permutation); - } - var permutedAxis = getInnerMostAxes(1, $x.rank)[0]; - var value = backend.cumsum(permutedX, permutedAxis, exclusive, reverse); - save([$x]); - if (permutation != null) { - var reversePermutation = getUndoAxesPermutation(permutation); - value = transpose(value, reversePermutation); - } - return value; - }; - var inputs = { x: $x }; - var attrs = { axis: axis, exclusive: exclusive, reverse: reverse }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Cumsum, attrs); - } - var cumsum = op({ cumsum_: cumsum_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var cumsumGradConfig = { - kernelName: Cumsum, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0]; - var _a = attrs, axis = _a.axis, exclusive = _a.exclusive, reverse = _a.reverse; - return { - x: function () { - var permutation = getAxesPermutation([axis], x.rank); - var out = cumsum(dy, axis, exclusive, !reverse); - if (permutation != null) { - out = transpose(out, permutation); - } - return out; - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function depthwiseConv2dNativeBackpropFilter_(x, dy, filterShape, convInfo) { - var x4D = x; - if (x.rank === 3) { - x4D = reshape(x, [1, x.shape[0], x.shape[1], x.shape[2]]); - } - var dy4D = dy; - if (dy4D.rank === 3) { - dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); - } - var forward = function (backend) { - return backend.depthwiseConv2DDerFilter(x4D, dy4D, convInfo); - }; - var inputs = { x: x4D, dy: dy4D }; - return ENGINE.runKernelFunc(forward, inputs, null, DepthwiseConv2dNativeBackpropFilter); - } - var depthwiseConv2dNativeBackpropFilter = op({ depthwiseConv2dNativeBackpropFilter_: depthwiseConv2dNativeBackpropFilter_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function depthwiseConv2dNativeBackpropInput_(xShape, dy, filter, convInfo) { - var dy4D = dy; - var reshapedTo4D = false; - if (dy.rank === 3) { - reshapedTo4D = true; - dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); - } - var forward = function (backend) { - return backend.depthwiseConv2DDerInput(dy4D, filter, convInfo); - }; - var inputs = { dy: dy4D }; - var res = ENGINE.runKernelFunc(forward, inputs, null, DepthwiseConv2dNativeBackpropInput); - if (reshapedTo4D) { - return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); - } - return res; - } - var depthwiseConv2dNativeBackpropInput = op({ depthwiseConv2dNativeBackpropInput_: depthwiseConv2dNativeBackpropInput_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var depthwiseConv2dNativeGradConfig = { - kernelName: DepthwiseConv2dNative, - inputsToSave: ['x', 'filter'], - gradFunc: function (dy, saved, attrs) { - var _a = attrs, dilations = _a.dilations, strides = _a.strides, pad = _a.pad, dimRoundingMode = _a.dimRoundingMode; - var $dilations = dilations == null ? [1, 1] : dilations; - assert(tupleValuesAreOne($dilations), function () { return 'Error in gradient of depthwiseConv2dNative: dilation rates ' + - "greater than 1 are not yet supported. Got dilations " + - ("'" + $dilations + "'"); }); - var _b = saved, x = _b[0], filter = _b[1]; - assert(x.rank === 4, function () { return "Error in gradient of depthwiseConv2dNative: input must be " + - ("rank 4, but got rank " + x.rank + "."); }); - assert(filter.rank === 4, function () { return "Error in gradient of depthwiseConv2dNative: filter must be " + - ("rank 4, but got rank " + filter.rank + "."); }); - assert(x.shape[3] === filter.shape[2], function () { return "Error in gradient of depthwiseConv2d: number of input " + - ("channels (" + x.shape[3] + ") must match the inChannels dimension ") + - ("in filter " + filter.shape[2] + "."); }); - assert(eitherStridesOrDilationsAreOne(strides, $dilations), function () { return 'Error in gradient of depthwiseConv2d: Either strides or ' + - ("dilations must be 1. Got strides " + strides + " and dilations ") + - ("'" + $dilations + "'."); }); - if (dimRoundingMode != null) { - assert(isInt(pad), function () { - return "Error in depthwiseConv2d: pad must be an integer when using, " + - ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); - }); - } - var convInfo = computeConv2DInfo(x.shape, filter.shape, strides, $dilations, pad, dimRoundingMode, true /* depthwise */); - return { - x: function () { - return depthwiseConv2dNativeBackpropInput(x.shape, dy, filter, convInfo); - }, - filter: function () { - return depthwiseConv2dNativeBackpropFilter(x, dy, filter.shape, convInfo); - }, - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var dilation2dGradConfig = { - kernelName: Dilation2D, - inputsToSave: ['x', 'filter'], - gradFunc: function (dy, saved, attrs) { - var _a = saved, x = _a[0], filter = _a[1]; - var inputInputs = { x: x, filter: filter, dy: dy }; - var filterInputs = { x: x, filter: filter, dy: dy }; - return { - x: function () { return ENGINE.runKernel(Dilation2DBackpropInput, inputInputs, attrs); }, - filter: function () { return ENGINE.runKernel(Dilation2DBackpropFilter, filterInputs, attrs); } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var divGradConfig = { - kernelName: Div, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var outShape = assertAndGetBroadcastShape(a.shape, b.shape); - var derA = function () { - var res = div(dy, b.toFloat()); - var reduceAxes = getReductionAxes(a.shape, outShape); - if (reduceAxes.length > 0) { - return sum$1(res, reduceAxes).reshape(a.shape); - } - return res; - }; - var derB = function () { - var res = mul(dy, a.toFloat()); - var reduceAxes = getReductionAxes(b.shape, outShape); - if (reduceAxes.length > 0) { - res = reshape(sum$1(res, reduceAxes), b.shape); - } - var tmp = square(b); - return neg(div(res, tmp.toFloat())); - }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var eluGradConfig = { - kernelName: Elu, - outputsToSave: [true], - gradFunc: function (dy, saved) { - var y = saved[0]; - var backPropKernelFunc = function (backend) { - return backend.eluDer(dy, y); - }; - var inputs = { dy: dy, y: y }; - return { - x: function () { return ENGINE.runKernelFunc(backPropKernelFunc, inputs, null /* grad */, EluGrad); } - }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes exponential of the input `tf.Tensor` element-wise. `e ^ x` - * - * ```js - * const x = tf.tensor1d([1, 2, -3]); - * - * x.exp().print(); // or tf.exp(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function exp_(x) { - var $x = convertToTensor(x, 'x', 'exp'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.exp($x); - save([res]); - return res; - }, inputs, null /* grad */, Exp); - } - var exp = op({ exp_: exp_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var erfGradConfig = { - kernelName: Erf, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - var a = mul(exp(neg(square(x))), 2 / Math.sqrt(Math.PI)); - return { x: function () { return mul(dy, a); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var expGradConfig = { - kernelName: Exp, - outputsToSave: [true], - gradFunc: function (dy, saved) { - var y = saved[0]; - return { x: function () { return mul(dy, y); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var expm1GradConfig = { - kernelName: Expm1, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(dy, exp(x)); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var floorGradConfig = { - kernelName: Floor, - gradFunc: function (dy) { - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var floorDivGradConfig = { - kernelName: FloorDiv, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var outShape = assertAndGetBroadcastShape(a.shape, b.shape); - var derA = function () { - var res = dy.div(b.toFloat()); - var reduceAxes = getReductionAxes(a.shape, outShape); - if (reduceAxes.length > 0) { - return res.sum(reduceAxes).reshape(a.shape); - } - return res; - }; - var derB = function () { - var res = dy.mul(a.toFloat()); - var reduceAxes = getReductionAxes(b.shape, outShape); - if (reduceAxes.length > 0) { - res = res.sum(reduceAxes).reshape(b.shape); - } - var tmp = b.square(); - return res.div(tmp.toFloat()).neg(); - }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes reciprocal of square root of the input `tf.Tensor` element-wise: - * `y = 1 / sqrt(x)` - * - * ```js - * const x = tf.tensor1d([1, 2, 4, -1]); - * - * x.rsqrt().print(); // or tf.rsqrt(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function rsqrt_(x) { - var $x = convertToTensor(x, 'x', 'rsqrt'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.rsqrt($x); - save([$x]); - return res; - }, inputs, null /* grad */, Rsqrt); - } - var rsqrt = op({ rsqrt_: rsqrt_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Construct a tensor by repeating it the number of times given by reps. - * - * This operation creates a new tensor by replicating `input` `reps` - * times. The output tensor's i'th dimension has `input.shape[i] * - * reps[i]` elements, and the values of `input` are replicated - * `reps[i]` times along the i'th dimension. For example, tiling - * `[a, b, c, d]` by `[2]` produces `[a, b, c, d, a, b, c, d]`. - * - * ```js - * const a = tf.tensor1d([1, 2]); - * - * a.tile([2]).print(); // or a.tile([2]) - * ``` - * - * ```js - * const a = tf.tensor2d([1, 2, 3, 4], [2, 2]); - * - * a.tile([1, 2]).print(); // or a.tile([1, 2]) - * ``` - * @param x The tensor to tile. - * @param reps Determines the number of replications per dimension. - */ - /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ - function tile_(x, reps) { - var parseAs = null; - var $x = convertToTensor(x, 'x', 'tile', parseAs); - assert($x.rank === reps.length, function () { return "Error in transpose: rank of input " + $x.rank + " " + - ("must match length of reps " + reps + "."); }); - var forward = function (backend, save) { - var res = backend.tile($x, reps); - save([$x]); - return res; - }; - var inputsToSave = [$x]; - var inputs = { x: $x }; - var attrs = { reps: reps }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Tile, attrs, inputsToSave); - } - var tile = op({ tile_: tile_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var fusedBatchNormGradConfig = { - kernelName: FusedBatchNorm, - inputsToSave: ['x', 'mean', 'variance', 'scale'], - gradFunc: function (dy, saved, attrs) { - var varianceEpsilon = attrs.varianceEpsilon; - var x = saved[0], mean = saved[1], variance = saved[2], scale = saved[3]; - var scaleValue = scale == null ? scalar(1) : scale; - var reductionAxes = getReductionAxes(mean.shape, x.shape); - var tileShape = []; - if (mean.rank === 1) { - for (var i = 0; i < x.shape.length - 1; ++i) { - tileShape.push(x.shape[i]); - } - tileShape.push(1); - } - var xMinusMean = sub(x, mean); - var dyTimesScaleValue = mul(dy, scaleValue); - var oneOverSqrtVariance = rsqrt(add(variance, scalar(varianceEpsilon))); - var minusHalfRCube = mul(mul(mul(oneOverSqrtVariance, oneOverSqrtVariance), oneOverSqrtVariance), scalar(-0.5)); - var derX = function () { - if (mean.rank === 1) { - return reshape(mul(mul(dy, tile(oneOverSqrtVariance.as4D(1, 1, 1, mean.shape[0]), tileShape)), scaleValue), x.shape); - } - else { - return reshape(mul(mul(dy, oneOverSqrtVariance), scaleValue), x.shape); - } - }; - var derMean = function () { - var meanDer = mul(mul(oneOverSqrtVariance, scalar(-1)), dyTimesScaleValue); - if (mean.rank === 1) { - meanDer = sum$1(meanDer, reductionAxes); - } - return reshape(meanDer, mean.shape); - }; - var derVariance = function () { - var varianceDer = mul(mul(minusHalfRCube, xMinusMean), dyTimesScaleValue); - if (mean.rank === 1) { - varianceDer = sum$1(varianceDer, reductionAxes); - } - return reshape(varianceDer, mean.shape); - }; - var derScale = function () { - var xMinusMean2TimesRsqrt = mul(xMinusMean, oneOverSqrtVariance); - var scaleDer = mul(dy, xMinusMean2TimesRsqrt); - if (mean.rank === 1) { - scaleDer = sum$1(scaleDer, reductionAxes); - } - return reshape(scaleDer, mean.shape); - }; - var derOffset = function () { - var offsetDer = dy; - if (mean.rank === 1) { - offsetDer = sum$1(offsetDer, reductionAxes); - } - return reshape(offsetDer, mean.shape); - }; - return { - x: derX, - mean: derMean, - variance: derVariance, - scale: derScale, - offset: derOffset - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the sum along segments of a `tf.Tensor`. - * - * ```js - * const x = tf.tensor1d([1, 2, 3, 4]); - * const segmentIds = tf.tensor1d([1, 2, 0, 1], 'int32'); - * const numSegments = 3; - * - * x.unsortedSegmentSum(segmentIds, numSegments).print() - * //or tf.unsortedSegmentSum(x, segmentIds, numSegments) - * ``` - * @param x The `tf.Tensor` that will be summed along its segments. - * @param segmentIds A `tf.Tensor1D` whose rank is equal to the rank of `x`'s - * dimension along the `axis`. Maps each element of `x` to a segment. - * @param numSegments The number of distinct `segmentIds`. - */ - /** @doc {heading: 'Operations', subheading: 'Segment'} */ - function unsortedSegmentSum_(x, segmentIds, numSegments) { - var $x = convertToTensor(x, 'x', 'unsortedSegmentSum'); - var $segmentIds = convertToTensor(segmentIds, 'segmentIds', 'unsortedSegmentSum', 'int32'); - assert(isInt(numSegments), function () { return 'numSegments must be of dtype int'; }); - var inputs = { x: $x, segmentIds: $segmentIds }; - var attrs = { numSegments: numSegments }; - var forward = function (backend, save) { - var res = backend.unsortedSegmentSum($x, $segmentIds, numSegments); - save([$segmentIds]); - return res; - }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, UnsortedSegmentSum, attrs); - } - var unsortedSegmentSum = op({ unsortedSegmentSum_: unsortedSegmentSum_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var gatherGradConfig = { - kernelName: GatherV2, - inputsToSave: ['x', 'indices'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0], indices = saved[1]; - var axis = attrs.axis; - var parsedAxis = parseAxisParam(axis, x.shape)[0]; - var derX = function () { - var paramsShape = x.shape; - var indicesSize = indices.size; - var outerShape = paramsShape.slice(0, parsedAxis); - var outerDims = outerShape.length; - var innerShape = paramsShape.slice(axis, paramsShape.length).slice(1); - var innerDims = innerShape.length; - var outerAxesIndices = arrayRange(0, outerDims); - var innerAxesIndices = arrayRange(outerDims + 1, outerDims + 1 + innerDims); - var valuesShape = arrayConcat([outerShape, [indicesSize], innerShape]); - var values = reshape(dy, valuesShape); - var reshapedIndices = reshape(indices, [indicesSize]); - var transposeDims = arrayConcat([[outerDims], outerAxesIndices, innerAxesIndices]); - var valuesTranspose = transpose(values, transposeDims); - var paramsGrad = unsortedSegmentSum(valuesTranspose, reshapedIndices, x.shape[parsedAxis]); - var invertTransposeDims = getUndoAxesPermutation(transposeDims); - paramsGrad = transpose(paramsGrad, invertTransposeDims); - return paramsGrad; - }; - return { x: derX, indices: function () { return indices; } }; - } - }; - function arrayRange(start, stop) { - var result = []; - for (var i = start; i < stop; ++i) { - result.push(i); - } - return result; - } - function arrayConcat(arrays) { - var result = []; - for (var i = 0; i < arrays.length; ++i) { - for (var j = 0; j < arrays[i].length; ++j) { - result.push(arrays[i][j]); - } - } - return result; - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var greaterEqualGradConfig = { - kernelName: GreaterEqual, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - return { a: function () { return zerosLike(a); }, b: function () { return zerosLike(b); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var identityGradConfig = { - kernelName: Identity, - gradFunc: function (dy) { - return { x: function () { return dy.toFloat(); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var isFiniteGradConfig = { - kernelName: IsFinite, - gradFunc: function (dy) { - // TODO(nsthorat): Let gradients be null for cases where we want to stop - // backpropgation. - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var isInfGradConfig = { - kernelName: IsInf, - gradFunc: function (dy) { - // TODO(nsthorat): Let gradients be null for cases where we want to stop - // backpropgation. - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var isNanGradConfig = { - kernelName: IsNan, - gradFunc: function (dy) { - // TODO(nsthorat): Let gradients be null for cases where we want to stop - // backpropgation. - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var log1pGradConfig = { - kernelName: Log1p, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, add(x, 1)); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var logGradConfig = { - kernelName: Log, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, cast(x, 'float32')); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var logSoftmaxGradConfig = { - kernelName: LogSoftmax, - inputsToSave: [], - outputsToSave: [true], - gradFunc: function (dy, saved, attrs) { - var value = saved[0]; - var axis = attrs.axis; - return { - logits: function () { - var keepDims = true; - var softmax = value.exp(); - return dy.sub(dy.sum(axis, keepDims).mul(softmax)); - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function localResponseNormalizationBackprop_(x, y, dy, depthRadius, bias, alpha, beta) { - if (depthRadius === void 0) { depthRadius = 5; } - if (bias === void 0) { bias = 1; } - if (alpha === void 0) { alpha = 1; } - if (beta === void 0) { beta = 0.5; } - var forward = function (backend) { - return backend.LRNGrad(dy, x, y, depthRadius, bias, alpha, beta); - }; - var inputs = { x: x, y: y, dy: dy }; - var attrs = { depthRadius: depthRadius, bias: bias, alpha: alpha, beta: beta }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, LRNBackprop, attrs); - } - var localResponseNormalizationBackprop = op({ localResponseNormalizationBackprop_: localResponseNormalizationBackprop_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var lrnGradConfig = { - kernelName: LRN, - inputsToSave: ['x'], - outputsToSave: [true], - gradFunc: function (dy, saved, attrs) { - var _a = saved, x = _a[0], y = _a[1]; - var _b = attrs, depthRadius = _b.depthRadius, bias = _b.bias, alpha = _b.alpha, beta = _b.beta; - return { - x: function () { return localResponseNormalizationBackprop(x, y, dy, depthRadius, bias, alpha, beta); } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the truth value of (a == b) element-wise. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([1, 2, 3]); - * const b = tf.tensor1d([2, 2, 2]); - * - * a.equal(b).print(); - * ``` - * - * @param a The first input tensor. - * @param b The second input tensor. Must have the same dtype as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function equal_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'equal'); - var $b = convertToTensor(b, 'b', 'equal'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - assertAndGetBroadcastShape($a.shape, $b.shape); - var forward = function (backend) { return backend.equal($a, $b); }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null, Equal); - } - var equal = op({ equal_: equal_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Gradient helper function for the min and max operations. - */ - function gradForMinAndMax(dy, y, xOrig, origAxes, permutedAxes) { - if (y.rank < xOrig.rank) { - y = reshape(y, expandShapeToKeepDim(y.shape, origAxes)); - } - if (dy.rank < xOrig.rank) { - dy = reshape(dy, expandShapeToKeepDim(dy.shape, origAxes)); - } - return { - x: function () { - var dx = mul(dy, cast(equal(xOrig, y), dy.dtype)); - return permutedAxes == null ? dx : transpose(dx, permutedAxes); - } - }; - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var maxGradConfig = { - kernelName: Max, - inputsToSave: ['x'], - outputsToSave: [true], - gradFunc: function (dy, saved, attrs) { - var maxAttrs = attrs; - var reductionIndices = maxAttrs.reductionIndices; - var x = saved[0], y = saved[1]; - var origAxes = parseAxisParam(reductionIndices, x.shape); - var permutedAxes = getAxesPermutation(origAxes, x.rank); - var maxGrad = gradForMinAndMax(dy, y, x, origAxes, permutedAxes); - return { - x: function () { - var out = maxGrad['x'](); - if (permutedAxes != null) { - out = transpose(out); - } - return out; - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the truth value of (a < b) element-wise. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([1, 2, 3]); - * const b = tf.tensor1d([2, 2, 2]); - * - * a.less(b).print(); - * ``` - * @param a The first input tensor. - * @param b The second input tensor. Must have the same dtype as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function less_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'less'); - var $b = convertToTensor(b, 'b', 'less'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - assertAndGetBroadcastShape($a.shape, $b.shape); - var forward = function (backend) { return backend.less($a, $b); }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Less); - } - var less = op({ less_: less_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var maximumGradConfig = { - kernelName: Maximum, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var derA = function () { return mul(dy, cast(greaterEqual(a, b), 'float32')); }; - var derB = function () { return mul(dy, cast(less(a, b), 'float32')); }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the backprop of a 3d max pool. - * - * @param dy The dy error, of rank 5 of shape - * [batchSize, depth, height, width, channels]. - * assumed. - * @param input The original input image, of rank 5 or rank 4 of shape - * [batchSize, depth, height, width, channels]. - * @param output The original output image, of rank 5 of shape - * [batchSize, outDepth, outHeight, outWidth, channels]. - * @param filterSize The filter size: - * `[filterDepth, filterHeight, filterWidth]`. - * `filterSize` is a single number, - * then `filterDepth == filterHeight == filterWidth`. - * @param strides The strides of the pooling: - * `[strideDepth, strideHeight, strideWidth]`. If - * `strides` is a single number, then `strideHeight == strideWidth`. - * @param dilations Deprecated, this field will be gone in v3.0.0. - * The dilation rates: `[dilationDepth, dilationHeight, dilationWidth]` - * in which we sample input values across the depth, height and width - * dimensions in dilated pooling. - * Defaults to `[1, 1, 1]`. If `dilations` is a single number, - * then `dilationDepth == dilationHeight == dilationWidth`. - * If it is greater than 1, then all values of `strides` must be 1. - * @param pad A string from: 'same', 'valid'. The type of padding algorithm - * used in the forward prop of the op. - * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The - * rounding mode used when computing output dimensions if pad is a - * number. If none is provided, it will not round and error if the output - * is of fractional size. - */ - function maxPool3dBackprop_(dy, input, output, filterSize, strides, dilations, pad, dimRoundingMode) { - if (dilations === void 0) { dilations = [1, 1, 1]; } - var $dy = convertToTensor(dy, 'dy', 'maxPool3dBackprop'); - var $input = convertToTensor(input, 'input', 'maxPool3dBackprop'); - var $output = convertToTensor(output, 'output', 'maxPool3dBackprop'); - var dy5D = $dy; - var input5D = $input; - var output5D = $output; - var reshapedTo5D = false; - if ($input.rank === 4) { - reshapedTo5D = true; - dy5D = reshape($dy, [1, $dy.shape[0], $dy.shape[1], $dy.shape[2], $dy.shape[3]]); - input5D = reshape($input, [ - 1, $input.shape[0], $input.shape[1], $input.shape[2], $input.shape[3] - ]); - output5D = reshape($output, [ - 1, $output.shape[0], $output.shape[1], $output.shape[2], $output.shape[3] - ]); - } - assert(dy5D.rank === 5, function () { return "Error in maxPool3dBackprop: dy must be rank 5 but got rank " + - (dy5D.rank + "."); }); - assert(input5D.rank === 5, function () { return "Error in maxPool3dBackprop: input must be rank 5 but got rank " + - (input5D.rank + "."); }); - assert(output5D.rank === 5, function () { return "Error in maxPool3dBackprop: output must be rank 5 but got rank " + - (output5D.rank + "."); }); - assert(eitherStridesOrDilationsAreOne(strides, dilations), function () { return 'Error in maxPool3dBackprop: Either strides or dilations ' + - ("must be 1. Got strides " + strides + " and dilations '" + dilations + "'"); }); - if (dimRoundingMode != null) { - assert(isInt(pad), function () { return "Error in maxPool3dBackprop: pad must be an integer when " + - ("using, dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); - } - var forward = function (backend) { - var convInfo = computePool3DInfo(input5D.shape, filterSize, strides, dilations, pad, dimRoundingMode); - return backend.maxPool3dBackprop(dy5D, input5D, output5D, convInfo); - }; - var inputs = { dy: dy5D, input: input5D, output: output5D }; - var attrs = { filterSize: filterSize, strides: strides, dilations: dilations, pad: pad, dimRoundingMode: dimRoundingMode }; - var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, MaxPool3DBackprop, attrs); - if (reshapedTo5D) { - return reshape(res, [res.shape[1], res.shape[2], res.shape[3], res.shape[4]]); - } - return res; - } - var maxPool3dBackprop = op({ maxPool3dBackprop_: maxPool3dBackprop_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var maxPool3DGradConfig = { - kernelName: MaxPool3D, - inputsToSave: ['x'], - outputsToSave: [true], - gradFunc: function (dy, saved, attrs) { - var _a = saved, x = _a[0], y = _a[1]; - var _b = attrs, filterSize = _b.filterSize, strides = _b.strides, dilations = _b.dilations, pad = _b.pad, dimRoundingMode = _b.dimRoundingMode; - var $dilations = dilations == null ? [1, 1, 1] : dilations; - return { - x: function () { return maxPool3dBackprop(dy, x, y, filterSize, strides, $dilations, pad, dimRoundingMode); } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the backprop of a 2D max pool. - * - * @param dy The dy error, of rank 4 or rank 3 of shape - * [batchSize, height, width, channels]. If rank 3, batch of 1 is - * assumed. - * @param input The original input image, of rank 4, of shape - * [batchSize, height, width, channels]. - * @param output The original output image, of rank 4, of shape - * [batchSize, outHeight, outWidth, channels]. - * @param filterSize The filter size: `[filterHeight, filterWidth]`. If - * `filterSize` is a single number, then `filterHeight == filterWidth`. - * @param strides The strides of the pooling: `[strideHeight, strideWidth]`. If - * `strides` is a single number, then `strideHeight == strideWidth`. - * @param pad A string from: 'same', 'valid'. The type of padding algorithm - * used in the forward prop of the op. - * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The - * rounding mode used when computing output dimensions if pad is a - * number. If none is provided, it will not round and error if the output - * is of fractional size. - */ - function maxPoolBackprop_(dy, input, output, filterSize, strides, pad, dimRoundingMode) { - var $dy = convertToTensor(dy, 'dy', 'maxPoolBackprop'); - var $input = convertToTensor(input, 'input', 'maxPoolBackprop'); - var $output = convertToTensor(output, 'output', 'maxPoolBackprop'); - assert($input.rank === $dy.rank, function () { return "Rank of input (" + $input.rank + ") does not match rank of dy " + - ("(" + $dy.rank + ")"); }); - assert($dy.rank === 4, function () { return "Error in maxPoolBackprop: dy must be rank 4 but got rank " + - ($dy.rank + "."); }); - assert($input.rank === 4, function () { return "Error in maxPoolBackprop: input must be rank 4 but got rank " + - ($input.rank + "."); }); - if (dimRoundingMode != null) { - assert(isInt(pad), function () { return "Error in maxPoolBackprop: pad must be an integer when using, " + - ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); - } - var forward = function (backend) { - var convInfo = computePool2DInfo($input.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); - return backend.maxPoolBackprop($dy, $input, $output, convInfo); - }; - var inputs = { dy: $dy, input: $input, output: $output }; - var attrs = { filterSize: filterSize, strides: strides, pad: pad, dimRoundingMode: dimRoundingMode }; - return ENGINE.runKernelFunc(forward, inputs, null, MaxPoolBackprop, attrs); - } - var maxPoolBackprop = op({ maxPoolBackprop_: maxPoolBackprop_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var maxPoolGradConfig = { - kernelName: MaxPool, - inputsToSave: ['x'], - outputsToSave: [true], - gradFunc: function (dy, saved, attrs) { - var _a = saved, x = _a[0], y = _a[1]; - var _b = attrs, filterSize = _b.filterSize, strides = _b.strides, pad = _b.pad; - return { - x: function () { return maxPoolBackprop(dy, x, y, filterSize, strides, pad); } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var minGradConfig = { - kernelName: Min, - inputsToSave: ['x'], - outputsToSave: [true], - gradFunc: function (dy, saved, attrs) { - var minAttrs = attrs; - var axis = minAttrs.axis; - var x = saved[0], y = saved[1]; - var origAxes = parseAxisParam(axis, x.shape); - var permutedAxes = getAxesPermutation(origAxes, x.rank); - var minGrad = gradForMinAndMax(dy, y, x, origAxes, permutedAxes); - return { - x: function () { - var out = minGrad['x'](); - if (permutedAxes != null) { - out = transpose(out); - } - return out; - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the truth value of (a > b) element-wise. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([1, 2, 3]); - * const b = tf.tensor1d([2, 2, 2]); - * - * a.greater(b).print(); - * ``` - * - * @param a The first input tensor. - * @param b The second input tensor. Must have the same dtype as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function greater_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'greater'); - var $b = convertToTensor(b, 'b', 'greater'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - assertAndGetBroadcastShape($a.shape, $b.shape); - var forward = function (backend) { return backend.greater($a, $b); }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Greater); - } - var greater = op({ greater_: greater_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var minimumGradConfig = { - kernelName: Minimum, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var derA = function () { return mul(dy, cast(lessEqual(a, b), 'float32')); }; - var derB = function () { return mul(dy, cast(greater(a, b), 'float32')); }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes floor of input `tf.Tensor` element-wise: `floor(x)`. - * - * ```js - * const x = tf.tensor1d([.6, 1.1, -3.3]); - * - * x.floor().print(); // or tf.floor(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function floor_(x) { - var $x = convertToTensor(x, 'x', 'floor'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend) { return backend.floor($x); }, inputs, null /* grad */, Floor); - } - var floor = op({ floor_: floor_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var modGradConfig = { - kernelName: Mod, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var outShape = assertAndGetBroadcastShape(a.shape, b.shape); - var derA = function () { - var reduceAxes = getReductionAxes(a.shape, outShape); - if (reduceAxes.length > 0) { - return reshape(sum$1(dy, reduceAxes), a.shape); - } - return dy; - }; - var derB = function () { - var res = mul(dy, neg(floor(div(a, b)))); - var reduceAxes = getReductionAxes(b.shape, outShape); - if (reduceAxes.length > 0) { - return reshape(sum$1(res, reduceAxes), b.shape); - } - return res; - }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var multiplyGradConfig = { - kernelName: Multiply, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var outShape = assertAndGetBroadcastShape(a.shape, b.shape); - var derA = function () { - var res = mul(dy, cast(b, 'float32')); - var reduceAxes = getReductionAxes(a.shape, outShape); - if (reduceAxes.length > 0) { - return reshape(sum$1(res, reduceAxes), a.shape); - } - return res; - }; - var derB = function () { - var res = mul(dy, cast(a, 'float32')); - var reduceAxes = getReductionAxes(b.shape, outShape); - if (reduceAxes.length > 0) { - return reshape(sum$1(res, reduceAxes), b.shape); - } - return res; - }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var negateGradConfig = { - kernelName: Negate, - gradFunc: function (dy) { - return { x: function () { return neg(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Converts two real numbers to a complex number. - * - * Given a tensor `real` representing the real part of a complex number, and a - * tensor `imag` representing the imaginary part of a complex number, this - * operation returns complex numbers elementwise of the form [r0, i0, r1, i1], - * where r represents the real part and i represents the imag part. - * - * The input tensors real and imag must have the same shape. - * - * ```js - * const real = tf.tensor1d([2.25, 3.25]); - * const imag = tf.tensor1d([4.75, 5.75]); - * const complex = tf.complex(real, imag); - * - * complex.print(); - * ``` - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function complex_(real, imag) { - var $real = convertToTensor(real, 'real', 'complex'); - var $imag = convertToTensor(imag, 'imag', 'complex'); - assertShapesMatch($real.shape, $imag.shape, "real and imag shapes, " + $real.shape + " and " + $imag.shape + ", " + - "must match in call to tf.complex()."); - var forward = function (backend) { - return backend.complex($real, $imag); - }; - var inputs = { real: $real, imag: $imag }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Complex); - } - var complex = op({ complex_: complex_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates a `tf.Tensor` with all elements set to 0. - * - * ```js - * tf.zeros([2, 2]).print(); - * ``` - * - * @param shape An array of integers defining the output tensor shape. - * @param dtype The type of an element in the resulting tensor. Can - * be 'float32', 'int32' or 'bool'. Defaults to 'float'. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function zeros(shape, dtype) { - if (dtype === void 0) { dtype = 'float32'; } - if (dtype === 'complex64') { - var real = zeros(shape, 'float32'); - var imag = zeros(shape, 'float32'); - return complex(real, imag); - } - var values = makeZerosTypedArray(sizeFromShape(shape), dtype); - return ENGINE.makeTensor(values, shape, dtype); - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var oneHotGradConfig = { - kernelName: OneHot, - inputsToSave: ['indices'], - gradFunc: function (dy, saved) { - var indices = saved[0]; - return { indices: function () { return zeros(indices.shape, 'float32'); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var onesLikeGradConfig = { - kernelName: OnesLike, - gradFunc: function (dy) { - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var padV2GradConfig = { - kernelName: PadV2, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - // Pad introduces values around the original tensor, so the gradient - // slices the original shape out of the gradient. - var x = saved[0]; - var paddings = attrs.paddings; - var begin = paddings.map(function (p) { return p[0]; }); - return { x: function () { return dy.slice(begin, x.shape); } }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes natural logarithm of the input `tf.Tensor` element-wise: `ln(x)` - * - * ```js - * const x = tf.tensor1d([1, 2, Math.E]); - * - * x.log().print(); // or tf.log(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function log_(x) { - var $x = convertToTensor(x, 'x', 'log'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.log($x); - save([$x]); - return res; - }, inputs, null /* grad */, Log); - } - var log = op({ log_: log_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the power of one `tf.Tensor` to another. Supports broadcasting. - * - * Given a `tf.Tensor` x and a `tf.Tensor` y, this operation computes x^y for - * corresponding elements in x and y. The result's dtype will be the upcasted - * type of the `base` and `exp` dtypes. - * - * ```js - * const a = tf.tensor([[2, 3], [4, 5]]) - * const b = tf.tensor([[1, 2], [3, 0]]).toInt(); - * - * a.pow(b).print(); // or tf.pow(a, b) - * ``` - * - * ```js - * const a = tf.tensor([[1, 2], [3, 4]]) - * const b = tf.tensor(2).toInt(); - * - * a.pow(b).print(); // or tf.pow(a, b) - * ``` - * We also expose `powStrict` which has the same signature as this op and - * asserts that `base` and `exp` are the same shape (does not broadcast). - * - * @param base The base `tf.Tensor` to pow element-wise. - * @param exp The exponent `tf.Tensor` to pow element-wise. - */ - /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ - function pow_(base, exp) { - var _a; - var $base = convertToTensor(base, 'base', 'pow'); - var $exp = convertToTensor(exp, 'exp', 'pow'); - _a = makeTypesMatch($base, $exp), $base = _a[0], $exp = _a[1]; - var inputs = { a: $base, b: $exp }; - var forward = function (backend, save) { - var y = backend.pow($base, $exp); - save([$base, $exp, y]); - return y; - }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Pow); - } - var pow = op({ pow_: pow_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var powGradConfig = { - kernelName: Pow, - inputsToSave: ['a', 'b'], - outputsToSave: [true], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1], y = saved[2]; - var base = a; - var exp = b; - var outShape = assertAndGetBroadcastShape(base.shape, exp.shape); - var derBase = function () { - var expFloat = cast(exp, 'float32'); - var res = mul(dy, mul(expFloat, pow(base, sub(expFloat, scalar(1))))); - var reduceAxes = getReductionAxes(base.shape, outShape); - if (reduceAxes.length > 0) { - res = sum$1(res, reduceAxes); - } - return reshape(res, base.shape); - }; - var derExp = function () { - var condition = greater(base, 0); - var logBase = where(condition, log(base), zerosLike(base)); - var res = mul(dy, mul(y, logBase)); - var reduceAxes = getReductionAxes(exp.shape, outShape); - if (reduceAxes.length > 0) { - res = sum$1(res, reduceAxes); - } - return reshape(res, exp.shape); - }; - return { a: derBase, b: derExp }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var preluGradConfig = { - kernelName: Prelu, - inputsToSave: ['x', 'alpha'], - gradFunc: function (dy, saved) { - var x = saved[0], alpha = saved[1]; - var mask = greater(x, 0); - return { - x: function () { return where(mask, dy, mul(dy, alpha)); }, - alpha: function () { - var res = where(mask, zerosLike(dy), mul(dy, x)); - var reduceAxes = getReductionAxes(alpha.shape, dy.shape); - if (reduceAxes.length > 0) { - res = sum$1(res, reduceAxes); - } - return reshape(res, alpha.shape); - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var reciprocalGradConfig = { - kernelName: Reciprocal, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, neg(square(x))); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var relu6GradConfig = { - kernelName: Relu6, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - var mask = mul(lessEqual(x, 6), step(x)); - return { x: function () { return mul(dy, cast(mask, 'float32')); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var reluGradConfig = { - kernelName: Relu, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(dy, cast(step(x), 'float32')); } }; - } - }; - - /** - * @license - * Copyright 2020 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var reshapeGradConfig = { - kernelName: Reshape, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return reshape(dy, x.shape); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var resizeBilinearGradConfig = { - kernelName: ResizeBilinear, - inputsToSave: ['images'], - gradFunc: function (dy, saved, attrs) { - var images = saved[0]; - var backPropKernelFunc = function (backend) { - var alignCorners = attrs.alignCorners; - return backend.resizeBilinearBackprop(dy, images, alignCorners); - }; - var inputs = { images: images }; - var imagesDer = function () { return ENGINE.runKernelFunc(backPropKernelFunc, inputs, null /* gradient */, ResizeBilinearGrad, attrs); }; - return { images: imagesDer }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var resizeNearestNeighborGradConfig = { - kernelName: ResizeNearestNeighbor, - inputsToSave: ['images'], - gradFunc: function (dy, saved, attrs) { - var images = saved[0]; - var backPropKernelFunc = function (backend) { - var alignCorners = attrs.alignCorners; - return backend.resizeNearestNeighborBackprop(dy, images, alignCorners); - }; - var inputs = { images: images }; - var imagesDer = function () { return ENGINE.runKernelFunc(backPropKernelFunc, inputs, null /* gradient */, ResizeNearestNeighborGrad, attrs); }; - return { images: imagesDer }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates a new tensor with the same values and shape as the specified - * tensor. - * - * ```js - * const x = tf.tensor([1, 2]); - * - * x.clone().print(); - * ``` - * - * @param x The tensor to clone. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function clone_(x) { - var $x = convertToTensor(x, 'x', 'clone', null); - var forward = function () { - return ENGINE.makeTensorFromDataId($x.dataId, $x.shape, $x.dtype); - }; - var inputs = { x: $x }; - // Note this op is called tf.identity in python. Hence the kernel name used - // here. - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Identity); - } - var clone = op({ clone_: clone_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Reverses a `tf.Tensor` along a specified axis. - * - * Also available are stricter rank-specific methods that assert that `x` is - * of the given rank: - * - `tf.reverse1d` - * - `tf.reverse2d` - * - `tf.reverse3d` - * - `tf.reverse4d` - * - * Except `tf.reverse1d` (which does not have axis param), all methods have - * same signature as this method. - * - * ```js - * const x = tf.tensor1d([1, 2, 3, 4]); - * - * x.reverse().print(); - * ``` - * - * ```js - * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); - * - * const axis = 1; - * x.reverse(axis).print(); - * ``` - * @param x The input tensor to be reversed. - * @param axis The set of dimensions to reverse. Must be in the - * range [-rank(x), rank(x)). Defaults to all axes. - */ - /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ - function reverse_(x, axis) { - var $x = convertToTensor(x, 'x', 'reverse'); - var forward = function (backend) { - var axes = parseAxisParam(axis, $x.shape); - if ($x.rank === 0) { - return clone($x); - } - var res = backend.reverse($x, axes); - return reshape(res, $x.shape); - }; - var inputs = { x: $x }; - var attrs = { dims: axis }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Reverse, attrs); - } - var reverse = op({ reverse_: reverse_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var reverseGradConfig = { - kernelName: Reverse, - gradFunc: function (dy, saved, attrs) { - var dims = attrs.dims; - var axes = parseAxisParam(dims, dy.shape); - return { x: function () { return reverse(dy, axes); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var roundGradConfig = { - kernelName: Round, - gradFunc: function (dy) { - // TODO(nsthorat): Let gradients be null for cases where we want to stop - // backpropgation. - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var rsqrtGradConfig = { - kernelName: Rsqrt, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return neg(div(dy, mul(pow(x, 1.5), 2))); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the truth value of `NOT x` element-wise. - * - * ```js - * const a = tf.tensor1d([false, true], 'bool'); - * - * a.logicalNot().print(); - * ``` - * - * @param x The input tensor. Must be of dtype 'bool'. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function logicalNot_(x) { - var $x = convertToTensor(x, 'x', 'logicalNot', 'bool'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend) { return backend.logicalNot($x); }, inputs, null /* grad */, LogicalNot); - } - var logicalNot = op({ logicalNot_: logicalNot_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var selectV2PoolGradConfig = { - kernelName: SelectV2, - inputsToSave: ['condition'], - gradFunc: function (dy, saved) { - var condition = saved[0]; - return { - // TODO(julianoks): Return null for condition gradient - // when backprop supports it. - condition: function () { return cast(zerosLike(condition), 'float32'); }, - t: function () { return mul(dy, cast(condition, dy.dtype)); }, - e: function () { return mul(dy, cast(logicalNot(condition), dy.dtype)); } - }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var SELU_SCALEALPHA = 1.7580993408473768599402175208123; - var SELU_SCALE = 1.0507009873554804934193349852946; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var seluGradConfig = { - kernelName: Selu, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { - x: function () { - var mask = greater(x, scalar(0)); - var scaleAlpha = scalar(SELU_SCALEALPHA); - var scale = scalar(SELU_SCALE); - var greaterThanZeroDer = mul(dy, scale); - var lessEqualZeroDer = mul(mul(dy, scaleAlpha), exp(cast(x, 'float32'))); - return where(mask, greaterThanZeroDer, lessEqualZeroDer); - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var sigmoidGradConfig = { - kernelName: Sigmoid, - outputsToSave: [true], - gradFunc: function (dy, saved) { - var y = saved[0]; - return { x: function () { return mul(dy, mul(y, sub(scalar(1), y))); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var signGradConfig = { - kernelName: Sign, - gradFunc: function (dy) { - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes cos of the input `tf.Tensor` element-wise: `cos(x)` - * - * ```js - * const x = tf.tensor1d([0, Math.PI / 2, Math.PI * 3 / 4]); - * - * x.cos().print(); // or tf.cos(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function cos_(x) { - var $x = convertToTensor(x, 'x', 'cos'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.cos($x); - save([$x]); - return res; - }, inputs, null /* grad */, Cos); - } - var cos = op({ cos_: cos_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var sinGradConfig = { - kernelName: Sin, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(cos(cast(x, 'float32')), dy); } }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes hyperbolic cos of the input `tf.Tensor` element-wise: `cosh(x)` - * - * ```js - * const x = tf.tensor1d([0, 1, -1, .7]); - * - * x.cosh().print(); // or tf.cosh(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function cosh_(x) { - var $x = convertToTensor(x, 'x', 'cosh'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.cosh($x); - save([$x]); - return res; - }, inputs, null /* grad */, Cosh); - } - var cosh = op({ cosh_: cosh_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var sinhGradConfig = { - kernelName: Sinh, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(cosh(cast(x, 'float32')), dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Pads a `tf.Tensor` with a given value and paddings. - * - * This operation currently only implements the `CONSTANT` mode. - * - * Also available are stricter rank-specific methods with the same signature - * as this method that assert that `paddings` is of given length. - * - `tf.pad1d` - * - `tf.pad2d` - * - `tf.pad3d` - * - `tf.pad4d` - * - * ```js - * const x = tf.tensor1d([1, 2, 3, 4]); - * x.pad([[1, 2]]).print(); - * ``` - * @param x The tensor to pad. - * @param paddings An array of length `R` (the rank of the tensor), where - * each element is a length-2 tuple of ints `[padBefore, padAfter]`, - * specifying how much to pad along each dimension of the tensor. - * @param constantValue The pad value to use. Defaults to 0. - */ - /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ - function pad_(x, paddings, constantValue) { - if (constantValue === void 0) { constantValue = 0; } - var $x = convertToTensor(x, 'x', 'pad'); - if ($x.rank === 0) { - throw new Error('pad(scalar) is not defined. Pass non-scalar to pad'); - } - var forward = function (backend, save) { - save([$x]); - return backend.pad($x, paddings, constantValue); - }; - var attrs = { paddings: paddings, constantValue: constantValue }; - var inputs = { x: $x }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, PadV2, attrs); - } - var pad = op({ pad_: pad_ }); - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function assertParamsValid(input, begin, size) { - assert(input.rank === begin.length, function () { return "Error in slice" + input.rank + "D: Length of begin " + begin + " must " + - ("match the rank of the array (" + input.rank + ")."); }); - assert(input.rank === size.length, function () { return "Error in slice" + input.rank + "D: Length of size " + size + " must " + - ("match the rank of the array (" + input.rank + ")."); }); - var _loop_1 = function (i) { - assert(begin[i] + size[i] <= input.shape[i], function () { return "Error in slice" + input.rank + "D: begin[" + i + "] + size[" + i + "] " + - ("(" + (begin[i] + size[i]) + ") would overflow input.shape[" + i + "] (" + input.shape[i] + ")"); }); - }; - for (var i = 0; i < input.rank; ++i) { - _loop_1(i); - } - } - /** Converts a binary mask to an array of axes. Used in stridedSlice(). */ - function maskToAxes(mask) { - var axes = []; - var axis = 0; - while (mask > 0) { - if (mask & 1) { - axes.push(axis); - } - mask /= 2; - axis++; - } - return axes; - } - /** Computes the output shape given the strided slice params. */ - function computeOutShape(begin, end, strides) { - var size = []; - for (var axis = 0; axis < begin.length; axis++) { - size[axis] = Math.ceil((end[axis] - begin[axis]) / strides[axis]); - } - return size; - } - // Creates full selection at the elided dimensions. If the dimension matches - // the ellipsis mask, override the current stride value. Otherwise, insert. - function stridesWithElidedDims(strides, ellipsisInsertionIndex, numElidedAxes, inputShape) { - var newStrides = strides.slice(); - for (var i = newStrides.length; i < inputShape.length; i++) { - newStrides.push(1); - } - for (var i = 0; i < numElidedAxes; i++) { - if (i === 0) { - newStrides[ellipsisInsertionIndex] = 1; - } - else { - newStrides.splice(ellipsisInsertionIndex, 0 /* num elements to delete */, 1 /* element to add */); - newStrides.pop(); - } - } - return newStrides; - } - function unnormalizeAxis(ellipsisInsertionIndex, numElidedAxes, normalizedAxis) { - if (normalizedAxis <= ellipsisInsertionIndex) { - return normalizedAxis; - } - return normalizedAxis - (numElidedAxes - 1); - } - function getElidedAxes(numElidedAxes, ellipsisInsertionIndex) { - var elidedAxes = []; - for (var i = 0; i < numElidedAxes; i++) { - elidedAxes.push(ellipsisInsertionIndex + i); - } - return elidedAxes; - } - // Creates full selection at the elided dimensions. If the dimension matches - // the ellipsis mask, override the current start value. Otherwise, insert. - function startIndicesWithElidedDims(beginMask, ellipsisInsertionIndex, numElidedAxes, originalBegin, inputShape) { - var newIndices = inputShape.slice(); - var elidedAxes = getElidedAxes(numElidedAxes, ellipsisInsertionIndex); - for (var axis = 0; axis < newIndices.length; axis++) { - if (elidedAxes.indexOf(axis) > -1) { - newIndices[axis] = 0; - } - else { - var originalAxis = unnormalizeAxis(ellipsisInsertionIndex, numElidedAxes, axis); - var originalValue = originalBegin[originalAxis]; - if (beginMask & 1 << originalAxis) { - originalValue = 0; - } - newIndices[axis] = originalValue; - } - } - return newIndices; - } - // Creates full selection at the elided dimensions. If the dimension matches - // the ellipsis mask, override the current stop value. Otherwise, insert. - function stopIndicesWithElidedDims(endMask, ellipsisInsertionIndex, numElidedAxes, originalEnd, inputShape) { - var newIndices = inputShape.slice(); - var elidedAxes = getElidedAxes(numElidedAxes, ellipsisInsertionIndex); - for (var axis = 0; axis < newIndices.length; axis++) { - if (elidedAxes.indexOf(axis) > -1) { - newIndices[axis] = Number.MAX_SAFE_INTEGER; - } - else { - var originalAxis = unnormalizeAxis(ellipsisInsertionIndex, numElidedAxes, axis); - var originalValue = originalEnd[originalAxis]; - if (endMask & 1 << originalAxis) { - originalValue = Number.MAX_SAFE_INTEGER; - } - newIndices[axis] = originalValue; - } - } - for (var i = 0; i < newIndices.length; i++) { - // Handle negative indices - var axisSize = inputShape[i]; - if (newIndices[i] < 0) { - newIndices[i] += axisSize; - } - newIndices[i] = clamp(0, newIndices[i], inputShape[i]); - } - return newIndices; - } - function stridesForAxis(strides, axis, ellipsisMask) { - var stride = strides[axis]; - if (ellipsisMask & (1 << axis) || stride == null) { - stride = 1; - } - return stride; - } - function startForAxis(beginMask, startIndices, strides, inputShape, axis, ellipsisMask) { - // Begin with the specified index - var start = startIndices[axis]; - var stride = strides[axis] || 1; - // Check the axis bit from right of masked axes, or the begin index is not set - // for the axis. - if (beginMask & 1 << axis || ellipsisMask & 1 << axis || start == null) { - if (stride > 0) { - // Forward iteration - use the first element. These values will get - // clamped below (Note: We could have set them to 0 and axis_size-1, but - // use lowest() and max() to maintain symmetry with StopForAxis()) - start = Number.MIN_SAFE_INTEGER; - } - else { - // Backward iteration - use the last element. - start = Number.MAX_SAFE_INTEGER; - } - } - // Handle negative indices - var axisSize = inputShape[axis]; - if (start < 0) { - start += axisSize; - } - // Clamping - start = clamp(0, start, axisSize - 1); - return start; - } - function stopForAxis(endMask, stopIndices, strides, inputShape, axis, ellipsisMask) { - // Begin with the specified index - var stop = stopIndices[axis]; - var stride = strides[axis] || 1; - // Check the axis bit from right of masked axes, or if the stop index is not - // set for this axis. - if (endMask & (1 << axis) || ellipsisMask & (1 << axis) || stop == null) { - if (stride > 0) { - // Forward iteration - use the last element. These values will get - // clamped below - stop = Number.MAX_SAFE_INTEGER; - } - else { - // Backward iteration - use the first element. - stop = Number.MIN_SAFE_INTEGER; - } - } - // Handle negative indices - var axisSize = inputShape[axis]; - if (stop < 0) { - stop += axisSize; - } - // Clamping - // Because the end index points one past the last element, we need slightly - // different clamping ranges depending on the direction. - if (stride > 0) { - // Forward iteration - stop = clamp(0, stop, axisSize); - } - else { - // Backward iteration - stop = clamp(-1, stop, axisSize - 1); - } - return stop; - } - /** - * Returns true if the slice occupies a continous set of elements in the - * 'flat' space. - */ - function isSliceContinous(shape, begin, size) { - // Index of the first axis that has size > 1. - var firstNonOneAxis = size.length; - for (var i = 0; i < size.length; i++) { - if (size[i] > 1) { - firstNonOneAxis = i; - break; - } - } - for (var i = firstNonOneAxis + 1; i < size.length; i++) { - if (begin[i] > 0 || size[i] !== shape[i]) { - return false; - } - } - return true; - } - function computeFlatOffset(begin, strides) { - var flatOffset = begin.length > 0 ? begin[begin.length - 1] : 1; - for (var i = 0; i < begin.length - 1; i++) { - flatOffset += begin[i] * strides[i]; - } - return flatOffset; - } - function parseSliceParams(x, begin, size) { - // The following logic allows for more ergonomic calls. - var begin_; - if (typeof begin === 'number') { - begin_ = [begin].concat(new Array(x.rank - 1).fill(0)); - } - else if (begin.length < x.rank) { - begin_ = begin.concat(new Array(x.rank - begin.length).fill(0)); - } - else { - begin_ = begin.slice(); - } - begin_.forEach(function (d) { - assert(d !== -1, function () { return 'slice() does not support negative begin indexing.'; }); - }); - var size_; - if (size == null) { - size_ = new Array(x.rank).fill(-1); - } - else if (typeof size === 'number') { - size_ = [size].concat(new Array(x.rank - 1).fill(-1)); - } - else if (size.length < x.rank) { - size_ = size.concat(new Array(x.rank - size.length).fill(-1)); - } - else { - size_ = size; - } - size_ = size_.map(function (d, i) { - if (d >= 0) { - return d; - } - else { - assert(d === -1, function () { return "Negative size values should be exactly -1 but got " + - (d + " for the slice() size at index " + i + "."); }); - return x.shape[i] - begin_[i]; - } - }); - return [begin_, size_]; - } - - var slice_util = { - __proto__: null, - assertParamsValid: assertParamsValid, - maskToAxes: maskToAxes, - computeOutShape: computeOutShape, - stridesWithElidedDims: stridesWithElidedDims, - startIndicesWithElidedDims: startIndicesWithElidedDims, - stopIndicesWithElidedDims: stopIndicesWithElidedDims, - stridesForAxis: stridesForAxis, - startForAxis: startForAxis, - stopForAxis: stopForAxis, - isSliceContinous: isSliceContinous, - computeFlatOffset: computeFlatOffset, - parseSliceParams: parseSliceParams - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var sliceGradConfig = { - kernelName: Slice, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0]; - var _a = attrs, begin = _a.begin, size = _a.size; - var inputShape = x.shape; - var _b = parseSliceParams(x, begin, size), begin_ = _b[0], size_ = _b[1]; - // Create an Nx2 padding where the first column represents how many - // zeros are prepended (at start) for each dimension, and the second - // column indicates how many zeros are appended (at end). - // The number of zeros to append is the shape of the input - // elementwise-subtracted by both the begin vector and sizes vector. - var paddings = []; - for (var i = 0; i < dy.rank; i++) { - paddings.push([begin_[i], inputShape[i] - begin_[i] - size_[i]]); - } - return { x: function () { return pad(dy, paddings); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var softmaxGradConfig = { - kernelName: Softmax, - outputsToSave: [true], - gradFunc: function (dy, saved, attrs) { - var y = saved[0]; - var dim = attrs.dim; - var keepDims = true; - var dyTimesY = mul(dy, y); - return { - logits: function () { return sub(dyTimesY, mul(sum$1(dyTimesY, [dim], keepDims), y)); } - }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes sigmoid element-wise, `1 / (1 + exp(-x))` - * - * ```js - * const x = tf.tensor1d([0, -1, 2, -3]); - * - * x.sigmoid().print(); // or tf.sigmoid(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function sigmoid_(x) { - var $x = convertToTensor(x, 'x', 'sigmoid'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.sigmoid($x); - save([res]); - return res; - }, inputs, null /* grad */, Sigmoid); - } - var sigmoid = op({ sigmoid_: sigmoid_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var softplusGradConfig = { - kernelName: Softplus, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(dy, sigmoid(x)); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * This operation reshapes the "batch" dimension 0 into `M + 1` dimensions of - * shape `blockShape + [batch]`, interleaves these blocks back into the grid - * defined by the spatial dimensions `[1, ..., M]`, to obtain a result with - * the same rank as the input. The spatial dimensions of this intermediate - * result are then optionally cropped according to `crops` to produce the - * output. This is the reverse of `tf.spaceToBatchND`. See below for a precise - * description. - * - * ```js - * const x = tf.tensor4d([1, 2, 3, 4], [4, 1, 1, 1]); - * const blockShape = [2, 2]; - * const crops = [[0, 0], [0, 0]]; - * - * x.batchToSpaceND(blockShape, crops).print(); - * ``` - * - * @param x A `tf.Tensor`. N-D with `x.shape` = `[batch] + spatialShape + - * remainingShape`, where spatialShape has `M` dimensions. - * @param blockShape A 1-D array. Must have shape `[M]`, all values must - * be >= 1. - * @param crops A 2-D array. Must have shape `[M, 2]`, all values must be >= 0. - * `crops[i] = [cropStart, cropEnd]` specifies the amount to crop from input - * dimension `i + 1`, which corresponds to spatial dimension `i`. It is required - * that `cropStart[i] + cropEnd[i] <= blockShape[i] * inputShape[i + 1]` - * - * This operation is equivalent to the following steps: - * - * 1. Reshape `x` to `reshaped` of shape: `[blockShape[0], ..., - * blockShape[M-1], batch / prod(blockShape), x.shape[1], ..., - * x.shape[N-1]]` - * - * 2. Permute dimensions of `reshaped`to produce `permuted` of shape `[batch / - * prod(blockShape),x.shape[1], blockShape[0], ..., x.shape[M], - * blockShape[M-1],x.shape[M+1], ..., x.shape[N-1]]` - * - * 3. Reshape `permuted` to produce `reshapedPermuted` of shape `[batch / - * prod(blockShape),x.shape[1] * blockShape[0], ..., x.shape[M] * - * blockShape[M-1],x.shape[M+1], ..., x.shape[N-1]]` - * - * 4. Crop the start and end of dimensions `[1, ..., M]` of `reshapedPermuted` - * according to `crops` to produce the output of shape: `[batch / - * prod(blockShape),x.shape[1] * blockShape[0] - crops[0,0] - crops[0,1], - * ..., x.shape[M] * blockShape[M-1] - crops[M-1,0] - - * crops[M-1,1],x.shape[M+1], ..., x.shape[N-1]]` - */ - /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ - function batchToSpaceND_(x, blockShape, crops) { - var $x = convertToTensor(x, 'x', 'batchToSpaceND'); - var prod = blockShape.reduce(function (a, b) { return a * b; }); - assert($x.rank >= 1 + blockShape.length, function () { return "input rank is " + $x.rank + " but should be > than blockShape.length " + blockShape.length; }); - assert(crops.length === blockShape.length, function () { return "crops.length is " + crops.length + " but should be equal to blockShape.length " + blockShape.length; }); - assert($x.shape[0] % prod === 0, function () { return "input tensor batch is " + $x.shape[0] + " but is not divisible by the product of " + - ("the elements of blockShape " + blockShape.join(' * ') + " === " + prod); }); - var forward = function (backend) { - return backend.batchToSpaceND($x, blockShape, crops); - }; - var inputs = { x: $x }; - var attrs = { blockShape: blockShape, crops: crops }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, BatchToSpaceND, attrs); - } - var batchToSpaceND = op({ batchToSpaceND_: batchToSpaceND_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var spaceToBatchNDGradConfig = { - kernelName: SpaceToBatchND, - gradFunc: function (dy, saved, attrs) { - var _a = attrs, blockShape = _a.blockShape, paddings = _a.paddings; - return { x: function () { return batchToSpaceND(dy, blockShape, paddings); } }; - } - }; - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function assertParamsConsistent(shapes, axis) { - var rank = shapes[0].length; - shapes.forEach(function (shape, i) { - assert(shape.length === rank, function () { - return "Error in concat" + rank + "D: rank of tensors[" + i + "] must be the same " + - ("as the rank of the rest (" + rank + ")"); - }); - }); - assert(axis >= 0 && axis < rank, function () { return "Error in concat" + rank + "D: axis must be between 0 and " + (rank - 1) + "."; }); - var firstShape = shapes[0]; - shapes.forEach(function (shape, i) { - for (var r = 0; r < rank; r++) { - assert((r === axis) || (shape[r] === firstShape[r]), function () { return "Error in concat" + rank + "D: Shape of tensors[" + i + "] (" + shape + ") " + - ("does not match the shape of the rest (" + firstShape + ") ") + - ("along the non-concatenated axis " + i + "."); }); - } - }); - } - function computeOutShape$1(shapes, axis) { - var outputShape = shapes[0].slice(); - for (var i = 1; i < shapes.length; i++) { - outputShape[axis] += shapes[i][axis]; - } - return outputShape; - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates a `tf.Tensor` with the provided values, shape and dtype. - * - * ```js - * // Pass an array of values to create a vector. - * tf.tensor([1, 2, 3, 4]).print(); - * ``` - * - * ```js - * // Pass a nested array of values to make a matrix or a higher - * // dimensional tensor. - * tf.tensor([[1, 2], [3, 4]]).print(); - * ``` - * - * ```js - * // Pass a flat array and specify a shape yourself. - * tf.tensor([1, 2, 3, 4], [2, 2]).print(); - * ``` - * - * @param values The values of the tensor. Can be nested array of numbers, - * or a flat array, or a `TypedArray`. If the values are strings, - * they will be encoded as utf-8 and kept as `Uint8Array[]`. - * @param shape The shape of the tensor. Optional. If not provided, - * it is inferred from `values`. - * @param dtype The data type. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function tensor(values, shape, dtype) { - var inferredShape = inferShape(values, dtype); - return makeTensor(values, shape, inferredShape, dtype); - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Concatenates a list of `tf.Tensor`s along a given axis. - * - * The tensors ranks and types must match, and their sizes must match in all - * dimensions except `axis`. - * - * Also available are stricter rank-specific methods that assert that - * `tensors` are of the given rank: - * - `tf.concat1d` - * - `tf.concat2d` - * - `tf.concat3d` - * - `tf.concat4d` - * - * Except `tf.concat1d` (which does not have axis param), all methods have - * same signature as this method. - * - * ```js - * const a = tf.tensor1d([1, 2]); - * const b = tf.tensor1d([3, 4]); - * a.concat(b).print(); // or a.concat(b) - * ``` - * - * ```js - * const a = tf.tensor1d([1, 2]); - * const b = tf.tensor1d([3, 4]); - * const c = tf.tensor1d([5, 6]); - * tf.concat([a, b, c]).print(); - * ``` - * - * ```js - * const a = tf.tensor2d([[1, 2], [10, 20]]); - * const b = tf.tensor2d([[3, 4], [30, 40]]); - * const axis = 1; - * tf.concat([a, b], axis).print(); - * ``` - * @param tensors A list of tensors to concatenate. - * @param axis The axis to concate along. Defaults to 0 (the first dim). - */ - /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ - function concat_(tensors, axis) { - if (axis === void 0) { axis = 0; } - assert(tensors.length >= 1, function () { return 'Pass at least one tensor to concat'; }); - var $tensors = convertToTensorArray(tensors, 'tensors', 'concat'); - if ($tensors[0].dtype === 'complex64') { - $tensors.forEach(function (tensor) { - if (tensor.dtype !== 'complex64') { - throw new Error("Cannot concatenate complex64 tensors with a tensor\n with dtype " + tensor.dtype + ". "); - } - }); - } - var $axis = parseAxisParam(axis, $tensors[0].shape)[0]; - var outShape = computeOutShape$1($tensors.map(function (t) { return t.shape; }), $axis); - if (sizeFromShape(outShape) === 0) { - return tensor([], outShape); - } - // Keep only non-empty tensors (ignore tensors with 0 in their shape). - $tensors = $tensors.filter(function (t) { return t.size > 0; }); - if ($tensors.length === 1) { - return $tensors[0]; - } - var shapes = $tensors.map(function (t) { return t.shape; }); - assertParamsConsistent(shapes, $axis); - var forward = function (backend, save) { - var res = backend.concat($tensors, $axis); - save($tensors); - return res; - }; - var inputs = $tensors; - var attr = { axis: axis }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Concat, attr); - } - var concat = op({ concat_: concat_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var splitVGradConfig = { - kernelName: SplitV, - gradFunc: function (dy, saved, attrs) { - var axis = attrs.axis; - return { x: function () { return concat(dy, axis); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var sqrtGradConfig = { - kernelName: Sqrt, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, mul(sqrt(cast(x, 'float32')), 2)); } }; - } - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var squareGradConfig = { - kernelName: Square, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(dy, mul(x.toFloat(), 2)); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var squaredDifferenceGradConfig = { - kernelName: SquaredDifference, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var two = scalar(2); - var derA = function () { return mul(dy, mul(two, sub(a, b))); }; - var derB = function () { return mul(dy, mul(two, sub(b, a))); }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var stepGradConfig = { - kernelName: Step, - gradFunc: function (dy) { - // TODO(manrajgrover): Return null for gradients when backprop supports - // it. - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var subGradConfig = { - kernelName: Sub, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var outShape = assertAndGetBroadcastShape(a.shape, b.shape); - var derA = function () { - var res = dy; - var reduceAxes = getReductionAxes(a.shape, outShape); - if (reduceAxes.length > 0) { - res = sum$1(res, reduceAxes); - } - return reshape(res, a.shape); - }; - var derB = function () { - var res = dy; - var reduceAxes = getReductionAxes(b.shape, outShape); - if (reduceAxes.length > 0) { - res = sum$1(res, reduceAxes); - } - return reshape(neg(res), b.shape); - }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates a `tf.Tensor` with all elements set to 1. - * - * ```js - * tf.ones([2, 2]).print(); - * ``` - * - * @param shape An array of integers defining the output tensor shape. - * @param dtype The type of an element in the resulting tensor. Defaults to - * 'float'. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function ones$1(shape, dtype) { - if (dtype === void 0) { dtype = 'float32'; } - if (dtype === 'complex64') { - var real = ones$1(shape, 'float32'); - var imag = zeros(shape, 'float32'); - return complex(real, imag); - } - var values = makeOnesTypedArray(sizeFromShape(shape), dtype); - return ENGINE.makeTensor(values, shape, dtype); - } - - /** - * @license - * Copyright 2020 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var sumGradConfig = { - kernelName: Sum, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0]; - var expandedDyShape = x.shape.slice(); - var axis = attrs.axis; - var axes = parseAxisParam(axis, x.shape); - axes.forEach(function (axis) { - expandedDyShape[axis] = 1; - }); - var expandedDy = reshape(dy, expandedDyShape); - var derX = mul(expandedDy, ones$1(x.shape, 'float32')); - return { x: function () { return derX; } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var tanGradConfig = { - kernelName: Tan, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, square(cos(x))); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var tanhGradConfig = { - kernelName: Tanh, - outputsToSave: [true], - gradFunc: function (dy, saved) { - var y = saved[0]; - return { x: function () { return mul(sub(scalar(1), square(y)), dy); } }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Extracts a slice from a `tf.Tensor` starting at coordinates `begin` - * and is of size `size`. - * - * Also available are stricter rank-specific methods with the same signature - * as this method that assert that `x` is of the given rank: - * - `tf.slice1d` - * - `tf.slice2d` - * - `tf.slice3d` - * - `tf.slice4d` - * - * ```js - * const x = tf.tensor1d([1, 2, 3, 4]); - * - * x.slice([1], [2]).print(); - * ``` - * - * ```js - * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); - * - * x.slice([1, 0], [1, 2]).print(); - * ``` - * @param x The input `tf.Tensor` to slice from. - * @param begin The coordinates to start the slice from. The length can be - * less than the rank of x - the rest of the axes will have implicit 0 as - * start. Can also be a single number, in which case it specifies the - * first axis. - * @param size The size of the slice. The length can be less than the rank of - * x - the rest of the axes will have implicit -1. A value of -1 requests - * the rest of the dimensions in the axis. Can also be a single number, - * in which case it specifies the size of the first axis. - */ - /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ - function slice_(x, begin, size) { - var $x = convertToTensor(x, 'x', 'slice'); - if ($x.rank === 0) { - throw new Error('Slicing scalar is not possible'); - } - var _a = parseSliceParams($x, begin, size), begin_ = _a[0], size_ = _a[1]; - assertParamsValid($x, begin_, size_); - var forward = function (backend, save) { - save([$x]); - return backend.slice($x, begin_, size_); - }; - var inputs = { x: $x }; - var attrs = { begin: begin, size: size }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Slice, attrs); - } - var slice = op({ slice_: slice_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var tileGradConfig = { - kernelName: Tile, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0]; - var reps = attrs.reps; - var derX = function () { - var xGrad = zerosLike(x); - // TODO(cais): Maybe reduce memory footprint by avoiding repeated - // slicing. - if (x.rank === 1) { - for (var i = 0; i < reps[0]; ++i) { - xGrad = add(xGrad, slice(dy, [i * x.shape[0]], [x.shape[0]])); - } - } - else if (x.rank === 2) { - for (var i = 0; i < reps[0]; ++i) { - for (var j = 0; j < reps[1]; ++j) { - xGrad = add(xGrad, slice(dy, [i * x.shape[0], j * x.shape[1]], [ - x.shape[0], x.shape[1] - ])); - } - } - } - else if (x.rank === 3) { - for (var i = 0; i < reps[0]; ++i) { - for (var j = 0; j < reps[1]; ++j) { - for (var k = 0; k < reps[2]; ++k) { - xGrad = - add(xGrad, slice(dy, [i * x.shape[0], j * x.shape[1], k * x.shape[2]], [x.shape[0], x.shape[1], x.shape[2]])); - } - } - } - } - else if (x.rank === 4) { - for (var i = 0; i < reps[0]; ++i) { - for (var j = 0; j < reps[1]; ++j) { - for (var k = 0; k < reps[2]; ++k) { - for (var l = 0; l < reps[3]; ++l) { - xGrad = - add(xGrad, slice(dy, [ - i * x.shape[0], j * x.shape[1], k * x.shape[2], - l * x.shape[3] - ], [x.shape[0], x.shape[1], x.shape[2], x.shape[3]])); - } - } - } - } - } - else { - throw new Error("Gradient for tile operation is not implemented for rank-" + - (x.rank + " tensors yet.")); - } - return xGrad; - }; - return { x: derX }; - }, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var transposeGradConfig = { - kernelName: Transpose, - gradFunc: function (dy, saved, attrs) { - var transposeAttrs = attrs; - var perm = transposeAttrs.perm; - var undoPerm = getUndoAxesPermutation(perm); - return { x: function () { return transpose(dy, undoPerm); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns a `tf.Tensor` that has expanded rank, by inserting a dimension - * into the tensor's shape. - * - * ```js - * const x = tf.tensor1d([1, 2, 3, 4]); - * const axis = 1; - * x.expandDims(axis).print(); - * ``` - * - * @param x The input tensor whose dimensions to be expanded. - * @param axis The dimension index at which to insert shape of `1`. Defaults - * to 0 (the first dimension). - */ - /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ - function expandDims_(x, axis) { - if (axis === void 0) { axis = 0; } - var parseAs = null; - var $x = convertToTensor(x, 'x', 'expandDims', parseAs); - assert(axis <= $x.rank, function () { return 'Axis must be <= rank of the tensor'; }); - var newShape = $x.shape.slice(); - if (axis < 0) { - // Negative value is counted from the tail of rank. - assert(-($x.rank + 1) <= axis, function () { return "Axis must be in the interval [" + -($x.rank + 1) + ", " + $x.rank + "]"; }); - axis = $x.rank + axis + 1; - } - newShape.splice(axis, 0, 1); - return reshape($x, newShape); - } - var expandDims = op({ expandDims_: expandDims_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Stacks a list of rank-`R` `tf.Tensor`s into one rank-`(R+1)` `tf.Tensor`. - * - * ```js - * const a = tf.tensor1d([1, 2]); - * const b = tf.tensor1d([3, 4]); - * const c = tf.tensor1d([5, 6]); - * tf.stack([a, b, c]).print(); - * ``` - * - * @param tensors A list of tensor objects with the same shape and dtype. - * @param axis The axis to stack along. Defaults to 0 (the first dim). - */ - /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ - function stack_(tensors, axis) { - if (axis === void 0) { axis = 0; } - var $tensors = convertToTensorArray(tensors, 'tensors', 'stack'); - assert($tensors.length >= 1, function () { return 'Pass at least one tensor to tf.stack'; }); - if ($tensors.length === 1) { - return expandDims($tensors[0], axis); - } - var rank = $tensors[0].rank; - var shape = $tensors[0].shape; - var dtype = $tensors[0].dtype; - assert(axis <= rank, function () { return 'Axis must be <= rank of the tensor'; }); - $tensors.forEach(function (t) { - assertShapesMatch(shape, t.shape, 'All tensors passed to stack must have matching shapes'); - assert(dtype === t.dtype, function () { return 'All tensors passed to stack must have matching dtypes'; }); - }); - var expandedTensors = $tensors.map(function (t) { return expandDims(t, axis); }); - // Stack exists in the TensorFlow C++ API - // (https://www.tensorflow.org/api_docs/cc/class/tensorflow/ops/stack) but not - // in - // https://raw.githubusercontent.com/tensorflow/tensorflow/master/tensorflow/core/ops/ops.pbtxt. - // Therefore we are treating it like a high-level op rather than - // creating a dedicated stack kernel. - return concat(expandedTensors, axis); - } - var stack = op({ stack_: stack_ }); - - /** - * @license - * Copyright 2020 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var unpackGradConfig = { - kernelName: Unpack, - gradFunc: function (dy, saved, attrs) { - var unpackAttrs = attrs; - var axis = unpackAttrs.axis; - return { value: function () { return stack(dy, axis); } }; - } - }; - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var PARALLELIZE_THRESHOLD = 30; - function computeOptimalWindowSize(inSize) { - if (inSize <= PARALLELIZE_THRESHOLD) { - return inSize; - } - return nearestDivisor(inSize, Math.floor(Math.sqrt(inSize))); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function segOpComputeOptimalWindowSize(inSize, numSegments) { - var done = false; - var res; - if (inSize <= PARALLELIZE_THRESHOLD) { - res = inSize; - done = true; - } - else { - res = nearestDivisor(inSize, Math.floor(Math.sqrt(inSize))); - } - while (!done) { - if (res > numSegments || res === inSize) { - done = true; - } - else { - res = nearestDivisor(inSize, res + 1); - } - } - return res; - } - function computeOutShape$2(aShape, axis, numSegments) { - var outShape = []; - var rank = aShape.length; - for (var dim = 0; dim < rank; dim++) { - if (dim !== axis) { - outShape.push(aShape[dim]); - } - else { - outShape.push(numSegments); - } - } - return outShape; - } - function collectGatherOpShapeInfo(x, indices, axis) { - var dimSize = x.shape[axis]; - var outputShape = []; - var batchSize = 1; - var sliceSize = 1; - for (var i = 0; i < axis; i++) { - outputShape.push(x.shape[i]); - batchSize *= x.shape[i]; - } - for (var i = 0; i < indices.rank; i++) { - outputShape.push(indices.shape[i]); - } - for (var i = axis + 1; i < x.rank; i++) { - outputShape.push(x.shape[i]); - sliceSize *= x.shape[i]; - } - return { batchSize: batchSize, sliceSize: sliceSize, dimSize: dimSize, outputShape: outputShape }; - } - - var segment_util = { - __proto__: null, - segOpComputeOptimalWindowSize: segOpComputeOptimalWindowSize, - computeOutShape: computeOutShape$2, - collectGatherOpShapeInfo: collectGatherOpShapeInfo - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Gather slices from tensor `x`'s axis `axis` according to `indices`. - * - * ```js - * const x = tf.tensor1d([1, 2, 3, 4]); - * const indices = tf.tensor1d([1, 3, 3], 'int32'); - * - * x.gather(indices).print(); - * ``` - * - * ```js - * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); - * const indices = tf.tensor1d([1, 1, 0], 'int32'); - * - * x.gather(indices).print(); - * ``` - * @param x The input tensor whose slices to be gathered. - * @param indices The indices of the values to extract. - * @param axis The axis over which to select values. Defaults to 0. - */ - /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ - function gather_(x, indices, axis) { - if (axis === void 0) { axis = 0; } - var $x = convertToTensor(x, 'x', 'gather'); - var $indices = convertToTensor(indices, 'indices', 'gather', 'int32'); - var inputs = { x: $x, indices: $indices }; - var attrs = { axis: axis }; - var forward = function (backend, save) { - var parsedAxis = parseAxisParam(axis, $x.shape)[0]; - var shapeInfo = collectGatherOpShapeInfo($x, $indices, parsedAxis); - var res = backend.gather($x, $indices.flatten(), parsedAxis); - save([$x, $indices]); - return res.reshape(shapeInfo.outputShape); - }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, GatherV2, attrs); - } - var gather = op({ gather_: gather_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the max of a and b (`a > b ? a : b`) element-wise. - * Supports broadcasting. - * - * We also expose `tf.maximumStrict` which has the same signature as this op and - * asserts that `a` and `b` are the same shape (does not broadcast). - * - * ```js - * const a = tf.tensor1d([1, 4, 3, 16]); - * const b = tf.tensor1d([1, 2, 9, 4]); - * - * a.maximum(b).print(); // or tf.maximum(a, b) - * ``` - * - * ```js - * // Broadcast maximum a with b. - * const a = tf.tensor1d([2, 4, 6, 8]); - * const b = tf.scalar(5); - * - * a.maximum(b).print(); // or tf.maximum(a, b) - * ``` - * - * @param a The first tensor. - * @param b The second tensor. Must have the same type as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ - function maximum_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'maximum'); - var $b = convertToTensor(b, 'b', 'maximum'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - if ($a.dtype === 'bool') { - $a = cast($a, 'int32'); - $b = cast($b, 'int32'); - } - assertAndGetBroadcastShape($a.shape, $b.shape); - var forward = function (backend, save) { - var res = backend.maximum($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Maximum); - } - var maximum = op({ maximum_: maximum_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var unsortedSegmentSumGradConfig = { - kernelName: UnsortedSegmentSum, - inputsToSave: ['segmentIds'], - gradFunc: function (dy, saved) { - var segmentIds = saved[0]; - var derX = function () { - return gatherDropNegatives(dy, segmentIds); - }; - return { x: derX }; - } - }; - function gatherDropNegatives(x, indices) { - // Helper function for unsorted segment ops. Gathers params for - // positive segment ids and gathers 0 for inputs with negative segment id. - // Mirrors _GatherDropNegatives from tensorflow/python/ops/math_grad.py - var zeroClippedIndices = maximum(indices, zerosLike(indices)); - var gathered = gather(x, zeroClippedIndices); - var isPositive = greaterEqual(indices, scalar(0, 'int32')); - var numIters = gathered.rank - isPositive.rank; - for (var i = 0; i < numIters; ++i) { - isPositive = expandDims(isPositive, i + 1); - } - isPositive = logicalAnd(isPositive, ones$1(gathered.shape, 'bool')); - var zeroSlice = zerosLike(gathered); - return where(isPositive, gathered, zeroSlice); - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var zerosLikeGradConfig = { - kernelName: ZerosLike, - gradFunc: function (dy) { - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // Export all kernel configs here so that the package can auto register them - var gradConfigs = [ - absGradConfig, - acosGradConfig, - acoshGradConfig, - addGradConfig, - addNGradConfig, - argMaxGradConfig, - argMinGradConfig, - asinGradConfig, - asinhGradConfig, - atan2GradConfig, - atanGradConfig, - atanhGradConfig, - avgPool3DGradConfig, - avgPoolGradConfig, - batchMatMulGradConfig, - batchToSpaceNDGradConfig, - broadcastToGradConfig, - castGradConfig, - ceilGradConfig, - clipByValueGradConfig, - concatGradConfig, - conv2DBackpropInputGradConfig, - conv2DGradConfig, - conv3DGradConfig, - cosGradConfig, - coshGradConfig, - cumsumGradConfig, - depthwiseConv2dNativeGradConfig, - dilation2dGradConfig, - divGradConfig, - eluGradConfig, - erfGradConfig, - expGradConfig, - expm1GradConfig, - floorDivGradConfig, - floorGradConfig, - fusedBatchNormGradConfig, - gatherGradConfig, - greaterEqualGradConfig, - identityGradConfig, - isFiniteGradConfig, - isInfGradConfig, - isNanGradConfig, - log1pGradConfig, - logGradConfig, - logSoftmaxGradConfig, - lrnGradConfig, - maxGradConfig, - maxGradConfig, - maximumGradConfig, - maxPool3DGradConfig, - maxPoolGradConfig, - minGradConfig, - minimumGradConfig, - modGradConfig, - multiplyGradConfig, - negateGradConfig, - oneHotGradConfig, - onesLikeGradConfig, - padV2GradConfig, - padV2GradConfig, - powGradConfig, - preluGradConfig, - reciprocalGradConfig, - relu6GradConfig, - reluGradConfig, - reshapeGradConfig, - resizeBilinearGradConfig, - resizeNearestNeighborGradConfig, - reverseGradConfig, - roundGradConfig, - rsqrtGradConfig, - selectV2PoolGradConfig, - seluGradConfig, - sigmoidGradConfig, - signGradConfig, - sinGradConfig, - sinhGradConfig, - sliceGradConfig, - softmaxGradConfig, - softplusGradConfig, - spaceToBatchNDGradConfig, - spaceToBatchNDGradConfig, - splitVGradConfig, - splitVGradConfig, - sqrtGradConfig, - squaredDifferenceGradConfig, - squareGradConfig, - stepGradConfig, - subGradConfig, - sumGradConfig, - tanGradConfig, - tanhGradConfig, - tileGradConfig, - transposeGradConfig, - unpackGradConfig, - unsortedSegmentSumGradConfig, - zerosLikeGradConfig - ]; - for (var _i = 0, gradConfigs_1 = gradConfigs; _i < gradConfigs_1.length; _i++) { - var gradientConfig = gradConfigs_1[_i]; - registerGradient(gradientConfig); - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var PlatformBrowser = /** @class */ (function () { - function PlatformBrowser() { - } - PlatformBrowser.prototype.fetch = function (path, init) { - return fetch(path, init); - }; - PlatformBrowser.prototype.now = function () { - return performance.now(); - }; - PlatformBrowser.prototype.encode = function (text, encoding) { - if (encoding !== 'utf-8' && encoding !== 'utf8') { - throw new Error("Browser's encoder only supports utf-8, but got " + encoding); - } - if (this.textEncoder == null) { - this.textEncoder = new TextEncoder(); - } - return this.textEncoder.encode(text); - }; - PlatformBrowser.prototype.decode = function (bytes, encoding) { - return new TextDecoder(encoding).decode(bytes); - }; - return PlatformBrowser; - }()); - if (env().get('IS_BROWSER')) { - env().setPlatform('browser', new PlatformBrowser()); - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // We are wrapping this within an object so it can be stubbed by Jasmine. - var getNodeFetch = { - // tslint:disable-next-line:no-require-imports - importFetch: function () { return require('node-fetch'); } - }; - var systemFetch; - var PlatformNode = /** @class */ (function () { - function PlatformNode() { - // tslint:disable-next-line:no-require-imports - this.util = require('util'); - // According to the spec, the built-in encoder can do only UTF-8 encoding. - // https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder/TextEncoder - this.textEncoder = new this.util.TextEncoder(); - } - PlatformNode.prototype.fetch = function (path, requestInits) { - if (env().global.fetch != null) { - return env().global.fetch(path, requestInits); - } - if (systemFetch == null) { - systemFetch = getNodeFetch.importFetch(); - } - return systemFetch(path, requestInits); - }; - PlatformNode.prototype.now = function () { - var time = process.hrtime(); - return time[0] * 1000 + time[1] / 1000000; - }; - PlatformNode.prototype.encode = function (text, encoding) { - if (encoding !== 'utf-8' && encoding !== 'utf8') { - throw new Error("Node built-in encoder only supports utf-8, but got " + encoding); - } - return this.textEncoder.encode(text); - }; - PlatformNode.prototype.decode = function (bytes, encoding) { - if (bytes.length === 0) { - return ''; - } - return new this.util.TextDecoder(encoding).decode(bytes); - }; - return PlatformNode; - }()); - if (env().get('IS_NODE')) { - env().setPlatform('node', new PlatformNode()); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /* Type definitions for exporting and importing of models. */ - /** - * A map from Tensor dtype to number of bytes per element of the Tensor. - */ - var DTYPE_VALUE_SIZE_MAP = { - 'float32': 4, - 'float16': 2, - 'int32': 4, - 'uint16': 2, - 'uint8': 1, - 'bool': 1, - 'complex64': 8 - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** Number of bytes reserved for the length of the string. (32bit integer). */ - var NUM_BYTES_STRING_LENGTH = 4; - /** - * Encode a map from names to weight values as an ArrayBuffer, along with an - * `Array` of `WeightsManifestEntry` as specification of the encoded weights. - * - * This function does not perform sharding. - * - * This function is the reverse of `decodeWeights`. - * - * @param tensors A map ("dict") from names to tensors. - * @param group Group to which the weights belong (optional). - * @returns A `Promise` of - * - A flat `ArrayBuffer` with all the binary values of the `Tensor`s - * concatenated. - * - An `Array` of `WeightManifestEntry`s, carrying information including - * tensor names, `dtype`s and shapes. - * @throws Error: on unsupported tensor `dtype`. - */ - function encodeWeights(tensors, group) { - return __awaiter(this, void 0, void 0, function () { - var specs, dataPromises, names, _loop_1, i, tensorValues; - var _this = this; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - specs = []; - dataPromises = []; - names = Array.isArray(tensors) ? - tensors.map(function (tensor) { return tensor.name; }) : - Object.keys(tensors); - _loop_1 = function (i) { - var name_1 = names[i]; - var t = Array.isArray(tensors) ? tensors[i].tensor : tensors[name_1]; - if (t.dtype !== 'float32' && t.dtype !== 'int32' && t.dtype !== 'bool' && - t.dtype !== 'string' && t.dtype !== 'complex64') { - throw new Error("Unsupported dtype in weight '" + name_1 + "': " + t.dtype); - } - var spec = { name: name_1, shape: t.shape, dtype: t.dtype }; - if (t.dtype === 'string') { - var utf8bytes = new Promise(function (resolve) { return __awaiter(_this, void 0, void 0, function () { - var vals, totalNumBytes, bytes, offset, i_1, val, bytesOfLength; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, t.bytes()]; - case 1: - vals = _a.sent(); - totalNumBytes = vals.reduce(function (p, c) { return p + c.length; }, 0) + - NUM_BYTES_STRING_LENGTH * vals.length; - bytes = new Uint8Array(totalNumBytes); - offset = 0; - for (i_1 = 0; i_1 < vals.length; i_1++) { - val = vals[i_1]; - bytesOfLength = new Uint8Array(new Uint32Array([val.length]).buffer); - bytes.set(bytesOfLength, offset); - offset += NUM_BYTES_STRING_LENGTH; - bytes.set(val, offset); - offset += val.length; - } - resolve(bytes); - return [2 /*return*/]; - } - }); - }); }); - dataPromises.push(utf8bytes); - } - else { - dataPromises.push(t.data()); - } - if (group != null) { - spec.group = group; - } - specs.push(spec); - }; - for (i = 0; i < names.length; ++i) { - _loop_1(i); - } - return [4 /*yield*/, Promise.all(dataPromises)]; - case 1: - tensorValues = _a.sent(); - return [2 /*return*/, { data: concatenateTypedArrays(tensorValues), specs: specs }]; - } - }); - }); - } - /** - * Decode flat ArrayBuffer as weights. - * - * This function does not handle sharding. - * - * This function is the reverse of `encodeWeights`. - * - * @param buffer A flat ArrayBuffer carrying the binary values of the tensors - * concatenated in the order specified in `specs`. - * @param specs Specifications of the names, dtypes and shapes of the tensors - * whose value are encoded by `buffer`. - * @return A map from tensor name to tensor value, with the names corresponding - * to names in `specs`. - * @throws Error, if any of the tensors has unsupported dtype. - */ - function decodeWeights(buffer, specs) { - // TODO(adarob, cais): Support quantization. - var out = {}; - var float16Decode; - var offset = 0; - for (var _i = 0, specs_1 = specs; _i < specs_1.length; _i++) { - var spec = specs_1[_i]; - var name_2 = spec.name; - var dtype = spec.dtype; - var shape = spec.shape; - var size = sizeFromShape(shape); - var values = void 0; - if ('quantization' in spec) { - var quantization = spec.quantization; - if (quantization.dtype === 'uint8' || quantization.dtype === 'uint16') { - if (!('min' in quantization && 'scale' in quantization)) { - throw new Error("Weight " + spec.name + " with quantization " + quantization.dtype + " " + - "doesn't have corresponding metadata min and scale."); - } - } - else if (quantization.dtype === 'float16') { - if (dtype !== 'float32') { - throw new Error("Weight " + spec.name + " is quantized with " + quantization.dtype + " " + - ("which only supports weights of type float32 not " + dtype + ".")); - } - } - else { - throw new Error("Weight " + spec.name + " has unknown " + - ("quantization dtype " + quantization.dtype + ". ") + - "Supported quantization dtypes are: " + - "'uint8', 'uint16', and 'float16'."); - } - var quantizationSizeFactor = DTYPE_VALUE_SIZE_MAP[quantization.dtype]; - var byteBuffer = buffer.slice(offset, offset + size * quantizationSizeFactor); - var quantizedArray = (quantization.dtype === 'uint8') ? - new Uint8Array(byteBuffer) : - new Uint16Array(byteBuffer); - if (dtype === 'float32') { - if (quantization.dtype === 'uint8' || quantization.dtype === 'uint16') { - values = new Float32Array(quantizedArray.length); - for (var i = 0; i < quantizedArray.length; i++) { - var v = quantizedArray[i]; - values[i] = v * quantization.scale + quantization.min; - } - } - else if (quantization.dtype === 'float16') { - if (float16Decode === undefined) { - float16Decode = getFloat16Decoder(); - } - values = float16Decode(quantizedArray); - } - else { - throw new Error("Unsupported quantization type " + quantization.dtype + " " + - "for weight type float32."); - } - } - else if (dtype === 'int32') { - if (quantization.dtype !== 'uint8' && quantization.dtype !== 'uint16') { - throw new Error("Unsupported quantization type " + quantization.dtype + " " + - "for weight type int32."); - } - values = new Int32Array(quantizedArray.length); - for (var i = 0; i < quantizedArray.length; i++) { - var v = quantizedArray[i]; - values[i] = Math.round(v * quantization.scale + quantization.min); - } - } - else { - throw new Error("Unsupported dtype in weight '" + name_2 + "': " + dtype); - } - offset += size * quantizationSizeFactor; - } - else if (dtype === 'string') { - var size_1 = sizeFromShape(spec.shape); - values = []; - for (var i = 0; i < size_1; i++) { - var byteLength = new Uint32Array(buffer.slice(offset, offset + NUM_BYTES_STRING_LENGTH))[0]; - offset += NUM_BYTES_STRING_LENGTH; - var bytes = new Uint8Array(buffer.slice(offset, offset + byteLength)); - values.push(bytes); - offset += byteLength; - } - } - else { - var dtypeFactor = DTYPE_VALUE_SIZE_MAP[dtype]; - var byteBuffer = buffer.slice(offset, offset + size * dtypeFactor); - if (dtype === 'float32') { - values = new Float32Array(byteBuffer); - } - else if (dtype === 'int32') { - values = new Int32Array(byteBuffer); - } - else if (dtype === 'bool') { - values = new Uint8Array(byteBuffer); - } - else if (dtype === 'complex64') { - values = new Float32Array(byteBuffer); - var real = new Float32Array(values.length / 2); - var image = new Float32Array(values.length / 2); - for (var i = 0; i < real.length; i++) { - real[i] = values[i * 2]; - image[i] = values[i * 2 + 1]; - } - var realTensor = tensor(real, shape, 'float32'); - var imageTensor = tensor(image, shape, 'float32'); - out[name_2] = complex(realTensor, imageTensor); - } - else { - throw new Error("Unsupported dtype in weight '" + name_2 + "': " + dtype); - } - offset += size * dtypeFactor; - } - if (dtype !== 'complex64') { - out[name_2] = tensor(values, shape, dtype); - } - } - return out; - } - /** - * Concatenate TypedArrays into an ArrayBuffer. - */ - function concatenateTypedArrays(xs) { - // TODO(adarob, cais): Support quantization. - if (xs === null) { - throw new Error("Invalid input value: " + JSON.stringify(xs)); - } - var totalByteLength = 0; - // `normalizedXs` is here for this reason: a `TypedArray`'s `buffer' - // can have a different byte length from that of the `TypedArray` itself, - // for example, when the `TypedArray` is created from an offset in an - // `ArrayBuffer`. `normliazedXs` holds `TypedArray`s whose `buffer`s match - // the `TypedArray` in byte length. If an element of `xs` does not show - // this property, a new `TypedArray` that satisfy this property will be - // constructed and pushed into `normalizedXs`. - var normalizedXs = []; - xs.forEach(function (x) { - totalByteLength += x.byteLength; - // tslint:disable:no-any - normalizedXs.push(x.byteLength === x.buffer.byteLength ? x : - new x.constructor(x)); - if (!(x instanceof Float32Array || x instanceof Int32Array || - x instanceof Uint8Array)) { - throw new Error("Unsupported TypedArray subtype: " + x.constructor.name); - } - // tslint:enable:no-any - }); - var y = new Uint8Array(totalByteLength); - var offset = 0; - normalizedXs.forEach(function (x) { - y.set(new Uint8Array(x.buffer), offset); - offset += x.byteLength; - }); - return y.buffer; - } - // Use Buffer on Node.js instead of Blob/atob/btoa - var useNodeBuffer = typeof Buffer !== 'undefined' && - (typeof Blob === 'undefined' || typeof atob === 'undefined' || - typeof btoa === 'undefined'); - /** - * Calculate the byte length of a JavaScript string. - * - * Note that a JavaScript string can contain wide characters, therefore the - * length of the string is not necessarily equal to the byte length. - * - * @param str Input string. - * @returns Byte length. - */ - function stringByteLength(str) { - if (useNodeBuffer) { - return Buffer.byteLength(str); - } - return new Blob([str]).size; - } - /** - * Encode an ArrayBuffer as a base64 encoded string. - * - * @param buffer `ArrayBuffer` to be converted. - * @returns A string that base64-encodes `buffer`. - */ - function arrayBufferToBase64String(buffer) { - if (useNodeBuffer) { - return Buffer.from(buffer).toString('base64'); - } - var buf = new Uint8Array(buffer); - var s = ''; - for (var i = 0, l = buf.length; i < l; i++) { - s += String.fromCharCode(buf[i]); - } - return btoa(s); - } - /** - * Decode a base64 string as an ArrayBuffer. - * - * @param str Base64 string. - * @returns Decoded `ArrayBuffer`. - */ - function base64StringToArrayBuffer(str) { - if (useNodeBuffer) { - var buf = Buffer.from(str, 'base64'); - return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); - } - var s = atob(str); - var buffer = new Uint8Array(s.length); - for (var i = 0; i < s.length; ++i) { - buffer.set([s.charCodeAt(i)], i); - } - return buffer.buffer; - } - /** - * Concatenate a number of ArrayBuffers into one. - * - * @param buffers A number of array buffers to concatenate. - * @returns Result of concatenating `buffers` in order. - */ - function concatenateArrayBuffers(buffers) { - if (buffers.length === 1) { - return buffers[0]; - } - var totalByteLength = 0; - buffers.forEach(function (buffer) { - totalByteLength += buffer.byteLength; - }); - var temp = new Uint8Array(totalByteLength); - var offset = 0; - buffers.forEach(function (buffer) { - temp.set(new Uint8Array(buffer), offset); - offset += buffer.byteLength; - }); - return temp.buffer; - } - /** - * Get the basename of a path. - * - * Behaves in a way analogous to Linux's basename command. - * - * @param path - */ - function basename(path) { - var SEPARATOR = '/'; - path = path.trim(); - while (path.endsWith(SEPARATOR)) { - path = path.slice(0, path.length - 1); - } - var items = path.split(SEPARATOR); - return items[items.length - 1]; - } - /** - * Populate ModelArtifactsInfo fields for a model with JSON topology. - * @param modelArtifacts - * @returns A ModelArtifactsInfo object. - */ - function getModelArtifactsInfoForJSON(modelArtifacts) { - if (modelArtifacts.modelTopology instanceof ArrayBuffer) { - throw new Error('Expected JSON model topology, received ArrayBuffer.'); - } - return { - dateSaved: new Date(), - modelTopologyType: 'JSON', - modelTopologyBytes: modelArtifacts.modelTopology == null ? - 0 : - stringByteLength(JSON.stringify(modelArtifacts.modelTopology)), - weightSpecsBytes: modelArtifacts.weightSpecs == null ? - 0 : - stringByteLength(JSON.stringify(modelArtifacts.weightSpecs)), - weightDataBytes: modelArtifacts.weightData == null ? - 0 : - modelArtifacts.weightData.byteLength, - }; - } - /** - * Computes mantisa table for casting Float16 to Float32 - * See http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf - * - * @returns Uint32Array, 2048 mantissa lookup values. - */ - function computeFloat16MantisaTable() { - var convertMantissa = function (i) { - var m = i << 13; - var e = 0; - while ((m & 0x00800000) === 0) { - e -= 0x00800000; - m <<= 1; - } - m &= ~0x00800000; - e += 0x38800000; - return m | e; - }; - var mantisaTable = new Uint32Array(2048); - mantisaTable[0] = 0; - for (var i = 1; i < 1024; i++) { - mantisaTable[i] = convertMantissa(i); - } - for (var i = 1024; i < 2048; i++) { - mantisaTable[i] = 0x38000000 + ((i - 1024) << 13); - } - return mantisaTable; - } - /** - * Computes exponent table for casting Float16 to Float32 - * See http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf - * - * @returns Uint32Array, 64 exponent lookup values. - */ - function computeFloat16ExponentTable() { - var exponentTable = new Uint32Array(64); - exponentTable[0] = 0; - exponentTable[31] = 0x47800000; - exponentTable[32] = 0x80000000; - exponentTable[63] = 0xc7800000; - for (var i = 1; i < 31; i++) { - exponentTable[i] = i << 23; - } - for (var i = 33; i < 63; i++) { - exponentTable[i] = 0x80000000 + ((i - 32) << 23); - } - return exponentTable; - } - /** - * Computes offset table for casting Float16 to Float32 - * See http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf - * - * @returns Uint32Array, 6d offset values. - */ - function computeFloat16OffsetTable() { - var offsetTable = new Uint32Array(64); - for (var i = 0; i < 64; i++) { - offsetTable[i] = 1024; - } - offsetTable[0] = offsetTable[32] = 0; - return offsetTable; - } - /** - * Retrieve a Float16 decoder which will decode a ByteArray of Float16 values - * to a Float32Array. - * - * @returns Function (buffer: Uint16Array) => Float32Array which decodes - * the Uint16Array of Float16 bytes to a Float32Array. - */ - function getFloat16Decoder() { - // Algorithm is based off of - // http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf - // Cache lookup tables - var mantisaTable = computeFloat16MantisaTable(); - var exponentTable = computeFloat16ExponentTable(); - var offsetTable = computeFloat16OffsetTable(); - return function (quantizedArray) { - var buffer = new ArrayBuffer(4 * quantizedArray.length); - var bufferUint32View = new Uint32Array(buffer); - for (var index = 0; index < quantizedArray.length; index++) { - var float16Bits = quantizedArray[index]; - var float32Bits = mantisaTable[offsetTable[float16Bits >> 10] + (float16Bits & 0x3ff)] + - exponentTable[float16Bits >> 10]; - bufferUint32View[index] = float32Bits; - } - return new Float32Array(buffer); - }; - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var IORouterRegistry = /** @class */ (function () { - function IORouterRegistry() { - this.saveRouters = []; - this.loadRouters = []; - } - IORouterRegistry.getInstance = function () { - if (IORouterRegistry.instance == null) { - IORouterRegistry.instance = new IORouterRegistry(); - } - return IORouterRegistry.instance; - }; - /** - * Register a save-handler router. - * - * @param saveRouter A function that maps a URL-like string onto an instance - * of `IOHandler` with the `save` method defined or `null`. - */ - IORouterRegistry.registerSaveRouter = function (saveRouter) { - IORouterRegistry.getInstance().saveRouters.push(saveRouter); - }; - /** - * Register a load-handler router. - * - * @param loadRouter A function that maps a URL-like string onto an instance - * of `IOHandler` with the `load` method defined or `null`. - */ - IORouterRegistry.registerLoadRouter = function (loadRouter) { - IORouterRegistry.getInstance().loadRouters.push(loadRouter); - }; - /** - * Look up IOHandler for saving, given a URL-like string. - * - * @param url - * @returns If only one match is found, an instance of IOHandler with the - * `save` method defined. If no match is found, `null`. - * @throws Error, if more than one match is found. - */ - IORouterRegistry.getSaveHandlers = function (url) { - return IORouterRegistry.getHandlers(url, 'save'); - }; - /** - * Look up IOHandler for loading, given a URL-like string. - * - * @param url - * @param loadOptions Optional, custom load options. - * @returns All valid handlers for `url`, given the currently registered - * handler routers. - */ - IORouterRegistry.getLoadHandlers = function (url, loadOptions) { - return IORouterRegistry.getHandlers(url, 'load', loadOptions); - }; - IORouterRegistry.getHandlers = function (url, handlerType, loadOptions) { - var validHandlers = []; - var routers = handlerType === 'load' ? - IORouterRegistry.getInstance().loadRouters : - IORouterRegistry.getInstance().saveRouters; - routers.forEach(function (router) { - var handler = router(url, loadOptions); - if (handler !== null) { - validHandlers.push(handler); - } - }); - return validHandlers; - }; - return IORouterRegistry; - }()); - var registerSaveRouter = function (loudRouter) { - return IORouterRegistry.registerSaveRouter(loudRouter); - }; - var registerLoadRouter = function (loudRouter) { - return IORouterRegistry.registerLoadRouter(loudRouter); - }; - var getSaveHandlers = function (url) { - return IORouterRegistry.getSaveHandlers(url); - }; - var getLoadHandlers = function (url, loadOptions) { - return IORouterRegistry.getLoadHandlers(url, loadOptions); - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var URL_SCHEME_SUFFIX = '://'; - var ModelStoreManagerRegistry = /** @class */ (function () { - function ModelStoreManagerRegistry() { - this.managers = {}; - } - ModelStoreManagerRegistry.getInstance = function () { - if (ModelStoreManagerRegistry.instance == null) { - ModelStoreManagerRegistry.instance = new ModelStoreManagerRegistry(); - } - return ModelStoreManagerRegistry.instance; - }; - /** - * Register a save-handler router. - * - * @param saveRouter A function that maps a URL-like string onto an instance - * of `IOHandler` with the `save` method defined or `null`. - */ - ModelStoreManagerRegistry.registerManager = function (scheme, manager) { - assert(scheme != null, function () { return 'scheme must not be undefined or null.'; }); - if (scheme.endsWith(URL_SCHEME_SUFFIX)) { - scheme = scheme.slice(0, scheme.indexOf(URL_SCHEME_SUFFIX)); - } - assert(scheme.length > 0, function () { return 'scheme must not be an empty string.'; }); - var registry = ModelStoreManagerRegistry.getInstance(); - assert(registry.managers[scheme] == null, function () { return "A model store manager is already registered for scheme '" + scheme + "'."; }); - registry.managers[scheme] = manager; - }; - ModelStoreManagerRegistry.getManager = function (scheme) { - var manager = this.getInstance().managers[scheme]; - if (manager == null) { - throw new Error("Cannot find model manager for scheme '" + scheme + "'"); - } - return manager; - }; - ModelStoreManagerRegistry.getSchemes = function () { - return Object.keys(this.getInstance().managers); - }; - return ModelStoreManagerRegistry; - }()); - /** - * Helper method for parsing a URL string into a scheme and a path. - * - * @param url E.g., 'localstorage://my-model' - * @returns A dictionary with two fields: scheme and path. - * Scheme: e.g., 'localstorage' in the example above. - * Path: e.g., 'my-model' in the example above. - */ - function parseURL(url) { - if (url.indexOf(URL_SCHEME_SUFFIX) === -1) { - throw new Error("The url string provided does not contain a scheme. " + - "Supported schemes are: " + - ("" + ModelStoreManagerRegistry.getSchemes().join(','))); - } - return { - scheme: url.split(URL_SCHEME_SUFFIX)[0], - path: url.split(URL_SCHEME_SUFFIX)[1], - }; - } - function cloneModelInternal(sourceURL, destURL, deleteSource) { - if (deleteSource === void 0) { deleteSource = false; } - return __awaiter(this, void 0, void 0, function () { - var loadHandlers, loadHandler, saveHandlers, saveHandler, sourceScheme, sourcePath, sameMedium, modelArtifacts, saveResult; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - assert(sourceURL !== destURL, function () { return "Old path and new path are the same: '" + sourceURL + "'"; }); - loadHandlers = IORouterRegistry.getLoadHandlers(sourceURL); - assert(loadHandlers.length > 0, function () { return "Copying failed because no load handler is found for source URL " + sourceURL + "."; }); - assert(loadHandlers.length < 2, function () { return "Copying failed because more than one (" + loadHandlers.length + ") " + - ("load handlers for source URL " + sourceURL + "."); }); - loadHandler = loadHandlers[0]; - saveHandlers = IORouterRegistry.getSaveHandlers(destURL); - assert(saveHandlers.length > 0, function () { return "Copying failed because no save handler is found for destination " + - ("URL " + destURL + "."); }); - assert(saveHandlers.length < 2, function () { return "Copying failed because more than one (" + loadHandlers.length + ") " + - ("save handlers for destination URL " + destURL + "."); }); - saveHandler = saveHandlers[0]; - sourceScheme = parseURL(sourceURL).scheme; - sourcePath = parseURL(sourceURL).path; - sameMedium = sourceScheme === parseURL(sourceURL).scheme; - return [4 /*yield*/, loadHandler.load()]; - case 1: - modelArtifacts = _a.sent(); - if (!(deleteSource && sameMedium)) return [3 /*break*/, 3]; - return [4 /*yield*/, ModelStoreManagerRegistry.getManager(sourceScheme) - .removeModel(sourcePath)]; - case 2: - _a.sent(); - _a.label = 3; - case 3: return [4 /*yield*/, saveHandler.save(modelArtifacts)]; - case 4: - saveResult = _a.sent(); - if (!(deleteSource && !sameMedium)) return [3 /*break*/, 6]; - return [4 /*yield*/, ModelStoreManagerRegistry.getManager(sourceScheme) - .removeModel(sourcePath)]; - case 5: - _a.sent(); - _a.label = 6; - case 6: return [2 /*return*/, saveResult.modelArtifactsInfo]; - } - }); - }); - } - /** - * List all models stored in registered storage mediums. - * - * For a web browser environment, the registered mediums are Local Storage and - * IndexedDB. - * - * ```js - * // First create and save a model. - * const model = tf.sequential(); - * model.add(tf.layers.dense( - * {units: 1, inputShape: [10], activation: 'sigmoid'})); - * await model.save('localstorage://demo/management/model1'); - * - * // Then list existing models. - * console.log(JSON.stringify(await tf.io.listModels())); - * - * // Delete the model. - * await tf.io.removeModel('localstorage://demo/management/model1'); - * - * // List models again. - * console.log(JSON.stringify(await tf.io.listModels())); - * ``` - * - * @returns A `Promise` of a dictionary mapping URLs of existing models to - * their model artifacts info. URLs include medium-specific schemes, e.g., - * 'indexeddb://my/model/1'. Model artifacts info include type of the - * model's topology, byte sizes of the topology, weights, etc. - */ - /** - * @doc { - * heading: 'Models', - * subheading: 'Management', - * namespace: 'io', - * ignoreCI: true - * } - */ - function listModels() { - return __awaiter(this, void 0, void 0, function () { - var schemes, out, _i, schemes_1, scheme, schemeOut, path, url; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - schemes = ModelStoreManagerRegistry.getSchemes(); - out = {}; - _i = 0, schemes_1 = schemes; - _a.label = 1; - case 1: - if (!(_i < schemes_1.length)) return [3 /*break*/, 4]; - scheme = schemes_1[_i]; - return [4 /*yield*/, ModelStoreManagerRegistry.getManager(scheme).listModels()]; - case 2: - schemeOut = _a.sent(); - for (path in schemeOut) { - url = scheme + URL_SCHEME_SUFFIX + path; - out[url] = schemeOut[path]; - } - _a.label = 3; - case 3: - _i++; - return [3 /*break*/, 1]; - case 4: return [2 /*return*/, out]; - } - }); - }); - } - /** - * Remove a model specified by URL from a reigstered storage medium. - * - * ```js - * // First create and save a model. - * const model = tf.sequential(); - * model.add(tf.layers.dense( - * {units: 1, inputShape: [10], activation: 'sigmoid'})); - * await model.save('localstorage://demo/management/model1'); - * - * // Then list existing models. - * console.log(JSON.stringify(await tf.io.listModels())); - * - * // Delete the model. - * await tf.io.removeModel('localstorage://demo/management/model1'); - * - * // List models again. - * console.log(JSON.stringify(await tf.io.listModels())); - * ``` - * - * @param url A URL to a stored model, with a scheme prefix, e.g., - * 'localstorage://my-model-1', 'indexeddb://my/model/2'. - * @returns ModelArtifactsInfo of the deleted model (if and only if deletion - * is successful). - * @throws Error if deletion fails, e.g., if no model exists at `path`. - */ - /** - * @doc { - * heading: 'Models', - * subheading: 'Management', - * namespace: 'io', - * ignoreCI: true - * } - */ - function removeModel(url) { - return __awaiter(this, void 0, void 0, function () { - var schemeAndPath, manager; - return __generator(this, function (_a) { - schemeAndPath = parseURL(url); - manager = ModelStoreManagerRegistry.getManager(schemeAndPath.scheme); - return [2 /*return*/, manager.removeModel(schemeAndPath.path)]; - }); - }); - } - /** - * Copy a model from one URL to another. - * - * This function supports: - * - * 1. Copying within a storage medium, e.g., - * `tf.io.copyModel('localstorage://model-1', 'localstorage://model-2')` - * 2. Copying between two storage mediums, e.g., - * `tf.io.copyModel('localstorage://model-1', 'indexeddb://model-1')` - * - * ```js - * // First create and save a model. - * const model = tf.sequential(); - * model.add(tf.layers.dense( - * {units: 1, inputShape: [10], activation: 'sigmoid'})); - * await model.save('localstorage://demo/management/model1'); - * - * // Then list existing models. - * console.log(JSON.stringify(await tf.io.listModels())); - * - * // Copy the model, from Local Storage to IndexedDB. - * await tf.io.copyModel( - * 'localstorage://demo/management/model1', - * 'indexeddb://demo/management/model1'); - * - * // List models again. - * console.log(JSON.stringify(await tf.io.listModels())); - * - * // Remove both models. - * await tf.io.removeModel('localstorage://demo/management/model1'); - * await tf.io.removeModel('indexeddb://demo/management/model1'); - * ``` - * - * @param sourceURL Source URL of copying. - * @param destURL Destination URL of copying. - * @returns ModelArtifactsInfo of the copied model (if and only if copying - * is successful). - * @throws Error if copying fails, e.g., if no model exists at `sourceURL`, or - * if `oldPath` and `newPath` are identical. - */ - /** - * @doc { - * heading: 'Models', - * subheading: 'Management', - * namespace: 'io', - * ignoreCI: true - * } - */ - function copyModel(sourceURL, destURL) { - return __awaiter(this, void 0, void 0, function () { - var deleteSource; - return __generator(this, function (_a) { - deleteSource = false; - return [2 /*return*/, cloneModelInternal(sourceURL, destURL, deleteSource)]; - }); - }); - } - /** - * Move a model from one URL to another. - * - * This function supports: - * - * 1. Moving within a storage medium, e.g., - * `tf.io.moveModel('localstorage://model-1', 'localstorage://model-2')` - * 2. Moving between two storage mediums, e.g., - * `tf.io.moveModel('localstorage://model-1', 'indexeddb://model-1')` - * - * ```js - * // First create and save a model. - * const model = tf.sequential(); - * model.add(tf.layers.dense( - * {units: 1, inputShape: [10], activation: 'sigmoid'})); - * await model.save('localstorage://demo/management/model1'); - * - * // Then list existing models. - * console.log(JSON.stringify(await tf.io.listModels())); - * - * // Move the model, from Local Storage to IndexedDB. - * await tf.io.moveModel( - * 'localstorage://demo/management/model1', - * 'indexeddb://demo/management/model1'); - * - * // List models again. - * console.log(JSON.stringify(await tf.io.listModels())); - * - * // Remove the moved model. - * await tf.io.removeModel('indexeddb://demo/management/model1'); - * ``` - * - * @param sourceURL Source URL of moving. - * @param destURL Destination URL of moving. - * @returns ModelArtifactsInfo of the copied model (if and only if copying - * is successful). - * @throws Error if moving fails, e.g., if no model exists at `sourceURL`, or - * if `oldPath` and `newPath` are identical. - */ - /** - * @doc { - * heading: 'Models', - * subheading: 'Management', - * namespace: 'io', - * ignoreCI: true - * } - */ - function moveModel(sourceURL, destURL) { - return __awaiter(this, void 0, void 0, function () { - var deleteSource; - return __generator(this, function (_a) { - deleteSource = true; - return [2 /*return*/, cloneModelInternal(sourceURL, destURL, deleteSource)]; - }); - }); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var DATABASE_NAME = 'tensorflowjs'; - var DATABASE_VERSION = 1; - // Model data and ModelArtifactsInfo (metadata) are stored in two separate - // stores for efficient access of the list of stored models and their metadata. - // 1. The object store for model data: topology, weights and weight manifests. - var MODEL_STORE_NAME = 'models_store'; - // 2. The object store for ModelArtifactsInfo, including meta-information such - // as the type of topology (JSON vs binary), byte size of the topology, byte - // size of the weights, etc. - var INFO_STORE_NAME = 'model_info_store'; - function getIndexedDBFactory() { - if (!env().getBool('IS_BROWSER')) { - // TODO(cais): Add more info about what IOHandler subtypes are available. - // Maybe point to a doc page on the web and/or automatically determine - // the available IOHandlers and print them in the error message. - throw new Error('Failed to obtain IndexedDB factory because the current environment' + - 'is not a web browser.'); - } - // tslint:disable-next-line:no-any - var theWindow = typeof window === 'undefined' ? self : window; - var factory = theWindow.indexedDB || theWindow.mozIndexedDB || - theWindow.webkitIndexedDB || theWindow.msIndexedDB || - theWindow.shimIndexedDB; - if (factory == null) { - throw new Error('The current browser does not appear to support IndexedDB.'); - } - return factory; - } - function setUpDatabase(openRequest) { - var db = openRequest.result; - db.createObjectStore(MODEL_STORE_NAME, { keyPath: 'modelPath' }); - db.createObjectStore(INFO_STORE_NAME, { keyPath: 'modelPath' }); - } - /** - * IOHandler subclass: Browser IndexedDB. - * - * See the doc string of `browserIndexedDB` for more details. - */ - var BrowserIndexedDB = /** @class */ (function () { - function BrowserIndexedDB(modelPath) { - this.indexedDB = getIndexedDBFactory(); - if (modelPath == null || !modelPath) { - throw new Error('For IndexedDB, modelPath must not be null, undefined or empty.'); - } - this.modelPath = modelPath; - } - BrowserIndexedDB.prototype.save = function (modelArtifacts) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - // TODO(cais): Support saving GraphDef models. - if (modelArtifacts.modelTopology instanceof ArrayBuffer) { - throw new Error('BrowserLocalStorage.save() does not support saving model topology ' + - 'in binary formats yet.'); - } - return [2 /*return*/, this.databaseAction(this.modelPath, modelArtifacts)]; - }); - }); - }; - BrowserIndexedDB.prototype.load = function () { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.databaseAction(this.modelPath)]; - }); - }); - }; - /** - * Perform database action to put model artifacts into or read model artifacts - * from IndexedDB object store. - * - * Whether the action is put or get depends on whether `modelArtifacts` is - * specified. If it is specified, the action will be put; otherwise the action - * will be get. - * - * @param modelPath A unique string path for the model. - * @param modelArtifacts If specified, it will be the model artifacts to be - * stored in IndexedDB. - * @returns A `Promise` of `SaveResult`, if the action is put, or a `Promise` - * of `ModelArtifacts`, if the action is get. - */ - BrowserIndexedDB.prototype.databaseAction = function (modelPath, modelArtifacts) { - var _this = this; - return new Promise(function (resolve, reject) { - var openRequest = _this.indexedDB.open(DATABASE_NAME, DATABASE_VERSION); - openRequest.onupgradeneeded = function () { return setUpDatabase(openRequest); }; - openRequest.onsuccess = function () { - var db = openRequest.result; - if (modelArtifacts == null) { - // Read model out from object store. - var modelTx = db.transaction(MODEL_STORE_NAME, 'readonly'); - var modelStore = modelTx.objectStore(MODEL_STORE_NAME); - var getRequest_1 = modelStore.get(_this.modelPath); - getRequest_1.onsuccess = function () { - if (getRequest_1.result == null) { - db.close(); - return reject(new Error("Cannot find model with path '" + _this.modelPath + "' " + - "in IndexedDB.")); - } - else { - resolve(getRequest_1.result.modelArtifacts); - } - }; - getRequest_1.onerror = function (error) { - db.close(); - return reject(getRequest_1.error); - }; - modelTx.oncomplete = function () { return db.close(); }; - } - else { - // Put model into object store. - var modelArtifactsInfo_1 = getModelArtifactsInfoForJSON(modelArtifacts); - // First, put ModelArtifactsInfo into info store. - var infoTx_1 = db.transaction(INFO_STORE_NAME, 'readwrite'); - var infoStore_1 = infoTx_1.objectStore(INFO_STORE_NAME); - var putInfoRequest_1 = infoStore_1.put({ modelPath: _this.modelPath, modelArtifactsInfo: modelArtifactsInfo_1 }); - var modelTx_1; - putInfoRequest_1.onsuccess = function () { - // Second, put model data into model store. - modelTx_1 = db.transaction(MODEL_STORE_NAME, 'readwrite'); - var modelStore = modelTx_1.objectStore(MODEL_STORE_NAME); - var putModelRequest = modelStore.put({ - modelPath: _this.modelPath, - modelArtifacts: modelArtifacts, - modelArtifactsInfo: modelArtifactsInfo_1 - }); - putModelRequest.onsuccess = function () { return resolve({ modelArtifactsInfo: modelArtifactsInfo_1 }); }; - putModelRequest.onerror = function (error) { - // If the put-model request fails, roll back the info entry as - // well. - infoStore_1 = infoTx_1.objectStore(INFO_STORE_NAME); - var deleteInfoRequest = infoStore_1.delete(_this.modelPath); - deleteInfoRequest.onsuccess = function () { - db.close(); - return reject(putModelRequest.error); - }; - deleteInfoRequest.onerror = function (error) { - db.close(); - return reject(putModelRequest.error); - }; - }; - }; - putInfoRequest_1.onerror = function (error) { - db.close(); - return reject(putInfoRequest_1.error); - }; - infoTx_1.oncomplete = function () { - if (modelTx_1 == null) { - db.close(); - } - else { - modelTx_1.oncomplete = function () { return db.close(); }; - } - }; - } - }; - openRequest.onerror = function (error) { return reject(openRequest.error); }; - }); - }; - BrowserIndexedDB.URL_SCHEME = 'indexeddb://'; - return BrowserIndexedDB; - }()); - var indexedDBRouter = function (url) { - if (!env().getBool('IS_BROWSER')) { - return null; - } - else { - if (!Array.isArray(url) && url.startsWith(BrowserIndexedDB.URL_SCHEME)) { - return browserIndexedDB(url.slice(BrowserIndexedDB.URL_SCHEME.length)); - } - else { - return null; - } - } - }; - IORouterRegistry.registerSaveRouter(indexedDBRouter); - IORouterRegistry.registerLoadRouter(indexedDBRouter); - /** - * Creates a browser IndexedDB IOHandler for saving and loading models. - * - * ```js - * const model = tf.sequential(); - * model.add( - * tf.layers.dense({units: 1, inputShape: [100], activation: 'sigmoid'})); - * - * const saveResult = await model.save('indexeddb://MyModel')); - * console.log(saveResult); - * ``` - * - * @param modelPath A unique identifier for the model to be saved. Must be a - * non-empty string. - * @returns An instance of `BrowserIndexedDB` (sublcass of `IOHandler`), - * which can be used with, e.g., `tf.Model.save`. - */ - function browserIndexedDB(modelPath) { - return new BrowserIndexedDB(modelPath); - } - function maybeStripScheme(key) { - return key.startsWith(BrowserIndexedDB.URL_SCHEME) ? - key.slice(BrowserIndexedDB.URL_SCHEME.length) : - key; - } - var BrowserIndexedDBManager = /** @class */ (function () { - function BrowserIndexedDBManager() { - this.indexedDB = getIndexedDBFactory(); - } - BrowserIndexedDBManager.prototype.listModels = function () { - return __awaiter(this, void 0, void 0, function () { - var _this = this; - return __generator(this, function (_a) { - return [2 /*return*/, new Promise(function (resolve, reject) { - var openRequest = _this.indexedDB.open(DATABASE_NAME, DATABASE_VERSION); - openRequest.onupgradeneeded = function () { return setUpDatabase(openRequest); }; - openRequest.onsuccess = function () { - var db = openRequest.result; - var tx = db.transaction(INFO_STORE_NAME, 'readonly'); - var store = tx.objectStore(INFO_STORE_NAME); - // tslint:disable:max-line-length - // Need to cast `store` as `any` here because TypeScript's DOM - // library does not have the `getAll()` method even though the - // method is supported in the latest version of most mainstream - // browsers: - // https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/getAll - // tslint:enable:max-line-length - // tslint:disable-next-line:no-any - var getAllInfoRequest = store.getAll(); - getAllInfoRequest.onsuccess = function () { - var out = {}; - for (var _i = 0, _a = getAllInfoRequest.result; _i < _a.length; _i++) { - var item = _a[_i]; - out[item.modelPath] = item.modelArtifactsInfo; - } - resolve(out); - }; - getAllInfoRequest.onerror = function (error) { - db.close(); - return reject(getAllInfoRequest.error); - }; - tx.oncomplete = function () { return db.close(); }; - }; - openRequest.onerror = function (error) { return reject(openRequest.error); }; - })]; - }); - }); - }; - BrowserIndexedDBManager.prototype.removeModel = function (path) { - return __awaiter(this, void 0, void 0, function () { - var _this = this; - return __generator(this, function (_a) { - path = maybeStripScheme(path); - return [2 /*return*/, new Promise(function (resolve, reject) { - var openRequest = _this.indexedDB.open(DATABASE_NAME, DATABASE_VERSION); - openRequest.onupgradeneeded = function () { return setUpDatabase(openRequest); }; - openRequest.onsuccess = function () { - var db = openRequest.result; - var infoTx = db.transaction(INFO_STORE_NAME, 'readwrite'); - var infoStore = infoTx.objectStore(INFO_STORE_NAME); - var getInfoRequest = infoStore.get(path); - var modelTx; - getInfoRequest.onsuccess = function () { - if (getInfoRequest.result == null) { - db.close(); - return reject(new Error("Cannot find model with path '" + path + "' " + - "in IndexedDB.")); - } - else { - // First, delete the entry in the info store. - var deleteInfoRequest = infoStore.delete(path); - var deleteModelData_1 = function () { - // Second, delete the entry in the model store. - modelTx = db.transaction(MODEL_STORE_NAME, 'readwrite'); - var modelStore = modelTx.objectStore(MODEL_STORE_NAME); - var deleteModelRequest = modelStore.delete(path); - deleteModelRequest.onsuccess = function () { - return resolve(getInfoRequest.result.modelArtifactsInfo); - }; - deleteModelRequest.onerror = function (error) { - return reject(getInfoRequest.error); - }; - }; - // Proceed with deleting model data regardless of whether deletion - // of info data succeeds or not. - deleteInfoRequest.onsuccess = deleteModelData_1; - deleteInfoRequest.onerror = function (error) { - deleteModelData_1(); - db.close(); - return reject(getInfoRequest.error); - }; - } - }; - getInfoRequest.onerror = function (error) { - db.close(); - return reject(getInfoRequest.error); - }; - infoTx.oncomplete = function () { - if (modelTx == null) { - db.close(); - } - else { - modelTx.oncomplete = function () { return db.close(); }; - } - }; - }; - openRequest.onerror = function (error) { return reject(openRequest.error); }; - })]; - }); - }); - }; - return BrowserIndexedDBManager; - }()); - if (env().getBool('IS_BROWSER')) { - // Wrap the construction and registration, to guard against browsers that - // don't support Local Storage. - try { - ModelStoreManagerRegistry.registerManager(BrowserIndexedDB.URL_SCHEME, new BrowserIndexedDBManager()); - } - catch (err) { - } - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var PATH_SEPARATOR = '/'; - var PATH_PREFIX = 'tensorflowjs_models'; - var INFO_SUFFIX = 'info'; - var MODEL_TOPOLOGY_SUFFIX = 'model_topology'; - var WEIGHT_SPECS_SUFFIX = 'weight_specs'; - var WEIGHT_DATA_SUFFIX = 'weight_data'; - var MODEL_METADATA_SUFFIX = 'model_metadata'; - function getModelKeys(path) { - return { - info: [PATH_PREFIX, path, INFO_SUFFIX].join(PATH_SEPARATOR), - topology: [PATH_PREFIX, path, MODEL_TOPOLOGY_SUFFIX].join(PATH_SEPARATOR), - weightSpecs: [PATH_PREFIX, path, WEIGHT_SPECS_SUFFIX].join(PATH_SEPARATOR), - weightData: [PATH_PREFIX, path, WEIGHT_DATA_SUFFIX].join(PATH_SEPARATOR), - modelMetadata: [PATH_PREFIX, path, MODEL_METADATA_SUFFIX].join(PATH_SEPARATOR) - }; - } - /** - * Get model path from a local-storage key. - * - * E.g., 'tensorflowjs_models/my/model/1/info' --> 'my/model/1' - * - * @param key - */ - function getModelPathFromKey(key) { - var items = key.split(PATH_SEPARATOR); - if (items.length < 3) { - throw new Error("Invalid key format: " + key); - } - return items.slice(1, items.length - 1).join(PATH_SEPARATOR); - } - function maybeStripScheme$1(key) { - return key.startsWith(BrowserLocalStorage.URL_SCHEME) ? - key.slice(BrowserLocalStorage.URL_SCHEME.length) : - key; - } - /** - * IOHandler subclass: Browser Local Storage. - * - * See the doc string to `browserLocalStorage` for more details. - */ - var BrowserLocalStorage = /** @class */ (function () { - function BrowserLocalStorage(modelPath) { - if (!env().getBool('IS_BROWSER') || - typeof window === 'undefined' || - typeof window.localStorage === 'undefined') { - // TODO(cais): Add more info about what IOHandler subtypes are - // available. - // Maybe point to a doc page on the web and/or automatically determine - // the available IOHandlers and print them in the error message. - throw new Error('The current environment does not support local storage.'); - } - this.LS = window.localStorage; - if (modelPath == null || !modelPath) { - throw new Error('For local storage, modelPath must not be null, undefined or empty.'); - } - this.modelPath = modelPath; - this.keys = getModelKeys(this.modelPath); - } - /** - * Save model artifacts to browser local storage. - * - * See the documentation to `browserLocalStorage` for details on the saved - * artifacts. - * - * @param modelArtifacts The model artifacts to be stored. - * @returns An instance of SaveResult. - */ - BrowserLocalStorage.prototype.save = function (modelArtifacts) { - return __awaiter(this, void 0, void 0, function () { - var topology, weightSpecs, modelArtifactsInfo; - return __generator(this, function (_a) { - if (modelArtifacts.modelTopology instanceof ArrayBuffer) { - throw new Error('BrowserLocalStorage.save() does not support saving model topology ' + - 'in binary formats yet.'); - } - else { - topology = JSON.stringify(modelArtifacts.modelTopology); - weightSpecs = JSON.stringify(modelArtifacts.weightSpecs); - modelArtifactsInfo = getModelArtifactsInfoForJSON(modelArtifacts); - try { - this.LS.setItem(this.keys.info, JSON.stringify(modelArtifactsInfo)); - this.LS.setItem(this.keys.topology, topology); - this.LS.setItem(this.keys.weightSpecs, weightSpecs); - this.LS.setItem(this.keys.weightData, arrayBufferToBase64String(modelArtifacts.weightData)); - this.LS.setItem(this.keys.modelMetadata, JSON.stringify({ - format: modelArtifacts.format, - generatedBy: modelArtifacts.generatedBy, - convertedBy: modelArtifacts.convertedBy, - userDefinedMetadata: modelArtifacts.userDefinedMetadata - })); - return [2 /*return*/, { modelArtifactsInfo: modelArtifactsInfo }]; - } - catch (err) { - // If saving failed, clean up all items saved so far. - this.LS.removeItem(this.keys.info); - this.LS.removeItem(this.keys.topology); - this.LS.removeItem(this.keys.weightSpecs); - this.LS.removeItem(this.keys.weightData); - this.LS.removeItem(this.keys.modelMetadata); - throw new Error("Failed to save model '" + this.modelPath + "' to local storage: " + - "size quota being exceeded is a possible cause of this failure: " + - ("modelTopologyBytes=" + modelArtifactsInfo.modelTopologyBytes + ", ") + - ("weightSpecsBytes=" + modelArtifactsInfo.weightSpecsBytes + ", ") + - ("weightDataBytes=" + modelArtifactsInfo.weightDataBytes + ".")); - } - } - return [2 /*return*/]; - }); - }); - }; - /** - * Load a model from local storage. - * - * See the documentation to `browserLocalStorage` for details on the saved - * artifacts. - * - * @returns The loaded model (if loading succeeds). - */ - BrowserLocalStorage.prototype.load = function () { - return __awaiter(this, void 0, void 0, function () { - var info, out, topology, weightSpecs, metadataString, metadata, weightDataBase64; - return __generator(this, function (_a) { - info = JSON.parse(this.LS.getItem(this.keys.info)); - if (info == null) { - throw new Error("In local storage, there is no model with name '" + this.modelPath + "'"); - } - if (info.modelTopologyType !== 'JSON') { - throw new Error('BrowserLocalStorage does not support loading non-JSON model ' + - 'topology yet.'); - } - out = {}; - topology = JSON.parse(this.LS.getItem(this.keys.topology)); - if (topology == null) { - throw new Error("In local storage, the topology of model '" + this.modelPath + "' " + - "is missing."); - } - out.modelTopology = topology; - weightSpecs = JSON.parse(this.LS.getItem(this.keys.weightSpecs)); - if (weightSpecs == null) { - throw new Error("In local storage, the weight specs of model '" + this.modelPath + "' " + - "are missing."); - } - out.weightSpecs = weightSpecs; - metadataString = this.LS.getItem(this.keys.modelMetadata); - if (metadataString != null) { - metadata = JSON.parse(metadataString); - out.format = metadata['format']; - out.generatedBy = metadata['generatedBy']; - out.convertedBy = metadata['convertedBy']; - out.userDefinedMetadata = metadata['userDefinedMetadata']; - } - weightDataBase64 = this.LS.getItem(this.keys.weightData); - if (weightDataBase64 == null) { - throw new Error("In local storage, the binary weight values of model " + - ("'" + this.modelPath + "' are missing.")); - } - out.weightData = base64StringToArrayBuffer(weightDataBase64); - return [2 /*return*/, out]; - }); - }); - }; - BrowserLocalStorage.URL_SCHEME = 'localstorage://'; - return BrowserLocalStorage; - }()); - var localStorageRouter = function (url) { - if (!env().getBool('IS_BROWSER')) { - return null; - } - else { - if (!Array.isArray(url) && url.startsWith(BrowserLocalStorage.URL_SCHEME)) { - return browserLocalStorage(url.slice(BrowserLocalStorage.URL_SCHEME.length)); - } - else { - return null; - } - } - }; - IORouterRegistry.registerSaveRouter(localStorageRouter); - IORouterRegistry.registerLoadRouter(localStorageRouter); - /** - * Factory function for local storage IOHandler. - * - * This `IOHandler` supports both `save` and `load`. - * - * For each model's saved artifacts, four items are saved to local storage. - * - `${PATH_SEPARATOR}/${modelPath}/info`: Contains meta-info about the - * model, such as date saved, type of the topology, size in bytes, etc. - * - `${PATH_SEPARATOR}/${modelPath}/topology`: Model topology. For Keras- - * style models, this is a stringized JSON. - * - `${PATH_SEPARATOR}/${modelPath}/weight_specs`: Weight specs of the - * model, can be used to decode the saved binary weight values (see - * item below). - * - `${PATH_SEPARATOR}/${modelPath}/weight_data`: Concatenated binary - * weight values, stored as a base64-encoded string. - * - * Saving may throw an `Error` if the total size of the artifacts exceed the - * browser-specific quota. - * - * @param modelPath A unique identifier for the model to be saved. Must be a - * non-empty string. - * @returns An instance of `IOHandler`, which can be used with, e.g., - * `tf.Model.save`. - */ - function browserLocalStorage(modelPath) { - return new BrowserLocalStorage(modelPath); - } - var BrowserLocalStorageManager = /** @class */ (function () { - function BrowserLocalStorageManager() { - assert(env().getBool('IS_BROWSER'), function () { return 'Current environment is not a web browser'; }); - assert(typeof window === 'undefined' || - typeof window.localStorage !== 'undefined', function () { return 'Current browser does not appear to support localStorage'; }); - this.LS = window.localStorage; - } - BrowserLocalStorageManager.prototype.listModels = function () { - return __awaiter(this, void 0, void 0, function () { - var out, prefix, suffix, i, key, modelPath; - return __generator(this, function (_a) { - out = {}; - prefix = PATH_PREFIX + PATH_SEPARATOR; - suffix = PATH_SEPARATOR + INFO_SUFFIX; - for (i = 0; i < this.LS.length; ++i) { - key = this.LS.key(i); - if (key.startsWith(prefix) && key.endsWith(suffix)) { - modelPath = getModelPathFromKey(key); - out[modelPath] = JSON.parse(this.LS.getItem(key)); - } - } - return [2 /*return*/, out]; - }); - }); - }; - BrowserLocalStorageManager.prototype.removeModel = function (path) { - return __awaiter(this, void 0, void 0, function () { - var keys, info; - return __generator(this, function (_a) { - path = maybeStripScheme$1(path); - keys = getModelKeys(path); - if (this.LS.getItem(keys.info) == null) { - throw new Error("Cannot find model at path '" + path + "'"); - } - info = JSON.parse(this.LS.getItem(keys.info)); - this.LS.removeItem(keys.info); - this.LS.removeItem(keys.topology); - this.LS.removeItem(keys.weightSpecs); - this.LS.removeItem(keys.weightData); - return [2 /*return*/, info]; - }); - }); - }; - return BrowserLocalStorageManager; - }()); - if (env().getBool('IS_BROWSER')) { - // Wrap the construction and registration, to guard against browsers that - // don't support Local Storage. - try { - ModelStoreManagerRegistry.registerManager(BrowserLocalStorage.URL_SCHEME, new BrowserLocalStorageManager()); - } - catch (err) { - } - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var DEFAULT_FILE_NAME_PREFIX = 'model'; - var DEFAULT_JSON_EXTENSION_NAME = '.json'; - var DEFAULT_WEIGHT_DATA_EXTENSION_NAME = '.weights.bin'; - function defer(f) { - return new Promise(function (resolve) { return setTimeout(resolve); }).then(f); - } - var BrowserDownloads = /** @class */ (function () { - function BrowserDownloads(fileNamePrefix) { - if (!env().getBool('IS_BROWSER')) { - // TODO(cais): Provide info on what IOHandlers are available under the - // current environment. - throw new Error('browserDownloads() cannot proceed because the current environment ' + - 'is not a browser.'); - } - if (fileNamePrefix.startsWith(BrowserDownloads.URL_SCHEME)) { - fileNamePrefix = fileNamePrefix.slice(BrowserDownloads.URL_SCHEME.length); - } - if (fileNamePrefix == null || fileNamePrefix.length === 0) { - fileNamePrefix = DEFAULT_FILE_NAME_PREFIX; - } - this.modelTopologyFileName = fileNamePrefix + DEFAULT_JSON_EXTENSION_NAME; - this.weightDataFileName = - fileNamePrefix + DEFAULT_WEIGHT_DATA_EXTENSION_NAME; - } - BrowserDownloads.prototype.save = function (modelArtifacts) { - return __awaiter(this, void 0, void 0, function () { - var weightsURL, weightsManifest, modelTopologyAndWeightManifest, modelTopologyAndWeightManifestURL, jsonAnchor_1, weightDataAnchor_1; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (typeof (document) === 'undefined') { - throw new Error('Browser downloads are not supported in ' + - 'this environment since `document` is not present'); - } - weightsURL = window.URL.createObjectURL(new Blob([modelArtifacts.weightData], { type: 'application/octet-stream' })); - if (!(modelArtifacts.modelTopology instanceof ArrayBuffer)) return [3 /*break*/, 1]; - throw new Error('BrowserDownloads.save() does not support saving model topology ' + - 'in binary formats yet.'); - case 1: - weightsManifest = [{ - paths: ['./' + this.weightDataFileName], - weights: modelArtifacts.weightSpecs - }]; - modelTopologyAndWeightManifest = { - modelTopology: modelArtifacts.modelTopology, - format: modelArtifacts.format, - generatedBy: modelArtifacts.generatedBy, - convertedBy: modelArtifacts.convertedBy, - weightsManifest: weightsManifest - }; - modelTopologyAndWeightManifestURL = window.URL.createObjectURL(new Blob([JSON.stringify(modelTopologyAndWeightManifest)], { type: 'application/json' })); - jsonAnchor_1 = this.jsonAnchor == null ? document.createElement('a') : - this.jsonAnchor; - jsonAnchor_1.download = this.modelTopologyFileName; - jsonAnchor_1.href = modelTopologyAndWeightManifestURL; - // Trigger downloads by evoking a click event on the download anchors. - // When multiple downloads are started synchronously, Firefox will only - // save the last one. - return [4 /*yield*/, defer(function () { return jsonAnchor_1.dispatchEvent(new MouseEvent('click')); })]; - case 2: - // Trigger downloads by evoking a click event on the download anchors. - // When multiple downloads are started synchronously, Firefox will only - // save the last one. - _a.sent(); - if (!(modelArtifacts.weightData != null)) return [3 /*break*/, 4]; - weightDataAnchor_1 = this.weightDataAnchor == null ? - document.createElement('a') : - this.weightDataAnchor; - weightDataAnchor_1.download = this.weightDataFileName; - weightDataAnchor_1.href = weightsURL; - return [4 /*yield*/, defer(function () { return weightDataAnchor_1.dispatchEvent(new MouseEvent('click')); })]; - case 3: - _a.sent(); - _a.label = 4; - case 4: return [2 /*return*/, { modelArtifactsInfo: getModelArtifactsInfoForJSON(modelArtifacts) }]; - } - }); - }); - }; - BrowserDownloads.URL_SCHEME = 'downloads://'; - return BrowserDownloads; - }()); - var BrowserFiles = /** @class */ (function () { - function BrowserFiles(files) { - if (files == null || files.length < 1) { - throw new Error("When calling browserFiles, at least 1 file is required, " + - ("but received " + files)); - } - this.files = files; - } - BrowserFiles.prototype.load = function () { - return __awaiter(this, void 0, void 0, function () { - var jsonFile, weightFiles; - var _this = this; - return __generator(this, function (_a) { - jsonFile = this.files[0]; - weightFiles = this.files.slice(1); - return [2 /*return*/, new Promise(function (resolve, reject) { - var jsonReader = new FileReader(); - jsonReader.onload = function (event) { - // tslint:disable-next-line:no-any - var modelJSON = JSON.parse(event.target.result); - var modelTopology = modelJSON.modelTopology; - if (modelTopology == null) { - reject(new Error("modelTopology field is missing from file " + jsonFile.name)); - return; - } - if (weightFiles.length === 0) { - resolve({ modelTopology: modelTopology }); - } - var weightsManifest = modelJSON.weightsManifest; - if (weightsManifest == null) { - reject(new Error("weightManifest field is missing from file " + jsonFile.name)); - return; - } - var pathToFile; - try { - pathToFile = - _this.checkManifestAndWeightFiles(weightsManifest, weightFiles); - } - catch (err) { - reject(err); - return; - } - var weightSpecs = []; - var paths = []; - var perFileBuffers = []; - weightsManifest.forEach(function (weightsGroup) { - weightsGroup.paths.forEach(function (path) { - paths.push(path); - perFileBuffers.push(null); - }); - weightSpecs.push.apply(weightSpecs, weightsGroup.weights); - }); - weightsManifest.forEach(function (weightsGroup) { - weightsGroup.paths.forEach(function (path) { - var weightFileReader = new FileReader(); - weightFileReader.onload = function (event) { - // tslint:disable-next-line:no-any - var weightData = event.target.result; - var index = paths.indexOf(path); - perFileBuffers[index] = weightData; - if (perFileBuffers.indexOf(null) === -1) { - resolve({ - modelTopology: modelTopology, - weightSpecs: weightSpecs, - weightData: concatenateArrayBuffers(perFileBuffers), - format: modelJSON.format, - generatedBy: modelJSON.generatedBy, - convertedBy: modelJSON.convertedBy, - userDefinedMetadata: modelJSON.userDefinedMetadata - }); - } - }; - weightFileReader.onerror = function (error) { - return reject("Failed to weights data from file of path '" + path + "'."); - }; - weightFileReader.readAsArrayBuffer(pathToFile[path]); - }); - }); - }; - jsonReader.onerror = function (error) { return reject("Failed to read model topology and weights manifest JSON " + - ("from file '" + jsonFile.name + "'. BrowserFiles supports loading ") + - "Keras-style tf.Model artifacts only."); }; - jsonReader.readAsText(jsonFile); - })]; - }); - }); - }; - /** - * Check the compatibility between weights manifest and weight files. - */ - BrowserFiles.prototype.checkManifestAndWeightFiles = function (manifest, files) { - var basenames = []; - var fileNames = files.map(function (file) { return basename(file.name); }); - var pathToFile = {}; - for (var _i = 0, manifest_1 = manifest; _i < manifest_1.length; _i++) { - var group = manifest_1[_i]; - group.paths.forEach(function (path) { - var pathBasename = basename(path); - if (basenames.indexOf(pathBasename) !== -1) { - throw new Error("Duplicate file basename found in weights manifest: " + - ("'" + pathBasename + "'")); - } - basenames.push(pathBasename); - if (fileNames.indexOf(pathBasename) === -1) { - throw new Error("Weight file with basename '" + pathBasename + "' is not provided."); - } - else { - pathToFile[path] = files[fileNames.indexOf(pathBasename)]; - } - }); - } - if (basenames.length !== files.length) { - throw new Error("Mismatch in the number of files in weights manifest " + - ("(" + basenames.length + ") and the number of weight files provided ") + - ("(" + files.length + ").")); - } - return pathToFile; - }; - return BrowserFiles; - }()); - var browserDownloadsRouter = function (url) { - if (!env().getBool('IS_BROWSER')) { - return null; - } - else { - if (!Array.isArray(url) && url.startsWith(BrowserDownloads.URL_SCHEME)) { - return browserDownloads(url.slice(BrowserDownloads.URL_SCHEME.length)); - } - else { - return null; - } - } - }; - IORouterRegistry.registerSaveRouter(browserDownloadsRouter); - /** - * Creates an IOHandler that triggers file downloads from the browser. - * - * The returned `IOHandler` instance can be used as model exporting methods such - * as `tf.Model.save` and supports only saving. - * - * ```js - * const model = tf.sequential(); - * model.add(tf.layers.dense( - * {units: 1, inputShape: [10], activation: 'sigmoid'})); - * const saveResult = await model.save('downloads://mymodel'); - * // This will trigger downloading of two files: - * // 'mymodel.json' and 'mymodel.weights.bin'. - * console.log(saveResult); - * ``` - * - * @param fileNamePrefix Prefix name of the files to be downloaded. For use with - * `tf.Model`, `fileNamePrefix` should follow either of the following two - * formats: - * 1. `null` or `undefined`, in which case the default file - * names will be used: - * - 'model.json' for the JSON file containing the model topology and - * weights manifest. - * - 'model.weights.bin' for the binary file containing the binary weight - * values. - * 2. A single string or an Array of a single string, as the file name prefix. - * For example, if `'foo'` is provided, the downloaded JSON - * file and binary weights file will be named 'foo.json' and - * 'foo.weights.bin', respectively. - * @param config Additional configuration for triggering downloads. - * @returns An instance of `BrowserDownloads` `IOHandler`. - */ - /** - * @doc { - * heading: 'Models', - * subheading: 'Loading', - * namespace: 'io', - * ignoreCI: true - * } - */ - function browserDownloads(fileNamePrefix) { - if (fileNamePrefix === void 0) { fileNamePrefix = 'model'; } - return new BrowserDownloads(fileNamePrefix); - } - /** - * Creates an IOHandler that loads model artifacts from user-selected files. - * - * This method can be used for loading from files such as user-selected files - * in the browser. - * When used in conjunction with `tf.loadLayersModel`, an instance of - * `tf.LayersModel` (Keras-style) can be constructed from the loaded artifacts. - * - * ```js - * // Note: This code snippet won't run properly without the actual file input - * // elements in the HTML DOM. - * - * // Suppose there are two HTML file input (``) - * // elements. - * const uploadJSONInput = document.getElementById('upload-json'); - * const uploadWeightsInput = document.getElementById('upload-weights'); - * const model = await tf.loadLayersModel(tf.io.browserFiles( - * [uploadJSONInput.files[0], uploadWeightsInput.files[0]])); - * ``` - * - * @param files `File`s to load from. Currently, this function supports only - * loading from files that contain Keras-style models (i.e., `tf.Model`s), for - * which an `Array` of `File`s is expected (in that order): - * - A JSON file containing the model topology and weight manifest. - * - Optionally, One or more binary files containing the binary weights. - * These files must have names that match the paths in the `weightsManifest` - * contained by the aforementioned JSON file, or errors will be thrown - * during loading. These weights files have the same format as the ones - * generated by `tensorflowjs_converter` that comes with the `tensorflowjs` - * Python PIP package. If no weights files are provided, only the model - * topology will be loaded from the JSON file above. - * @returns An instance of `Files` `IOHandler`. - */ - /** - * @doc { - * heading: 'Models', - * subheading: 'Loading', - * namespace: 'io', - * ignoreCI: true - * } - */ - function browserFiles(files) { - return new BrowserFiles(files); - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Monitor Promise.all progress, fire onProgress callback function. - * - * @param promises Promise list going to be monitored - * @param onProgress Callback function. Fired when a promise resolved. - * @param startFraction Optional fraction start. Default to 0. - * @param endFraction Optional fraction end. Default to 1. - */ - function monitorPromisesProgress(promises, onProgress, startFraction, endFraction) { - checkPromises(promises); - startFraction = startFraction == null ? 0 : startFraction; - endFraction = endFraction == null ? 1 : endFraction; - checkFraction(startFraction, endFraction); - var resolvedPromise = 0; - var registerMonitor = function (promise) { - promise.then(function (value) { - var fraction = startFraction + - ++resolvedPromise / promises.length * (endFraction - startFraction); - // pass fraction as parameter to callback function. - onProgress(fraction); - return value; - }); - return promise; - }; - function checkPromises(promises) { - assert(promises != null && Array.isArray(promises) && promises.length > 0, function () { return 'promises must be a none empty array'; }); - } - function checkFraction(startFraction, endFraction) { - assert(startFraction >= 0 && startFraction <= 1, function () { return "Progress fraction must be in range [0, 1], but " + - ("got startFraction " + startFraction); }); - assert(endFraction >= 0 && endFraction <= 1, function () { return "Progress fraction must be in range [0, 1], but " + - ("got endFraction " + endFraction); }); - assert(endFraction >= startFraction, function () { return "startFraction must be no more than endFraction, but " + - ("got startFraction " + startFraction + " and endFraction ") + - ("" + endFraction); }); - } - return Promise.all(promises.map(registerMonitor)); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Reads binary weights data from a number of URLs. - * - * @param fetchURLs URLs to send the HTTP requests at, using `fetch` calls. - * @param requestOptions RequestInit (options) for the HTTP requests. - * @param fetchFunc Optional overriding value for the `window.fetch` function. - * @param onProgress Optional, progress callback function, fired periodically - * before the load is completed. - * @returns A `Promise` of an Array of `ArrayBuffer`. The Array has the same - * length as `fetchURLs`. - */ - function loadWeightsAsArrayBuffer(fetchURLs, loadOptions) { - return __awaiter(this, void 0, void 0, function () { - var fetchFunc, requests, fetchStartFraction, fetchEndFraction, responses, _a, bufferPromises, bufferStartFraction, bufferEndFraction, buffers, _b; - return __generator(this, function (_c) { - switch (_c.label) { - case 0: - if (loadOptions == null) { - loadOptions = {}; - } - fetchFunc = loadOptions.fetchFunc == null ? env().platform.fetch : - loadOptions.fetchFunc; - requests = fetchURLs.map(function (fetchURL) { - return fetchFunc(fetchURL, loadOptions.requestInit, { isBinary: true }); - }); - fetchStartFraction = 0; - fetchEndFraction = 0.5; - if (!(loadOptions.onProgress == null)) return [3 /*break*/, 2]; - return [4 /*yield*/, Promise.all(requests)]; - case 1: - _a = _c.sent(); - return [3 /*break*/, 4]; - case 2: return [4 /*yield*/, monitorPromisesProgress(requests, loadOptions.onProgress, fetchStartFraction, fetchEndFraction)]; - case 3: - _a = _c.sent(); - _c.label = 4; - case 4: - responses = _a; - bufferPromises = responses.map(function (response) { return response.arrayBuffer(); }); - bufferStartFraction = 0.5; - bufferEndFraction = 1; - if (!(loadOptions.onProgress == null)) return [3 /*break*/, 6]; - return [4 /*yield*/, Promise.all(bufferPromises)]; - case 5: - _b = _c.sent(); - return [3 /*break*/, 8]; - case 6: return [4 /*yield*/, monitorPromisesProgress(bufferPromises, loadOptions.onProgress, bufferStartFraction, bufferEndFraction)]; - case 7: - _b = _c.sent(); - _c.label = 8; - case 8: - buffers = _b; - return [2 /*return*/, buffers]; - } - }); - }); - } - /** - * Reads a weights manifest JSON configuration, fetches the weights and - * returns them as `Tensor`s. - * - * @param manifest The weights manifest JSON. - * @param filePathPrefix The path prefix for filenames given in the manifest. - * Defaults to the empty string. - * @param weightNames The names of the weights to be fetched. - */ - function loadWeights(manifest, filePathPrefix, weightNames, requestInit) { - if (filePathPrefix === void 0) { filePathPrefix = ''; } - return __awaiter(this, void 0, void 0, function () { - var fetchWeights, loadWeights; - return __generator(this, function (_a) { - fetchWeights = function (fetchUrls) { - return loadWeightsAsArrayBuffer(fetchUrls, { requestInit: requestInit }); - }; - loadWeights = weightsLoaderFactory(fetchWeights); - return [2 /*return*/, loadWeights(manifest, filePathPrefix, weightNames)]; - }); - }); - } - /** - * Creates a function, which reads a weights manifest JSON configuration, - * fetches the weight files using the specified function and returns them as - * `Tensor`s. - * - * ```js - * // example for creating a nodejs weight loader, which reads the weight files - * // from disk using fs.readFileSync - * - * import * as fs from 'fs' - * - * const fetchWeightsFromDisk = (filePaths: string[]) => - * filePaths.map(filePath => fs.readFileSync(filePath).buffer) - * - * const loadWeights = tf.io.weightsLoaderFactory(fetchWeightsFromDisk) - * - * const manifest = JSON.parse( - * fs.readFileSync('./my_model-weights_manifest').toString() - * ) - * const weightMap = await loadWeights(manifest, './') - * ``` - * @param fetchWeightsFunction The function used for fetching the weight files. - * @returns Weight loading function. - */ - function weightsLoaderFactory(fetchWeightsFunction) { - var _this = this; - return function (manifest, filePathPrefix, weightNames) { - if (filePathPrefix === void 0) { filePathPrefix = ''; } - return __awaiter(_this, void 0, void 0, function () { - var groupIndicesToFetchMap, groupWeightsToFetch, weightsFound, allManifestWeightNames, weightsNotFound, groupIndicesToFetch, fetchUrls, buffers, weightsTensorMap, bufferIndexOffset; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - groupIndicesToFetchMap = manifest.map(function () { return false; }); - groupWeightsToFetch = {}; - weightsFound = weightNames != null ? weightNames.map(function () { return false; }) : []; - allManifestWeightNames = []; - manifest.forEach(function (manifestGroupConfig, groupIndex) { - var groupOffset = 0; - manifestGroupConfig.weights.forEach(function (weightsEntry) { - var rawDtype = ('quantization' in weightsEntry) ? - weightsEntry.quantization.dtype : - weightsEntry.dtype; - var weightsBytes = DTYPE_VALUE_SIZE_MAP[rawDtype] * - sizeFromShape(weightsEntry.shape); - var enqueueWeightsForFetchingFn = function () { - groupIndicesToFetchMap[groupIndex] = true; - if (groupWeightsToFetch[groupIndex] == null) { - groupWeightsToFetch[groupIndex] = []; - } - groupWeightsToFetch[groupIndex].push({ - manifestEntry: weightsEntry, - groupOffset: groupOffset, - sizeBytes: weightsBytes - }); - }; - if (weightNames != null) { - weightNames.forEach(function (weightName, weightIndex) { - if (weightName === weightsEntry.name) { - enqueueWeightsForFetchingFn(); - weightsFound[weightIndex] = true; - } - }); - } - else { - enqueueWeightsForFetchingFn(); - } - allManifestWeightNames.push(weightsEntry.name); - groupOffset += weightsBytes; - }); - }); - if (!weightsFound.every(function (found) { return found; })) { - weightsNotFound = weightNames.filter(function (_, i) { return !weightsFound[i]; }); - throw new Error("Could not find weights in manifest with names: " + - (weightsNotFound.join(', ') + ". \n") + - "Manifest JSON has weights with names: " + - (allManifestWeightNames.join(', ') + ".")); - } - groupIndicesToFetch = groupIndicesToFetchMap.reduce(function (accumulator, shouldFetch, i) { - if (shouldFetch) { - accumulator.push(i); - } - return accumulator; - }, []); - fetchUrls = []; - groupIndicesToFetch.forEach(function (i) { - manifest[i].paths.forEach(function (filepath) { - var fetchUrl = filePathPrefix + - (!filePathPrefix.endsWith('/') ? '/' : '') + filepath; - fetchUrls.push(fetchUrl); - }); - }); - return [4 /*yield*/, fetchWeightsFunction(fetchUrls)]; - case 1: - buffers = _a.sent(); - weightsTensorMap = {}; - bufferIndexOffset = 0; - groupIndicesToFetch.forEach(function (i) { - var numBuffers = manifest[i].paths.length; - var groupBytes = 0; - for (var i_1 = 0; i_1 < numBuffers; i_1++) { - groupBytes += buffers[bufferIndexOffset + i_1].byteLength; - } - // Create a buffer for the whole group. - var groupBuffer = new ArrayBuffer(groupBytes); - var groupByteBuffer = new Uint8Array(groupBuffer); - var groupBufferOffset = 0; - for (var i_2 = 0; i_2 < numBuffers; i_2++) { - var buffer = new Uint8Array(buffers[bufferIndexOffset + i_2]); - groupByteBuffer.set(buffer, groupBufferOffset); - groupBufferOffset += buffer.byteLength; - } - var weightsEntries = groupWeightsToFetch[i]; - weightsEntries.forEach(function (weightsEntry) { - var byteBuffer = groupBuffer.slice(weightsEntry.groupOffset, weightsEntry.groupOffset + weightsEntry.sizeBytes); - var nameToTensorMap = decodeWeights(byteBuffer, [weightsEntry.manifestEntry]); - for (var name_1 in nameToTensorMap) { - weightsTensorMap[name_1] = nameToTensorMap[name_1]; - } - }); - bufferIndexOffset += numBuffers; - }); - return [2 /*return*/, weightsTensorMap]; - } - }); - }); - }; - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var OCTET_STREAM_MIME_TYPE = 'application/octet-stream'; - var JSON_TYPE = 'application/json'; - var HTTPRequest = /** @class */ (function () { - function HTTPRequest(path, loadOptions) { - this.DEFAULT_METHOD = 'POST'; - if (loadOptions == null) { - loadOptions = {}; - } - this.weightPathPrefix = loadOptions.weightPathPrefix; - this.onProgress = loadOptions.onProgress; - if (loadOptions.fetchFunc != null) { - assert(typeof loadOptions.fetchFunc === 'function', function () { return 'Must pass a function that matches the signature of ' + - '`fetch` (see ' + - 'https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)'; }); - this.fetch = loadOptions.fetchFunc; - } - else { - this.fetch = env().platform.fetch; - } - assert(path != null && path.length > 0, function () { return 'URL path for http must not be null, undefined or ' + - 'empty.'; }); - if (Array.isArray(path)) { - assert(path.length === 2, function () { return 'URL paths for http must have a length of 2, ' + - ("(actual length is " + path.length + ")."); }); - } - this.path = path; - if (loadOptions.requestInit != null && - loadOptions.requestInit.body != null) { - throw new Error('requestInit is expected to have no pre-existing body, but has one.'); - } - this.requestInit = loadOptions.requestInit || {}; - } - HTTPRequest.prototype.save = function (modelArtifacts) { - return __awaiter(this, void 0, void 0, function () { - var init, weightsManifest, modelTopologyAndWeightManifest, response; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (modelArtifacts.modelTopology instanceof ArrayBuffer) { - throw new Error('BrowserHTTPRequest.save() does not support saving model topology ' + - 'in binary formats yet.'); - } - init = Object.assign({ method: this.DEFAULT_METHOD }, this.requestInit); - init.body = new FormData(); - weightsManifest = [{ - paths: ['./model.weights.bin'], - weights: modelArtifacts.weightSpecs, - }]; - modelTopologyAndWeightManifest = { - modelTopology: modelArtifacts.modelTopology, - format: modelArtifacts.format, - generatedBy: modelArtifacts.generatedBy, - convertedBy: modelArtifacts.convertedBy, - userDefinedMetadata: modelArtifacts.userDefinedMetadata, - weightsManifest: weightsManifest - }; - init.body.append('model.json', new Blob([JSON.stringify(modelTopologyAndWeightManifest)], { type: JSON_TYPE }), 'model.json'); - if (modelArtifacts.weightData != null) { - init.body.append('model.weights.bin', new Blob([modelArtifacts.weightData], { type: OCTET_STREAM_MIME_TYPE }), 'model.weights.bin'); - } - return [4 /*yield*/, this.fetch(this.path, init)]; - case 1: - response = _a.sent(); - if (response.ok) { - return [2 /*return*/, { - modelArtifactsInfo: getModelArtifactsInfoForJSON(modelArtifacts), - responses: [response], - }]; - } - else { - throw new Error("BrowserHTTPRequest.save() failed due to HTTP response status " + - (response.status + ".")); - } - } - }); - }); - }; - /** - * Load model artifacts via HTTP request(s). - * - * See the documentation to `tf.io.http` for details on the saved - * artifacts. - * - * @returns The loaded model artifacts (if loading succeeds). - */ - HTTPRequest.prototype.load = function () { - return __awaiter(this, void 0, void 0, function () { - var modelConfigRequest, modelConfig, e_1, message, modelTopology, weightsManifest, generatedBy, convertedBy, format, userDefinedMetadata, weightSpecs, weightData, results; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.fetch(this.path, this.requestInit)]; - case 1: - modelConfigRequest = _a.sent(); - if (!modelConfigRequest.ok) { - throw new Error("Request to " + this.path + " failed with status code " + - (modelConfigRequest.status + ". Please verify this URL points to ") + - "the model JSON of the model to load."); - } - _a.label = 2; - case 2: - _a.trys.push([2, 4, , 5]); - return [4 /*yield*/, modelConfigRequest.json()]; - case 3: - modelConfig = _a.sent(); - return [3 /*break*/, 5]; - case 4: - e_1 = _a.sent(); - message = "Failed to parse model JSON of response from " + this.path + "."; - // TODO(nsthorat): Remove this after some time when we're comfortable that - // .pb files are mostly gone. - if (this.path.endsWith('.pb')) { - message += ' Your path contains a .pb file extension. ' + - 'Support for .pb models have been removed in TensorFlow.js 1.0 ' + - 'in favor of .json models. You can re-convert your Python ' + - 'TensorFlow model using the TensorFlow.js 1.0 conversion scripts ' + - 'or you can convert your.pb models with the \'pb2json\'' + - 'NPM script in the tensorflow/tfjs-converter repository.'; - } - else { - message += ' Please make sure the server is serving valid ' + - 'JSON for this request.'; - } - throw new Error(message); - case 5: - modelTopology = modelConfig.modelTopology; - weightsManifest = modelConfig.weightsManifest; - generatedBy = modelConfig.generatedBy; - convertedBy = modelConfig.convertedBy; - format = modelConfig.format; - userDefinedMetadata = modelConfig.userDefinedMetadata; - // We do not allow both modelTopology and weightsManifest to be missing. - if (modelTopology == null && weightsManifest == null) { - throw new Error("The JSON from HTTP path " + this.path + " contains neither model " + - "topology or manifest for weights."); - } - if (!(weightsManifest != null)) return [3 /*break*/, 7]; - return [4 /*yield*/, this.loadWeights(weightsManifest)]; - case 6: - results = _a.sent(); - weightSpecs = results[0], weightData = results[1]; - _a.label = 7; - case 7: return [2 /*return*/, { - modelTopology: modelTopology, - weightSpecs: weightSpecs, - weightData: weightData, - userDefinedMetadata: userDefinedMetadata, - generatedBy: generatedBy, - convertedBy: convertedBy, - format: format - }]; - } - }); - }); - }; - HTTPRequest.prototype.loadWeights = function (weightsManifest) { - return __awaiter(this, void 0, void 0, function () { - var weightPath, _a, prefix, suffix, pathPrefix, weightSpecs, _i, weightsManifest_1, entry, fetchURLs, buffers; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: - weightPath = Array.isArray(this.path) ? this.path[1] : this.path; - _a = parseUrl(weightPath), prefix = _a[0], suffix = _a[1]; - pathPrefix = this.weightPathPrefix || prefix; - weightSpecs = []; - for (_i = 0, weightsManifest_1 = weightsManifest; _i < weightsManifest_1.length; _i++) { - entry = weightsManifest_1[_i]; - weightSpecs.push.apply(weightSpecs, entry.weights); - } - fetchURLs = []; - weightsManifest.forEach(function (weightsGroup) { - weightsGroup.paths.forEach(function (path) { - fetchURLs.push(pathPrefix + path + suffix); - }); - }); - return [4 /*yield*/, loadWeightsAsArrayBuffer(fetchURLs, { - requestInit: this.requestInit, - fetchFunc: this.fetch, - onProgress: this.onProgress - })]; - case 1: - buffers = _b.sent(); - return [2 /*return*/, [weightSpecs, concatenateArrayBuffers(buffers)]]; - } - }); - }); - }; - HTTPRequest.URL_SCHEME_REGEX = /^https?:\/\//; - return HTTPRequest; - }()); - /** - * Extract the prefix and suffix of the url, where the prefix is the path before - * the last file, and suffix is the search params after the last file. - * ``` - * const url = 'http://tfhub.dev/model/1/tensorflowjs_model.pb?tfjs-format=file' - * [prefix, suffix] = parseUrl(url) - * // prefix = 'http://tfhub.dev/model/1/' - * // suffix = '?tfjs-format=file' - * ``` - * @param url the model url to be parsed. - */ - function parseUrl(url) { - var lastSlash = url.lastIndexOf('/'); - var lastSearchParam = url.lastIndexOf('?'); - var prefix = url.substring(0, lastSlash); - var suffix = lastSearchParam > lastSlash ? url.substring(lastSearchParam) : ''; - return [prefix + '/', suffix]; - } - function isHTTPScheme(url) { - return url.match(HTTPRequest.URL_SCHEME_REGEX) != null; - } - var httpRouter = function (url, loadOptions) { - if (typeof fetch === 'undefined' && - (loadOptions == null || loadOptions.fetchFunc == null)) { - // `http` uses `fetch` or `node-fetch`, if one wants to use it in - // an environment that is not the browser or node they have to setup a - // global fetch polyfill. - return null; - } - else { - var isHTTP = true; - if (Array.isArray(url)) { - isHTTP = url.every(function (urlItem) { return isHTTPScheme(urlItem); }); - } - else { - isHTTP = isHTTPScheme(url); - } - if (isHTTP) { - return http(url, loadOptions); - } - } - return null; - }; - IORouterRegistry.registerSaveRouter(httpRouter); - IORouterRegistry.registerLoadRouter(httpRouter); - /** - * Creates an IOHandler subtype that sends model artifacts to HTTP server. - * - * An HTTP request of the `multipart/form-data` mime type will be sent to the - * `path` URL. The form data includes artifacts that represent the topology - * and/or weights of the model. In the case of Keras-style `tf.Model`, two - * blobs (files) exist in form-data: - * - A JSON file consisting of `modelTopology` and `weightsManifest`. - * - A binary weights file consisting of the concatenated weight values. - * These files are in the same format as the one generated by - * [tfjs_converter](https://js.tensorflow.org/tutorials/import-keras.html). - * - * The following code snippet exemplifies the client-side code that uses this - * function: - * - * ```js - * const model = tf.sequential(); - * model.add( - * tf.layers.dense({units: 1, inputShape: [100], activation: 'sigmoid'})); - * - * const saveResult = await model.save(tf.io.http( - * 'http://model-server:5000/upload', {requestInit: {method: 'PUT'}})); - * console.log(saveResult); - * ``` - * - * If the default `POST` method is to be used, without any custom parameters - * such as headers, you can simply pass an HTTP or HTTPS URL to `model.save`: - * - * ```js - * const saveResult = await model.save('http://model-server:5000/upload'); - * ``` - * - * The following GitHub Gist - * https://gist.github.com/dsmilkov/1b6046fd6132d7408d5257b0976f7864 - * implements a server based on [flask](https://github.com/pallets/flask) that - * can receive the request. Upon receiving the model artifacts via the requst, - * this particular server reconsistutes instances of [Keras - * Models](https://keras.io/models/model/) in memory. - * - * - * @param path A URL path to the model. - * Can be an absolute HTTP path (e.g., - * 'http://localhost:8000/model-upload)') or a relative path (e.g., - * './model-upload'). - * @param requestInit Request configurations to be used when sending - * HTTP request to server using `fetch`. It can contain fields such as - * `method`, `credentials`, `headers`, `mode`, etc. See - * https://developer.mozilla.org/en-US/docs/Web/API/Request/Request - * for more information. `requestInit` must not have a body, because the - * body will be set by TensorFlow.js. File blobs representing the model - * topology (filename: 'model.json') and the weights of the model (filename: - * 'model.weights.bin') will be appended to the body. If `requestInit` has a - * `body`, an Error will be thrown. - * @param loadOptions Optional configuration for the loading. It includes the - * following fields: - * - weightPathPrefix Optional, this specifies the path prefix for weight - * files, by default this is calculated from the path param. - * - fetchFunc Optional, custom `fetch` function. E.g., in Node.js, - * the `fetch` from node-fetch can be used here. - * - onProgress Optional, progress callback function, fired periodically - * before the load is completed. - * @returns An instance of `IOHandler`. - */ - /** - * @doc { - * heading: 'Models', - * subheading: 'Loading', - * namespace: 'io', - * ignoreCI: true - * } - */ - function http(path, loadOptions) { - return new HTTPRequest(path, loadOptions); - } - /** - * Deprecated. Use `tf.io.http`. - * @param path - * @param loadOptions - */ - function browserHTTPRequest(path, loadOptions) { - return http(path, loadOptions); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var PassthroughLoader = /** @class */ (function () { - function PassthroughLoader(modelArtifacts) { - this.modelArtifacts = modelArtifacts; - } - PassthroughLoader.prototype.load = function () { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.modelArtifacts]; - }); - }); - }; - return PassthroughLoader; - }()); - var PassthroughSaver = /** @class */ (function () { - function PassthroughSaver(saveHandler) { - this.saveHandler = saveHandler; - } - PassthroughSaver.prototype.save = function (modelArtifacts) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.saveHandler(modelArtifacts)]; - }); - }); - }; - return PassthroughSaver; - }()); - /** - * Creates an IOHandler that loads model artifacts from memory. - * - * When used in conjunction with `tf.loadLayersModel`, an instance of - * `tf.LayersModel` (Keras-style) can be constructed from the loaded artifacts. - * - * ```js - * const model = await tf.loadLayersModel(tf.io.fromMemory( - * modelTopology, weightSpecs, weightData)); - * ``` - * - * @param modelArtifacts a object containing model topology (i.e., parsed from - * the JSON format). - * @param weightSpecs An array of `WeightsManifestEntry` objects describing the - * names, shapes, types, and quantization of the weight data. - * @param weightData A single `ArrayBuffer` containing the weight data, - * concatenated in the order described by the weightSpecs. - * @param trainingConfig Model training configuration. Optional. - * - * @returns A passthrough `IOHandler` that simply loads the provided data. - */ - function fromMemory(modelArtifacts, weightSpecs, weightData, trainingConfig) { - if (arguments.length === 1) { - var isModelArtifacts = modelArtifacts.modelTopology != null || - modelArtifacts.weightSpecs != null; - if (isModelArtifacts) { - return new PassthroughLoader(modelArtifacts); - } - else { - // Legacy support: with only modelTopology. - // TODO(cais): Remove this deprecated API. - console.warn('Please call tf.io.fromMemory() with only one argument. ' + - 'The argument should be of type ModelArtifacts. ' + - 'The multi-argument signature of tf.io.fromMemory() has been ' + - 'deprecated and will be removed in a future release.'); - return new PassthroughLoader({ modelTopology: modelArtifacts }); - } - } - else { - // Legacy support. - // TODO(cais): Remove this deprecated API. - console.warn('Please call tf.io.fromMemory() with only one argument. ' + - 'The argument should be of type ModelArtifacts. ' + - 'The multi-argument signature of tf.io.fromMemory() has been ' + - 'deprecated and will be removed in a future release.'); - return new PassthroughLoader({ - modelTopology: modelArtifacts, - weightSpecs: weightSpecs, - weightData: weightData, - trainingConfig: trainingConfig - }); - } - } - /** - * Creates an IOHandler that passes saved model artifacts to a callback. - * - * ```js - * function handleSave(artifacts) { - * // ... do something with the artifacts ... - * return {modelArtifactsInfo: {...}, ...}; - * } - * - * const saveResult = model.save(tf.io.withSaveHandler(handleSave)); - * ``` - * - * @param saveHandler A function that accepts a `ModelArtifacts` and returns a - * `SaveResult`. - */ - function withSaveHandler(saveHandler) { - return new PassthroughSaver(saveHandler); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - - var io = { - __proto__: null, - browserFiles: browserFiles, - browserHTTPRequest: browserHTTPRequest, - concatenateArrayBuffers: concatenateArrayBuffers, - decodeWeights: decodeWeights, - encodeWeights: encodeWeights, - fromMemory: fromMemory, - getLoadHandlers: getLoadHandlers, - getModelArtifactsInfoForJSON: getModelArtifactsInfoForJSON, - getSaveHandlers: getSaveHandlers, - http: http, - isHTTPScheme: isHTTPScheme, - loadWeights: loadWeights, - registerLoadRouter: registerLoadRouter, - registerSaveRouter: registerSaveRouter, - weightsLoaderFactory: weightsLoaderFactory, - withSaveHandler: withSaveHandler, - copyModel: copyModel, - listModels: listModels, - moveModel: moveModel, - removeModel: removeModel - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates a one-hot `tf.Tensor`. The locations represented by `indices` take - * value `onValue` (defaults to 1), while all other locations take value - * `offValue` (defaults to 0). If `indices` is rank `R`, the output has rank - * `R+1` with the last axis of size `depth`. - * - * ```js - * tf.oneHot(tf.tensor1d([0, 1], 'int32'), 3).print(); - * ``` - * - * @param indices `tf.Tensor` of indices with dtype `int32`. - * @param depth The depth of the one hot dimension. - * @param onValue A number used to fill in the output when the index matches - * the location. - * @param offValue A number used to fill in the output when the index does - * not match the location. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function oneHot_(indices, depth, onValue, offValue) { - if (onValue === void 0) { onValue = 1; } - if (offValue === void 0) { offValue = 0; } - if (depth < 2) { - throw new Error("Error in oneHot: depth must be >=2, but it is " + depth); - } - var $indices = convertToTensor(indices, 'indices', 'oneHot', 'int32'); - var outShape = $indices.shape.concat([depth]); - var forward = function (backend, save) { - save([$indices]); - return reshape(backend.oneHot($indices.flatten(), depth, onValue, offValue), outShape); - }; - var inputs = { indices: $indices }; - var attrs = { depth: depth, onValue: onValue, offValue: offValue }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, OneHot, attrs); - } - var oneHot = op({ oneHot_: oneHot_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the confusion matrix from true labels and predicted labels. - * - * ```js - * const labels = tf.tensor1d([0, 1, 2, 1, 0], 'int32'); - * const predictions = tf.tensor1d([0, 2, 2, 1, 0], 'int32'); - * const numClasses = 3; - * const out = tf.math.confusionMatrix(labels, predictions, numClasses); - * out.print(); - * // Expected output matrix: - * // [[2, 0, 0], - * // [0, 1, 1], - * // [0, 0, 1]] - * ``` - * - * @param labels The target labels, assumed to be 0-based integers - * for the classes. The shape is `[numExamples]`, where - * `numExamples` is the number of examples included. - * @param predictions The predicted classes, assumed to be - * 0-based integers for the classes. Must have the same shape as `labels`. - * @param numClasses Number of all classes, as an integer. - * Its value must be larger than the largest element in `labels` and - * `predictions`. - * @returns The confusion matrix as a int32-type 2D tensor. The value at - * row `r` and column `c` is the number of times examples of actual class - * `r` were predicted as class `c`. - */ - /** @doc {heading: 'Operations', subheading: 'Evaluation'} */ - function confusionMatrix_(labels, predictions, numClasses) { - var $labels = convertToTensor(labels, 'labels', 'confusionMatrix'); - var $predictions = convertToTensor(predictions, 'predictions', 'confusionMatrix'); - assert(numClasses == null || numClasses > 0 && Number.isInteger(numClasses), function () { return "If provided, numClasses must be a positive integer, " + - ("but got " + numClasses); }); - assert($labels.rank === 1, function () { return "Expected the rank of labels to be 1, but got " + $labels.rank; }); - assert($predictions.rank === 1, function () { return "Expected the rank of predictions to be 1, " + - ("but got " + $predictions.rank); }); - assert($labels.shape[0] === $predictions.shape[0], function () { return "Mismatch in the number of examples: " + - ($labels.shape[0] + " vs. " + $predictions.shape[0] + ". ") + - "Labels and predictions should have the same number of elements."; }); - assert(numClasses > 0 && Number.isInteger(numClasses), function () { return "numClasses is required to be a positive integer, but got " + - ("" + numClasses); }); - // TODO(cais): In the future, if oneHot supports tensors inputs for - // `numClasses`, `confusionMatrix` can make `numClasses` optional. - var oneHotLabels = oneHot($labels.asType('int32'), numClasses); - var oneHotPredictions = oneHot($predictions.asType('int32'), numClasses); - var oneHotLabelsT = oneHotLabels.transpose(); - return oneHotLabelsT.matMul(oneHotPredictions).asType('int32'); - } - var confusionMatrix = op({ confusionMatrix_: confusionMatrix_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - - var math = { - __proto__: null, - confusionMatrix: confusionMatrix - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates rank-3 `tf.Tensor` with the provided values, shape and dtype. - * - * The same functionality can be achieved with `tf.tensor`, but in general - * we recommend using `tf.tensor3d` as it makes the code more readable. - * - * ```js - * // Pass a nested array. - * tf.tensor3d([[[1], [2]], [[3], [4]]]).print(); - * ``` - * ```js - * // Pass a flat array and specify a shape. - * tf.tensor3d([1, 2, 3, 4], [2, 2, 1]).print(); - * ``` - * - * @param values The values of the tensor. Can be nested array of numbers, - * or a flat array, or a `TypedArray`. - * @param shape The shape of the tensor. If not provided, it is inferred from - * `values`. - * @param dtype The data type. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function tensor3d(values, shape, dtype) { - assertNonNull(values); - if (shape != null && shape.length !== 3) { - throw new Error('tensor3d() requires shape to have three numbers'); - } - var inferredShape = inferShape(values, dtype); - if (inferredShape.length !== 3 && inferredShape.length !== 1) { - throw new Error('tensor3d() requires values to be number[][][] or flat/TypedArray'); - } - if (inferredShape.length === 1 && shape == null) { - throw new Error('tensor3d() requires shape to be provided when `values` ' + - 'are a flat array'); - } - return makeTensor(values, shape, inferredShape, dtype); - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var fromPixels2DContext; - /** - * Creates a `tf.Tensor` from an image. - * - * ```js - * const image = new ImageData(1, 1); - * image.data[0] = 100; - * image.data[1] = 150; - * image.data[2] = 200; - * image.data[3] = 255; - * - * tf.browser.fromPixels(image).print(); - * ``` - * - * @param pixels The input image to construct the tensor from. The - * supported image types are all 4-channel. You can also pass in an image - * object with following attributes: - * `{data: Uint8Array; width: number; height: number}` - * @param numChannels The number of channels of the output tensor. A - * numChannels value less than 4 allows you to ignore channels. Defaults to - * 3 (ignores alpha channel of input image). - */ - /** @doc {heading: 'Browser', namespace: 'browser', ignoreCI: true} */ - function fromPixels_(pixels, numChannels) { - if (numChannels === void 0) { numChannels = 3; } - // Sanity checks. - if (numChannels > 4) { - throw new Error('Cannot construct Tensor with more than 4 channels from pixels.'); - } - if (pixels == null) { - throw new Error('pixels passed to tf.browser.fromPixels() can not be null'); - } - var isPixelData = false; - var isImageData = false; - var isVideo = false; - var isImage = false; - var isCanvasLike = false; - if (pixels.data instanceof Uint8Array) { - isPixelData = true; - } - else if (typeof (ImageData) !== 'undefined' && pixels instanceof ImageData) { - isImageData = true; - } - else if (typeof (HTMLVideoElement) !== 'undefined' && - pixels instanceof HTMLVideoElement) { - isVideo = true; - } - else if (typeof (HTMLImageElement) !== 'undefined' && - pixels instanceof HTMLImageElement) { - isImage = true; - // tslint:disable-next-line: no-any - } - else if (pixels.getContext != null) { - isCanvasLike = true; - } - else { - throw new Error('pixels passed to tf.browser.fromPixels() must be either an ' + - "HTMLVideoElement, HTMLImageElement, HTMLCanvasElement, ImageData " + - "in browser, or OffscreenCanvas, ImageData in webworker" + - " or {data: Uint32Array, width: number, height: number}, " + - ("but was " + pixels.constructor.name)); - } - if (isVideo) { - var HAVE_CURRENT_DATA_READY_STATE = 2; - if (isVideo && - pixels.readyState < - HAVE_CURRENT_DATA_READY_STATE) { - throw new Error('The video element has not loaded data yet. Please wait for ' + - '`loadeddata` event on the

    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� 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

  • h`6##Z4- zo<67Xw+GDpYEGB^D@F_`p~&H9;=hdMeqIp+ipr^4dK#;u2)0|UL^Z+$o%QjebJY&C z=Y$ZZGaSntc_P(gST|WhO5rmat3oK8l#hDrYd*P)-#}~*u17~RCGITOHp-D~Ta8A| zDmZ!?&7P=&esO7Ppdip?9pXTW6xPPFYp!TtrR?`6ppZ5rRr zHXIvfOJ@5?w$?plZ;dlzt{$<^gM=SBOu$=jjH5TO^-?Nc2FsbDu?)t&r*2UQEu@VFGBaaIaplC7n4&o|Fa?Z{GSNYcgii_bj~rwqDm~FY~JHigD49Va{pPT zy8LeUMnqE4ObpFafZTx|--u*)o4fnQMn>pv=y%^!bl#p?_!BVgiW(xC!g@S|NEVv5pf|uYe_zR&zxF8XB3VVbE;ec>dI3c79=Y>omN5~V3 zgzLh6K}z_4)pxzv*T3t$Tjc$(dZ&u~|E~KLk^Xo6?}|JpCm+{!;?aG8hqtSWuXuCo zw#GM@An`cBH$W7N@5JI%F>+FIq9?G3ed0x4_x@ru#fV7V1)_(-8xebnp@_P=u&BQw R1}ncR3J+By*CSVN{@+HkvWox! diff --git a/e2e/benchmarks/tfjs-backend-wasm.wasm b/e2e/benchmarks/tfjs-backend-wasm.wasm deleted file mode 100644 index b341cf828d85e26051acde90e7c4aefe3d85ca0c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155531 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 Date: Thu, 30 Jul 2020 13:41:06 -0400 Subject: [PATCH 31/70] revive --- tfjs-backend-wasm/scripts/build-benchmark.sh | 2 +- tfjs-backend-wasm/scripts/build-wasm.sh | 7 +++---- tfjs-backend-wasm/src/backend_wasm.ts | 11 ++++++---- tfjs-backend-wasm/src/cc/BUILD | 22 ++++++++++++++++++++ 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/tfjs-backend-wasm/scripts/build-benchmark.sh b/tfjs-backend-wasm/scripts/build-benchmark.sh index f9635006b24..dfe81513c97 100755 --- a/tfjs-backend-wasm/scripts/build-benchmark.sh +++ b/tfjs-backend-wasm/scripts/build-benchmark.sh @@ -3,5 +3,5 @@ yarn rollup -c cp dist/tf-backend-wasm.js ../e2e/benchmarks/ cp wasm-out/tfjs-backend-wasm.wasm ../e2e/benchmarks/ -# cp wasm-out/tfjs-backend-wasm-simd.wasm ../e2e/benchmarks/ +cp wasm-out/tfjs-backend-wasm-simd.wasm ../e2e/benchmarks/ cp wasm-out/tfjs-backend-wasm-threaded-simd.wasm ../e2e/benchmarks/ diff --git a/tfjs-backend-wasm/scripts/build-wasm.sh b/tfjs-backend-wasm/scripts/build-wasm.sh index 579ae80c257..b0277e7ab82 100755 --- a/tfjs-backend-wasm/scripts/build-wasm.sh +++ b/tfjs-backend-wasm/scripts/build-wasm.sh @@ -25,10 +25,9 @@ cp -f bazel-bin/src/cc/tfjs-backend-wasm.js \ wasm-out/ # # SIMD build. -# yarn bazel build -c opt //src/cc:tfjs-backend-wasm-simd.js --config=wasm --copt="-msimd128" -# cp -f bazel-bin/src/cc/tfjs-backend-wasm-simd.js \ -# bazel-bin/src/cc/tfjs-backend-wasm-simd.wasm \ -# wasm-out/ +yarn bazel build -c opt //src/cc:tfjs-backend-wasm-simd.wasm --config=wasm --copt="-msimd128" +cp -f bazel-bin/src/cc/tfjs-backend-wasm-simd.wasm \ + wasm-out/ # Threaded + SIMD build. yarn bazel build -c opt //src/cc:tfjs-backend-wasm-threaded-simd.js --config=wasm --copt="-pthread" --copt="-msimd128" diff --git a/tfjs-backend-wasm/src/backend_wasm.ts b/tfjs-backend-wasm/src/backend_wasm.ts index b557d9d9804..7204a04a0df 100644 --- a/tfjs-backend-wasm/src/backend_wasm.ts +++ b/tfjs-backend-wasm/src/backend_wasm.ts @@ -19,8 +19,6 @@ import './flags_wasm'; import {backend_util, BackendTimingInfo, DataStorage, DataType, engine, env, KernelBackend, registerBackend, TensorInfo, util} from '@tensorflow/tfjs-core'; import {BackendWasmModule, WasmFactoryConfig} from '../wasm-out/tfjs-backend-wasm'; -// import wasmFactorySimd, {BackendWasmModuleSimd} from -// '../wasm-out/tfjs-backend-wasm-simd.js'; import wasmFactoryThreadedSimd from '../wasm-out/tfjs-backend-wasm-threaded-simd.js'; // @ts-ignore import {wasmWorkerContents} from '../wasm-out/tfjs-backend-wasm-threaded-simd.worker.ts'; @@ -220,6 +218,13 @@ export async function init(): Promise<{wasm: BackendWasmModule}> { const blob = new Blob([response], {type: 'application/javascript'}); return URL.createObjectURL(blob); } + + if (path.endsWith('.wasm')) { + if (simdSupported) { + return prefix + 'tfjs-backend-wasm-simd.wasm'; + } + return prefix + 'tfjs-backend-wasm.wasm'; + } return prefix + path; }; @@ -246,8 +251,6 @@ export async function init(): Promise<{wasm: BackendWasmModule}> { [`var _scriptDir = undefined; var WasmBackendModuleSimd = ` + wasmFactoryThreadedSimd.toString()], {type: 'text/javascript'}); - // } else if (simdSupported) { - // wasm = wasmFactorySimd(factoryConfig); } else { wasm = wasmFactory(factoryConfig); } diff --git a/tfjs-backend-wasm/src/cc/BUILD b/tfjs-backend-wasm/src/cc/BUILD index f1518dbb64f..912c7b858ac 100644 --- a/tfjs-backend-wasm/src/cc/BUILD +++ b/tfjs-backend-wasm/src/cc/BUILD @@ -21,6 +21,28 @@ cc_binary( "-s MODULARIZE=1", "-s EXPORT_NAME=WasmBackendModule", "-s MALLOC=emmalloc", + "-s STANDALONE_WASM=1", + ], + deps = [ + ":all_kernels", + ":backend", + ], +) + +cc_binary( + name = "tfjs-backend-wasm-simd.wasm", + srcs = ["backend.cc"] + KERNELS_WITH_KEEPALIVE, + linkopts = [ + "-s ALLOW_MEMORY_GROWTH=1", + "-s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]", + "-s DISABLE_EXCEPTION_CATCHING=1", + "-s FILESYSTEM=0", + "-s EXIT_RUNTIME=0", + "-s EXPORTED_FUNCTIONS='[\"_malloc\", \"_free\"]'", + "-s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'", + "-s MALLOC=emmalloc", + "-s SIMD=1", + "-s STANDALONE_WASM=1", ], deps = [ ":all_kernels", From 537ea6cee73ed6321155d4af20a5ec447437ce5b Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Thu, 30 Jul 2020 14:07:52 -0400 Subject: [PATCH 32/70] revive simd --- e2e/benchmarks/tf-backend-wasm.js | 10 +++++++--- e2e/benchmarks/tfjs-backend-wasm-simd.wasm | Bin 213267 -> 214255 bytes e2e/benchmarks/tfjs-backend-wasm.wasm | Bin 154838 -> 155773 bytes 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/e2e/benchmarks/tf-backend-wasm.js b/e2e/benchmarks/tf-backend-wasm.js index f0355d21f91..c50a8c60702 100644 --- a/e2e/benchmarks/tf-backend-wasm.js +++ b/e2e/benchmarks/tf-backend-wasm.js @@ -3398,7 +3398,7 @@ function(WasmBackendModule) { WasmBackendModule = WasmBackendModule || {}; - var Module=typeof WasmBackendModule!=="undefined"?WasmBackendModule:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":146,"maximum":146+0,"element":"anyfunc"});var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023);}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var DYNAMIC_BASE=5254800,DYNAMICTOP_PTR=11760;var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":2147483648/WASM_PAGE_SIZE});}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;removeRunDependency();}addRunDependency();function receiveInstantiatedSource(output){receiveInstance(output["instance"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}__ATINIT__.push({func:function(){___wasm_call_ctors();}});function _abort(){abort();}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num);}function _emscripten_get_heap_size(){return HEAPU8.length}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=65536;var maxHeapSize=2147483648;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}var asmLibraryArg={"a":_abort,"e":_emscripten_memcpy_big,"f":_emscripten_resize_heap,"g":_fd_close,"d":_fd_seek,"c":_fd_write,"memory":wasmMemory,"b":_roundf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return (___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["h"]).apply(null,arguments)};var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["i"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["j"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["k"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["l"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["m"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["n"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["o"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["p"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["q"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["r"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["s"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["t"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["u"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["v"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["w"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["x"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["y"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["z"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["A"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["B"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["C"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["D"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["E"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["F"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["G"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["H"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["I"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["J"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["K"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["L"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["M"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["N"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["O"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["P"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["Q"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["R"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["S"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["T"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["U"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["V"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["W"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["X"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["Y"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["Z"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["_"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["$"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["aa"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["ba"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["ca"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["da"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["ea"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["fa"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["ga"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["ha"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["ia"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["ja"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["ka"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["la"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["ma"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["na"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["oa"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["pa"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["qa"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["ra"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["sa"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["ta"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["ua"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["va"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["wa"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["xa"]).apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){return (dynCall_vi=Module["dynCall_vi"]=Module["asm"]["ya"]).apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){return (dynCall_v=Module["dynCall_v"]=Module["asm"]["za"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}noExitRuntime=true;run(); + var Module=typeof WasmBackendModule!=="undefined"?WasmBackendModule:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":147,"maximum":147+0,"element":"anyfunc"});var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023);}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer);}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=exports["memory"];updateGlobalBufferAndViews(wasmMemory.buffer);removeRunDependency();}addRunDependency();function receiveInstantiatedSource(output){receiveInstance(output["instance"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}__ATINIT__.push();function _emscripten_notify_memory_growth(memoryIndex){updateGlobalBufferAndViews(wasmMemory.buffer);}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _exit(status){exit(status);}function _proc_exit(code){_exit(code);}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}var asmLibraryArg={"emscripten_notify_memory_growth":_emscripten_notify_memory_growth,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"proc_exit":_proc_exit,"roundf":_roundf};var asm=createWasm();Module["asm"]=asm;var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["init"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["register_tensor"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["dispose_data"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["dispose"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["Abs"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["Add"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["AddN"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["ArgMax"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["AvgPool"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["BatchMatMul"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["ClipByValue"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["Conv2D"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["Conv2DBackpropInput"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["Cos"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["CropAndResize"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["DepthwiseConv2dNative"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["Div"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["Equal"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["Exp"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["FloorDiv"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["FusedBatchNorm"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["FusedConv2D"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["FusedDepthwiseConv2D"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["Gather"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["GatherNd"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["Greater"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["GreaterEqual"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["Less"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["LessEqual"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["Log"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["LogicalAnd"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["Max"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["MaxPool"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["Maximum"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["Min"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["Minimum"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["Multiply"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["Negate"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["NonMaxSuppressionV3"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["NonMaxSuppressionV4"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["NonMaxSuppressionV5"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["NotEqual"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["OneHot"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["PadV2"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["Pow"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["Prelu"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["Relu"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["Relu6"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["ResizeBilinear"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["Reverse"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["RotateWithOffset"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["Rsqrt"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["ScatterNd"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["SelectV2"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["Sigmoid"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["Sin"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["Softmax"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["Sqrt"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["Square"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["Sub"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["Sum"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["Tanh"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["Tile"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["Transpose"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["_FusedMatMul"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["malloc"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["free"]).apply(null,arguments)};var __start=Module["__start"]=function(){return (__start=Module["__start"]=Module["asm"]["_start"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["stackSave"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["stackAlloc"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["stackRestore"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function callMain(args){var entryFunction=Module["__start"];try{entryFunction();var ret=0;exit(ret,true);}catch(e){if(e instanceof ExitStatus){return}else if(e=="unwind"){noExitRuntime=true;return}else{var toLog=e;if(e&&typeof e==="object"&&e.stack){toLog=[e,e.stack];}err("exception thrown: "+toLog);quit_(1,e);}}finally{}}function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;function exit(status,implicit){if(implicit&&noExitRuntime&&status===0){return}if(noExitRuntime);else{ABORT=true;if(Module["onExit"])Module["onExit"](status);}quit_(status,new ExitStatus(status));}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;noExitRuntime=true;run(); return WasmBackendModule @@ -3572,6 +3572,12 @@ const blob = new Blob([response], { type: 'application/javascript' }); return URL.createObjectURL(blob); } + if (path.endsWith('.wasm')) { + if (simdSupported) { + return prefix + 'tfjs-backend-wasm-simd.wasm'; + } + return prefix + 'tfjs-backend-wasm.wasm'; + } return prefix + path; }; factoryConfig.locateFile = locateFile; @@ -3594,8 +3600,6 @@ wasm = tfjsBackendWasmThreadedSimd(factoryConfig); wasm.mainScriptUrlOrBlob = new Blob([`var _scriptDir = undefined; var WasmBackendModuleSimd = ` + tfjsBackendWasmThreadedSimd.toString()], { type: 'text/javascript' }); - // } else if (simdSupported) { - // wasm = wasmFactorySimd(factoryConfig); } else { wasm = tfjsBackendWasm(factoryConfig); diff --git a/e2e/benchmarks/tfjs-backend-wasm-simd.wasm b/e2e/benchmarks/tfjs-backend-wasm-simd.wasm index ef55ad6ec8e3d0e6b5fd69c929d83db4b453376f..9af56a4c638d434077b11c8e334ebacfc5589c13 100644 GIT binary patch delta 15014 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 F{|6c_HH-iN diff --git a/e2e/benchmarks/tfjs-backend-wasm.wasm b/e2e/benchmarks/tfjs-backend-wasm.wasm index d876cd489ce6aa24771103715f88a489a2c68081..e8b4207c6b96a50f9496d91c0c560f145e14345e 100644 GIT binary patch delta 13922 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 delta 13095 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 G(EkGdZ(0Qa From a8b47d2553296f881077a12c40f7ea2be0bbec19 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Thu, 30 Jul 2020 14:11:51 -0400 Subject: [PATCH 33/70] fix --- e2e/benchmarks/tf-backend-wasm.js | 479 +++++++++++++------------- tfjs-backend-wasm/src/backend_wasm.ts | 3 + 2 files changed, 244 insertions(+), 238 deletions(-) diff --git a/e2e/benchmarks/tf-backend-wasm.js b/e2e/benchmarks/tf-backend-wasm.js index c50a8c60702..84c30ec100f 100644 --- a/e2e/benchmarks/tf-backend-wasm.js +++ b/e2e/benchmarks/tf-backend-wasm.js @@ -1,30 +1,30 @@ -/** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tensorflow/tfjs-core'), require('path'), require('fs'), require('worker_threads'), require('perf_hooks')) : - typeof define === 'function' && define.amd ? define(['exports', '@tensorflow/tfjs-core', 'path', 'fs', 'worker_threads', 'perf_hooks'], factory) : - (global = global || self, factory((global.tf = global.tf || {}, global.tf.wasm = global.tf.wasm || {}), global.tf, global.path, global.fs, global.worker_threads, global.perf_hooks)); -}(this, (function (exports, tfjsCore, path, fs, worker_threads, perf_hooks) { 'use strict'; - - path = path && path.hasOwnProperty('default') ? path['default'] : path; - fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; - worker_threads = worker_threads && worker_threads.hasOwnProperty('default') ? worker_threads['default'] : worker_threads; - perf_hooks = perf_hooks && perf_hooks.hasOwnProperty('default') ? perf_hooks['default'] : perf_hooks; - +/** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tensorflow/tfjs-core'), require('path'), require('fs'), require('worker_threads'), require('perf_hooks')) : + typeof define === 'function' && define.amd ? define(['exports', '@tensorflow/tfjs-core', 'path', 'fs', 'worker_threads', 'perf_hooks'], factory) : + (global = global || self, factory((global.tf = global.tf || {}, global.tf.wasm = global.tf.wasm || {}), global.tf, global.path, global.fs, global.worker_threads, global.perf_hooks)); +}(this, (function (exports, tfjsCore, path, fs, worker_threads, perf_hooks) { 'use strict'; + + path = path && path.hasOwnProperty('default') ? path['default'] : path; + fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; + worker_threads = worker_threads && worker_threads.hasOwnProperty('default') ? worker_threads['default'] : worker_threads; + perf_hooks = perf_hooks && perf_hooks.hasOwnProperty('default') ? perf_hooks['default'] : perf_hooks; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -57,8 +57,8 @@ FusableActivation[FusableActivation["relu"] = 1] = "relu"; FusableActivation[FusableActivation["relu6"] = 2] = "relu6"; FusableActivation[FusableActivation["prelu"] = 3] = "prelu"; - })(FusableActivation || (FusableActivation = {})); - + })(FusableActivation || (FusableActivation = {})); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -133,8 +133,8 @@ backendName: 'wasm', setupFunc: setup, kernelFunc: fusedBatchMatMul - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -170,8 +170,8 @@ return out; } return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; - } - + } + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -188,8 +188,8 @@ * limitations under the License. * ============================================================================= */ - const absConfig = createUnaryKernelConfig(tfjsCore.Abs); - + const absConfig = createUnaryKernelConfig(tfjsCore.Abs); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -255,8 +255,8 @@ } } return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; - } - + } + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -274,8 +274,8 @@ * ============================================================================= */ const supportsFullBroadcast = true; - const addConfig = createBinaryKernelConfig(tfjsCore.Add, supportsFullBroadcast); - + const addConfig = createBinaryKernelConfig(tfjsCore.Add, supportsFullBroadcast); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -319,8 +319,8 @@ backendName: 'wasm', setupFunc, kernelFunc: addn, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -349,8 +349,8 @@ kernelName: tfjsCore.Identity, backendName: 'wasm', kernelFunc: identity, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -444,8 +444,8 @@ backendName: 'wasm', kernelFunc: transpose, setupFunc: setup$1, - }; - + }; + /** * @license * Copyright 2020 Google Inc. All Rights Reserved. @@ -493,8 +493,8 @@ } } return { transposed: xTransposed, originalAxes, axes, inputWasTransposed }; - } - + } + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -555,8 +555,8 @@ backendName: 'wasm', kernelFunc: argmax, setupFunc: setup$2 - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -625,8 +625,8 @@ backendName: 'wasm', setupFunc: setup$3, kernelFunc: avgPool - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -681,8 +681,8 @@ backendName: 'wasm', setupFunc: setup$4, kernelFunc: batchMatMul - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -711,8 +711,8 @@ kernelName: tfjsCore.Cast, backendName: 'wasm', kernelFunc: cast, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -753,8 +753,8 @@ backendName: 'wasm', setupFunc: setup$5, kernelFunc: clip - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -801,8 +801,8 @@ kernelName: tfjsCore.Concat, backendName: 'wasm', kernelFunc: concat, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -878,8 +878,8 @@ backendName: 'wasm', setupFunc: setup$6, kernelFunc: conv2d - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -962,8 +962,8 @@ backendName: 'wasm', setupFunc: setup$7, kernelFunc: conv2DBackpropInput - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -980,8 +980,8 @@ * limitations under the License. * ============================================================================= */ - const cosConfig = createUnaryKernelConfig(tfjsCore.Cos); - + const cosConfig = createUnaryKernelConfig(tfjsCore.Cos); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1049,8 +1049,8 @@ backendName: 'wasm', setupFunc: setup$8, kernelFunc: cropAndResize - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1127,8 +1127,8 @@ backendName: 'wasm', setupFunc: setup$9, kernelFunc: depthwiseConv2d - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1146,8 +1146,8 @@ * ============================================================================= */ const supportsFullBroadcast$1 = true; - const divConfig = createBinaryKernelConfig(tfjsCore.Div, supportsFullBroadcast$1); - + const divConfig = createBinaryKernelConfig(tfjsCore.Div, supportsFullBroadcast$1); + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -1165,8 +1165,8 @@ * ============================================================================= */ const supportsFullBroadcast$2 = false; - const equalConfig = createBinaryKernelConfig(tfjsCore.Equal, supportsFullBroadcast$2, 'bool'); - + const equalConfig = createBinaryKernelConfig(tfjsCore.Equal, supportsFullBroadcast$2, 'bool'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1183,8 +1183,8 @@ * limitations under the License. * ============================================================================= */ - const expConfig = createUnaryKernelConfig(tfjsCore.Exp); - + const expConfig = createUnaryKernelConfig(tfjsCore.Exp); + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -1212,8 +1212,8 @@ kernelName: tfjsCore.Fill, backendName: 'wasm', kernelFunc: fill, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1231,8 +1231,8 @@ * ============================================================================= */ const supportsFullBroadcast$3 = false; - const floorDivConfig = createBinaryKernelConfig(tfjsCore.FloorDiv, supportsFullBroadcast$3); - + const floorDivConfig = createBinaryKernelConfig(tfjsCore.FloorDiv, supportsFullBroadcast$3); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1276,8 +1276,8 @@ backendName: 'wasm', setupFunc: setup$a, kernelFunc: fusedBatchNorm - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1379,8 +1379,8 @@ backendName: 'wasm', setupFunc: setup$b, kernelFunc: fusedConv2d - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1483,8 +1483,8 @@ backendName: 'wasm', setupFunc: setup$c, kernelFunc: fusedDepthwiseConv2d - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1538,8 +1538,8 @@ backendName: 'wasm', setupFunc: setup$d, kernelFunc: gatherNd - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1599,8 +1599,8 @@ backendName: 'wasm', setupFunc: setup$e, kernelFunc: gatherV2 - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1618,8 +1618,8 @@ * ============================================================================= */ const supportsFullBroadcast$4 = false; - const greaterConfig = createBinaryKernelConfig(tfjsCore.Greater, supportsFullBroadcast$4, 'bool'); - + const greaterConfig = createBinaryKernelConfig(tfjsCore.Greater, supportsFullBroadcast$4, 'bool'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1637,8 +1637,8 @@ * ============================================================================= */ const supportsFullBroadcast$5 = false; - const greaterEqualConfig = createBinaryKernelConfig(tfjsCore.GreaterEqual, supportsFullBroadcast$5, 'bool'); - + const greaterEqualConfig = createBinaryKernelConfig(tfjsCore.GreaterEqual, supportsFullBroadcast$5, 'bool'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1656,8 +1656,8 @@ * ============================================================================= */ const supportsFullBroadcast$6 = false; - const lessConfig = createBinaryKernelConfig(tfjsCore.Less, supportsFullBroadcast$6, 'bool'); - + const lessConfig = createBinaryKernelConfig(tfjsCore.Less, supportsFullBroadcast$6, 'bool'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1675,8 +1675,8 @@ * ============================================================================= */ const supportsFullBroadcast$7 = false; - const lessEqualConfig = createBinaryKernelConfig(tfjsCore.LessEqual, supportsFullBroadcast$7, 'bool'); - + const lessEqualConfig = createBinaryKernelConfig(tfjsCore.LessEqual, supportsFullBroadcast$7, 'bool'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1693,8 +1693,8 @@ * limitations under the License. * ============================================================================= */ - const logConfig = createUnaryKernelConfig(tfjsCore.Log); - + const logConfig = createUnaryKernelConfig(tfjsCore.Log); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1712,8 +1712,8 @@ * ============================================================================= */ const supportsFullBroadcast$8 = false; - const logicalAndConfig = createBinaryKernelConfig(tfjsCore.LogicalAnd, supportsFullBroadcast$8, 'bool'); - + const logicalAndConfig = createBinaryKernelConfig(tfjsCore.LogicalAnd, supportsFullBroadcast$8, 'bool'); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1772,8 +1772,8 @@ backendName: 'wasm', setupFunc: setup$f, kernelFunc: max - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1791,8 +1791,8 @@ * ============================================================================= */ const supportsFullBroadcast$9 = false; - const maximumConfig = createBinaryKernelConfig(tfjsCore.Maximum, supportsFullBroadcast$9); - + const maximumConfig = createBinaryKernelConfig(tfjsCore.Maximum, supportsFullBroadcast$9); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1863,8 +1863,8 @@ backendName: 'wasm', setupFunc: setup$g, kernelFunc: maxPool - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1927,8 +1927,8 @@ backendName: 'wasm', setupFunc: setup$h, kernelFunc: min - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1946,8 +1946,8 @@ * ============================================================================= */ const supportsFullBroadcast$a = false; - const minimumConfig = createBinaryKernelConfig(tfjsCore.Minimum, supportsFullBroadcast$a); - + const minimumConfig = createBinaryKernelConfig(tfjsCore.Minimum, supportsFullBroadcast$a); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -1965,8 +1965,8 @@ * ============================================================================= */ const supportsFullBroadcast$b = true; - const multiplyConfig = createBinaryKernelConfig(tfjsCore.Multiply, supportsFullBroadcast$b); - + const multiplyConfig = createBinaryKernelConfig(tfjsCore.Multiply, supportsFullBroadcast$b); + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -1983,8 +1983,8 @@ * limitations under the License. * ============================================================================= */ - const negateConfig = createUnaryKernelConfig(tfjsCore.Negate); - + const negateConfig = createUnaryKernelConfig(tfjsCore.Negate); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2014,8 +2014,8 @@ // Since the result was allocated on the heap, we have to delete it. backend.wasm._free(resOffset); return { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs }; - } - + } + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2062,8 +2062,8 @@ backendName: 'wasm', setupFunc: setup$i, kernelFunc: kernelFunc, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2111,8 +2111,8 @@ backendName: 'wasm', setupFunc: setup$j, kernelFunc: nonMaxSuppressionV4, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2161,8 +2161,8 @@ backendName: 'wasm', setupFunc: setup$k, kernelFunc: kernelFunc$1, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2180,8 +2180,8 @@ * ============================================================================= */ const supportsFullBroadcast$c = false; - const notEqualConfig = createBinaryKernelConfig(tfjsCore.NotEqual, supportsFullBroadcast$c, 'bool'); - + const notEqualConfig = createBinaryKernelConfig(tfjsCore.NotEqual, supportsFullBroadcast$c, 'bool'); + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2224,8 +2224,8 @@ backendName: 'wasm', setupFunc: setup$l, kernelFunc: oneHot, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2253,8 +2253,8 @@ kernelName: tfjsCore.OnesLike, backendName: 'wasm', kernelFunc: onesLike, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2303,8 +2303,8 @@ backendName: 'wasm', kernelFunc: pad, setupFunc: setup$m - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2322,8 +2322,8 @@ * ============================================================================= */ const supportsFullBroadcast$d = false; - const powConfig = createBinaryKernelConfig(tfjsCore.Pow, supportsFullBroadcast$d); - + const powConfig = createBinaryKernelConfig(tfjsCore.Pow, supportsFullBroadcast$d); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2363,8 +2363,8 @@ backendName: 'wasm', setupFunc: setup$n, kernelFunc: prelu - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2381,8 +2381,8 @@ * limitations under the License. * ============================================================================= */ - const reluConfig = createUnaryKernelConfig(tfjsCore.Relu); - + const reluConfig = createUnaryKernelConfig(tfjsCore.Relu); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2399,8 +2399,8 @@ * limitations under the License. * ============================================================================= */ - const relu6Config = createUnaryKernelConfig(tfjsCore.Relu6); - + const relu6Config = createUnaryKernelConfig(tfjsCore.Relu6); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2427,8 +2427,8 @@ kernelName: tfjsCore.Reshape, backendName: 'wasm', kernelFunc: reshape, - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2490,8 +2490,8 @@ backendName: 'wasm', setupFunc: setup$o, kernelFunc: resizeBilinear - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2540,8 +2540,8 @@ backendName: 'wasm', kernelFunc: reverse, setupFunc: setup$p - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2597,8 +2597,8 @@ backendName: 'wasm', kernelFunc: rotateWithOffset, setupFunc: setup$q - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2615,8 +2615,8 @@ * limitations under the License. * ============================================================================= */ - const rsqrtConfig = createUnaryKernelConfig(tfjsCore.Rsqrt); - + const rsqrtConfig = createUnaryKernelConfig(tfjsCore.Rsqrt); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2670,8 +2670,8 @@ backendName: 'wasm', setupFunc: setup$r, kernelFunc: scatterNd - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2719,8 +2719,8 @@ backendName: 'wasm', kernelFunc: select, setupFunc: setup$s - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2758,8 +2758,8 @@ backendName: 'wasm', setupFunc: setup$t, kernelFunc: sigmoid - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2776,8 +2776,8 @@ * limitations under the License. * ============================================================================= */ - const sinConfig = createUnaryKernelConfig(tfjsCore.Sin); - + const sinConfig = createUnaryKernelConfig(tfjsCore.Sin); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -2880,8 +2880,8 @@ kernelName: tfjsCore.Slice, backendName: 'wasm', kernelFunc: slice, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2926,8 +2926,8 @@ backendName: 'wasm', setupFunc: setup$u, kernelFunc: softmax - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2964,8 +2964,8 @@ kernelName: tfjsCore.SplitV, backendName: 'wasm', kernelFunc: split - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -2982,8 +2982,8 @@ * limitations under the License. * ============================================================================= */ - const sqrtConfig = createUnaryKernelConfig(tfjsCore.Sqrt); - + const sqrtConfig = createUnaryKernelConfig(tfjsCore.Sqrt); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -3000,8 +3000,8 @@ * limitations under the License. * ============================================================================= */ - const squareConfig = createUnaryKernelConfig(tfjsCore.Square); - + const squareConfig = createUnaryKernelConfig(tfjsCore.Square); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -3019,8 +3019,8 @@ * ============================================================================= */ const supportsFullBroadcast$e = true; - const subConfig = createBinaryKernelConfig(tfjsCore.Sub, supportsFullBroadcast$e); - + const subConfig = createBinaryKernelConfig(tfjsCore.Sub, supportsFullBroadcast$e); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -3084,8 +3084,8 @@ backendName: 'wasm', setupFunc: setup$v, kernelFunc: sum - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -3102,8 +3102,8 @@ * limitations under the License. * ============================================================================= */ - const tanhConfig = createUnaryKernelConfig(tfjsCore.Tanh); - + const tanhConfig = createUnaryKernelConfig(tfjsCore.Tanh); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -3152,8 +3152,8 @@ backendName: 'wasm', setupFunc: setup$w, kernelFunc: tile - }; - + }; + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -3197,8 +3197,8 @@ kernelName: tfjsCore.Unpack, backendName: 'wasm', kernelFunc: unpack, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -3226,8 +3226,8 @@ kernelName: tfjsCore.ZerosLike, backendName: 'wasm', kernelFunc: zerosLike, - }; - + }; + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -3320,8 +3320,8 @@ ]; for (const kernelConfig of kernelConfigs) { tfjsCore.registerKernel(kernelConfig); - } - + } + /** * @license * Copyright 2020 Google LLC. All Rights Reserved. @@ -3364,50 +3364,50 @@ catch (e) { return false; } - }); - - function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; - } - - var tfjsBackendWasmThreadedSimd = createCommonjsModule(function (module, exports) { - var WasmBackendModuleSimd = (function() { - var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; - if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; - return ( - function(WasmBackendModuleSimd) { - WasmBackendModuleSimd = WasmBackendModuleSimd || {}; - - function GROWABLE_HEAP_I8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP8}function GROWABLE_HEAP_U8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU8}function GROWABLE_HEAP_I32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP32}function GROWABLE_HEAP_U32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPF64}var Module=typeof WasmBackendModuleSimd!=="undefined"?WasmBackendModuleSimd:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var ENVIRONMENT_IS_PTHREAD=Module["ENVIRONMENT_IS_PTHREAD"]||false;if(ENVIRONMENT_IS_PTHREAD){buffer=Module["buffer"];DYNAMIC_BASE=Module["DYNAMIC_BASE"];DYNAMICTOP_PTR=Module["DYNAMICTOP_PTR"];}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};var nodeWorkerThreads;try{nodeWorkerThreads=worker_threads;}catch(e){console.error('The "worker_threads" module is not supported in this node.js build - perhaps a newer version is needed?');throw e}Worker=nodeWorkerThreads.Worker;}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}if(ENVIRONMENT_IS_NODE){read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};}else{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}if(ENVIRONMENT_IS_NODE){if(typeof performance==="undefined"){performance=perf_hooks.performance;}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":165,"maximum":165+0,"element":"anyfunc"});var wasmModule;var threadInfoStruct=0;var selfThreadId=0;var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx)){var u0=heap[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heap[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heap[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2;}else{u0=(u0&7)<<18|u1<<12|u2<<6|heap[idx++]&63;}if(u0<65536){str+=String.fromCharCode(u0);}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023);}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4;}return len}function writeArrayToMemory(array,buffer){GROWABLE_HEAP_I8().set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var DYNAMIC_BASE=5256288,DYNAMICTOP_PTR=12480;var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||1073741824;if(ENVIRONMENT_IS_PTHREAD){wasmMemory=Module["wasmMemory"];buffer=Module["buffer"];}else{if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":1073741824/WASM_PAGE_SIZE,"shared":true});if(!(wasmMemory.buffer instanceof SharedArrayBuffer)){err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");if(ENVIRONMENT_IS_NODE){console.log("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)");}throw Error("bad memory")}}}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);if(!ENVIRONMENT_IS_PTHREAD){GROWABLE_HEAP_I32()[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){if(ENVIRONMENT_IS_PTHREAD)return;callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){assert(!ENVIRONMENT_IS_PTHREAD,"addRunDependency cannot be used in a pthread worker");runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}if(ENVIRONMENT_IS_PTHREAD)console.error("Pthread aborting at "+(new Error).stack);what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm-threaded-simd.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmModule=module;if(!ENVIRONMENT_IS_PTHREAD){var numWorkersToLoad=PThread.unusedWorkers.length;PThread.unusedWorkers.forEach(function(w){PThread.loadWasmModuleToWorker(w,function(){if(!--numWorkersToLoad)removeRunDependency();});});}}if(!ENVIRONMENT_IS_PTHREAD){addRunDependency();}function receiveInstantiatedSource(output){receiveInstance(output["instance"],output["module"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}var ASM_CONSTS={};function initPthreadsJS(){PThread.initRuntime();}if(!ENVIRONMENT_IS_PTHREAD)__ATINIT__.push({func:function(){___wasm_call_ctors();}});var __pthread_ptr=0;var __pthread_is_main_runtime_thread=0;var __pthread_is_main_browser_thread=0;function __register_pthread_ptr(pthreadPtr,isMainBrowserThread,isMainRuntimeThread){pthreadPtr=pthreadPtr|0;isMainBrowserThread=isMainBrowserThread|0;isMainRuntimeThread=isMainRuntimeThread|0;__pthread_ptr=pthreadPtr;__pthread_is_main_browser_thread=isMainBrowserThread;__pthread_is_main_runtime_thread=isMainRuntimeThread;}Module["__register_pthread_ptr"]=__register_pthread_ptr;var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var __main_thread_futex_wait_address=13392;function _emscripten_futex_wake(addr,count){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0||count<0)return -28;if(count==0)return 0;if(count>=2147483647)count=Infinity;var mainThreadWaitAddress=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);var mainThreadWoken=0;if(mainThreadWaitAddress==addr){var loadedAddr=Atomics.compareExchange(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,mainThreadWaitAddress,0);if(loadedAddr==mainThreadWaitAddress){--count;mainThreadWoken=1;if(count<=0)return 1}}var ret=Atomics.notify(GROWABLE_HEAP_I32(),addr>>2,count);if(ret>=0)return ret+mainThreadWoken;throw "Atomics.notify returned an unexpected value "+ret}Module["_emscripten_futex_wake"]=_emscripten_futex_wake;function __kill_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _kill_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _kill_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];pthread.worker.terminate();PThread.freeThreadData(pthread);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(pthread.worker),1);pthread.worker.pthread=undefined;}function __cancel_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cancel_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cancel_thread!";var pthread=PThread.pthreads[pthread_ptr];pthread.worker.postMessage({"cmd":"cancel"});}function __cleanup_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cleanup_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cleanup_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];if(pthread){var worker=pthread.worker;PThread.returnWorkerToPool(worker);}}var PThread={MAIN_THREAD_ID:1,mainThreadInfo:{schedPolicy:0,schedPrio:0},unusedWorkers:[],runningWorkers:[],initRuntime:function(){__register_pthread_ptr(PThread.mainThreadBlock,!ENVIRONMENT_IS_WORKER,1);_emscripten_register_main_browser_thread_id(PThread.mainThreadBlock);},initMainThreadBlock:function(){var pthreadPoolSize=8;for(var i=0;i>2]=PThread.mainThreadBlock;var headPtr=PThread.mainThreadBlock+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var tlsMemory=12880;for(var i=0;i<128;++i)GROWABLE_HEAP_U32()[tlsMemory/4+i]=0;Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+104>>2,tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+40>>2,PThread.mainThreadBlock);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+44>>2,42);},initWorker:function(){},pthreads:{},exitHandlers:null,setThreadStatus:function(){},runExitHandlers:function(){if(PThread.exitHandlers!==null){while(PThread.exitHandlers.length>0){PThread.exitHandlers.pop()();}PThread.exitHandlers=null;}if(ENVIRONMENT_IS_PTHREAD&&threadInfoStruct)___pthread_tsd_run_dtors();},threadExit:function(exitCode){var tb=_pthread_self();if(tb){Atomics.store(GROWABLE_HEAP_U32(),tb+4>>2,exitCode);Atomics.store(GROWABLE_HEAP_U32(),tb+0>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+60>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+64>>2,0);PThread.runExitHandlers();_emscripten_futex_wake(tb+0,2147483647);__register_pthread_ptr(0,0,0);threadInfoStruct=0;if(ENVIRONMENT_IS_PTHREAD){postMessage({"cmd":"exit"});}}},threadCancel:function(){PThread.runExitHandlers();Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+4>>2,-1);Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+0>>2,1);_emscripten_futex_wake(threadInfoStruct+0,2147483647);threadInfoStruct=selfThreadId=0;__register_pthread_ptr(0,0,0);postMessage({"cmd":"cancelDone"});},terminateAllThreads:function(){for(var t in PThread.pthreads){var pthread=PThread.pthreads[t];if(pthread&&pthread.worker){PThread.returnWorkerToPool(pthread.worker);}}PThread.pthreads={};for(var i=0;i>2];GROWABLE_HEAP_I32()[pthread.threadInfoStruct+104>>2]=0;_free(tlsMemory);_free(pthread.threadInfoStruct);}pthread.threadInfoStruct=0;if(pthread.allocatedOwnStack&&pthread.stackBase)_free(pthread.stackBase);pthread.stackBase=0;if(pthread.worker)pthread.worker.pthread=null;},returnWorkerToPool:function(worker){delete PThread.pthreads[worker.pthread.thread];PThread.unusedWorkers.push(worker);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);PThread.freeThreadData(worker.pthread);worker.pthread=undefined;},receiveObjectTransfer:function(data){},loadWasmModuleToWorker:function(worker,onFinishedLoading){worker.onmessage=function(e){var d=e["data"];var cmd=d["cmd"];if(worker.pthread)PThread.currentProxiedOperationCallerThread=worker.pthread.threadInfoStruct;if(d["targetThread"]&&d["targetThread"]!=_pthread_self()){var thread=PThread.pthreads[d.targetThread];if(thread){thread.worker.postMessage(e.data,d["transferList"]);}else{console.error('Internal error! Worker sent a message "'+cmd+'" to target pthread '+d["targetThread"]+", but that thread no longer exists!");}PThread.currentProxiedOperationCallerThread=undefined;return}if(cmd==="processQueuedMainThreadWork"){_emscripten_main_thread_process_queued_calls();}else if(cmd==="spawnThread"){__spawn_thread(e.data);}else if(cmd==="cleanupThread"){__cleanup_thread(d["thread"]);}else if(cmd==="killThread"){__kill_thread(d["thread"]);}else if(cmd==="cancelThread"){__cancel_thread(d["thread"]);}else if(cmd==="loaded"){worker.loaded=true;if(onFinishedLoading)onFinishedLoading(worker);if(worker.runPthread){worker.runPthread();delete worker.runPthread;}}else if(cmd==="print"){out("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="printErr"){err("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="alert"){alert("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="exit"){var detached=worker.pthread&&Atomics.load(GROWABLE_HEAP_U32(),worker.pthread.thread+68>>2);if(detached){PThread.returnWorkerToPool(worker);}}else if(cmd==="cancelDone"){PThread.returnWorkerToPool(worker);}else if(cmd==="objectTransfer"){PThread.receiveObjectTransfer(e.data);}else if(e.data.target==="setimmediate"){worker.postMessage(e.data);}else{err("worker sent an unknown command "+cmd);}PThread.currentProxiedOperationCallerThread=undefined;};worker.onerror=function(e){err("pthread sent an error! "+e.filename+":"+e.lineno+": "+e.message);};if(ENVIRONMENT_IS_NODE){worker.on("message",function(data){worker.onmessage({data:data});});worker.on("error",function(data){worker.onerror(data);});worker.on("exit",function(data){console.log("worker exited - TODO: update the worker queue?");});}worker.postMessage({"cmd":"load","urlOrBlob":Module["mainScriptUrlOrBlob"]||_scriptDir,"wasmMemory":wasmMemory,"wasmModule":wasmModule,"DYNAMIC_BASE":DYNAMIC_BASE,"DYNAMICTOP_PTR":DYNAMICTOP_PTR});},allocateUnusedWorker:function(){var pthreadMainJs=locateFile("tfjs-backend-wasm-threaded-simd.worker.js");PThread.unusedWorkers.push(new Worker(pthreadMainJs));},getNewWorker:function(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]);}if(PThread.unusedWorkers.length>0)return PThread.unusedWorkers.pop();else return null},busySpinWait:function(msecs){var t=performance.now()+msecs;while(performance.now()>2]=value;return value}function _atexit(func,arg){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(1,1,func,arg);}function __emscripten_notify_thread_queue(targetThreadId,mainThreadId){if(targetThreadId==mainThreadId){postMessage({"cmd":"processQueuedMainThreadWork"});}else if(ENVIRONMENT_IS_PTHREAD){postMessage({"targetThread":targetThreadId,"cmd":"processThreadQueue"});}else{var pthread=PThread.pthreads[targetThreadId];var worker=pthread&&pthread.worker;if(!worker){return}worker.postMessage({"cmd":"processThreadQueue"});}return 1}function _abort(){abort();}function _emscripten_conditional_set_current_thread_status(expectedStatus,newStatus){}function _emscripten_futex_wait(addr,val,timeout){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0)return -28;if(ENVIRONMENT_IS_WORKER){var ret=Atomics.wait(GROWABLE_HEAP_I32(),addr>>2,val,timeout);if(ret==="timed-out")return -73;if(ret==="not-equal")return -6;if(ret==="ok")return 0;throw "Atomics.wait returned an unexpected value "+ret}else{var loadedVal=Atomics.load(GROWABLE_HEAP_I32(),addr>>2);if(val!=loadedVal)return -6;var tNow=performance.now();var tEnd=tNow+timeout;Atomics.store(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,addr);var ourWaitAddress=addr;while(addr==ourWaitAddress){tNow=performance.now();if(tNow>tEnd){return -73}_emscripten_main_thread_process_queued_calls();addr=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);}return 0}}function _emscripten_is_main_browser_thread(){return __pthread_is_main_browser_thread|0}function _emscripten_is_main_runtime_thread(){return __pthread_is_main_runtime_thread|0}function _emscripten_memcpy_big(dest,src,num){GROWABLE_HEAP_U8().copyWithin(dest,src,src+num);}function _emscripten_num_logical_cores(){return navigator["hardwareConcurrency"]}function _emscripten_proxy_to_main_thread_js(index,sync){var numCallArgs=arguments.length-2;var stack=stackSave();var args=stackAlloc(numCallArgs*8);var b=args>>3;for(var i=0;i>3]);buf+=8;}else{buf=buf+3&~3;args.push(GROWABLE_HEAP_I32()[buf>>2]);buf+=4;}}return args}function _emscripten_receive_on_main_thread_js(index,numCallArgs,args){_emscripten_receive_on_main_thread_js_callArgs.length=numCallArgs;var b=args>>3;for(var i=0;i>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();if(requestedSize<=oldSize){return false}var PAGE_MULTIPLE=65536;var maxHeapSize=1073741824;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var JSEvents={keyEvent:0,mouseEvent:0,wheelEvent:0,uiEvent:0,focusEvent:0,deviceOrientationEvent:0,deviceMotionEvent:0,fullscreenChangeEvent:0,pointerlockChangeEvent:0,visibilityChangeEvent:0,touchEvent:0,previousFullscreenElement:null,previousScreenX:null,previousScreenY:null,removeEventListenersRegistered:false,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i);}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[];},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){JSEvents.removeEventListenersRegistered=true;}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence>2]=eventTypeId;GROWABLE_HEAP_I32()[varargs+4>>2]=eventData;GROWABLE_HEAP_I32()[varargs+8>>2]=userData;_emscripten_async_queue_on_thread_(targetThread,637534208,eventHandlerFunc,eventData,varargs);stackRestore(stackTop);},getTargetThreadForEventCallback:function(targetThread){switch(targetThread){case 1:return 0;case 2:return PThread.currentProxiedOperationCallerThread;default:return targetThread}},getNodeNameForTarget:function(target){if(!target)return "";if(target==window)return "#window";if(target==screen)return "#screen";return target&&target.nodeName?target.nodeName:""},fullscreenEnabled:function(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+1;var cString=_malloc(length);stringToUTF8(jsString,cString,length);return cString}function _emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height){var stackTop=stackSave();var varargs=stackAlloc(12);var targetCanvasPtr=0;if(targetCanvas){targetCanvasPtr=stringToNewUTF8(targetCanvas);}GROWABLE_HEAP_I32()[varargs>>2]=targetCanvasPtr;GROWABLE_HEAP_I32()[varargs+4>>2]=width;GROWABLE_HEAP_I32()[varargs+8>>2]=height;_emscripten_async_queue_on_thread_(targetThread,657457152,0,targetCanvasPtr,varargs);stackRestore(stackTop);}function _emscripten_set_offscreencanvas_size_on_target_thread(targetThread,targetCanvas,width,height){targetCanvas=targetCanvas?UTF8ToString(targetCanvas):"";_emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height);}function __maybeCStringToJsString(cString){return cString>2?UTF8ToString(cString):cString}var specialHTMLTargets=[0,typeof document!=="undefined"?document:0,typeof window!=="undefined"?window:0];function __findEventTarget(target){target=__maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!=="undefined"?document.querySelector(target):undefined);return domElement}function __findCanvasEventTarget(target){return __findEventTarget(target)}function _emscripten_set_canvas_element_size_calling_thread(target,width,height){var canvas=__findCanvasEventTarget(target);if(!canvas)return -4;if(canvas.canvasSharedPtr){GROWABLE_HEAP_I32()[canvas.canvasSharedPtr>>2]=width;GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+4>>2]=height;}if(canvas.offscreenCanvas||!canvas.controlTransferredOffscreen){if(canvas.offscreenCanvas)canvas=canvas.offscreenCanvas;var autoResizeViewport=false;if(canvas.GLctxObject&&canvas.GLctxObject.GLctx){var prevViewport=canvas.GLctxObject.GLctx.getParameter(2978);autoResizeViewport=prevViewport[0]===0&&prevViewport[1]===0&&prevViewport[2]===canvas.width&&prevViewport[3]===canvas.height;}canvas.width=width;canvas.height=height;if(autoResizeViewport){canvas.GLctxObject.GLctx.viewport(0,0,width,height);}}else if(canvas.canvasSharedPtr){var targetThread=GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+8>>2];_emscripten_set_offscreencanvas_size_on_target_thread(targetThread,target,width,height);return 1}else{return -4}return 0}function _emscripten_set_canvas_element_size_main_thread(target,width,height){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(2,1,target,width,height);return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}function _emscripten_set_canvas_element_size(target,width,height){var canvas=__findCanvasEventTarget(target);if(canvas){return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}else{return _emscripten_set_canvas_element_size_main_thread(target,width,height)}}function _emscripten_set_current_thread_status(newStatus){}function _emscripten_set_thread_name(threadId,name){}function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=function(index,divisor){ext["vertexAttribDivisorANGLE"](index,divisor);};ctx["drawArraysInstanced"]=function(mode,first,count,primcount){ext["drawArraysInstancedANGLE"](mode,first,count,primcount);};ctx["drawElementsInstanced"]=function(mode,count,type,indices,primcount){ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);};return 1}}function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=function(){return ext["createVertexArrayOES"]()};ctx["deleteVertexArray"]=function(vao){ext["deleteVertexArrayOES"](vao);};ctx["bindVertexArray"]=function(vao){ext["bindVertexArrayOES"](vao);};ctx["isVertexArray"]=function(vao){return ext["isVertexArrayOES"](vao)};return 1}}function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=function(n,bufs){ext["drawBuffersWEBGL"](n,bufs);};return 1}}var GL={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:{},currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],programInfos:{},stringCache:{},unpackAlignment:4,init:function(){var miniTempFloatBuffer=new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);for(var i=0;i>2]:-1;source+=UTF8ToString(GROWABLE_HEAP_I32()[string+i*4>>2],len<0?undefined:len);}return source},createContext:function(canvas,webGLContextAttributes){var ctx=canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=_malloc(8);GROWABLE_HEAP_I32()[handle+4>>2]=_pthread_self();var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context);}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return !(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;_free(GL.contexts[contextHandle].handle);GL.contexts[contextHandle]=null;},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;__webgl_enable_ANGLE_instanced_arrays(GLctx);__webgl_enable_OES_vertex_array_object(GLctx);__webgl_enable_WEBGL_draw_buffers(GLctx);GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query");var automaticallyEnabledExtensions=["OES_texture_float","OES_texture_half_float","OES_standard_derivatives","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBGL_depth_texture","OES_element_index_uint","EXT_texture_filter_anisotropic","EXT_frag_depth","WEBGL_draw_buffers","ANGLE_instanced_arrays","OES_texture_float_linear","OES_texture_half_float_linear","EXT_blend_minmax","EXT_shader_texture_lod","EXT_texture_norm16","WEBGL_compressed_texture_pvrtc","EXT_color_buffer_half_float","WEBGL_color_buffer_float","EXT_sRGB","WEBGL_compressed_texture_etc1","EXT_disjoint_timer_query","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_astc","EXT_color_buffer_float","WEBGL_compressed_texture_s3tc_srgb","EXT_disjoint_timer_query_webgl2","WEBKIT_WEBGL_compressed_texture_pvrtc"];var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext);}});},populateUniformTable:function(program){var p=GL.programs[program];var ptable=GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,35718);for(var i=0;i>2;contextAttributes["alpha"]=!!GROWABLE_HEAP_I32()[a+(0>>2)];contextAttributes["depth"]=!!GROWABLE_HEAP_I32()[a+(4>>2)];contextAttributes["stencil"]=!!GROWABLE_HEAP_I32()[a+(8>>2)];contextAttributes["antialias"]=!!GROWABLE_HEAP_I32()[a+(12>>2)];contextAttributes["premultipliedAlpha"]=!!GROWABLE_HEAP_I32()[a+(16>>2)];contextAttributes["preserveDrawingBuffer"]=!!GROWABLE_HEAP_I32()[a+(20>>2)];var powerPreference=GROWABLE_HEAP_I32()[a+(24>>2)];contextAttributes["powerPreference"]=__emscripten_webgl_power_preferences[powerPreference];contextAttributes["failIfMajorPerformanceCaveat"]=!!GROWABLE_HEAP_I32()[a+(28>>2)];contextAttributes.majorVersion=GROWABLE_HEAP_I32()[a+(32>>2)];contextAttributes.minorVersion=GROWABLE_HEAP_I32()[a+(36>>2)];contextAttributes.enableExtensionsByDefault=GROWABLE_HEAP_I32()[a+(40>>2)];contextAttributes.explicitSwapControl=GROWABLE_HEAP_I32()[a+(44>>2)];contextAttributes.proxyContextToMainThread=GROWABLE_HEAP_I32()[a+(48>>2)];contextAttributes.renderViaOffscreenBackBuffer=GROWABLE_HEAP_I32()[a+(52>>2)];var canvas=__findCanvasEventTarget(target);if(!canvas){return -4}if(contextAttributes.explicitSwapControl){return -1}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}function _emscripten_webgl_create_context(a0,a1){return _emscripten_webgl_do_create_context(a0,a1)}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=GROWABLE_HEAP_I32()[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(3,1,fd);return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(4,1,fd,offset_low,offset_high,whence,newOffset)}function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(5,1,fd,iov,iovcnt,pnum);var num=0;for(var i=0;i>2];var len=GROWABLE_HEAP_I32()[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _pthread_cleanup_pop(execute){var routine=PThread.exitHandlers.pop();if(execute)routine();}function _pthread_cleanup_push(routine,arg){if(PThread.exitHandlers===null){PThread.exitHandlers=[];}PThread.exitHandlers.push(function(){dynCall_vi(routine,arg);});}function __spawn_thread(threadParams){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _spawn_thread() can only ever be called from main application thread!";var worker=PThread.getNewWorker();if(worker.pthread!==undefined)throw "Internal error!";if(!threadParams.pthread_ptr)throw "Internal error, no pthread ptr!";PThread.runningWorkers.push(worker);var tlsMemory=_malloc(128*4);for(var i=0;i<128;++i){GROWABLE_HEAP_I32()[tlsMemory+i*4>>2]=0;}var stackHigh=threadParams.stackBase+threadParams.stackSize;var pthread=PThread.pthreads[threadParams.pthread_ptr]={worker:worker,stackBase:threadParams.stackBase,stackSize:threadParams.stackSize,allocatedOwnStack:threadParams.allocatedOwnStack,thread:threadParams.pthread_ptr,threadInfoStruct:threadParams.pthread_ptr};var tis=pthread.threadInfoStruct>>2;Atomics.store(GROWABLE_HEAP_U32(),tis+(0>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(4>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(8>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(68>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(104>>2),tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),tis+(48>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(40>>2),pthread.threadInfoStruct);Atomics.store(GROWABLE_HEAP_U32(),tis+(44>>2),42);Atomics.store(GROWABLE_HEAP_U32(),tis+(108>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(84>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(80>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+8>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+12>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+20>>2),threadParams.schedPolicy);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+24>>2),threadParams.schedPrio);var global_libc=_emscripten_get_global_libc();var global_locale=global_libc+40;Atomics.store(GROWABLE_HEAP_U32(),tis+(176>>2),global_locale);worker.pthread=pthread;var msg={"cmd":"run","start_routine":threadParams.startRoutine,"arg":threadParams.arg,"threadInfoStruct":threadParams.pthread_ptr,"selfThreadId":threadParams.pthread_ptr,"parentThreadId":threadParams.parent_pthread_ptr,"stackBase":threadParams.stackBase,"stackSize":threadParams.stackSize};worker.runPthread=function(){msg.time=performance.now();worker.postMessage(msg,threadParams.transferList);};if(worker.loaded){worker.runPthread();delete worker.runPthread;}}function _pthread_getschedparam(thread,policy,schedparam){if(!policy&&!schedparam)return ERRNO_CODES.EINVAL;if(!thread){err("pthread_getschedparam called with a null thread pointer!");return ERRNO_CODES.ESRCH}var self=GROWABLE_HEAP_I32()[thread+12>>2];if(self!==thread){err("pthread_getschedparam attempted on thread "+thread+", which does not point to a valid thread, or does not exist anymore!");return ERRNO_CODES.ESRCH}var schedPolicy=Atomics.load(GROWABLE_HEAP_U32(),thread+108+20>>2);var schedPrio=Atomics.load(GROWABLE_HEAP_U32(),thread+108+24>>2);if(policy)GROWABLE_HEAP_I32()[policy>>2]=schedPolicy;if(schedparam)GROWABLE_HEAP_I32()[schedparam>>2]=schedPrio;return 0}function _pthread_self(){return __pthread_ptr|0}Module["_pthread_self"]=_pthread_self;function _pthread_create(pthread_ptr,attr,start_routine,arg){if(typeof SharedArrayBuffer==="undefined"){err("Current environment does not support SharedArrayBuffer, pthreads are not available!");return 6}if(!pthread_ptr){err("pthread_create called with a null thread pointer!");return 28}var transferList=[];var error=0;if(ENVIRONMENT_IS_PTHREAD&&(transferList.length===0||error)){return _emscripten_sync_run_in_main_thread_4(687865856,pthread_ptr,attr,start_routine,arg)}var stackSize=0;var stackBase=0;var detached=0;var schedPolicy=0;var schedPrio=0;if(attr){stackSize=GROWABLE_HEAP_I32()[attr>>2];stackSize+=81920;stackBase=GROWABLE_HEAP_I32()[attr+8>>2];detached=GROWABLE_HEAP_I32()[attr+12>>2]!==0;var inheritSched=GROWABLE_HEAP_I32()[attr+16>>2]===0;if(inheritSched){var prevSchedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];var prevSchedPrio=GROWABLE_HEAP_I32()[attr+24>>2];var parentThreadPtr=PThread.currentProxiedOperationCallerThread?PThread.currentProxiedOperationCallerThread:_pthread_self();_pthread_getschedparam(parentThreadPtr,attr+20,attr+24);schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];GROWABLE_HEAP_I32()[attr+20>>2]=prevSchedPolicy;GROWABLE_HEAP_I32()[attr+24>>2]=prevSchedPrio;}else{schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];}}else{stackSize=2097152;}var allocatedOwnStack=stackBase==0;if(allocatedOwnStack){stackBase=_memalign(16,stackSize);}else{stackBase-=stackSize;assert(stackBase>0);}var threadInfoStruct=_malloc(232);for(var i=0;i<232>>2;++i)GROWABLE_HEAP_U32()[(threadInfoStruct>>2)+i]=0;GROWABLE_HEAP_I32()[pthread_ptr>>2]=threadInfoStruct;GROWABLE_HEAP_I32()[threadInfoStruct+12>>2]=threadInfoStruct;var headPtr=threadInfoStruct+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var threadParams={stackBase:stackBase,stackSize:stackSize,allocatedOwnStack:allocatedOwnStack,schedPolicy:schedPolicy,schedPrio:schedPrio,detached:detached,startRoutine:start_routine,pthread_ptr:threadInfoStruct,parent_pthread_ptr:_pthread_self(),arg:arg,transferList:transferList};if(ENVIRONMENT_IS_PTHREAD){threadParams.cmd="spawnThread";postMessage(threadParams,transferList);}else{__spawn_thread(threadParams);}return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}function _sysconf(name){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(6,1,name);switch(name){case 30:return 16384;case 85:var maxHeapSize=1073741824;return maxHeapSize/16384;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:case 79:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return -1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}setErrNo(28);return -1}if(!ENVIRONMENT_IS_PTHREAD)PThread.initMainThreadBlock();else PThread.initWorker();var GLctx;GL.init();var proxiedFunctionTable=[null,_atexit,_emscripten_set_canvas_element_size_main_thread,_fd_close,_fd_seek,_fd_write,_sysconf];var asmLibraryArg={"e":___assert_fail,"r":___call_main,"w":__emscripten_notify_thread_queue,"a":_abort,"l":_emscripten_conditional_set_current_thread_status,"d":_emscripten_futex_wait,"c":_emscripten_futex_wake,"h":_emscripten_get_now,"g":_emscripten_is_main_browser_thread,"x":_emscripten_is_main_runtime_thread,"q":_emscripten_memcpy_big,"B":_emscripten_num_logical_cores,"t":_emscripten_receive_on_main_thread_js,"A":_emscripten_resize_heap,"u":_emscripten_set_canvas_element_size,"k":_emscripten_set_current_thread_status,"s":_emscripten_set_thread_name,"v":_emscripten_webgl_create_context,"m":_fd_close,"o":_fd_seek,"i":_fd_write,"p":initPthreadsJS,"memory":wasmMemory||Module["wasmMemory"],"y":_pthread_cleanup_pop,"z":_pthread_cleanup_push,"j":_pthread_create,"b":_pthread_self,"f":_roundf,"n":_sysconf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return (___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["C"]).apply(null,arguments)};var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["D"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["E"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["F"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["G"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["H"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["I"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["J"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["K"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["L"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["M"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["N"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["O"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["P"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["Q"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["R"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["S"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["T"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["U"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["V"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["W"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["X"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["Y"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["Z"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["_"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["$"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["aa"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["ba"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["ca"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["da"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["ea"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["fa"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["ga"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["ha"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["ia"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["ja"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["ka"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["la"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["ma"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["na"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["oa"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["pa"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["qa"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["ra"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["sa"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["ta"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["ua"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["va"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["wa"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["xa"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["ya"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["za"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["Aa"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["Ba"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["Ca"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["Da"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["Ea"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["Fa"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["Ga"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["Ha"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["Ia"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["Ja"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["Ka"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["La"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["Ma"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["Na"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["Oa"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["Pa"]).apply(null,arguments)};var ___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=function(){return (___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=Module["asm"]["Qa"]).apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){return (___errno_location=Module["___errno_location"]=Module["asm"]["Ra"]).apply(null,arguments)};var _emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=function(){return (_emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=Module["asm"]["Sa"]).apply(null,arguments)};var _memalign=Module["_memalign"]=function(){return (_memalign=Module["_memalign"]=Module["asm"]["Ta"]).apply(null,arguments)};var ___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=function(){return (___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=Module["asm"]["Ua"]).apply(null,arguments)};var _emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=function(){return (_emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=Module["asm"]["Va"]).apply(null,arguments)};var _emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=function(){return (_emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=Module["asm"]["Wa"]).apply(null,arguments)};var _emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=function(){return (_emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=Module["asm"]["Xa"]).apply(null,arguments)};var _emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=function(){return (_emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=Module["asm"]["Ya"]).apply(null,arguments)};var _emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=function(){return (_emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=Module["asm"]["Za"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=function(){return (_emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=Module["asm"]["_a"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=function(){return (_emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=Module["asm"]["$a"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=function(){return (_emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=Module["asm"]["ab"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=function(){return (_emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=Module["asm"]["bb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=function(){return (_emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=Module["asm"]["cb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=function(){return (_emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=Module["asm"]["db"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=function(){return (_emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=Module["asm"]["eb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=function(){return (_emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=Module["asm"]["fb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=function(){return (_emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=Module["asm"]["gb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=function(){return (_emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=Module["asm"]["hb"]).apply(null,arguments)};var _emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=function(){return (_emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=Module["asm"]["ib"]).apply(null,arguments)};var _emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=function(){return (_emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=Module["asm"]["jb"]).apply(null,arguments)};var _emscripten_tls_init=Module["_emscripten_tls_init"]=function(){return (_emscripten_tls_init=Module["_emscripten_tls_init"]=Module["asm"]["kb"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["lb"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["mb"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["nb"]).apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){return (dynCall_vi=Module["dynCall_vi"]=Module["asm"]["ob"]).apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){return (dynCall_v=Module["dynCall_v"]=Module["asm"]["pb"]).apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){return (dynCall_ii=Module["dynCall_ii"]=Module["asm"]["qb"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;Module["PThread"]=PThread;Module["PThread"]=PThread;Module["_pthread_self"]=_pthread_self;Module["wasmMemory"]=wasmMemory;Module["ExitStatus"]=ExitStatus;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}if(!ENVIRONMENT_IS_PTHREAD)noExitRuntime=true;if(!ENVIRONMENT_IS_PTHREAD)run(); - - - return WasmBackendModuleSimd - } - ); - })(); - module.exports = WasmBackendModuleSimd; - }); - - const wasmWorkerContents = 'var threadInfoStruct=0;var selfThreadId=0;var parentThreadId=0;var Module={};function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:selfThreadId})}var err=threadPrintErr;this.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);Module["wasmModule"]=null;receiveInstance(instance);return instance.exports};this.onmessage=function(e){try{if(e.data.cmd==="load"){Module["DYNAMIC_BASE"]=e.data.DYNAMIC_BASE;Module["DYNAMICTOP_PTR"]=e.data.DYNAMICTOP_PTR;Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob==="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}Module=WasmBackendModuleSimd(Module);postMessage({"cmd":"loaded"})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;threadInfoStruct=e.data.threadInfoStruct;Module["__register_pthread_ptr"](threadInfoStruct,0,0);selfThreadId=e.data.selfThreadId;parentThreadId=e.data.parentThreadId;var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["_emscripten_tls_init"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].setThreadStatus(Module["_pthread_self"](),1);try{var result=Module["dynCall_ii"](e.data.start_routine,e.data.arg);if(!Module["getNoExitRuntime"]())Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){Atomics.store(Module["HEAPU32"],threadInfoStruct+4>>2,ex instanceof Module["ExitStatus"]?ex.status:-2);Atomics.store(Module["HEAPU32"],threadInfoStruct+0>>2,1);Module["_emscripten_futex_wake"](threadInfoStruct+0,2147483647);if(!(ex instanceof Module["ExitStatus"]))throw ex}}}else if(e.data.cmd==="cancel"){if(threadInfoStruct){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(threadInfoStruct){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex.stack)err(ex.stack);throw ex}};if(typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string"){self={location:{href:__filename}};var onmessage=this.onmessage;var nodeWorkerThreads=require("worker_threads");Worker=nodeWorkerThreads.Worker;var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var nodeFS=require("fs");var nodeRead=function(filename){return nodeFS.readFileSync(filename,"utf8")};function globalEval(x){global.require=require;global.Module=Module;eval.call(null,x)}importScripts=function(f){globalEval(nodeRead(f))};postMessage=function(msg){parentPort.postMessage(msg)};if(typeof performance==="undefined"){performance={now:function(){return Date.now()}}}}'; - - var tfjsBackendWasm = createCommonjsModule(function (module, exports) { - var WasmBackendModule = (function() { - var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; - if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; - return ( - function(WasmBackendModule) { - WasmBackendModule = WasmBackendModule || {}; - - var Module=typeof WasmBackendModule!=="undefined"?WasmBackendModule:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":147,"maximum":147+0,"element":"anyfunc"});var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023);}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer);}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=exports["memory"];updateGlobalBufferAndViews(wasmMemory.buffer);removeRunDependency();}addRunDependency();function receiveInstantiatedSource(output){receiveInstance(output["instance"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}__ATINIT__.push();function _emscripten_notify_memory_growth(memoryIndex){updateGlobalBufferAndViews(wasmMemory.buffer);}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _exit(status){exit(status);}function _proc_exit(code){_exit(code);}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}var asmLibraryArg={"emscripten_notify_memory_growth":_emscripten_notify_memory_growth,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"proc_exit":_proc_exit,"roundf":_roundf};var asm=createWasm();Module["asm"]=asm;var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["init"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["register_tensor"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["dispose_data"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["dispose"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["Abs"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["Add"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["AddN"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["ArgMax"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["AvgPool"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["BatchMatMul"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["ClipByValue"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["Conv2D"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["Conv2DBackpropInput"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["Cos"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["CropAndResize"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["DepthwiseConv2dNative"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["Div"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["Equal"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["Exp"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["FloorDiv"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["FusedBatchNorm"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["FusedConv2D"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["FusedDepthwiseConv2D"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["Gather"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["GatherNd"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["Greater"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["GreaterEqual"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["Less"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["LessEqual"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["Log"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["LogicalAnd"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["Max"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["MaxPool"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["Maximum"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["Min"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["Minimum"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["Multiply"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["Negate"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["NonMaxSuppressionV3"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["NonMaxSuppressionV4"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["NonMaxSuppressionV5"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["NotEqual"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["OneHot"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["PadV2"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["Pow"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["Prelu"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["Relu"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["Relu6"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["ResizeBilinear"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["Reverse"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["RotateWithOffset"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["Rsqrt"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["ScatterNd"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["SelectV2"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["Sigmoid"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["Sin"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["Softmax"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["Sqrt"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["Square"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["Sub"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["Sum"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["Tanh"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["Tile"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["Transpose"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["_FusedMatMul"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["malloc"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["free"]).apply(null,arguments)};var __start=Module["__start"]=function(){return (__start=Module["__start"]=Module["asm"]["_start"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["stackSave"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["stackAlloc"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["stackRestore"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function callMain(args){var entryFunction=Module["__start"];try{entryFunction();var ret=0;exit(ret,true);}catch(e){if(e instanceof ExitStatus){return}else if(e=="unwind"){noExitRuntime=true;return}else{var toLog=e;if(e&&typeof e==="object"&&e.stack){toLog=[e,e.stack];}err("exception thrown: "+toLog);quit_(1,e);}}finally{}}function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;function exit(status,implicit){if(implicit&&noExitRuntime&&status===0){return}if(noExitRuntime);else{ABORT=true;if(Module["onExit"])Module["onExit"](status);}quit_(status,new ExitStatus(status));}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;noExitRuntime=true;run(); - - - return WasmBackendModule - } - ); - })(); - module.exports = WasmBackendModule; - }); - + }); + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var tfjsBackendWasmThreadedSimd = createCommonjsModule(function (module, exports) { + var WasmBackendModuleSimd = (function() { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( + function(WasmBackendModuleSimd) { + WasmBackendModuleSimd = WasmBackendModuleSimd || {}; + + function GROWABLE_HEAP_I8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP8}function GROWABLE_HEAP_U8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU8}function GROWABLE_HEAP_I32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP32}function GROWABLE_HEAP_U32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPF64}var Module=typeof WasmBackendModuleSimd!=="undefined"?WasmBackendModuleSimd:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var ENVIRONMENT_IS_PTHREAD=Module["ENVIRONMENT_IS_PTHREAD"]||false;if(ENVIRONMENT_IS_PTHREAD){buffer=Module["buffer"];DYNAMIC_BASE=Module["DYNAMIC_BASE"];DYNAMICTOP_PTR=Module["DYNAMICTOP_PTR"];}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};var nodeWorkerThreads;try{nodeWorkerThreads=worker_threads;}catch(e){console.error('The "worker_threads" module is not supported in this node.js build - perhaps a newer version is needed?');throw e}Worker=nodeWorkerThreads.Worker;}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}if(ENVIRONMENT_IS_NODE){read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};}else{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}if(ENVIRONMENT_IS_NODE){if(typeof performance==="undefined"){performance=perf_hooks.performance;}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":165,"maximum":165+0,"element":"anyfunc"});var wasmModule;var threadInfoStruct=0;var selfThreadId=0;var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx)){var u0=heap[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heap[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heap[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2;}else{u0=(u0&7)<<18|u1<<12|u2<<6|heap[idx++]&63;}if(u0<65536){str+=String.fromCharCode(u0);}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023);}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4;}return len}function writeArrayToMemory(array,buffer){GROWABLE_HEAP_I8().set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var DYNAMIC_BASE=5256288,DYNAMICTOP_PTR=12480;var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||1073741824;if(ENVIRONMENT_IS_PTHREAD){wasmMemory=Module["wasmMemory"];buffer=Module["buffer"];}else{if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":1073741824/WASM_PAGE_SIZE,"shared":true});if(!(wasmMemory.buffer instanceof SharedArrayBuffer)){err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");if(ENVIRONMENT_IS_NODE){console.log("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)");}throw Error("bad memory")}}}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);if(!ENVIRONMENT_IS_PTHREAD){GROWABLE_HEAP_I32()[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){if(ENVIRONMENT_IS_PTHREAD)return;callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){assert(!ENVIRONMENT_IS_PTHREAD,"addRunDependency cannot be used in a pthread worker");runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}if(ENVIRONMENT_IS_PTHREAD)console.error("Pthread aborting at "+(new Error).stack);what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm-threaded-simd.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmModule=module;if(!ENVIRONMENT_IS_PTHREAD){var numWorkersToLoad=PThread.unusedWorkers.length;PThread.unusedWorkers.forEach(function(w){PThread.loadWasmModuleToWorker(w,function(){if(!--numWorkersToLoad)removeRunDependency();});});}}if(!ENVIRONMENT_IS_PTHREAD){addRunDependency();}function receiveInstantiatedSource(output){receiveInstance(output["instance"],output["module"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}var ASM_CONSTS={};function initPthreadsJS(){PThread.initRuntime();}if(!ENVIRONMENT_IS_PTHREAD)__ATINIT__.push({func:function(){___wasm_call_ctors();}});var __pthread_ptr=0;var __pthread_is_main_runtime_thread=0;var __pthread_is_main_browser_thread=0;function __register_pthread_ptr(pthreadPtr,isMainBrowserThread,isMainRuntimeThread){pthreadPtr=pthreadPtr|0;isMainBrowserThread=isMainBrowserThread|0;isMainRuntimeThread=isMainRuntimeThread|0;__pthread_ptr=pthreadPtr;__pthread_is_main_browser_thread=isMainBrowserThread;__pthread_is_main_runtime_thread=isMainRuntimeThread;}Module["__register_pthread_ptr"]=__register_pthread_ptr;var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var __main_thread_futex_wait_address=13392;function _emscripten_futex_wake(addr,count){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0||count<0)return -28;if(count==0)return 0;if(count>=2147483647)count=Infinity;var mainThreadWaitAddress=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);var mainThreadWoken=0;if(mainThreadWaitAddress==addr){var loadedAddr=Atomics.compareExchange(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,mainThreadWaitAddress,0);if(loadedAddr==mainThreadWaitAddress){--count;mainThreadWoken=1;if(count<=0)return 1}}var ret=Atomics.notify(GROWABLE_HEAP_I32(),addr>>2,count);if(ret>=0)return ret+mainThreadWoken;throw "Atomics.notify returned an unexpected value "+ret}Module["_emscripten_futex_wake"]=_emscripten_futex_wake;function __kill_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _kill_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _kill_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];pthread.worker.terminate();PThread.freeThreadData(pthread);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(pthread.worker),1);pthread.worker.pthread=undefined;}function __cancel_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cancel_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cancel_thread!";var pthread=PThread.pthreads[pthread_ptr];pthread.worker.postMessage({"cmd":"cancel"});}function __cleanup_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cleanup_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cleanup_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];if(pthread){var worker=pthread.worker;PThread.returnWorkerToPool(worker);}}var PThread={MAIN_THREAD_ID:1,mainThreadInfo:{schedPolicy:0,schedPrio:0},unusedWorkers:[],runningWorkers:[],initRuntime:function(){__register_pthread_ptr(PThread.mainThreadBlock,!ENVIRONMENT_IS_WORKER,1);_emscripten_register_main_browser_thread_id(PThread.mainThreadBlock);},initMainThreadBlock:function(){var pthreadPoolSize=8;for(var i=0;i>2]=PThread.mainThreadBlock;var headPtr=PThread.mainThreadBlock+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var tlsMemory=12880;for(var i=0;i<128;++i)GROWABLE_HEAP_U32()[tlsMemory/4+i]=0;Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+104>>2,tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+40>>2,PThread.mainThreadBlock);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+44>>2,42);},initWorker:function(){},pthreads:{},exitHandlers:null,setThreadStatus:function(){},runExitHandlers:function(){if(PThread.exitHandlers!==null){while(PThread.exitHandlers.length>0){PThread.exitHandlers.pop()();}PThread.exitHandlers=null;}if(ENVIRONMENT_IS_PTHREAD&&threadInfoStruct)___pthread_tsd_run_dtors();},threadExit:function(exitCode){var tb=_pthread_self();if(tb){Atomics.store(GROWABLE_HEAP_U32(),tb+4>>2,exitCode);Atomics.store(GROWABLE_HEAP_U32(),tb+0>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+60>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+64>>2,0);PThread.runExitHandlers();_emscripten_futex_wake(tb+0,2147483647);__register_pthread_ptr(0,0,0);threadInfoStruct=0;if(ENVIRONMENT_IS_PTHREAD){postMessage({"cmd":"exit"});}}},threadCancel:function(){PThread.runExitHandlers();Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+4>>2,-1);Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+0>>2,1);_emscripten_futex_wake(threadInfoStruct+0,2147483647);threadInfoStruct=selfThreadId=0;__register_pthread_ptr(0,0,0);postMessage({"cmd":"cancelDone"});},terminateAllThreads:function(){for(var t in PThread.pthreads){var pthread=PThread.pthreads[t];if(pthread&&pthread.worker){PThread.returnWorkerToPool(pthread.worker);}}PThread.pthreads={};for(var i=0;i>2];GROWABLE_HEAP_I32()[pthread.threadInfoStruct+104>>2]=0;_free(tlsMemory);_free(pthread.threadInfoStruct);}pthread.threadInfoStruct=0;if(pthread.allocatedOwnStack&&pthread.stackBase)_free(pthread.stackBase);pthread.stackBase=0;if(pthread.worker)pthread.worker.pthread=null;},returnWorkerToPool:function(worker){delete PThread.pthreads[worker.pthread.thread];PThread.unusedWorkers.push(worker);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);PThread.freeThreadData(worker.pthread);worker.pthread=undefined;},receiveObjectTransfer:function(data){},loadWasmModuleToWorker:function(worker,onFinishedLoading){worker.onmessage=function(e){var d=e["data"];var cmd=d["cmd"];if(worker.pthread)PThread.currentProxiedOperationCallerThread=worker.pthread.threadInfoStruct;if(d["targetThread"]&&d["targetThread"]!=_pthread_self()){var thread=PThread.pthreads[d.targetThread];if(thread){thread.worker.postMessage(e.data,d["transferList"]);}else{console.error('Internal error! Worker sent a message "'+cmd+'" to target pthread '+d["targetThread"]+", but that thread no longer exists!");}PThread.currentProxiedOperationCallerThread=undefined;return}if(cmd==="processQueuedMainThreadWork"){_emscripten_main_thread_process_queued_calls();}else if(cmd==="spawnThread"){__spawn_thread(e.data);}else if(cmd==="cleanupThread"){__cleanup_thread(d["thread"]);}else if(cmd==="killThread"){__kill_thread(d["thread"]);}else if(cmd==="cancelThread"){__cancel_thread(d["thread"]);}else if(cmd==="loaded"){worker.loaded=true;if(onFinishedLoading)onFinishedLoading(worker);if(worker.runPthread){worker.runPthread();delete worker.runPthread;}}else if(cmd==="print"){out("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="printErr"){err("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="alert"){alert("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="exit"){var detached=worker.pthread&&Atomics.load(GROWABLE_HEAP_U32(),worker.pthread.thread+68>>2);if(detached){PThread.returnWorkerToPool(worker);}}else if(cmd==="cancelDone"){PThread.returnWorkerToPool(worker);}else if(cmd==="objectTransfer"){PThread.receiveObjectTransfer(e.data);}else if(e.data.target==="setimmediate"){worker.postMessage(e.data);}else{err("worker sent an unknown command "+cmd);}PThread.currentProxiedOperationCallerThread=undefined;};worker.onerror=function(e){err("pthread sent an error! "+e.filename+":"+e.lineno+": "+e.message);};if(ENVIRONMENT_IS_NODE){worker.on("message",function(data){worker.onmessage({data:data});});worker.on("error",function(data){worker.onerror(data);});worker.on("exit",function(data){console.log("worker exited - TODO: update the worker queue?");});}worker.postMessage({"cmd":"load","urlOrBlob":Module["mainScriptUrlOrBlob"]||_scriptDir,"wasmMemory":wasmMemory,"wasmModule":wasmModule,"DYNAMIC_BASE":DYNAMIC_BASE,"DYNAMICTOP_PTR":DYNAMICTOP_PTR});},allocateUnusedWorker:function(){var pthreadMainJs=locateFile("tfjs-backend-wasm-threaded-simd.worker.js");PThread.unusedWorkers.push(new Worker(pthreadMainJs));},getNewWorker:function(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]);}if(PThread.unusedWorkers.length>0)return PThread.unusedWorkers.pop();else return null},busySpinWait:function(msecs){var t=performance.now()+msecs;while(performance.now()>2]=value;return value}function _atexit(func,arg){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(1,1,func,arg);}function __emscripten_notify_thread_queue(targetThreadId,mainThreadId){if(targetThreadId==mainThreadId){postMessage({"cmd":"processQueuedMainThreadWork"});}else if(ENVIRONMENT_IS_PTHREAD){postMessage({"targetThread":targetThreadId,"cmd":"processThreadQueue"});}else{var pthread=PThread.pthreads[targetThreadId];var worker=pthread&&pthread.worker;if(!worker){return}worker.postMessage({"cmd":"processThreadQueue"});}return 1}function _abort(){abort();}function _emscripten_conditional_set_current_thread_status(expectedStatus,newStatus){}function _emscripten_futex_wait(addr,val,timeout){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0)return -28;if(ENVIRONMENT_IS_WORKER){var ret=Atomics.wait(GROWABLE_HEAP_I32(),addr>>2,val,timeout);if(ret==="timed-out")return -73;if(ret==="not-equal")return -6;if(ret==="ok")return 0;throw "Atomics.wait returned an unexpected value "+ret}else{var loadedVal=Atomics.load(GROWABLE_HEAP_I32(),addr>>2);if(val!=loadedVal)return -6;var tNow=performance.now();var tEnd=tNow+timeout;Atomics.store(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,addr);var ourWaitAddress=addr;while(addr==ourWaitAddress){tNow=performance.now();if(tNow>tEnd){return -73}_emscripten_main_thread_process_queued_calls();addr=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);}return 0}}function _emscripten_is_main_browser_thread(){return __pthread_is_main_browser_thread|0}function _emscripten_is_main_runtime_thread(){return __pthread_is_main_runtime_thread|0}function _emscripten_memcpy_big(dest,src,num){GROWABLE_HEAP_U8().copyWithin(dest,src,src+num);}function _emscripten_num_logical_cores(){return navigator["hardwareConcurrency"]}function _emscripten_proxy_to_main_thread_js(index,sync){var numCallArgs=arguments.length-2;var stack=stackSave();var args=stackAlloc(numCallArgs*8);var b=args>>3;for(var i=0;i>3]);buf+=8;}else{buf=buf+3&~3;args.push(GROWABLE_HEAP_I32()[buf>>2]);buf+=4;}}return args}function _emscripten_receive_on_main_thread_js(index,numCallArgs,args){_emscripten_receive_on_main_thread_js_callArgs.length=numCallArgs;var b=args>>3;for(var i=0;i>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();if(requestedSize<=oldSize){return false}var PAGE_MULTIPLE=65536;var maxHeapSize=1073741824;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var JSEvents={keyEvent:0,mouseEvent:0,wheelEvent:0,uiEvent:0,focusEvent:0,deviceOrientationEvent:0,deviceMotionEvent:0,fullscreenChangeEvent:0,pointerlockChangeEvent:0,visibilityChangeEvent:0,touchEvent:0,previousFullscreenElement:null,previousScreenX:null,previousScreenY:null,removeEventListenersRegistered:false,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i);}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[];},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){JSEvents.removeEventListenersRegistered=true;}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence>2]=eventTypeId;GROWABLE_HEAP_I32()[varargs+4>>2]=eventData;GROWABLE_HEAP_I32()[varargs+8>>2]=userData;_emscripten_async_queue_on_thread_(targetThread,637534208,eventHandlerFunc,eventData,varargs);stackRestore(stackTop);},getTargetThreadForEventCallback:function(targetThread){switch(targetThread){case 1:return 0;case 2:return PThread.currentProxiedOperationCallerThread;default:return targetThread}},getNodeNameForTarget:function(target){if(!target)return "";if(target==window)return "#window";if(target==screen)return "#screen";return target&&target.nodeName?target.nodeName:""},fullscreenEnabled:function(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+1;var cString=_malloc(length);stringToUTF8(jsString,cString,length);return cString}function _emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height){var stackTop=stackSave();var varargs=stackAlloc(12);var targetCanvasPtr=0;if(targetCanvas){targetCanvasPtr=stringToNewUTF8(targetCanvas);}GROWABLE_HEAP_I32()[varargs>>2]=targetCanvasPtr;GROWABLE_HEAP_I32()[varargs+4>>2]=width;GROWABLE_HEAP_I32()[varargs+8>>2]=height;_emscripten_async_queue_on_thread_(targetThread,657457152,0,targetCanvasPtr,varargs);stackRestore(stackTop);}function _emscripten_set_offscreencanvas_size_on_target_thread(targetThread,targetCanvas,width,height){targetCanvas=targetCanvas?UTF8ToString(targetCanvas):"";_emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height);}function __maybeCStringToJsString(cString){return cString>2?UTF8ToString(cString):cString}var specialHTMLTargets=[0,typeof document!=="undefined"?document:0,typeof window!=="undefined"?window:0];function __findEventTarget(target){target=__maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!=="undefined"?document.querySelector(target):undefined);return domElement}function __findCanvasEventTarget(target){return __findEventTarget(target)}function _emscripten_set_canvas_element_size_calling_thread(target,width,height){var canvas=__findCanvasEventTarget(target);if(!canvas)return -4;if(canvas.canvasSharedPtr){GROWABLE_HEAP_I32()[canvas.canvasSharedPtr>>2]=width;GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+4>>2]=height;}if(canvas.offscreenCanvas||!canvas.controlTransferredOffscreen){if(canvas.offscreenCanvas)canvas=canvas.offscreenCanvas;var autoResizeViewport=false;if(canvas.GLctxObject&&canvas.GLctxObject.GLctx){var prevViewport=canvas.GLctxObject.GLctx.getParameter(2978);autoResizeViewport=prevViewport[0]===0&&prevViewport[1]===0&&prevViewport[2]===canvas.width&&prevViewport[3]===canvas.height;}canvas.width=width;canvas.height=height;if(autoResizeViewport){canvas.GLctxObject.GLctx.viewport(0,0,width,height);}}else if(canvas.canvasSharedPtr){var targetThread=GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+8>>2];_emscripten_set_offscreencanvas_size_on_target_thread(targetThread,target,width,height);return 1}else{return -4}return 0}function _emscripten_set_canvas_element_size_main_thread(target,width,height){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(2,1,target,width,height);return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}function _emscripten_set_canvas_element_size(target,width,height){var canvas=__findCanvasEventTarget(target);if(canvas){return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}else{return _emscripten_set_canvas_element_size_main_thread(target,width,height)}}function _emscripten_set_current_thread_status(newStatus){}function _emscripten_set_thread_name(threadId,name){}function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=function(index,divisor){ext["vertexAttribDivisorANGLE"](index,divisor);};ctx["drawArraysInstanced"]=function(mode,first,count,primcount){ext["drawArraysInstancedANGLE"](mode,first,count,primcount);};ctx["drawElementsInstanced"]=function(mode,count,type,indices,primcount){ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);};return 1}}function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=function(){return ext["createVertexArrayOES"]()};ctx["deleteVertexArray"]=function(vao){ext["deleteVertexArrayOES"](vao);};ctx["bindVertexArray"]=function(vao){ext["bindVertexArrayOES"](vao);};ctx["isVertexArray"]=function(vao){return ext["isVertexArrayOES"](vao)};return 1}}function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=function(n,bufs){ext["drawBuffersWEBGL"](n,bufs);};return 1}}var GL={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:{},currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],programInfos:{},stringCache:{},unpackAlignment:4,init:function(){var miniTempFloatBuffer=new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);for(var i=0;i>2]:-1;source+=UTF8ToString(GROWABLE_HEAP_I32()[string+i*4>>2],len<0?undefined:len);}return source},createContext:function(canvas,webGLContextAttributes){var ctx=canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=_malloc(8);GROWABLE_HEAP_I32()[handle+4>>2]=_pthread_self();var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context);}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return !(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;_free(GL.contexts[contextHandle].handle);GL.contexts[contextHandle]=null;},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;__webgl_enable_ANGLE_instanced_arrays(GLctx);__webgl_enable_OES_vertex_array_object(GLctx);__webgl_enable_WEBGL_draw_buffers(GLctx);GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query");var automaticallyEnabledExtensions=["OES_texture_float","OES_texture_half_float","OES_standard_derivatives","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBGL_depth_texture","OES_element_index_uint","EXT_texture_filter_anisotropic","EXT_frag_depth","WEBGL_draw_buffers","ANGLE_instanced_arrays","OES_texture_float_linear","OES_texture_half_float_linear","EXT_blend_minmax","EXT_shader_texture_lod","EXT_texture_norm16","WEBGL_compressed_texture_pvrtc","EXT_color_buffer_half_float","WEBGL_color_buffer_float","EXT_sRGB","WEBGL_compressed_texture_etc1","EXT_disjoint_timer_query","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_astc","EXT_color_buffer_float","WEBGL_compressed_texture_s3tc_srgb","EXT_disjoint_timer_query_webgl2","WEBKIT_WEBGL_compressed_texture_pvrtc"];var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext);}});},populateUniformTable:function(program){var p=GL.programs[program];var ptable=GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,35718);for(var i=0;i>2;contextAttributes["alpha"]=!!GROWABLE_HEAP_I32()[a+(0>>2)];contextAttributes["depth"]=!!GROWABLE_HEAP_I32()[a+(4>>2)];contextAttributes["stencil"]=!!GROWABLE_HEAP_I32()[a+(8>>2)];contextAttributes["antialias"]=!!GROWABLE_HEAP_I32()[a+(12>>2)];contextAttributes["premultipliedAlpha"]=!!GROWABLE_HEAP_I32()[a+(16>>2)];contextAttributes["preserveDrawingBuffer"]=!!GROWABLE_HEAP_I32()[a+(20>>2)];var powerPreference=GROWABLE_HEAP_I32()[a+(24>>2)];contextAttributes["powerPreference"]=__emscripten_webgl_power_preferences[powerPreference];contextAttributes["failIfMajorPerformanceCaveat"]=!!GROWABLE_HEAP_I32()[a+(28>>2)];contextAttributes.majorVersion=GROWABLE_HEAP_I32()[a+(32>>2)];contextAttributes.minorVersion=GROWABLE_HEAP_I32()[a+(36>>2)];contextAttributes.enableExtensionsByDefault=GROWABLE_HEAP_I32()[a+(40>>2)];contextAttributes.explicitSwapControl=GROWABLE_HEAP_I32()[a+(44>>2)];contextAttributes.proxyContextToMainThread=GROWABLE_HEAP_I32()[a+(48>>2)];contextAttributes.renderViaOffscreenBackBuffer=GROWABLE_HEAP_I32()[a+(52>>2)];var canvas=__findCanvasEventTarget(target);if(!canvas){return -4}if(contextAttributes.explicitSwapControl){return -1}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}function _emscripten_webgl_create_context(a0,a1){return _emscripten_webgl_do_create_context(a0,a1)}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=GROWABLE_HEAP_I32()[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(3,1,fd);return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(4,1,fd,offset_low,offset_high,whence,newOffset)}function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(5,1,fd,iov,iovcnt,pnum);var num=0;for(var i=0;i>2];var len=GROWABLE_HEAP_I32()[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _pthread_cleanup_pop(execute){var routine=PThread.exitHandlers.pop();if(execute)routine();}function _pthread_cleanup_push(routine,arg){if(PThread.exitHandlers===null){PThread.exitHandlers=[];}PThread.exitHandlers.push(function(){dynCall_vi(routine,arg);});}function __spawn_thread(threadParams){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _spawn_thread() can only ever be called from main application thread!";var worker=PThread.getNewWorker();if(worker.pthread!==undefined)throw "Internal error!";if(!threadParams.pthread_ptr)throw "Internal error, no pthread ptr!";PThread.runningWorkers.push(worker);var tlsMemory=_malloc(128*4);for(var i=0;i<128;++i){GROWABLE_HEAP_I32()[tlsMemory+i*4>>2]=0;}var stackHigh=threadParams.stackBase+threadParams.stackSize;var pthread=PThread.pthreads[threadParams.pthread_ptr]={worker:worker,stackBase:threadParams.stackBase,stackSize:threadParams.stackSize,allocatedOwnStack:threadParams.allocatedOwnStack,thread:threadParams.pthread_ptr,threadInfoStruct:threadParams.pthread_ptr};var tis=pthread.threadInfoStruct>>2;Atomics.store(GROWABLE_HEAP_U32(),tis+(0>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(4>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(8>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(68>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(104>>2),tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),tis+(48>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(40>>2),pthread.threadInfoStruct);Atomics.store(GROWABLE_HEAP_U32(),tis+(44>>2),42);Atomics.store(GROWABLE_HEAP_U32(),tis+(108>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(84>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(80>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+8>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+12>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+20>>2),threadParams.schedPolicy);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+24>>2),threadParams.schedPrio);var global_libc=_emscripten_get_global_libc();var global_locale=global_libc+40;Atomics.store(GROWABLE_HEAP_U32(),tis+(176>>2),global_locale);worker.pthread=pthread;var msg={"cmd":"run","start_routine":threadParams.startRoutine,"arg":threadParams.arg,"threadInfoStruct":threadParams.pthread_ptr,"selfThreadId":threadParams.pthread_ptr,"parentThreadId":threadParams.parent_pthread_ptr,"stackBase":threadParams.stackBase,"stackSize":threadParams.stackSize};worker.runPthread=function(){msg.time=performance.now();worker.postMessage(msg,threadParams.transferList);};if(worker.loaded){worker.runPthread();delete worker.runPthread;}}function _pthread_getschedparam(thread,policy,schedparam){if(!policy&&!schedparam)return ERRNO_CODES.EINVAL;if(!thread){err("pthread_getschedparam called with a null thread pointer!");return ERRNO_CODES.ESRCH}var self=GROWABLE_HEAP_I32()[thread+12>>2];if(self!==thread){err("pthread_getschedparam attempted on thread "+thread+", which does not point to a valid thread, or does not exist anymore!");return ERRNO_CODES.ESRCH}var schedPolicy=Atomics.load(GROWABLE_HEAP_U32(),thread+108+20>>2);var schedPrio=Atomics.load(GROWABLE_HEAP_U32(),thread+108+24>>2);if(policy)GROWABLE_HEAP_I32()[policy>>2]=schedPolicy;if(schedparam)GROWABLE_HEAP_I32()[schedparam>>2]=schedPrio;return 0}function _pthread_self(){return __pthread_ptr|0}Module["_pthread_self"]=_pthread_self;function _pthread_create(pthread_ptr,attr,start_routine,arg){if(typeof SharedArrayBuffer==="undefined"){err("Current environment does not support SharedArrayBuffer, pthreads are not available!");return 6}if(!pthread_ptr){err("pthread_create called with a null thread pointer!");return 28}var transferList=[];var error=0;if(ENVIRONMENT_IS_PTHREAD&&(transferList.length===0||error)){return _emscripten_sync_run_in_main_thread_4(687865856,pthread_ptr,attr,start_routine,arg)}var stackSize=0;var stackBase=0;var detached=0;var schedPolicy=0;var schedPrio=0;if(attr){stackSize=GROWABLE_HEAP_I32()[attr>>2];stackSize+=81920;stackBase=GROWABLE_HEAP_I32()[attr+8>>2];detached=GROWABLE_HEAP_I32()[attr+12>>2]!==0;var inheritSched=GROWABLE_HEAP_I32()[attr+16>>2]===0;if(inheritSched){var prevSchedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];var prevSchedPrio=GROWABLE_HEAP_I32()[attr+24>>2];var parentThreadPtr=PThread.currentProxiedOperationCallerThread?PThread.currentProxiedOperationCallerThread:_pthread_self();_pthread_getschedparam(parentThreadPtr,attr+20,attr+24);schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];GROWABLE_HEAP_I32()[attr+20>>2]=prevSchedPolicy;GROWABLE_HEAP_I32()[attr+24>>2]=prevSchedPrio;}else{schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];}}else{stackSize=2097152;}var allocatedOwnStack=stackBase==0;if(allocatedOwnStack){stackBase=_memalign(16,stackSize);}else{stackBase-=stackSize;assert(stackBase>0);}var threadInfoStruct=_malloc(232);for(var i=0;i<232>>2;++i)GROWABLE_HEAP_U32()[(threadInfoStruct>>2)+i]=0;GROWABLE_HEAP_I32()[pthread_ptr>>2]=threadInfoStruct;GROWABLE_HEAP_I32()[threadInfoStruct+12>>2]=threadInfoStruct;var headPtr=threadInfoStruct+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var threadParams={stackBase:stackBase,stackSize:stackSize,allocatedOwnStack:allocatedOwnStack,schedPolicy:schedPolicy,schedPrio:schedPrio,detached:detached,startRoutine:start_routine,pthread_ptr:threadInfoStruct,parent_pthread_ptr:_pthread_self(),arg:arg,transferList:transferList};if(ENVIRONMENT_IS_PTHREAD){threadParams.cmd="spawnThread";postMessage(threadParams,transferList);}else{__spawn_thread(threadParams);}return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}function _sysconf(name){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(6,1,name);switch(name){case 30:return 16384;case 85:var maxHeapSize=1073741824;return maxHeapSize/16384;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:case 79:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return -1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}setErrNo(28);return -1}if(!ENVIRONMENT_IS_PTHREAD)PThread.initMainThreadBlock();else PThread.initWorker();var GLctx;GL.init();var proxiedFunctionTable=[null,_atexit,_emscripten_set_canvas_element_size_main_thread,_fd_close,_fd_seek,_fd_write,_sysconf];var asmLibraryArg={"e":___assert_fail,"r":___call_main,"w":__emscripten_notify_thread_queue,"a":_abort,"l":_emscripten_conditional_set_current_thread_status,"d":_emscripten_futex_wait,"c":_emscripten_futex_wake,"h":_emscripten_get_now,"g":_emscripten_is_main_browser_thread,"x":_emscripten_is_main_runtime_thread,"q":_emscripten_memcpy_big,"B":_emscripten_num_logical_cores,"t":_emscripten_receive_on_main_thread_js,"A":_emscripten_resize_heap,"u":_emscripten_set_canvas_element_size,"k":_emscripten_set_current_thread_status,"s":_emscripten_set_thread_name,"v":_emscripten_webgl_create_context,"m":_fd_close,"o":_fd_seek,"i":_fd_write,"p":initPthreadsJS,"memory":wasmMemory||Module["wasmMemory"],"y":_pthread_cleanup_pop,"z":_pthread_cleanup_push,"j":_pthread_create,"b":_pthread_self,"f":_roundf,"n":_sysconf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return (___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["C"]).apply(null,arguments)};var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["D"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["E"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["F"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["G"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["H"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["I"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["J"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["K"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["L"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["M"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["N"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["O"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["P"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["Q"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["R"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["S"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["T"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["U"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["V"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["W"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["X"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["Y"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["Z"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["_"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["$"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["aa"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["ba"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["ca"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["da"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["ea"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["fa"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["ga"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["ha"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["ia"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["ja"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["ka"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["la"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["ma"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["na"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["oa"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["pa"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["qa"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["ra"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["sa"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["ta"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["ua"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["va"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["wa"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["xa"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["ya"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["za"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["Aa"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["Ba"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["Ca"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["Da"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["Ea"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["Fa"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["Ga"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["Ha"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["Ia"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["Ja"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["Ka"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["La"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["Ma"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["Na"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["Oa"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["Pa"]).apply(null,arguments)};var ___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=function(){return (___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=Module["asm"]["Qa"]).apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){return (___errno_location=Module["___errno_location"]=Module["asm"]["Ra"]).apply(null,arguments)};var _emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=function(){return (_emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=Module["asm"]["Sa"]).apply(null,arguments)};var _memalign=Module["_memalign"]=function(){return (_memalign=Module["_memalign"]=Module["asm"]["Ta"]).apply(null,arguments)};var ___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=function(){return (___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=Module["asm"]["Ua"]).apply(null,arguments)};var _emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=function(){return (_emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=Module["asm"]["Va"]).apply(null,arguments)};var _emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=function(){return (_emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=Module["asm"]["Wa"]).apply(null,arguments)};var _emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=function(){return (_emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=Module["asm"]["Xa"]).apply(null,arguments)};var _emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=function(){return (_emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=Module["asm"]["Ya"]).apply(null,arguments)};var _emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=function(){return (_emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=Module["asm"]["Za"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=function(){return (_emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=Module["asm"]["_a"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=function(){return (_emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=Module["asm"]["$a"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=function(){return (_emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=Module["asm"]["ab"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=function(){return (_emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=Module["asm"]["bb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=function(){return (_emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=Module["asm"]["cb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=function(){return (_emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=Module["asm"]["db"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=function(){return (_emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=Module["asm"]["eb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=function(){return (_emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=Module["asm"]["fb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=function(){return (_emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=Module["asm"]["gb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=function(){return (_emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=Module["asm"]["hb"]).apply(null,arguments)};var _emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=function(){return (_emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=Module["asm"]["ib"]).apply(null,arguments)};var _emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=function(){return (_emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=Module["asm"]["jb"]).apply(null,arguments)};var _emscripten_tls_init=Module["_emscripten_tls_init"]=function(){return (_emscripten_tls_init=Module["_emscripten_tls_init"]=Module["asm"]["kb"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["lb"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["mb"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["nb"]).apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){return (dynCall_vi=Module["dynCall_vi"]=Module["asm"]["ob"]).apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){return (dynCall_v=Module["dynCall_v"]=Module["asm"]["pb"]).apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){return (dynCall_ii=Module["dynCall_ii"]=Module["asm"]["qb"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;Module["PThread"]=PThread;Module["PThread"]=PThread;Module["_pthread_self"]=_pthread_self;Module["wasmMemory"]=wasmMemory;Module["ExitStatus"]=ExitStatus;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}if(!ENVIRONMENT_IS_PTHREAD)noExitRuntime=true;if(!ENVIRONMENT_IS_PTHREAD)run(); + + + return WasmBackendModuleSimd + } + ); + })(); + module.exports = WasmBackendModuleSimd; + }); + + const wasmWorkerContents = 'var threadInfoStruct=0;var selfThreadId=0;var parentThreadId=0;var Module={};function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:selfThreadId})}var err=threadPrintErr;this.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);Module["wasmModule"]=null;receiveInstance(instance);return instance.exports};this.onmessage=function(e){try{if(e.data.cmd==="load"){Module["DYNAMIC_BASE"]=e.data.DYNAMIC_BASE;Module["DYNAMICTOP_PTR"]=e.data.DYNAMICTOP_PTR;Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob==="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}Module=WasmBackendModuleSimd(Module);postMessage({"cmd":"loaded"})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;threadInfoStruct=e.data.threadInfoStruct;Module["__register_pthread_ptr"](threadInfoStruct,0,0);selfThreadId=e.data.selfThreadId;parentThreadId=e.data.parentThreadId;var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["_emscripten_tls_init"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].setThreadStatus(Module["_pthread_self"](),1);try{var result=Module["dynCall_ii"](e.data.start_routine,e.data.arg);if(!Module["getNoExitRuntime"]())Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){Atomics.store(Module["HEAPU32"],threadInfoStruct+4>>2,ex instanceof Module["ExitStatus"]?ex.status:-2);Atomics.store(Module["HEAPU32"],threadInfoStruct+0>>2,1);Module["_emscripten_futex_wake"](threadInfoStruct+0,2147483647);if(!(ex instanceof Module["ExitStatus"]))throw ex}}}else if(e.data.cmd==="cancel"){if(threadInfoStruct){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(threadInfoStruct){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex.stack)err(ex.stack);throw ex}};if(typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string"){self={location:{href:__filename}};var onmessage=this.onmessage;var nodeWorkerThreads=require("worker_threads");Worker=nodeWorkerThreads.Worker;var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var nodeFS=require("fs");var nodeRead=function(filename){return nodeFS.readFileSync(filename,"utf8")};function globalEval(x){global.require=require;global.Module=Module;eval.call(null,x)}importScripts=function(f){globalEval(nodeRead(f))};postMessage=function(msg){parentPort.postMessage(msg)};if(typeof performance==="undefined"){performance={now:function(){return Date.now()}}}}'; + + var tfjsBackendWasm = createCommonjsModule(function (module, exports) { + var WasmBackendModule = (function() { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( + function(WasmBackendModule) { + WasmBackendModule = WasmBackendModule || {}; + + var Module=typeof WasmBackendModule!=="undefined"?WasmBackendModule:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":147,"maximum":147+0,"element":"anyfunc"});var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023);}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer);}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=exports["memory"];updateGlobalBufferAndViews(wasmMemory.buffer);removeRunDependency();}addRunDependency();function receiveInstantiatedSource(output){receiveInstance(output["instance"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}__ATINIT__.push();function _emscripten_notify_memory_growth(memoryIndex){updateGlobalBufferAndViews(wasmMemory.buffer);}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _exit(status){exit(status);}function _proc_exit(code){_exit(code);}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}var asmLibraryArg={"emscripten_notify_memory_growth":_emscripten_notify_memory_growth,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"proc_exit":_proc_exit,"roundf":_roundf};var asm=createWasm();Module["asm"]=asm;var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["init"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["register_tensor"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["dispose_data"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["dispose"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["Abs"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["Add"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["AddN"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["ArgMax"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["AvgPool"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["BatchMatMul"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["ClipByValue"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["Conv2D"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["Conv2DBackpropInput"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["Cos"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["CropAndResize"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["DepthwiseConv2dNative"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["Div"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["Equal"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["Exp"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["FloorDiv"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["FusedBatchNorm"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["FusedConv2D"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["FusedDepthwiseConv2D"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["Gather"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["GatherNd"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["Greater"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["GreaterEqual"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["Less"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["LessEqual"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["Log"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["LogicalAnd"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["Max"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["MaxPool"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["Maximum"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["Min"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["Minimum"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["Multiply"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["Negate"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["NonMaxSuppressionV3"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["NonMaxSuppressionV4"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["NonMaxSuppressionV5"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["NotEqual"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["OneHot"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["PadV2"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["Pow"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["Prelu"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["Relu"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["Relu6"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["ResizeBilinear"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["Reverse"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["RotateWithOffset"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["Rsqrt"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["ScatterNd"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["SelectV2"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["Sigmoid"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["Sin"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["Softmax"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["Sqrt"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["Square"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["Sub"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["Sum"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["Tanh"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["Tile"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["Transpose"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["_FusedMatMul"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["malloc"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["free"]).apply(null,arguments)};var __start=Module["__start"]=function(){return (__start=Module["__start"]=Module["asm"]["_start"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["stackSave"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["stackAlloc"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["stackRestore"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function callMain(args){var entryFunction=Module["__start"];try{entryFunction();var ret=0;exit(ret,true);}catch(e){if(e instanceof ExitStatus){return}else if(e=="unwind"){noExitRuntime=true;return}else{var toLog=e;if(e&&typeof e==="object"&&e.stack){toLog=[e,e.stack];}err("exception thrown: "+toLog);quit_(1,e);}}finally{}}function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;function exit(status,implicit){if(implicit&&noExitRuntime&&status===0){return}if(noExitRuntime);else{ABORT=true;if(Module["onExit"])Module["onExit"](status);}quit_(status,new ExitStatus(status));}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;noExitRuntime=true;run(); + + + return WasmBackendModule + } + ); + })(); + module.exports = WasmBackendModule; + }); + /** * @license * Copyright 2019 Google LLC. All Rights Reserved. @@ -3573,7 +3573,10 @@ return URL.createObjectURL(blob); } if (path.endsWith('.wasm')) { - if (simdSupported) { + if (simdSupported) { + if(threadsSupported) { + return prefix + 'tfjs-backend-wasm-threaded-simd.wasm'; + } return prefix + 'tfjs-backend-wasm-simd.wasm'; } return prefix + 'tfjs-backend-wasm.wasm'; @@ -3671,17 +3674,17 @@ } wasmPath = path; customFetch = usePlatformFetch; - } - + } + /** @license See the LICENSE file. */ // This code is auto-generated, do not modify this file! - const version = '0.0.0'; - - exports.BackendWasm = BackendWasm; - exports.setWasmPath = setWasmPath; - exports.version_wasm = version; - - Object.defineProperty(exports, '__esModule', { value: true }); - -}))); -//# sourceMappingURL=tf-backend-wasm.js.map + const version = '0.0.0'; + + exports.BackendWasm = BackendWasm; + exports.setWasmPath = setWasmPath; + exports.version_wasm = version; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); +//# sourceMappingURL=tf-backend-wasm.js.map diff --git a/tfjs-backend-wasm/src/backend_wasm.ts b/tfjs-backend-wasm/src/backend_wasm.ts index 7204a04a0df..1c3441fed48 100644 --- a/tfjs-backend-wasm/src/backend_wasm.ts +++ b/tfjs-backend-wasm/src/backend_wasm.ts @@ -221,6 +221,9 @@ export async function init(): Promise<{wasm: BackendWasmModule}> { if (path.endsWith('.wasm')) { if (simdSupported) { + if (threadsSupported) { + return prefix + 'tfjs-backend-wasm-threaded-simd.wasm'; + } return prefix + 'tfjs-backend-wasm-simd.wasm'; } return prefix + 'tfjs-backend-wasm.wasm'; From d2d82f6cdd7e33678f3872f18687ae88a8977ca1 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Fri, 31 Jul 2020 13:03:43 -0400 Subject: [PATCH 34/70] rm standalone from top --- e2e/benchmarks/tf-backend-wasm.js | 3627 ++++++++++++++++++++ e2e/benchmarks/tfjs-backend-wasm-simd.wasm | Bin 0 -> 214013 bytes e2e/benchmarks/tfjs-backend-wasm.wasm | Bin 0 -> 154589 bytes tfjs-backend-wasm/src/cc/BUILD | 1 - 4 files changed, 3627 insertions(+), 1 deletion(-) create mode 100644 e2e/benchmarks/tf-backend-wasm.js create mode 100644 e2e/benchmarks/tfjs-backend-wasm-simd.wasm create mode 100644 e2e/benchmarks/tfjs-backend-wasm.wasm diff --git a/e2e/benchmarks/tf-backend-wasm.js b/e2e/benchmarks/tf-backend-wasm.js new file mode 100644 index 00000000000..6143a807553 --- /dev/null +++ b/e2e/benchmarks/tf-backend-wasm.js @@ -0,0 +1,3627 @@ +/** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tensorflow/tfjs-core'), require('path'), require('fs')) : + typeof define === 'function' && define.amd ? define(['exports', '@tensorflow/tfjs-core', 'path', 'fs'], factory) : + (global = global || self, factory((global.tf = global.tf || {}, global.tf.wasm = global.tf.wasm || {}), global.tf, global.path, global.fs)); +}(this, (function (exports, tfjsCore, path, fs) { 'use strict'; + + path = path && path.hasOwnProperty('default') ? path['default'] : path; + fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // This enum must align with the enum defined in cc/backend.h. + var CppDType; + (function (CppDType) { + CppDType[CppDType["float32"] = 0] = "float32"; + CppDType[CppDType["int32"] = 1] = "int32"; + CppDType[CppDType["bool"] = 2] = "bool"; + CppDType[CppDType["string"] = 3] = "string"; + CppDType[CppDType["complex64"] = 4] = "complex64"; + })(CppDType || (CppDType = {})); + // Must match enum in cc/fusable_activations.h. + var FusableActivation; + (function (FusableActivation) { + FusableActivation[FusableActivation["linear"] = 0] = "linear"; + FusableActivation[FusableActivation["relu"] = 1] = "relu"; + FusableActivation[FusableActivation["relu6"] = 2] = "relu6"; + FusableActivation[FusableActivation["prelu"] = 3] = "prelu"; + })(FusableActivation || (FusableActivation = {})); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFusedMatMul; + function setup(backend) { + wasmFusedMatMul = backend.wasm.cwrap(tfjsCore._FusedMatMul, null /* void */, [ + 'number', + 'array', + 'number', + 'number', + 'array', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number' // out_id + ]); + } + function fusedBatchMatMul(args) { + const { inputs, backend, attrs } = args; + const { a, b, bias, preluActivationWeights } = inputs; + if (a.dtype !== 'float32' || b.dtype !== 'float32') { + throw new Error(`_FusedMatMul for non non-float32 tensors not yet supported.`); + } + const { transposeA, transposeB, activation } = attrs; + const aId = backend.dataIdMap.get(a.dataId).id; + const bId = backend.dataIdMap.get(b.dataId).id; + let biasId = 0; + if (bias != null) { + const biasData = backend.dataIdMap.get(bias.dataId); + if (biasData.shape.length !== 1) { + throw new Error(`_FusedMatMul only supports rank-1 bias but got ` + + `rank ${biasData.shape.length}.`); + } + biasId = biasData.id; + } + const preluActivationWeightsId = preluActivationWeights == null ? + 0 : + backend.dataIdMap.get(preluActivationWeights.dataId).id; + const fusedActivation = FusableActivation[activation]; + if (fusedActivation == null) { + throw new Error(`${activation} activation not yet supported for FusedConv2D ` + + `in the wasm backend.`); + } + const leftDim = transposeA ? a.shape[2] : a.shape[1]; + const rightDim = transposeB ? b.shape[1] : b.shape[2]; + const batchDim = a.shape[0]; + const out = backend.makeOutput([batchDim, leftDim, rightDim], a.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); + const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); + wasmFusedMatMul(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, transposeA, transposeB, fusedActivation, biasId, preluActivationWeightsId, outId); + return out; + } + const fusedMatMulConfig = { + kernelName: tfjsCore._FusedMatMul, + backendName: 'wasm', + setupFunc: setup, + kernelFunc: fusedBatchMatMul + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function createUnaryKernelConfig(kernelName) { + let wasmFunc; + function setupFunc(backend) { + wasmFunc = + backend.wasm.cwrap(kernelName, null /* void */, ['number', 'number']); + } + function kernelFunc(args) { + const { backend, inputs: { x } } = args; + const xId = backend.dataIdMap.get(x.dataId).id; + const out = backend.makeOutput(x.shape, x.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(out.shape) === 0) { + return out; + } + wasmFunc(xId, outId); + return out; + } + return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const absConfig = createUnaryKernelConfig(tfjsCore.Abs); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function createBinaryKernelConfig(kernelName, supportsFullBroadcast, dtype) { + let wasmFunc; + function setupFunc(backend) { + wasmFunc = backend.wasm.cwrap(kernelName, null /* void */, [ + 'number', + 'array', + 'number', + 'number', + 'array', + 'number', + 'number', + 'number' // out_id + ]); + } + function kernelFunc(args) { + const { backend, inputs } = args; + const { a, b } = inputs; + const aId = backend.dataIdMap.get(a.dataId).id; + const bId = backend.dataIdMap.get(b.dataId).id; + const outputType = dtype != null ? dtype : a.dtype; + const newShape = tfjsCore.backend_util.assertAndGetBroadcastShape(a.shape, b.shape); + const out = backend.makeOutput(newShape, outputType); + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(newShape) === 0) { + return out; + } + const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); + const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); + const outId = backend.dataIdMap.get(out.dataId).id; + const kernelFunc = () => wasmFunc(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, CppDType[a.dtype], outId); + // Currently only some float operations support full broadcast. + if (supportsFullBroadcast && a.dtype === 'float32') { + kernelFunc(); + return out; + } + const aBroadcastDims = tfjsCore.backend_util.getBroadcastDims(a.shape, newShape); + const bBroadcastDims = tfjsCore.backend_util.getBroadcastDims(b.shape, newShape); + const loopsOverAllOfA = aBroadcastDims.every((v, i) => v === i); + const loopsOverAllOfB = bBroadcastDims.every((v, i) => v === i); + if (loopsOverAllOfA && loopsOverAllOfB) { + kernelFunc(); + return out; + } + else { + throw new Error(`Broadcasting along outer dims is not yet ` + + `supported for ${a.dtype} ${kernelName}.`); + } + } + return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast = true; + const addConfig = createBinaryKernelConfig(tfjsCore.Add, supportsFullBroadcast); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc; + function setupFunc(backend) { + wasmFunc = backend.wasm.cwrap(tfjsCore.AddN, null /* void */, [ + 'array', + 'number', + 'number', + 'number', + ]); + } + function addn(args) { + const { inputs, backend } = args; + const out = backend.makeOutput(inputs[0].shape, inputs[0].dtype); + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(out.shape) === 0) { + return out; + } + const inputIds = inputs.map(x => backend.dataIdMap.get(x.dataId).id); + const inputIdsBytes = new Uint8Array(new Int32Array(inputIds).buffer); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmFunc(inputIdsBytes, inputIds.length, CppDType[out.dtype], outId); + return out; + } + const addNConfig = { + kernelName: tfjsCore.AddN, + backendName: 'wasm', + setupFunc, + kernelFunc: addn, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function identity(args) { + const { inputs: { x }, backend } = args; + const out = backend.makeOutput(x.shape, x.dtype); + const inVals = backend.typedArrayFromHeap(x); + const outVals = backend.typedArrayFromHeap(out); + outVals.set(inVals); + return out; + } + const identityConfig = { + kernelName: tfjsCore.Identity, + backendName: 'wasm', + kernelFunc: identity, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmTranspose; + function setup$1(backend) { + wasmTranspose = backend.wasm.cwrap(tfjsCore.Transpose, null /* void */, [ + 'number', + 'array', + 'number', + 'number', + 'number', + 'array', + 'number', + ]); + } + function transpose(args) { + const { inputs, backend, attrs } = args; + // Reduce any dimensions with size one. Lower-rank transpose kernel performs + // better due to simpler memory access pattern. + const [reducedShape, perm] = removeOneSizeDims(inputs.x.shape, attrs.perm); + let permIsNoOp = true; + for (let i = 0; i < perm.length; i++) { + if (perm[i] !== i) { + permIsNoOp = false; + } + } + const outShape = computeOutShape(inputs.x.shape, attrs.perm); + const x = { + dataId: inputs.x.dataId, + shape: reducedShape, + dtype: inputs.x.dtype + }; + if (permIsNoOp) { + const cloned = identity({ inputs, backend }); + cloned.shape = outShape; + return cloned; + } + const out = backend.makeOutput(outShape, x.dtype); + const xId = backend.dataIdMap.get(x.dataId).id; + const outId = backend.dataIdMap.get(out.dataId).id; + const permBytes = new Uint8Array(new Int32Array(perm).buffer); + const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); + wasmTranspose(xId, xShapeBytes, x.shape.length, CppDType[x.dtype], outId, permBytes, perm.length); + return out; + } + function computeOutShape(inShape, perm) { + const outShape = new Array(inShape.length); + for (let i = 0; i < outShape.length; i++) { + outShape[i] = inShape[perm[i]]; + } + return outShape; + } + function removeOneSizeDims(shape, perm) { + const newShape = []; + const newPerm = []; + for (let i = 0; i < shape.length; ++i) { + if (shape[i] !== 1) { + newShape.push(shape[i]); + } + if (shape[perm[i]] !== 1) { + newPerm.push(perm[i]); + } + } + for (let i = 0; i < newPerm.length; ++i) { + let minValIdx = -1; + for (let j = 0; j < newPerm.length; ++j) { + if (newPerm[j] >= i && + (minValIdx === -1 || newPerm[minValIdx] > newPerm[j])) { + minValIdx = j; + } + } + newPerm[minValIdx] = i; + } + return [newShape, newPerm]; + } + const transposeConfig = { + kernelName: tfjsCore.Transpose, + backendName: 'wasm', + kernelFunc: transpose, + setupFunc: setup$1, + }; + + /** + * @license + * Copyright 2020 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Compute permutation axes and do a transpose if necessary. + * + * Used by reduction ops. + * @param x input TensorInfo + * @param axis reduction axes + * @param backend wasm backend instance + */ + function permuteAxesAndTranspose(x, axis, backend) { + const xShape = x.shape; + const xRank = x.shape.length; + const originalAxes = tfjsCore.util.parseAxisParam(axis, xShape); + let axes = originalAxes; + const permutedAxes = tfjsCore.backend_util.getAxesPermutation(axes, xRank); + let xTransposed = null; + let inputWasTransposed = false; + if (permutedAxes != null) { + const newShape = new Array(xRank); + for (let i = 0; i < newShape.length; i++) { + newShape[i] = xShape[permutedAxes[i]]; + } + axes = tfjsCore.backend_util.getInnerMostAxes(axes.length, xRank); + xTransposed = + transpose({ inputs: { x }, attrs: { perm: permutedAxes }, backend }); + const xId = backend.dataIdMap.get(x.dataId).id; + const transposedId = backend.dataIdMap.get(xTransposed.dataId).id; + if (transposedId !== xId) { + inputWasTransposed = true; + } + } + return { transposed: xTransposed, originalAxes, axes, inputWasTransposed }; + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$1; + function setup$2(backend) { + wasmFunc$1 = backend.wasm.cwrap(tfjsCore.ArgMax, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number' // out_id + ]); + } + function argmax(args) { + const { backend, inputs, attrs } = args; + const { axis } = attrs; + const { x } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + let inputId = xId; + let input = x; + const { transposed, axes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); + if (inputWasTransposed) { + const transposedId = backend.dataIdMap.get(transposed.dataId).id; + if (transposedId !== xId) { + // transpose was not a no-op. We will need to dispose of this + // once we are done. + input = transposed; + inputId = transposedId; + } + } + const outShape = input.shape.slice(0, -1); + const out = backend.makeOutput(outShape, 'int32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const outerSize = tfjsCore.util.sizeFromShape(out.shape); + const innerSize = input.shape[axes[0]]; + wasmFunc$1(inputId, CppDType[input.dtype], outerSize, innerSize, outId); + if (inputWasTransposed) { + // dispose of the transposed tensor. + backend.disposeData(transposed.dataId); + } + return out; + } + const argMaxConfig = { + kernelName: tfjsCore.ArgMax, + backendName: 'wasm', + kernelFunc: argmax, + setupFunc: setup$2 + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmAvgPool; + function setup$3(backend) { + wasmAvgPool = backend.wasm.cwrap(tfjsCore.AvgPool, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function avgPool(args) { + const { inputs, attrs, backend } = args; + const x = inputs.x; + const xId = backend.dataIdMap.get(x.dataId).id; + const { filterSize, strides, pad, dimRoundingMode } = attrs; + const convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const channels = convInfo.inChannels; + if (convInfo.dataFormat !== 'channelsLast') { + throw new Error(`wasm backend does not support dataFormat:'` + + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + } + if (convInfo.dilationWidth !== 1 || convInfo.dilationHeight !== 1) { + throw new Error(`was backend only supports average pooling with dilation = [1, 1], ` + + `got [${convInfo.dilationHeight}, ${convInfo.dilationWidth}].`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmAvgPool(xId, x.shape[0], x.shape[1], x.shape[2], filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, strideHeight, strideWidth, channels, outId); + return out; + } + const avgPoolConfig = { + kernelName: tfjsCore.AvgPool, + backendName: 'wasm', + setupFunc: setup$3, + kernelFunc: avgPool + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmBatchMatMul; + function setup$4(backend) { + wasmBatchMatMul = backend.wasm.cwrap(tfjsCore.BatchMatMul, null /* void */, [ + 'number', + 'array', + 'number', + 'number', + 'array', + 'number', + 'number', + 'number', + 'number' // out_id + ]); + } + function batchMatMul(args) { + const { inputs, backend, attrs } = args; + const { a, b } = inputs; + if (a.dtype !== 'float32' || b.dtype !== 'float32') { + throw new Error(`BatchMatMul for non non-float32 tensors not yet supported.`); + } + const { transposeA, transposeB } = attrs; + const aId = backend.dataIdMap.get(a.dataId).id; + const bId = backend.dataIdMap.get(b.dataId).id; + const leftDim = transposeA ? a.shape[2] : a.shape[1]; + const rightDim = transposeB ? b.shape[1] : b.shape[2]; + const batchDim = a.shape[0]; + const out = backend.makeOutput([batchDim, leftDim, rightDim], a.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); + const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); + wasmBatchMatMul(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, transposeA, transposeB, outId); + return out; + } + const batchMatMulConfig = { + kernelName: tfjsCore.BatchMatMul, + backendName: 'wasm', + setupFunc: setup$4, + kernelFunc: batchMatMul + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function cast(args) { + const { inputs: { x }, attrs: { dtype }, backend } = args; + const out = backend.makeOutput(x.shape, dtype); + const inVals = backend.typedArrayFromHeap(x); + const outVals = backend.typedArrayFromHeap(out); + outVals.set(inVals); + return out; + } + const castConfig = { + kernelName: tfjsCore.Cast, + backendName: 'wasm', + kernelFunc: cast, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmClip; + function setup$5(backend) { + wasmClip = backend.wasm.cwrap(tfjsCore.ClipByValue, null /* void */, [ + 'number', + 'number', + 'number', + 'number' // out_id + ]); + } + function clip(args) { + const { inputs, backend, attrs } = args; + const { x } = inputs; + const { clipValueMin, clipValueMax } = attrs; + const xId = backend.dataIdMap.get(x.dataId).id; + const out = backend.makeOutput(x.shape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmClip(xId, clipValueMin, clipValueMax, outId); + return out; + } + const clipByValueConfig = { + kernelName: tfjsCore.ClipByValue, + backendName: 'wasm', + setupFunc: setup$5, + kernelFunc: clip + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function concat(args) { + const { inputs, backend } = args; + const axis = tfjsCore.util.parseAxisParam(args.attrs.axis, inputs[0].shape)[0]; + const outShape = tfjsCore.backend_util.computeOutShape(inputs.map(t => t.shape), axis); + const out = backend.makeOutput(outShape, inputs[0].dtype); + const batchDim = tfjsCore.util.sizeFromShape(inputs[0].shape.slice(0, axis)); + let sumInnerDims = 0; + const innerDims = inputs.map(input => { + const innerDim = tfjsCore.util.sizeFromShape(input.shape.slice(axis)); + sumInnerDims += innerDim; + return innerDim; + }); + const inVals = inputs.map(input => backend.typedArrayFromHeap(input)); + const outVals = backend.typedArrayFromHeap(out); + for (let b = 0; b < batchDim; b++) { + let outOffset = b * sumInnerDims; + for (let i = 0; i < inVals.length; i++) { + const innerDim = innerDims[i]; + const inOffset = b * innerDim; + const vals = inVals[i].subarray(inOffset, inOffset + innerDim); + outVals.set(vals, outOffset); + outOffset += innerDim; + } + } + return out; + } + const concatConfig = { + kernelName: tfjsCore.Concat, + backendName: 'wasm', + kernelFunc: concat, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmConv2d; + function setup$6(backend) { + wasmConv2d = backend.wasm.cwrap(tfjsCore.Conv2D, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function conv2d(args) { + const { inputs, attrs, backend } = args; + const { x, filter } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const filterId = backend.dataIdMap.get(filter.dataId).id; + const { strides, dilations, pad, dimRoundingMode, dataFormat } = attrs; + const $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat); + const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const dilationHeight = convInfo.dilationHeight; + const dilationWidth = convInfo.dilationWidth; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const inputChannels = convInfo.inChannels; + const outputChannels = convInfo.outChannels; + const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; + if (convInfo.dataFormat !== 'channelsLast') { + throw new Error(`wasm backend Conv2D does not support dataFormat:'` + + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmConv2d(xId, x.shape[0], x.shape[1], x.shape[2], filterId, filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); + return out; + } + const conv2DConfig = { + kernelName: tfjsCore.Conv2D, + backendName: 'wasm', + setupFunc: setup$6, + kernelFunc: conv2d + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmConv2DBackpropInput; + function setup$7(backend) { + wasmConv2DBackpropInput = backend.wasm.cwrap(tfjsCore.Conv2DBackpropInput, null, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function conv2DBackpropInput(args) { + const { backend, inputs, attrs } = args; + const { dy, filter } = inputs; + const { strides, pad, dataFormat, dimRoundingMode, inputShape } = attrs; + const dilations = 1; + const $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat); + const convInfo = tfjsCore.backend_util.computeConv2DInfo(inputShape, filter.shape, strides, dilations, pad, dimRoundingMode, false /* depthwise */, $dataFormat); + const { batchSize, filterHeight, filterWidth, inChannels, inHeight, inWidth, outChannels, outHeight, outWidth, strideHeight, strideWidth } = convInfo; + const topPad = filterHeight - 1 - convInfo.padInfo.top; + const leftPad = filterWidth - 1 - convInfo.padInfo.left; + const isChannelsLast = convInfo.dataFormat === 'channelsLast'; + const dxStrides = tfjsCore.util.computeStrides(convInfo.inShape); + const dyStrides = tfjsCore.util.computeStrides(dy.shape); + const [fltS0, fltS1, fltS2] = tfjsCore.util.computeStrides(filter.shape); + const xBatchStride = dxStrides[0]; + const xRowStride = isChannelsLast ? dxStrides[1] : dxStrides[2]; + const xColStride = isChannelsLast ? dxStrides[2] : 1; + const xChannelStride = isChannelsLast ? 1 : dxStrides[1]; + const yBatchStride = dyStrides[0]; + const yRowStride = isChannelsLast ? dyStrides[1] : dyStrides[2]; + const yColStride = isChannelsLast ? dyStrides[2] : 1; + const yChannelStride = isChannelsLast ? 1 : dyStrides[1]; + const out = backend.makeOutput(convInfo.inShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const dyId = backend.dataIdMap.get(dy.dataId).id; + const filterId = backend.dataIdMap.get(filter.dataId).id; + wasmConv2DBackpropInput(dyId, filterId, batchSize, filterHeight, filterWidth, inHeight, inWidth, inChannels, outHeight, outWidth, outChannels, strideHeight, strideWidth, topPad, leftPad, fltS0, fltS1, fltS2, xBatchStride, xRowStride, xColStride, xChannelStride, yBatchStride, yRowStride, yColStride, yChannelStride, outId); + return out; + } + const conv2DBackpropInputConfig = { + kernelName: tfjsCore.Conv2DBackpropInput, + backendName: 'wasm', + setupFunc: setup$7, + kernelFunc: conv2DBackpropInput + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const cosConfig = createUnaryKernelConfig(tfjsCore.Cos); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // Must match enum in CropAndResize.cc + var InterpolationMethod; + (function (InterpolationMethod) { + InterpolationMethod[InterpolationMethod["bilinear"] = 0] = "bilinear"; + InterpolationMethod[InterpolationMethod["nearest"] = 1] = "nearest"; + })(InterpolationMethod || (InterpolationMethod = {})); + let wasmCropAndResize; + function setup$8(backend) { + wasmCropAndResize = backend.wasm.cwrap(tfjsCore.CropAndResize, null /*void*/, [ + 'number', + 'number', + 'number', + 'number', + 'array', + 'number', + 'number', + 'number', + 'number', + 'number' // out id + ]); + } + function cropAndResize(args) { + const { backend, inputs, attrs } = args; + const { method, extrapolationValue, cropSize } = attrs; + const { image, boxes, boxInd } = inputs; + const numBoxes = boxes.shape[0]; + const [cropHeight, cropWidth] = cropSize; + const outShape = [numBoxes, cropHeight, cropWidth, image.shape[3]]; + let imagesData = backend.dataIdMap.get(image.dataId); + let castedData; + if (image.dtype !== 'float32') { + castedData = cast({ backend, inputs: { x: image }, attrs: { dtype: 'float32' } }); + imagesData = backend.dataIdMap.get(castedData.dataId); + } + const imagesId = imagesData.id; + const boxesId = backend.dataIdMap.get(boxes.dataId).id; + const boxIndId = backend.dataIdMap.get(boxInd.dataId).id; + const out = backend.makeOutput(outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const imagesShapeBytes = new Uint8Array(new Int32Array(image.shape).buffer); + wasmCropAndResize(imagesId, boxesId, boxIndId, numBoxes, imagesShapeBytes, cropHeight, cropWidth, InterpolationMethod[method], extrapolationValue, outId); + if (castedData != null) { + backend.disposeData(castedData.dataId); + } + return out; + } + const cropAndResizeConfig = { + kernelName: tfjsCore.CropAndResize, + backendName: 'wasm', + setupFunc: setup$8, + kernelFunc: cropAndResize + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmDepthwiseConv2d; + function setup$9(backend) { + wasmDepthwiseConv2d = + backend.wasm.cwrap(tfjsCore.DepthwiseConv2dNative, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function depthwiseConv2d(args) { + const { inputs, attrs, backend } = args; + const { x, filter } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const filterId = backend.dataIdMap.get(filter.dataId).id; + const { strides, dilations, pad, dimRoundingMode } = attrs; + const $dilations = dilations == null ? [1, 1] : dilations; + const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, $dilations, pad, dimRoundingMode, true /* depthwise */); + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const dilationHeight = convInfo.dilationHeight; + const dilationWidth = convInfo.dilationWidth; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const inputChannels = convInfo.inChannels; + const outputChannels = convInfo.outChannels; + const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; + if (convInfo.dataFormat !== 'channelsLast') { + throw new Error(`wasm backend DepthwiseConv2dNative does not support dataFormat:'` + + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmDepthwiseConv2d(xId, x.shape[0], x.shape[1], x.shape[2], filterId, filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); + return out; + } + const depthwiseConv2DNativeConfig = { + kernelName: tfjsCore.DepthwiseConv2dNative, + backendName: 'wasm', + setupFunc: setup$9, + kernelFunc: depthwiseConv2d + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$1 = true; + const divConfig = createBinaryKernelConfig(tfjsCore.Div, supportsFullBroadcast$1); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$2 = false; + const equalConfig = createBinaryKernelConfig(tfjsCore.Equal, supportsFullBroadcast$2, 'bool'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const expConfig = createUnaryKernelConfig(tfjsCore.Exp); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function fill(args) { + const { attrs: { shape, value, dtype }, backend } = args; + const out = backend.makeOutput(shape, dtype); + const outVals = backend.typedArrayFromHeap(out); + outVals.fill(value); + return out; + } + const fillConfig = { + kernelName: tfjsCore.Fill, + backendName: 'wasm', + kernelFunc: fill, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$3 = false; + const floorDivConfig = createBinaryKernelConfig(tfjsCore.FloorDiv, supportsFullBroadcast$3); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmBatchNorm; + function setup$a(backend) { + wasmBatchNorm = backend.wasm.cwrap(tfjsCore.FusedBatchNorm, null /* void */, ['number', 'number', 'number', 'number', 'number', 'number', 'number']); + } + function fusedBatchNorm(args) { + const { backend, inputs, attrs } = args; + const { varianceEpsilon } = attrs; + const { x, mean, variance, offset, scale } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const meanId = backend.dataIdMap.get(mean.dataId).id; + const varianceId = backend.dataIdMap.get(variance.dataId).id; + const offsetId = offset != null ? backend.dataIdMap.get(offset.dataId).id : 0; + const scaleId = scale != null ? backend.dataIdMap.get(scale.dataId).id : 0; + const out = backend.makeOutput(x.shape, x.dtype); + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(x.shape) === 0) { + return out; + } + const outId = backend.dataIdMap.get(out.dataId).id; + wasmBatchNorm(xId, meanId, varianceId, offsetId, scaleId, varianceEpsilon, outId); + return out; + } + const fusedBatchNormConfig = { + kernelName: tfjsCore.FusedBatchNorm, + backendName: 'wasm', + setupFunc: setup$a, + kernelFunc: fusedBatchNorm + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFusedConv2d; + function setup$b(backend) { + wasmFusedConv2d = backend.wasm.cwrap(tfjsCore.FusedConv2D, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function fusedConv2d(args) { + const { inputs, attrs, backend } = args; + const { x, filter, bias, preluActivationWeights } = inputs; + const { strides, pad, dilations, dataFormat, dimRoundingMode, activation } = attrs; + const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode); + const fusedActivation = FusableActivation[activation]; + if (fusedActivation == null) { + throw new Error(`${activation} activation not yet supported for FusedConv2D ` + + `in the wasm backend.`); + } + const xId = backend.dataIdMap.get(x.dataId).id; + const filterId = backend.dataIdMap.get(filter.dataId).id; + const outputChannels = convInfo.outChannels; + let biasId = 0; + if (bias != null) { + const biasData = backend.dataIdMap.get(bias.dataId); + if (biasData.shape.length !== 1) { + throw new Error(`FusedConv2D only supports rank-1 bias but got ` + + `rank ${biasData.shape.length}.`); + } + if (biasData.shape[0] !== outputChannels) { + throw new Error(`FusedConv2D bias shape (${biasData.shape}) does not ` + + `match the number of output channels (${outputChannels})`); + } + biasId = biasData.id; + } + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const dilationHeight = convInfo.dilationHeight; + const dilationWidth = convInfo.dilationWidth; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const inputChannels = convInfo.inChannels; + const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; + const batchSize = convInfo.batchSize; + const inHeight = convInfo.inHeight; + const inWidth = convInfo.inWidth; + if (dataFormat !== 'NHWC') { + throw new Error(`wasm backend FusedConv2D does not support dataFormat:'` + + `${dataFormat}'. Please use 'NHWC'.`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const preluActivationWeightsId = preluActivationWeights == null ? + 0 : + backend.dataIdMap.get(preluActivationWeights.dataId).id; + wasmFusedConv2d(xId, batchSize, inHeight, inWidth, filterId, filterHeight, filterWidth, biasId, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, fusedActivation, preluActivationWeightsId, outId); + return out; + } + const fusedConv2DConfig = { + kernelName: tfjsCore.FusedConv2D, + backendName: 'wasm', + setupFunc: setup$b, + kernelFunc: fusedConv2d + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFusedDepthwiseConv2d; + function setup$c(backend) { + wasmFusedDepthwiseConv2d = + backend.wasm.cwrap(tfjsCore.FusedDepthwiseConv2D, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function fusedDepthwiseConv2d(args) { + const { inputs, attrs, backend } = args; + const { x, filter, bias, preluActivationWeights } = inputs; + const { strides, pad, dilations, dataFormat, dimRoundingMode, activation } = attrs; + const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, true /* depthwise */); + const fusedActivation = FusableActivation[activation]; + if (fusedActivation == null) { + throw new Error(`${activation} activation not yet supported for FusedDepthwiseConv2D ` + + `in the wasm backend.`); + } + const xId = backend.dataIdMap.get(x.dataId).id; + const filterId = backend.dataIdMap.get(filter.dataId).id; + const outputChannels = convInfo.outChannels; + let biasId = 0; + if (bias != null) { + const biasData = backend.dataIdMap.get(bias.dataId); + if (biasData.shape.length !== 1) { + throw new Error(`FusedDepthwiseConv2D only supports rank-1 bias but got ` + + `rank ${biasData.shape.length}.`); + } + if (biasData.shape[0] !== outputChannels) { + throw new Error(`FusedDepthwiseConv2D bias shape (${biasData.shape}) does not ` + + `match the number of output channels (${outputChannels})`); + } + biasId = biasData.id; + } + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const dilationHeight = convInfo.dilationHeight; + const dilationWidth = convInfo.dilationWidth; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const inputChannels = convInfo.inChannels; + const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; + const batchSize = convInfo.batchSize; + const inHeight = convInfo.inHeight; + const inWidth = convInfo.inWidth; + if (dataFormat !== 'NHWC') { + throw new Error(`wasm backend FusedDepthwiseConv2D does not support dataFormat:'` + + `${dataFormat}'. Please use 'NHWC'.`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const preluActivationWeightsId = preluActivationWeights == null ? + 0 : + backend.dataIdMap.get(preluActivationWeights.dataId).id; + wasmFusedDepthwiseConv2d(xId, batchSize, inHeight, inWidth, filterId, filterHeight, filterWidth, biasId, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, fusedActivation, preluActivationWeightsId, outId); + return out; + } + const fusedDepthwiseConv2DConfig = { + kernelName: tfjsCore.FusedDepthwiseConv2D, + backendName: 'wasm', + setupFunc: setup$c, + kernelFunc: fusedDepthwiseConv2d + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmGatherNd; + function setup$d(backend) { + wasmGatherNd = backend.wasm.cwrap(tfjsCore.GatherNd, null /*void*/, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'array', + 'number' // outId + ]); + } + function gatherNd(args) { + const { backend, inputs } = args; + const { params, indices } = inputs; + const [resultShape, numSlices, sliceSize, strides] = tfjsCore.gather_util.prepareAndValidate(params, indices); + const out = backend.makeOutput(resultShape, params.dtype); + if (numSlices === 0) { + return out; + } + const indicesShape = indices.shape; + const sliceRank = indicesShape[indicesShape.length - 1]; + const xData = backend.dataIdMap.get(params.dataId); + const xId = xData.id; + const indicesData = backend.dataIdMap.get(indices.dataId); + const indicesId = indicesData.id; + const stridesBytes = new Uint8Array(new Int32Array(strides).buffer); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmGatherNd(xId, CppDType[params.dtype], indicesId, numSlices, sliceRank, sliceSize, stridesBytes, outId); + return out; + } + const gatherNdConfig = { + kernelName: tfjsCore.GatherNd, + backendName: 'wasm', + setupFunc: setup$d, + kernelFunc: gatherNd + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmGather; + function setup$e(backend) { + wasmGather = backend.wasm.cwrap('Gather', null /*void*/, [ + 'number', + 'number', + 'array', + 'number', + 'number', + 'number', + 'array', + 'number' // outId + ]); + } + function gatherV2(args) { + const { backend, inputs, attrs } = args; + const { x, indices } = inputs; + const { axis } = attrs; + const newShape = x.shape.slice(); + newShape[axis] = tfjsCore.util.sizeFromShape(indices.shape); + const stridesSize = x.shape.length - 1; + const out = backend.makeOutput(newShape, x.dtype); + if (tfjsCore.util.sizeFromShape(x.shape) === 0) { + return out; + } + const xData = backend.dataIdMap.get(x.dataId); + const xId = xData.id; + const indicesData = backend.dataIdMap.get(indices.dataId); + const indicesId = indicesData.id; + const outId = backend.dataIdMap.get(out.dataId).id; + const xStridesBytes = new Uint8Array(new Int32Array(tfjsCore.util.computeStrides(x.shape)).buffer); + const outStridesBytes = new Uint8Array(new Int32Array(tfjsCore.util.computeStrides(newShape)).buffer); + wasmGather(xId, CppDType[x.dtype], xStridesBytes, stridesSize, indicesId, axis, outStridesBytes, outId); + // reshape + const parsedAxis = tfjsCore.util.parseAxisParam(axis, x.shape)[0]; + const shapeInfo = tfjsCore.backend_util.segment_util.collectGatherOpShapeInfo(x, indices, parsedAxis); + out.shape = shapeInfo.outputShape; + return out; + } + const gatherV2Config = { + kernelName: tfjsCore.GatherV2, + backendName: 'wasm', + setupFunc: setup$e, + kernelFunc: gatherV2 + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$4 = false; + const greaterConfig = createBinaryKernelConfig(tfjsCore.Greater, supportsFullBroadcast$4, 'bool'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$5 = false; + const greaterEqualConfig = createBinaryKernelConfig(tfjsCore.GreaterEqual, supportsFullBroadcast$5, 'bool'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$6 = false; + const lessConfig = createBinaryKernelConfig(tfjsCore.Less, supportsFullBroadcast$6, 'bool'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$7 = false; + const lessEqualConfig = createBinaryKernelConfig(tfjsCore.LessEqual, supportsFullBroadcast$7, 'bool'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const logConfig = createUnaryKernelConfig(tfjsCore.Log); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$8 = false; + const logicalAndConfig = createBinaryKernelConfig(tfjsCore.LogicalAnd, supportsFullBroadcast$8, 'bool'); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmMax; + function setup$f(backend) { + wasmMax = backend.wasm.cwrap(tfjsCore.Max, null /*void*/, ['number, number, number']); + } + function max(args) { + const { backend, inputs, attrs } = args; + const { reductionIndices: axis, keepDims } = attrs; + const { x } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + let inputId = xId; + let input = x; + const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); + if (inputWasTransposed) { + const transposedId = backend.dataIdMap.get(transposed.dataId).id; + input = transposed; + inputId = transposedId; + } + const inputRank = input.shape.length; + tfjsCore.backend_util.assertAxesAreInnerMostDims('max', axes, inputRank); + const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, axes); + const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); + const out = backend.makeOutput(outShape, x.dtype); + if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { + const outId = backend.dataIdMap.get(out.dataId).id; + wasmMax(inputId, reduceSize, outId); + } + if (inputWasTransposed) { + // dispose of the transposed tensor. + backend.disposeData(transposed.dataId); + } + if (keepDims) { + // reshape + const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); + out.shape = newShape; + } + return out; + } + const maxConfig = { + kernelName: tfjsCore.Max, + backendName: 'wasm', + setupFunc: setup$f, + kernelFunc: max + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$9 = false; + const maximumConfig = createBinaryKernelConfig(tfjsCore.Maximum, supportsFullBroadcast$9); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmMaxPool; + function setup$g(backend) { + wasmMaxPool = backend.wasm.cwrap(tfjsCore.MaxPool, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function maxPool(args) { + const { inputs, attrs, backend } = args; + const x = inputs.x; + const xId = backend.dataIdMap.get(x.dataId).id; + const { filterSize, strides, pad, dimRoundingMode } = attrs; + const convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); + const filterHeight = convInfo.filterHeight; + const filterWidth = convInfo.filterWidth; + const padTop = convInfo.padInfo.top; + const padRight = convInfo.padInfo.right; + const padBottom = convInfo.padInfo.bottom; + const padLeft = convInfo.padInfo.left; + const dilationHeight = convInfo.dilationHeight; + const dilationWidth = convInfo.dilationWidth; + const strideHeight = convInfo.strideHeight; + const strideWidth = convInfo.strideWidth; + const inputChannels = convInfo.inChannels; + const outputChannels = convInfo.outChannels; + if (convInfo.dataFormat !== 'channelsLast') { + throw new Error(`wasm backend does not support dataFormat:'` + + `${convInfo.dataFormat}'. Please use 'channelsLast'.`); + } + const out = backend.makeOutput(convInfo.outShape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmMaxPool(xId, x.shape[0], x.shape[1], x.shape[2], filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); + return out; + } + const maxPoolConfig = { + kernelName: tfjsCore.MaxPool, + backendName: 'wasm', + setupFunc: setup$g, + kernelFunc: maxPool + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmMin; + function setup$h(backend) { + wasmMin = backend.wasm.cwrap(tfjsCore.Min, null /*void*/, ['number, number, number']); + } + function min(args) { + const { backend, inputs, attrs } = args; + const { axis, keepDims } = attrs; + const { x } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + let inputId = xId; + let input = x; + const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); + if (inputWasTransposed) { + const transposedId = backend.dataIdMap.get(transposed.dataId).id; + if (transposedId !== xId) { + // transpose was not a no-op. We will need to dispose of this + // once we are done. + input = transposed; + inputId = transposedId; + } + } + const inputRank = input.shape.length; + tfjsCore.backend_util.assertAxesAreInnerMostDims('min', axes, inputRank); + const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, axes); + const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); + const out = backend.makeOutput(outShape, input.dtype); + if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { + const outId = backend.dataIdMap.get(out.dataId).id; + wasmMin(inputId, reduceSize, outId); + } + if (inputWasTransposed) { + // dispose of the transposed tensor. + backend.disposeData(transposed.dataId); + } + if (keepDims) { + // reshape + const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); + out.shape = newShape; + } + return out; + } + const minConfig = { + kernelName: tfjsCore.Min, + backendName: 'wasm', + setupFunc: setup$h, + kernelFunc: min + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$a = false; + const minimumConfig = createBinaryKernelConfig(tfjsCore.Minimum, supportsFullBroadcast$a); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$b = true; + const multiplyConfig = createBinaryKernelConfig(tfjsCore.Multiply, supportsFullBroadcast$b); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const negateConfig = createUnaryKernelConfig(tfjsCore.Negate); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + /** + * Parse the result of the c++ method, which has the shape equivalent to + * `Result`. + */ + function parseResultStruct(backend, resOffset) { + const result = new Int32Array(backend.wasm.HEAPU8.buffer, resOffset, 4); + const pSelectedIndices = result[0]; + const selectedSize = result[1]; + const pSelectedScores = result[2]; + const pValidOutputs = result[3]; + // Since the result was allocated on the heap, we have to delete it. + backend.wasm._free(resOffset); + return { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs }; + } + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$2; + function setup$i(backend) { + wasmFunc$2 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV3, 'number', // Result* + [ + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function kernelFunc(args) { + const { backend, inputs, attrs } = args; + const { iouThreshold, maxOutputSize, scoreThreshold } = attrs; + const { boxes, scores } = inputs; + const boxesId = backend.dataIdMap.get(boxes.dataId).id; + const scoresId = backend.dataIdMap.get(scores.dataId).id; + const resOffset = wasmFunc$2(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold); + const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); + // Since we are not using scores for V3, we have to delete it from the heap. + backend.wasm._free(pSelectedScores); + backend.wasm._free(pValidOutputs); + const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); + return selectedIndicesTensor; + } + const nonMaxSuppressionV3Config = { + kernelName: tfjsCore.NonMaxSuppressionV3, + backendName: 'wasm', + setupFunc: setup$i, + kernelFunc: kernelFunc, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$3; + function setup$j(backend) { + wasmFunc$3 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV4, 'number', // Result* + [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'bool', + ]); + } + function nonMaxSuppressionV4(args) { + const { backend, inputs, attrs } = args; + const { iouThreshold, maxOutputSize, scoreThreshold, padToMaxOutputSize } = attrs; + const { boxes, scores } = inputs; + const boxesId = backend.dataIdMap.get(boxes.dataId).id; + const scoresId = backend.dataIdMap.get(scores.dataId).id; + const resOffset = wasmFunc$3(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize); + const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); + // Since we are not using scores for V4, we have to delete it from the heap. + backend.wasm._free(pSelectedScores); + const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); + const validOutputsTensor = backend.makeOutput([], 'int32', pValidOutputs); + return [selectedIndicesTensor, validOutputsTensor]; + } + const nonMaxSuppressionV4Config = { + kernelName: tfjsCore.NonMaxSuppressionV4, + backendName: 'wasm', + setupFunc: setup$j, + kernelFunc: nonMaxSuppressionV4, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$4; + function setup$k(backend) { + wasmFunc$4 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV5, 'number', // Result* + [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function kernelFunc$1(args) { + const { backend, inputs, attrs } = args; + const { iouThreshold, maxOutputSize, scoreThreshold, softNmsSigma } = attrs; + const { boxes, scores } = inputs; + const boxesId = backend.dataIdMap.get(boxes.dataId).id; + const scoresId = backend.dataIdMap.get(scores.dataId).id; + const resOffset = wasmFunc$4(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma); + const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); + // Since we are not using validOutputs for V5, we have to delete it from the + // heap. + backend.wasm._free(pValidOutputs); + const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); + const selectedScoresTensor = backend.makeOutput([selectedSize], 'float32', pSelectedScores); + return [selectedIndicesTensor, selectedScoresTensor]; + } + const nonMaxSuppressionV5Config = { + kernelName: tfjsCore.NonMaxSuppressionV5, + backendName: 'wasm', + setupFunc: setup$k, + kernelFunc: kernelFunc$1, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$c = false; + const notEqualConfig = createBinaryKernelConfig(tfjsCore.NotEqual, supportsFullBroadcast$c, 'bool'); + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmOneHot; + function setup$l(backend) { + wasmOneHot = backend.wasm.cwrap(tfjsCore.OneHot, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number' // out_id + ]); + } + function oneHot(args) { + const { inputs, backend, attrs } = args; + const { indices } = inputs; + const { depth, onValue, offValue } = attrs; + const out = backend.makeOutput([...indices.shape, depth], 'int32'); + const outId = backend.dataIdMap.get(out.dataId).id; + const indicesData = backend.dataIdMap.get(indices.dataId); + const indicesId = indicesData.id; + wasmOneHot(indicesId, depth, onValue, offValue, outId); + return out; + } + const oneHotConfig = { + kernelName: tfjsCore.OneHot, + backendName: 'wasm', + setupFunc: setup$l, + kernelFunc: oneHot, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function onesLike(args) { + const { inputs: { x }, backend } = args; + const out = backend.makeOutput(x.shape, x.dtype); + const outVals = backend.typedArrayFromHeap(out); + outVals.fill(1); + return out; + } + const onesLikeConfig = { + kernelName: tfjsCore.OnesLike, + backendName: 'wasm', + kernelFunc: onesLike, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmPadV2; + function setup$m(backend) { + wasmPadV2 = backend.wasm.cwrap(tfjsCore.PadV2, null /* void */, [ + 'number', + 'array', + 'number', + 'number', + 'array', + 'array', + 'number', + 'number', + ]); + } + function pad(args) { + const { inputs: { x }, backend, attrs: { paddings, constantValue } } = args; + const outShape = paddings.map((p, i) => p[0] /* beforePad */ + x.shape[i] + p[1] /* afterPad */); + const xId = backend.dataIdMap.get(x.dataId).id; + const out = backend.makeOutput(outShape, x.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); + const prePaddingsFlat = paddings.map(padTuple => padTuple[0]); + const postPaddingsFlat = paddings.map(padTuple => padTuple[1]); + const prePaddingsBytes = new Uint8Array(new Int32Array(prePaddingsFlat).buffer); + const postPaddingsBytes = new Uint8Array(new Int32Array(postPaddingsFlat).buffer); + wasmPadV2(xId, xShapeBytes, x.shape.length, CppDType[x.dtype], prePaddingsBytes, postPaddingsBytes, constantValue, outId); + return out; + } + const padV2Config = { + kernelName: tfjsCore.PadV2, + backendName: 'wasm', + kernelFunc: pad, + setupFunc: setup$m + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$d = false; + const powConfig = createBinaryKernelConfig(tfjsCore.Pow, supportsFullBroadcast$d); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmPrelu; + function setup$n(backend) { + wasmPrelu = backend.wasm.cwrap(tfjsCore.Prelu, null /* void */, [ + 'number', + 'number', + 'number' // out_id + ]); + } + function prelu(args) { + const { inputs, backend } = args; + const { x, alpha } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const weightsId = backend.dataIdMap.get(alpha.dataId).id; + const out = backend.makeOutput(x.shape, 'float32'); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmPrelu(xId, weightsId, outId); + return out; + } + const preluConfig = { + kernelName: tfjsCore.Prelu, + backendName: 'wasm', + setupFunc: setup$n, + kernelFunc: prelu + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const reluConfig = createUnaryKernelConfig(tfjsCore.Relu); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const relu6Config = createUnaryKernelConfig(tfjsCore.Relu6); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function reshape(args) { + const { inputs, attrs } = args; + const { x } = inputs; + const { shape } = attrs; + return { dataId: x.dataId, shape, dtype: x.dtype }; + } + const reshapeConfig = { + kernelName: tfjsCore.Reshape, + backendName: 'wasm', + kernelFunc: reshape, + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmResizeBilinear; + function setup$o(backend) { + wasmResizeBilinear = backend.wasm.cwrap(tfjsCore.ResizeBilinear, null /*void*/, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number' // outId + ]); + } + function resizeBilinear(args) { + const { backend, inputs, attrs } = args; + const { images } = inputs; + const { alignCorners, size } = attrs; + const [newHeight, newWidth] = size; + const [batch, oldHeight, oldWidth, numChannels] = images.shape; + const outShape = [batch, newHeight, newWidth, numChannels]; + let xData = backend.dataIdMap.get(images.dataId); + let castedData; + if (xData.dtype !== 'float32') { + castedData = + cast({ backend, inputs: { x: images }, attrs: { dtype: 'float32' } }); + xData = backend.dataIdMap.get(castedData.dataId); + } + const xId = xData.id; + const out = backend.makeOutput(outShape, 'float32'); + if (tfjsCore.util.sizeFromShape(images.shape) === 0) { + return out; + } + const outId = backend.dataIdMap.get(out.dataId).id; + wasmResizeBilinear(xId, batch, oldHeight, oldWidth, numChannels, newHeight, newWidth, alignCorners ? 1 : 0, outId); + if (castedData != null) { + backend.disposeData(castedData.dataId); + } + return out; + } + const resizeBilinearConfig = { + kernelName: tfjsCore.ResizeBilinear, + backendName: 'wasm', + setupFunc: setup$o, + kernelFunc: resizeBilinear + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmReverse; + function setup$p(backend) { + wasmReverse = backend.wasm.cwrap(tfjsCore.Reverse, null, [ + 'number', + 'array', + 'number', + 'array', + 'number', + 'number' // out_id + ]); + } + function reverse(args) { + const { inputs, backend, attrs } = args; + const { x } = inputs; + const { dims } = attrs; + const axes = tfjsCore.util.parseAxisParam(dims, x.shape); + if (x.shape.length === 0) { + return identity({ inputs: { x }, backend }); + } + const out = backend.makeOutput(x.shape, x.dtype); + const xId = backend.dataIdMap.get(x.dataId).id; + const outId = backend.dataIdMap.get(out.dataId).id; + const axesBytes = new Uint8Array(new Int32Array(axes).buffer); + const outShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); + wasmReverse(xId, axesBytes, axes.length, outShapeBytes, x.shape.length, outId); + return reshape({ inputs: { x: out }, attrs: { shape: x.shape }, backend }); + } + const reverseConfig = { + kernelName: tfjsCore.Reverse, + backendName: 'wasm', + kernelFunc: reverse, + setupFunc: setup$p + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmRotate; + function setup$q(backend) { + wasmRotate = backend.wasm.cwrap(tfjsCore.RotateWithOffset, null /* void */, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'array', + 'number', + 'number', + ]); + } + function rotateWithOffset(args) { + const { inputs, backend, attrs } = args; + const { image } = inputs; + const { radians, fillValue, center } = attrs; + const out = backend.makeOutput(image.shape, image.dtype); + const imageId = backend.dataIdMap.get(image.dataId).id; + const outId = backend.dataIdMap.get(out.dataId).id; + const [batch, imageHeight, imageWidth, numChannels] = image.shape; + const [centerX, centerY] = tfjsCore.backend_util.getImageCenter(center, imageHeight, imageWidth); + const fillIsBlack = fillValue === 0; + const fullOpacityValue = 255; + const fillValues = typeof fillValue === 'number' ? + [fillValue, fillValue, fillValue, fillIsBlack ? 0 : fullOpacityValue] : + [...fillValue, fullOpacityValue]; + const fillBytes = new Uint8Array(new Int32Array(fillValues).buffer); + wasmRotate(imageId, batch, imageHeight, imageWidth, numChannels, radians, centerX, centerY, fillBytes, fillValues.length, outId); + return out; + } + const rotateWithOffsetConfig = { + kernelName: tfjsCore.RotateWithOffset, + backendName: 'wasm', + kernelFunc: rotateWithOffset, + setupFunc: setup$q + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const rsqrtConfig = createUnaryKernelConfig(tfjsCore.Rsqrt); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmScatterNd; + function setup$r(backend) { + wasmScatterNd = backend.wasm.cwrap(tfjsCore.ScatterNd, null /*void*/, [ + 'number', + 'number', + 'number', + 'number', + 'number', + 'number', + 'array', + 'number', + 'number' // outId + ]); + } + function scatterNd(args) { + const { backend, inputs, attrs } = args; + const { indices, updates } = inputs; + const { shape } = attrs; + const out = backend.makeOutput(shape, updates.dtype); + if (tfjsCore.util.sizeFromShape(shape) === 0) { + return out; + } + const { sliceRank, numUpdates, sliceSize, strides, outputSize } = tfjsCore.scatter_util.calculateShapes(updates, indices, shape); + const indicesData = backend.dataIdMap.get(indices.dataId); + const indicesId = indicesData.id; + const updatesData = backend.dataIdMap.get(updates.dataId); + const updatesId = updatesData.id; + const stridesBytes = new Uint8Array(new Int32Array(strides).buffer); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmScatterNd(indicesId, updatesId, CppDType[updates.dtype], sliceRank, numUpdates, sliceSize, stridesBytes, outputSize, outId); + return out; + } + const scatterNdConfig = { + kernelName: tfjsCore.ScatterNd, + backendName: 'wasm', + setupFunc: setup$r, + kernelFunc: scatterNd + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmSelect; + function setup$s(backend) { + wasmSelect = backend.wasm.cwrap(tfjsCore.SelectV2, null, [ + 'number', + 'number', + 'number', + 'number', + 'number', + ]); + } + function select(args) { + const { inputs, backend } = args; + const { condition, t, e } = inputs; + const conditionId = backend.dataIdMap.get(condition.dataId).id; + const tId = backend.dataIdMap.get(t.dataId).id; + const eId = backend.dataIdMap.get(e.dataId).id; + const out = backend.makeOutput(t.shape, t.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + const cRank = condition.shape.length; + const tRank = t.shape.length; + const offset = cRank === 0 || cRank > 1 || tRank === 1 ? + 1 : + tfjsCore.util.sizeFromShape(t.shape.slice(1)); + wasmSelect(conditionId, tId, eId, offset, outId); + return out; + } + const selectV2Config = { + kernelName: tfjsCore.SelectV2, + backendName: 'wasm', + kernelFunc: select, + setupFunc: setup$s + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$5; + function setup$t(backend) { + wasmFunc$5 = backend.wasm.cwrap(tfjsCore.Sigmoid, null /* void */, ['number', 'number']); + } + function sigmoid(args) { + const { backend, inputs: { x } } = args; + const xId = backend.dataIdMap.get(x.dataId).id; + const out = backend.makeOutput(x.shape, x.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(out.shape) === 0) { + return out; + } + wasmFunc$5(xId, outId); + return out; + } + const sigmoidConfig = { + kernelName: 'Sigmoid', + backendName: 'wasm', + setupFunc: setup$t, + kernelFunc: sigmoid + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const sinConfig = createUnaryKernelConfig(tfjsCore.Sin); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function slice(args) { + const { inputs: { x }, attrs: { begin, size }, backend } = args; + const [begin_, size_] = tfjsCore.slice_util.parseSliceParams(x, begin, size); + const isContinous = tfjsCore.slice_util.isSliceContinous(x.shape, begin_, size_); + const xVals = backend.typedArrayFromHeap(x); + const out = backend.makeOutput(size_, x.dtype); + const outVals = backend.typedArrayFromHeap(out); + const xStrides = tfjsCore.util.computeStrides(x.shape); + if (isContinous) { + const flatOffset = tfjsCore.slice_util.computeFlatOffset(begin_, xStrides); + outVals.set(xVals.subarray(flatOffset, flatOffset + tfjsCore.util.sizeFromShape(size_))); + return out; + } + const rank = x.shape.length; + if (rank === 2) { + slice2d(xVals, xStrides[0], outVals, begin_, size_); + } + else if (rank === 3) { + slice3d(xVals, xStrides[0], xStrides[1], outVals, begin_, size_); + } + else if (rank === 4) { + slice4d(xVals, xStrides[0], xStrides[1], xStrides[2], outVals, begin_, size_); + } + else { + genericSliceSlow(xVals, x, outVals, begin_, size_); + } + return out; + } + function slice2d(xVals, xStride, outVals, begin, size) { + let outOffset = 0; + const beginI = begin[0]; + const beginJ = begin[1]; + const endI = beginI + size[0]; + for (let i = beginI; i < endI; i++) { + const xOffset = i * xStride + beginJ; + outVals.set(xVals.subarray(xOffset, xOffset + size[1]), outOffset); + outOffset += size[1]; + } + } + function slice3d(xVals, xStride1, xStride2, outVals, begin, size) { + let outOffset = 0; + const beginI = begin[0]; + const beginJ = begin[1]; + const beginK = begin[2]; + const endI = beginI + size[0]; + const endJ = beginJ + size[1]; + for (let i = beginI; i < endI; i++) { + for (let j = beginJ; j < endJ; j++) { + const xOffset = i * xStride1 + j * xStride2 + beginK; + outVals.set(xVals.subarray(xOffset, xOffset + size[2]), outOffset); + outOffset += size[2]; + } + } + } + function slice4d(xVals, xStride1, xStride2, xStride3, outVals, begin, size) { + let outOffset = 0; + const beginI = begin[0]; + const beginJ = begin[1]; + const beginK = begin[2]; + const endI = beginI + size[0]; + const endJ = beginJ + size[1]; + const endK = beginK + size[2]; + const beginL = begin[3]; + for (let i = beginI; i < endI; i++) { + for (let j = beginJ; j < endJ; j++) { + for (let k = beginK; k < endK; k++) { + const xOffset = i * xStride1 + j * xStride2 + k * xStride3 + beginL; + outVals.set(xVals.subarray(xOffset, xOffset + size[3]), outOffset); + outOffset += size[3]; + } + } + } + } + function genericSliceSlow(xVals, xInfo, outVals, begin, size) { + const outBuf = tfjsCore.buffer(size, xInfo.dtype, outVals); + const xBuf = tfjsCore.buffer(xInfo.shape, xInfo.dtype, xVals); + for (let i = 0; i < outBuf.size; ++i) { + const loc = outBuf.indexToLoc(i); + const xLoc = loc.map((idx, j) => idx + begin[j]); + outVals[i] = xBuf.get(...xLoc); + } + } + const sliceConfig = { + kernelName: tfjsCore.Slice, + backendName: 'wasm', + kernelFunc: slice, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmFunc$6; + function setup$u(backend) { + wasmFunc$6 = backend.wasm.cwrap(tfjsCore.Softmax, null /* void */, [ + 'number', + 'number', + 'number', + 'number' // batch + ]); + } + function softmax(args) { + const { backend, inputs: { logits }, attrs: { dim } } = args; + const xId = backend.dataIdMap.get(logits.dataId).id; + const out = backend.makeOutput(logits.shape, logits.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + const channels = logits.shape[dim]; + const batch = tfjsCore.util.sizeFromShape(logits.shape) / channels; + // Short-circuit zero-sized tensors. + if (tfjsCore.util.sizeFromShape(out.shape) === 0) { + return out; + } + wasmFunc$6(xId, outId, channels, batch); + return out; + } + const softmaxConfig = { + kernelName: tfjsCore.Softmax, + backendName: 'wasm', + setupFunc: setup$u, + kernelFunc: softmax + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function split(args) { + const { inputs, attrs, backend } = args; + const { x } = inputs; + const { numOrSizeSplits, axis } = attrs; + const $axis = tfjsCore.util.parseAxisParam(axis, x.shape)[0]; + const splitSizes = tfjsCore.backend_util.prepareSplitSize(x, numOrSizeSplits, axis); + const begin = new Array(x.shape.length).fill(0); + const size = x.shape.slice(); + return splitSizes.map(s => { + const xSliceSize = [...size]; + xSliceSize[$axis] = s; + const xSlice = slice({ inputs: { x }, attrs: { begin, size: xSliceSize }, backend }); + begin[$axis] += s; + return xSlice; + }); + } + const splitVConfig = { + kernelName: tfjsCore.SplitV, + backendName: 'wasm', + kernelFunc: split + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const sqrtConfig = createUnaryKernelConfig(tfjsCore.Sqrt); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const squareConfig = createUnaryKernelConfig(tfjsCore.Square); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const supportsFullBroadcast$e = true; + const subConfig = createBinaryKernelConfig(tfjsCore.Sub, supportsFullBroadcast$e); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmSum; + function setup$v(backend) { + wasmSum = backend.wasm.cwrap(tfjsCore.Sum, null /*void*/, ['number, number, number']); + } + function sum(args) { + const { backend, inputs, attrs } = args; + const { axis, keepDims } = attrs; + const { x } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + let inputId = xId; + let input = x; + const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); + let reductionAxes = axes; + if (inputWasTransposed) { + const transposedId = backend.dataIdMap.get(transposed.dataId).id; + if (transposedId !== xId) { + // transpose was not a no-op. We will need to dispose of this + // once we are done. + input = transposed; + inputId = transposedId; + reductionAxes = tfjsCore.backend_util.getInnerMostAxes(reductionAxes.length, input.shape.length); + } + } + tfjsCore.backend_util.assertAxesAreInnerMostDims('sum', reductionAxes, input.shape.length); + const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, reductionAxes); + const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); + const out = backend.makeOutput(outShape, input.dtype); + if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { + const outId = backend.dataIdMap.get(out.dataId).id; + wasmSum(inputId, reduceSize, outId); + } + if (inputWasTransposed) { + // dispose of the transposed tensor. + backend.disposeData(transposed.dataId); + } + if (keepDims) { + // reshape + const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); + out.shape = newShape; + } + return out; + } + const sumConfig = { + kernelName: tfjsCore.Sum, + backendName: 'wasm', + setupFunc: setup$v, + kernelFunc: sum + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const tanhConfig = createUnaryKernelConfig(tfjsCore.Tanh); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + let wasmTile; + function setup$w(backend) { + wasmTile = backend.wasm.cwrap(tfjsCore.Tile, null /* void */, [ + 'number', + 'array', + 'number', + 'array', + 'number', + 'number' // out_id + ]); + } + function tile(args) { + const { inputs, backend, attrs } = args; + const { x } = inputs; + const xId = backend.dataIdMap.get(x.dataId).id; + const { reps } = attrs; + const newShape = new Array(x.shape.length); + for (let i = 0; i < newShape.length; i++) { + newShape[i] = x.shape[i] * reps[i]; + } + const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); + const newShapeBytes = new Uint8Array(new Int32Array(newShape).buffer); + const out = backend.makeOutput(newShape, x.dtype); + const outId = backend.dataIdMap.get(out.dataId).id; + wasmTile(xId, xShapeBytes, x.shape.length, newShapeBytes, newShape.length, CppDType[out.dtype], outId); + return out; + } + const tileConfig = { + kernelName: tfjsCore.Tile, + backendName: 'wasm', + setupFunc: setup$w, + kernelFunc: tile + }; + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function unpack(args) { + const { inputs, backend, attrs } = args; + const { value } = inputs; + const { axis } = attrs; + const numOutputs = value.shape[axis]; + const rank = value.shape.length; + const outShape = new Array(rank - 1); + let outIndex = 0; + for (let i = 0; i < rank; i++) { + if (i !== axis) { + outShape[outIndex++] = value.shape[i]; + } + } + const outs = new Array(numOutputs); + const begin = new Array(rank).fill(0); + const size = value.shape.slice(); + size[axis] = 1; + for (let i = 0; i < outs.length; i++) { + begin[axis] = i; + outs[i] = slice({ inputs: { x: value }, attrs: { begin, size }, backend }); + } + return outs.map(({ dataId, dtype }) => ({ dataId, dtype, shape: outShape })); + } + const unpackConfig = { + kernelName: tfjsCore.Unpack, + backendName: 'wasm', + kernelFunc: unpack, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + function zerosLike(args) { + const { inputs: { x }, backend } = args; + const out = backend.makeOutput(x.shape, x.dtype); + const outVals = backend.typedArrayFromHeap(out); + outVals.fill(0); + return out; + } + const zerosLikeConfig = { + kernelName: tfjsCore.ZerosLike, + backendName: 'wasm', + kernelFunc: zerosLike, + }; + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + // List all kernel configs here + const kernelConfigs = [ + absConfig, + addConfig, + addNConfig, + argMaxConfig, + avgPoolConfig, + batchMatMulConfig, + castConfig, + clipByValueConfig, + concatConfig, + conv2DConfig, + conv2DBackpropInputConfig, + cosConfig, + cropAndResizeConfig, + depthwiseConv2DNativeConfig, + divConfig, + equalConfig, + expConfig, + fillConfig, + floorDivConfig, + fusedMatMulConfig, + fusedBatchNormConfig, + fusedConv2DConfig, + fusedDepthwiseConv2DConfig, + gatherNdConfig, + gatherV2Config, + greaterConfig, + greaterEqualConfig, + identityConfig, + lessConfig, + lessEqualConfig, + logConfig, + logicalAndConfig, + maxConfig, + maximumConfig, + maxPoolConfig, + minConfig, + minimumConfig, + multiplyConfig, + negateConfig, + nonMaxSuppressionV3Config, + nonMaxSuppressionV4Config, + nonMaxSuppressionV5Config, + notEqualConfig, + oneHotConfig, + onesLikeConfig, + padV2Config, + powConfig, + preluConfig, + reluConfig, + relu6Config, + reshapeConfig, + resizeBilinearConfig, + reverseConfig, + rotateWithOffsetConfig, + rsqrtConfig, + scatterNdConfig, + selectV2Config, + sigmoidConfig, + sinConfig, + sliceConfig, + softmaxConfig, + splitVConfig, + sqrtConfig, + squareConfig, + subConfig, + sumConfig, + tanhConfig, + tileConfig, + transposeConfig, + unpackConfig, + zerosLikeConfig + ]; + for (const kernelConfig of kernelConfigs) { + tfjsCore.registerKernel(kernelConfig); + } + + /** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const ENV = tfjsCore.env(); + /** + * True if SIMD is supported. + */ + // From: https://github.com/GoogleChromeLabs/wasm-feature-detect + ENV.registerFlag('WASM_HAS_SIMD_SUPPORT', async () => WebAssembly.validate(new Uint8Array([ + 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, + 2, 1, 0, 10, 9, 1, 7, 0, 65, 0, 253, 15, 26, 11 + ]))); + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var tfjsBackendWasm = createCommonjsModule(function (module, exports) { + var WasmBackendModule = (function() { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( + function(WasmBackendModule) { + WasmBackendModule = WasmBackendModule || {}; + + var Module=typeof WasmBackendModule!=="undefined"?WasmBackendModule:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":146,"maximum":146+0,"element":"anyfunc"});var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023);}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var DYNAMIC_BASE=5254800,DYNAMICTOP_PTR=11760;var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":2147483648/WASM_PAGE_SIZE});}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;removeRunDependency();}addRunDependency();function receiveInstantiatedSource(output){receiveInstance(output["instance"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}__ATINIT__.push({func:function(){___wasm_call_ctors();}});function _abort(){abort();}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num);}function _emscripten_get_heap_size(){return HEAPU8.length}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=65536;var maxHeapSize=2147483648;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}var asmLibraryArg={"a":_abort,"e":_emscripten_memcpy_big,"f":_emscripten_resize_heap,"g":_fd_close,"d":_fd_seek,"c":_fd_write,"memory":wasmMemory,"b":_roundf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return (___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["h"]).apply(null,arguments)};var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["i"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["j"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["k"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["l"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["m"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["n"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["o"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["p"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["q"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["r"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["s"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["t"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["u"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["v"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["w"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["x"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["y"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["z"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["A"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["B"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["C"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["D"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["E"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["F"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["G"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["H"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["I"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["J"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["K"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["L"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["M"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["N"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["O"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["P"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["Q"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["R"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["S"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["T"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["U"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["V"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["W"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["X"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["Y"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["Z"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["_"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["$"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["aa"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["ba"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["ca"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["da"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["ea"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["fa"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["ga"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["ha"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["ia"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["ja"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["ka"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["la"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["ma"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["na"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["oa"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["pa"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["qa"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["ra"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["sa"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["ta"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["ua"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["va"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["wa"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["xa"]).apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){return (dynCall_vi=Module["dynCall_vi"]=Module["asm"]["ya"]).apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){return (dynCall_v=Module["dynCall_v"]=Module["asm"]["za"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}noExitRuntime=true;run(); + + + return WasmBackendModule + } + ); + })(); + module.exports = WasmBackendModule; + }); + + /** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ + const WASM_PRIORITY = 2; + class BackendWasm extends tfjsCore.KernelBackend { + constructor(wasm) { + super(); + this.wasm = wasm; + // 0 is reserved for null data ids. + this.dataIdNextNumber = 1; + this.wasm.tfjs.init(); + this.dataIdMap = new tfjsCore.DataStorage(this, tfjsCore.engine()); + } + write(values, shape, dtype) { + const dataId = {}; + this.move(dataId, values, shape, dtype); + return dataId; + } + numDataIds() { + return this.dataIdMap.numDataIds(); + } + async time(f) { + const start = tfjsCore.util.now(); + f(); + const kernelMs = tfjsCore.util.now() - start; + return { kernelMs }; + } + move(dataId, values, shape, dtype) { + const id = this.dataIdNextNumber++; + if (dtype === 'string') { + const stringBytes = values; + this.dataIdMap.set(dataId, { id, stringBytes, shape, dtype, memoryOffset: null }); + return; + } + const size = tfjsCore.util.sizeFromShape(shape); + const numBytes = size * tfjsCore.util.bytesPerElement(dtype); + const memoryOffset = this.wasm._malloc(numBytes); + this.dataIdMap.set(dataId, { id, memoryOffset, shape, dtype }); + this.wasm.tfjs.registerTensor(id, size, memoryOffset); + if (values != null) { + this.wasm.HEAPU8.set(new Uint8Array(values.buffer, values.byteOffset, numBytes), memoryOffset); + } + } + async read(dataId) { + return this.readSync(dataId); + } + readSync(dataId) { + const { memoryOffset, dtype, shape, stringBytes } = this.dataIdMap.get(dataId); + if (dtype === 'string') { + return stringBytes; + } + const bytes = this.wasm.HEAPU8.slice(memoryOffset, memoryOffset + tfjsCore.util.sizeFromShape(shape) * tfjsCore.util.bytesPerElement(dtype)); + return typedArrayFromBuffer(bytes.buffer, dtype); + } + disposeData(dataId) { + const data = this.dataIdMap.get(dataId); + this.wasm._free(data.memoryOffset); + this.wasm.tfjs.disposeData(data.id); + this.dataIdMap.delete(dataId); + } + floatPrecision() { + return 32; + } + // Returns the memory offset of a tensor. Useful for debugging and unit + // testing. + getMemoryOffset(dataId) { + return this.dataIdMap.get(dataId).memoryOffset; + } + dispose() { + this.wasm.tfjs.dispose(); + this.wasm = null; + } + memory() { + return { unreliable: false }; + } + /** + * Make a tensor info for the output of an op. If `memoryOffset` is not + * present, this method allocates memory on the WASM heap. If `memoryOffset` + * is present, the memory was allocated elsewhere (in c++) and we just record + * the pointer where that memory lives. + */ + makeOutput(shape, dtype, memoryOffset) { + let dataId; + if (memoryOffset == null) { + dataId = this.write(null /* values */, shape, dtype); + } + else { + dataId = {}; + const id = this.dataIdNextNumber++; + this.dataIdMap.set(dataId, { id, memoryOffset, shape, dtype }); + const size = tfjsCore.util.sizeFromShape(shape); + this.wasm.tfjs.registerTensor(id, size, memoryOffset); + } + return { dataId, shape, dtype }; + } + typedArrayFromHeap({ shape, dtype, dataId }) { + const buffer = this.wasm.HEAPU8.buffer; + const { memoryOffset } = this.dataIdMap.get(dataId); + const size = tfjsCore.util.sizeFromShape(shape); + switch (dtype) { + case 'float32': + return new Float32Array(buffer, memoryOffset, size); + case 'int32': + return new Int32Array(buffer, memoryOffset, size); + case 'bool': + return new Uint8Array(buffer, memoryOffset, size); + default: + throw new Error(`Uknown dtype ${dtype}`); + } + } + } + tfjsCore.registerBackend('wasm', async () => { + const { wasm } = await init(); + return new BackendWasm(wasm); + }, WASM_PRIORITY); + function createInstantiateWasmFunc(path) { + // tslint:disable-next-line:no-any + return (imports, callback) => { + tfjsCore.util.fetch(path, { credentials: 'same-origin' }).then((response) => { + if (!response['ok']) { + imports.env.a(`failed to load wasm binary file at '${path}'`); + } + response.arrayBuffer().then(binary => { + WebAssembly.instantiate(binary, imports).then(output => { + callback(output.instance); + }); + }); + }); + return {}; + }; + } + /** + * Initializes the wasm module and creates the js <--> wasm bridge. + * + * NOTE: We wrap the wasm module in a object with property 'wasm' instead of + * returning Promise to avoid freezing Chrome (last tested + * in Chrome 76). + */ + async function init() { + const simdSupported = await tfjsCore.env().getAsync('WASM_HAS_SIMD_SUPPORT'); + return new Promise((resolve, reject) => { + const factoryConfig = {}; + factoryConfig.locateFile = (path, prefix) => { + if (path.endsWith('.wasm')) { + if (wasmPath != null) { + return wasmPath; + } + if (simdSupported) { + return prefix + 'tfjs-backend-wasm-simd.wasm'; + } + return prefix + 'tfjs-backend-wasm.wasm'; + } + return prefix + path; + }; + if (wasmPath != null) { + // use wasm instantiateWasm override when system fetch is not available. + // For detail references + // https://github.com/emscripten-core/emscripten/blob/2bca083cbbd5a4133db61fbd74d04f7feecfa907/tests/manual_wasm_instantiate.html#L170 + if (customFetch) { + factoryConfig.instantiateWasm = createInstantiateWasmFunc(wasmPath); + } + } + const wasm = tfjsBackendWasm(factoryConfig); + const voidReturnType = null; + // Using the tfjs namespace to avoid conflict with emscripten's API. + wasm.tfjs = { + init: wasm.cwrap('init', null, []), + registerTensor: wasm.cwrap('register_tensor', null, [ + 'number', + 'number', + 'number', + ]), + disposeData: wasm.cwrap('dispose_data', voidReturnType, ['number']), + dispose: wasm.cwrap('dispose', voidReturnType, []), + }; + let initialized = false; + wasm.onRuntimeInitialized = () => { + initialized = true; + initAborted = false; + resolve({ wasm }); + }; + wasm.onAbort = () => { + if (initialized) { + // Emscripten already called console.warn so no need to double log. + return; + } + if (initAborted) { + // Emscripten calls `onAbort` twice, resulting in double error + // messages. + return; + } + initAborted = true; + const rejectMsg = 'Make sure the server can serve the `.wasm` file relative to the ' + + 'bundled js file. For more details see https://github.com/tensorflow/tfjs/blob/master/tfjs-backend-wasm/README.md#using-bundlers'; + reject({ message: rejectMsg }); + }; + }); + } + function typedArrayFromBuffer(buffer, dtype) { + switch (dtype) { + case 'float32': + return new Float32Array(buffer); + case 'int32': + return new Int32Array(buffer); + case 'bool': + return new Uint8Array(buffer); + default: + throw new Error(`Unknown dtype ${dtype}`); + } + } + let wasmPath = null; + let initAborted = false; + let customFetch = false; + /** + * Sets the path to the `.wasm` file which will be fetched when the wasm + * backend is initialized. See + * https://github.com/tensorflow/tfjs/blob/master/tfjs-backend-wasm/README.md#using-bundlers + * for more details. + * @param path wasm file path or url + * @param usePlatformFetch optional boolean to use platform fetch to download + * the wasm file, default to false. + */ + /** @doc {heading: 'Environment', namespace: 'wasm'} */ + function setWasmPath(path, usePlatformFetch = false) { + if (initAborted) { + throw new Error('The WASM backend was already initialized. Make sure you call ' + + '`setWasmPath()` before you call `tf.setBackend()` or `tf.ready()`'); + } + wasmPath = path; + customFetch = usePlatformFetch; + } + + /** @license See the LICENSE file. */ + // This code is auto-generated, do not modify this file! + const version = '0.0.0'; + + exports.BackendWasm = BackendWasm; + exports.setWasmPath = setWasmPath; + exports.version_wasm = version; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); +//# sourceMappingURL=tf-backend-wasm.js.map diff --git a/e2e/benchmarks/tfjs-backend-wasm-simd.wasm b/e2e/benchmarks/tfjs-backend-wasm-simd.wasm new file mode 100644 index 0000000000000000000000000000000000000000..5ce27d3d361dcb5fc43dfecf1b3cc340b86e828f GIT binary patch literal 214013 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� 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

  • h`6##Z4- zo<67Xw+GDpYEGB^D@F_`p~&H9;=hdMeqIp+ipr^4dK#;u2)0|UL^Z+$o%QjebJY&C z=Y$ZZGaSntc_P(gST|WhO5rmat3oK8l#hDrYd*P)-#}~*u17~RCGITOHp-D~Ta8A| zDmZ!?&7P=&esO7Ppdip?9pXTW6xPPFYp!TtrR?`6ppZ5rRr zHXIvfOJ@5?w$?plZ;dlzt{$<^gM=SBOu$=jjH5TO^-?Nc2FsbDu?)t&r*2UQEu@VFGBaaIaplC7n4&o|Fa?Z{GSNYcgii_bj~rwqDm~FY~JHigD49Va{pPT zy8LeUMnqE4ObpFafZTx|--u*)o4fnQMn>pv=y%^!bl#p?_!BVgiW(xC!g@S|NEVv5pf|uYe_zR&zxF8XB3VVbE;ec>dI3c79=Y>omN5~V3 zgzLh6K}z_4)pxzv*T3t$Tjc$(dZ&u~|E~KLk^Xo6?}|JpCm+{!;?aG8hqtSWuXuCo zw#GM@An`cBH$W7N@5JI%F>+FIq9?G3ed0x4_x@ru#fV7V1)_(-8xebnp@_P=u&BQw R1}ncR3J+By*CSVN{@+HkvWox! literal 0 HcmV?d00001 diff --git a/e2e/benchmarks/tfjs-backend-wasm.wasm b/e2e/benchmarks/tfjs-backend-wasm.wasm new file mode 100644 index 0000000000000000000000000000000000000000..2a371e8ad5b83a38fd0c51deb1402945b921bdfb GIT binary patch literal 154589 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

    {$l7_JtSLg2; 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 literal 0 HcmV?d00001 diff --git a/tfjs-backend-wasm/src/cc/BUILD b/tfjs-backend-wasm/src/cc/BUILD index 26124198cd4..e3a67442724 100644 --- a/tfjs-backend-wasm/src/cc/BUILD +++ b/tfjs-backend-wasm/src/cc/BUILD @@ -21,7 +21,6 @@ cc_binary( "-s MODULARIZE=1", "-s EXPORT_NAME=WasmBackendModule", "-s MALLOC=emmalloc", - "-s STANDALONE_WASM=1", ], deps = [ ":all_kernels", From 5ab0abbb58fd1bb0bd358870d81df1c3818d079d Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Fri, 31 Jul 2020 13:29:32 -0400 Subject: [PATCH 35/70] rm --- e2e/benchmarks/tf-backend-wasm.js | 3627 -------------------- e2e/benchmarks/tfjs-backend-wasm-simd.wasm | Bin 214013 -> 0 bytes e2e/benchmarks/tfjs-backend-wasm.wasm | Bin 154589 -> 0 bytes 3 files changed, 3627 deletions(-) delete mode 100644 e2e/benchmarks/tf-backend-wasm.js delete mode 100644 e2e/benchmarks/tfjs-backend-wasm-simd.wasm delete mode 100644 e2e/benchmarks/tfjs-backend-wasm.wasm diff --git a/e2e/benchmarks/tf-backend-wasm.js b/e2e/benchmarks/tf-backend-wasm.js deleted file mode 100644 index 6143a807553..00000000000 --- a/e2e/benchmarks/tf-backend-wasm.js +++ /dev/null @@ -1,3627 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tensorflow/tfjs-core'), require('path'), require('fs')) : - typeof define === 'function' && define.amd ? define(['exports', '@tensorflow/tfjs-core', 'path', 'fs'], factory) : - (global = global || self, factory((global.tf = global.tf || {}, global.tf.wasm = global.tf.wasm || {}), global.tf, global.path, global.fs)); -}(this, (function (exports, tfjsCore, path, fs) { 'use strict'; - - path = path && path.hasOwnProperty('default') ? path['default'] : path; - fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // This enum must align with the enum defined in cc/backend.h. - var CppDType; - (function (CppDType) { - CppDType[CppDType["float32"] = 0] = "float32"; - CppDType[CppDType["int32"] = 1] = "int32"; - CppDType[CppDType["bool"] = 2] = "bool"; - CppDType[CppDType["string"] = 3] = "string"; - CppDType[CppDType["complex64"] = 4] = "complex64"; - })(CppDType || (CppDType = {})); - // Must match enum in cc/fusable_activations.h. - var FusableActivation; - (function (FusableActivation) { - FusableActivation[FusableActivation["linear"] = 0] = "linear"; - FusableActivation[FusableActivation["relu"] = 1] = "relu"; - FusableActivation[FusableActivation["relu6"] = 2] = "relu6"; - FusableActivation[FusableActivation["prelu"] = 3] = "prelu"; - })(FusableActivation || (FusableActivation = {})); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFusedMatMul; - function setup(backend) { - wasmFusedMatMul = backend.wasm.cwrap(tfjsCore._FusedMatMul, null /* void */, [ - 'number', - 'array', - 'number', - 'number', - 'array', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number' // out_id - ]); - } - function fusedBatchMatMul(args) { - const { inputs, backend, attrs } = args; - const { a, b, bias, preluActivationWeights } = inputs; - if (a.dtype !== 'float32' || b.dtype !== 'float32') { - throw new Error(`_FusedMatMul for non non-float32 tensors not yet supported.`); - } - const { transposeA, transposeB, activation } = attrs; - const aId = backend.dataIdMap.get(a.dataId).id; - const bId = backend.dataIdMap.get(b.dataId).id; - let biasId = 0; - if (bias != null) { - const biasData = backend.dataIdMap.get(bias.dataId); - if (biasData.shape.length !== 1) { - throw new Error(`_FusedMatMul only supports rank-1 bias but got ` + - `rank ${biasData.shape.length}.`); - } - biasId = biasData.id; - } - const preluActivationWeightsId = preluActivationWeights == null ? - 0 : - backend.dataIdMap.get(preluActivationWeights.dataId).id; - const fusedActivation = FusableActivation[activation]; - if (fusedActivation == null) { - throw new Error(`${activation} activation not yet supported for FusedConv2D ` + - `in the wasm backend.`); - } - const leftDim = transposeA ? a.shape[2] : a.shape[1]; - const rightDim = transposeB ? b.shape[1] : b.shape[2]; - const batchDim = a.shape[0]; - const out = backend.makeOutput([batchDim, leftDim, rightDim], a.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); - const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); - wasmFusedMatMul(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, transposeA, transposeB, fusedActivation, biasId, preluActivationWeightsId, outId); - return out; - } - const fusedMatMulConfig = { - kernelName: tfjsCore._FusedMatMul, - backendName: 'wasm', - setupFunc: setup, - kernelFunc: fusedBatchMatMul - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function createUnaryKernelConfig(kernelName) { - let wasmFunc; - function setupFunc(backend) { - wasmFunc = - backend.wasm.cwrap(kernelName, null /* void */, ['number', 'number']); - } - function kernelFunc(args) { - const { backend, inputs: { x } } = args; - const xId = backend.dataIdMap.get(x.dataId).id; - const out = backend.makeOutput(x.shape, x.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(out.shape) === 0) { - return out; - } - wasmFunc(xId, outId); - return out; - } - return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const absConfig = createUnaryKernelConfig(tfjsCore.Abs); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function createBinaryKernelConfig(kernelName, supportsFullBroadcast, dtype) { - let wasmFunc; - function setupFunc(backend) { - wasmFunc = backend.wasm.cwrap(kernelName, null /* void */, [ - 'number', - 'array', - 'number', - 'number', - 'array', - 'number', - 'number', - 'number' // out_id - ]); - } - function kernelFunc(args) { - const { backend, inputs } = args; - const { a, b } = inputs; - const aId = backend.dataIdMap.get(a.dataId).id; - const bId = backend.dataIdMap.get(b.dataId).id; - const outputType = dtype != null ? dtype : a.dtype; - const newShape = tfjsCore.backend_util.assertAndGetBroadcastShape(a.shape, b.shape); - const out = backend.makeOutput(newShape, outputType); - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(newShape) === 0) { - return out; - } - const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); - const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); - const outId = backend.dataIdMap.get(out.dataId).id; - const kernelFunc = () => wasmFunc(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, CppDType[a.dtype], outId); - // Currently only some float operations support full broadcast. - if (supportsFullBroadcast && a.dtype === 'float32') { - kernelFunc(); - return out; - } - const aBroadcastDims = tfjsCore.backend_util.getBroadcastDims(a.shape, newShape); - const bBroadcastDims = tfjsCore.backend_util.getBroadcastDims(b.shape, newShape); - const loopsOverAllOfA = aBroadcastDims.every((v, i) => v === i); - const loopsOverAllOfB = bBroadcastDims.every((v, i) => v === i); - if (loopsOverAllOfA && loopsOverAllOfB) { - kernelFunc(); - return out; - } - else { - throw new Error(`Broadcasting along outer dims is not yet ` + - `supported for ${a.dtype} ${kernelName}.`); - } - } - return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast = true; - const addConfig = createBinaryKernelConfig(tfjsCore.Add, supportsFullBroadcast); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc; - function setupFunc(backend) { - wasmFunc = backend.wasm.cwrap(tfjsCore.AddN, null /* void */, [ - 'array', - 'number', - 'number', - 'number', - ]); - } - function addn(args) { - const { inputs, backend } = args; - const out = backend.makeOutput(inputs[0].shape, inputs[0].dtype); - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(out.shape) === 0) { - return out; - } - const inputIds = inputs.map(x => backend.dataIdMap.get(x.dataId).id); - const inputIdsBytes = new Uint8Array(new Int32Array(inputIds).buffer); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmFunc(inputIdsBytes, inputIds.length, CppDType[out.dtype], outId); - return out; - } - const addNConfig = { - kernelName: tfjsCore.AddN, - backendName: 'wasm', - setupFunc, - kernelFunc: addn, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function identity(args) { - const { inputs: { x }, backend } = args; - const out = backend.makeOutput(x.shape, x.dtype); - const inVals = backend.typedArrayFromHeap(x); - const outVals = backend.typedArrayFromHeap(out); - outVals.set(inVals); - return out; - } - const identityConfig = { - kernelName: tfjsCore.Identity, - backendName: 'wasm', - kernelFunc: identity, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmTranspose; - function setup$1(backend) { - wasmTranspose = backend.wasm.cwrap(tfjsCore.Transpose, null /* void */, [ - 'number', - 'array', - 'number', - 'number', - 'number', - 'array', - 'number', - ]); - } - function transpose(args) { - const { inputs, backend, attrs } = args; - // Reduce any dimensions with size one. Lower-rank transpose kernel performs - // better due to simpler memory access pattern. - const [reducedShape, perm] = removeOneSizeDims(inputs.x.shape, attrs.perm); - let permIsNoOp = true; - for (let i = 0; i < perm.length; i++) { - if (perm[i] !== i) { - permIsNoOp = false; - } - } - const outShape = computeOutShape(inputs.x.shape, attrs.perm); - const x = { - dataId: inputs.x.dataId, - shape: reducedShape, - dtype: inputs.x.dtype - }; - if (permIsNoOp) { - const cloned = identity({ inputs, backend }); - cloned.shape = outShape; - return cloned; - } - const out = backend.makeOutput(outShape, x.dtype); - const xId = backend.dataIdMap.get(x.dataId).id; - const outId = backend.dataIdMap.get(out.dataId).id; - const permBytes = new Uint8Array(new Int32Array(perm).buffer); - const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); - wasmTranspose(xId, xShapeBytes, x.shape.length, CppDType[x.dtype], outId, permBytes, perm.length); - return out; - } - function computeOutShape(inShape, perm) { - const outShape = new Array(inShape.length); - for (let i = 0; i < outShape.length; i++) { - outShape[i] = inShape[perm[i]]; - } - return outShape; - } - function removeOneSizeDims(shape, perm) { - const newShape = []; - const newPerm = []; - for (let i = 0; i < shape.length; ++i) { - if (shape[i] !== 1) { - newShape.push(shape[i]); - } - if (shape[perm[i]] !== 1) { - newPerm.push(perm[i]); - } - } - for (let i = 0; i < newPerm.length; ++i) { - let minValIdx = -1; - for (let j = 0; j < newPerm.length; ++j) { - if (newPerm[j] >= i && - (minValIdx === -1 || newPerm[minValIdx] > newPerm[j])) { - minValIdx = j; - } - } - newPerm[minValIdx] = i; - } - return [newShape, newPerm]; - } - const transposeConfig = { - kernelName: tfjsCore.Transpose, - backendName: 'wasm', - kernelFunc: transpose, - setupFunc: setup$1, - }; - - /** - * @license - * Copyright 2020 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Compute permutation axes and do a transpose if necessary. - * - * Used by reduction ops. - * @param x input TensorInfo - * @param axis reduction axes - * @param backend wasm backend instance - */ - function permuteAxesAndTranspose(x, axis, backend) { - const xShape = x.shape; - const xRank = x.shape.length; - const originalAxes = tfjsCore.util.parseAxisParam(axis, xShape); - let axes = originalAxes; - const permutedAxes = tfjsCore.backend_util.getAxesPermutation(axes, xRank); - let xTransposed = null; - let inputWasTransposed = false; - if (permutedAxes != null) { - const newShape = new Array(xRank); - for (let i = 0; i < newShape.length; i++) { - newShape[i] = xShape[permutedAxes[i]]; - } - axes = tfjsCore.backend_util.getInnerMostAxes(axes.length, xRank); - xTransposed = - transpose({ inputs: { x }, attrs: { perm: permutedAxes }, backend }); - const xId = backend.dataIdMap.get(x.dataId).id; - const transposedId = backend.dataIdMap.get(xTransposed.dataId).id; - if (transposedId !== xId) { - inputWasTransposed = true; - } - } - return { transposed: xTransposed, originalAxes, axes, inputWasTransposed }; - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$1; - function setup$2(backend) { - wasmFunc$1 = backend.wasm.cwrap(tfjsCore.ArgMax, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number' // out_id - ]); - } - function argmax(args) { - const { backend, inputs, attrs } = args; - const { axis } = attrs; - const { x } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - let inputId = xId; - let input = x; - const { transposed, axes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); - if (inputWasTransposed) { - const transposedId = backend.dataIdMap.get(transposed.dataId).id; - if (transposedId !== xId) { - // transpose was not a no-op. We will need to dispose of this - // once we are done. - input = transposed; - inputId = transposedId; - } - } - const outShape = input.shape.slice(0, -1); - const out = backend.makeOutput(outShape, 'int32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const outerSize = tfjsCore.util.sizeFromShape(out.shape); - const innerSize = input.shape[axes[0]]; - wasmFunc$1(inputId, CppDType[input.dtype], outerSize, innerSize, outId); - if (inputWasTransposed) { - // dispose of the transposed tensor. - backend.disposeData(transposed.dataId); - } - return out; - } - const argMaxConfig = { - kernelName: tfjsCore.ArgMax, - backendName: 'wasm', - kernelFunc: argmax, - setupFunc: setup$2 - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmAvgPool; - function setup$3(backend) { - wasmAvgPool = backend.wasm.cwrap(tfjsCore.AvgPool, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function avgPool(args) { - const { inputs, attrs, backend } = args; - const x = inputs.x; - const xId = backend.dataIdMap.get(x.dataId).id; - const { filterSize, strides, pad, dimRoundingMode } = attrs; - const convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const channels = convInfo.inChannels; - if (convInfo.dataFormat !== 'channelsLast') { - throw new Error(`wasm backend does not support dataFormat:'` + - `${convInfo.dataFormat}'. Please use 'channelsLast'.`); - } - if (convInfo.dilationWidth !== 1 || convInfo.dilationHeight !== 1) { - throw new Error(`was backend only supports average pooling with dilation = [1, 1], ` + - `got [${convInfo.dilationHeight}, ${convInfo.dilationWidth}].`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmAvgPool(xId, x.shape[0], x.shape[1], x.shape[2], filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, strideHeight, strideWidth, channels, outId); - return out; - } - const avgPoolConfig = { - kernelName: tfjsCore.AvgPool, - backendName: 'wasm', - setupFunc: setup$3, - kernelFunc: avgPool - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmBatchMatMul; - function setup$4(backend) { - wasmBatchMatMul = backend.wasm.cwrap(tfjsCore.BatchMatMul, null /* void */, [ - 'number', - 'array', - 'number', - 'number', - 'array', - 'number', - 'number', - 'number', - 'number' // out_id - ]); - } - function batchMatMul(args) { - const { inputs, backend, attrs } = args; - const { a, b } = inputs; - if (a.dtype !== 'float32' || b.dtype !== 'float32') { - throw new Error(`BatchMatMul for non non-float32 tensors not yet supported.`); - } - const { transposeA, transposeB } = attrs; - const aId = backend.dataIdMap.get(a.dataId).id; - const bId = backend.dataIdMap.get(b.dataId).id; - const leftDim = transposeA ? a.shape[2] : a.shape[1]; - const rightDim = transposeB ? b.shape[1] : b.shape[2]; - const batchDim = a.shape[0]; - const out = backend.makeOutput([batchDim, leftDim, rightDim], a.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); - const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); - wasmBatchMatMul(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, transposeA, transposeB, outId); - return out; - } - const batchMatMulConfig = { - kernelName: tfjsCore.BatchMatMul, - backendName: 'wasm', - setupFunc: setup$4, - kernelFunc: batchMatMul - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function cast(args) { - const { inputs: { x }, attrs: { dtype }, backend } = args; - const out = backend.makeOutput(x.shape, dtype); - const inVals = backend.typedArrayFromHeap(x); - const outVals = backend.typedArrayFromHeap(out); - outVals.set(inVals); - return out; - } - const castConfig = { - kernelName: tfjsCore.Cast, - backendName: 'wasm', - kernelFunc: cast, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmClip; - function setup$5(backend) { - wasmClip = backend.wasm.cwrap(tfjsCore.ClipByValue, null /* void */, [ - 'number', - 'number', - 'number', - 'number' // out_id - ]); - } - function clip(args) { - const { inputs, backend, attrs } = args; - const { x } = inputs; - const { clipValueMin, clipValueMax } = attrs; - const xId = backend.dataIdMap.get(x.dataId).id; - const out = backend.makeOutput(x.shape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmClip(xId, clipValueMin, clipValueMax, outId); - return out; - } - const clipByValueConfig = { - kernelName: tfjsCore.ClipByValue, - backendName: 'wasm', - setupFunc: setup$5, - kernelFunc: clip - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function concat(args) { - const { inputs, backend } = args; - const axis = tfjsCore.util.parseAxisParam(args.attrs.axis, inputs[0].shape)[0]; - const outShape = tfjsCore.backend_util.computeOutShape(inputs.map(t => t.shape), axis); - const out = backend.makeOutput(outShape, inputs[0].dtype); - const batchDim = tfjsCore.util.sizeFromShape(inputs[0].shape.slice(0, axis)); - let sumInnerDims = 0; - const innerDims = inputs.map(input => { - const innerDim = tfjsCore.util.sizeFromShape(input.shape.slice(axis)); - sumInnerDims += innerDim; - return innerDim; - }); - const inVals = inputs.map(input => backend.typedArrayFromHeap(input)); - const outVals = backend.typedArrayFromHeap(out); - for (let b = 0; b < batchDim; b++) { - let outOffset = b * sumInnerDims; - for (let i = 0; i < inVals.length; i++) { - const innerDim = innerDims[i]; - const inOffset = b * innerDim; - const vals = inVals[i].subarray(inOffset, inOffset + innerDim); - outVals.set(vals, outOffset); - outOffset += innerDim; - } - } - return out; - } - const concatConfig = { - kernelName: tfjsCore.Concat, - backendName: 'wasm', - kernelFunc: concat, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmConv2d; - function setup$6(backend) { - wasmConv2d = backend.wasm.cwrap(tfjsCore.Conv2D, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function conv2d(args) { - const { inputs, attrs, backend } = args; - const { x, filter } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - const filterId = backend.dataIdMap.get(filter.dataId).id; - const { strides, dilations, pad, dimRoundingMode, dataFormat } = attrs; - const $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat); - const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const dilationHeight = convInfo.dilationHeight; - const dilationWidth = convInfo.dilationWidth; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const inputChannels = convInfo.inChannels; - const outputChannels = convInfo.outChannels; - const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; - if (convInfo.dataFormat !== 'channelsLast') { - throw new Error(`wasm backend Conv2D does not support dataFormat:'` + - `${convInfo.dataFormat}'. Please use 'channelsLast'.`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmConv2d(xId, x.shape[0], x.shape[1], x.shape[2], filterId, filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); - return out; - } - const conv2DConfig = { - kernelName: tfjsCore.Conv2D, - backendName: 'wasm', - setupFunc: setup$6, - kernelFunc: conv2d - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmConv2DBackpropInput; - function setup$7(backend) { - wasmConv2DBackpropInput = backend.wasm.cwrap(tfjsCore.Conv2DBackpropInput, null, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function conv2DBackpropInput(args) { - const { backend, inputs, attrs } = args; - const { dy, filter } = inputs; - const { strides, pad, dataFormat, dimRoundingMode, inputShape } = attrs; - const dilations = 1; - const $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat); - const convInfo = tfjsCore.backend_util.computeConv2DInfo(inputShape, filter.shape, strides, dilations, pad, dimRoundingMode, false /* depthwise */, $dataFormat); - const { batchSize, filterHeight, filterWidth, inChannels, inHeight, inWidth, outChannels, outHeight, outWidth, strideHeight, strideWidth } = convInfo; - const topPad = filterHeight - 1 - convInfo.padInfo.top; - const leftPad = filterWidth - 1 - convInfo.padInfo.left; - const isChannelsLast = convInfo.dataFormat === 'channelsLast'; - const dxStrides = tfjsCore.util.computeStrides(convInfo.inShape); - const dyStrides = tfjsCore.util.computeStrides(dy.shape); - const [fltS0, fltS1, fltS2] = tfjsCore.util.computeStrides(filter.shape); - const xBatchStride = dxStrides[0]; - const xRowStride = isChannelsLast ? dxStrides[1] : dxStrides[2]; - const xColStride = isChannelsLast ? dxStrides[2] : 1; - const xChannelStride = isChannelsLast ? 1 : dxStrides[1]; - const yBatchStride = dyStrides[0]; - const yRowStride = isChannelsLast ? dyStrides[1] : dyStrides[2]; - const yColStride = isChannelsLast ? dyStrides[2] : 1; - const yChannelStride = isChannelsLast ? 1 : dyStrides[1]; - const out = backend.makeOutput(convInfo.inShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const dyId = backend.dataIdMap.get(dy.dataId).id; - const filterId = backend.dataIdMap.get(filter.dataId).id; - wasmConv2DBackpropInput(dyId, filterId, batchSize, filterHeight, filterWidth, inHeight, inWidth, inChannels, outHeight, outWidth, outChannels, strideHeight, strideWidth, topPad, leftPad, fltS0, fltS1, fltS2, xBatchStride, xRowStride, xColStride, xChannelStride, yBatchStride, yRowStride, yColStride, yChannelStride, outId); - return out; - } - const conv2DBackpropInputConfig = { - kernelName: tfjsCore.Conv2DBackpropInput, - backendName: 'wasm', - setupFunc: setup$7, - kernelFunc: conv2DBackpropInput - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const cosConfig = createUnaryKernelConfig(tfjsCore.Cos); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // Must match enum in CropAndResize.cc - var InterpolationMethod; - (function (InterpolationMethod) { - InterpolationMethod[InterpolationMethod["bilinear"] = 0] = "bilinear"; - InterpolationMethod[InterpolationMethod["nearest"] = 1] = "nearest"; - })(InterpolationMethod || (InterpolationMethod = {})); - let wasmCropAndResize; - function setup$8(backend) { - wasmCropAndResize = backend.wasm.cwrap(tfjsCore.CropAndResize, null /*void*/, [ - 'number', - 'number', - 'number', - 'number', - 'array', - 'number', - 'number', - 'number', - 'number', - 'number' // out id - ]); - } - function cropAndResize(args) { - const { backend, inputs, attrs } = args; - const { method, extrapolationValue, cropSize } = attrs; - const { image, boxes, boxInd } = inputs; - const numBoxes = boxes.shape[0]; - const [cropHeight, cropWidth] = cropSize; - const outShape = [numBoxes, cropHeight, cropWidth, image.shape[3]]; - let imagesData = backend.dataIdMap.get(image.dataId); - let castedData; - if (image.dtype !== 'float32') { - castedData = cast({ backend, inputs: { x: image }, attrs: { dtype: 'float32' } }); - imagesData = backend.dataIdMap.get(castedData.dataId); - } - const imagesId = imagesData.id; - const boxesId = backend.dataIdMap.get(boxes.dataId).id; - const boxIndId = backend.dataIdMap.get(boxInd.dataId).id; - const out = backend.makeOutput(outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const imagesShapeBytes = new Uint8Array(new Int32Array(image.shape).buffer); - wasmCropAndResize(imagesId, boxesId, boxIndId, numBoxes, imagesShapeBytes, cropHeight, cropWidth, InterpolationMethod[method], extrapolationValue, outId); - if (castedData != null) { - backend.disposeData(castedData.dataId); - } - return out; - } - const cropAndResizeConfig = { - kernelName: tfjsCore.CropAndResize, - backendName: 'wasm', - setupFunc: setup$8, - kernelFunc: cropAndResize - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmDepthwiseConv2d; - function setup$9(backend) { - wasmDepthwiseConv2d = - backend.wasm.cwrap(tfjsCore.DepthwiseConv2dNative, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function depthwiseConv2d(args) { - const { inputs, attrs, backend } = args; - const { x, filter } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - const filterId = backend.dataIdMap.get(filter.dataId).id; - const { strides, dilations, pad, dimRoundingMode } = attrs; - const $dilations = dilations == null ? [1, 1] : dilations; - const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, $dilations, pad, dimRoundingMode, true /* depthwise */); - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const dilationHeight = convInfo.dilationHeight; - const dilationWidth = convInfo.dilationWidth; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const inputChannels = convInfo.inChannels; - const outputChannels = convInfo.outChannels; - const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; - if (convInfo.dataFormat !== 'channelsLast') { - throw new Error(`wasm backend DepthwiseConv2dNative does not support dataFormat:'` + - `${convInfo.dataFormat}'. Please use 'channelsLast'.`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmDepthwiseConv2d(xId, x.shape[0], x.shape[1], x.shape[2], filterId, filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); - return out; - } - const depthwiseConv2DNativeConfig = { - kernelName: tfjsCore.DepthwiseConv2dNative, - backendName: 'wasm', - setupFunc: setup$9, - kernelFunc: depthwiseConv2d - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$1 = true; - const divConfig = createBinaryKernelConfig(tfjsCore.Div, supportsFullBroadcast$1); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$2 = false; - const equalConfig = createBinaryKernelConfig(tfjsCore.Equal, supportsFullBroadcast$2, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const expConfig = createUnaryKernelConfig(tfjsCore.Exp); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function fill(args) { - const { attrs: { shape, value, dtype }, backend } = args; - const out = backend.makeOutput(shape, dtype); - const outVals = backend.typedArrayFromHeap(out); - outVals.fill(value); - return out; - } - const fillConfig = { - kernelName: tfjsCore.Fill, - backendName: 'wasm', - kernelFunc: fill, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$3 = false; - const floorDivConfig = createBinaryKernelConfig(tfjsCore.FloorDiv, supportsFullBroadcast$3); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmBatchNorm; - function setup$a(backend) { - wasmBatchNorm = backend.wasm.cwrap(tfjsCore.FusedBatchNorm, null /* void */, ['number', 'number', 'number', 'number', 'number', 'number', 'number']); - } - function fusedBatchNorm(args) { - const { backend, inputs, attrs } = args; - const { varianceEpsilon } = attrs; - const { x, mean, variance, offset, scale } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - const meanId = backend.dataIdMap.get(mean.dataId).id; - const varianceId = backend.dataIdMap.get(variance.dataId).id; - const offsetId = offset != null ? backend.dataIdMap.get(offset.dataId).id : 0; - const scaleId = scale != null ? backend.dataIdMap.get(scale.dataId).id : 0; - const out = backend.makeOutput(x.shape, x.dtype); - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(x.shape) === 0) { - return out; - } - const outId = backend.dataIdMap.get(out.dataId).id; - wasmBatchNorm(xId, meanId, varianceId, offsetId, scaleId, varianceEpsilon, outId); - return out; - } - const fusedBatchNormConfig = { - kernelName: tfjsCore.FusedBatchNorm, - backendName: 'wasm', - setupFunc: setup$a, - kernelFunc: fusedBatchNorm - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFusedConv2d; - function setup$b(backend) { - wasmFusedConv2d = backend.wasm.cwrap(tfjsCore.FusedConv2D, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function fusedConv2d(args) { - const { inputs, attrs, backend } = args; - const { x, filter, bias, preluActivationWeights } = inputs; - const { strides, pad, dilations, dataFormat, dimRoundingMode, activation } = attrs; - const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode); - const fusedActivation = FusableActivation[activation]; - if (fusedActivation == null) { - throw new Error(`${activation} activation not yet supported for FusedConv2D ` + - `in the wasm backend.`); - } - const xId = backend.dataIdMap.get(x.dataId).id; - const filterId = backend.dataIdMap.get(filter.dataId).id; - const outputChannels = convInfo.outChannels; - let biasId = 0; - if (bias != null) { - const biasData = backend.dataIdMap.get(bias.dataId); - if (biasData.shape.length !== 1) { - throw new Error(`FusedConv2D only supports rank-1 bias but got ` + - `rank ${biasData.shape.length}.`); - } - if (biasData.shape[0] !== outputChannels) { - throw new Error(`FusedConv2D bias shape (${biasData.shape}) does not ` + - `match the number of output channels (${outputChannels})`); - } - biasId = biasData.id; - } - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const dilationHeight = convInfo.dilationHeight; - const dilationWidth = convInfo.dilationWidth; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const inputChannels = convInfo.inChannels; - const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; - const batchSize = convInfo.batchSize; - const inHeight = convInfo.inHeight; - const inWidth = convInfo.inWidth; - if (dataFormat !== 'NHWC') { - throw new Error(`wasm backend FusedConv2D does not support dataFormat:'` + - `${dataFormat}'. Please use 'NHWC'.`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const preluActivationWeightsId = preluActivationWeights == null ? - 0 : - backend.dataIdMap.get(preluActivationWeights.dataId).id; - wasmFusedConv2d(xId, batchSize, inHeight, inWidth, filterId, filterHeight, filterWidth, biasId, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, fusedActivation, preluActivationWeightsId, outId); - return out; - } - const fusedConv2DConfig = { - kernelName: tfjsCore.FusedConv2D, - backendName: 'wasm', - setupFunc: setup$b, - kernelFunc: fusedConv2d - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFusedDepthwiseConv2d; - function setup$c(backend) { - wasmFusedDepthwiseConv2d = - backend.wasm.cwrap(tfjsCore.FusedDepthwiseConv2D, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function fusedDepthwiseConv2d(args) { - const { inputs, attrs, backend } = args; - const { x, filter, bias, preluActivationWeights } = inputs; - const { strides, pad, dilations, dataFormat, dimRoundingMode, activation } = attrs; - const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, true /* depthwise */); - const fusedActivation = FusableActivation[activation]; - if (fusedActivation == null) { - throw new Error(`${activation} activation not yet supported for FusedDepthwiseConv2D ` + - `in the wasm backend.`); - } - const xId = backend.dataIdMap.get(x.dataId).id; - const filterId = backend.dataIdMap.get(filter.dataId).id; - const outputChannels = convInfo.outChannels; - let biasId = 0; - if (bias != null) { - const biasData = backend.dataIdMap.get(bias.dataId); - if (biasData.shape.length !== 1) { - throw new Error(`FusedDepthwiseConv2D only supports rank-1 bias but got ` + - `rank ${biasData.shape.length}.`); - } - if (biasData.shape[0] !== outputChannels) { - throw new Error(`FusedDepthwiseConv2D bias shape (${biasData.shape}) does not ` + - `match the number of output channels (${outputChannels})`); - } - biasId = biasData.id; - } - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const dilationHeight = convInfo.dilationHeight; - const dilationWidth = convInfo.dilationWidth; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const inputChannels = convInfo.inChannels; - const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; - const batchSize = convInfo.batchSize; - const inHeight = convInfo.inHeight; - const inWidth = convInfo.inWidth; - if (dataFormat !== 'NHWC') { - throw new Error(`wasm backend FusedDepthwiseConv2D does not support dataFormat:'` + - `${dataFormat}'. Please use 'NHWC'.`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const preluActivationWeightsId = preluActivationWeights == null ? - 0 : - backend.dataIdMap.get(preluActivationWeights.dataId).id; - wasmFusedDepthwiseConv2d(xId, batchSize, inHeight, inWidth, filterId, filterHeight, filterWidth, biasId, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, fusedActivation, preluActivationWeightsId, outId); - return out; - } - const fusedDepthwiseConv2DConfig = { - kernelName: tfjsCore.FusedDepthwiseConv2D, - backendName: 'wasm', - setupFunc: setup$c, - kernelFunc: fusedDepthwiseConv2d - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmGatherNd; - function setup$d(backend) { - wasmGatherNd = backend.wasm.cwrap(tfjsCore.GatherNd, null /*void*/, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'array', - 'number' // outId - ]); - } - function gatherNd(args) { - const { backend, inputs } = args; - const { params, indices } = inputs; - const [resultShape, numSlices, sliceSize, strides] = tfjsCore.gather_util.prepareAndValidate(params, indices); - const out = backend.makeOutput(resultShape, params.dtype); - if (numSlices === 0) { - return out; - } - const indicesShape = indices.shape; - const sliceRank = indicesShape[indicesShape.length - 1]; - const xData = backend.dataIdMap.get(params.dataId); - const xId = xData.id; - const indicesData = backend.dataIdMap.get(indices.dataId); - const indicesId = indicesData.id; - const stridesBytes = new Uint8Array(new Int32Array(strides).buffer); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmGatherNd(xId, CppDType[params.dtype], indicesId, numSlices, sliceRank, sliceSize, stridesBytes, outId); - return out; - } - const gatherNdConfig = { - kernelName: tfjsCore.GatherNd, - backendName: 'wasm', - setupFunc: setup$d, - kernelFunc: gatherNd - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmGather; - function setup$e(backend) { - wasmGather = backend.wasm.cwrap('Gather', null /*void*/, [ - 'number', - 'number', - 'array', - 'number', - 'number', - 'number', - 'array', - 'number' // outId - ]); - } - function gatherV2(args) { - const { backend, inputs, attrs } = args; - const { x, indices } = inputs; - const { axis } = attrs; - const newShape = x.shape.slice(); - newShape[axis] = tfjsCore.util.sizeFromShape(indices.shape); - const stridesSize = x.shape.length - 1; - const out = backend.makeOutput(newShape, x.dtype); - if (tfjsCore.util.sizeFromShape(x.shape) === 0) { - return out; - } - const xData = backend.dataIdMap.get(x.dataId); - const xId = xData.id; - const indicesData = backend.dataIdMap.get(indices.dataId); - const indicesId = indicesData.id; - const outId = backend.dataIdMap.get(out.dataId).id; - const xStridesBytes = new Uint8Array(new Int32Array(tfjsCore.util.computeStrides(x.shape)).buffer); - const outStridesBytes = new Uint8Array(new Int32Array(tfjsCore.util.computeStrides(newShape)).buffer); - wasmGather(xId, CppDType[x.dtype], xStridesBytes, stridesSize, indicesId, axis, outStridesBytes, outId); - // reshape - const parsedAxis = tfjsCore.util.parseAxisParam(axis, x.shape)[0]; - const shapeInfo = tfjsCore.backend_util.segment_util.collectGatherOpShapeInfo(x, indices, parsedAxis); - out.shape = shapeInfo.outputShape; - return out; - } - const gatherV2Config = { - kernelName: tfjsCore.GatherV2, - backendName: 'wasm', - setupFunc: setup$e, - kernelFunc: gatherV2 - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$4 = false; - const greaterConfig = createBinaryKernelConfig(tfjsCore.Greater, supportsFullBroadcast$4, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$5 = false; - const greaterEqualConfig = createBinaryKernelConfig(tfjsCore.GreaterEqual, supportsFullBroadcast$5, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$6 = false; - const lessConfig = createBinaryKernelConfig(tfjsCore.Less, supportsFullBroadcast$6, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$7 = false; - const lessEqualConfig = createBinaryKernelConfig(tfjsCore.LessEqual, supportsFullBroadcast$7, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const logConfig = createUnaryKernelConfig(tfjsCore.Log); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$8 = false; - const logicalAndConfig = createBinaryKernelConfig(tfjsCore.LogicalAnd, supportsFullBroadcast$8, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmMax; - function setup$f(backend) { - wasmMax = backend.wasm.cwrap(tfjsCore.Max, null /*void*/, ['number, number, number']); - } - function max(args) { - const { backend, inputs, attrs } = args; - const { reductionIndices: axis, keepDims } = attrs; - const { x } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - let inputId = xId; - let input = x; - const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); - if (inputWasTransposed) { - const transposedId = backend.dataIdMap.get(transposed.dataId).id; - input = transposed; - inputId = transposedId; - } - const inputRank = input.shape.length; - tfjsCore.backend_util.assertAxesAreInnerMostDims('max', axes, inputRank); - const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, axes); - const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); - const out = backend.makeOutput(outShape, x.dtype); - if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { - const outId = backend.dataIdMap.get(out.dataId).id; - wasmMax(inputId, reduceSize, outId); - } - if (inputWasTransposed) { - // dispose of the transposed tensor. - backend.disposeData(transposed.dataId); - } - if (keepDims) { - // reshape - const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); - out.shape = newShape; - } - return out; - } - const maxConfig = { - kernelName: tfjsCore.Max, - backendName: 'wasm', - setupFunc: setup$f, - kernelFunc: max - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$9 = false; - const maximumConfig = createBinaryKernelConfig(tfjsCore.Maximum, supportsFullBroadcast$9); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmMaxPool; - function setup$g(backend) { - wasmMaxPool = backend.wasm.cwrap(tfjsCore.MaxPool, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function maxPool(args) { - const { inputs, attrs, backend } = args; - const x = inputs.x; - const xId = backend.dataIdMap.get(x.dataId).id; - const { filterSize, strides, pad, dimRoundingMode } = attrs; - const convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const dilationHeight = convInfo.dilationHeight; - const dilationWidth = convInfo.dilationWidth; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const inputChannels = convInfo.inChannels; - const outputChannels = convInfo.outChannels; - if (convInfo.dataFormat !== 'channelsLast') { - throw new Error(`wasm backend does not support dataFormat:'` + - `${convInfo.dataFormat}'. Please use 'channelsLast'.`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmMaxPool(xId, x.shape[0], x.shape[1], x.shape[2], filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); - return out; - } - const maxPoolConfig = { - kernelName: tfjsCore.MaxPool, - backendName: 'wasm', - setupFunc: setup$g, - kernelFunc: maxPool - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmMin; - function setup$h(backend) { - wasmMin = backend.wasm.cwrap(tfjsCore.Min, null /*void*/, ['number, number, number']); - } - function min(args) { - const { backend, inputs, attrs } = args; - const { axis, keepDims } = attrs; - const { x } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - let inputId = xId; - let input = x; - const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); - if (inputWasTransposed) { - const transposedId = backend.dataIdMap.get(transposed.dataId).id; - if (transposedId !== xId) { - // transpose was not a no-op. We will need to dispose of this - // once we are done. - input = transposed; - inputId = transposedId; - } - } - const inputRank = input.shape.length; - tfjsCore.backend_util.assertAxesAreInnerMostDims('min', axes, inputRank); - const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, axes); - const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); - const out = backend.makeOutput(outShape, input.dtype); - if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { - const outId = backend.dataIdMap.get(out.dataId).id; - wasmMin(inputId, reduceSize, outId); - } - if (inputWasTransposed) { - // dispose of the transposed tensor. - backend.disposeData(transposed.dataId); - } - if (keepDims) { - // reshape - const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); - out.shape = newShape; - } - return out; - } - const minConfig = { - kernelName: tfjsCore.Min, - backendName: 'wasm', - setupFunc: setup$h, - kernelFunc: min - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$a = false; - const minimumConfig = createBinaryKernelConfig(tfjsCore.Minimum, supportsFullBroadcast$a); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$b = true; - const multiplyConfig = createBinaryKernelConfig(tfjsCore.Multiply, supportsFullBroadcast$b); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const negateConfig = createUnaryKernelConfig(tfjsCore.Negate); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Parse the result of the c++ method, which has the shape equivalent to - * `Result`. - */ - function parseResultStruct(backend, resOffset) { - const result = new Int32Array(backend.wasm.HEAPU8.buffer, resOffset, 4); - const pSelectedIndices = result[0]; - const selectedSize = result[1]; - const pSelectedScores = result[2]; - const pValidOutputs = result[3]; - // Since the result was allocated on the heap, we have to delete it. - backend.wasm._free(resOffset); - return { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs }; - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$2; - function setup$i(backend) { - wasmFunc$2 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV3, 'number', // Result* - [ - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function kernelFunc(args) { - const { backend, inputs, attrs } = args; - const { iouThreshold, maxOutputSize, scoreThreshold } = attrs; - const { boxes, scores } = inputs; - const boxesId = backend.dataIdMap.get(boxes.dataId).id; - const scoresId = backend.dataIdMap.get(scores.dataId).id; - const resOffset = wasmFunc$2(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold); - const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); - // Since we are not using scores for V3, we have to delete it from the heap. - backend.wasm._free(pSelectedScores); - backend.wasm._free(pValidOutputs); - const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); - return selectedIndicesTensor; - } - const nonMaxSuppressionV3Config = { - kernelName: tfjsCore.NonMaxSuppressionV3, - backendName: 'wasm', - setupFunc: setup$i, - kernelFunc: kernelFunc, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$3; - function setup$j(backend) { - wasmFunc$3 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV4, 'number', // Result* - [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'bool', - ]); - } - function nonMaxSuppressionV4(args) { - const { backend, inputs, attrs } = args; - const { iouThreshold, maxOutputSize, scoreThreshold, padToMaxOutputSize } = attrs; - const { boxes, scores } = inputs; - const boxesId = backend.dataIdMap.get(boxes.dataId).id; - const scoresId = backend.dataIdMap.get(scores.dataId).id; - const resOffset = wasmFunc$3(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize); - const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); - // Since we are not using scores for V4, we have to delete it from the heap. - backend.wasm._free(pSelectedScores); - const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); - const validOutputsTensor = backend.makeOutput([], 'int32', pValidOutputs); - return [selectedIndicesTensor, validOutputsTensor]; - } - const nonMaxSuppressionV4Config = { - kernelName: tfjsCore.NonMaxSuppressionV4, - backendName: 'wasm', - setupFunc: setup$j, - kernelFunc: nonMaxSuppressionV4, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$4; - function setup$k(backend) { - wasmFunc$4 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV5, 'number', // Result* - [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function kernelFunc$1(args) { - const { backend, inputs, attrs } = args; - const { iouThreshold, maxOutputSize, scoreThreshold, softNmsSigma } = attrs; - const { boxes, scores } = inputs; - const boxesId = backend.dataIdMap.get(boxes.dataId).id; - const scoresId = backend.dataIdMap.get(scores.dataId).id; - const resOffset = wasmFunc$4(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma); - const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); - // Since we are not using validOutputs for V5, we have to delete it from the - // heap. - backend.wasm._free(pValidOutputs); - const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); - const selectedScoresTensor = backend.makeOutput([selectedSize], 'float32', pSelectedScores); - return [selectedIndicesTensor, selectedScoresTensor]; - } - const nonMaxSuppressionV5Config = { - kernelName: tfjsCore.NonMaxSuppressionV5, - backendName: 'wasm', - setupFunc: setup$k, - kernelFunc: kernelFunc$1, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$c = false; - const notEqualConfig = createBinaryKernelConfig(tfjsCore.NotEqual, supportsFullBroadcast$c, 'bool'); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmOneHot; - function setup$l(backend) { - wasmOneHot = backend.wasm.cwrap(tfjsCore.OneHot, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number' // out_id - ]); - } - function oneHot(args) { - const { inputs, backend, attrs } = args; - const { indices } = inputs; - const { depth, onValue, offValue } = attrs; - const out = backend.makeOutput([...indices.shape, depth], 'int32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const indicesData = backend.dataIdMap.get(indices.dataId); - const indicesId = indicesData.id; - wasmOneHot(indicesId, depth, onValue, offValue, outId); - return out; - } - const oneHotConfig = { - kernelName: tfjsCore.OneHot, - backendName: 'wasm', - setupFunc: setup$l, - kernelFunc: oneHot, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function onesLike(args) { - const { inputs: { x }, backend } = args; - const out = backend.makeOutput(x.shape, x.dtype); - const outVals = backend.typedArrayFromHeap(out); - outVals.fill(1); - return out; - } - const onesLikeConfig = { - kernelName: tfjsCore.OnesLike, - backendName: 'wasm', - kernelFunc: onesLike, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmPadV2; - function setup$m(backend) { - wasmPadV2 = backend.wasm.cwrap(tfjsCore.PadV2, null /* void */, [ - 'number', - 'array', - 'number', - 'number', - 'array', - 'array', - 'number', - 'number', - ]); - } - function pad(args) { - const { inputs: { x }, backend, attrs: { paddings, constantValue } } = args; - const outShape = paddings.map((p, i) => p[0] /* beforePad */ + x.shape[i] + p[1] /* afterPad */); - const xId = backend.dataIdMap.get(x.dataId).id; - const out = backend.makeOutput(outShape, x.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); - const prePaddingsFlat = paddings.map(padTuple => padTuple[0]); - const postPaddingsFlat = paddings.map(padTuple => padTuple[1]); - const prePaddingsBytes = new Uint8Array(new Int32Array(prePaddingsFlat).buffer); - const postPaddingsBytes = new Uint8Array(new Int32Array(postPaddingsFlat).buffer); - wasmPadV2(xId, xShapeBytes, x.shape.length, CppDType[x.dtype], prePaddingsBytes, postPaddingsBytes, constantValue, outId); - return out; - } - const padV2Config = { - kernelName: tfjsCore.PadV2, - backendName: 'wasm', - kernelFunc: pad, - setupFunc: setup$m - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$d = false; - const powConfig = createBinaryKernelConfig(tfjsCore.Pow, supportsFullBroadcast$d); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmPrelu; - function setup$n(backend) { - wasmPrelu = backend.wasm.cwrap(tfjsCore.Prelu, null /* void */, [ - 'number', - 'number', - 'number' // out_id - ]); - } - function prelu(args) { - const { inputs, backend } = args; - const { x, alpha } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - const weightsId = backend.dataIdMap.get(alpha.dataId).id; - const out = backend.makeOutput(x.shape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmPrelu(xId, weightsId, outId); - return out; - } - const preluConfig = { - kernelName: tfjsCore.Prelu, - backendName: 'wasm', - setupFunc: setup$n, - kernelFunc: prelu - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const reluConfig = createUnaryKernelConfig(tfjsCore.Relu); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const relu6Config = createUnaryKernelConfig(tfjsCore.Relu6); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function reshape(args) { - const { inputs, attrs } = args; - const { x } = inputs; - const { shape } = attrs; - return { dataId: x.dataId, shape, dtype: x.dtype }; - } - const reshapeConfig = { - kernelName: tfjsCore.Reshape, - backendName: 'wasm', - kernelFunc: reshape, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmResizeBilinear; - function setup$o(backend) { - wasmResizeBilinear = backend.wasm.cwrap(tfjsCore.ResizeBilinear, null /*void*/, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number' // outId - ]); - } - function resizeBilinear(args) { - const { backend, inputs, attrs } = args; - const { images } = inputs; - const { alignCorners, size } = attrs; - const [newHeight, newWidth] = size; - const [batch, oldHeight, oldWidth, numChannels] = images.shape; - const outShape = [batch, newHeight, newWidth, numChannels]; - let xData = backend.dataIdMap.get(images.dataId); - let castedData; - if (xData.dtype !== 'float32') { - castedData = - cast({ backend, inputs: { x: images }, attrs: { dtype: 'float32' } }); - xData = backend.dataIdMap.get(castedData.dataId); - } - const xId = xData.id; - const out = backend.makeOutput(outShape, 'float32'); - if (tfjsCore.util.sizeFromShape(images.shape) === 0) { - return out; - } - const outId = backend.dataIdMap.get(out.dataId).id; - wasmResizeBilinear(xId, batch, oldHeight, oldWidth, numChannels, newHeight, newWidth, alignCorners ? 1 : 0, outId); - if (castedData != null) { - backend.disposeData(castedData.dataId); - } - return out; - } - const resizeBilinearConfig = { - kernelName: tfjsCore.ResizeBilinear, - backendName: 'wasm', - setupFunc: setup$o, - kernelFunc: resizeBilinear - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmReverse; - function setup$p(backend) { - wasmReverse = backend.wasm.cwrap(tfjsCore.Reverse, null, [ - 'number', - 'array', - 'number', - 'array', - 'number', - 'number' // out_id - ]); - } - function reverse(args) { - const { inputs, backend, attrs } = args; - const { x } = inputs; - const { dims } = attrs; - const axes = tfjsCore.util.parseAxisParam(dims, x.shape); - if (x.shape.length === 0) { - return identity({ inputs: { x }, backend }); - } - const out = backend.makeOutput(x.shape, x.dtype); - const xId = backend.dataIdMap.get(x.dataId).id; - const outId = backend.dataIdMap.get(out.dataId).id; - const axesBytes = new Uint8Array(new Int32Array(axes).buffer); - const outShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); - wasmReverse(xId, axesBytes, axes.length, outShapeBytes, x.shape.length, outId); - return reshape({ inputs: { x: out }, attrs: { shape: x.shape }, backend }); - } - const reverseConfig = { - kernelName: tfjsCore.Reverse, - backendName: 'wasm', - kernelFunc: reverse, - setupFunc: setup$p - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmRotate; - function setup$q(backend) { - wasmRotate = backend.wasm.cwrap(tfjsCore.RotateWithOffset, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'array', - 'number', - 'number', - ]); - } - function rotateWithOffset(args) { - const { inputs, backend, attrs } = args; - const { image } = inputs; - const { radians, fillValue, center } = attrs; - const out = backend.makeOutput(image.shape, image.dtype); - const imageId = backend.dataIdMap.get(image.dataId).id; - const outId = backend.dataIdMap.get(out.dataId).id; - const [batch, imageHeight, imageWidth, numChannels] = image.shape; - const [centerX, centerY] = tfjsCore.backend_util.getImageCenter(center, imageHeight, imageWidth); - const fillIsBlack = fillValue === 0; - const fullOpacityValue = 255; - const fillValues = typeof fillValue === 'number' ? - [fillValue, fillValue, fillValue, fillIsBlack ? 0 : fullOpacityValue] : - [...fillValue, fullOpacityValue]; - const fillBytes = new Uint8Array(new Int32Array(fillValues).buffer); - wasmRotate(imageId, batch, imageHeight, imageWidth, numChannels, radians, centerX, centerY, fillBytes, fillValues.length, outId); - return out; - } - const rotateWithOffsetConfig = { - kernelName: tfjsCore.RotateWithOffset, - backendName: 'wasm', - kernelFunc: rotateWithOffset, - setupFunc: setup$q - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const rsqrtConfig = createUnaryKernelConfig(tfjsCore.Rsqrt); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmScatterNd; - function setup$r(backend) { - wasmScatterNd = backend.wasm.cwrap(tfjsCore.ScatterNd, null /*void*/, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'array', - 'number', - 'number' // outId - ]); - } - function scatterNd(args) { - const { backend, inputs, attrs } = args; - const { indices, updates } = inputs; - const { shape } = attrs; - const out = backend.makeOutput(shape, updates.dtype); - if (tfjsCore.util.sizeFromShape(shape) === 0) { - return out; - } - const { sliceRank, numUpdates, sliceSize, strides, outputSize } = tfjsCore.scatter_util.calculateShapes(updates, indices, shape); - const indicesData = backend.dataIdMap.get(indices.dataId); - const indicesId = indicesData.id; - const updatesData = backend.dataIdMap.get(updates.dataId); - const updatesId = updatesData.id; - const stridesBytes = new Uint8Array(new Int32Array(strides).buffer); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmScatterNd(indicesId, updatesId, CppDType[updates.dtype], sliceRank, numUpdates, sliceSize, stridesBytes, outputSize, outId); - return out; - } - const scatterNdConfig = { - kernelName: tfjsCore.ScatterNd, - backendName: 'wasm', - setupFunc: setup$r, - kernelFunc: scatterNd - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmSelect; - function setup$s(backend) { - wasmSelect = backend.wasm.cwrap(tfjsCore.SelectV2, null, [ - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function select(args) { - const { inputs, backend } = args; - const { condition, t, e } = inputs; - const conditionId = backend.dataIdMap.get(condition.dataId).id; - const tId = backend.dataIdMap.get(t.dataId).id; - const eId = backend.dataIdMap.get(e.dataId).id; - const out = backend.makeOutput(t.shape, t.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - const cRank = condition.shape.length; - const tRank = t.shape.length; - const offset = cRank === 0 || cRank > 1 || tRank === 1 ? - 1 : - tfjsCore.util.sizeFromShape(t.shape.slice(1)); - wasmSelect(conditionId, tId, eId, offset, outId); - return out; - } - const selectV2Config = { - kernelName: tfjsCore.SelectV2, - backendName: 'wasm', - kernelFunc: select, - setupFunc: setup$s - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$5; - function setup$t(backend) { - wasmFunc$5 = backend.wasm.cwrap(tfjsCore.Sigmoid, null /* void */, ['number', 'number']); - } - function sigmoid(args) { - const { backend, inputs: { x } } = args; - const xId = backend.dataIdMap.get(x.dataId).id; - const out = backend.makeOutput(x.shape, x.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(out.shape) === 0) { - return out; - } - wasmFunc$5(xId, outId); - return out; - } - const sigmoidConfig = { - kernelName: 'Sigmoid', - backendName: 'wasm', - setupFunc: setup$t, - kernelFunc: sigmoid - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const sinConfig = createUnaryKernelConfig(tfjsCore.Sin); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function slice(args) { - const { inputs: { x }, attrs: { begin, size }, backend } = args; - const [begin_, size_] = tfjsCore.slice_util.parseSliceParams(x, begin, size); - const isContinous = tfjsCore.slice_util.isSliceContinous(x.shape, begin_, size_); - const xVals = backend.typedArrayFromHeap(x); - const out = backend.makeOutput(size_, x.dtype); - const outVals = backend.typedArrayFromHeap(out); - const xStrides = tfjsCore.util.computeStrides(x.shape); - if (isContinous) { - const flatOffset = tfjsCore.slice_util.computeFlatOffset(begin_, xStrides); - outVals.set(xVals.subarray(flatOffset, flatOffset + tfjsCore.util.sizeFromShape(size_))); - return out; - } - const rank = x.shape.length; - if (rank === 2) { - slice2d(xVals, xStrides[0], outVals, begin_, size_); - } - else if (rank === 3) { - slice3d(xVals, xStrides[0], xStrides[1], outVals, begin_, size_); - } - else if (rank === 4) { - slice4d(xVals, xStrides[0], xStrides[1], xStrides[2], outVals, begin_, size_); - } - else { - genericSliceSlow(xVals, x, outVals, begin_, size_); - } - return out; - } - function slice2d(xVals, xStride, outVals, begin, size) { - let outOffset = 0; - const beginI = begin[0]; - const beginJ = begin[1]; - const endI = beginI + size[0]; - for (let i = beginI; i < endI; i++) { - const xOffset = i * xStride + beginJ; - outVals.set(xVals.subarray(xOffset, xOffset + size[1]), outOffset); - outOffset += size[1]; - } - } - function slice3d(xVals, xStride1, xStride2, outVals, begin, size) { - let outOffset = 0; - const beginI = begin[0]; - const beginJ = begin[1]; - const beginK = begin[2]; - const endI = beginI + size[0]; - const endJ = beginJ + size[1]; - for (let i = beginI; i < endI; i++) { - for (let j = beginJ; j < endJ; j++) { - const xOffset = i * xStride1 + j * xStride2 + beginK; - outVals.set(xVals.subarray(xOffset, xOffset + size[2]), outOffset); - outOffset += size[2]; - } - } - } - function slice4d(xVals, xStride1, xStride2, xStride3, outVals, begin, size) { - let outOffset = 0; - const beginI = begin[0]; - const beginJ = begin[1]; - const beginK = begin[2]; - const endI = beginI + size[0]; - const endJ = beginJ + size[1]; - const endK = beginK + size[2]; - const beginL = begin[3]; - for (let i = beginI; i < endI; i++) { - for (let j = beginJ; j < endJ; j++) { - for (let k = beginK; k < endK; k++) { - const xOffset = i * xStride1 + j * xStride2 + k * xStride3 + beginL; - outVals.set(xVals.subarray(xOffset, xOffset + size[3]), outOffset); - outOffset += size[3]; - } - } - } - } - function genericSliceSlow(xVals, xInfo, outVals, begin, size) { - const outBuf = tfjsCore.buffer(size, xInfo.dtype, outVals); - const xBuf = tfjsCore.buffer(xInfo.shape, xInfo.dtype, xVals); - for (let i = 0; i < outBuf.size; ++i) { - const loc = outBuf.indexToLoc(i); - const xLoc = loc.map((idx, j) => idx + begin[j]); - outVals[i] = xBuf.get(...xLoc); - } - } - const sliceConfig = { - kernelName: tfjsCore.Slice, - backendName: 'wasm', - kernelFunc: slice, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$6; - function setup$u(backend) { - wasmFunc$6 = backend.wasm.cwrap(tfjsCore.Softmax, null /* void */, [ - 'number', - 'number', - 'number', - 'number' // batch - ]); - } - function softmax(args) { - const { backend, inputs: { logits }, attrs: { dim } } = args; - const xId = backend.dataIdMap.get(logits.dataId).id; - const out = backend.makeOutput(logits.shape, logits.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - const channels = logits.shape[dim]; - const batch = tfjsCore.util.sizeFromShape(logits.shape) / channels; - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(out.shape) === 0) { - return out; - } - wasmFunc$6(xId, outId, channels, batch); - return out; - } - const softmaxConfig = { - kernelName: tfjsCore.Softmax, - backendName: 'wasm', - setupFunc: setup$u, - kernelFunc: softmax - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function split(args) { - const { inputs, attrs, backend } = args; - const { x } = inputs; - const { numOrSizeSplits, axis } = attrs; - const $axis = tfjsCore.util.parseAxisParam(axis, x.shape)[0]; - const splitSizes = tfjsCore.backend_util.prepareSplitSize(x, numOrSizeSplits, axis); - const begin = new Array(x.shape.length).fill(0); - const size = x.shape.slice(); - return splitSizes.map(s => { - const xSliceSize = [...size]; - xSliceSize[$axis] = s; - const xSlice = slice({ inputs: { x }, attrs: { begin, size: xSliceSize }, backend }); - begin[$axis] += s; - return xSlice; - }); - } - const splitVConfig = { - kernelName: tfjsCore.SplitV, - backendName: 'wasm', - kernelFunc: split - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const sqrtConfig = createUnaryKernelConfig(tfjsCore.Sqrt); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const squareConfig = createUnaryKernelConfig(tfjsCore.Square); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$e = true; - const subConfig = createBinaryKernelConfig(tfjsCore.Sub, supportsFullBroadcast$e); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmSum; - function setup$v(backend) { - wasmSum = backend.wasm.cwrap(tfjsCore.Sum, null /*void*/, ['number, number, number']); - } - function sum(args) { - const { backend, inputs, attrs } = args; - const { axis, keepDims } = attrs; - const { x } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - let inputId = xId; - let input = x; - const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); - let reductionAxes = axes; - if (inputWasTransposed) { - const transposedId = backend.dataIdMap.get(transposed.dataId).id; - if (transposedId !== xId) { - // transpose was not a no-op. We will need to dispose of this - // once we are done. - input = transposed; - inputId = transposedId; - reductionAxes = tfjsCore.backend_util.getInnerMostAxes(reductionAxes.length, input.shape.length); - } - } - tfjsCore.backend_util.assertAxesAreInnerMostDims('sum', reductionAxes, input.shape.length); - const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, reductionAxes); - const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); - const out = backend.makeOutput(outShape, input.dtype); - if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { - const outId = backend.dataIdMap.get(out.dataId).id; - wasmSum(inputId, reduceSize, outId); - } - if (inputWasTransposed) { - // dispose of the transposed tensor. - backend.disposeData(transposed.dataId); - } - if (keepDims) { - // reshape - const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); - out.shape = newShape; - } - return out; - } - const sumConfig = { - kernelName: tfjsCore.Sum, - backendName: 'wasm', - setupFunc: setup$v, - kernelFunc: sum - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const tanhConfig = createUnaryKernelConfig(tfjsCore.Tanh); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmTile; - function setup$w(backend) { - wasmTile = backend.wasm.cwrap(tfjsCore.Tile, null /* void */, [ - 'number', - 'array', - 'number', - 'array', - 'number', - 'number' // out_id - ]); - } - function tile(args) { - const { inputs, backend, attrs } = args; - const { x } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - const { reps } = attrs; - const newShape = new Array(x.shape.length); - for (let i = 0; i < newShape.length; i++) { - newShape[i] = x.shape[i] * reps[i]; - } - const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); - const newShapeBytes = new Uint8Array(new Int32Array(newShape).buffer); - const out = backend.makeOutput(newShape, x.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmTile(xId, xShapeBytes, x.shape.length, newShapeBytes, newShape.length, CppDType[out.dtype], outId); - return out; - } - const tileConfig = { - kernelName: tfjsCore.Tile, - backendName: 'wasm', - setupFunc: setup$w, - kernelFunc: tile - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function unpack(args) { - const { inputs, backend, attrs } = args; - const { value } = inputs; - const { axis } = attrs; - const numOutputs = value.shape[axis]; - const rank = value.shape.length; - const outShape = new Array(rank - 1); - let outIndex = 0; - for (let i = 0; i < rank; i++) { - if (i !== axis) { - outShape[outIndex++] = value.shape[i]; - } - } - const outs = new Array(numOutputs); - const begin = new Array(rank).fill(0); - const size = value.shape.slice(); - size[axis] = 1; - for (let i = 0; i < outs.length; i++) { - begin[axis] = i; - outs[i] = slice({ inputs: { x: value }, attrs: { begin, size }, backend }); - } - return outs.map(({ dataId, dtype }) => ({ dataId, dtype, shape: outShape })); - } - const unpackConfig = { - kernelName: tfjsCore.Unpack, - backendName: 'wasm', - kernelFunc: unpack, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function zerosLike(args) { - const { inputs: { x }, backend } = args; - const out = backend.makeOutput(x.shape, x.dtype); - const outVals = backend.typedArrayFromHeap(out); - outVals.fill(0); - return out; - } - const zerosLikeConfig = { - kernelName: tfjsCore.ZerosLike, - backendName: 'wasm', - kernelFunc: zerosLike, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // List all kernel configs here - const kernelConfigs = [ - absConfig, - addConfig, - addNConfig, - argMaxConfig, - avgPoolConfig, - batchMatMulConfig, - castConfig, - clipByValueConfig, - concatConfig, - conv2DConfig, - conv2DBackpropInputConfig, - cosConfig, - cropAndResizeConfig, - depthwiseConv2DNativeConfig, - divConfig, - equalConfig, - expConfig, - fillConfig, - floorDivConfig, - fusedMatMulConfig, - fusedBatchNormConfig, - fusedConv2DConfig, - fusedDepthwiseConv2DConfig, - gatherNdConfig, - gatherV2Config, - greaterConfig, - greaterEqualConfig, - identityConfig, - lessConfig, - lessEqualConfig, - logConfig, - logicalAndConfig, - maxConfig, - maximumConfig, - maxPoolConfig, - minConfig, - minimumConfig, - multiplyConfig, - negateConfig, - nonMaxSuppressionV3Config, - nonMaxSuppressionV4Config, - nonMaxSuppressionV5Config, - notEqualConfig, - oneHotConfig, - onesLikeConfig, - padV2Config, - powConfig, - preluConfig, - reluConfig, - relu6Config, - reshapeConfig, - resizeBilinearConfig, - reverseConfig, - rotateWithOffsetConfig, - rsqrtConfig, - scatterNdConfig, - selectV2Config, - sigmoidConfig, - sinConfig, - sliceConfig, - softmaxConfig, - splitVConfig, - sqrtConfig, - squareConfig, - subConfig, - sumConfig, - tanhConfig, - tileConfig, - transposeConfig, - unpackConfig, - zerosLikeConfig - ]; - for (const kernelConfig of kernelConfigs) { - tfjsCore.registerKernel(kernelConfig); - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const ENV = tfjsCore.env(); - /** - * True if SIMD is supported. - */ - // From: https://github.com/GoogleChromeLabs/wasm-feature-detect - ENV.registerFlag('WASM_HAS_SIMD_SUPPORT', async () => WebAssembly.validate(new Uint8Array([ - 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, - 2, 1, 0, 10, 9, 1, 7, 0, 65, 0, 253, 15, 26, 11 - ]))); - - function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; - } - - var tfjsBackendWasm = createCommonjsModule(function (module, exports) { - var WasmBackendModule = (function() { - var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; - if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; - return ( - function(WasmBackendModule) { - WasmBackendModule = WasmBackendModule || {}; - - var Module=typeof WasmBackendModule!=="undefined"?WasmBackendModule:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":146,"maximum":146+0,"element":"anyfunc"});var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023);}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var DYNAMIC_BASE=5254800,DYNAMICTOP_PTR=11760;var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":2147483648/WASM_PAGE_SIZE});}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;removeRunDependency();}addRunDependency();function receiveInstantiatedSource(output){receiveInstance(output["instance"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}__ATINIT__.push({func:function(){___wasm_call_ctors();}});function _abort(){abort();}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num);}function _emscripten_get_heap_size(){return HEAPU8.length}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();var PAGE_MULTIPLE=65536;var maxHeapSize=2147483648;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}var asmLibraryArg={"a":_abort,"e":_emscripten_memcpy_big,"f":_emscripten_resize_heap,"g":_fd_close,"d":_fd_seek,"c":_fd_write,"memory":wasmMemory,"b":_roundf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return (___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["h"]).apply(null,arguments)};var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["i"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["j"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["k"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["l"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["m"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["n"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["o"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["p"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["q"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["r"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["s"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["t"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["u"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["v"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["w"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["x"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["y"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["z"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["A"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["B"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["C"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["D"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["E"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["F"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["G"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["H"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["I"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["J"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["K"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["L"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["M"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["N"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["O"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["P"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["Q"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["R"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["S"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["T"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["U"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["V"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["W"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["X"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["Y"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["Z"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["_"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["$"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["aa"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["ba"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["ca"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["da"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["ea"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["fa"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["ga"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["ha"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["ia"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["ja"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["ka"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["la"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["ma"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["na"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["oa"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["pa"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["qa"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["ra"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["sa"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["ta"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["ua"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["va"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["wa"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["xa"]).apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){return (dynCall_vi=Module["dynCall_vi"]=Module["asm"]["ya"]).apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){return (dynCall_v=Module["dynCall_v"]=Module["asm"]["za"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}noExitRuntime=true;run(); - - - return WasmBackendModule - } - ); - })(); - module.exports = WasmBackendModule; - }); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const WASM_PRIORITY = 2; - class BackendWasm extends tfjsCore.KernelBackend { - constructor(wasm) { - super(); - this.wasm = wasm; - // 0 is reserved for null data ids. - this.dataIdNextNumber = 1; - this.wasm.tfjs.init(); - this.dataIdMap = new tfjsCore.DataStorage(this, tfjsCore.engine()); - } - write(values, shape, dtype) { - const dataId = {}; - this.move(dataId, values, shape, dtype); - return dataId; - } - numDataIds() { - return this.dataIdMap.numDataIds(); - } - async time(f) { - const start = tfjsCore.util.now(); - f(); - const kernelMs = tfjsCore.util.now() - start; - return { kernelMs }; - } - move(dataId, values, shape, dtype) { - const id = this.dataIdNextNumber++; - if (dtype === 'string') { - const stringBytes = values; - this.dataIdMap.set(dataId, { id, stringBytes, shape, dtype, memoryOffset: null }); - return; - } - const size = tfjsCore.util.sizeFromShape(shape); - const numBytes = size * tfjsCore.util.bytesPerElement(dtype); - const memoryOffset = this.wasm._malloc(numBytes); - this.dataIdMap.set(dataId, { id, memoryOffset, shape, dtype }); - this.wasm.tfjs.registerTensor(id, size, memoryOffset); - if (values != null) { - this.wasm.HEAPU8.set(new Uint8Array(values.buffer, values.byteOffset, numBytes), memoryOffset); - } - } - async read(dataId) { - return this.readSync(dataId); - } - readSync(dataId) { - const { memoryOffset, dtype, shape, stringBytes } = this.dataIdMap.get(dataId); - if (dtype === 'string') { - return stringBytes; - } - const bytes = this.wasm.HEAPU8.slice(memoryOffset, memoryOffset + tfjsCore.util.sizeFromShape(shape) * tfjsCore.util.bytesPerElement(dtype)); - return typedArrayFromBuffer(bytes.buffer, dtype); - } - disposeData(dataId) { - const data = this.dataIdMap.get(dataId); - this.wasm._free(data.memoryOffset); - this.wasm.tfjs.disposeData(data.id); - this.dataIdMap.delete(dataId); - } - floatPrecision() { - return 32; - } - // Returns the memory offset of a tensor. Useful for debugging and unit - // testing. - getMemoryOffset(dataId) { - return this.dataIdMap.get(dataId).memoryOffset; - } - dispose() { - this.wasm.tfjs.dispose(); - this.wasm = null; - } - memory() { - return { unreliable: false }; - } - /** - * Make a tensor info for the output of an op. If `memoryOffset` is not - * present, this method allocates memory on the WASM heap. If `memoryOffset` - * is present, the memory was allocated elsewhere (in c++) and we just record - * the pointer where that memory lives. - */ - makeOutput(shape, dtype, memoryOffset) { - let dataId; - if (memoryOffset == null) { - dataId = this.write(null /* values */, shape, dtype); - } - else { - dataId = {}; - const id = this.dataIdNextNumber++; - this.dataIdMap.set(dataId, { id, memoryOffset, shape, dtype }); - const size = tfjsCore.util.sizeFromShape(shape); - this.wasm.tfjs.registerTensor(id, size, memoryOffset); - } - return { dataId, shape, dtype }; - } - typedArrayFromHeap({ shape, dtype, dataId }) { - const buffer = this.wasm.HEAPU8.buffer; - const { memoryOffset } = this.dataIdMap.get(dataId); - const size = tfjsCore.util.sizeFromShape(shape); - switch (dtype) { - case 'float32': - return new Float32Array(buffer, memoryOffset, size); - case 'int32': - return new Int32Array(buffer, memoryOffset, size); - case 'bool': - return new Uint8Array(buffer, memoryOffset, size); - default: - throw new Error(`Uknown dtype ${dtype}`); - } - } - } - tfjsCore.registerBackend('wasm', async () => { - const { wasm } = await init(); - return new BackendWasm(wasm); - }, WASM_PRIORITY); - function createInstantiateWasmFunc(path) { - // tslint:disable-next-line:no-any - return (imports, callback) => { - tfjsCore.util.fetch(path, { credentials: 'same-origin' }).then((response) => { - if (!response['ok']) { - imports.env.a(`failed to load wasm binary file at '${path}'`); - } - response.arrayBuffer().then(binary => { - WebAssembly.instantiate(binary, imports).then(output => { - callback(output.instance); - }); - }); - }); - return {}; - }; - } - /** - * Initializes the wasm module and creates the js <--> wasm bridge. - * - * NOTE: We wrap the wasm module in a object with property 'wasm' instead of - * returning Promise to avoid freezing Chrome (last tested - * in Chrome 76). - */ - async function init() { - const simdSupported = await tfjsCore.env().getAsync('WASM_HAS_SIMD_SUPPORT'); - return new Promise((resolve, reject) => { - const factoryConfig = {}; - factoryConfig.locateFile = (path, prefix) => { - if (path.endsWith('.wasm')) { - if (wasmPath != null) { - return wasmPath; - } - if (simdSupported) { - return prefix + 'tfjs-backend-wasm-simd.wasm'; - } - return prefix + 'tfjs-backend-wasm.wasm'; - } - return prefix + path; - }; - if (wasmPath != null) { - // use wasm instantiateWasm override when system fetch is not available. - // For detail references - // https://github.com/emscripten-core/emscripten/blob/2bca083cbbd5a4133db61fbd74d04f7feecfa907/tests/manual_wasm_instantiate.html#L170 - if (customFetch) { - factoryConfig.instantiateWasm = createInstantiateWasmFunc(wasmPath); - } - } - const wasm = tfjsBackendWasm(factoryConfig); - const voidReturnType = null; - // Using the tfjs namespace to avoid conflict with emscripten's API. - wasm.tfjs = { - init: wasm.cwrap('init', null, []), - registerTensor: wasm.cwrap('register_tensor', null, [ - 'number', - 'number', - 'number', - ]), - disposeData: wasm.cwrap('dispose_data', voidReturnType, ['number']), - dispose: wasm.cwrap('dispose', voidReturnType, []), - }; - let initialized = false; - wasm.onRuntimeInitialized = () => { - initialized = true; - initAborted = false; - resolve({ wasm }); - }; - wasm.onAbort = () => { - if (initialized) { - // Emscripten already called console.warn so no need to double log. - return; - } - if (initAborted) { - // Emscripten calls `onAbort` twice, resulting in double error - // messages. - return; - } - initAborted = true; - const rejectMsg = 'Make sure the server can serve the `.wasm` file relative to the ' + - 'bundled js file. For more details see https://github.com/tensorflow/tfjs/blob/master/tfjs-backend-wasm/README.md#using-bundlers'; - reject({ message: rejectMsg }); - }; - }); - } - function typedArrayFromBuffer(buffer, dtype) { - switch (dtype) { - case 'float32': - return new Float32Array(buffer); - case 'int32': - return new Int32Array(buffer); - case 'bool': - return new Uint8Array(buffer); - default: - throw new Error(`Unknown dtype ${dtype}`); - } - } - let wasmPath = null; - let initAborted = false; - let customFetch = false; - /** - * Sets the path to the `.wasm` file which will be fetched when the wasm - * backend is initialized. See - * https://github.com/tensorflow/tfjs/blob/master/tfjs-backend-wasm/README.md#using-bundlers - * for more details. - * @param path wasm file path or url - * @param usePlatformFetch optional boolean to use platform fetch to download - * the wasm file, default to false. - */ - /** @doc {heading: 'Environment', namespace: 'wasm'} */ - function setWasmPath(path, usePlatformFetch = false) { - if (initAborted) { - throw new Error('The WASM backend was already initialized. Make sure you call ' + - '`setWasmPath()` before you call `tf.setBackend()` or `tf.ready()`'); - } - wasmPath = path; - customFetch = usePlatformFetch; - } - - /** @license See the LICENSE file. */ - // This code is auto-generated, do not modify this file! - const version = '0.0.0'; - - exports.BackendWasm = BackendWasm; - exports.setWasmPath = setWasmPath; - exports.version_wasm = version; - - Object.defineProperty(exports, '__esModule', { value: true }); - -}))); -//# sourceMappingURL=tf-backend-wasm.js.map diff --git a/e2e/benchmarks/tfjs-backend-wasm-simd.wasm b/e2e/benchmarks/tfjs-backend-wasm-simd.wasm deleted file mode 100644 index 5ce27d3d361dcb5fc43dfecf1b3cc340b86e828f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 214013 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� 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

  • h`6##Z4- zo<67Xw+GDpYEGB^D@F_`p~&H9;=hdMeqIp+ipr^4dK#;u2)0|UL^Z+$o%QjebJY&C z=Y$ZZGaSntc_P(gST|WhO5rmat3oK8l#hDrYd*P)-#}~*u17~RCGITOHp-D~Ta8A| zDmZ!?&7P=&esO7Ppdip?9pXTW6xPPFYp!TtrR?`6ppZ5rRr zHXIvfOJ@5?w$?plZ;dlzt{$<^gM=SBOu$=jjH5TO^-?Nc2FsbDu?)t&r*2UQEu@VFGBaaIaplC7n4&o|Fa?Z{GSNYcgii_bj~rwqDm~FY~JHigD49Va{pPT zy8LeUMnqE4ObpFafZTx|--u*)o4fnQMn>pv=y%^!bl#p?_!BVgiW(xC!g@S|NEVv5pf|uYe_zR&zxF8XB3VVbE;ec>dI3c79=Y>omN5~V3 zgzLh6K}z_4)pxzv*T3t$Tjc$(dZ&u~|E~KLk^Xo6?}|JpCm+{!;?aG8hqtSWuXuCo zw#GM@An`cBH$W7N@5JI%F>+FIq9?G3ed0x4_x@ru#fV7V1)_(-8xebnp@_P=u&BQw R1}ncR3J+By*CSVN{@+HkvWox! diff --git a/e2e/benchmarks/tfjs-backend-wasm.wasm b/e2e/benchmarks/tfjs-backend-wasm.wasm deleted file mode 100644 index 2a371e8ad5b83a38fd0c51deb1402945b921bdfb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 154589 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

    {$l7_JtSLg2; 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 From 56996aaedffb81744b70f315028195e9ccd6382b Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Sat, 1 Aug 2020 20:18:52 -0400 Subject: [PATCH 36/70] add comments --- tfjs-backend-wasm/src/backend_wasm.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tfjs-backend-wasm/src/backend_wasm.ts b/tfjs-backend-wasm/src/backend_wasm.ts index 31acefa7d2c..6c3900c4aa3 100644 --- a/tfjs-backend-wasm/src/backend_wasm.ts +++ b/tfjs-backend-wasm/src/backend_wasm.ts @@ -205,11 +205,20 @@ export async function init(): Promise<{wasm: BackendWasmModule}> { const simdSupported = await env().getAsync('WASM_HAS_SIMD_SUPPORT'); return new Promise((resolve, reject) => { const factoryConfig: WasmFactoryConfig = {}; + + /** + * This function overrides the Emscripten module locateFile utility. + * @param path The relative path to the file that needs to be loaded. + * @param prefix The path to the main JavaScript file's directory. + */ factoryConfig.locateFile = (path, prefix) => { if (path.endsWith('.wasm')) { if (wasmPath != null) { + // If wasmPath is defined, the user has supplied a full path to + // the .wasm binary. return wasmPath; } + if (simdSupported) { return prefix + 'tfjs-backend-wasm-simd.wasm'; } @@ -217,6 +226,7 @@ export async function init(): Promise<{wasm: BackendWasmModule}> { } return prefix + path; }; + if (wasmPath != null) { // use wasm instantiateWasm override when system fetch is not available. // For detail references @@ -282,6 +292,7 @@ function typedArrayFromBuffer( let wasmPath: string = null; let initAborted = false; let customFetch = false; + /** * Sets the path to the `.wasm` file which will be fetched when the wasm * backend is initialized. See From 048f1e6a8f9369eab0d91bd90aec299e3ad32341 Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Mon, 3 Aug 2020 08:07:04 -0400 Subject: [PATCH 37/70] comments --- tfjs-backend-wasm/README.md | 3 +-- tfjs-backend-wasm/scripts/build-wasm.sh | 2 +- tfjs-backend-wasm/scripts/create-worker-module.js | 8 ++++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/tfjs-backend-wasm/README.md b/tfjs-backend-wasm/README.md index 967e339dec3..a66bdb482de 100644 --- a/tfjs-backend-wasm/README.md +++ b/tfjs-backend-wasm/README.md @@ -172,8 +172,7 @@ Yes. If you run into issues, please let us know. Yes. We take advantage of SIMD wherever it is supported. If you intend to serve the WASM assets yourself, note that the SIMD-enabled WASM binary is separate from the default binary. ### Do you support multi-threading? -Multi-threading support is not a priority for us at this point since it is still -a proposal. We will keep a close eye on it as the proposal progresses. +Yes. We take advantage of multi-threading wherever it is supported. If you intend to serve the WASM assets yourself, note that the multi-threading-enabled WASM binary is separate from the default binary. ### How do I give feedback? We'd love your feedback as we develop this backend! Please file an issue diff --git a/tfjs-backend-wasm/scripts/build-wasm.sh b/tfjs-backend-wasm/scripts/build-wasm.sh index b0277e7ab82..1279a3d2635 100755 --- a/tfjs-backend-wasm/scripts/build-wasm.sh +++ b/tfjs-backend-wasm/scripts/build-wasm.sh @@ -24,7 +24,7 @@ cp -f bazel-bin/src/cc/tfjs-backend-wasm.js \ bazel-bin/src/cc/tfjs-backend-wasm.wasm \ wasm-out/ -# # SIMD build. +# SIMD build. yarn bazel build -c opt //src/cc:tfjs-backend-wasm-simd.wasm --config=wasm --copt="-msimd128" cp -f bazel-bin/src/cc/tfjs-backend-wasm-simd.wasm \ wasm-out/ diff --git a/tfjs-backend-wasm/scripts/create-worker-module.js b/tfjs-backend-wasm/scripts/create-worker-module.js index b76ed3a3273..e6da1ab89c2 100755 --- a/tfjs-backend-wasm/scripts/create-worker-module.js +++ b/tfjs-backend-wasm/scripts/create-worker-module.js @@ -24,10 +24,10 @@ const fs = require('fs'); const BASE_PATH = './wasm-out/'; const WORKER_PATH = `${BASE_PATH}tfjs-backend-wasm-threaded-simd.worker.js`; +// Write out a worker TypeScript module. const workerContents = fs.readFileSync(WORKER_PATH, "utf8"); +fs.writeFileSync(`${BASE_PATH}tfjs-backend-wasm-threaded-simd.worker.ts`, + `export const wasmWorkerContents = '${workerContents.trim()}';`); -const fileContents = `export const wasmWorkerContents = '${workerContents.trim()}';`; - -fs.writeFileSync(`${BASE_PATH}tfjs-backend-wasm-threaded-simd.worker.ts`, fileContents); - +// Delete the original worker file. fs.unlinkSync(WORKER_PATH) From 2687bf7a7b3335c0b9bb63901382f4845631addc Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Mon, 3 Aug 2020 08:37:08 -0400 Subject: [PATCH 38/70] clean --- tfjs-backend-wasm/README.md | 2 +- tfjs-backend-wasm/src/backend_wasm.ts | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/tfjs-backend-wasm/README.md b/tfjs-backend-wasm/README.md index a66bdb482de..67f842772a2 100644 --- a/tfjs-backend-wasm/README.md +++ b/tfjs-backend-wasm/README.md @@ -82,7 +82,7 @@ setWasmPath(yourCustomPath); // or tf.wasm.setWasmPath when using + - - + diff --git a/e2e/benchmarks/tf-backend-wasm.js b/e2e/benchmarks/tf-backend-wasm.js deleted file mode 100644 index c060cdcfb12..00000000000 --- a/e2e/benchmarks/tf-backend-wasm.js +++ /dev/null @@ -1,3700 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tensorflow/tfjs-core'), require('path'), require('fs'), require('worker_threads'), require('perf_hooks')) : - typeof define === 'function' && define.amd ? define(['exports', '@tensorflow/tfjs-core', 'path', 'fs', 'worker_threads', 'perf_hooks'], factory) : - (global = global || self, factory((global.tf = global.tf || {}, global.tf.wasm = global.tf.wasm || {}), global.tf, global.path, global.fs, global.worker_threads, global.perf_hooks)); -}(this, (function (exports, tfjsCore, path, fs, worker_threads, perf_hooks) { 'use strict'; - - path = path && path.hasOwnProperty('default') ? path['default'] : path; - fs = fs && fs.hasOwnProperty('default') ? fs['default'] : fs; - worker_threads = worker_threads && worker_threads.hasOwnProperty('default') ? worker_threads['default'] : worker_threads; - perf_hooks = perf_hooks && perf_hooks.hasOwnProperty('default') ? perf_hooks['default'] : perf_hooks; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // This enum must align with the enum defined in cc/backend.h. - var CppDType; - (function (CppDType) { - CppDType[CppDType["float32"] = 0] = "float32"; - CppDType[CppDType["int32"] = 1] = "int32"; - CppDType[CppDType["bool"] = 2] = "bool"; - CppDType[CppDType["string"] = 3] = "string"; - CppDType[CppDType["complex64"] = 4] = "complex64"; - })(CppDType || (CppDType = {})); - // Must match enum in cc/fusable_activations.h. - var FusableActivation; - (function (FusableActivation) { - FusableActivation[FusableActivation["linear"] = 0] = "linear"; - FusableActivation[FusableActivation["relu"] = 1] = "relu"; - FusableActivation[FusableActivation["relu6"] = 2] = "relu6"; - FusableActivation[FusableActivation["prelu"] = 3] = "prelu"; - })(FusableActivation || (FusableActivation = {})); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFusedMatMul; - function setup(backend) { - wasmFusedMatMul = backend.wasm.cwrap(tfjsCore._FusedMatMul, null /* void */, [ - 'number', - 'array', - 'number', - 'number', - 'array', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number' // out_id - ]); - } - function fusedBatchMatMul(args) { - const { inputs, backend, attrs } = args; - const { a, b, bias, preluActivationWeights } = inputs; - if (a.dtype !== 'float32' || b.dtype !== 'float32') { - throw new Error(`_FusedMatMul for non non-float32 tensors not yet supported.`); - } - const { transposeA, transposeB, activation } = attrs; - const aId = backend.dataIdMap.get(a.dataId).id; - const bId = backend.dataIdMap.get(b.dataId).id; - let biasId = 0; - if (bias != null) { - const biasData = backend.dataIdMap.get(bias.dataId); - if (biasData.shape.length !== 1) { - throw new Error(`_FusedMatMul only supports rank-1 bias but got ` + - `rank ${biasData.shape.length}.`); - } - biasId = biasData.id; - } - const preluActivationWeightsId = preluActivationWeights == null ? - 0 : - backend.dataIdMap.get(preluActivationWeights.dataId).id; - const fusedActivation = FusableActivation[activation]; - if (fusedActivation == null) { - throw new Error(`${activation} activation not yet supported for FusedConv2D ` + - `in the wasm backend.`); - } - const leftDim = transposeA ? a.shape[2] : a.shape[1]; - const rightDim = transposeB ? b.shape[1] : b.shape[2]; - const batchDim = a.shape[0]; - const out = backend.makeOutput([batchDim, leftDim, rightDim], a.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); - const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); - wasmFusedMatMul(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, transposeA, transposeB, fusedActivation, biasId, preluActivationWeightsId, outId); - return out; - } - const fusedMatMulConfig = { - kernelName: tfjsCore._FusedMatMul, - backendName: 'wasm', - setupFunc: setup, - kernelFunc: fusedBatchMatMul - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function createUnaryKernelConfig(kernelName) { - let wasmFunc; - function setupFunc(backend) { - wasmFunc = - backend.wasm.cwrap(kernelName, null /* void */, ['number', 'number']); - } - function kernelFunc(args) { - const { backend, inputs: { x } } = args; - const xId = backend.dataIdMap.get(x.dataId).id; - const out = backend.makeOutput(x.shape, x.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(out.shape) === 0) { - return out; - } - wasmFunc(xId, outId); - return out; - } - return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const absConfig = createUnaryKernelConfig(tfjsCore.Abs); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function createBinaryKernelConfig(kernelName, supportsFullBroadcast, dtype) { - let wasmFunc; - function setupFunc(backend) { - wasmFunc = backend.wasm.cwrap(kernelName, null /* void */, [ - 'number', - 'array', - 'number', - 'number', - 'array', - 'number', - 'number', - 'number' // out_id - ]); - } - function kernelFunc(args) { - const { backend, inputs } = args; - const { a, b } = inputs; - const aId = backend.dataIdMap.get(a.dataId).id; - const bId = backend.dataIdMap.get(b.dataId).id; - const outputType = dtype != null ? dtype : a.dtype; - const newShape = tfjsCore.backend_util.assertAndGetBroadcastShape(a.shape, b.shape); - const out = backend.makeOutput(newShape, outputType); - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(newShape) === 0) { - return out; - } - const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); - const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); - const outId = backend.dataIdMap.get(out.dataId).id; - const kernelFunc = () => wasmFunc(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, CppDType[a.dtype], outId); - // Currently only some float operations support full broadcast. - if (supportsFullBroadcast && a.dtype === 'float32') { - kernelFunc(); - return out; - } - const aBroadcastDims = tfjsCore.backend_util.getBroadcastDims(a.shape, newShape); - const bBroadcastDims = tfjsCore.backend_util.getBroadcastDims(b.shape, newShape); - const loopsOverAllOfA = aBroadcastDims.every((v, i) => v === i); - const loopsOverAllOfB = bBroadcastDims.every((v, i) => v === i); - if (loopsOverAllOfA && loopsOverAllOfB) { - kernelFunc(); - return out; - } - else { - throw new Error(`Broadcasting along outer dims is not yet ` + - `supported for ${a.dtype} ${kernelName}.`); - } - } - return { kernelName, backendName: 'wasm', setupFunc, kernelFunc }; - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast = true; - const addConfig = createBinaryKernelConfig(tfjsCore.Add, supportsFullBroadcast); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc; - function setupFunc(backend) { - wasmFunc = backend.wasm.cwrap(tfjsCore.AddN, null /* void */, [ - 'array', - 'number', - 'number', - 'number', - ]); - } - function addn(args) { - const { inputs, backend } = args; - const out = backend.makeOutput(inputs[0].shape, inputs[0].dtype); - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(out.shape) === 0) { - return out; - } - const inputIds = inputs.map(x => backend.dataIdMap.get(x.dataId).id); - const inputIdsBytes = new Uint8Array(new Int32Array(inputIds).buffer); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmFunc(inputIdsBytes, inputIds.length, CppDType[out.dtype], outId); - return out; - } - const addNConfig = { - kernelName: tfjsCore.AddN, - backendName: 'wasm', - setupFunc, - kernelFunc: addn, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function identity(args) { - const { inputs: { x }, backend } = args; - const out = backend.makeOutput(x.shape, x.dtype); - const inVals = backend.typedArrayFromHeap(x); - const outVals = backend.typedArrayFromHeap(out); - outVals.set(inVals); - return out; - } - const identityConfig = { - kernelName: tfjsCore.Identity, - backendName: 'wasm', - kernelFunc: identity, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmTranspose; - function setup$1(backend) { - wasmTranspose = backend.wasm.cwrap(tfjsCore.Transpose, null /* void */, [ - 'number', - 'array', - 'number', - 'number', - 'number', - 'array', - 'number', - ]); - } - function transpose(args) { - const { inputs, backend, attrs } = args; - // Reduce any dimensions with size one. Lower-rank transpose kernel performs - // better due to simpler memory access pattern. - const [reducedShape, perm] = removeOneSizeDims(inputs.x.shape, attrs.perm); - let permIsNoOp = true; - for (let i = 0; i < perm.length; i++) { - if (perm[i] !== i) { - permIsNoOp = false; - } - } - const outShape = computeOutShape(inputs.x.shape, attrs.perm); - const x = { - dataId: inputs.x.dataId, - shape: reducedShape, - dtype: inputs.x.dtype - }; - if (permIsNoOp) { - const cloned = identity({ inputs, backend }); - cloned.shape = outShape; - return cloned; - } - const out = backend.makeOutput(outShape, x.dtype); - const xId = backend.dataIdMap.get(x.dataId).id; - const outId = backend.dataIdMap.get(out.dataId).id; - const permBytes = new Uint8Array(new Int32Array(perm).buffer); - const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); - wasmTranspose(xId, xShapeBytes, x.shape.length, CppDType[x.dtype], outId, permBytes, perm.length); - return out; - } - function computeOutShape(inShape, perm) { - const outShape = new Array(inShape.length); - for (let i = 0; i < outShape.length; i++) { - outShape[i] = inShape[perm[i]]; - } - return outShape; - } - function removeOneSizeDims(shape, perm) { - const newShape = []; - const newPerm = []; - for (let i = 0; i < shape.length; ++i) { - if (shape[i] !== 1) { - newShape.push(shape[i]); - } - if (shape[perm[i]] !== 1) { - newPerm.push(perm[i]); - } - } - for (let i = 0; i < newPerm.length; ++i) { - let minValIdx = -1; - for (let j = 0; j < newPerm.length; ++j) { - if (newPerm[j] >= i && - (minValIdx === -1 || newPerm[minValIdx] > newPerm[j])) { - minValIdx = j; - } - } - newPerm[minValIdx] = i; - } - return [newShape, newPerm]; - } - const transposeConfig = { - kernelName: tfjsCore.Transpose, - backendName: 'wasm', - kernelFunc: transpose, - setupFunc: setup$1, - }; - - /** - * @license - * Copyright 2020 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Compute permutation axes and do a transpose if necessary. - * - * Used by reduction ops. - * @param x input TensorInfo - * @param axis reduction axes - * @param backend wasm backend instance - */ - function permuteAxesAndTranspose(x, axis, backend) { - const xShape = x.shape; - const xRank = x.shape.length; - const originalAxes = tfjsCore.util.parseAxisParam(axis, xShape); - let axes = originalAxes; - const permutedAxes = tfjsCore.backend_util.getAxesPermutation(axes, xRank); - let xTransposed = null; - let inputWasTransposed = false; - if (permutedAxes != null) { - const newShape = new Array(xRank); - for (let i = 0; i < newShape.length; i++) { - newShape[i] = xShape[permutedAxes[i]]; - } - axes = tfjsCore.backend_util.getInnerMostAxes(axes.length, xRank); - xTransposed = - transpose({ inputs: { x }, attrs: { perm: permutedAxes }, backend }); - const xId = backend.dataIdMap.get(x.dataId).id; - const transposedId = backend.dataIdMap.get(xTransposed.dataId).id; - if (transposedId !== xId) { - inputWasTransposed = true; - } - } - return { transposed: xTransposed, originalAxes, axes, inputWasTransposed }; - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$1; - function setup$2(backend) { - wasmFunc$1 = backend.wasm.cwrap(tfjsCore.ArgMax, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number' // out_id - ]); - } - function argmax(args) { - const { backend, inputs, attrs } = args; - const { axis } = attrs; - const { x } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - let inputId = xId; - let input = x; - const { transposed, axes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); - if (inputWasTransposed) { - const transposedId = backend.dataIdMap.get(transposed.dataId).id; - if (transposedId !== xId) { - // transpose was not a no-op. We will need to dispose of this - // once we are done. - input = transposed; - inputId = transposedId; - } - } - const outShape = input.shape.slice(0, -1); - const out = backend.makeOutput(outShape, 'int32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const outerSize = tfjsCore.util.sizeFromShape(out.shape); - const innerSize = input.shape[axes[0]]; - wasmFunc$1(inputId, CppDType[input.dtype], outerSize, innerSize, outId); - if (inputWasTransposed) { - // dispose of the transposed tensor. - backend.disposeData(transposed.dataId); - } - return out; - } - const argMaxConfig = { - kernelName: tfjsCore.ArgMax, - backendName: 'wasm', - kernelFunc: argmax, - setupFunc: setup$2 - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmAvgPool; - function setup$3(backend) { - wasmAvgPool = backend.wasm.cwrap(tfjsCore.AvgPool, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function avgPool(args) { - const { inputs, attrs, backend } = args; - const x = inputs.x; - const xId = backend.dataIdMap.get(x.dataId).id; - const { filterSize, strides, pad, dimRoundingMode } = attrs; - const convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const channels = convInfo.inChannels; - if (convInfo.dataFormat !== 'channelsLast') { - throw new Error(`wasm backend does not support dataFormat:'` + - `${convInfo.dataFormat}'. Please use 'channelsLast'.`); - } - if (convInfo.dilationWidth !== 1 || convInfo.dilationHeight !== 1) { - throw new Error(`was backend only supports average pooling with dilation = [1, 1], ` + - `got [${convInfo.dilationHeight}, ${convInfo.dilationWidth}].`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmAvgPool(xId, x.shape[0], x.shape[1], x.shape[2], filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, strideHeight, strideWidth, channels, outId); - return out; - } - const avgPoolConfig = { - kernelName: tfjsCore.AvgPool, - backendName: 'wasm', - setupFunc: setup$3, - kernelFunc: avgPool - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmBatchMatMul; - function setup$4(backend) { - wasmBatchMatMul = backend.wasm.cwrap(tfjsCore.BatchMatMul, null /* void */, [ - 'number', - 'array', - 'number', - 'number', - 'array', - 'number', - 'number', - 'number', - 'number' // out_id - ]); - } - function batchMatMul(args) { - const { inputs, backend, attrs } = args; - const { a, b } = inputs; - if (a.dtype !== 'float32' || b.dtype !== 'float32') { - throw new Error(`BatchMatMul for non non-float32 tensors not yet supported.`); - } - const { transposeA, transposeB } = attrs; - const aId = backend.dataIdMap.get(a.dataId).id; - const bId = backend.dataIdMap.get(b.dataId).id; - const leftDim = transposeA ? a.shape[2] : a.shape[1]; - const rightDim = transposeB ? b.shape[1] : b.shape[2]; - const batchDim = a.shape[0]; - const out = backend.makeOutput([batchDim, leftDim, rightDim], a.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - const aShapeBytes = new Uint8Array(new Int32Array(a.shape).buffer); - const bShapeBytes = new Uint8Array(new Int32Array(b.shape).buffer); - wasmBatchMatMul(aId, aShapeBytes, a.shape.length, bId, bShapeBytes, b.shape.length, transposeA, transposeB, outId); - return out; - } - const batchMatMulConfig = { - kernelName: tfjsCore.BatchMatMul, - backendName: 'wasm', - setupFunc: setup$4, - kernelFunc: batchMatMul - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function cast(args) { - const { inputs: { x }, attrs: { dtype }, backend } = args; - const out = backend.makeOutput(x.shape, dtype); - const inVals = backend.typedArrayFromHeap(x); - const outVals = backend.typedArrayFromHeap(out); - outVals.set(inVals); - return out; - } - const castConfig = { - kernelName: tfjsCore.Cast, - backendName: 'wasm', - kernelFunc: cast, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmClip; - function setup$5(backend) { - wasmClip = backend.wasm.cwrap(tfjsCore.ClipByValue, null /* void */, [ - 'number', - 'number', - 'number', - 'number' // out_id - ]); - } - function clip(args) { - const { inputs, backend, attrs } = args; - const { x } = inputs; - const { clipValueMin, clipValueMax } = attrs; - const xId = backend.dataIdMap.get(x.dataId).id; - const out = backend.makeOutput(x.shape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmClip(xId, clipValueMin, clipValueMax, outId); - return out; - } - const clipByValueConfig = { - kernelName: tfjsCore.ClipByValue, - backendName: 'wasm', - setupFunc: setup$5, - kernelFunc: clip - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function concat(args) { - const { inputs, backend } = args; - const axis = tfjsCore.util.parseAxisParam(args.attrs.axis, inputs[0].shape)[0]; - const outShape = tfjsCore.backend_util.computeOutShape(inputs.map(t => t.shape), axis); - const out = backend.makeOutput(outShape, inputs[0].dtype); - const batchDim = tfjsCore.util.sizeFromShape(inputs[0].shape.slice(0, axis)); - let sumInnerDims = 0; - const innerDims = inputs.map(input => { - const innerDim = tfjsCore.util.sizeFromShape(input.shape.slice(axis)); - sumInnerDims += innerDim; - return innerDim; - }); - const inVals = inputs.map(input => backend.typedArrayFromHeap(input)); - const outVals = backend.typedArrayFromHeap(out); - for (let b = 0; b < batchDim; b++) { - let outOffset = b * sumInnerDims; - for (let i = 0; i < inVals.length; i++) { - const innerDim = innerDims[i]; - const inOffset = b * innerDim; - const vals = inVals[i].subarray(inOffset, inOffset + innerDim); - outVals.set(vals, outOffset); - outOffset += innerDim; - } - } - return out; - } - const concatConfig = { - kernelName: tfjsCore.Concat, - backendName: 'wasm', - kernelFunc: concat, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmConv2d; - function setup$6(backend) { - wasmConv2d = backend.wasm.cwrap(tfjsCore.Conv2D, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function conv2d(args) { - const { inputs, attrs, backend } = args; - const { x, filter } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - const filterId = backend.dataIdMap.get(filter.dataId).id; - const { strides, dilations, pad, dimRoundingMode, dataFormat } = attrs; - const $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat); - const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const dilationHeight = convInfo.dilationHeight; - const dilationWidth = convInfo.dilationWidth; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const inputChannels = convInfo.inChannels; - const outputChannels = convInfo.outChannels; - const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; - if (convInfo.dataFormat !== 'channelsLast') { - throw new Error(`wasm backend Conv2D does not support dataFormat:'` + - `${convInfo.dataFormat}'. Please use 'channelsLast'.`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmConv2d(xId, x.shape[0], x.shape[1], x.shape[2], filterId, filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); - return out; - } - const conv2DConfig = { - kernelName: tfjsCore.Conv2D, - backendName: 'wasm', - setupFunc: setup$6, - kernelFunc: conv2d - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmConv2DBackpropInput; - function setup$7(backend) { - wasmConv2DBackpropInput = backend.wasm.cwrap(tfjsCore.Conv2DBackpropInput, null, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function conv2DBackpropInput(args) { - const { backend, inputs, attrs } = args; - const { dy, filter } = inputs; - const { strides, pad, dataFormat, dimRoundingMode, inputShape } = attrs; - const dilations = 1; - const $dataFormat = tfjsCore.backend_util.convertConv2DDataFormat(dataFormat); - const convInfo = tfjsCore.backend_util.computeConv2DInfo(inputShape, filter.shape, strides, dilations, pad, dimRoundingMode, false /* depthwise */, $dataFormat); - const { batchSize, filterHeight, filterWidth, inChannels, inHeight, inWidth, outChannels, outHeight, outWidth, strideHeight, strideWidth } = convInfo; - const topPad = filterHeight - 1 - convInfo.padInfo.top; - const leftPad = filterWidth - 1 - convInfo.padInfo.left; - const isChannelsLast = convInfo.dataFormat === 'channelsLast'; - const dxStrides = tfjsCore.util.computeStrides(convInfo.inShape); - const dyStrides = tfjsCore.util.computeStrides(dy.shape); - const [fltS0, fltS1, fltS2] = tfjsCore.util.computeStrides(filter.shape); - const xBatchStride = dxStrides[0]; - const xRowStride = isChannelsLast ? dxStrides[1] : dxStrides[2]; - const xColStride = isChannelsLast ? dxStrides[2] : 1; - const xChannelStride = isChannelsLast ? 1 : dxStrides[1]; - const yBatchStride = dyStrides[0]; - const yRowStride = isChannelsLast ? dyStrides[1] : dyStrides[2]; - const yColStride = isChannelsLast ? dyStrides[2] : 1; - const yChannelStride = isChannelsLast ? 1 : dyStrides[1]; - const out = backend.makeOutput(convInfo.inShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const dyId = backend.dataIdMap.get(dy.dataId).id; - const filterId = backend.dataIdMap.get(filter.dataId).id; - wasmConv2DBackpropInput(dyId, filterId, batchSize, filterHeight, filterWidth, inHeight, inWidth, inChannels, outHeight, outWidth, outChannels, strideHeight, strideWidth, topPad, leftPad, fltS0, fltS1, fltS2, xBatchStride, xRowStride, xColStride, xChannelStride, yBatchStride, yRowStride, yColStride, yChannelStride, outId); - return out; - } - const conv2DBackpropInputConfig = { - kernelName: tfjsCore.Conv2DBackpropInput, - backendName: 'wasm', - setupFunc: setup$7, - kernelFunc: conv2DBackpropInput - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const cosConfig = createUnaryKernelConfig(tfjsCore.Cos); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // Must match enum in CropAndResize.cc - var InterpolationMethod; - (function (InterpolationMethod) { - InterpolationMethod[InterpolationMethod["bilinear"] = 0] = "bilinear"; - InterpolationMethod[InterpolationMethod["nearest"] = 1] = "nearest"; - })(InterpolationMethod || (InterpolationMethod = {})); - let wasmCropAndResize; - function setup$8(backend) { - wasmCropAndResize = backend.wasm.cwrap(tfjsCore.CropAndResize, null /*void*/, [ - 'number', - 'number', - 'number', - 'number', - 'array', - 'number', - 'number', - 'number', - 'number', - 'number' // out id - ]); - } - function cropAndResize(args) { - const { backend, inputs, attrs } = args; - const { method, extrapolationValue, cropSize } = attrs; - const { image, boxes, boxInd } = inputs; - const numBoxes = boxes.shape[0]; - const [cropHeight, cropWidth] = cropSize; - const outShape = [numBoxes, cropHeight, cropWidth, image.shape[3]]; - let imagesData = backend.dataIdMap.get(image.dataId); - let castedData; - if (image.dtype !== 'float32') { - castedData = cast({ backend, inputs: { x: image }, attrs: { dtype: 'float32' } }); - imagesData = backend.dataIdMap.get(castedData.dataId); - } - const imagesId = imagesData.id; - const boxesId = backend.dataIdMap.get(boxes.dataId).id; - const boxIndId = backend.dataIdMap.get(boxInd.dataId).id; - const out = backend.makeOutput(outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const imagesShapeBytes = new Uint8Array(new Int32Array(image.shape).buffer); - wasmCropAndResize(imagesId, boxesId, boxIndId, numBoxes, imagesShapeBytes, cropHeight, cropWidth, InterpolationMethod[method], extrapolationValue, outId); - if (castedData != null) { - backend.disposeData(castedData.dataId); - } - return out; - } - const cropAndResizeConfig = { - kernelName: tfjsCore.CropAndResize, - backendName: 'wasm', - setupFunc: setup$8, - kernelFunc: cropAndResize - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmDepthwiseConv2d; - function setup$9(backend) { - wasmDepthwiseConv2d = - backend.wasm.cwrap(tfjsCore.DepthwiseConv2dNative, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function depthwiseConv2d(args) { - const { inputs, attrs, backend } = args; - const { x, filter } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - const filterId = backend.dataIdMap.get(filter.dataId).id; - const { strides, dilations, pad, dimRoundingMode } = attrs; - const $dilations = dilations == null ? [1, 1] : dilations; - const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, $dilations, pad, dimRoundingMode, true /* depthwise */); - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const dilationHeight = convInfo.dilationHeight; - const dilationWidth = convInfo.dilationWidth; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const inputChannels = convInfo.inChannels; - const outputChannels = convInfo.outChannels; - const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; - if (convInfo.dataFormat !== 'channelsLast') { - throw new Error(`wasm backend DepthwiseConv2dNative does not support dataFormat:'` + - `${convInfo.dataFormat}'. Please use 'channelsLast'.`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmDepthwiseConv2d(xId, x.shape[0], x.shape[1], x.shape[2], filterId, filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); - return out; - } - const depthwiseConv2DNativeConfig = { - kernelName: tfjsCore.DepthwiseConv2dNative, - backendName: 'wasm', - setupFunc: setup$9, - kernelFunc: depthwiseConv2d - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$1 = true; - const divConfig = createBinaryKernelConfig(tfjsCore.Div, supportsFullBroadcast$1); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$2 = false; - const equalConfig = createBinaryKernelConfig(tfjsCore.Equal, supportsFullBroadcast$2, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const expConfig = createUnaryKernelConfig(tfjsCore.Exp); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function fill(args) { - const { attrs: { shape, value, dtype }, backend } = args; - const out = backend.makeOutput(shape, dtype); - const outVals = backend.typedArrayFromHeap(out); - outVals.fill(value); - return out; - } - const fillConfig = { - kernelName: tfjsCore.Fill, - backendName: 'wasm', - kernelFunc: fill, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$3 = false; - const floorDivConfig = createBinaryKernelConfig(tfjsCore.FloorDiv, supportsFullBroadcast$3); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmBatchNorm; - function setup$a(backend) { - wasmBatchNorm = backend.wasm.cwrap(tfjsCore.FusedBatchNorm, null /* void */, ['number', 'number', 'number', 'number', 'number', 'number', 'number']); - } - function fusedBatchNorm(args) { - const { backend, inputs, attrs } = args; - const { varianceEpsilon } = attrs; - const { x, mean, variance, offset, scale } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - const meanId = backend.dataIdMap.get(mean.dataId).id; - const varianceId = backend.dataIdMap.get(variance.dataId).id; - const offsetId = offset != null ? backend.dataIdMap.get(offset.dataId).id : 0; - const scaleId = scale != null ? backend.dataIdMap.get(scale.dataId).id : 0; - const out = backend.makeOutput(x.shape, x.dtype); - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(x.shape) === 0) { - return out; - } - const outId = backend.dataIdMap.get(out.dataId).id; - wasmBatchNorm(xId, meanId, varianceId, offsetId, scaleId, varianceEpsilon, outId); - return out; - } - const fusedBatchNormConfig = { - kernelName: tfjsCore.FusedBatchNorm, - backendName: 'wasm', - setupFunc: setup$a, - kernelFunc: fusedBatchNorm - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFusedConv2d; - function setup$b(backend) { - wasmFusedConv2d = backend.wasm.cwrap(tfjsCore.FusedConv2D, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function fusedConv2d(args) { - const { inputs, attrs, backend } = args; - const { x, filter, bias, preluActivationWeights } = inputs; - const { strides, pad, dilations, dataFormat, dimRoundingMode, activation } = attrs; - const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode); - const fusedActivation = FusableActivation[activation]; - if (fusedActivation == null) { - throw new Error(`${activation} activation not yet supported for FusedConv2D ` + - `in the wasm backend.`); - } - const xId = backend.dataIdMap.get(x.dataId).id; - const filterId = backend.dataIdMap.get(filter.dataId).id; - const outputChannels = convInfo.outChannels; - let biasId = 0; - if (bias != null) { - const biasData = backend.dataIdMap.get(bias.dataId); - if (biasData.shape.length !== 1) { - throw new Error(`FusedConv2D only supports rank-1 bias but got ` + - `rank ${biasData.shape.length}.`); - } - if (biasData.shape[0] !== outputChannels) { - throw new Error(`FusedConv2D bias shape (${biasData.shape}) does not ` + - `match the number of output channels (${outputChannels})`); - } - biasId = biasData.id; - } - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const dilationHeight = convInfo.dilationHeight; - const dilationWidth = convInfo.dilationWidth; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const inputChannels = convInfo.inChannels; - const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; - const batchSize = convInfo.batchSize; - const inHeight = convInfo.inHeight; - const inWidth = convInfo.inWidth; - if (dataFormat !== 'NHWC') { - throw new Error(`wasm backend FusedConv2D does not support dataFormat:'` + - `${dataFormat}'. Please use 'NHWC'.`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const preluActivationWeightsId = preluActivationWeights == null ? - 0 : - backend.dataIdMap.get(preluActivationWeights.dataId).id; - wasmFusedConv2d(xId, batchSize, inHeight, inWidth, filterId, filterHeight, filterWidth, biasId, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, fusedActivation, preluActivationWeightsId, outId); - return out; - } - const fusedConv2DConfig = { - kernelName: tfjsCore.FusedConv2D, - backendName: 'wasm', - setupFunc: setup$b, - kernelFunc: fusedConv2d - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFusedDepthwiseConv2d; - function setup$c(backend) { - wasmFusedDepthwiseConv2d = - backend.wasm.cwrap(tfjsCore.FusedDepthwiseConv2D, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function fusedDepthwiseConv2d(args) { - const { inputs, attrs, backend } = args; - const { x, filter, bias, preluActivationWeights } = inputs; - const { strides, pad, dilations, dataFormat, dimRoundingMode, activation } = attrs; - const convInfo = tfjsCore.backend_util.computeConv2DInfo(x.shape, filter.shape, strides, dilations, pad, dimRoundingMode, true /* depthwise */); - const fusedActivation = FusableActivation[activation]; - if (fusedActivation == null) { - throw new Error(`${activation} activation not yet supported for FusedDepthwiseConv2D ` + - `in the wasm backend.`); - } - const xId = backend.dataIdMap.get(x.dataId).id; - const filterId = backend.dataIdMap.get(filter.dataId).id; - const outputChannels = convInfo.outChannels; - let biasId = 0; - if (bias != null) { - const biasData = backend.dataIdMap.get(bias.dataId); - if (biasData.shape.length !== 1) { - throw new Error(`FusedDepthwiseConv2D only supports rank-1 bias but got ` + - `rank ${biasData.shape.length}.`); - } - if (biasData.shape[0] !== outputChannels) { - throw new Error(`FusedDepthwiseConv2D bias shape (${biasData.shape}) does not ` + - `match the number of output channels (${outputChannels})`); - } - biasId = biasData.id; - } - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const dilationHeight = convInfo.dilationHeight; - const dilationWidth = convInfo.dilationWidth; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const inputChannels = convInfo.inChannels; - const isSamePad = convInfo.padInfo.type === 'SAME' ? 1 : 0; - const batchSize = convInfo.batchSize; - const inHeight = convInfo.inHeight; - const inWidth = convInfo.inWidth; - if (dataFormat !== 'NHWC') { - throw new Error(`wasm backend FusedDepthwiseConv2D does not support dataFormat:'` + - `${dataFormat}'. Please use 'NHWC'.`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const preluActivationWeightsId = preluActivationWeights == null ? - 0 : - backend.dataIdMap.get(preluActivationWeights.dataId).id; - wasmFusedDepthwiseConv2d(xId, batchSize, inHeight, inWidth, filterId, filterHeight, filterWidth, biasId, padTop, padRight, padBottom, padLeft, isSamePad, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, fusedActivation, preluActivationWeightsId, outId); - return out; - } - const fusedDepthwiseConv2DConfig = { - kernelName: tfjsCore.FusedDepthwiseConv2D, - backendName: 'wasm', - setupFunc: setup$c, - kernelFunc: fusedDepthwiseConv2d - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmGatherNd; - function setup$d(backend) { - wasmGatherNd = backend.wasm.cwrap(tfjsCore.GatherNd, null /*void*/, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'array', - 'number' // outId - ]); - } - function gatherNd(args) { - const { backend, inputs } = args; - const { params, indices } = inputs; - const [resultShape, numSlices, sliceSize, strides] = tfjsCore.gather_util.prepareAndValidate(params, indices); - const out = backend.makeOutput(resultShape, params.dtype); - if (numSlices === 0) { - return out; - } - const indicesShape = indices.shape; - const sliceRank = indicesShape[indicesShape.length - 1]; - const xData = backend.dataIdMap.get(params.dataId); - const xId = xData.id; - const indicesData = backend.dataIdMap.get(indices.dataId); - const indicesId = indicesData.id; - const stridesBytes = new Uint8Array(new Int32Array(strides).buffer); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmGatherNd(xId, CppDType[params.dtype], indicesId, numSlices, sliceRank, sliceSize, stridesBytes, outId); - return out; - } - const gatherNdConfig = { - kernelName: tfjsCore.GatherNd, - backendName: 'wasm', - setupFunc: setup$d, - kernelFunc: gatherNd - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmGather; - function setup$e(backend) { - wasmGather = backend.wasm.cwrap('Gather', null /*void*/, [ - 'number', - 'number', - 'array', - 'number', - 'number', - 'number', - 'array', - 'number' // outId - ]); - } - function gatherV2(args) { - const { backend, inputs, attrs } = args; - const { x, indices } = inputs; - const { axis } = attrs; - const newShape = x.shape.slice(); - newShape[axis] = tfjsCore.util.sizeFromShape(indices.shape); - const stridesSize = x.shape.length - 1; - const out = backend.makeOutput(newShape, x.dtype); - if (tfjsCore.util.sizeFromShape(x.shape) === 0) { - return out; - } - const xData = backend.dataIdMap.get(x.dataId); - const xId = xData.id; - const indicesData = backend.dataIdMap.get(indices.dataId); - const indicesId = indicesData.id; - const outId = backend.dataIdMap.get(out.dataId).id; - const xStridesBytes = new Uint8Array(new Int32Array(tfjsCore.util.computeStrides(x.shape)).buffer); - const outStridesBytes = new Uint8Array(new Int32Array(tfjsCore.util.computeStrides(newShape)).buffer); - wasmGather(xId, CppDType[x.dtype], xStridesBytes, stridesSize, indicesId, axis, outStridesBytes, outId); - // reshape - const parsedAxis = tfjsCore.util.parseAxisParam(axis, x.shape)[0]; - const shapeInfo = tfjsCore.backend_util.segment_util.collectGatherOpShapeInfo(x, indices, parsedAxis); - out.shape = shapeInfo.outputShape; - return out; - } - const gatherV2Config = { - kernelName: tfjsCore.GatherV2, - backendName: 'wasm', - setupFunc: setup$e, - kernelFunc: gatherV2 - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$4 = false; - const greaterConfig = createBinaryKernelConfig(tfjsCore.Greater, supportsFullBroadcast$4, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$5 = false; - const greaterEqualConfig = createBinaryKernelConfig(tfjsCore.GreaterEqual, supportsFullBroadcast$5, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$6 = false; - const lessConfig = createBinaryKernelConfig(tfjsCore.Less, supportsFullBroadcast$6, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$7 = false; - const lessEqualConfig = createBinaryKernelConfig(tfjsCore.LessEqual, supportsFullBroadcast$7, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const logConfig = createUnaryKernelConfig(tfjsCore.Log); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$8 = false; - const logicalAndConfig = createBinaryKernelConfig(tfjsCore.LogicalAnd, supportsFullBroadcast$8, 'bool'); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmMax; - function setup$f(backend) { - wasmMax = backend.wasm.cwrap(tfjsCore.Max, null /*void*/, ['number, number, number']); - } - function max(args) { - const { backend, inputs, attrs } = args; - const { reductionIndices: axis, keepDims } = attrs; - const { x } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - let inputId = xId; - let input = x; - const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); - if (inputWasTransposed) { - const transposedId = backend.dataIdMap.get(transposed.dataId).id; - input = transposed; - inputId = transposedId; - } - const inputRank = input.shape.length; - tfjsCore.backend_util.assertAxesAreInnerMostDims('max', axes, inputRank); - const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, axes); - const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); - const out = backend.makeOutput(outShape, x.dtype); - if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { - const outId = backend.dataIdMap.get(out.dataId).id; - wasmMax(inputId, reduceSize, outId); - } - if (inputWasTransposed) { - // dispose of the transposed tensor. - backend.disposeData(transposed.dataId); - } - if (keepDims) { - // reshape - const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); - out.shape = newShape; - } - return out; - } - const maxConfig = { - kernelName: tfjsCore.Max, - backendName: 'wasm', - setupFunc: setup$f, - kernelFunc: max - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$9 = false; - const maximumConfig = createBinaryKernelConfig(tfjsCore.Maximum, supportsFullBroadcast$9); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmMaxPool; - function setup$g(backend) { - wasmMaxPool = backend.wasm.cwrap(tfjsCore.MaxPool, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function maxPool(args) { - const { inputs, attrs, backend } = args; - const x = inputs.x; - const xId = backend.dataIdMap.get(x.dataId).id; - const { filterSize, strides, pad, dimRoundingMode } = attrs; - const convInfo = tfjsCore.backend_util.computePool2DInfo(x.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); - const filterHeight = convInfo.filterHeight; - const filterWidth = convInfo.filterWidth; - const padTop = convInfo.padInfo.top; - const padRight = convInfo.padInfo.right; - const padBottom = convInfo.padInfo.bottom; - const padLeft = convInfo.padInfo.left; - const dilationHeight = convInfo.dilationHeight; - const dilationWidth = convInfo.dilationWidth; - const strideHeight = convInfo.strideHeight; - const strideWidth = convInfo.strideWidth; - const inputChannels = convInfo.inChannels; - const outputChannels = convInfo.outChannels; - if (convInfo.dataFormat !== 'channelsLast') { - throw new Error(`wasm backend does not support dataFormat:'` + - `${convInfo.dataFormat}'. Please use 'channelsLast'.`); - } - const out = backend.makeOutput(convInfo.outShape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmMaxPool(xId, x.shape[0], x.shape[1], x.shape[2], filterHeight, filterWidth, padTop, padRight, padBottom, padLeft, dilationHeight, dilationWidth, strideHeight, strideWidth, inputChannels, outputChannels, outId); - return out; - } - const maxPoolConfig = { - kernelName: tfjsCore.MaxPool, - backendName: 'wasm', - setupFunc: setup$g, - kernelFunc: maxPool - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmMin; - function setup$h(backend) { - wasmMin = backend.wasm.cwrap(tfjsCore.Min, null /*void*/, ['number, number, number']); - } - function min(args) { - const { backend, inputs, attrs } = args; - const { axis, keepDims } = attrs; - const { x } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - let inputId = xId; - let input = x; - const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); - if (inputWasTransposed) { - const transposedId = backend.dataIdMap.get(transposed.dataId).id; - if (transposedId !== xId) { - // transpose was not a no-op. We will need to dispose of this - // once we are done. - input = transposed; - inputId = transposedId; - } - } - const inputRank = input.shape.length; - tfjsCore.backend_util.assertAxesAreInnerMostDims('min', axes, inputRank); - const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, axes); - const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); - const out = backend.makeOutput(outShape, input.dtype); - if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { - const outId = backend.dataIdMap.get(out.dataId).id; - wasmMin(inputId, reduceSize, outId); - } - if (inputWasTransposed) { - // dispose of the transposed tensor. - backend.disposeData(transposed.dataId); - } - if (keepDims) { - // reshape - const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); - out.shape = newShape; - } - return out; - } - const minConfig = { - kernelName: tfjsCore.Min, - backendName: 'wasm', - setupFunc: setup$h, - kernelFunc: min - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$a = false; - const minimumConfig = createBinaryKernelConfig(tfjsCore.Minimum, supportsFullBroadcast$a); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$b = true; - const multiplyConfig = createBinaryKernelConfig(tfjsCore.Multiply, supportsFullBroadcast$b); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const negateConfig = createUnaryKernelConfig(tfjsCore.Negate); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Parse the result of the c++ method, which has the shape equivalent to - * `Result`. - */ - function parseResultStruct(backend, resOffset) { - const result = new Int32Array(backend.wasm.HEAPU8.buffer, resOffset, 4); - const pSelectedIndices = result[0]; - const selectedSize = result[1]; - const pSelectedScores = result[2]; - const pValidOutputs = result[3]; - // Since the result was allocated on the heap, we have to delete it. - backend.wasm._free(resOffset); - return { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs }; - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$2; - function setup$i(backend) { - wasmFunc$2 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV3, 'number', // Result* - [ - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function kernelFunc(args) { - const { backend, inputs, attrs } = args; - const { iouThreshold, maxOutputSize, scoreThreshold } = attrs; - const { boxes, scores } = inputs; - const boxesId = backend.dataIdMap.get(boxes.dataId).id; - const scoresId = backend.dataIdMap.get(scores.dataId).id; - const resOffset = wasmFunc$2(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold); - const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); - // Since we are not using scores for V3, we have to delete it from the heap. - backend.wasm._free(pSelectedScores); - backend.wasm._free(pValidOutputs); - const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); - return selectedIndicesTensor; - } - const nonMaxSuppressionV3Config = { - kernelName: tfjsCore.NonMaxSuppressionV3, - backendName: 'wasm', - setupFunc: setup$i, - kernelFunc: kernelFunc, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$3; - function setup$j(backend) { - wasmFunc$3 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV4, 'number', // Result* - [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'bool', - ]); - } - function nonMaxSuppressionV4(args) { - const { backend, inputs, attrs } = args; - const { iouThreshold, maxOutputSize, scoreThreshold, padToMaxOutputSize } = attrs; - const { boxes, scores } = inputs; - const boxesId = backend.dataIdMap.get(boxes.dataId).id; - const scoresId = backend.dataIdMap.get(scores.dataId).id; - const resOffset = wasmFunc$3(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold, padToMaxOutputSize); - const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); - // Since we are not using scores for V4, we have to delete it from the heap. - backend.wasm._free(pSelectedScores); - const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); - const validOutputsTensor = backend.makeOutput([], 'int32', pValidOutputs); - return [selectedIndicesTensor, validOutputsTensor]; - } - const nonMaxSuppressionV4Config = { - kernelName: tfjsCore.NonMaxSuppressionV4, - backendName: 'wasm', - setupFunc: setup$j, - kernelFunc: nonMaxSuppressionV4, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$4; - function setup$k(backend) { - wasmFunc$4 = backend.wasm.cwrap(tfjsCore.NonMaxSuppressionV5, 'number', // Result* - [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function kernelFunc$1(args) { - const { backend, inputs, attrs } = args; - const { iouThreshold, maxOutputSize, scoreThreshold, softNmsSigma } = attrs; - const { boxes, scores } = inputs; - const boxesId = backend.dataIdMap.get(boxes.dataId).id; - const scoresId = backend.dataIdMap.get(scores.dataId).id; - const resOffset = wasmFunc$4(boxesId, scoresId, maxOutputSize, iouThreshold, scoreThreshold, softNmsSigma); - const { pSelectedIndices, selectedSize, pSelectedScores, pValidOutputs } = parseResultStruct(backend, resOffset); - // Since we are not using validOutputs for V5, we have to delete it from the - // heap. - backend.wasm._free(pValidOutputs); - const selectedIndicesTensor = backend.makeOutput([selectedSize], 'int32', pSelectedIndices); - const selectedScoresTensor = backend.makeOutput([selectedSize], 'float32', pSelectedScores); - return [selectedIndicesTensor, selectedScoresTensor]; - } - const nonMaxSuppressionV5Config = { - kernelName: tfjsCore.NonMaxSuppressionV5, - backendName: 'wasm', - setupFunc: setup$k, - kernelFunc: kernelFunc$1, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$c = false; - const notEqualConfig = createBinaryKernelConfig(tfjsCore.NotEqual, supportsFullBroadcast$c, 'bool'); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmOneHot; - function setup$l(backend) { - wasmOneHot = backend.wasm.cwrap(tfjsCore.OneHot, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number' // out_id - ]); - } - function oneHot(args) { - const { inputs, backend, attrs } = args; - const { indices } = inputs; - const { depth, onValue, offValue } = attrs; - const out = backend.makeOutput([...indices.shape, depth], 'int32'); - const outId = backend.dataIdMap.get(out.dataId).id; - const indicesData = backend.dataIdMap.get(indices.dataId); - const indicesId = indicesData.id; - wasmOneHot(indicesId, depth, onValue, offValue, outId); - return out; - } - const oneHotConfig = { - kernelName: tfjsCore.OneHot, - backendName: 'wasm', - setupFunc: setup$l, - kernelFunc: oneHot, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function onesLike(args) { - const { inputs: { x }, backend } = args; - const out = backend.makeOutput(x.shape, x.dtype); - const outVals = backend.typedArrayFromHeap(out); - outVals.fill(1); - return out; - } - const onesLikeConfig = { - kernelName: tfjsCore.OnesLike, - backendName: 'wasm', - kernelFunc: onesLike, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmPadV2; - function setup$m(backend) { - wasmPadV2 = backend.wasm.cwrap(tfjsCore.PadV2, null /* void */, [ - 'number', - 'array', - 'number', - 'number', - 'array', - 'array', - 'number', - 'number', - ]); - } - function pad(args) { - const { inputs: { x }, backend, attrs: { paddings, constantValue } } = args; - const outShape = paddings.map((p, i) => p[0] /* beforePad */ + x.shape[i] + p[1] /* afterPad */); - const xId = backend.dataIdMap.get(x.dataId).id; - const out = backend.makeOutput(outShape, x.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); - const prePaddingsFlat = paddings.map(padTuple => padTuple[0]); - const postPaddingsFlat = paddings.map(padTuple => padTuple[1]); - const prePaddingsBytes = new Uint8Array(new Int32Array(prePaddingsFlat).buffer); - const postPaddingsBytes = new Uint8Array(new Int32Array(postPaddingsFlat).buffer); - wasmPadV2(xId, xShapeBytes, x.shape.length, CppDType[x.dtype], prePaddingsBytes, postPaddingsBytes, constantValue, outId); - return out; - } - const padV2Config = { - kernelName: tfjsCore.PadV2, - backendName: 'wasm', - kernelFunc: pad, - setupFunc: setup$m - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$d = false; - const powConfig = createBinaryKernelConfig(tfjsCore.Pow, supportsFullBroadcast$d); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmPrelu; - function setup$n(backend) { - wasmPrelu = backend.wasm.cwrap(tfjsCore.Prelu, null /* void */, [ - 'number', - 'number', - 'number' // out_id - ]); - } - function prelu(args) { - const { inputs, backend } = args; - const { x, alpha } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - const weightsId = backend.dataIdMap.get(alpha.dataId).id; - const out = backend.makeOutput(x.shape, 'float32'); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmPrelu(xId, weightsId, outId); - return out; - } - const preluConfig = { - kernelName: tfjsCore.Prelu, - backendName: 'wasm', - setupFunc: setup$n, - kernelFunc: prelu - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const reluConfig = createUnaryKernelConfig(tfjsCore.Relu); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const relu6Config = createUnaryKernelConfig(tfjsCore.Relu6); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function reshape(args) { - const { inputs, attrs } = args; - const { x } = inputs; - const { shape } = attrs; - return { dataId: x.dataId, shape, dtype: x.dtype }; - } - const reshapeConfig = { - kernelName: tfjsCore.Reshape, - backendName: 'wasm', - kernelFunc: reshape, - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmResizeBilinear; - function setup$o(backend) { - wasmResizeBilinear = backend.wasm.cwrap(tfjsCore.ResizeBilinear, null /*void*/, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number' // outId - ]); - } - function resizeBilinear(args) { - const { backend, inputs, attrs } = args; - const { images } = inputs; - const { alignCorners, size } = attrs; - const [newHeight, newWidth] = size; - const [batch, oldHeight, oldWidth, numChannels] = images.shape; - const outShape = [batch, newHeight, newWidth, numChannels]; - let xData = backend.dataIdMap.get(images.dataId); - let castedData; - if (xData.dtype !== 'float32') { - castedData = - cast({ backend, inputs: { x: images }, attrs: { dtype: 'float32' } }); - xData = backend.dataIdMap.get(castedData.dataId); - } - const xId = xData.id; - const out = backend.makeOutput(outShape, 'float32'); - if (tfjsCore.util.sizeFromShape(images.shape) === 0) { - return out; - } - const outId = backend.dataIdMap.get(out.dataId).id; - wasmResizeBilinear(xId, batch, oldHeight, oldWidth, numChannels, newHeight, newWidth, alignCorners ? 1 : 0, outId); - if (castedData != null) { - backend.disposeData(castedData.dataId); - } - return out; - } - const resizeBilinearConfig = { - kernelName: tfjsCore.ResizeBilinear, - backendName: 'wasm', - setupFunc: setup$o, - kernelFunc: resizeBilinear - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmReverse; - function setup$p(backend) { - wasmReverse = backend.wasm.cwrap(tfjsCore.Reverse, null, [ - 'number', - 'array', - 'number', - 'array', - 'number', - 'number' // out_id - ]); - } - function reverse(args) { - const { inputs, backend, attrs } = args; - const { x } = inputs; - const { dims } = attrs; - const axes = tfjsCore.util.parseAxisParam(dims, x.shape); - if (x.shape.length === 0) { - return identity({ inputs: { x }, backend }); - } - const out = backend.makeOutput(x.shape, x.dtype); - const xId = backend.dataIdMap.get(x.dataId).id; - const outId = backend.dataIdMap.get(out.dataId).id; - const axesBytes = new Uint8Array(new Int32Array(axes).buffer); - const outShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); - wasmReverse(xId, axesBytes, axes.length, outShapeBytes, x.shape.length, outId); - return reshape({ inputs: { x: out }, attrs: { shape: x.shape }, backend }); - } - const reverseConfig = { - kernelName: tfjsCore.Reverse, - backendName: 'wasm', - kernelFunc: reverse, - setupFunc: setup$p - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmRotate; - function setup$q(backend) { - wasmRotate = backend.wasm.cwrap(tfjsCore.RotateWithOffset, null /* void */, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'array', - 'number', - 'number', - ]); - } - function rotateWithOffset(args) { - const { inputs, backend, attrs } = args; - const { image } = inputs; - const { radians, fillValue, center } = attrs; - const out = backend.makeOutput(image.shape, image.dtype); - const imageId = backend.dataIdMap.get(image.dataId).id; - const outId = backend.dataIdMap.get(out.dataId).id; - const [batch, imageHeight, imageWidth, numChannels] = image.shape; - const [centerX, centerY] = tfjsCore.backend_util.getImageCenter(center, imageHeight, imageWidth); - const fillIsBlack = fillValue === 0; - const fullOpacityValue = 255; - const fillValues = typeof fillValue === 'number' ? - [fillValue, fillValue, fillValue, fillIsBlack ? 0 : fullOpacityValue] : - [...fillValue, fullOpacityValue]; - const fillBytes = new Uint8Array(new Int32Array(fillValues).buffer); - wasmRotate(imageId, batch, imageHeight, imageWidth, numChannels, radians, centerX, centerY, fillBytes, fillValues.length, outId); - return out; - } - const rotateWithOffsetConfig = { - kernelName: tfjsCore.RotateWithOffset, - backendName: 'wasm', - kernelFunc: rotateWithOffset, - setupFunc: setup$q - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const rsqrtConfig = createUnaryKernelConfig(tfjsCore.Rsqrt); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmScatterNd; - function setup$r(backend) { - wasmScatterNd = backend.wasm.cwrap(tfjsCore.ScatterNd, null /*void*/, [ - 'number', - 'number', - 'number', - 'number', - 'number', - 'number', - 'array', - 'number', - 'number' // outId - ]); - } - function scatterNd(args) { - const { backend, inputs, attrs } = args; - const { indices, updates } = inputs; - const { shape } = attrs; - const out = backend.makeOutput(shape, updates.dtype); - if (tfjsCore.util.sizeFromShape(shape) === 0) { - return out; - } - const { sliceRank, numUpdates, sliceSize, strides, outputSize } = tfjsCore.scatter_util.calculateShapes(updates, indices, shape); - const indicesData = backend.dataIdMap.get(indices.dataId); - const indicesId = indicesData.id; - const updatesData = backend.dataIdMap.get(updates.dataId); - const updatesId = updatesData.id; - const stridesBytes = new Uint8Array(new Int32Array(strides).buffer); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmScatterNd(indicesId, updatesId, CppDType[updates.dtype], sliceRank, numUpdates, sliceSize, stridesBytes, outputSize, outId); - return out; - } - const scatterNdConfig = { - kernelName: tfjsCore.ScatterNd, - backendName: 'wasm', - setupFunc: setup$r, - kernelFunc: scatterNd - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmSelect; - function setup$s(backend) { - wasmSelect = backend.wasm.cwrap(tfjsCore.SelectV2, null, [ - 'number', - 'number', - 'number', - 'number', - 'number', - ]); - } - function select(args) { - const { inputs, backend } = args; - const { condition, t, e } = inputs; - const conditionId = backend.dataIdMap.get(condition.dataId).id; - const tId = backend.dataIdMap.get(t.dataId).id; - const eId = backend.dataIdMap.get(e.dataId).id; - const out = backend.makeOutput(t.shape, t.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - const cRank = condition.shape.length; - const tRank = t.shape.length; - const offset = cRank === 0 || cRank > 1 || tRank === 1 ? - 1 : - tfjsCore.util.sizeFromShape(t.shape.slice(1)); - wasmSelect(conditionId, tId, eId, offset, outId); - return out; - } - const selectV2Config = { - kernelName: tfjsCore.SelectV2, - backendName: 'wasm', - kernelFunc: select, - setupFunc: setup$s - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$5; - function setup$t(backend) { - wasmFunc$5 = backend.wasm.cwrap(tfjsCore.Sigmoid, null /* void */, ['number', 'number']); - } - function sigmoid(args) { - const { backend, inputs: { x } } = args; - const xId = backend.dataIdMap.get(x.dataId).id; - const out = backend.makeOutput(x.shape, x.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(out.shape) === 0) { - return out; - } - wasmFunc$5(xId, outId); - return out; - } - const sigmoidConfig = { - kernelName: 'Sigmoid', - backendName: 'wasm', - setupFunc: setup$t, - kernelFunc: sigmoid - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const sinConfig = createUnaryKernelConfig(tfjsCore.Sin); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function slice(args) { - const { inputs: { x }, attrs: { begin, size }, backend } = args; - const [begin_, size_] = tfjsCore.slice_util.parseSliceParams(x, begin, size); - const isContinous = tfjsCore.slice_util.isSliceContinous(x.shape, begin_, size_); - const xVals = backend.typedArrayFromHeap(x); - const out = backend.makeOutput(size_, x.dtype); - const outVals = backend.typedArrayFromHeap(out); - const xStrides = tfjsCore.util.computeStrides(x.shape); - if (isContinous) { - const flatOffset = tfjsCore.slice_util.computeFlatOffset(begin_, xStrides); - outVals.set(xVals.subarray(flatOffset, flatOffset + tfjsCore.util.sizeFromShape(size_))); - return out; - } - const rank = x.shape.length; - if (rank === 2) { - slice2d(xVals, xStrides[0], outVals, begin_, size_); - } - else if (rank === 3) { - slice3d(xVals, xStrides[0], xStrides[1], outVals, begin_, size_); - } - else if (rank === 4) { - slice4d(xVals, xStrides[0], xStrides[1], xStrides[2], outVals, begin_, size_); - } - else { - genericSliceSlow(xVals, x, outVals, begin_, size_); - } - return out; - } - function slice2d(xVals, xStride, outVals, begin, size) { - let outOffset = 0; - const beginI = begin[0]; - const beginJ = begin[1]; - const endI = beginI + size[0]; - for (let i = beginI; i < endI; i++) { - const xOffset = i * xStride + beginJ; - outVals.set(xVals.subarray(xOffset, xOffset + size[1]), outOffset); - outOffset += size[1]; - } - } - function slice3d(xVals, xStride1, xStride2, outVals, begin, size) { - let outOffset = 0; - const beginI = begin[0]; - const beginJ = begin[1]; - const beginK = begin[2]; - const endI = beginI + size[0]; - const endJ = beginJ + size[1]; - for (let i = beginI; i < endI; i++) { - for (let j = beginJ; j < endJ; j++) { - const xOffset = i * xStride1 + j * xStride2 + beginK; - outVals.set(xVals.subarray(xOffset, xOffset + size[2]), outOffset); - outOffset += size[2]; - } - } - } - function slice4d(xVals, xStride1, xStride2, xStride3, outVals, begin, size) { - let outOffset = 0; - const beginI = begin[0]; - const beginJ = begin[1]; - const beginK = begin[2]; - const endI = beginI + size[0]; - const endJ = beginJ + size[1]; - const endK = beginK + size[2]; - const beginL = begin[3]; - for (let i = beginI; i < endI; i++) { - for (let j = beginJ; j < endJ; j++) { - for (let k = beginK; k < endK; k++) { - const xOffset = i * xStride1 + j * xStride2 + k * xStride3 + beginL; - outVals.set(xVals.subarray(xOffset, xOffset + size[3]), outOffset); - outOffset += size[3]; - } - } - } - } - function genericSliceSlow(xVals, xInfo, outVals, begin, size) { - const outBuf = tfjsCore.buffer(size, xInfo.dtype, outVals); - const xBuf = tfjsCore.buffer(xInfo.shape, xInfo.dtype, xVals); - for (let i = 0; i < outBuf.size; ++i) { - const loc = outBuf.indexToLoc(i); - const xLoc = loc.map((idx, j) => idx + begin[j]); - outVals[i] = xBuf.get(...xLoc); - } - } - const sliceConfig = { - kernelName: tfjsCore.Slice, - backendName: 'wasm', - kernelFunc: slice, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmFunc$6; - function setup$u(backend) { - wasmFunc$6 = backend.wasm.cwrap(tfjsCore.Softmax, null /* void */, [ - 'number', - 'number', - 'number', - 'number' // batch - ]); - } - function softmax(args) { - const { backend, inputs: { logits }, attrs: { dim } } = args; - const xId = backend.dataIdMap.get(logits.dataId).id; - const out = backend.makeOutput(logits.shape, logits.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - const channels = logits.shape[dim]; - const batch = tfjsCore.util.sizeFromShape(logits.shape) / channels; - // Short-circuit zero-sized tensors. - if (tfjsCore.util.sizeFromShape(out.shape) === 0) { - return out; - } - wasmFunc$6(xId, outId, channels, batch); - return out; - } - const softmaxConfig = { - kernelName: tfjsCore.Softmax, - backendName: 'wasm', - setupFunc: setup$u, - kernelFunc: softmax - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function split(args) { - const { inputs, attrs, backend } = args; - const { x } = inputs; - const { numOrSizeSplits, axis } = attrs; - const $axis = tfjsCore.util.parseAxisParam(axis, x.shape)[0]; - const splitSizes = tfjsCore.backend_util.prepareSplitSize(x, numOrSizeSplits, axis); - const begin = new Array(x.shape.length).fill(0); - const size = x.shape.slice(); - return splitSizes.map(s => { - const xSliceSize = [...size]; - xSliceSize[$axis] = s; - const xSlice = slice({ inputs: { x }, attrs: { begin, size: xSliceSize }, backend }); - begin[$axis] += s; - return xSlice; - }); - } - const splitVConfig = { - kernelName: tfjsCore.SplitV, - backendName: 'wasm', - kernelFunc: split - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const sqrtConfig = createUnaryKernelConfig(tfjsCore.Sqrt); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const squareConfig = createUnaryKernelConfig(tfjsCore.Square); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const supportsFullBroadcast$e = true; - const subConfig = createBinaryKernelConfig(tfjsCore.Sub, supportsFullBroadcast$e); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmSum; - function setup$v(backend) { - wasmSum = backend.wasm.cwrap(tfjsCore.Sum, null /*void*/, ['number, number, number']); - } - function sum(args) { - const { backend, inputs, attrs } = args; - const { axis, keepDims } = attrs; - const { x } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - let inputId = xId; - let input = x; - const { transposed, axes, originalAxes, inputWasTransposed } = permuteAxesAndTranspose(x, axis, backend); - let reductionAxes = axes; - if (inputWasTransposed) { - const transposedId = backend.dataIdMap.get(transposed.dataId).id; - if (transposedId !== xId) { - // transpose was not a no-op. We will need to dispose of this - // once we are done. - input = transposed; - inputId = transposedId; - reductionAxes = tfjsCore.backend_util.getInnerMostAxes(reductionAxes.length, input.shape.length); - } - } - tfjsCore.backend_util.assertAxesAreInnerMostDims('sum', reductionAxes, input.shape.length); - const [outShape, reduceShape] = tfjsCore.backend_util.computeOutAndReduceShapes(input.shape, reductionAxes); - const reduceSize = tfjsCore.util.sizeFromShape(reduceShape); - const out = backend.makeOutput(outShape, input.dtype); - if (tfjsCore.util.sizeFromShape(input.shape) !== 0) { - const outId = backend.dataIdMap.get(out.dataId).id; - wasmSum(inputId, reduceSize, outId); - } - if (inputWasTransposed) { - // dispose of the transposed tensor. - backend.disposeData(transposed.dataId); - } - if (keepDims) { - // reshape - const newShape = tfjsCore.backend_util.expandShapeToKeepDim(out.shape, originalAxes); - out.shape = newShape; - } - return out; - } - const sumConfig = { - kernelName: tfjsCore.Sum, - backendName: 'wasm', - setupFunc: setup$v, - kernelFunc: sum - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const tanhConfig = createUnaryKernelConfig(tfjsCore.Tanh); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - let wasmTile; - function setup$w(backend) { - wasmTile = backend.wasm.cwrap(tfjsCore.Tile, null /* void */, [ - 'number', - 'array', - 'number', - 'array', - 'number', - 'number' // out_id - ]); - } - function tile(args) { - const { inputs, backend, attrs } = args; - const { x } = inputs; - const xId = backend.dataIdMap.get(x.dataId).id; - const { reps } = attrs; - const newShape = new Array(x.shape.length); - for (let i = 0; i < newShape.length; i++) { - newShape[i] = x.shape[i] * reps[i]; - } - const xShapeBytes = new Uint8Array(new Int32Array(x.shape).buffer); - const newShapeBytes = new Uint8Array(new Int32Array(newShape).buffer); - const out = backend.makeOutput(newShape, x.dtype); - const outId = backend.dataIdMap.get(out.dataId).id; - wasmTile(xId, xShapeBytes, x.shape.length, newShapeBytes, newShape.length, CppDType[out.dtype], outId); - return out; - } - const tileConfig = { - kernelName: tfjsCore.Tile, - backendName: 'wasm', - setupFunc: setup$w, - kernelFunc: tile - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function unpack(args) { - const { inputs, backend, attrs } = args; - const { value } = inputs; - const { axis } = attrs; - const numOutputs = value.shape[axis]; - const rank = value.shape.length; - const outShape = new Array(rank - 1); - let outIndex = 0; - for (let i = 0; i < rank; i++) { - if (i !== axis) { - outShape[outIndex++] = value.shape[i]; - } - } - const outs = new Array(numOutputs); - const begin = new Array(rank).fill(0); - const size = value.shape.slice(); - size[axis] = 1; - for (let i = 0; i < outs.length; i++) { - begin[axis] = i; - outs[i] = slice({ inputs: { x: value }, attrs: { begin, size }, backend }); - } - return outs.map(({ dataId, dtype }) => ({ dataId, dtype, shape: outShape })); - } - const unpackConfig = { - kernelName: tfjsCore.Unpack, - backendName: 'wasm', - kernelFunc: unpack, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function zerosLike(args) { - const { inputs: { x }, backend } = args; - const out = backend.makeOutput(x.shape, x.dtype); - const outVals = backend.typedArrayFromHeap(out); - outVals.fill(0); - return out; - } - const zerosLikeConfig = { - kernelName: tfjsCore.ZerosLike, - backendName: 'wasm', - kernelFunc: zerosLike, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // List all kernel configs here - const kernelConfigs = [ - absConfig, - addConfig, - addNConfig, - argMaxConfig, - avgPoolConfig, - batchMatMulConfig, - castConfig, - clipByValueConfig, - concatConfig, - conv2DConfig, - conv2DBackpropInputConfig, - cosConfig, - cropAndResizeConfig, - depthwiseConv2DNativeConfig, - divConfig, - equalConfig, - expConfig, - fillConfig, - floorDivConfig, - fusedMatMulConfig, - fusedBatchNormConfig, - fusedConv2DConfig, - fusedDepthwiseConv2DConfig, - gatherNdConfig, - gatherV2Config, - greaterConfig, - greaterEqualConfig, - identityConfig, - lessConfig, - lessEqualConfig, - logConfig, - logicalAndConfig, - maxConfig, - maximumConfig, - maxPoolConfig, - minConfig, - minimumConfig, - multiplyConfig, - negateConfig, - nonMaxSuppressionV3Config, - nonMaxSuppressionV4Config, - nonMaxSuppressionV5Config, - notEqualConfig, - oneHotConfig, - onesLikeConfig, - padV2Config, - powConfig, - preluConfig, - reluConfig, - relu6Config, - reshapeConfig, - resizeBilinearConfig, - reverseConfig, - rotateWithOffsetConfig, - rsqrtConfig, - scatterNdConfig, - selectV2Config, - sigmoidConfig, - sinConfig, - sliceConfig, - softmaxConfig, - splitVConfig, - sqrtConfig, - squareConfig, - subConfig, - sumConfig, - tanhConfig, - tileConfig, - transposeConfig, - unpackConfig, - zerosLikeConfig - ]; - for (const kernelConfig of kernelConfigs) { - tfjsCore.registerKernel(kernelConfig); - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const ENV = tfjsCore.env(); - /** - * True if SIMD is supported. - */ - // From: https://github.com/GoogleChromeLabs/wasm-feature-detect - ENV.registerFlag('WASM_HAS_SIMD_SUPPORT', async () => WebAssembly.validate(new Uint8Array([ - 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, - 2, 1, 0, 10, 9, 1, 7, 0, 65, 0, 253, 15, 26, 11 - ]))); - /** - * True if threads are supported. - */ - // From: https://github.com/GoogleChromeLabs/wasm-feature-detect - ENV.registerFlag('WASM_HAS_MULTITHREAD_SUPPORT', async () => { - try { - // Test for transferability of SABs (needed for Firefox) - // https://groups.google.com/forum/#!msg/mozilla.dev.platform/IHkBZlHETpA/dwsMNchWEQAJ - new MessageChannel().port1.postMessage(new SharedArrayBuffer(1)); - return WebAssembly.validate(new Uint8Array([ - 0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 2, 1, 0, 5, - 4, 1, 3, 1, 1, 10, 11, 1, 9, 0, 65, 0, 254, 16, 2, 0, 26, 11 - ])); - } - catch (e) { - return false; - } - }); - - function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; - } - - var tfjsBackendWasmThreadedSimd = createCommonjsModule(function (module, exports) { - var WasmBackendModuleThreadedSimd = (function() { - var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; - if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; - return ( - function(WasmBackendModuleThreadedSimd) { - WasmBackendModuleThreadedSimd = WasmBackendModuleThreadedSimd || {}; - - function GROWABLE_HEAP_I8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP8}function GROWABLE_HEAP_U8(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU8}function GROWABLE_HEAP_I32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAP32}function GROWABLE_HEAP_U32(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPU32}function GROWABLE_HEAP_F64(){if(wasmMemory.buffer!=buffer){updateGlobalBufferAndViews(wasmMemory.buffer);}return HEAPF64}var Module=typeof WasmBackendModuleThreadedSimd!=="undefined"?WasmBackendModuleThreadedSimd:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var ENVIRONMENT_IS_PTHREAD=Module["ENVIRONMENT_IS_PTHREAD"]||false;if(ENVIRONMENT_IS_PTHREAD){buffer=Module["buffer"];DYNAMIC_BASE=Module["DYNAMIC_BASE"];DYNAMICTOP_PTR=Module["DYNAMICTOP_PTR"];}var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};var nodeWorkerThreads;try{nodeWorkerThreads=worker_threads;}catch(e){console.error('The "worker_threads" module is not supported in this node.js build - perhaps a newer version is needed?');throw e}Worker=nodeWorkerThreads.Worker;}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}if(ENVIRONMENT_IS_NODE){read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};}else{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}if(ENVIRONMENT_IS_NODE){if(typeof performance==="undefined"){performance=perf_hooks.performance;}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":165,"maximum":165+0,"element":"anyfunc"});var wasmModule;var threadInfoStruct=0;var selfThreadId=0;var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx)){var u0=heap[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heap[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heap[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2;}else{u0=(u0&7)<<18|u1<<12|u2<<6|heap[idx++]&63;}if(u0<65536){str+=String.fromCharCode(u0);}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023);}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(GROWABLE_HEAP_U8(),ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,GROWABLE_HEAP_U8(),outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4;}return len}function writeArrayToMemory(array,buffer){GROWABLE_HEAP_I8().set(array,buffer);}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple;}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var DYNAMIC_BASE=5256288,DYNAMICTOP_PTR=12480;var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;if(ENVIRONMENT_IS_PTHREAD){wasmMemory=Module["wasmMemory"];buffer=Module["buffer"];}else{if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"];}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":2147483648/WASM_PAGE_SIZE,"shared":true});if(!(wasmMemory.buffer instanceof SharedArrayBuffer)){err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");if(ENVIRONMENT_IS_NODE){console.log("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)");}throw Error("bad memory")}}}if(wasmMemory){buffer=wasmMemory.buffer;}INITIAL_INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);if(!ENVIRONMENT_IS_PTHREAD){GROWABLE_HEAP_I32()[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){if(ENVIRONMENT_IS_PTHREAD)return;callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(ENVIRONMENT_IS_PTHREAD)return;if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){assert(!ENVIRONMENT_IS_PTHREAD,"addRunDependency cannot be used in a pthread worker");runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}if(ENVIRONMENT_IS_PTHREAD)console.error("Pthread aborting at "+(new Error).stack);what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm-threaded-simd.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmModule=module;if(!ENVIRONMENT_IS_PTHREAD){var numWorkersToLoad=PThread.unusedWorkers.length;PThread.unusedWorkers.forEach(function(w){PThread.loadWasmModuleToWorker(w,function(){if(!--numWorkersToLoad)removeRunDependency();});});}}if(!ENVIRONMENT_IS_PTHREAD){addRunDependency();}function receiveInstantiatedSource(output){receiveInstance(output["instance"],output["module"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}var ASM_CONSTS={};function initPthreadsJS(){PThread.initRuntime();}if(!ENVIRONMENT_IS_PTHREAD)__ATINIT__.push({func:function(){___wasm_call_ctors();}});var __pthread_ptr=0;var __pthread_is_main_runtime_thread=0;var __pthread_is_main_browser_thread=0;function __register_pthread_ptr(pthreadPtr,isMainBrowserThread,isMainRuntimeThread){pthreadPtr=pthreadPtr|0;isMainBrowserThread=isMainBrowserThread|0;isMainRuntimeThread=isMainRuntimeThread|0;__pthread_ptr=pthreadPtr;__pthread_is_main_browser_thread=isMainBrowserThread;__pthread_is_main_runtime_thread=isMainRuntimeThread;}Module["__register_pthread_ptr"]=__register_pthread_ptr;var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var __main_thread_futex_wait_address=13392;function _emscripten_futex_wake(addr,count){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0||count<0)return -28;if(count==0)return 0;if(count>=2147483647)count=Infinity;var mainThreadWaitAddress=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);var mainThreadWoken=0;if(mainThreadWaitAddress==addr){var loadedAddr=Atomics.compareExchange(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,mainThreadWaitAddress,0);if(loadedAddr==mainThreadWaitAddress){--count;mainThreadWoken=1;if(count<=0)return 1}}var ret=Atomics.notify(GROWABLE_HEAP_I32(),addr>>2,count);if(ret>=0)return ret+mainThreadWoken;throw "Atomics.notify returned an unexpected value "+ret}Module["_emscripten_futex_wake"]=_emscripten_futex_wake;function __kill_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _kill_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _kill_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];pthread.worker.terminate();PThread.freeThreadData(pthread);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(pthread.worker),1);pthread.worker.pthread=undefined;}function __cancel_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cancel_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cancel_thread!";var pthread=PThread.pthreads[pthread_ptr];pthread.worker.postMessage({"cmd":"cancel"});}function __cleanup_thread(pthread_ptr){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _cleanup_thread() can only ever be called from main application thread!";if(!pthread_ptr)throw "Internal Error! Null pthread_ptr in _cleanup_thread!";GROWABLE_HEAP_I32()[pthread_ptr+12>>2]=0;var pthread=PThread.pthreads[pthread_ptr];if(pthread){var worker=pthread.worker;PThread.returnWorkerToPool(worker);}}var PThread={MAIN_THREAD_ID:1,mainThreadInfo:{schedPolicy:0,schedPrio:0},unusedWorkers:[],runningWorkers:[],initRuntime:function(){__register_pthread_ptr(PThread.mainThreadBlock,!ENVIRONMENT_IS_WORKER,1);_emscripten_register_main_browser_thread_id(PThread.mainThreadBlock);},initMainThreadBlock:function(){var pthreadPoolSize=8;for(var i=0;i>2]=PThread.mainThreadBlock;var headPtr=PThread.mainThreadBlock+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var tlsMemory=12880;for(var i=0;i<128;++i)GROWABLE_HEAP_U32()[tlsMemory/4+i]=0;Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+104>>2,tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+40>>2,PThread.mainThreadBlock);Atomics.store(GROWABLE_HEAP_U32(),PThread.mainThreadBlock+44>>2,42);},initWorker:function(){},pthreads:{},exitHandlers:null,setThreadStatus:function(){},runExitHandlers:function(){if(PThread.exitHandlers!==null){while(PThread.exitHandlers.length>0){PThread.exitHandlers.pop()();}PThread.exitHandlers=null;}if(ENVIRONMENT_IS_PTHREAD&&threadInfoStruct)___pthread_tsd_run_dtors();},threadExit:function(exitCode){var tb=_pthread_self();if(tb){Atomics.store(GROWABLE_HEAP_U32(),tb+4>>2,exitCode);Atomics.store(GROWABLE_HEAP_U32(),tb+0>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+60>>2,1);Atomics.store(GROWABLE_HEAP_U32(),tb+64>>2,0);PThread.runExitHandlers();_emscripten_futex_wake(tb+0,2147483647);__register_pthread_ptr(0,0,0);threadInfoStruct=0;if(ENVIRONMENT_IS_PTHREAD){postMessage({"cmd":"exit"});}}},threadCancel:function(){PThread.runExitHandlers();Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+4>>2,-1);Atomics.store(GROWABLE_HEAP_U32(),threadInfoStruct+0>>2,1);_emscripten_futex_wake(threadInfoStruct+0,2147483647);threadInfoStruct=selfThreadId=0;__register_pthread_ptr(0,0,0);postMessage({"cmd":"cancelDone"});},terminateAllThreads:function(){for(var t in PThread.pthreads){var pthread=PThread.pthreads[t];if(pthread&&pthread.worker){PThread.returnWorkerToPool(pthread.worker);}}PThread.pthreads={};for(var i=0;i>2];GROWABLE_HEAP_I32()[pthread.threadInfoStruct+104>>2]=0;_free(tlsMemory);_free(pthread.threadInfoStruct);}pthread.threadInfoStruct=0;if(pthread.allocatedOwnStack&&pthread.stackBase)_free(pthread.stackBase);pthread.stackBase=0;if(pthread.worker)pthread.worker.pthread=null;},returnWorkerToPool:function(worker){delete PThread.pthreads[worker.pthread.thread];PThread.unusedWorkers.push(worker);PThread.runningWorkers.splice(PThread.runningWorkers.indexOf(worker),1);PThread.freeThreadData(worker.pthread);worker.pthread=undefined;},receiveObjectTransfer:function(data){},loadWasmModuleToWorker:function(worker,onFinishedLoading){worker.onmessage=function(e){var d=e["data"];var cmd=d["cmd"];if(worker.pthread)PThread.currentProxiedOperationCallerThread=worker.pthread.threadInfoStruct;if(d["targetThread"]&&d["targetThread"]!=_pthread_self()){var thread=PThread.pthreads[d.targetThread];if(thread){thread.worker.postMessage(e.data,d["transferList"]);}else{console.error('Internal error! Worker sent a message "'+cmd+'" to target pthread '+d["targetThread"]+", but that thread no longer exists!");}PThread.currentProxiedOperationCallerThread=undefined;return}if(cmd==="processQueuedMainThreadWork"){_emscripten_main_thread_process_queued_calls();}else if(cmd==="spawnThread"){__spawn_thread(e.data);}else if(cmd==="cleanupThread"){__cleanup_thread(d["thread"]);}else if(cmd==="killThread"){__kill_thread(d["thread"]);}else if(cmd==="cancelThread"){__cancel_thread(d["thread"]);}else if(cmd==="loaded"){worker.loaded=true;if(onFinishedLoading)onFinishedLoading(worker);if(worker.runPthread){worker.runPthread();delete worker.runPthread;}}else if(cmd==="print"){out("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="printErr"){err("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="alert"){alert("Thread "+d["threadId"]+": "+d["text"]);}else if(cmd==="exit"){var detached=worker.pthread&&Atomics.load(GROWABLE_HEAP_U32(),worker.pthread.thread+68>>2);if(detached){PThread.returnWorkerToPool(worker);}}else if(cmd==="cancelDone"){PThread.returnWorkerToPool(worker);}else if(cmd==="objectTransfer"){PThread.receiveObjectTransfer(e.data);}else if(e.data.target==="setimmediate"){worker.postMessage(e.data);}else{err("worker sent an unknown command "+cmd);}PThread.currentProxiedOperationCallerThread=undefined;};worker.onerror=function(e){err("pthread sent an error! "+e.filename+":"+e.lineno+": "+e.message);};if(ENVIRONMENT_IS_NODE){worker.on("message",function(data){worker.onmessage({data:data});});worker.on("error",function(data){worker.onerror(data);});worker.on("exit",function(data){console.log("worker exited - TODO: update the worker queue?");});}worker.postMessage({"cmd":"load","urlOrBlob":Module["mainScriptUrlOrBlob"]||_scriptDir,"wasmMemory":wasmMemory,"wasmModule":wasmModule,"DYNAMIC_BASE":DYNAMIC_BASE,"DYNAMICTOP_PTR":DYNAMICTOP_PTR});},allocateUnusedWorker:function(){var pthreadMainJs=locateFile("tfjs-backend-wasm-threaded-simd.worker.js");PThread.unusedWorkers.push(new Worker(pthreadMainJs));},getNewWorker:function(){if(PThread.unusedWorkers.length==0){PThread.allocateUnusedWorker();PThread.loadWasmModuleToWorker(PThread.unusedWorkers[0]);}if(PThread.unusedWorkers.length>0)return PThread.unusedWorkers.pop();else return null},busySpinWait:function(msecs){var t=performance.now()+msecs;while(performance.now()>2]=value;return value}function _atexit(func,arg){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(1,1,func,arg);}function __emscripten_notify_thread_queue(targetThreadId,mainThreadId){if(targetThreadId==mainThreadId){postMessage({"cmd":"processQueuedMainThreadWork"});}else if(ENVIRONMENT_IS_PTHREAD){postMessage({"targetThread":targetThreadId,"cmd":"processThreadQueue"});}else{var pthread=PThread.pthreads[targetThreadId];var worker=pthread&&pthread.worker;if(!worker){return}worker.postMessage({"cmd":"processThreadQueue"});}return 1}function _abort(){abort();}function _emscripten_conditional_set_current_thread_status(expectedStatus,newStatus){}function _emscripten_futex_wait(addr,val,timeout){if(addr<=0||addr>GROWABLE_HEAP_I8().length||addr&3!=0)return -28;if(ENVIRONMENT_IS_WORKER){var ret=Atomics.wait(GROWABLE_HEAP_I32(),addr>>2,val,timeout);if(ret==="timed-out")return -73;if(ret==="not-equal")return -6;if(ret==="ok")return 0;throw "Atomics.wait returned an unexpected value "+ret}else{var loadedVal=Atomics.load(GROWABLE_HEAP_I32(),addr>>2);if(val!=loadedVal)return -6;var tNow=performance.now();var tEnd=tNow+timeout;Atomics.store(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2,addr);var ourWaitAddress=addr;while(addr==ourWaitAddress){tNow=performance.now();if(tNow>tEnd){return -73}_emscripten_main_thread_process_queued_calls();addr=Atomics.load(GROWABLE_HEAP_I32(),__main_thread_futex_wait_address>>2);}return 0}}function _emscripten_is_main_browser_thread(){return __pthread_is_main_browser_thread|0}function _emscripten_is_main_runtime_thread(){return __pthread_is_main_runtime_thread|0}function _emscripten_memcpy_big(dest,src,num){GROWABLE_HEAP_U8().copyWithin(dest,src,src+num);}function _emscripten_num_logical_cores(){return navigator["hardwareConcurrency"]}function _emscripten_proxy_to_main_thread_js(index,sync){var numCallArgs=arguments.length-2;var stack=stackSave();var args=stackAlloc(numCallArgs*8);var b=args>>3;for(var i=0;i>3]);buf+=8;}else{buf=buf+3&~3;args.push(GROWABLE_HEAP_I32()[buf>>2]);buf+=4;}}return args}function _emscripten_receive_on_main_thread_js(index,numCallArgs,args){_emscripten_receive_on_main_thread_js_callArgs.length=numCallArgs;var b=args>>3;for(var i=0;i>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();if(requestedSize<=oldSize){return false}var PAGE_MULTIPLE=65536;var maxHeapSize=2147483648;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),PAGE_MULTIPLE));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var JSEvents={keyEvent:0,mouseEvent:0,wheelEvent:0,uiEvent:0,focusEvent:0,deviceOrientationEvent:0,deviceMotionEvent:0,fullscreenChangeEvent:0,pointerlockChangeEvent:0,visibilityChangeEvent:0,touchEvent:0,previousFullscreenElement:null,previousScreenX:null,previousScreenY:null,removeEventListenersRegistered:false,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i);}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[];},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){JSEvents.removeEventListenersRegistered=true;}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence>2]=eventTypeId;GROWABLE_HEAP_I32()[varargs+4>>2]=eventData;GROWABLE_HEAP_I32()[varargs+8>>2]=userData;_emscripten_async_queue_on_thread_(targetThread,637534208,eventHandlerFunc,eventData,varargs);stackRestore(stackTop);},getTargetThreadForEventCallback:function(targetThread){switch(targetThread){case 1:return 0;case 2:return PThread.currentProxiedOperationCallerThread;default:return targetThread}},getNodeNameForTarget:function(target){if(!target)return "";if(target==window)return "#window";if(target==screen)return "#screen";return target&&target.nodeName?target.nodeName:""},fullscreenEnabled:function(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+1;var cString=_malloc(length);stringToUTF8(jsString,cString,length);return cString}function _emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height){var stackTop=stackSave();var varargs=stackAlloc(12);var targetCanvasPtr=0;if(targetCanvas){targetCanvasPtr=stringToNewUTF8(targetCanvas);}GROWABLE_HEAP_I32()[varargs>>2]=targetCanvasPtr;GROWABLE_HEAP_I32()[varargs+4>>2]=width;GROWABLE_HEAP_I32()[varargs+8>>2]=height;_emscripten_async_queue_on_thread_(targetThread,657457152,0,targetCanvasPtr,varargs);stackRestore(stackTop);}function _emscripten_set_offscreencanvas_size_on_target_thread(targetThread,targetCanvas,width,height){targetCanvas=targetCanvas?UTF8ToString(targetCanvas):"";_emscripten_set_offscreencanvas_size_on_target_thread_js(targetThread,targetCanvas,width,height);}function __maybeCStringToJsString(cString){return cString>2?UTF8ToString(cString):cString}var specialHTMLTargets=[0,typeof document!=="undefined"?document:0,typeof window!=="undefined"?window:0];function __findEventTarget(target){target=__maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!=="undefined"?document.querySelector(target):undefined);return domElement}function __findCanvasEventTarget(target){return __findEventTarget(target)}function _emscripten_set_canvas_element_size_calling_thread(target,width,height){var canvas=__findCanvasEventTarget(target);if(!canvas)return -4;if(canvas.canvasSharedPtr){GROWABLE_HEAP_I32()[canvas.canvasSharedPtr>>2]=width;GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+4>>2]=height;}if(canvas.offscreenCanvas||!canvas.controlTransferredOffscreen){if(canvas.offscreenCanvas)canvas=canvas.offscreenCanvas;var autoResizeViewport=false;if(canvas.GLctxObject&&canvas.GLctxObject.GLctx){var prevViewport=canvas.GLctxObject.GLctx.getParameter(2978);autoResizeViewport=prevViewport[0]===0&&prevViewport[1]===0&&prevViewport[2]===canvas.width&&prevViewport[3]===canvas.height;}canvas.width=width;canvas.height=height;if(autoResizeViewport){canvas.GLctxObject.GLctx.viewport(0,0,width,height);}}else if(canvas.canvasSharedPtr){var targetThread=GROWABLE_HEAP_I32()[canvas.canvasSharedPtr+8>>2];_emscripten_set_offscreencanvas_size_on_target_thread(targetThread,target,width,height);return 1}else{return -4}return 0}function _emscripten_set_canvas_element_size_main_thread(target,width,height){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(2,1,target,width,height);return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}function _emscripten_set_canvas_element_size(target,width,height){var canvas=__findCanvasEventTarget(target);if(canvas){return _emscripten_set_canvas_element_size_calling_thread(target,width,height)}else{return _emscripten_set_canvas_element_size_main_thread(target,width,height)}}function _emscripten_set_current_thread_status(newStatus){}function _emscripten_set_thread_name(threadId,name){}function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=function(index,divisor){ext["vertexAttribDivisorANGLE"](index,divisor);};ctx["drawArraysInstanced"]=function(mode,first,count,primcount){ext["drawArraysInstancedANGLE"](mode,first,count,primcount);};ctx["drawElementsInstanced"]=function(mode,count,type,indices,primcount){ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);};return 1}}function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=function(){return ext["createVertexArrayOES"]()};ctx["deleteVertexArray"]=function(vao){ext["deleteVertexArrayOES"](vao);};ctx["bindVertexArray"]=function(vao){ext["bindVertexArrayOES"](vao);};ctx["isVertexArray"]=function(vao){return ext["isVertexArrayOES"](vao)};return 1}}function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=function(n,bufs){ext["drawBuffersWEBGL"](n,bufs);};return 1}}var GL={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:{},currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],programInfos:{},stringCache:{},unpackAlignment:4,init:function(){var miniTempFloatBuffer=new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);for(var i=0;i>2]:-1;source+=UTF8ToString(GROWABLE_HEAP_I32()[string+i*4>>2],len<0?undefined:len);}return source},createContext:function(canvas,webGLContextAttributes){var ctx=canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=_malloc(8);GROWABLE_HEAP_I32()[handle+4>>2]=_pthread_self();var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context);}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return !(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;_free(GL.contexts[contextHandle].handle);GL.contexts[contextHandle]=null;},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;__webgl_enable_ANGLE_instanced_arrays(GLctx);__webgl_enable_OES_vertex_array_object(GLctx);__webgl_enable_WEBGL_draw_buffers(GLctx);GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query");var automaticallyEnabledExtensions=["OES_texture_float","OES_texture_half_float","OES_standard_derivatives","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBGL_depth_texture","OES_element_index_uint","EXT_texture_filter_anisotropic","EXT_frag_depth","WEBGL_draw_buffers","ANGLE_instanced_arrays","OES_texture_float_linear","OES_texture_half_float_linear","EXT_blend_minmax","EXT_shader_texture_lod","EXT_texture_norm16","WEBGL_compressed_texture_pvrtc","EXT_color_buffer_half_float","WEBGL_color_buffer_float","EXT_sRGB","WEBGL_compressed_texture_etc1","EXT_disjoint_timer_query","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_astc","EXT_color_buffer_float","WEBGL_compressed_texture_s3tc_srgb","EXT_disjoint_timer_query_webgl2","WEBKIT_WEBGL_compressed_texture_pvrtc"];var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext);}});},populateUniformTable:function(program){var p=GL.programs[program];var ptable=GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,35718);for(var i=0;i>2;contextAttributes["alpha"]=!!GROWABLE_HEAP_I32()[a+(0>>2)];contextAttributes["depth"]=!!GROWABLE_HEAP_I32()[a+(4>>2)];contextAttributes["stencil"]=!!GROWABLE_HEAP_I32()[a+(8>>2)];contextAttributes["antialias"]=!!GROWABLE_HEAP_I32()[a+(12>>2)];contextAttributes["premultipliedAlpha"]=!!GROWABLE_HEAP_I32()[a+(16>>2)];contextAttributes["preserveDrawingBuffer"]=!!GROWABLE_HEAP_I32()[a+(20>>2)];var powerPreference=GROWABLE_HEAP_I32()[a+(24>>2)];contextAttributes["powerPreference"]=__emscripten_webgl_power_preferences[powerPreference];contextAttributes["failIfMajorPerformanceCaveat"]=!!GROWABLE_HEAP_I32()[a+(28>>2)];contextAttributes.majorVersion=GROWABLE_HEAP_I32()[a+(32>>2)];contextAttributes.minorVersion=GROWABLE_HEAP_I32()[a+(36>>2)];contextAttributes.enableExtensionsByDefault=GROWABLE_HEAP_I32()[a+(40>>2)];contextAttributes.explicitSwapControl=GROWABLE_HEAP_I32()[a+(44>>2)];contextAttributes.proxyContextToMainThread=GROWABLE_HEAP_I32()[a+(48>>2)];contextAttributes.renderViaOffscreenBackBuffer=GROWABLE_HEAP_I32()[a+(52>>2)];var canvas=__findCanvasEventTarget(target);if(!canvas){return -4}if(contextAttributes.explicitSwapControl){return -1}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}function _emscripten_webgl_create_context(a0,a1){return _emscripten_webgl_do_create_context(a0,a1)}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=GROWABLE_HEAP_I32()[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(3,1,fd);return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(4,1,fd,offset_low,offset_high,whence,newOffset)}function _fd_write(fd,iov,iovcnt,pnum){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(5,1,fd,iov,iovcnt,pnum);var num=0;for(var i=0;i>2];var len=GROWABLE_HEAP_I32()[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _pthread_cleanup_pop(execute){var routine=PThread.exitHandlers.pop();if(execute)routine();}function _pthread_cleanup_push(routine,arg){if(PThread.exitHandlers===null){PThread.exitHandlers=[];}PThread.exitHandlers.push(function(){dynCall_vi(routine,arg);});}function __spawn_thread(threadParams){if(ENVIRONMENT_IS_PTHREAD)throw "Internal Error! _spawn_thread() can only ever be called from main application thread!";var worker=PThread.getNewWorker();if(worker.pthread!==undefined)throw "Internal error!";if(!threadParams.pthread_ptr)throw "Internal error, no pthread ptr!";PThread.runningWorkers.push(worker);var tlsMemory=_malloc(128*4);for(var i=0;i<128;++i){GROWABLE_HEAP_I32()[tlsMemory+i*4>>2]=0;}var stackHigh=threadParams.stackBase+threadParams.stackSize;var pthread=PThread.pthreads[threadParams.pthread_ptr]={worker:worker,stackBase:threadParams.stackBase,stackSize:threadParams.stackSize,allocatedOwnStack:threadParams.allocatedOwnStack,thread:threadParams.pthread_ptr,threadInfoStruct:threadParams.pthread_ptr};var tis=pthread.threadInfoStruct>>2;Atomics.store(GROWABLE_HEAP_U32(),tis+(0>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(4>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(8>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(68>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(104>>2),tlsMemory);Atomics.store(GROWABLE_HEAP_U32(),tis+(48>>2),0);Atomics.store(GROWABLE_HEAP_U32(),tis+(40>>2),pthread.threadInfoStruct);Atomics.store(GROWABLE_HEAP_U32(),tis+(44>>2),42);Atomics.store(GROWABLE_HEAP_U32(),tis+(108>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(84>>2),threadParams.stackSize);Atomics.store(GROWABLE_HEAP_U32(),tis+(80>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+8>>2),stackHigh);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+12>>2),threadParams.detached);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+20>>2),threadParams.schedPolicy);Atomics.store(GROWABLE_HEAP_U32(),tis+(108+24>>2),threadParams.schedPrio);var global_libc=_emscripten_get_global_libc();var global_locale=global_libc+40;Atomics.store(GROWABLE_HEAP_U32(),tis+(176>>2),global_locale);worker.pthread=pthread;var msg={"cmd":"run","start_routine":threadParams.startRoutine,"arg":threadParams.arg,"threadInfoStruct":threadParams.pthread_ptr,"selfThreadId":threadParams.pthread_ptr,"parentThreadId":threadParams.parent_pthread_ptr,"stackBase":threadParams.stackBase,"stackSize":threadParams.stackSize};worker.runPthread=function(){msg.time=performance.now();worker.postMessage(msg,threadParams.transferList);};if(worker.loaded){worker.runPthread();delete worker.runPthread;}}function _pthread_getschedparam(thread,policy,schedparam){if(!policy&&!schedparam)return ERRNO_CODES.EINVAL;if(!thread){err("pthread_getschedparam called with a null thread pointer!");return ERRNO_CODES.ESRCH}var self=GROWABLE_HEAP_I32()[thread+12>>2];if(self!==thread){err("pthread_getschedparam attempted on thread "+thread+", which does not point to a valid thread, or does not exist anymore!");return ERRNO_CODES.ESRCH}var schedPolicy=Atomics.load(GROWABLE_HEAP_U32(),thread+108+20>>2);var schedPrio=Atomics.load(GROWABLE_HEAP_U32(),thread+108+24>>2);if(policy)GROWABLE_HEAP_I32()[policy>>2]=schedPolicy;if(schedparam)GROWABLE_HEAP_I32()[schedparam>>2]=schedPrio;return 0}function _pthread_self(){return __pthread_ptr|0}Module["_pthread_self"]=_pthread_self;function _pthread_create(pthread_ptr,attr,start_routine,arg){if(typeof SharedArrayBuffer==="undefined"){err("Current environment does not support SharedArrayBuffer, pthreads are not available!");return 6}if(!pthread_ptr){err("pthread_create called with a null thread pointer!");return 28}var transferList=[];var error=0;if(ENVIRONMENT_IS_PTHREAD&&(transferList.length===0||error)){return _emscripten_sync_run_in_main_thread_4(687865856,pthread_ptr,attr,start_routine,arg)}var stackSize=0;var stackBase=0;var detached=0;var schedPolicy=0;var schedPrio=0;if(attr){stackSize=GROWABLE_HEAP_I32()[attr>>2];stackSize+=81920;stackBase=GROWABLE_HEAP_I32()[attr+8>>2];detached=GROWABLE_HEAP_I32()[attr+12>>2]!==0;var inheritSched=GROWABLE_HEAP_I32()[attr+16>>2]===0;if(inheritSched){var prevSchedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];var prevSchedPrio=GROWABLE_HEAP_I32()[attr+24>>2];var parentThreadPtr=PThread.currentProxiedOperationCallerThread?PThread.currentProxiedOperationCallerThread:_pthread_self();_pthread_getschedparam(parentThreadPtr,attr+20,attr+24);schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];GROWABLE_HEAP_I32()[attr+20>>2]=prevSchedPolicy;GROWABLE_HEAP_I32()[attr+24>>2]=prevSchedPrio;}else{schedPolicy=GROWABLE_HEAP_I32()[attr+20>>2];schedPrio=GROWABLE_HEAP_I32()[attr+24>>2];}}else{stackSize=2097152;}var allocatedOwnStack=stackBase==0;if(allocatedOwnStack){stackBase=_memalign(16,stackSize);}else{stackBase-=stackSize;assert(stackBase>0);}var threadInfoStruct=_malloc(232);for(var i=0;i<232>>2;++i)GROWABLE_HEAP_U32()[(threadInfoStruct>>2)+i]=0;GROWABLE_HEAP_I32()[pthread_ptr>>2]=threadInfoStruct;GROWABLE_HEAP_I32()[threadInfoStruct+12>>2]=threadInfoStruct;var headPtr=threadInfoStruct+156;GROWABLE_HEAP_I32()[headPtr>>2]=headPtr;var threadParams={stackBase:stackBase,stackSize:stackSize,allocatedOwnStack:allocatedOwnStack,schedPolicy:schedPolicy,schedPrio:schedPrio,detached:detached,startRoutine:start_routine,pthread_ptr:threadInfoStruct,parent_pthread_ptr:_pthread_self(),arg:arg,transferList:transferList};if(ENVIRONMENT_IS_PTHREAD){threadParams.cmd="spawnThread";postMessage(threadParams,transferList);}else{__spawn_thread(threadParams);}return 0}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}function _sysconf(name){if(ENVIRONMENT_IS_PTHREAD)return _emscripten_proxy_to_main_thread_js(6,1,name);switch(name){case 30:return 16384;case 85:var maxHeapSize=2147483648;return maxHeapSize/16384;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:case 79:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return -1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}setErrNo(28);return -1}if(!ENVIRONMENT_IS_PTHREAD)PThread.initMainThreadBlock();else PThread.initWorker();var GLctx;GL.init();var proxiedFunctionTable=[null,_atexit,_emscripten_set_canvas_element_size_main_thread,_fd_close,_fd_seek,_fd_write,_sysconf];var asmLibraryArg={"e":___assert_fail,"r":___call_main,"w":__emscripten_notify_thread_queue,"a":_abort,"l":_emscripten_conditional_set_current_thread_status,"d":_emscripten_futex_wait,"c":_emscripten_futex_wake,"h":_emscripten_get_now,"g":_emscripten_is_main_browser_thread,"x":_emscripten_is_main_runtime_thread,"q":_emscripten_memcpy_big,"B":_emscripten_num_logical_cores,"t":_emscripten_receive_on_main_thread_js,"A":_emscripten_resize_heap,"u":_emscripten_set_canvas_element_size,"k":_emscripten_set_current_thread_status,"s":_emscripten_set_thread_name,"v":_emscripten_webgl_create_context,"m":_fd_close,"o":_fd_seek,"i":_fd_write,"p":initPthreadsJS,"memory":wasmMemory||Module["wasmMemory"],"y":_pthread_cleanup_pop,"z":_pthread_cleanup_push,"j":_pthread_create,"b":_pthread_self,"f":_roundf,"n":_sysconf,"table":wasmTable};var asm=createWasm();Module["asm"]=asm;var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return (___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["C"]).apply(null,arguments)};var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["D"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["E"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["F"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["G"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["H"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["I"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["J"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["K"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["L"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["M"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["N"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["O"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["P"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["Q"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["R"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["S"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["T"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["U"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["V"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["W"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["X"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["Y"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["Z"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["_"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["$"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["aa"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["ba"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["ca"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["da"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["ea"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["fa"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["ga"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["ha"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["ia"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["ja"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["ka"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["la"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["ma"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["na"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["oa"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["pa"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["qa"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["ra"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["sa"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["ta"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["ua"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["va"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["wa"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["xa"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["ya"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["za"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["Aa"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["Ba"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["Ca"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["Da"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["Ea"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["Fa"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["Ga"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["Ha"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["Ia"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["Ja"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["Ka"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["La"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["Ma"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["Na"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["Oa"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["Pa"]).apply(null,arguments)};var ___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=function(){return (___em_js__initPthreadsJS=Module["___em_js__initPthreadsJS"]=Module["asm"]["Qa"]).apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){return (___errno_location=Module["___errno_location"]=Module["asm"]["Ra"]).apply(null,arguments)};var _emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=function(){return (_emscripten_get_global_libc=Module["_emscripten_get_global_libc"]=Module["asm"]["Sa"]).apply(null,arguments)};var _memalign=Module["_memalign"]=function(){return (_memalign=Module["_memalign"]=Module["asm"]["Ta"]).apply(null,arguments)};var ___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=function(){return (___pthread_tsd_run_dtors=Module["___pthread_tsd_run_dtors"]=Module["asm"]["Ua"]).apply(null,arguments)};var _emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=function(){return (_emscripten_main_thread_process_queued_calls=Module["_emscripten_main_thread_process_queued_calls"]=Module["asm"]["Va"]).apply(null,arguments)};var _emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=function(){return (_emscripten_current_thread_process_queued_calls=Module["_emscripten_current_thread_process_queued_calls"]=Module["asm"]["Wa"]).apply(null,arguments)};var _emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=function(){return (_emscripten_register_main_browser_thread_id=Module["_emscripten_register_main_browser_thread_id"]=Module["asm"]["Xa"]).apply(null,arguments)};var _emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=function(){return (_emscripten_main_browser_thread_id=Module["_emscripten_main_browser_thread_id"]=Module["asm"]["Ya"]).apply(null,arguments)};var _emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=function(){return (_emscripten_async_run_in_main_thread=Module["_emscripten_async_run_in_main_thread"]=Module["asm"]["Za"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=function(){return (_emscripten_sync_run_in_main_thread=Module["_emscripten_sync_run_in_main_thread"]=Module["asm"]["_a"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=function(){return (_emscripten_sync_run_in_main_thread_0=Module["_emscripten_sync_run_in_main_thread_0"]=Module["asm"]["$a"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=function(){return (_emscripten_sync_run_in_main_thread_1=Module["_emscripten_sync_run_in_main_thread_1"]=Module["asm"]["ab"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=function(){return (_emscripten_sync_run_in_main_thread_2=Module["_emscripten_sync_run_in_main_thread_2"]=Module["asm"]["bb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=function(){return (_emscripten_sync_run_in_main_thread_xprintf_varargs=Module["_emscripten_sync_run_in_main_thread_xprintf_varargs"]=Module["asm"]["cb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=function(){return (_emscripten_sync_run_in_main_thread_3=Module["_emscripten_sync_run_in_main_thread_3"]=Module["asm"]["db"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=function(){return (_emscripten_sync_run_in_main_thread_4=Module["_emscripten_sync_run_in_main_thread_4"]=Module["asm"]["eb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=function(){return (_emscripten_sync_run_in_main_thread_5=Module["_emscripten_sync_run_in_main_thread_5"]=Module["asm"]["fb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=function(){return (_emscripten_sync_run_in_main_thread_6=Module["_emscripten_sync_run_in_main_thread_6"]=Module["asm"]["gb"]).apply(null,arguments)};var _emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=function(){return (_emscripten_sync_run_in_main_thread_7=Module["_emscripten_sync_run_in_main_thread_7"]=Module["asm"]["hb"]).apply(null,arguments)};var _emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=function(){return (_emscripten_run_in_main_runtime_thread_js=Module["_emscripten_run_in_main_runtime_thread_js"]=Module["asm"]["ib"]).apply(null,arguments)};var _emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=function(){return (_emscripten_async_queue_on_thread_=Module["_emscripten_async_queue_on_thread_"]=Module["asm"]["jb"]).apply(null,arguments)};var _emscripten_tls_init=Module["_emscripten_tls_init"]=function(){return (_emscripten_tls_init=Module["_emscripten_tls_init"]=Module["asm"]["kb"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["lb"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["mb"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["nb"]).apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){return (dynCall_vi=Module["dynCall_vi"]=Module["asm"]["ob"]).apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){return (dynCall_v=Module["dynCall_v"]=Module["asm"]["pb"]).apply(null,arguments)};var dynCall_ii=Module["dynCall_ii"]=function(){return (dynCall_ii=Module["dynCall_ii"]=Module["asm"]["qb"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;Module["PThread"]=PThread;Module["PThread"]=PThread;Module["_pthread_self"]=_pthread_self;Module["wasmMemory"]=wasmMemory;Module["ExitStatus"]=ExitStatus;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}if(!ENVIRONMENT_IS_PTHREAD)noExitRuntime=true;if(!ENVIRONMENT_IS_PTHREAD)run(); - - - return WasmBackendModuleThreadedSimd - } - ); - })(); - module.exports = WasmBackendModuleThreadedSimd; - }); - - const wasmWorkerContents = 'var threadInfoStruct=0;var selfThreadId=0;var parentThreadId=0;var Module={};function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:selfThreadId})}var err=threadPrintErr;this.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);Module["wasmModule"]=null;receiveInstance(instance);return instance.exports};this.onmessage=function(e){try{if(e.data.cmd==="load"){Module["DYNAMIC_BASE"]=e.data.DYNAMIC_BASE;Module["DYNAMICTOP_PTR"]=e.data.DYNAMICTOP_PTR;Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;if(typeof e.data.urlOrBlob==="string"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}Module=WasmBackendModuleThreadedSimd(Module);postMessage({"cmd":"loaded"})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;threadInfoStruct=e.data.threadInfoStruct;Module["__register_pthread_ptr"](threadInfoStruct,0,0);selfThreadId=e.data.selfThreadId;parentThreadId=e.data.parentThreadId;var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["_emscripten_tls_init"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].setThreadStatus(Module["_pthread_self"](),1);try{var result=Module["dynCall_ii"](e.data.start_routine,e.data.arg);if(!Module["getNoExitRuntime"]())Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){Atomics.store(Module["HEAPU32"],threadInfoStruct+4>>2,ex instanceof Module["ExitStatus"]?ex.status:-2);Atomics.store(Module["HEAPU32"],threadInfoStruct+0>>2,1);Module["_emscripten_futex_wake"](threadInfoStruct+0,2147483647);if(!(ex instanceof Module["ExitStatus"]))throw ex}}}else if(e.data.cmd==="cancel"){if(threadInfoStruct){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(threadInfoStruct){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex.stack)err(ex.stack);throw ex}};if(typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string"){self={location:{href:__filename}};var onmessage=this.onmessage;var nodeWorkerThreads=require("worker_threads");Worker=nodeWorkerThreads.Worker;var parentPort=nodeWorkerThreads.parentPort;parentPort.on("message",function(data){onmessage({data:data})});var nodeFS=require("fs");var nodeRead=function(filename){return nodeFS.readFileSync(filename,"utf8")};function globalEval(x){global.require=require;global.Module=Module;eval.call(null,x)}importScripts=function(f){globalEval(nodeRead(f))};postMessage=function(msg){parentPort.postMessage(msg)};if(typeof performance==="undefined"){performance={now:function(){return Date.now()}}}}'; - - var tfjsBackendWasm = createCommonjsModule(function (module, exports) { - var WasmBackendModule = (function() { - var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; - if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; - return ( - function(WasmBackendModule) { - WasmBackendModule = WasmBackendModule || {}; - - var Module=typeof WasmBackendModule!=="undefined"?WasmBackendModule:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key];}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readBinary;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=path.dirname(scriptDirectory)+"/";}else{scriptDirectory=__dirname+"/";}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=fs;if(!nodePath)nodePath=path;filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret);}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/");}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status);};Module["inspect"]=function(){return "[Emscripten Module object]"};}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)};}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs;}else if(typeof arguments!="undefined"){arguments_=arguments;}if(typeof quit==="function"){quit_=function(status){quit(status);};}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print;}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href;}else if(document.currentScript){scriptDirectory=document.currentScript.src;}if(_scriptDir){scriptDirectory=_scriptDir;}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1);}else{scriptDirectory="";}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)};}}}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key];}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected");}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":147,"maximum":147+0,"element":"anyfunc"});var ABORT=false;function assert(condition,text){if(!condition){abort("Assertion failed: "+text);}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len);}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023);}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023;}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u;}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63;}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63;}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer);}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf);}var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func);}else{Module["dynCall_vi"](func,callback.arg);}}else{func(callback.arg===undefined?null:callback.arg);}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift());}}callRuntimeCallbacks(__ATPRERUN__);}function initRuntime(){callRuntimeCallbacks(__ATINIT__);}function preMain(){callRuntimeCallbacks(__ATMAIN__);}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift());}}callRuntimeCallbacks(__ATPOSTRUN__);}function addOnPreRun(cb){__ATPRERUN__.unshift(cb);}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb);}var Math_ceil=Math.ceil;var Math_floor=Math.floor;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies);}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null;}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback();}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what);}what+="";out(what);err(what);ABORT=true;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";throw new WebAssembly.RuntimeError(what)}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="tfjs-backend-wasm.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile);}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw "both async and sync fetching of the wasm failed"}}catch(err){abort(err);}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw "failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary());})}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=exports["memory"];updateGlobalBufferAndViews(wasmMemory.buffer);removeRunDependency();}addRunDependency();function receiveInstantiatedSource(output){receiveInstance(output["instance"]);}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason);})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource);})});}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return {}}__ATINIT__.push();function _emscripten_notify_memory_growth(memoryIndex){updateGlobalBufferAndViews(wasmMemory.buffer);}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0;}else{buffer.push(curr);}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _exit(status){exit(status);}function _proc_exit(code){_exit(code);}function _roundf(d){d=+d;return d>=+0?+Math_floor(d+ +.5):+Math_ceil(d-+.5)}var asmLibraryArg={"emscripten_notify_memory_growth":_emscripten_notify_memory_growth,"fd_close":_fd_close,"fd_seek":_fd_seek,"fd_write":_fd_write,"proc_exit":_proc_exit,"roundf":_roundf};var asm=createWasm();Module["asm"]=asm;var _init=Module["_init"]=function(){return (_init=Module["_init"]=Module["asm"]["init"]).apply(null,arguments)};var _register_tensor=Module["_register_tensor"]=function(){return (_register_tensor=Module["_register_tensor"]=Module["asm"]["register_tensor"]).apply(null,arguments)};var _dispose_data=Module["_dispose_data"]=function(){return (_dispose_data=Module["_dispose_data"]=Module["asm"]["dispose_data"]).apply(null,arguments)};var _dispose=Module["_dispose"]=function(){return (_dispose=Module["_dispose"]=Module["asm"]["dispose"]).apply(null,arguments)};var _Abs=Module["_Abs"]=function(){return (_Abs=Module["_Abs"]=Module["asm"]["Abs"]).apply(null,arguments)};var _Add=Module["_Add"]=function(){return (_Add=Module["_Add"]=Module["asm"]["Add"]).apply(null,arguments)};var _AddN=Module["_AddN"]=function(){return (_AddN=Module["_AddN"]=Module["asm"]["AddN"]).apply(null,arguments)};var _ArgMax=Module["_ArgMax"]=function(){return (_ArgMax=Module["_ArgMax"]=Module["asm"]["ArgMax"]).apply(null,arguments)};var _AvgPool=Module["_AvgPool"]=function(){return (_AvgPool=Module["_AvgPool"]=Module["asm"]["AvgPool"]).apply(null,arguments)};var _BatchMatMul=Module["_BatchMatMul"]=function(){return (_BatchMatMul=Module["_BatchMatMul"]=Module["asm"]["BatchMatMul"]).apply(null,arguments)};var _ClipByValue=Module["_ClipByValue"]=function(){return (_ClipByValue=Module["_ClipByValue"]=Module["asm"]["ClipByValue"]).apply(null,arguments)};var _Conv2D=Module["_Conv2D"]=function(){return (_Conv2D=Module["_Conv2D"]=Module["asm"]["Conv2D"]).apply(null,arguments)};var _Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=function(){return (_Conv2DBackpropInput=Module["_Conv2DBackpropInput"]=Module["asm"]["Conv2DBackpropInput"]).apply(null,arguments)};var _Cos=Module["_Cos"]=function(){return (_Cos=Module["_Cos"]=Module["asm"]["Cos"]).apply(null,arguments)};var _CropAndResize=Module["_CropAndResize"]=function(){return (_CropAndResize=Module["_CropAndResize"]=Module["asm"]["CropAndResize"]).apply(null,arguments)};var _DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=function(){return (_DepthwiseConv2dNative=Module["_DepthwiseConv2dNative"]=Module["asm"]["DepthwiseConv2dNative"]).apply(null,arguments)};var _Div=Module["_Div"]=function(){return (_Div=Module["_Div"]=Module["asm"]["Div"]).apply(null,arguments)};var _Equal=Module["_Equal"]=function(){return (_Equal=Module["_Equal"]=Module["asm"]["Equal"]).apply(null,arguments)};var _Exp=Module["_Exp"]=function(){return (_Exp=Module["_Exp"]=Module["asm"]["Exp"]).apply(null,arguments)};var _FloorDiv=Module["_FloorDiv"]=function(){return (_FloorDiv=Module["_FloorDiv"]=Module["asm"]["FloorDiv"]).apply(null,arguments)};var _FusedBatchNorm=Module["_FusedBatchNorm"]=function(){return (_FusedBatchNorm=Module["_FusedBatchNorm"]=Module["asm"]["FusedBatchNorm"]).apply(null,arguments)};var _FusedConv2D=Module["_FusedConv2D"]=function(){return (_FusedConv2D=Module["_FusedConv2D"]=Module["asm"]["FusedConv2D"]).apply(null,arguments)};var _FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=function(){return (_FusedDepthwiseConv2D=Module["_FusedDepthwiseConv2D"]=Module["asm"]["FusedDepthwiseConv2D"]).apply(null,arguments)};var _Gather=Module["_Gather"]=function(){return (_Gather=Module["_Gather"]=Module["asm"]["Gather"]).apply(null,arguments)};var _GatherNd=Module["_GatherNd"]=function(){return (_GatherNd=Module["_GatherNd"]=Module["asm"]["GatherNd"]).apply(null,arguments)};var _Greater=Module["_Greater"]=function(){return (_Greater=Module["_Greater"]=Module["asm"]["Greater"]).apply(null,arguments)};var _GreaterEqual=Module["_GreaterEqual"]=function(){return (_GreaterEqual=Module["_GreaterEqual"]=Module["asm"]["GreaterEqual"]).apply(null,arguments)};var _Less=Module["_Less"]=function(){return (_Less=Module["_Less"]=Module["asm"]["Less"]).apply(null,arguments)};var _LessEqual=Module["_LessEqual"]=function(){return (_LessEqual=Module["_LessEqual"]=Module["asm"]["LessEqual"]).apply(null,arguments)};var _Log=Module["_Log"]=function(){return (_Log=Module["_Log"]=Module["asm"]["Log"]).apply(null,arguments)};var _LogicalAnd=Module["_LogicalAnd"]=function(){return (_LogicalAnd=Module["_LogicalAnd"]=Module["asm"]["LogicalAnd"]).apply(null,arguments)};var _Max=Module["_Max"]=function(){return (_Max=Module["_Max"]=Module["asm"]["Max"]).apply(null,arguments)};var _MaxPool=Module["_MaxPool"]=function(){return (_MaxPool=Module["_MaxPool"]=Module["asm"]["MaxPool"]).apply(null,arguments)};var _Maximum=Module["_Maximum"]=function(){return (_Maximum=Module["_Maximum"]=Module["asm"]["Maximum"]).apply(null,arguments)};var _Min=Module["_Min"]=function(){return (_Min=Module["_Min"]=Module["asm"]["Min"]).apply(null,arguments)};var _Minimum=Module["_Minimum"]=function(){return (_Minimum=Module["_Minimum"]=Module["asm"]["Minimum"]).apply(null,arguments)};var _Multiply=Module["_Multiply"]=function(){return (_Multiply=Module["_Multiply"]=Module["asm"]["Multiply"]).apply(null,arguments)};var _Negate=Module["_Negate"]=function(){return (_Negate=Module["_Negate"]=Module["asm"]["Negate"]).apply(null,arguments)};var _NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=function(){return (_NonMaxSuppressionV3=Module["_NonMaxSuppressionV3"]=Module["asm"]["NonMaxSuppressionV3"]).apply(null,arguments)};var _NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=function(){return (_NonMaxSuppressionV4=Module["_NonMaxSuppressionV4"]=Module["asm"]["NonMaxSuppressionV4"]).apply(null,arguments)};var _NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=function(){return (_NonMaxSuppressionV5=Module["_NonMaxSuppressionV5"]=Module["asm"]["NonMaxSuppressionV5"]).apply(null,arguments)};var _NotEqual=Module["_NotEqual"]=function(){return (_NotEqual=Module["_NotEqual"]=Module["asm"]["NotEqual"]).apply(null,arguments)};var _OneHot=Module["_OneHot"]=function(){return (_OneHot=Module["_OneHot"]=Module["asm"]["OneHot"]).apply(null,arguments)};var _PadV2=Module["_PadV2"]=function(){return (_PadV2=Module["_PadV2"]=Module["asm"]["PadV2"]).apply(null,arguments)};var _Pow=Module["_Pow"]=function(){return (_Pow=Module["_Pow"]=Module["asm"]["Pow"]).apply(null,arguments)};var _Prelu=Module["_Prelu"]=function(){return (_Prelu=Module["_Prelu"]=Module["asm"]["Prelu"]).apply(null,arguments)};var _Relu=Module["_Relu"]=function(){return (_Relu=Module["_Relu"]=Module["asm"]["Relu"]).apply(null,arguments)};var _Relu6=Module["_Relu6"]=function(){return (_Relu6=Module["_Relu6"]=Module["asm"]["Relu6"]).apply(null,arguments)};var _ResizeBilinear=Module["_ResizeBilinear"]=function(){return (_ResizeBilinear=Module["_ResizeBilinear"]=Module["asm"]["ResizeBilinear"]).apply(null,arguments)};var _Reverse=Module["_Reverse"]=function(){return (_Reverse=Module["_Reverse"]=Module["asm"]["Reverse"]).apply(null,arguments)};var _RotateWithOffset=Module["_RotateWithOffset"]=function(){return (_RotateWithOffset=Module["_RotateWithOffset"]=Module["asm"]["RotateWithOffset"]).apply(null,arguments)};var _Rsqrt=Module["_Rsqrt"]=function(){return (_Rsqrt=Module["_Rsqrt"]=Module["asm"]["Rsqrt"]).apply(null,arguments)};var _ScatterNd=Module["_ScatterNd"]=function(){return (_ScatterNd=Module["_ScatterNd"]=Module["asm"]["ScatterNd"]).apply(null,arguments)};var _SelectV2=Module["_SelectV2"]=function(){return (_SelectV2=Module["_SelectV2"]=Module["asm"]["SelectV2"]).apply(null,arguments)};var _Sigmoid=Module["_Sigmoid"]=function(){return (_Sigmoid=Module["_Sigmoid"]=Module["asm"]["Sigmoid"]).apply(null,arguments)};var _Sin=Module["_Sin"]=function(){return (_Sin=Module["_Sin"]=Module["asm"]["Sin"]).apply(null,arguments)};var _Softmax=Module["_Softmax"]=function(){return (_Softmax=Module["_Softmax"]=Module["asm"]["Softmax"]).apply(null,arguments)};var _Sqrt=Module["_Sqrt"]=function(){return (_Sqrt=Module["_Sqrt"]=Module["asm"]["Sqrt"]).apply(null,arguments)};var _Square=Module["_Square"]=function(){return (_Square=Module["_Square"]=Module["asm"]["Square"]).apply(null,arguments)};var _Sub=Module["_Sub"]=function(){return (_Sub=Module["_Sub"]=Module["asm"]["Sub"]).apply(null,arguments)};var _Sum=Module["_Sum"]=function(){return (_Sum=Module["_Sum"]=Module["asm"]["Sum"]).apply(null,arguments)};var _Tanh=Module["_Tanh"]=function(){return (_Tanh=Module["_Tanh"]=Module["asm"]["Tanh"]).apply(null,arguments)};var _Tile=Module["_Tile"]=function(){return (_Tile=Module["_Tile"]=Module["asm"]["Tile"]).apply(null,arguments)};var _Transpose=Module["_Transpose"]=function(){return (_Transpose=Module["_Transpose"]=Module["asm"]["Transpose"]).apply(null,arguments)};var __FusedMatMul=Module["__FusedMatMul"]=function(){return (__FusedMatMul=Module["__FusedMatMul"]=Module["asm"]["_FusedMatMul"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return (_malloc=Module["_malloc"]=Module["asm"]["malloc"]).apply(null,arguments)};var _free=Module["_free"]=function(){return (_free=Module["_free"]=Module["asm"]["free"]).apply(null,arguments)};var __start=Module["__start"]=function(){return (__start=Module["__start"]=Module["asm"]["_start"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return (stackSave=Module["stackSave"]=Module["asm"]["stackSave"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return (stackAlloc=Module["stackAlloc"]=Module["asm"]["stackAlloc"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return (stackRestore=Module["stackRestore"]=Module["asm"]["stackRestore"]).apply(null,arguments)};Module["asm"]=asm;Module["cwrap"]=cwrap;var calledRun;Module["then"]=function(func){if(calledRun){func(Module);}else{var old=Module["onRuntimeInitialized"];Module["onRuntimeInitialized"]=function(){if(old)old();func(Module);};}return Module};function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status;}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller;};function callMain(args){var entryFunction=Module["__start"];try{entryFunction();var ret=0;exit(ret,true);}catch(e){if(e instanceof ExitStatus){return}else if(e=="unwind"){noExitRuntime=true;return}else{var toLog=e;if(e&&typeof e==="object"&&e.stack){toLog=[e,e.stack];}err("exception thrown: "+toLog);quit_(1,e);}}finally{}}function run(args){if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain();postRun();}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("");},1);doRun();},1);}else{doRun();}}Module["run"]=run;function exit(status,implicit){if(implicit&&noExitRuntime&&status===0){return}if(noExitRuntime);else{ABORT=true;if(Module["onExit"])Module["onExit"](status);}quit_(status,new ExitStatus(status));}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()();}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;noExitRuntime=true;run(); - - - return WasmBackendModule - } - ); - })(); - module.exports = WasmBackendModule; - }); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - const WASM_PRIORITY = 2; - class BackendWasm extends tfjsCore.KernelBackend { - constructor(wasm) { - super(); - this.wasm = wasm; - // 0 is reserved for null data ids. - this.dataIdNextNumber = 1; - this.wasm.tfjs.init(); - this.dataIdMap = new tfjsCore.DataStorage(this, tfjsCore.engine()); - } - write(values, shape, dtype) { - const dataId = {}; - this.move(dataId, values, shape, dtype); - return dataId; - } - numDataIds() { - return this.dataIdMap.numDataIds(); - } - async time(f) { - const start = tfjsCore.util.now(); - f(); - const kernelMs = tfjsCore.util.now() - start; - return { kernelMs }; - } - move(dataId, values, shape, dtype) { - const id = this.dataIdNextNumber++; - if (dtype === 'string') { - const stringBytes = values; - this.dataIdMap.set(dataId, { id, stringBytes, shape, dtype, memoryOffset: null }); - return; - } - const size = tfjsCore.util.sizeFromShape(shape); - const numBytes = size * tfjsCore.util.bytesPerElement(dtype); - const memoryOffset = this.wasm._malloc(numBytes); - this.dataIdMap.set(dataId, { id, memoryOffset, shape, dtype }); - this.wasm.tfjs.registerTensor(id, size, memoryOffset); - if (values != null) { - this.wasm.HEAPU8.set(new Uint8Array(values.buffer, values.byteOffset, numBytes), memoryOffset); - } - } - async read(dataId) { - return this.readSync(dataId); - } - readSync(dataId) { - const { memoryOffset, dtype, shape, stringBytes } = this.dataIdMap.get(dataId); - if (dtype === 'string') { - return stringBytes; - } - const bytes = this.wasm.HEAPU8.slice(memoryOffset, memoryOffset + tfjsCore.util.sizeFromShape(shape) * tfjsCore.util.bytesPerElement(dtype)); - return typedArrayFromBuffer(bytes.buffer, dtype); - } - disposeData(dataId) { - const data = this.dataIdMap.get(dataId); - this.wasm._free(data.memoryOffset); - this.wasm.tfjs.disposeData(data.id); - this.dataIdMap.delete(dataId); - } - floatPrecision() { - return 32; - } - // Returns the memory offset of a tensor. Useful for debugging and unit - // testing. - getMemoryOffset(dataId) { - return this.dataIdMap.get(dataId).memoryOffset; - } - dispose() { - this.wasm.tfjs.dispose(); - this.wasm = null; - } - memory() { - return { unreliable: false }; - } - /** - * Make a tensor info for the output of an op. If `memoryOffset` is not - * present, this method allocates memory on the WASM heap. If `memoryOffset` - * is present, the memory was allocated elsewhere (in c++) and we just record - * the pointer where that memory lives. - */ - makeOutput(shape, dtype, memoryOffset) { - let dataId; - if (memoryOffset == null) { - dataId = this.write(null /* values */, shape, dtype); - } - else { - dataId = {}; - const id = this.dataIdNextNumber++; - this.dataIdMap.set(dataId, { id, memoryOffset, shape, dtype }); - const size = tfjsCore.util.sizeFromShape(shape); - this.wasm.tfjs.registerTensor(id, size, memoryOffset); - } - return { dataId, shape, dtype }; - } - typedArrayFromHeap({ shape, dtype, dataId }) { - const buffer = this.wasm.HEAPU8.buffer; - const { memoryOffset } = this.dataIdMap.get(dataId); - const size = tfjsCore.util.sizeFromShape(shape); - switch (dtype) { - case 'float32': - return new Float32Array(buffer, memoryOffset, size); - case 'int32': - return new Int32Array(buffer, memoryOffset, size); - case 'bool': - return new Uint8Array(buffer, memoryOffset, size); - default: - throw new Error(`Uknown dtype ${dtype}`); - } - } - } - tfjsCore.registerBackend('wasm', async () => { - const { wasm } = await init(); - return new BackendWasm(wasm); - }, WASM_PRIORITY); - function createInstantiateWasmFunc(path) { - // tslint:disable-next-line:no-any - return (imports, callback) => { - tfjsCore.util.fetch(path, { credentials: 'same-origin' }).then((response) => { - if (!response['ok']) { - imports.env.a(`failed to load wasm binary file at '${path}'`); - } - response.arrayBuffer().then(binary => { - WebAssembly.instantiate(binary, imports).then(output => { - callback(output.instance); - }); - }); - }); - return {}; - }; - } - /** - * Initializes the wasm module and creates the js <--> wasm bridge. - * - * NOTE: We wrap the wasm module in a object with property 'wasm' instead of - * returning Promise to avoid freezing Chrome (last tested - * in Chrome 76). - */ - async function init() { - const [simdSupported, threadsSupported] = await Promise.all([ - tfjsCore.env().getAsync('WASM_HAS_SIMD_SUPPORT'), - tfjsCore.env().getAsync('WASM_HAS_MULTITHREAD_SUPPORT') - ]); - return new Promise((resolve, reject) => { - const factoryConfig = {}; - /** - * This function overrides the Emscripten module locateFile utility. - * @param path The relative path to the file that needs to be loaded. - * @param prefix The path to the main JavaScript file's directory. - */ - factoryConfig.locateFile = (path, prefix) => { - if (path.endsWith('.worker.js')) { - const response = wasmWorkerContents; - const blob = new Blob([response], { type: 'application/javascript' }); - return URL.createObjectURL(blob); - } - if (path.endsWith('.wasm')) { - if (wasmPath != null) { - // If wasmPath is defined, the user has supplied a full path to - // the .wasm binary. - return wasmPath; - } - if (simdSupported && threadsSupported) { - return prefix + 'tfjs-backend-wasm-threaded-simd.wasm'; - } - if (simdSupported) { - return prefix + 'tfjs-backend-wasm-simd.wasm'; - } - return prefix + 'tfjs-backend-wasm.wasm'; - } - return prefix + path; - }; - if (wasmPath != null) { - // use wasm instantiateWasm override when system fetch is not available. - // For detail references - // https://github.com/emscripten-core/emscripten/blob/2bca083cbbd5a4133db61fbd74d04f7feecfa907/tests/manual_wasm_instantiate.html#L170 - if (customFetch) { - factoryConfig.instantiateWasm = createInstantiateWasmFunc(wasmPath); - } - } - let wasm; - // There is currently no way to specify custom WASM paths to multiple - // binaries, so if `wasmPath` has been defined we must initialize the - // vanilla module. - // TODO(annxingyuan): remove `wasmPath == null` constraint once users are - // able to define a custom prefix to multiple WASM binaries - // (https://github.com/tensorflow/tfjs/issues/3718). - if (threadsSupported && simdSupported && wasmPath == null) { - wasm = tfjsBackendWasmThreadedSimd(factoryConfig); - wasm.mainScriptUrlOrBlob = new Blob([`var _scriptDir = undefined; var WasmBackendModuleThreadedSimd = ` + - tfjsBackendWasmThreadedSimd.toString()], { type: 'text/javascript' }); - } - else { - // The wasmFactory works for both vanilla and SIMD binaries. - wasm = tfjsBackendWasm(factoryConfig); - } - const voidReturnType = null; - // Using the tfjs namespace to avoid conflict with emscripten's API. - wasm.tfjs = { - init: wasm.cwrap('init', null, []), - registerTensor: wasm.cwrap('register_tensor', null, [ - 'number', - 'number', - 'number', - ]), - disposeData: wasm.cwrap('dispose_data', voidReturnType, ['number']), - dispose: wasm.cwrap('dispose', voidReturnType, []), - }; - let initialized = false; - wasm.onRuntimeInitialized = () => { - initialized = true; - initAborted = false; - resolve({ wasm }); - }; - wasm.onAbort = () => { - if (initialized) { - // Emscripten already called console.warn so no need to double log. - return; - } - if (initAborted) { - // Emscripten calls `onAbort` twice, resulting in double error - // messages. - return; - } - initAborted = true; - const rejectMsg = 'Make sure the server can serve the `.wasm` file relative to the ' + - 'bundled js file. For more details see https://github.com/tensorflow/tfjs/blob/master/tfjs-backend-wasm/README.md#using-bundlers'; - reject({ message: rejectMsg }); - }; - }); - } - function typedArrayFromBuffer(buffer, dtype) { - switch (dtype) { - case 'float32': - return new Float32Array(buffer); - case 'int32': - return new Int32Array(buffer); - case 'bool': - return new Uint8Array(buffer); - default: - throw new Error(`Unknown dtype ${dtype}`); - } - } - let wasmPath = null; - let initAborted = false; - let customFetch = false; - /** - * Sets the path to the `.wasm` file which will be fetched when the wasm - * backend is initialized. See - * https://github.com/tensorflow/tfjs/blob/master/tfjs-backend-wasm/README.md#using-bundlers - * for more details. - * @param path wasm file path or url - * @param usePlatformFetch optional boolean to use platform fetch to download - * the wasm file, default to false. - */ - /** @doc {heading: 'Environment', namespace: 'wasm'} */ - function setWasmPath(path, usePlatformFetch = false) { - if (initAborted) { - throw new Error('The WASM backend was already initialized. Make sure you call ' + - '`setWasmPath()` before you call `tf.setBackend()` or `tf.ready()`'); - } - wasmPath = path; - customFetch = usePlatformFetch; - } - - /** @license See the LICENSE file. */ - // This code is auto-generated, do not modify this file! - const version = '0.0.0'; - - exports.BackendWasm = BackendWasm; - exports.setWasmPath = setWasmPath; - exports.version_wasm = version; - - Object.defineProperty(exports, '__esModule', { value: true }); - -}))); -//# sourceMappingURL=tf-backend-wasm.js.map diff --git a/e2e/benchmarks/tfjs-backend-wasm-simd.wasm b/e2e/benchmarks/tfjs-backend-wasm-simd.wasm deleted file mode 100644 index e7f9e0d22cb7e43fecadb341e033f8df426f9456..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 214314 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

    m%oxI;;pBjvUPJo+t)>z^0+8d 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 diff --git a/e2e/benchmarks/tfjs-backend-wasm.wasm b/e2e/benchmarks/tfjs-backend-wasm.wasm deleted file mode 100644 index b10a1a4f5b8b27b6409d26b4682f7b8b04632694..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 155831 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%0A6A|=Zo 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 WR@*czF(T>he^3fAs$;Qs=7PFPF; From a0dd945884836dfcc1401c2b99a63c4af666070d Mon Sep 17 00:00:00 2001 From: Ann Yuan Date: Mon, 3 Aug 2020 10:19:17 -0400 Subject: [PATCH 46/70] remove --- e2e/benchmarks/tf-core.js | 32471 ------------------------------------ 1 file changed, 32471 deletions(-) delete mode 100644 e2e/benchmarks/tf-core.js diff --git a/e2e/benchmarks/tf-core.js b/e2e/benchmarks/tf-core.js deleted file mode 100644 index 2637d1e2b74..00000000000 --- a/e2e/benchmarks/tf-core.js +++ /dev/null @@ -1,32471 +0,0 @@ -/** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (global = global || self, factory(global.tf = global.tf || {})); -}(this, (function (exports) { 'use strict'; - - /*! ***************************************************************************** - Copyright (c) Microsoft Corporation. All rights reserved. - Licensed under the Apache License, Version 2.0 (the "License"); you may not use - this file except in compliance with the License. You may obtain a copy of the - License at http://www.apache.org/licenses/LICENSE-2.0 - - THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED - WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, - MERCHANTABLITY OR NON-INFRINGEMENT. - - See the Apache Version 2.0 License for specific language governing permissions - and limitations under the License. - ***************************************************************************** */ - /* global Reflect, Promise */ - - var extendStatics = function(d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - - function __extends(d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - } - - function __awaiter(thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); - } - - function __generator(thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } - } - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // Expects flags from URL in the format ?tfjsflags=FLAG1:1,FLAG2:true. - var TENSORFLOWJS_FLAGS_PREFIX = 'tfjsflags'; - /** - * The environment contains evaluated flags as well as the registered platform. - * This is always used as a global singleton and can be retrieved with - * `tf.env()`. - */ - /** @doc {heading: 'Environment'} */ - var Environment = /** @class */ (function () { - // tslint:disable-next-line: no-any - function Environment(global) { - this.global = global; - this.flags = {}; - this.flagRegistry = {}; - this.urlFlags = {}; - this.populateURLFlags(); - } - Environment.prototype.setPlatform = function (platformName, platform) { - if (this.platform != null) { - console.warn("Platform " + this.platformName + " has already been set. " + - ("Overwriting the platform with " + platform + ".")); - } - this.platformName = platformName; - this.platform = platform; - }; - Environment.prototype.registerFlag = function (flagName, evaluationFn, setHook) { - this.flagRegistry[flagName] = { evaluationFn: evaluationFn, setHook: setHook }; - // Override the flag value from the URL. This has to happen here because the - // environment is initialized before flags get registered. - if (this.urlFlags[flagName] != null) { - var flagValue = this.urlFlags[flagName]; - console.warn("Setting feature override from URL " + flagName + ": " + flagValue + "."); - this.set(flagName, flagValue); - } - }; - Environment.prototype.getAsync = function (flagName) { - return __awaiter(this, void 0, void 0, function () { - var _a, _b; - return __generator(this, function (_c) { - switch (_c.label) { - case 0: - if (flagName in this.flags) { - return [2 /*return*/, this.flags[flagName]]; - } - _a = this.flags; - _b = flagName; - return [4 /*yield*/, this.evaluateFlag(flagName)]; - case 1: - _a[_b] = _c.sent(); - return [2 /*return*/, this.flags[flagName]]; - } - }); - }); - }; - Environment.prototype.get = function (flagName) { - if (flagName in this.flags) { - return this.flags[flagName]; - } - var flagValue = this.evaluateFlag(flagName); - if (flagValue instanceof Promise) { - throw new Error("Flag " + flagName + " cannot be synchronously evaluated. " + - "Please use getAsync() instead."); - } - this.flags[flagName] = flagValue; - return this.flags[flagName]; - }; - Environment.prototype.getNumber = function (flagName) { - return this.get(flagName); - }; - Environment.prototype.getBool = function (flagName) { - return this.get(flagName); - }; - Environment.prototype.getFlags = function () { - return this.flags; - }; - Object.defineProperty(Environment.prototype, "features", { - // For backwards compatibility. - get: function () { - return this.flags; - }, - enumerable: true, - configurable: true - }); - Environment.prototype.set = function (flagName, value) { - if (this.flagRegistry[flagName] == null) { - throw new Error("Cannot set flag " + flagName + " as it has not been registered."); - } - this.flags[flagName] = value; - if (this.flagRegistry[flagName].setHook != null) { - this.flagRegistry[flagName].setHook(value); - } - }; - Environment.prototype.evaluateFlag = function (flagName) { - if (this.flagRegistry[flagName] == null) { - throw new Error("Cannot evaluate flag '" + flagName + "': no evaluation function found."); - } - return this.flagRegistry[flagName].evaluationFn(); - }; - Environment.prototype.setFlags = function (flags) { - this.flags = Object.assign({}, flags); - }; - Environment.prototype.reset = function () { - this.flags = {}; - this.urlFlags = {}; - this.populateURLFlags(); - }; - Environment.prototype.populateURLFlags = function () { - var _this = this; - if (typeof this.global === 'undefined' || - typeof this.global.location === 'undefined' || - typeof this.global.location.search === 'undefined') { - return; - } - var urlParams = getQueryParams(this.global.location.search); - if (TENSORFLOWJS_FLAGS_PREFIX in urlParams) { - var keyValues = urlParams[TENSORFLOWJS_FLAGS_PREFIX].split(','); - keyValues.forEach(function (keyValue) { - var _a = keyValue.split(':'), key = _a[0], value = _a[1]; - _this.urlFlags[key] = parseValue(key, value); - }); - } - }; - return Environment; - }()); - function getQueryParams(queryString) { - var params = {}; - queryString.replace(/[?&]([^=?&]+)(?:=([^&]*))?/g, function (s) { - var t = []; - for (var _i = 1; _i < arguments.length; _i++) { - t[_i - 1] = arguments[_i]; - } - decodeParam(params, t[0], t[1]); - return t.join('='); - }); - return params; - } - function decodeParam(params, name, value) { - params[decodeURIComponent(name)] = decodeURIComponent(value || ''); - } - function parseValue(flagName, value) { - value = value.toLowerCase(); - if (value === 'true' || value === 'false') { - return value === 'true'; - } - else if ("" + +value === value) { - return +value; - } - throw new Error("Could not parse value flag value " + value + " for flag " + flagName + "."); - } - /** - * Returns the current environment (a global singleton). - * - * The environment object contains the evaluated feature values as well as the - * active platform. - */ - /** @doc {heading: 'Environment'} */ - function env() { - return exports.ENV; - } - exports.ENV = null; - function setEnvironmentGlobal(environment) { - exports.ENV = environment; - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // Note that the identifier globalNameSpace is scoped to this module, but will - // always resolve to the same global object regardless of how the module is - // resolved. - // tslint:disable-next-line:no-any - var globalNameSpace; - // tslint:disable-next-line:no-any - function getGlobalNamespace() { - if (globalNameSpace == null) { - // tslint:disable-next-line:no-any - var ns = void 0; - if (typeof (window) !== 'undefined') { - ns = window; - } - else if (typeof (global) !== 'undefined') { - ns = global; - } - else if (typeof (process) !== 'undefined') { - ns = process; - } - else if (typeof (self) !== 'undefined') { - ns = self; - } - else { - throw new Error('Could not find a global object'); - } - globalNameSpace = ns; - } - return globalNameSpace; - } - // tslint:disable-next-line:no-any - function getGlobalMap() { - var ns = getGlobalNamespace(); - if (ns._tfGlobals == null) { - ns._tfGlobals = new Map(); - } - return ns._tfGlobals; - } - /** - * Returns a globally accessible 'singleton' object. - * - * @param key the name of the object - * @param init a function to initialize to initialize this object - * the first time it is fetched. - */ - function getGlobal(key, init) { - var globalMap = getGlobalMap(); - if (globalMap.has(key)) { - return globalMap.get(key); - } - else { - var singleton = init(); - globalMap.set(key, singleton); - return globalMap.get(key); - } - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var kernelRegistry = getGlobal('kernelRegistry', function () { return new Map(); }); - var gradRegistry = getGlobal('gradRegistry', function () { return new Map(); }); - /** - * Returns the kernel function (code) associated with the provided names. - * - * @param kernelName The official name of the kernel. - * @param backendName The official name of the backend. - */ - function getKernel(kernelName, backendName) { - var key = makeKey(kernelName, backendName); - return kernelRegistry.get(key); - } - /** - * Returns the registered gradient info associated with the provided kernel. - * @param kernelName The official TF kernel name. - */ - function getGradient(kernelName) { - return gradRegistry.get(kernelName); - } - function getKernelsForBackend(backendName) { - var it = kernelRegistry.entries(); - var result = []; - while (true) { - var _a = it.next(), done = _a.done, value = _a.value; - if (done) { - break; - } - var key = value[0], config = value[1]; - var backend = key.split('_')[0]; - if (backend === backendName) { - result.push(config); - } - } - return result; - } - /** - * Registers the function (forward pass) for the kernel in a global registry. - * - * @param config A config object with the following properties: - * - `kernelName` The official name of the kernel. - * - `backendName` The official name of the backend. - * - `kernelFunc` The function to run during the forward pass of the kernel. - * - `setupFunc` Optional. Gets called once, after the backend initializes. - * - `disposeFunc` Optional. Gets called once, right before the backend is - * disposed. - */ - function registerKernel(config) { - var kernelName = config.kernelName, backendName = config.backendName; - var key = makeKey(kernelName, backendName); - if (kernelRegistry.has(key)) { - console.warn("The kernel '" + kernelName + "' for backend " + - ("'" + backendName + "' is already registered")); - } - kernelRegistry.set(key, config); - } - /** - * Registers a gradient function for a given kernel in the global registry, - * to be used during the back-propagation of that kernel. - * - * @param config An object with the following properties: - * - `kernelName` The name of the kernel that the gradient function is for. - * - `gradFunc` The function to run during back-propagation. - */ - function registerGradient(config) { - var kernelName = config.kernelName; - if (gradRegistry.has(kernelName)) { - // TODO (yassogba) after 3.0 assess whether we need to keep this gated - // to debug mode. - if (env().getBool('DEBUG')) { - console.warn("Overriding the gradient for '" + kernelName + "'"); - } - } - gradRegistry.set(kernelName, config); - } - /** - * Removes the kernel function from the registry. - * - * @param kernelName The official name of the kernel. - * @param backendName The official name of the backend. - * - */ - function unregisterKernel(kernelName, backendName) { - var key = makeKey(kernelName, backendName); - if (!kernelRegistry.has(key)) { - throw new Error("The kernel '" + kernelName + "' for backend " + - ("'" + backendName + "' is not registered")); - } - kernelRegistry.delete(key); - } - /** Removes the registered gradient from the global registry. */ - function unregisterGradient(kernelName) { - if (!gradRegistry.has(kernelName)) { - throw new Error("The gradient '" + kernelName + "' for backend is not registered"); - } - gradRegistry.delete(kernelName); - } - function makeKey(kernelName, backendName) { - return backendName + "_" + kernelName; - } - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Shuffles the array in-place using Fisher-Yates algorithm. - * - * ```js - * const a = [1, 2, 3, 4, 5]; - * tf.util.shuffle(a); - * console.log(a); - * ``` - * - * @param array The array to shuffle in-place. - */ - /** @doc {heading: 'Util', namespace: 'util'} */ - // tslint:disable-next-line:no-any - function shuffle(array) { - var counter = array.length; - var temp = 0; - var index = 0; - // While there are elements in the array - while (counter > 0) { - // Pick a random index - index = (Math.random() * counter) | 0; - // Decrease counter by 1 - counter--; - // And swap the last element with it - temp = array[counter]; - array[counter] = array[index]; - array[index] = temp; - } - } - /** Clamps a value to a specified range. */ - function clamp(min, x, max) { - return Math.max(min, Math.min(x, max)); - } - function nearestLargerEven(val) { - return val % 2 === 0 ? val : val + 1; - } - function sum(arr) { - var sum = 0; - for (var i = 0; i < arr.length; i++) { - sum += arr[i]; - } - return sum; - } - /** - * Returns a sample from a uniform [a, b) distribution. - * - * @param a The minimum support (inclusive). - * @param b The maximum support (exclusive). - * @return A pseudorandom number on the half-open interval [a,b). - */ - function randUniform(a, b) { - var r = Math.random(); - return (b * r) + (1 - r) * a; - } - /** Returns the squared Euclidean distance between two vectors. */ - function distSquared(a, b) { - var result = 0; - for (var i = 0; i < a.length; i++) { - var diff = Number(a[i]) - Number(b[i]); - result += diff * diff; - } - return result; - } - /** - * Asserts that the expression is true. Otherwise throws an error with the - * provided message. - * - * ```js - * const x = 2; - * tf.util.assert(x === 2, 'x is not 2'); - * ``` - * - * @param expr The expression to assert (as a boolean). - * @param msg A function that returns the message to report when throwing an - * error. We use a function for performance reasons. - */ - /** @doc {heading: 'Util', namespace: 'util'} */ - function assert(expr, msg) { - if (!expr) { - throw new Error(typeof msg === 'string' ? msg : msg()); - } - } - function assertShapesMatch(shapeA, shapeB, errorMessagePrefix) { - if (errorMessagePrefix === void 0) { errorMessagePrefix = ''; } - assert(arraysEqual(shapeA, shapeB), function () { return errorMessagePrefix + (" Shapes " + shapeA + " and " + shapeB + " must match"); }); - } - function assertNonNull(a) { - assert(a != null, function () { return "The input to the tensor constructor must be a non-null value."; }); - } - // NOTE: We explicitly type out what T extends instead of any so that - // util.flatten on a nested array of number doesn't try to infer T as a - // number[][], causing us to explicitly type util.flatten(). - /** - * Flattens an arbitrarily nested array. - * - * ```js - * const a = [[1, 2], [3, 4], [5, [6, [7]]]]; - * const flat = tf.util.flatten(a); - * console.log(flat); - * ``` - * - * @param arr The nested array to flatten. - * @param result The destination array which holds the elements. - * @param skipTypedArray If true, avoids flattening the typed arrays. Defaults - * to false. - */ - /** @doc {heading: 'Util', namespace: 'util'} */ - function flatten(arr, result, skipTypedArray) { - if (result === void 0) { result = []; } - if (skipTypedArray === void 0) { skipTypedArray = false; } - if (result == null) { - result = []; - } - if (Array.isArray(arr) || isTypedArray(arr) && !skipTypedArray) { - for (var i = 0; i < arr.length; ++i) { - flatten(arr[i], result, skipTypedArray); - } - } - else { - result.push(arr); - } - return result; - } - /** - * Returns the size (number of elements) of the tensor given its shape. - * - * ```js - * const shape = [3, 4, 2]; - * const size = tf.util.sizeFromShape(shape); - * console.log(size); - * ``` - */ - /** @doc {heading: 'Util', namespace: 'util'} */ - function sizeFromShape(shape) { - if (shape.length === 0) { - // Scalar. - return 1; - } - var size = shape[0]; - for (var i = 1; i < shape.length; i++) { - size *= shape[i]; - } - return size; - } - function isScalarShape(shape) { - return shape.length === 0; - } - function arraysEqual(n1, n2) { - if (n1 === n2) { - return true; - } - if (n1 == null || n2 == null) { - return false; - } - if (n1.length !== n2.length) { - return false; - } - for (var i = 0; i < n1.length; i++) { - if (n1[i] !== n2[i]) { - return false; - } - } - return true; - } - function isInt(a) { - return a % 1 === 0; - } - function tanh(x) { - // tslint:disable-next-line:no-any - if (Math.tanh != null) { - // tslint:disable-next-line:no-any - return Math.tanh(x); - } - if (x === Infinity) { - return 1; - } - else if (x === -Infinity) { - return -1; - } - else { - var e2x = Math.exp(2 * x); - return (e2x - 1) / (e2x + 1); - } - } - function sizeToSquarishShape(size) { - var width = Math.ceil(Math.sqrt(size)); - return [width, Math.ceil(size / width)]; - } - /** - * Creates a new array with randomized indicies to a given quantity. - * - * ```js - * const randomTen = tf.util.createShuffledIndices(10); - * console.log(randomTen); - * ``` - * - * @param number Quantity of how many shuffled indicies to create. - */ - /** @doc {heading: 'Util', namespace: 'util'} */ - function createShuffledIndices(n) { - var shuffledIndices = new Uint32Array(n); - for (var i = 0; i < n; ++i) { - shuffledIndices[i] = i; - } - shuffle(shuffledIndices); - return shuffledIndices; - } - function rightPad(a, size) { - if (size <= a.length) { - return a; - } - return a + ' '.repeat(size - a.length); - } - function repeatedTry(checkFn, delayFn, maxCounter) { - if (delayFn === void 0) { delayFn = function (counter) { return 0; }; } - return new Promise(function (resolve, reject) { - var tryCount = 0; - var tryFn = function () { - if (checkFn()) { - resolve(); - return; - } - tryCount++; - var nextBackoff = delayFn(tryCount); - if (maxCounter != null && tryCount >= maxCounter) { - reject(); - return; - } - setTimeout(tryFn, nextBackoff); - }; - tryFn(); - }); - } - /** - * Given the full size of the array and a shape that may contain -1 as the - * implicit dimension, returns the inferred shape where -1 is replaced. - * E.g. For shape=[2, -1, 3] and size=24, it will return [2, 4, 3]. - * - * @param shape The shape, which may contain -1 in some dimension. - * @param size The full size (number of elements) of the array. - * @return The inferred shape where -1 is replaced with the inferred size. - */ - function inferFromImplicitShape(shape, size) { - var shapeProd = 1; - var implicitIdx = -1; - for (var i = 0; i < shape.length; ++i) { - if (shape[i] >= 0) { - shapeProd *= shape[i]; - } - else if (shape[i] === -1) { - if (implicitIdx !== -1) { - throw Error("Shapes can only have 1 implicit size. " + - ("Found -1 at dim " + implicitIdx + " and dim " + i)); - } - implicitIdx = i; - } - else if (shape[i] < 0) { - throw Error("Shapes can not be < 0. Found " + shape[i] + " at dim " + i); - } - } - if (implicitIdx === -1) { - if (size > 0 && size !== shapeProd) { - throw Error("Size(" + size + ") must match the product of shape " + shape); - } - return shape; - } - if (shapeProd === 0) { - throw Error("Cannot infer the missing size in [" + shape + "] when " + - "there are 0 elements"); - } - if (size % shapeProd !== 0) { - throw Error("The implicit shape can't be a fractional number. " + - ("Got " + size + " / " + shapeProd)); - } - var newShape = shape.slice(); - newShape[implicitIdx] = size / shapeProd; - return newShape; - } - function parseAxisParam(axis, shape) { - var rank = shape.length; - // Normalize input - axis = axis == null ? shape.map(function (s, i) { return i; }) : [].concat(axis); - // Check for valid range - assert(axis.every(function (ax) { return ax >= -rank && ax < rank; }), function () { - return "All values in axis param must be in range [-" + rank + ", " + rank + ") but " + - ("got axis " + axis); - }); - // Check for only integers - assert(axis.every(function (ax) { return isInt(ax); }), function () { return "All values in axis param must be integers but " + - ("got axis " + axis); }); - // Handle negative axis. - return axis.map(function (a) { return a < 0 ? rank + a : a; }); - } - /** Reduces the shape by removing all dimensions of shape 1. */ - function squeezeShape(shape, axis) { - var newShape = []; - var keptDims = []; - var isEmptyArray = axis != null && Array.isArray(axis) && axis.length === 0; - var axes = (axis == null || isEmptyArray) ? - null : - parseAxisParam(axis, shape).sort(); - var j = 0; - for (var i = 0; i < shape.length; ++i) { - if (axes != null) { - if (axes[j] === i && shape[i] !== 1) { - throw new Error("Can't squeeze axis " + i + " since its dim '" + shape[i] + "' is not 1"); - } - if ((axes[j] == null || axes[j] > i) && shape[i] === 1) { - newShape.push(shape[i]); - keptDims.push(i); - } - if (axes[j] <= i) { - j++; - } - } - if (shape[i] !== 1) { - newShape.push(shape[i]); - keptDims.push(i); - } - } - return { newShape: newShape, keptDims: keptDims }; - } - function getTypedArrayFromDType(dtype, size) { - var values = null; - if (dtype == null || dtype === 'float32') { - values = new Float32Array(size); - } - else if (dtype === 'int32') { - values = new Int32Array(size); - } - else if (dtype === 'bool') { - values = new Uint8Array(size); - } - else { - throw new Error("Unknown data type " + dtype); - } - return values; - } - function getArrayFromDType(dtype, size) { - var values = null; - if (dtype == null || dtype === 'float32') { - values = new Float32Array(size); - } - else if (dtype === 'int32') { - values = new Int32Array(size); - } - else if (dtype === 'bool') { - values = new Uint8Array(size); - } - else if (dtype === 'string') { - values = new Array(size); - } - else { - throw new Error("Unknown data type " + dtype); - } - return values; - } - function checkConversionForErrors(vals, dtype) { - for (var i = 0; i < vals.length; i++) { - var num = vals[i]; - if (isNaN(num) || !isFinite(num)) { - throw Error("A tensor of type " + dtype + " being uploaded contains " + num + "."); - } - } - } - /** Returns true if the dtype is valid. */ - function isValidDtype(dtype) { - return dtype === 'bool' || dtype === 'complex64' || dtype === 'float32' || - dtype === 'int32' || dtype === 'string'; - } - /** - * Returns true if the new type can't encode the old type without loss of - * precision. - */ - function hasEncodingLoss(oldType, newType) { - if (newType === 'complex64') { - return false; - } - if (newType === 'float32' && oldType !== 'complex64') { - return false; - } - if (newType === 'int32' && oldType !== 'float32' && oldType !== 'complex64') { - return false; - } - if (newType === 'bool' && oldType === 'bool') { - return false; - } - return true; - } - function isTypedArray(a) { - return a instanceof Float32Array || a instanceof Int32Array || - a instanceof Uint8Array; - } - function bytesPerElement(dtype) { - if (dtype === 'float32' || dtype === 'int32') { - return 4; - } - else if (dtype === 'complex64') { - return 8; - } - else if (dtype === 'bool') { - return 1; - } - else { - throw new Error("Unknown dtype " + dtype); - } - } - /** - * Returns the approximate number of bytes allocated in the string array - 2 - * bytes per character. Computing the exact bytes for a native string in JS is - * not possible since it depends on the encoding of the html page that serves - * the website. - */ - function bytesFromStringArray(arr) { - if (arr == null) { - return 0; - } - var bytes = 0; - arr.forEach(function (x) { return bytes += x.length; }); - return bytes; - } - /** Returns true if the value is a string. */ - function isString(value) { - return typeof value === 'string' || value instanceof String; - } - function isBoolean(value) { - return typeof value === 'boolean'; - } - function isNumber(value) { - return typeof value === 'number'; - } - function inferDtype(values) { - if (Array.isArray(values)) { - return inferDtype(values[0]); - } - if (values instanceof Float32Array) { - return 'float32'; - } - else if (values instanceof Int32Array || values instanceof Uint8Array) { - return 'int32'; - } - else if (isNumber(values)) { - return 'float32'; - } - else if (isString(values)) { - return 'string'; - } - else if (isBoolean(values)) { - return 'bool'; - } - return 'float32'; - } - function isFunction(f) { - return !!(f && f.constructor && f.call && f.apply); - } - function nearestDivisor(size, start) { - for (var i = start; i < size; ++i) { - if (size % i === 0) { - return i; - } - } - return size; - } - function computeStrides(shape) { - var rank = shape.length; - if (rank < 2) { - return []; - } - // Last dimension has implicit stride of 1, thus having D-1 (instead of D) - // strides. - var strides = new Array(rank - 1); - strides[rank - 2] = shape[rank - 1]; - for (var i = rank - 3; i >= 0; --i) { - strides[i] = strides[i + 1] * shape[i + 1]; - } - return strides; - } - function toTypedArray(a, dtype) { - if (dtype === 'string') { - throw new Error('Cannot convert a string[] to a TypedArray'); - } - if (Array.isArray(a)) { - a = flatten(a); - } - if (env().getBool('DEBUG')) { - checkConversionForErrors(a, dtype); - } - if (noConversionNeeded(a, dtype)) { - return a; - } - if (dtype == null || dtype === 'float32' || dtype === 'complex64') { - return new Float32Array(a); - } - else if (dtype === 'int32') { - return new Int32Array(a); - } - else if (dtype === 'bool') { - var bool = new Uint8Array(a.length); - for (var i = 0; i < bool.length; ++i) { - if (Math.round(a[i]) !== 0) { - bool[i] = 1; - } - } - return bool; - } - else { - throw new Error("Unknown data type " + dtype); - } - } - function createNestedArray(offset, shape, a) { - var ret = new Array(); - if (shape.length === 1) { - var d = shape[0]; - for (var i = 0; i < d; i++) { - ret[i] = a[offset + i]; - } - } - else { - var d = shape[0]; - var rest = shape.slice(1); - var len = rest.reduce(function (acc, c) { return acc * c; }); - for (var i = 0; i < d; i++) { - ret[i] = createNestedArray(offset + i * len, rest, a); - } - } - return ret; - } - // Provide a nested array of TypedArray in given shape. - function toNestedArray(shape, a) { - if (shape.length === 0) { - // Scalar type should return a single number. - return a[0]; - } - var size = shape.reduce(function (acc, c) { return acc * c; }); - if (size === 0) { - // A tensor with shape zero should be turned into empty list. - return []; - } - if (size !== a.length) { - throw new Error("[" + shape + "] does not match the input size " + a.length + "."); - } - return createNestedArray(0, shape, a); - } - function noConversionNeeded(a, dtype) { - return (a instanceof Float32Array && dtype === 'float32') || - (a instanceof Int32Array && dtype === 'int32') || - (a instanceof Uint8Array && dtype === 'bool'); - } - function makeOnesTypedArray(size, dtype) { - var array = makeZerosTypedArray(size, dtype); - for (var i = 0; i < array.length; i++) { - array[i] = 1; - } - return array; - } - function makeZerosTypedArray(size, dtype) { - if (dtype == null || dtype === 'float32' || dtype === 'complex64') { - return new Float32Array(size); - } - else if (dtype === 'int32') { - return new Int32Array(size); - } - else if (dtype === 'bool') { - return new Uint8Array(size); - } - else { - throw new Error("Unknown data type " + dtype); - } - } - /** - * Make nested `TypedArray` filled with zeros. - * @param shape The shape information for the nested array. - * @param dtype dtype of the array element. - */ - function makeZerosNestedTypedArray(shape, dtype) { - var size = shape.reduce(function (prev, curr) { return prev * curr; }, 1); - if (dtype == null || dtype === 'float32') { - return toNestedArray(shape, new Float32Array(size)); - } - else if (dtype === 'int32') { - return toNestedArray(shape, new Int32Array(size)); - } - else if (dtype === 'bool') { - return toNestedArray(shape, new Uint8Array(size)); - } - else { - throw new Error("Unknown data type " + dtype); - } - } - /** - * Returns the current high-resolution time in milliseconds relative to an - * arbitrary time in the past. It works across different platforms (node.js, - * browsers). - * - * ```js - * console.log(tf.util.now()); - * ``` - */ - /** @doc {heading: 'Util', namespace: 'util'} */ - function now() { - return env().platform.now(); - } - function assertNonNegativeIntegerDimensions(shape) { - shape.forEach(function (dimSize) { - assert(Number.isInteger(dimSize) && dimSize >= 0, function () { - return "Tensor must have a shape comprised of positive integers but got " + - ("shape [" + shape + "]."); - }); - }); - } - /** - * Returns a platform-specific implementation of - * [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). - * - * If `fetch` is defined on the global object (`window`, `process`, etc.), - * `tf.util.fetch` returns that function. - * - * If not, `tf.util.fetch` returns a platform-specific solution. - * - * ```js - * const resource = await tf.util.fetch('https://unpkg.com/@tensorflow/tfjs'); - * // handle response - * ``` - */ - /** @doc {heading: 'Util'} */ - function fetch$1(path, requestInits) { - return env().platform.fetch(path, requestInits); - } - /** - * Encodes the provided string into bytes using the provided encoding scheme. - * - * @param s The string to encode. - * @param encoding The encoding scheme. Defaults to utf-8. - * - */ - /** @doc {heading: 'Util'} */ - function encodeString(s, encoding) { - if (encoding === void 0) { encoding = 'utf-8'; } - encoding = encoding || 'utf-8'; - return env().platform.encode(s, encoding); - } - /** - * Decodes the provided bytes into a string using the provided encoding scheme. - * @param bytes The bytes to decode. - * - * @param encoding The encoding scheme. Defaults to utf-8. - */ - /** @doc {heading: 'Util'} */ - function decodeString(bytes, encoding) { - if (encoding === void 0) { encoding = 'utf-8'; } - encoding = encoding || 'utf-8'; - return env().platform.decode(bytes, encoding); - } - /** - * Computes flat index for a given location (multidimentionsal index) in a - * Tensor/multidimensional array. - * - * @param locs Location in the tensor. - * @param rank Rank of the tensor. - * @param strides Tensor strides. - */ - function locToIndex(locs, rank, strides) { - if (rank === 0) { - return 0; - } - else if (rank === 1) { - return locs[0]; - } - var index = locs[locs.length - 1]; - for (var i = 0; i < locs.length - 1; ++i) { - index += strides[i] * locs[i]; - } - return index; - } - /** - * Computes the location (multidimensional index) in a tensor/multidimentional - * array for a given flat index. - * - * @param index Index in flat array. - * @param rank Rank of tensor. - * @param strides Strides of tensor. - */ - function indexToLoc(index, rank, strides) { - if (rank === 0) { - return []; - } - else if (rank === 1) { - return [index]; - } - var locs = new Array(rank); - for (var i = 0; i < locs.length - 1; ++i) { - locs[i] = Math.floor(index / strides[i]); - index -= locs[i] * strides[i]; - } - locs[locs.length - 1] = index; - return locs; - } - - var util = { - __proto__: null, - shuffle: shuffle, - clamp: clamp, - nearestLargerEven: nearestLargerEven, - sum: sum, - randUniform: randUniform, - distSquared: distSquared, - assert: assert, - assertShapesMatch: assertShapesMatch, - assertNonNull: assertNonNull, - flatten: flatten, - sizeFromShape: sizeFromShape, - isScalarShape: isScalarShape, - arraysEqual: arraysEqual, - isInt: isInt, - tanh: tanh, - sizeToSquarishShape: sizeToSquarishShape, - createShuffledIndices: createShuffledIndices, - rightPad: rightPad, - repeatedTry: repeatedTry, - inferFromImplicitShape: inferFromImplicitShape, - parseAxisParam: parseAxisParam, - squeezeShape: squeezeShape, - getTypedArrayFromDType: getTypedArrayFromDType, - getArrayFromDType: getArrayFromDType, - checkConversionForErrors: checkConversionForErrors, - isValidDtype: isValidDtype, - hasEncodingLoss: hasEncodingLoss, - isTypedArray: isTypedArray, - bytesPerElement: bytesPerElement, - bytesFromStringArray: bytesFromStringArray, - isString: isString, - isBoolean: isBoolean, - isNumber: isNumber, - inferDtype: inferDtype, - isFunction: isFunction, - nearestDivisor: nearestDivisor, - computeStrides: computeStrides, - toTypedArray: toTypedArray, - toNestedArray: toNestedArray, - makeOnesTypedArray: makeOnesTypedArray, - makeZerosTypedArray: makeZerosTypedArray, - makeZerosNestedTypedArray: makeZerosNestedTypedArray, - now: now, - assertNonNegativeIntegerDimensions: assertNonNegativeIntegerDimensions, - fetch: fetch$1, - encodeString: encodeString, - decodeString: decodeString, - locToIndex: locToIndex, - indexToLoc: indexToLoc - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var Profiler = /** @class */ (function () { - function Profiler(backendTimer, logger) { - this.backendTimer = backendTimer; - this.logger = logger; - if (logger == null) { - this.logger = new Logger(); - } - } - Profiler.prototype.profileKernel = function (kernelName, inputs, f) { - var _this = this; - var outputs; - var holdResultWrapperFn = function () { - outputs = f(); - }; - var timer = this.backendTimer.time(holdResultWrapperFn); - outputs.forEach(function (r) { - // Dangling promise here because we don't want to propagate up - // asynchronicity. - r.data().then(function (vals) { - checkComputationForErrors(vals, r.dtype, kernelName); - timer.then(function (timing) { - var extraInfo = ''; - if (timing.getExtraProfileInfo != null) { - extraInfo = timing.getExtraProfileInfo(); - } - _this.logger.logKernelProfile(kernelName, r, vals, timing.kernelMs, inputs, extraInfo); - }); - }); - }); - return outputs; - }; - return Profiler; - }()); - function checkComputationForErrors(vals, dtype, kernelName) { - if (dtype !== 'float32') { - // Only floating point computations will generate NaN values - return false; - } - for (var i = 0; i < vals.length; i++) { - var num = vals[i]; - if (isNaN(num) || !isFinite(num)) { - // Throwing custom exception so behavior is testable. - console.warn("Found " + num + " in the result of '" + kernelName + "'"); - return true; - } - } - return false; - } - var Logger = /** @class */ (function () { - function Logger() { - } - Logger.prototype.logKernelProfile = function (name, result, vals, timeMs, inputs, extraInfo) { - var time = typeof timeMs === 'number' ? rightPad(timeMs + "ms", 9) : - timeMs['error']; - var paddedName = rightPad(name, 25); - var rank = result.rank; - var size = result.size; - var shape = rightPad(result.shape.toString(), 14); - var inputShapesDescription = ''; - for (var name_1 in inputs) { - var input = inputs[name_1]; - // The input might be a non-tensor (e.g HTMLImageElement), in which case - // we claim the output shape as input shape. - var inputShape = input.shape || result.shape; - var inputRank = inputShape.length; - inputShapesDescription += - name_1 + ": " + inputRank + "D " + (inputRank > 0 ? inputShape : '') + " "; - } - console.log("%c" + paddedName + "\t%c" + time + "\t%c" + rank + "D " + shape + "\t%c" + size + "\t%c" + inputShapesDescription + "\t%c" + extraInfo, 'font-weight:bold', 'color:red', 'color:blue', 'color: orange', 'color: green', 'color: steelblue'); - }; - return Logger; - }()); - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes a list of TapeNodes that connect x to y, filtering everything else - * out and preserving the order of the original tape elements. - * - * @param tape The tape elements to filter. - * @param xs The input Tensors. - * @param y The output Tensor. - */ - function getFilteredNodesXToY(tape, xs, y) { - // Forward pass to compute all the nodes and Tensors that are transitively a - // function of x. - var tensorsFromX = {}; - var nodesFromX = {}; - for (var i = 0; i < xs.length; i++) { - tensorsFromX[xs[i].id] = true; - } - for (var i = 0; i < tape.length; i++) { - var node = tape[i]; - var nodeInputs = node.inputs; - for (var inputName in nodeInputs) { - var input = nodeInputs[inputName]; - var anyInputFromX = false; - for (var j = 0; j < xs.length; j++) { - if (tensorsFromX[input.id]) { - node.outputs.forEach(function (output) { return tensorsFromX[output.id] = true; }); - anyInputFromX = true; - nodesFromX[node.id] = true; - break; - } - } - if (anyInputFromX) { - break; - } - } - } - // Backward pass to find all of the nodes and Tensors that lead to y. - var tensorsLeadToY = {}; - tensorsLeadToY[y.id] = true; - var nodesToY = {}; - for (var i = tape.length - 1; i >= 0; i--) { - var node = tape[i]; - var nodeInputs = node.inputs; - // If any of the outputs lead to y, mark all of the inputs as leading to y. - for (var j = 0; j < node.outputs.length; j++) { - if (tensorsLeadToY[node.outputs[j].id]) { - for (var inputName in nodeInputs) { - tensorsLeadToY[nodeInputs[inputName].id] = true; - nodesToY[node.id] = true; - } - break; - } - } - } - // Return the paths that come from x and lead to y. - var filteredTape = []; - for (var i = 0; i < tape.length; i++) { - var node = tape[i]; - if (nodesFromX[node.id] && nodesToY[node.id]) { - // Prune the inputs from the node that aren't a function of x. - var prunedInputs = {}; - for (var inputName in node.inputs) { - var nodeInput = node.inputs[inputName]; - if (tensorsFromX[nodeInput.id]) { - prunedInputs[inputName] = nodeInput; - } - } - // Copy the node and overwrite inputsAndArgs to the pruned version. - var prunedNode = Object.assign({}, node); - prunedNode.inputs = prunedInputs; - prunedNode.outputs = node.outputs; - filteredTape.push(prunedNode); - } - } - return filteredTape; - } - /** - * Backpropagate gradients through the filtered TapeNodes. - * - * @param tensorAccumulatedGradientMap A map of Tensor to its gradient. This map - * is mutated by this method. - * @param filteredTape The filtered TapeNodes to backprop through. - */ - function backpropagateGradients(tensorAccumulatedGradientMap, filteredTape, tidy) { - var _loop_1 = function (i) { - var node = filteredTape[i]; - var dys = []; - node.outputs.forEach(function (o) { - var gradTensor = tensorAccumulatedGradientMap[o.id]; - if (gradTensor != null) { - dys.push(gradTensor); - } - else { - // This particular output is not in the back-propagation subgraph, so it - // does not affect the final output, thus we put null for its dy. - dys.push(null); - } - }); - if (node.gradient == null) { - throw new Error("Cannot compute gradient: gradient function not found " + - ("for " + node.kernelName + ".")); - } - // Backprop dy through this node and accumulate gradients over the inputs. - var inputGradients = node.gradient(dys); - var _loop_2 = function (inputName) { - if (!(inputName in inputGradients)) { - throw new Error("Cannot backprop through input " + inputName + ". " + - ("Available gradients found: " + Object.keys(inputGradients) + ".")); - } - // Call the gradient function. - var dx = tidy(function () { return inputGradients[inputName](); }); - if (dx.dtype !== 'float32') { - throw new Error("Error in gradient for op " + node.kernelName + ". The gradient of input " + - (inputName + " must have 'float32' dtype, but has '" + dx.dtype + "'")); - } - var x = node.inputs[inputName]; - if (!arraysEqual(dx.shape, x.shape)) { - throw new Error("Error in gradient for op " + node.kernelName + ". The gradient of input " + - ("'" + inputName + "' has shape '" + dx.shape + "', which does not match ") + - ("the shape of the input '" + x.shape + "'")); - } - if (tensorAccumulatedGradientMap[x.id] == null) { - tensorAccumulatedGradientMap[x.id] = dx; - } - else { - var curGradient = tensorAccumulatedGradientMap[x.id]; - tensorAccumulatedGradientMap[x.id] = curGradient.add(dx); - curGradient.dispose(); - } - }; - for (var inputName in node.inputs) { - _loop_2(inputName); - } - }; - // Walk the tape backward and keep a map of Tensor to its gradient. - for (var i = filteredTape.length - 1; i >= 0; i--) { - _loop_1(i); - } - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // Maximum number of values before we decide to show ellipsis. - var FORMAT_LIMIT_NUM_VALS = 20; - // Number of first and last values to show when displaying a, b,...,y, z. - var FORMAT_NUM_FIRST_LAST_VALS = 3; - // Number of significant digits to show. - var FORMAT_NUM_SIG_DIGITS = 7; - function tensorToString(vals, shape, dtype, verbose) { - var strides = computeStrides(shape); - var padPerCol = computeMaxSizePerColumn(vals, shape, dtype, strides); - var rank = shape.length; - var valsLines = subTensorToString(vals, shape, dtype, strides, padPerCol); - var lines = ['Tensor']; - if (verbose) { - lines.push(" dtype: " + dtype); - lines.push(" rank: " + rank); - lines.push(" shape: [" + shape + "]"); - lines.push(" values:"); - } - lines.push(valsLines.map(function (l) { return ' ' + l; }).join('\n')); - return lines.join('\n'); - } - function computeMaxSizePerColumn(vals, shape, dtype, strides) { - var n = sizeFromShape(shape); - var numCols = strides[strides.length - 1]; - var padPerCol = new Array(numCols).fill(0); - var rank = shape.length; - var valuesOrTuples = dtype === 'complex64' ? createComplexTuples(vals) : vals; - if (rank > 1) { - for (var row = 0; row < n / numCols; row++) { - var offset = row * numCols; - for (var j = 0; j < numCols; j++) { - padPerCol[j] = Math.max(padPerCol[j], valToString(valuesOrTuples[offset + j], 0, dtype).length); - } - } - } - return padPerCol; - } - function valToString(val, pad, dtype) { - var valStr; - if (Array.isArray(val)) { - valStr = parseFloat(val[0].toFixed(FORMAT_NUM_SIG_DIGITS)) + " + " + - (parseFloat(val[1].toFixed(FORMAT_NUM_SIG_DIGITS)) + "j"); - } - else if (isString(val)) { - valStr = "'" + val + "'"; - } - else if (dtype === 'bool') { - valStr = boolNumToString(val); - } - else { - valStr = parseFloat(val.toFixed(FORMAT_NUM_SIG_DIGITS)).toString(); - } - return rightPad(valStr, pad); - } - function boolNumToString(v) { - return v === 0 ? 'false' : 'true'; - } - function subTensorToString(vals, shape, dtype, strides, padPerCol, isLast) { - if (isLast === void 0) { isLast = true; } - var storagePerElement = dtype === 'complex64' ? 2 : 1; - var size = shape[0]; - var rank = shape.length; - if (rank === 0) { - if (dtype === 'complex64') { - var complexTuple = createComplexTuples(vals); - return [valToString(complexTuple[0], 0, dtype)]; - } - if (dtype === 'bool') { - return [boolNumToString(vals[0])]; - } - return [vals[0].toString()]; - } - if (rank === 1) { - if (size > FORMAT_LIMIT_NUM_VALS) { - var firstValsSize = FORMAT_NUM_FIRST_LAST_VALS * storagePerElement; - var firstVals = Array.from(vals.slice(0, firstValsSize)); - var lastVals = Array.from(vals.slice((size - FORMAT_NUM_FIRST_LAST_VALS) * storagePerElement, size * storagePerElement)); - if (dtype === 'complex64') { - firstVals = createComplexTuples(firstVals); - lastVals = createComplexTuples(lastVals); - } - return [ - '[' + - firstVals.map(function (x, i) { return valToString(x, padPerCol[i], dtype); }) - .join(', ') + - ', ..., ' + - lastVals - .map(function (x, i) { return valToString(x, padPerCol[size - FORMAT_NUM_FIRST_LAST_VALS + i], dtype); }) - .join(', ') + - ']' - ]; - } - var displayVals = dtype === 'complex64' ? createComplexTuples(vals) : - Array.from(vals); - return [ - '[' + - displayVals.map(function (x, i) { return valToString(x, padPerCol[i], dtype); }) - .join(', ') + - ']' - ]; - } - // The array is rank 2 or more. - var subshape = shape.slice(1); - var substrides = strides.slice(1); - var stride = strides[0] * storagePerElement; - var lines = []; - if (size > FORMAT_LIMIT_NUM_VALS) { - for (var i = 0; i < FORMAT_NUM_FIRST_LAST_VALS; i++) { - var start = i * stride; - var end = start + stride; - lines.push.apply(lines, subTensorToString(vals.slice(start, end), subshape, dtype, substrides, padPerCol, false /* isLast */)); - } - lines.push('...'); - for (var i = size - FORMAT_NUM_FIRST_LAST_VALS; i < size; i++) { - var start = i * stride; - var end = start + stride; - lines.push.apply(lines, subTensorToString(vals.slice(start, end), subshape, dtype, substrides, padPerCol, i === size - 1 /* isLast */)); - } - } - else { - for (var i = 0; i < size; i++) { - var start = i * stride; - var end = start + stride; - lines.push.apply(lines, subTensorToString(vals.slice(start, end), subshape, dtype, substrides, padPerCol, i === size - 1 /* isLast */)); - } - } - var sep = rank === 2 ? ',' : ''; - lines[0] = '[' + lines[0] + sep; - for (var i = 1; i < lines.length - 1; i++) { - lines[i] = ' ' + lines[i] + sep; - } - var newLineSep = ',\n'; - for (var i = 2; i < rank; i++) { - newLineSep += '\n'; - } - lines[lines.length - 1] = - ' ' + lines[lines.length - 1] + ']' + (isLast ? '' : newLineSep); - return lines; - } - function createComplexTuples(vals) { - var complexTuples = []; - for (var i = 0; i < vals.length; i += 2) { - complexTuples.push([vals[i], vals[i + 1]]); - } - return complexTuples; - } - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * A mutable object, similar to `tf.Tensor`, that allows users to set values - * at locations before converting to an immutable `tf.Tensor`. - * - * See `tf.buffer` for creating a tensor buffer. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - var TensorBuffer = /** @class */ (function () { - function TensorBuffer(shape, dtype, values) { - var _this = this; - this.dtype = dtype; - this.shape = shape.slice(); - this.size = sizeFromShape(shape); - if (values != null) { - var n_1 = values.length; - assert(n_1 === this.size, function () { return "Length of values '" + n_1 + "' does not match the size " + - ("inferred by the shape '" + _this.size + "'."); }); - } - if (dtype === 'complex64') { - throw new Error("complex64 dtype TensorBuffers are not supported. Please create " + - "a TensorBuffer for the real and imaginary parts separately and " + - "call tf.complex(real, imag)."); - } - this.values = values || getArrayFromDType(dtype, this.size); - this.strides = computeStrides(shape); - } - /** - * Sets a value in the buffer at a given location. - * - * @param value The value to set. - * @param locs The location indices. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - TensorBuffer.prototype.set = function (value) { - var _this = this; - var locs = []; - for (var _i = 1; _i < arguments.length; _i++) { - locs[_i - 1] = arguments[_i]; - } - if (locs.length === 0) { - locs = [0]; - } - assert(locs.length === this.rank, function () { return "The number of provided coordinates (" + locs.length + ") must " + - ("match the rank (" + _this.rank + ")"); }); - var index = this.locToIndex(locs); - this.values[index] = value; - }; - /** - * Returns the value in the buffer at the provided location. - * - * @param locs The location indices. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - TensorBuffer.prototype.get = function () { - var locs = []; - for (var _i = 0; _i < arguments.length; _i++) { - locs[_i] = arguments[_i]; - } - if (locs.length === 0) { - locs = [0]; - } - var i = 0; - for (var _a = 0, locs_1 = locs; _a < locs_1.length; _a++) { - var loc = locs_1[_a]; - if (loc < 0 || loc >= this.shape[i]) { - var msg = "Requested out of range element at " + locs + ". " + - (" Buffer shape=" + this.shape); - throw new Error(msg); - } - i++; - } - var index = locs[locs.length - 1]; - for (var i_1 = 0; i_1 < locs.length - 1; ++i_1) { - index += this.strides[i_1] * locs[i_1]; - } - return this.values[index]; - }; - TensorBuffer.prototype.locToIndex = function (locs) { - if (this.rank === 0) { - return 0; - } - else if (this.rank === 1) { - return locs[0]; - } - var index = locs[locs.length - 1]; - for (var i = 0; i < locs.length - 1; ++i) { - index += this.strides[i] * locs[i]; - } - return index; - }; - TensorBuffer.prototype.indexToLoc = function (index) { - if (this.rank === 0) { - return []; - } - else if (this.rank === 1) { - return [index]; - } - var locs = new Array(this.shape.length); - for (var i = 0; i < locs.length - 1; ++i) { - locs[i] = Math.floor(index / this.strides[i]); - index -= locs[i] * this.strides[i]; - } - locs[locs.length - 1] = index; - return locs; - }; - Object.defineProperty(TensorBuffer.prototype, "rank", { - get: function () { - return this.shape.length; - }, - enumerable: true, - configurable: true - }); - /** - * Creates an immutable `tf.Tensor` object from the buffer. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - TensorBuffer.prototype.toTensor = function () { - return trackerFn().makeTensor(this.values, this.shape, this.dtype); - }; - return TensorBuffer; - }()); - // For tracking tensor creation and disposal. - var trackerFn = null; - // Used by chaining methods to call into ops. - var opHandler = null; - /** - * An external consumer can register itself as the tensor tracker. This way - * the Tensor class can notify the tracker for every tensor created and - * disposed. - */ - function setTensorTracker(fn) { - trackerFn = fn; - } - /** - * An external consumer can register itself as the op handler. This way the - * Tensor class can have chaining methods that call into ops via the op - * handler. - */ - function setOpHandler(handler) { - opHandler = handler; - } - /** - * A `tf.Tensor` object represents an immutable, multidimensional array of - * numbers that has a shape and a data type. - * - * See `tf.tensor` for details on how to create a `tf.Tensor`. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - var Tensor = /** @class */ (function () { - function Tensor(shape, dtype, dataId, id) { - /** Whether this tensor has been globally kept. */ - this.kept = false; - this.isDisposedInternal = false; - this.shape = shape.slice(); - this.dtype = dtype || 'float32'; - this.size = sizeFromShape(shape); - this.strides = computeStrides(shape); - this.dataId = dataId; - this.id = id; - this.rankType = (this.rank < 5 ? this.rank.toString() : 'higher'); - } - Object.defineProperty(Tensor.prototype, "rank", { - get: function () { - return this.shape.length; - }, - enumerable: true, - configurable: true - }); - /** - * Returns a promise of `tf.TensorBuffer` that holds the underlying data. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.buffer = function () { - return __awaiter(this, void 0, void 0, function () { - var vals; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.data()]; - case 1: - vals = _a.sent(); - return [2 /*return*/, opHandler.buffer(this.shape, this.dtype, vals)]; - } - }); - }); - }; - /** Returns a `tf.TensorBuffer` that holds the underlying data. */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.bufferSync = function () { - return opHandler.buffer(this.shape, this.dtype, this.dataSync()); - }; - /** - * Returns the tensor data as a nested array. The transfer of data is done - * asynchronously. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.array = function () { - return __awaiter(this, void 0, void 0, function () { - var vals; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.data()]; - case 1: - vals = _a.sent(); - return [2 /*return*/, toNestedArray(this.shape, vals)]; - } - }); - }); - }; - /** - * Returns the tensor data as a nested array. The transfer of data is done - * synchronously. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.arraySync = function () { - return toNestedArray(this.shape, this.dataSync()); - }; - /** - * Asynchronously downloads the values from the `tf.Tensor`. Returns a - * promise of `TypedArray` that resolves when the computation has finished. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.data = function () { - return __awaiter(this, void 0, void 0, function () { - var data, bytes; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - this.throwIfDisposed(); - data = trackerFn().read(this.dataId); - if (!(this.dtype === 'string')) return [3 /*break*/, 2]; - return [4 /*yield*/, data]; - case 1: - bytes = _a.sent(); - try { - return [2 /*return*/, bytes.map(function (b) { return decodeString(b); })]; - } - catch (_b) { - throw new Error('Failed to decode the string bytes into utf-8. ' + - 'To get the original bytes, call tensor.bytes().'); - } - _a.label = 2; - case 2: return [2 /*return*/, data]; - } - }); - }); - }; - /** - * Synchronously downloads the values from the `tf.Tensor`. This blocks the - * UI thread until the values are ready, which can cause performance issues. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.dataSync = function () { - this.throwIfDisposed(); - var data = trackerFn().readSync(this.dataId); - if (this.dtype === 'string') { - try { - return data.map(function (b) { return decodeString(b); }); - } - catch (_a) { - throw new Error('Failed to decode the string bytes into utf-8. ' + - 'To get the original bytes, call tensor.bytes().'); - } - } - return data; - }; - /** Returns the underlying bytes of the tensor's data. */ - Tensor.prototype.bytes = function () { - return __awaiter(this, void 0, void 0, function () { - var data; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - this.throwIfDisposed(); - return [4 /*yield*/, trackerFn().read(this.dataId)]; - case 1: - data = _a.sent(); - if (this.dtype === 'string') { - return [2 /*return*/, data]; - } - else { - return [2 /*return*/, new Uint8Array(data.buffer)]; - } - } - }); - }); - }; - /** - * Disposes `tf.Tensor` from memory. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.dispose = function () { - if (this.isDisposed) { - return; - } - trackerFn().disposeTensor(this); - this.isDisposedInternal = true; - }; - Object.defineProperty(Tensor.prototype, "isDisposed", { - get: function () { - return this.isDisposedInternal; - }, - enumerable: true, - configurable: true - }); - Tensor.prototype.throwIfDisposed = function () { - if (this.isDisposed) { - throw new Error("Tensor is disposed."); - } - }; - /** - * Prints the `tf.Tensor`. See `tf.print` for details. - * - * @param verbose Whether to print verbose information about the tensor, - * including dtype and size. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.print = function (verbose) { - if (verbose === void 0) { verbose = false; } - return opHandler.print(this, verbose); - }; - /** Returns a copy of the tensor. See `tf.clone` for details. */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.clone = function () { - this.throwIfDisposed(); - return opHandler.clone(this); - }; - /** - * Returns a human-readable description of the tensor. Useful for logging. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Tensor.prototype.toString = function (verbose) { - if (verbose === void 0) { verbose = false; } - var vals = this.dataSync(); - return tensorToString(vals, this.shape, this.dtype, verbose); - }; - Tensor.prototype.cast = function (dtype) { - this.throwIfDisposed(); - return opHandler.cast(this, dtype); - }; - Tensor.prototype.variable = function (trainable, name, dtype) { - if (trainable === void 0) { trainable = true; } - this.throwIfDisposed(); - return trackerFn().makeVariable(this, trainable, name, dtype); - }; - return Tensor; - }()); - Object.defineProperty(Tensor, Symbol.hasInstance, { - value: function (instance) { - return !!instance && instance.dataId != null && instance.shape != null && - instance.dtype != null; - } - }); - /** - * A mutable `tf.Tensor`, useful for persisting state, e.g. for training. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - var Variable = /** @class */ (function (_super) { - __extends(Variable, _super); - function Variable(initialValue, trainable, name, tensorId) { - var _this = _super.call(this, initialValue.shape, initialValue.dtype, initialValue.dataId, tensorId) || this; - _this.trainable = trainable; - _this.name = name; - return _this; - } - /** - * Assign a new `tf.Tensor` to this variable. The new `tf.Tensor` must have - * the same shape and dtype as the old `tf.Tensor`. - * - * @param newValue New tensor to be assigned to this variable. - */ - /** @doc {heading: 'Tensors', subheading: 'Classes'} */ - Variable.prototype.assign = function (newValue) { - if (newValue.dtype !== this.dtype) { - throw new Error("dtype of the new value (" + newValue.dtype + ") and " + - ("previous value (" + this.dtype + ") must match")); - } - if (!arraysEqual(newValue.shape, this.shape)) { - throw new Error("shape of the new value (" + newValue.shape + ") and " + - ("previous value (" + this.shape + ") must match")); - } - trackerFn().disposeTensor(this); - this.dataId = newValue.dataId; - trackerFn().incRef(this, null /* backend */); - }; - Variable.prototype.dispose = function () { - trackerFn().disposeVariable(this); - this.isDisposedInternal = true; - }; - return Variable; - }(Tensor)); - Object.defineProperty(Variable, Symbol.hasInstance, { - value: function (instance) { - return instance instanceof Tensor && instance.assign != null && - instance.assign instanceof Function; - } - }); - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - (function (Rank) { - Rank["R0"] = "R0"; - Rank["R1"] = "R1"; - Rank["R2"] = "R2"; - Rank["R3"] = "R3"; - Rank["R4"] = "R4"; - Rank["R5"] = "R5"; - Rank["R6"] = "R6"; - })(exports.Rank || (exports.Rank = {})); - // Looks for upcasting types. Used, for example, in operations with mixed dtype - // inputs. - var UpcastInt32AndMap; - (function (UpcastInt32AndMap) { - UpcastInt32AndMap["float32"] = "float32"; - UpcastInt32AndMap["int32"] = "int32"; - UpcastInt32AndMap["bool"] = "int32"; - UpcastInt32AndMap["complex64"] = "complex64"; - })(UpcastInt32AndMap || (UpcastInt32AndMap = {})); - var UpcastBoolAndMap; - (function (UpcastBoolAndMap) { - UpcastBoolAndMap["float32"] = "float32"; - UpcastBoolAndMap["int32"] = "int32"; - UpcastBoolAndMap["bool"] = "bool"; - UpcastBoolAndMap["complex64"] = "complex64"; - })(UpcastBoolAndMap || (UpcastBoolAndMap = {})); - var UpcastFloat32AndMap; - (function (UpcastFloat32AndMap) { - UpcastFloat32AndMap["float32"] = "float32"; - UpcastFloat32AndMap["int32"] = "float32"; - UpcastFloat32AndMap["bool"] = "float32"; - UpcastFloat32AndMap["complex64"] = "complex64"; - })(UpcastFloat32AndMap || (UpcastFloat32AndMap = {})); - var UpcastComplex64AndMap; - (function (UpcastComplex64AndMap) { - UpcastComplex64AndMap["float32"] = "complex64"; - UpcastComplex64AndMap["int32"] = "complex64"; - UpcastComplex64AndMap["bool"] = "complex64"; - UpcastComplex64AndMap["complex64"] = "complex64"; - })(UpcastComplex64AndMap || (UpcastComplex64AndMap = {})); - var upcastTypeMap = { - 'float32': UpcastFloat32AndMap, - 'int32': UpcastInt32AndMap, - 'bool': UpcastBoolAndMap, - 'complex64': UpcastComplex64AndMap - }; - function upcastType(typeA, typeB) { - if (typeA === 'string' || typeB === 'string') { - if (typeA === 'string' && typeB === 'string') { - return 'string'; - } - throw new Error("Can not upcast " + typeA + " with " + typeB); - } - return upcastTypeMap[typeA][typeB]; - } - /** Returns the output type after summation. */ - function sumOutType(type) { - return upcastType(type, 'int32'); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function makeTypesMatch(a, b) { - if (a.dtype === b.dtype) { - return [a, b]; - } - var dtype = upcastType(a.dtype, b.dtype); - return [a.cast(dtype), b.cast(dtype)]; - } - function assertTypesMatch(a, b) { - assert(a.dtype === b.dtype, function () { return "The dtypes of the first(" + a.dtype + ") and" + - (" second(" + b.dtype + ") input must match"); }); - } - function isTensorInList(tensor, tensorList) { - return tensorList.some(function (x) { return x.id === tensor.id; }); - } - /** - * Extracts any `Tensor`s found within the provided object. - * - * @param container an object that may be a `Tensor` or may directly contain - * `Tensor`s, such as a `Tensor[]` or `{key: Tensor, ...}`. In general it - * is safe to pass any object here, except that `Promise`s are not - * supported. - * @returns An array of `Tensors` found within the passed object. If the - * argument is simply a `Tensor', a list containing that `Tensor` is - * returned. If the object is not a `Tensor` or does not - * contain `Tensors`, an empty list is returned. - */ - function getTensorsInContainer(result) { - var list = []; - var seen = new Set(); - walkTensorContainer(result, list, seen); - return list; - } - function walkTensorContainer(container, list, seen) { - if (container == null) { - return; - } - if (container instanceof Tensor) { - list.push(container); - return; - } - if (!isIterable(container)) { - return; - } - // Iteration over keys works also for arrays. - var iterable = container; - for (var k in iterable) { - var val = iterable[k]; - if (!seen.has(val)) { - seen.add(val); - walkTensorContainer(val, list, seen); - } - } - } - // tslint:disable-next-line:no-any - function isIterable(obj) { - return Array.isArray(obj) || typeof obj === 'object'; - } - - var tensor_util = { - __proto__: null, - makeTypesMatch: makeTypesMatch, - assertTypesMatch: assertTypesMatch, - isTensorInList: isTensorInList, - getTensorsInContainer: getTensorsInContainer - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var EngineState = /** @class */ (function () { - function EngineState() { - // Public since optimizers will use it. - this.registeredVariables = {}; - this.nextTapeNodeId = 0; - this.numBytes = 0; - this.numTensors = 0; - this.numStringTensors = 0; - this.numDataBuffers = 0; - // Number of nested tf.grad() statements when computing higher-order - // gradients. E.g. `1` for first-order gradients and `2` for second-order - // gradients. Used to track if the tape should be removed after a backprop. - this.gradientDepth = 0; - // Number of nested kernel calls. When kernel depth is greater than 1, we turn - // off the tape. - this.kernelDepth = 0; - this.scopeStack = []; - /** - * Keeps track of the number of data moves during a kernel execution. We - * maintain a stack since kernels can call other kernels, recursively. - */ - this.numDataMovesStack = []; - this.nextScopeId = 0; - this.tensorInfo = new WeakMap(); - this.profiling = false; - this.activeProfile = { newBytes: 0, newTensors: 0, peakBytes: 0, kernels: [], result: null }; - } - EngineState.prototype.dispose = function () { - for (var variableName in this.registeredVariables) { - this.registeredVariables[variableName].dispose(); - } - }; - return EngineState; - }()); - var Engine = /** @class */ (function () { - function Engine(ENV) { - this.ENV = ENV; - this.registry = {}; - this.registryFactory = {}; - this.pendingBackendInitId = 0; - this.state = new EngineState(); - } - Engine.prototype.ready = function () { - return __awaiter(this, void 0, void 0, function () { - var sortedBackends, i, backendName, success; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (this.pendingBackendInit != null) { - return [2 /*return*/, this.pendingBackendInit.then(function () { })]; - } - if (this.backendInstance != null) { - return [2 /*return*/]; - } - sortedBackends = this.getSortedBackends(); - i = 0; - _a.label = 1; - case 1: - if (!(i < sortedBackends.length)) return [3 /*break*/, 5]; - backendName = sortedBackends[i]; - return [4 /*yield*/, this.initializeBackend(backendName).success]; - case 2: - success = _a.sent(); - if (!success) return [3 /*break*/, 4]; - return [4 /*yield*/, this.setBackend(backendName)]; - case 3: - _a.sent(); - return [2 /*return*/]; - case 4: - i++; - return [3 /*break*/, 1]; - case 5: throw new Error("Could not initialize any backends, all backend initializations " + - "failed."); - } - }); - }); - }; - Object.defineProperty(Engine.prototype, "backend", { - get: function () { - if (this.pendingBackendInit != null) { - throw new Error("Backend '" + this.backendName + "' has not yet been initialized. Make " + - "sure to await tf.ready() or await tf.setBackend() before calling " + - "other methods"); - } - if (this.backendInstance == null) { - var _a = this.initializeBackendsAndReturnBest(), name_1 = _a.name, asyncInit = _a.asyncInit; - if (asyncInit) { - throw new Error("The highest priority backend '" + name_1 + "' has not yet been " + - "initialized. Make sure to await tf.ready() or " + - "await tf.setBackend() before calling other methods"); - } - this.setBackend(name_1); - } - return this.backendInstance; - }, - enumerable: true, - configurable: true - }); - Engine.prototype.backendNames = function () { - return Object.keys(this.registryFactory); - }; - Engine.prototype.findBackend = function (backendName) { - if (!(backendName in this.registry)) { - // If the backend hasn't been initialized but we have a registry entry for - // it, initialize it and return it. - if (backendName in this.registryFactory) { - var asyncInit = this.initializeBackend(backendName).asyncInit; - if (asyncInit) { - // Backend is not ready yet. - return null; - } - } - else { - return null; - } - } - return this.registry[backendName]; - }; - Engine.prototype.findBackendFactory = function (backendName) { - if (!(backendName in this.registryFactory)) { - return null; - } - return this.registryFactory[backendName].factory; - }; - Engine.prototype.registerBackend = function (backendName, factory, priority) { - if (priority === void 0) { priority = 1; } - if (backendName in this.registryFactory) { - console.warn(backendName + " backend was already registered. " + - "Reusing existing backend factory."); - return false; - } - this.registryFactory[backendName] = { factory: factory, priority: priority }; - return true; - }; - Engine.prototype.setBackend = function (backendName) { - return __awaiter(this, void 0, void 0, function () { - var _a, success, asyncInit, result, _b; - return __generator(this, function (_c) { - switch (_c.label) { - case 0: - if (this.registryFactory[backendName] == null) { - throw new Error("Backend name '" + backendName + "' not found in registry"); - } - this.backendName = backendName; - if (!(this.registry[backendName] == null)) return [3 /*break*/, 4]; - this.backendInstance = null; - _a = this.initializeBackend(backendName), success = _a.success, asyncInit = _a.asyncInit; - if (!asyncInit) return [3 /*break*/, 2]; - return [4 /*yield*/, success]; - case 1: - _b = _c.sent(); - return [3 /*break*/, 3]; - case 2: - _b = success; - _c.label = 3; - case 3: - result = _b; - if (!result) { - return [2 /*return*/, false]; - } - _c.label = 4; - case 4: - this.backendInstance = this.registry[backendName]; - this.setupRegisteredKernels(); - // Reset the profiler. - this.profiler = new Profiler(this.backendInstance); - return [2 /*return*/, true]; - } - }); - }); - }; - Engine.prototype.setupRegisteredKernels = function () { - var _this = this; - var kernels = getKernelsForBackend(this.backendName); - kernels.forEach(function (kernel) { - if (kernel.setupFunc != null) { - kernel.setupFunc(_this.backendInstance); - } - }); - }; - Engine.prototype.disposeRegisteredKernels = function (backendName) { - var _this = this; - var kernels = getKernelsForBackend(backendName); - kernels.forEach(function (kernel) { - if (kernel.disposeFunc != null) { - kernel.disposeFunc(_this.registry[backendName]); - } - }); - }; - /** - * Initializes a backend by looking up the backend name in the factory - * registry and calling the factory method. Returns a boolean representing - * whether the initialization of the backend suceeded. Throws an error if - * there is no backend in the factory registry. - */ - Engine.prototype.initializeBackend = function (backendName) { - var _this = this; - var registryFactoryEntry = this.registryFactory[backendName]; - if (registryFactoryEntry == null) { - throw new Error("Cannot initialize backend " + backendName + ", no registration found."); - } - try { - var backend = registryFactoryEntry.factory(); - // Test if the factory returns a promise. - if (Promise.resolve(backend) === backend) { - var promiseId_1 = ++this.pendingBackendInitId; - var success = backend - .then(function (backendInstance) { - // Outdated promise. Another backend was set in the meantime. - if (promiseId_1 < _this.pendingBackendInitId) { - return false; - } - _this.registry[backendName] = backendInstance; - _this.pendingBackendInit = null; - return true; - }) - .catch(function (err) { - // Outdated promise. Another backend was set in the meantime. - if (promiseId_1 < _this.pendingBackendInitId) { - return false; - } - _this.pendingBackendInit = null; - console.warn("Initialization of backend " + backendName + " failed"); - console.warn(err.stack || err.message); - return false; - }); - this.pendingBackendInit = success; - return { success: success, asyncInit: true }; - } - else { - this.registry[backendName] = backend; - return { success: true, asyncInit: false }; - } - } - catch (err) { - console.warn("Initialization of backend " + backendName + " failed"); - console.warn(err.stack || err.message); - return { success: false, asyncInit: false }; - } - }; - Engine.prototype.removeBackend = function (backendName) { - if (!(backendName in this.registryFactory)) { - throw new Error(backendName + " backend not found in registry"); - } - if (this.backendName === backendName && this.pendingBackendInit != null) { - // There is a pending promise of the backend we want to remove. Make it - // obsolete. - this.pendingBackendInitId++; - } - if (backendName in this.registry) { - this.disposeRegisteredKernels(backendName); - this.registry[backendName].dispose(); - delete this.registry[backendName]; - } - delete this.registryFactory[backendName]; - // Unset the backend if it is active. - if (this.backendName === backendName) { - this.pendingBackendInit = null; - this.backendName = null; - this.backendInstance = null; - } - }; - Engine.prototype.getSortedBackends = function () { - var _this = this; - if (Object.keys(this.registryFactory).length === 0) { - throw new Error('No backend found in registry.'); - } - return Object.keys(this.registryFactory).sort(function (a, b) { - // Highest priority comes first. - return _this.registryFactory[b].priority - - _this.registryFactory[a].priority; - }); - }; - Engine.prototype.initializeBackendsAndReturnBest = function () { - var sortedBackends = this.getSortedBackends(); - for (var i = 0; i < sortedBackends.length; i++) { - var backendName = sortedBackends[i]; - var _a = this.initializeBackend(backendName), success = _a.success, asyncInit = _a.asyncInit; - if (asyncInit || success) { - return { name: backendName, asyncInit: asyncInit }; - } - } - throw new Error("Could not initialize any backends, all backend initializations " + - "failed."); - }; - Engine.prototype.moveData = function (backend, dataId) { - var info = this.state.tensorInfo.get(dataId); - var srcBackend = info.backend; - var values = this.readSync(dataId); - // Delete the tensor from the old backend and move it to the new - // backend. - srcBackend.disposeData(dataId); - info.backend = backend; - backend.move(dataId, values, info.shape, info.dtype); - if (this.shouldCheckForMemLeaks()) { - // Track the number of moves during a kernel execution to correctly - // detect memory leaks. - this.state.numDataMovesStack[this.state.numDataMovesStack.length - 1]++; - } - }; - Engine.prototype.tidy = function (nameOrFn, fn) { - var _this = this; - var name = null; - if (fn == null) { - // Called with only 1 argument. - if (typeof nameOrFn !== 'function') { - throw new Error('Please provide a function to tidy()'); - } - fn = nameOrFn; - } - else { - // Called with 2 arguments. - if (typeof nameOrFn !== 'string' && !(nameOrFn instanceof String)) { - throw new Error('When calling with two arguments, the first argument ' + - 'to tidy() must be a string'); - } - if (typeof fn !== 'function') { - throw new Error('When calling with two arguments, the 2nd argument ' + - 'to tidy() must be a function'); - } - name = nameOrFn; - // TODO(nsthorat,smilkov): Do operation logging and performance - // profiling. - } - var result; - return this.scopedRun(function () { return _this.startScope(name); }, function () { return _this.endScope(result); }, function () { - result = fn(); - if (result instanceof Promise) { - console.error('Cannot return a Promise inside of tidy.'); - } - return result; - }); - }; - Engine.prototype.scopedRun = function (start, end, f) { - start(); - try { - var res = f(); - end(); - return res; - } - catch (ex) { - end(); - throw ex; - } - }; - Engine.prototype.nextTensorId = function () { - return Engine.nextTensorId++; - }; - Engine.prototype.nextVariableId = function () { - return Engine.nextVariableId++; - }; - /** - * This method is called instead of the public-facing tensor.clone() when - * saving a tensor for backwards pass. It makes sure to add the clone - * operation to the tape regardless of being called inside a kernel - * execution. - * - * This method will go away once all kernels are modularized since we won't - * need to turn off the tape inside runKernel(). - */ - Engine.prototype.clone = function (x) { - var y = this.makeTensorFromDataId(x.dataId, x.shape, x.dtype); - var inputs = { x: x }; - var grad = function (dy) { return ({ x: function () { return dy.toFloat(); } }); }; - var saved = []; - this.addTapeNode(this.state.activeScope.name, inputs, [y], grad, saved, {}); - return y; - }; - /** - * Execute a kernel with the given name and return the output tensor. - * - * @param kernelName The name of the kernel to execute. - * @param inputs A map of input names to tensors. - * @param attrs A map of attribute names to their values. An attribute is a - * primitive (non-tensor) input to the kernel. - * @param inputsToSave A list of tensors, inputs to save for the backprop - * computation. - * @param outputsToSave A list of booleans, specifying which output to save - * for the backprop computation. These are booleans since the output - * tensors are not visible to the user. - */ - Engine.prototype.runKernel = function (kernelName, inputs, attrs, inputsToSave, outputsToSave) { - var forwardFunc = null; - var backwardsFunc = null; - // Call runKernel as a stop-gap until we modularize all kernels. - // Once we modularize all kernels, we will remove the existing - // `runKernelFunc`. - return this.runKernelFunc(forwardFunc, inputs, backwardsFunc, kernelName, attrs, inputsToSave, outputsToSave); - }; - Engine.prototype.shouldCheckForMemLeaks = function () { - return this.ENV.getBool('IS_TEST'); - }; - Engine.prototype.checkKernelForMemLeak = function (kernelName, numDataIdsBefore, outInfos) { - var numDataIdsAfter = this.backend.numDataIds(); - // Count the number of data ids associated with the result of the kernel. - var numOutputDataIds = 0; - outInfos.forEach(function (info) { - // Complex numbers allocate 3 data ids, one for 'real', one for - // 'imaginary', and one for the container that holds the former two. - numOutputDataIds += (info.dtype === 'complex64' ? 3 : 1); - }); - // Account for the number of moves during kernel execution. A "data move" - // can happen in the middle of a kernel execution, placing a new (key,value) - // pair in the data storage. Since data moves have net zero effect (we - // always remove the data from the old backend), we have to cancel them out - // when detecting memory leaks. - var numMoves = this.state.numDataMovesStack[this.state.numDataMovesStack.length - 1]; - var dataIdsLeaked = numDataIdsAfter - numDataIdsBefore - numOutputDataIds - numMoves; - if (dataIdsLeaked > 0) { - throw new Error("Backend '" + this.backendName + "' has an internal memory leak " + - ("(" + dataIdsLeaked + " data ids) after running '" + kernelName + "'")); - } - }; - /** - * @deprecated Use `runKernel` for newly added kernels. Keep using this method - * only for kernels that are not yet fully modularized. - */ - Engine.prototype.runKernelFunc = function (forwardFunc, inputs, backwardsFunc, kernelName, attrs, inputsToSave, outputsToSave) { - var _this = this; - var outputs; - var saved = []; - var isTapeOn = this.isTapeOn(); - if (kernelName == null) { - kernelName = - this.state.activeScope != null ? this.state.activeScope.name : ''; - } - var startingBytecount = this.state.numBytes; - var startingNumTensors = this.state.numTensors; - if (this.shouldCheckForMemLeaks()) { - this.state.numDataMovesStack.push(0); - } - var kernelFunc; - var kernel = getKernel(kernelName, this.backendName); - var out; - if (kernel != null) { - kernelFunc = function () { - var numDataIdsBefore = _this.backend.numDataIds(); - out = kernel.kernelFunc({ inputs: inputs, attrs: attrs, backend: _this.backend }); - var outInfos = Array.isArray(out) ? out : [out]; - if (_this.shouldCheckForMemLeaks()) { - _this.checkKernelForMemLeak(kernelName, numDataIdsBefore, outInfos); - } - var outTensors = outInfos.map(function (_a) { - var dataId = _a.dataId, shape = _a.shape, dtype = _a.dtype; - return _this.makeTensorFromDataId(dataId, shape, dtype); - }); - // Save the inputs and outputs. - // Do not save unless we are recording to the tape. Otherwise it would - // cause a mem leak since we would never run backprop, which disposes - // the kept tensors. - if (isTapeOn) { - var tensorsToSave = _this.getTensorsForGradient(kernelName, inputs, outTensors); - if (tensorsToSave == null) { - // Fallback for ops that call runKernelFunc and pass in - // inputsToSave and outputsToSave. Currently this is the set of ops - // with kernel support in the WASM backend. Once those ops and - // respective gradients are modularised we can remove this path. - if (outputsToSave == null) { - outputsToSave = []; - } - var outsToSave = outTensors.filter(function (_, i) { return outputsToSave[i]; }); - tensorsToSave = (inputsToSave || []).slice().concat(outsToSave); - } - saved = _this.saveTensorsForBackwardMode(tensorsToSave); - } - return outTensors; - }; - } - else { - var saveFunc_1 = function (tensors) { - // Do not save unless we are recording to the tape. Otherwise it would - // cause a mem leak since we would never run backprop, which disposes - // the kept tensors. - if (!isTapeOn) { - return; - } - saved = tensors.map(function (tensor) { return _this.keep(_this.clone(tensor)); }); - }; - kernelFunc = function () { - var numDataIdsBefore = _this.backend.numDataIds(); - out = _this.tidy(function () { return forwardFunc(_this.backend, saveFunc_1); }); - var outs = (Array.isArray(out) ? out : [out]); - if (_this.shouldCheckForMemLeaks()) { - _this.checkKernelForMemLeak(kernelName, numDataIdsBefore, outs); - } - return outs; - }; - } - // Stop recording to a tape when running a kernel. - this.scopedRun(function () { return _this.state.kernelDepth++; }, function () { return _this.state.kernelDepth--; }, function () { - if (!_this.ENV.getBool('DEBUG')) { - outputs = kernelFunc(); - } - else { - outputs = _this.profiler.profileKernel(kernelName, inputs, function () { return kernelFunc(); }); - } - }); - if (isTapeOn) { - this.addTapeNode(kernelName, inputs, outputs, backwardsFunc, saved, attrs); - } - if (this.state.profiling) { - this.state.activeProfile.kernels.push({ - name: kernelName, - bytesAdded: this.state.numBytes - startingBytecount, - totalBytesSnapshot: this.state.numBytes, - tensorsAdded: this.state.numTensors - startingNumTensors, - totalTensorsSnapshot: this.state.numTensors, - inputShapes: Object.keys(inputs).map(function (key) { return inputs[key].shape; }), - outputShapes: outputs.map(function (item) { return item.shape; }) - }); - } - return (Array.isArray(out) ? outputs : outputs[0]); - }; - /** - * Saves tensors used in forward mode for use in backward mode. - * - * @param tensors the list of tensors to save. - */ - Engine.prototype.saveTensorsForBackwardMode = function (tensors) { - var _this = this; - var saved = tensors.map(function (tensor) { return _this.keep(_this.clone(tensor)); }); - return saved; - }; - /** - * Returns a list of tensors to save for a given gradient calculation. - * - * Returns undefined if their is no registered gradient for this kernel in the - * gradient registry. - * - * @param kernelName name of kernel to look up gradient for. - * @param inputs a map of input tensors. - * @param outputs an array of output tensors from forward mode of kernel. - */ - Engine.prototype.getTensorsForGradient = function (kernelName, inputs, outputs) { - var gradConfig = getGradient(kernelName); - if (gradConfig != null) { - var inputsToSave = gradConfig.inputsToSave || []; - var outputsToSave_1 = gradConfig.outputsToSave || []; - // If saveAllInputs is true, all inputs will be saved. Otherwise, inputs - // specified in inputsToSave will be saved. - var inputTensorsToSave = void 0; - if (gradConfig.saveAllInputs) { - assert(Array.isArray(inputs), function () { return 'saveAllInputs is true, expected inputs to be an array.'; }); - inputTensorsToSave = Object.keys(inputs).map(function (key) { return inputs[key]; }); - } - else { - inputTensorsToSave = inputsToSave.map(function (inputName) { return inputs[inputName]; }); - } - var outputTensorsToSave = outputs.filter(function (_, i) { return outputsToSave_1[i]; }); - return inputTensorsToSave.concat(outputTensorsToSave); - } - // TODO(yassogba) throw exception here once all runkernelFunc calls with - // inputsToSave/outputsToSave are removed - return null; - }; - /** - * Internal method used by public APIs for tensor creation. Makes a new - * tensor with the provided shape, dtype and values. It always - * creates a new data id and writes the values to the underlying backend. - */ - Engine.prototype.makeTensor = function (values, shape, dtype, backend) { - if (values == null) { - throw new Error('Values passed to engine.makeTensor() are null'); - } - dtype = dtype || 'float32'; - backend = backend || this.backend; - var backendVals = values; - if (dtype === 'string' && isString(values[0])) { - backendVals = values.map(function (d) { return encodeString(d); }); - } - var dataId = backend.write(backendVals, shape, dtype); - var t = new Tensor(shape, dtype, dataId, this.nextTensorId()); - this.incRef(t, backend); - // Count bytes for string tensors. - if (dtype === 'string') { - var info = this.state.tensorInfo.get(dataId); - var newBytes = bytesFromStringArray(backendVals); - this.state.numBytes += newBytes - info.bytes; - info.bytes = newBytes; - } - return t; - }; - /** - * Internal method used by backends. Makes a new tensor - * that is a wrapper around an existing data id. It doesn't create - * a new data id, only increments the ref count used in memory tracking. - */ - Engine.prototype.makeTensorFromDataId = function (dataId, shape, dtype, backend) { - dtype = dtype || 'float32'; - var t = new Tensor(shape, dtype, dataId, this.nextTensorId()); - this.incRef(t, backend); - return t; - }; - Engine.prototype.makeVariable = function (initialValue, trainable, name, dtype) { - if (trainable === void 0) { trainable = true; } - name = name || this.nextVariableId().toString(); - if (dtype != null && dtype !== initialValue.dtype) { - initialValue = initialValue.cast(dtype); - } - var v = new Variable(initialValue, trainable, name, this.nextTensorId()); - if (this.state.registeredVariables[v.name] != null) { - throw new Error("Variable with name " + v.name + " was already registered"); - } - this.state.registeredVariables[v.name] = v; - this.incRef(v, this.backend); - return v; - }; - Engine.prototype.incRef = function (a, backend) { - var refCount = this.state.tensorInfo.has(a.dataId) ? - this.state.tensorInfo.get(a.dataId).refCount : - 0; - this.state.numTensors++; - if (a.dtype === 'string') { - this.state.numStringTensors++; - } - if (refCount === 0) { - this.state.numDataBuffers++; - // Bytes for complex numbers are counted by their components. Bytes for - // string tensors are counted when writing values. - var bytes = 0; - if (a.dtype !== 'complex64' && a.dtype !== 'string') { - bytes = a.size * bytesPerElement(a.dtype); - } - this.state.tensorInfo.set(a.dataId, { - backend: backend || this.backend, - dtype: a.dtype, - shape: a.shape, - bytes: bytes, - refCount: 0 - }); - this.state.numBytes += bytes; - } - this.state.tensorInfo.get(a.dataId).refCount++; - if (!(a instanceof Variable)) { - this.track(a); - } - }; - Engine.prototype.disposeTensor = function (a) { - if (!this.state.tensorInfo.has(a.dataId)) { - return; - } - this.state.numTensors--; - if (a.dtype === 'string') { - this.state.numStringTensors--; - } - var info = this.state.tensorInfo.get(a.dataId); - var refCount = info.refCount; - if (refCount <= 1) { - // Don't count bytes for complex numbers as they are counted by their - // components. - if (a.dtype !== 'complex64') { - this.state.numBytes -= info.bytes; - } - this.state.numDataBuffers--; - info.backend.disposeData(a.dataId); - this.state.tensorInfo.delete(a.dataId); - } - else { - this.state.tensorInfo.get(a.dataId).refCount--; - } - // TODO(nsthorat): Construct an error and save the stack trace for - // debugging when in debug mode. Creating a stack trace is too expensive - // to do unconditionally. - }; - Engine.prototype.disposeVariables = function () { - for (var varName in this.state.registeredVariables) { - var v = this.state.registeredVariables[varName]; - this.disposeVariable(v); - } - }; - Engine.prototype.disposeVariable = function (v) { - this.disposeTensor(v); - if (this.state.registeredVariables[v.name] != null) { - delete this.state.registeredVariables[v.name]; - } - }; - Engine.prototype.memory = function () { - var info = this.backend.memory(); - info.numTensors = this.state.numTensors; - info.numDataBuffers = this.state.numDataBuffers; - info.numBytes = this.state.numBytes; - if (this.state.numStringTensors > 0) { - info.unreliable = true; - if (info.reasons == null) { - info.reasons = []; - } - info.reasons.push('Memory usage by string tensors is approximate ' + - '(2 bytes per character)'); - } - return info; - }; - Engine.prototype.profile = function (query) { - return __awaiter(this, void 0, void 0, function () { - var startBytes, startNumTensors, _a; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: - this.state.profiling = true; - startBytes = this.state.numBytes; - startNumTensors = this.state.numTensors; - this.state.activeProfile.kernels = []; - _a = this.state.activeProfile; - return [4 /*yield*/, query()]; - case 1: - _a.result = _b.sent(); - this.state.profiling = false; - this.state.activeProfile.peakBytes = Math.max.apply(Math, this.state.activeProfile.kernels.map(function (d) { return d.totalBytesSnapshot; })); - this.state.activeProfile.newBytes = this.state.numBytes - startBytes; - this.state.activeProfile.newTensors = - this.state.numTensors - startNumTensors; - return [2 /*return*/, this.state.activeProfile]; - } - }); - }); - }; - Engine.prototype.isTapeOn = function () { - return this.state.gradientDepth > 0 && this.state.kernelDepth === 0; - }; - Engine.prototype.addTapeNode = function (kernelName, inputs, outputs, gradientsFunc, saved, attrs) { - var _this = this; - var tapeNode = { id: this.state.nextTapeNodeId++, kernelName: kernelName, inputs: inputs, outputs: outputs, saved: saved }; - var gradConfig = getGradient(kernelName); - if (gradConfig != null) { - gradientsFunc = gradConfig.gradFunc; - } - if (gradientsFunc != null) { - tapeNode.gradient = function (dys) { - // TODO(smilkov): To optimize back-prop, pass dys that are not used in - // the backprop graph to the user as null instead of zeros - dys = dys.map(function (dy, i) { - if (dy == null) { - var output = outputs[i]; - var vals = makeZerosTypedArray(output.size, output.dtype); - return _this.makeTensor(vals, output.shape, output.dtype); - } - return dy; - }); - // Grad functions of ops with single outputs expect a dy, while ops - // with multiple outputs expect dys (array of dy). - return gradientsFunc(dys.length > 1 ? dys : dys[0], saved, attrs); - }; - } - this.state.activeTape.push(tapeNode); - }; - Engine.prototype.keep = function (result) { - result.kept = true; - return result; - }; - Engine.prototype.startTape = function () { - if (this.state.gradientDepth === 0) { - this.state.activeTape = []; - } - this.state.gradientDepth++; - }; - Engine.prototype.endTape = function () { - this.state.gradientDepth--; - }; - /** - * Start a scope. Use this with endScope() to achieve the same functionality - * as scope() without the need for a function closure. - */ - Engine.prototype.startScope = function (name) { - var scopeInfo = { - track: [], - name: 'unnamed scope', - id: this.state.nextScopeId++ - }; - if (name) { - scopeInfo.name = name; - } - this.state.scopeStack.push(scopeInfo); - this.state.activeScope = scopeInfo; - }; - /** - * End a scope. Use this with startScope() to achieve the same functionality - * as scope() without the need for a function closure. - */ - Engine.prototype.endScope = function (result) { - var _this = this; - var tensorsToTrackInParent = getTensorsInContainer(result); - var tensorsToTrackInParentSet = new Set(tensorsToTrackInParent.map(function (t) { return t.id; })); - // Dispose the arrays tracked in this scope. - for (var i = 0; i < this.state.activeScope.track.length; i++) { - var tensor = this.state.activeScope.track[i]; - if (!tensor.kept && !tensorsToTrackInParentSet.has(tensor.id)) { - tensor.dispose(); - } - } - var oldScope = this.state.scopeStack.pop(); - this.state.activeScope = this.state.scopeStack.length === 0 ? - null : - this.state.scopeStack[this.state.scopeStack.length - 1]; - // Track the current result in the parent scope. - tensorsToTrackInParent.forEach(function (tensor) { - // Only track the tensor if was allocated in the inner scope and is not - // globally kept. - if (!tensor.kept && tensor.scopeId === oldScope.id) { - _this.track(tensor); - } - }); - }; - /** - * Returns gradients of `f` with respect to each of the `xs`. The gradients - * returned are of the same length as `xs`, but some might be null if `f` - * was not a function of that `x`. It also takes optional dy to multiply the - * gradient, which defaults to `1`. - */ - Engine.prototype.gradients = function (f, xs, dy, allowNoGradients) { - var _this = this; - if (allowNoGradients === void 0) { allowNoGradients = false; } - assert(xs.length > 0, function () { return 'gradients() received an empty list of xs.'; }); - if (dy != null && dy.dtype !== 'float32') { - throw new Error("dy must have 'float32' dtype, but has '" + dy.dtype + "'"); - } - var y = this.scopedRun(function () { return _this.startTape(); }, function () { return _this.endTape(); }, function () { return _this.tidy('forward', f); }); - assert(y instanceof Tensor, function () { return 'The result y returned by f() must be a tensor.'; }); - // Filter out the nodes that don't connect x => y. - var filteredTape = getFilteredNodesXToY(this.state.activeTape, xs, y); - if (!allowNoGradients && filteredTape.length === 0 && xs.length > 0) { - throw new Error('Cannot compute gradient of y=f(x) with respect to x. Make sure ' + - 'that the f you passed encloses all operations that lead from x ' + - 'to y.'); - } - return this.tidy('backward', function () { - var accumulatedGradientMap = {}; - accumulatedGradientMap[y.id] = (dy == null) ? ones(y.shape) : dy; - // Backprop gradients through the filtered nodes. - backpropagateGradients(accumulatedGradientMap, filteredTape, - // Pass the tidy function to avoid circular dep with `tape.ts`. - function (f) { return _this.tidy(f); }); - var grads = xs.map(function (x) { return accumulatedGradientMap[x.id]; }); - if (_this.state.gradientDepth === 0) { - // This means that we are not computing higher-order gradients - // and can clean up the tape. - _this.state.activeTape.forEach(function (node) { - for (var _i = 0, _a = node.saved; _i < _a.length; _i++) { - var tensor = _a[_i]; - tensor.dispose(); - } - }); - _this.state.activeTape = null; - } - return { value: y, grads: grads }; - }); - }; - Engine.prototype.customGrad = function (f) { - var _this = this; - assert(isFunction(f), function () { return 'The f passed in customGrad(f) must be a function.'; }); - return function () { - var inputs = []; - for (var _i = 0; _i < arguments.length; _i++) { - inputs[_i] = arguments[_i]; - } - assert(inputs.every(function (t) { return t instanceof Tensor; }), function () { return 'The args passed in customGrad(f)(x1, x2,...) must all be ' + - 'tensors'; }); - var res; - var inputMap = {}; - inputs.forEach(function (input, i) { - inputMap[i] = input; - }); - return _this.runKernelFunc(function (_, save) { - res = f.apply(void 0, inputs.concat([save])); - assert(res.value instanceof Tensor, function () { return 'The function f passed in customGrad(f) must return an ' + - 'object where `obj.value` is a tensor'; }); - assert(isFunction(res.gradFunc), function () { return 'The function f passed in customGrad(f) must return an ' + - 'object where `obj.gradFunc` is a function.'; }); - return res.value; - }, inputMap, function (dy, saved) { - var gradRes = res.gradFunc(dy, saved); - var grads = Array.isArray(gradRes) ? gradRes : [gradRes]; - assert(grads.length === inputs.length, function () { return 'The function f passed in customGrad(f) must return an ' + - 'object where `obj.gradFunc` is a function that returns ' + - 'the same number of tensors as inputs passed to f(...).'; }); - assert(grads.every(function (t) { return t instanceof Tensor; }), function () { return 'The function f passed in customGrad(f) must return an ' + - 'object where `obj.gradFunc` is a function that returns ' + - 'a list of only tensors.'; }); - var gradMap = {}; - grads.forEach(function (grad, i) { - gradMap[i] = function () { return grad; }; - }); - return gradMap; - }); - }; - }; - Engine.prototype.readSync = function (dataId) { - // Route the read to the correct backend. - var info = this.state.tensorInfo.get(dataId); - return info.backend.readSync(dataId); - }; - Engine.prototype.read = function (dataId) { - // Route the read to the correct backend. - var info = this.state.tensorInfo.get(dataId); - return info.backend.read(dataId); - }; - Engine.prototype.time = function (query) { - return __awaiter(this, void 0, void 0, function () { - var start, timingInfo; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - start = now(); - return [4 /*yield*/, this.backend.time(query)]; - case 1: - timingInfo = _a.sent(); - timingInfo.wallMs = now() - start; - return [2 /*return*/, timingInfo]; - } - }); - }); - }; - /** - * Tracks a Tensor in the current scope to be automatically cleaned up - * when the current scope ends, and returns the value. - * - * @param result The Tensor to track in the current scope. - */ - Engine.prototype.track = function (result) { - if (this.state.activeScope != null) { - result.scopeId = this.state.activeScope.id; - this.state.activeScope.track.push(result); - } - return result; - }; - Object.defineProperty(Engine.prototype, "registeredVariables", { - get: function () { - return this.state.registeredVariables; - }, - enumerable: true, - configurable: true - }); - /** - * Resets the engine state. Removes all backends but does not remove - * registered backend factories. - */ - Engine.prototype.reset = function () { - // Make any pending promise obsolete. - this.pendingBackendInitId++; - this.state.dispose(); - this.ENV.reset(); - this.state = new EngineState(); - for (var backendName in this.registry) { - this.disposeRegisteredKernels(backendName); - this.registry[backendName].dispose(); - delete this.registry[backendName]; - } - this.backendName = null; - this.backendInstance = null; - this.pendingBackendInit = null; - }; - Engine.nextTensorId = 0; - Engine.nextVariableId = 0; - return Engine; - }()); - function ones(shape) { - var values = makeOnesTypedArray(sizeFromShape(shape), 'float32'); - return ENGINE.makeTensor(values, shape, 'float32'); - } - function getOrMakeEngine() { - var ns = getGlobalNamespace(); - if (ns._tfengine == null) { - var environment = new Environment(ns); - ns._tfengine = new Engine(environment); - } - setEnvironmentGlobal(ns._tfengine.ENV); - // Tell the current tensor interface that the global engine is responsible - // for tracking. - setTensorTracker(function () { return ns._tfengine; }); - return ns._tfengine; - } - var ENGINE = getOrMakeEngine(); - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // tslint:disable-next-line:no-any - function _isNavigatorDefined() { - return typeof navigator !== 'undefined' && navigator != null; - } - function isMobile() { - if (_isNavigatorDefined()) { - // tslint:disable-next-line:no-any - var a = navigator.userAgent || navigator.vendor || window.opera; - // tslint:disable-next-line:max-line-length - return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i - .test(a) || - // tslint:disable-next-line:max-line-length - /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i - .test(a.substr(0, 4)); - } - return false; - } - function isBrowser() { - return (typeof window !== 'undefined' && window.document != null) || - //@ts-ignore - (typeof WorkerGlobalScope !== 'undefined'); - } - - var device_util = { - __proto__: null, - isMobile: isMobile, - isBrowser: isBrowser - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var ENV = env(); - /** - * This file contains environment-related flag registrations. - */ - /** Whether to enable debug mode. */ - ENV.registerFlag('DEBUG', function () { return false; }, function (debugValue) { - if (debugValue) { - console.warn('Debugging mode is ON. The output of every math call will ' + - 'be downloaded to CPU and checked for NaNs. ' + - 'This significantly impacts performance.'); - } - }); - /** Whether we are in a browser (as versus, say, node.js) environment. */ - ENV.registerFlag('IS_BROWSER', function () { return isBrowser(); }); - /** Whether we are in a browser (as versus, say, node.js) environment. */ - ENV.registerFlag('IS_NODE', function () { return (typeof process !== 'undefined') && - (typeof process.versions !== 'undefined') && - (typeof process.versions.node !== 'undefined'); }); - /** Whether this browser is Chrome. */ - ENV.registerFlag('IS_CHROME', function () { return typeof navigator !== 'undefined' && navigator != null && - navigator.userAgent != null && /Chrome/.test(navigator.userAgent) && - /Google Inc/.test(navigator.vendor); }); - /** - * True when the environment is "production" where we disable safety checks - * to gain performance. - */ - ENV.registerFlag('PROD', function () { return false; }); - /** - * Whether to do sanity checks when inferring a shape from user-provided - * values, used when creating a new tensor. - */ - ENV.registerFlag('TENSORLIKE_CHECK_SHAPE_CONSISTENCY', function () { return ENV.getBool('DEBUG'); }); - /** Whether deprecation warnings are enabled. */ - ENV.registerFlag('DEPRECATION_WARNINGS_ENABLED', function () { return true; }); - /** True if running unit tests. */ - ENV.registerFlag('IS_TEST', function () { return false; }); - - var Abs = 'Abs'; - var Acos = 'Acos'; - var Acosh = 'Acosh'; - var Add = 'Add'; - var AddN = 'AddN'; - var All = 'All'; - var Any = 'Any'; - var ArgMax = 'ArgMax'; - var ArgMin = 'ArgMin'; - var Asin = 'Asin'; - var Asinh = 'Asinh'; - var Atan = 'Atan'; - var Atanh = 'Atanh'; - var Atan2 = 'Atan2'; - var AvgPool = 'AvgPool'; - var AvgPoolBackprop = 'AvgPoolBackprop'; - var AvgPool3D = 'AvgPool3D'; - var AvgPool3DBackprop = 'AvgPool3DBackprop'; - var BatchMatMul = 'BatchMatMul'; - var BatchToSpaceND = 'BatchToSpaceND'; - var BroadcastTo = 'BroadcastTo'; - var Cast = 'Cast'; - var Ceil = 'Ceil'; - var ClipByValue = 'ClipByValue'; - var Complex = 'Complex'; - var Concat = 'Concat'; - var Conv2D = 'Conv2D'; - var Conv2DBackpropFilter = 'Conv2DBackpropFilter'; - var Conv2DBackpropInput = 'Conv2DBackpropInput'; - var Conv3D = 'Conv3D'; - var Conv3DBackpropFilterV2 = 'Conv3DBackpropFilterV2'; - var Conv3DBackpropInputV2 = 'Conv3DBackpropInputV2'; - var Cos = 'Cos'; - var Cosh = 'Cosh'; - var Cumsum = 'Cumsum'; - var CropAndResize = 'CropAndResize'; - var DepthToSpace = 'DepthToSpace'; - var DepthwiseConv2dNative = 'DepthwiseConv2dNative'; - var DepthwiseConv2dNativeBackpropFilter = 'DepthwiseConv2dNativeBackpropFilter'; - var DepthwiseConv2dNativeBackpropInput = 'DepthwiseConv2dNativeBackpropInput'; - var Diag = 'Diag'; - var Dilation2D = 'Dilation2D'; - var Dilation2DBackpropInput = 'Dilation2DBackpropInput'; - var Dilation2DBackpropFilter = 'Dilation2DBackpropFilter'; - var Div = 'Div'; - var Elu = 'Elu'; - var EluGrad = 'EluGrad'; - var Erf = 'Erf'; - var Equal = 'Equal'; - var Exp = 'Exp'; - var Expm1 = 'Expm1'; - var FFT = 'FFT'; - var Floor = 'Floor'; - var FloorDiv = 'FloorDiv'; - var Fill = 'Fill'; - var FusedBatchNorm = 'FusedBatchNorm'; - var GatherV2 = 'GatherV2'; - var GatherNd = 'GatherNd'; - var Greater = 'Greater'; - var GreaterEqual = 'GreaterEqual'; - var Identity = 'Identity'; - var IFFT = 'IFFT'; - var Imag = 'Imag'; - var IsFinite = 'IsFinite'; - var IsInf = 'IsInf'; - var IsNan = 'IsNan'; - var Less = 'Less'; - var LessEqual = 'LessEqual'; - var LinSpace = 'LinSpace'; - var Log = 'Log'; - var Log1p = 'Log1p'; - var LogicalAnd = 'LogicalAnd'; - var LogicalNot = 'LogicalNot'; - var LogicalOr = 'LogicalOr'; - var LogSoftmax = 'LogSoftmax'; - var LRN = 'LRN'; - var LRNBackprop = 'LRNBackprop'; - var Max = 'Max'; - var Maximum = 'Maximum'; - var MaxPool = 'MaxPool'; - var MaxPoolBackprop = 'MaxPoolBackprop'; - var MaxPool3D = 'MaxPool3D'; - var MaxPool3DBackprop = 'MaxPool3DBackprop'; - var MaxPoolWithArgmax = 'MaxPoolWithArgmax'; - var Mean = 'Mean'; - var Min = 'Min'; - var Minimum = 'Minimum'; - var Mod = 'Mod'; - var Multiply = 'Multiply'; - var Negate = 'Negate'; - var NotEqual = 'NotEqual'; - var NonMaxSuppressionV3 = 'NonMaxSuppressionV3'; - var NonMaxSuppressionV4 = 'NonMaxSuppressionV4'; - var NonMaxSuppressionV5 = 'NonMaxSuppressionV5'; - var OnesLike = 'OnesLike'; - var OneHot = 'OneHot'; - var PadV2 = 'PadV2'; - var Pool = 'Pool'; - var Pow = 'Pow'; - var Prelu = 'Prelu'; - var Prod = 'Prod'; - var Range = 'Range'; - var Real = 'Real'; - var Reciprocal = 'Reciprocal'; - var Relu = 'Relu'; - var Reshape = 'Reshape'; - var ResizeNearestNeighbor = 'ResizeNearestNeighbor'; - var ResizeNearestNeighborGrad = 'ResizeNearestNeighborGrad'; - var ResizeBilinear = 'ResizeBilinear'; - var ResizeBilinearGrad = 'ResizeBilinearGrad'; - var Relu6 = 'Relu6'; - var Reverse = 'Reverse'; - var Round = 'Round'; - var Rsqrt = 'Rsqrt'; - var ScatterNd = 'ScatterNd'; - var SelectV2 = 'SelectV2'; - var Selu = 'Selu'; - var Slice = 'Slice'; - var Sin = 'Sin'; - var Sinh = 'Sinh'; - var Sign = 'Sign'; - var Sigmoid = 'Sigmoid'; - var Softplus = 'Softplus'; - var Sqrt = 'Sqrt'; - var Sum = 'Sum'; - var SpaceToBatchND = 'SpaceToBatchND'; - var SplitV = 'SplitV'; - var Softmax = 'Softmax'; - var SquaredDifference = 'SquaredDifference'; - var Square = 'Square'; - var Sub = 'Sub'; - var SparseToDense = 'SparseToDense'; - var StridedSlice = 'StridedSlice'; - var Tan = 'Tan'; - var Tanh = 'Tanh'; - var Tile = 'Tile'; - var TopK = 'TopK'; - var Transpose = 'Transpose'; - var Unpack = 'Unpack'; - var UnsortedSegmentSum = 'UnsortedSegmentSum'; - var ZerosLike = 'ZerosLike'; - /** - * TensorFlow.js-only kernels - */ - var Step = 'Step'; - var FromPixels = 'FromPixels'; - var RotateWithOffset = 'RotateWithOffset'; - var _FusedMatMul = '_FusedMatMul'; - var FusedConv2D = 'FusedConv2D'; - var FusedDepthwiseConv2D = 'FusedDepthwiseConv2D'; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function inferShape(val, dtype) { - var firstElem = val; - if (isTypedArray(val)) { - return dtype === 'string' ? [] : [val.length]; - } - if (!Array.isArray(val)) { - return []; // Scalar. - } - var shape = []; - while (Array.isArray(firstElem) || - isTypedArray(firstElem) && dtype !== 'string') { - shape.push(firstElem.length); - firstElem = firstElem[0]; - } - if (Array.isArray(val) && - env().getBool('TENSORLIKE_CHECK_SHAPE_CONSISTENCY')) { - deepAssertShapeConsistency(val, shape, []); - } - return shape; - } - function deepAssertShapeConsistency(val, shape, indices) { - indices = indices || []; - if (!(Array.isArray(val)) && !isTypedArray(val)) { - assert(shape.length === 0, function () { return "Element arr[" + indices.join('][') + "] is a primitive, " + - ("but should be an array/TypedArray of " + shape[0] + " elements"); }); - return; - } - assert(shape.length > 0, function () { return "Element arr[" + indices.join('][') + "] should be a primitive, " + - ("but is an array of " + val.length + " elements"); }); - assert(val.length === shape[0], function () { return "Element arr[" + indices.join('][') + "] should have " + shape[0] + " " + - ("elements, but has " + val.length + " elements"); }); - var subShape = shape.slice(1); - for (var i = 0; i < val.length; ++i) { - deepAssertShapeConsistency(val[i], subShape, indices.concat(i)); - } - } - function assertDtype(expectedDtype, actualDType, argName, functionName) { - if (expectedDtype == null) { - return; - } - if (expectedDtype !== 'numeric' && expectedDtype !== actualDType || - expectedDtype === 'numeric' && actualDType === 'string') { - throw new Error("Argument '" + argName + "' passed to '" + functionName + "' must " + - ("be " + expectedDtype + " tensor, but got " + actualDType + " tensor")); - } - } - function convertToTensor(x, argName, functionName, parseAsDtype) { - if (parseAsDtype === void 0) { parseAsDtype = 'numeric'; } - if (x instanceof Tensor) { - assertDtype(parseAsDtype, x.dtype, argName, functionName); - return x; - } - var inferredDtype = inferDtype(x); - // If the user expects a bool/int/float, use that info to update the - // inferredDtype when it is not a string. - if (inferredDtype !== 'string' && - ['bool', 'int32', 'float32'].indexOf(parseAsDtype) >= 0) { - inferredDtype = parseAsDtype; - } - assertDtype(parseAsDtype, inferredDtype, argName, functionName); - if ((x == null) || - (!isTypedArray(x) && !Array.isArray(x) && typeof x !== 'number' && - typeof x !== 'boolean' && typeof x !== 'string')) { - var type = x == null ? 'null' : x.constructor.name; - throw new Error("Argument '" + argName + "' passed to '" + functionName + "' must be a " + - ("Tensor or TensorLike, but got '" + type + "'")); - } - var inferredShape = inferShape(x, inferredDtype); - if (!isTypedArray(x) && !Array.isArray(x)) { - x = [x]; - } - var skipTypedArray = true; - var values = inferredDtype !== 'string' ? - toTypedArray(x, inferredDtype) : - flatten(x, [], skipTypedArray); - return ENGINE.makeTensor(values, inferredShape, inferredDtype); - } - function convertToTensorArray(arg, argName, functionName, parseAsDtype) { - if (parseAsDtype === void 0) { parseAsDtype = 'numeric'; } - if (!Array.isArray(arg)) { - throw new Error("Argument " + argName + " passed to " + functionName + " must be a " + - '`Tensor[]` or `TensorLike[]`'); - } - var tensors = arg; - return tensors.map(function (t, i) { return convertToTensor(t, argName + "[" + i + "]", functionName); }, parseAsDtype); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Used for wrapping functions that perform math operations on - * Tensors. The function will be wrapped in a named scope that cleans all - * memory usage after the function is done. - */ - function op(f) { - var keys = Object.keys(f); - if (keys.length !== 1) { - throw new Error("Please provide an object with a single key " + - "(operation name) mapping to a function. Got an object with " + - (keys.length + " keys.")); - } - var opName = keys[0]; - var fn = f[opName]; - // Strip the underscore from the end of the function name. - if (opName.endsWith('_')) { - opName = opName.substring(0, opName.length - 1); - } - // tslint:disable-next-line:no-any - var f2 = function () { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - ENGINE.startScope(opName); - try { - var result = fn.apply(void 0, args); - if (result instanceof Promise) { - console.error('Cannot return a Promise inside of tidy.'); - } - ENGINE.endScope(result); - return result; - } - catch (ex) { - ENGINE.endScope(null); - throw ex; - } - }; - Object.defineProperty(f2, 'name', { value: opName, configurable: true }); - // tslint:disable-next-line:no-any - return f2; - } - - /** - * @license - * Copyright 2020 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Casts a `tf.Tensor` to a new dtype. - * - * ```js - * const x = tf.tensor1d([1.5, 2.5, 3]); - * tf.cast(x, 'int32').print(); - * ``` - * @param x The input tensor to be casted. - * @param dtype The dtype to cast the input tensor to. - */ - /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ - function cast_(x, dtype) { - var $x = convertToTensor(x, 'x', 'cast'); - // Sanity checks. - if (!isValidDtype(dtype)) { - throw new Error("Failed to cast to unknown dtype " + dtype); - } - if (dtype === 'string' && $x.dtype !== 'string' || - dtype !== 'string' && $x.dtype === 'string') { - throw new Error('Only strings can be casted to strings'); - } - var inputs = { x: $x }; - var attrs = { dtype: dtype }; - return ENGINE.runKernelFunc(function (backend) { return backend.cast($x, dtype); }, inputs, null /* grad */, Cast, attrs); - } - var cast = op({ cast_: cast_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Multiplies two `tf.Tensor`s element-wise, A * B. Supports broadcasting. - * - * We also expose `tf.mulStrict` which has the same signature as this op and - * asserts that `a` and `b` are the same shape (does not broadcast). - * - * ```js - * const a = tf.tensor1d([1, 2, 3, 4]); - * const b = tf.tensor1d([2, 3, 4, 5]); - * - * a.mul(b).print(); // or tf.mul(a, b) - * ``` - * - * ```js - * // Broadcast mul a with b. - * const a = tf.tensor1d([1, 2, 3, 4]); - * const b = tf.scalar(5); - * - * a.mul(b).print(); // or tf.mul(a, b) - * ``` - * @param a The first tensor to multiply. - * @param b The second tensor to multiply. Must have the same dtype as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ - function mul_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'mul'); - var $b = convertToTensor(b, 'b', 'mul'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - var forward = function (backend, save) { - var res = backend.multiply($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Multiply); - } - var mul = op({ mul_: mul_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes step of the input `tf.Tensor` element-wise: `x > 0 ? 1 : alpha * x` - * - * ```js - * const x = tf.tensor1d([0, 2, -1, -3]); - * - * x.step(.5).print(); // or tf.step(x, .5) - * ``` - * @param x The input tensor. - * @param alpha The gradient when input is negative. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function step_(x, alpha) { - if (alpha === void 0) { alpha = 0.0; } - var $x = convertToTensor(x, 'x', 'step'); - var inputs = { x: $x }; - var attrs = { alpha: alpha }; - return ENGINE.runKernelFunc(function (backend) { return backend.step($x, alpha); }, inputs, null /* grad */, Step, attrs); - } - var step = op({ step_: step_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var absGradConfig = { - kernelName: Abs, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(dy, step(cast(x, 'float32'), -1)); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Divides two `tf.Tensor`s element-wise, A / B. Supports broadcasting. - * The result is rounded with floor function. - * - * - * ```js - * const a = tf.tensor1d([1, 4, 9, 16]); - * const b = tf.tensor1d([1, 2, 3, 4]); - * - * a.floorDiv(b).print(); // or tf.div(a, b) - * ``` - * - * ```js - * // Broadcast div a with b. - * const a = tf.tensor1d([2, 4, 6, 8]); - * const b = tf.scalar(2); - * - * a.floorDiv(b).print(); // or tf.floorDiv(a, b) - * ``` - * - * @param a The first tensor as the numerator. - * @param b The second tensor as the denominator. Must have the same dtype as - * `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ - function floorDiv_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'floorDiv'); - var $b = convertToTensor(b, 'b', 'floorDiv'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - var forward = function (backend, save) { - var res = backend.floorDiv($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, FloorDiv); - } - var floorDiv = op({ floorDiv_: floorDiv_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Divides two `tf.Tensor`s element-wise, A / B. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([1, 4, 9, 16]); - * const b = tf.tensor1d([1, 2, 3, 4]); - * - * a.div(b).print(); // or tf.div(a, b) - * ``` - * - * ```js - * // Broadcast div a with b. - * const a = tf.tensor1d([2, 4, 6, 8]); - * const b = tf.scalar(2); - * - * a.div(b).print(); // or tf.div(a, b) - * ``` - * - * @param a The first tensor as the numerator. - * @param b The second tensor as the denominator. Must have the same dtype as - * `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ - function div_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'div'); - var $b = convertToTensor(b, 'b', 'div'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - if ($a.dtype === 'int32' && $b.dtype === 'int32') { - return floorDiv($a, $b); - } - var forward = function (backend, save) { - var res = backend.realDivide($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - var attrs = {}; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Div, attrs); - } - var div = op({ div_: div_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes `-1 * x` element-wise. - * - * ```js - * const x = tf.tensor2d([1, 2, -2, 0], [2, 2]); - * - * x.neg().print(); // or tf.neg(x) - * ``` - * - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function neg_(x) { - var $x = convertToTensor(x, 'x', 'neg'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend) { return backend.neg($x); }, inputs, null /* grad */, Negate); - } - var neg = op({ neg_: neg_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** This is shared code across all tensor creation methods. */ - function makeTensor(values, shape, inferredShape, dtype) { - if (dtype == null) { - dtype = inferDtype(values); - } - if (dtype === 'complex64') { - throw new Error("Cannot construct a complex64 tensor directly. " + - "Please use tf.complex(real, imag)."); - } - if (!isTypedArray(values) && !Array.isArray(values) && - typeof values !== 'number' && typeof values !== 'boolean' && - typeof values !== 'string') { - throw new Error('values passed to tensor(values) must be a number/boolean/string or ' + - 'an array of numbers/booleans/strings, or a TypedArray'); - } - if (shape != null) { - assertNonNegativeIntegerDimensions(shape); - var providedSize_1 = sizeFromShape(shape); - var inferredSize_1 = sizeFromShape(inferredShape); - assert(providedSize_1 === inferredSize_1, function () { - return "Based on the provided shape, [" + shape + "], the tensor should have " + - (providedSize_1 + " values but has " + inferredSize_1); - }); - for (var i = 0; i < inferredShape.length; ++i) { - var inferred = inferredShape[i]; - var flatDimsDontMatch = i === inferredShape.length - 1 ? - inferred !== sizeFromShape(shape.slice(i)) : - true; - assert(inferredShape[i] === shape[i] || !flatDimsDontMatch, function () { return "Error creating a new Tensor. Inferred shape " + - ("(" + inferredShape + ") does not match the provided ") + - ("shape (" + shape + "). "); }); - } - } - if (!isTypedArray(values) && !Array.isArray(values)) { - values = [values]; - } - shape = shape || inferredShape; - values = dtype !== 'string' ? - toTypedArray(values, dtype) : - flatten(values, [], true); - return ENGINE.makeTensor(values, shape, dtype); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates rank-0 `tf.Tensor` (scalar) with the provided value and dtype. - * - * The same functionality can be achieved with `tf.tensor`, but in general - * we recommend using `tf.scalar` as it makes the code more readable. - * - * ```js - * tf.scalar(3.14).print(); - * ``` - * - * @param value The value of the scalar. - * @param dtype The data type. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function scalar(value, dtype) { - if (((isTypedArray(value) && dtype !== 'string') || Array.isArray(value)) && - dtype !== 'complex64') { - throw new Error('Error creating a new Scalar: value must be a primitive ' + - '(number|boolean|string)'); - } - if (dtype === 'string' && isTypedArray(value) && - !(value instanceof Uint8Array)) { - throw new Error('When making a scalar from encoded string, ' + - 'the value must be `Uint8Array`.'); - } - var shape = []; - var inferredShape = []; - return makeTensor(value, shape, inferredShape, dtype); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes square root of the input `tf.Tensor` element-wise: `y = sqrt(x)` - * - * ```js - * const x = tf.tensor1d([1, 2, 4, -1]); - * - * x.sqrt().print(); // or tf.sqrt(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function sqrt_(x) { - var $x = convertToTensor(x, 'x', 'sqrt'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.sqrt($x); - save([$x]); - return res; - }, inputs, null /* grad */, Sqrt); - } - var sqrt = op({ sqrt_: sqrt_ }); - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes square of `x` element-wise: `x ^ 2` - * - * ```js - * const x = tf.tensor1d([1, 2, Math.sqrt(2), -1]); - * - * x.square().print(); // or tf.square(x) - * ``` - * @param x The input Tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function square_(x) { - var $x = convertToTensor(x, 'x', 'square'); - var attrs = {}; - var inputsToSave = [$x]; - var outputsToSave = []; - return ENGINE.runKernelFunc(function (backend, save) { - save([$x]); - return backend.square($x); - }, { x: $x }, null /* grad */, 'Square', attrs, inputsToSave, outputsToSave); - } - var square = op({ square_: square_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Subtracts two `tf.Tensor`s element-wise, A - B. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([10, 20, 30, 40]); - * const b = tf.tensor1d([1, 2, 3, 4]); - * - * a.sub(b).print(); // or tf.sub(a, b) - * ``` - * - * ```js - * // Broadcast subtract a with b. - * const a = tf.tensor1d([10, 20, 30, 40]); - * const b = tf.scalar(5); - * - * a.sub(b).print(); // or tf.sub(a, b) - * ``` - * @param a The first `tf.Tensor` to subtract from. - * @param b The second `tf.Tensor` to be subtracted. Must have the same dtype as - * `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ - function sub_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'sub'); - var $b = convertToTensor(b, 'b', 'sub'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - var forward = function (backend, save) { - var res = backend.subtract($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Sub); - } - var sub = op({ sub_: sub_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var acosGradConfig = { - kernelName: Acos, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { - x: function () { - var a = square(cast(x, 'float32')); - var b = sqrt(sub(scalar(1), a)); - return neg(div(dy, b)); - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var acoshGradConfig = { - kernelName: Acosh, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { - x: function () { - var a = sqrt(sub(square(cast(x, 'float32')), 1)); - return div(dy, a); - } - }; - } - }; - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the dimensions in the input shape that are broadcasted to - * produce the provided output shape. - * - * The returned dimensions are 0-indexed and sorted. An example: - * inShape = [4, 1, 3] - * outShape = [5, 4, 3, 3] - * result = [1]. Dimension 1 (2nd dimension of input) gets broadcasted 1 => 3. - */ - function getBroadcastDims(inShape, outShape) { - var inRank = inShape.length; - var dims = []; - for (var i = 0; i < inRank; i++) { - var dim = inRank - 1 - i; - var a = inShape[dim] || 1; - var b = outShape[outShape.length - 1 - i] || 1; - if (b > 1 && a === 1) { - dims.unshift(dim); - } - } - return dims; - } - /** - * Returns the axes in the output space that should be reduced to produce - * the input space. - */ - function getReductionAxes(inShape, outShape) { - var result = []; - for (var i = 0; i < outShape.length; i++) { - var inDim = inShape[inShape.length - i - 1]; - var outAxis = outShape.length - i - 1; - var outDim = outShape[outAxis]; - if (inDim == null || (inDim === 1 && outDim > 1)) { - result.unshift(outAxis); - } - } - return result; - } - function assertAndGetBroadcastShape(shapeA, shapeB) { - var result = []; - var l = Math.max(shapeA.length, shapeB.length); - for (var i = 0; i < l; i++) { - var a = shapeA[shapeA.length - i - 1]; - if (a == null) { - a = 1; - } - var b = shapeB[shapeB.length - i - 1]; - if (b == null) { - b = 1; - } - if (a === 1) { - result.unshift(b); - } - else if (b === 1) { - result.unshift(a); - } - else if (a !== b) { - var errMsg = "Operands could not be broadcast together with shapes " + - (shapeA + " and " + shapeB + "."); - throw Error(errMsg); - } - else { - result.unshift(a); - } - } - return result; - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var addGradConfig = { - kernelName: Add, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var outShape = assertAndGetBroadcastShape(a.shape, b.shape); - var derA = function () { - var res = dy; - var reduceAxes = getReductionAxes(a.shape, outShape); - if (reduceAxes.length > 0) { - res = res.sum(reduceAxes); - } - return res.reshape(a.shape); - }; - var derB = function () { - var res = dy; - var reduceAxes = getReductionAxes(b.shape, outShape); - if (reduceAxes.length > 0) { - res = res.sum(reduceAxes); - } - return res.reshape(b.shape); - }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var addNGradConfig = { - kernelName: AddN, - saveAllInputs: true, - gradFunc: function (dy, saved) { - var ders = {}; - saved.forEach(function (_, i) { - ders[i] = function () { return dy.clone(); }; - }); - return ders; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates a `tf.Tensor` with all elements set to 0 with the same shape as the - * given tensor. - * - * ```js - * const x = tf.tensor([1, 2]); - * tf.zerosLike(x).print(); - * ``` - * - * @param x The tensor of required shape. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function zerosLike_(x) { - var $x = convertToTensor(x, 'x', 'zerosLike'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend) { return backend.zerosLike($x); }, inputs, null /* grad */, ZerosLike); - } - var zerosLike = op({ zerosLike_: zerosLike_ }); - - /** - * @license - * Copyright 2020 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var argMaxGradConfig = { - kernelName: ArgMax, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return zerosLike(x); } }; - } - }; - - /** - * @license - * Copyright 2020 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var argMinGradConfig = { - kernelName: ArgMin, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return zerosLike(x); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var asinGradConfig = { - kernelName: Asin, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, sqrt(sub(scalar(1), square(cast(x, 'float32'))))); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Adds two `tf.Tensor`s element-wise, A + B. Supports broadcasting. - * - * - * ```js - * const a = tf.tensor1d([1, 2, 3, 4]); - * const b = tf.tensor1d([10, 20, 30, 40]); - * - * a.add(b).print(); // or tf.add(a, b) - * ``` - * - * ```js - * // Broadcast add a with b. - * const a = tf.scalar(5); - * const b = tf.tensor1d([10, 20, 30, 40]); - * - * a.add(b).print(); // or tf.add(a, b) - * ``` - * @param a The first `tf.Tensor` to add. - * @param b The second `tf.Tensor` to add. Must have the same type as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ - function add_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'add'); - var $b = convertToTensor(b, 'b', 'add'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - var forward = function (backend, save) { - var res = backend.add($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Add); - } - var add = op({ add_: add_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var asinhGradConfig = { - kernelName: Asinh, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { - x: function () { - var a = sqrt(add(scalar(1), square(cast(x, 'float32')))); - return div(dy, a); - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Reshapes a `tf.Tensor` to a given shape. - * - * Given an input tensor, returns a new tensor with the same values as the - * input tensor with shape `shape`. - * - * If one component of shape is the special value -1, the size of that - * dimension is computed so that the total size remains constant. In - * particular, a shape of [-1] flattens into 1-D. At most one component of - * shape can be -1. - * - * If shape is 1-D or higher, then the operation returns a tensor with shape - * shape filled with the values of tensor. In this case, the number of - * elements implied by shape must be the same as the number of elements in - * tensor. - * - * ```js - * const x = tf.tensor1d([1, 2, 3, 4]); - * x.reshape([2, 2]).print(); - * ``` - * - * @param x The input tensor to be reshaped. - * @param shape An array of integers defining the output tensor shape. - */ - /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ - function reshape_(x, shape) { - var $x = convertToTensor(x, 'x', 'reshape', null); - shape = inferFromImplicitShape(shape, $x.size); - assert($x.size === sizeFromShape(shape), function () { return 'new shape and old shape must have the same number of elements.'; }); - var inputs = { x: $x }; - var attrs = { shape: shape }; - var forward = function (backend, save) { - save([$x]); - return backend.reshape($x, shape); - }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Reshape, attrs); - } - var reshape = op({ reshape_: reshape_ }); - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns true if the axis specifies the inner most dimensions of the - * array. - */ - function axesAreInnerMostDims(axes, rank) { - for (var i = 0; i < axes.length; ++i) { - if (axes[axes.length - i - 1] !== rank - 1 - i) { - return false; - } - } - return true; - } - function combineLocations(outputLoc, reduceLoc, axes) { - var rank = outputLoc.length + reduceLoc.length; - var loc = []; - var outIdx = 0; - var reduceIdx = 0; - for (var dim = 0; dim < rank; dim++) { - if (axes.indexOf(dim) === -1) { - loc.push(outputLoc[outIdx++]); - } - else { - loc.push(reduceLoc[reduceIdx++]); - } - } - return loc; - } - function computeOutAndReduceShapes(aShape, axes) { - var outShape = []; - var rank = aShape.length; - for (var dim = 0; dim < rank; dim++) { - if (axes.indexOf(dim) === -1) { - outShape.push(aShape[dim]); - } - } - var reduceShape = axes.map(function (dim) { return aShape[dim]; }); - return [outShape, reduceShape]; - } - function expandShapeToKeepDim(shape, axes) { - var reduceSubShape = axes.map(function (x) { return 1; }); - return combineLocations(shape, reduceSubShape, axes); - } - function assertAxesAreInnerMostDims(msg, axes, rank) { - assert(axesAreInnerMostDims(axes, rank), function () { return msg + " supports only inner-most axes for now. " + - ("Got axes " + axes + " and rank-" + rank + " input."); }); - } - /** - * Returns the axes permutation to be used with `tf.transpose`, if such - * permutation is necessary. Otherwise it returns null. This method is used by - * operations that operate only on inner-most axes. - */ - function getAxesPermutation(axes, rank) { - if (axesAreInnerMostDims(axes, rank)) { - return null; - } - var result = []; - for (var i = 0; i < rank; ++i) { - if (axes.indexOf(i) === -1) { - result.push(i); - } - } - axes.forEach(function (axis) { return result.push(axis); }); - return result; - } - /** Returns the axes permutation that undoes the original permutation. */ - function getUndoAxesPermutation(axes) { - return axes.map(function (axis, i) { return [i, axis]; }) - .sort(function (a, b) { return a[1] - b[1]; }) - .map(function (x) { return x[0]; }); - } - function getInnerMostAxes(numAxes, rank) { - var res = []; - for (var i = rank - numAxes; i < rank; ++i) { - res.push(i); - } - return res; - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the sum of elements across dimensions of a `tf.Tensor`. - * - * Reduces the input along the dimensions given in `axes`. Unless `keepDims` - * is true, the rank of the `tf.Tensor` is reduced by 1 for each entry in - * `axes`. If `keepDims` is true, the reduced dimensions are retained with - * length 1. If axes has no entries, all dimensions are reduced, and a - * `tf.Tensor` with a single element is returned. - * - * ```js - * const x = tf.tensor1d([1, 2, 3]); - * - * x.sum().print(); // or tf.sum(x) - * ``` - * - * ```js - * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); - * - * const axis = 1; - * x.sum(axis).print(); // or tf.sum(x, axis) - * ``` - * - * @param x The input tensor to compute the sum over. If the dtype is `bool` - * it will be converted to `int32` and the output dtype will be `int32`. - * @param axis The dimension(s) to reduce. By default it reduces - * all dimensions. - * @param keepDims If true, retains reduced dimensions with size 1. - */ - /** @doc {heading: 'Operations', subheading: 'Reduction'} */ - function sum_(x, axis, keepDims) { - if (axis === void 0) { axis = null; } - if (keepDims === void 0) { keepDims = false; } - var $x = convertToTensor(x, 'x', 'sum'); - if ($x.dtype === 'bool') { - $x = $x.toInt(); - } - var forward = function (backend, save) { - save([$x]); - var axes = parseAxisParam(axis, $x.shape); - var permutation = getAxesPermutation(axes, $x.rank); - var reductionAxes = axes; - var permutedX = $x; - if (permutation != null) { - permutedX = $x.transpose(permutation); - reductionAxes = getInnerMostAxes(reductionAxes.length, $x.rank); - } - var value = backend.sum(permutedX, reductionAxes); - if (keepDims) { - var newShape = expandShapeToKeepDim(value.shape, axes); - value = value.reshape(newShape); - } - return value; - }; - var inputs = { x: $x }; - var attrs = { axis: axis, keepDims: keepDims }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Sum, attrs); - } - var sum$1 = op({ sum_: sum_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var atan2GradConfig = { - kernelName: Atan2, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var outShape = assertAndGetBroadcastShape(a.shape, b.shape); - var derA = function () { - var d = add(square(a), square(b)); - var res = mul(dy, div(b, d)); - var reduceAxes = getReductionAxes(a.shape, outShape); - if (reduceAxes.length > 0) { - res = sum$1(res, reduceAxes); - } - return reshape(res, a.shape); - }; - var derB = function () { - var d = add(square(a), square(b)); - var res = neg(mul(dy, div(a, d))); - var reduceAxes = getReductionAxes(b.shape, outShape); - if (reduceAxes.length > 0) { - res = sum$1(res, reduceAxes); - } - return reshape(res, b.shape); - }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var atanGradConfig = { - kernelName: Atan, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, add(square(cast(x, 'float32')), 1)); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var atanhGradConfig = { - kernelName: Atanh, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, sub(scalar(1), square(cast(x, 'float32')))); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * - * @param inputShape Input tensor shape is of the following dimensions: - * `[batch, height, width, inChannels]`. - * @param filterShape The filter shape is of the following dimensions: - * `[filterHeight, filterWidth, depth]`. - * @param strides The strides of the sliding window for each dimension of the - * input tensor: `[strideHeight, strideWidth]`. - * If `strides` is a single number, - * then `strideHeight == strideWidth`. - * @param pad The type of padding algorithm. - * - `same` and stride 1: output will be of same size as input, - * regardless of filter size. - * - `valid`: output will be smaller than input if filter is larger - * than 1*1x1. - * - For more info, see this guide: - * [https://www.tensorflow.org/api_guides/python/nn#Convolution]( - * https://www.tensorflow.org/api_guides/python/nn#Convolution) - * @param dataFormat The data format of the input and output data. - * Defaults to 'NHWC'. - * @param dilations The dilation rates: `[dilationHeight, dilationWidth]`. - * Defaults to `[1, 1]`. If `dilations` is a single number, then - * `dilationHeight == dilationWidth`. - */ - function computeDilation2DInfo(inputShape, filterShape, strides, pad, dataFormat, dilations) { - if (dataFormat === void 0) { dataFormat = 'NHWC'; } - // `computerConv2DInfo` require filterShape to be in the dimension of: - // `[filterHeight, filterWidth, depth, outDepth]`, dilation2d doesn't have - // outDepth, it should have the same depth as the input. - // Input shape: [batch, height, width, inChannels] - var inputChannels = inputShape[3]; - var $filterShape = filterShape.concat([inputChannels]); - var $dataFormat = convertConv2DDataFormat(dataFormat); - return computeConv2DInfo(inputShape, $filterShape, strides, dilations, pad, null /* roundingMode */, null /* depthWise */, $dataFormat); - } - function computePool2DInfo(inShape, filterSize, strides, dilations, pad, roundingMode, dataFormat) { - if (dataFormat === void 0) { dataFormat = 'channelsLast'; } - var _a = parseTupleParam(filterSize), filterHeight = _a[0], filterWidth = _a[1]; - var filterShape; - if (dataFormat === 'channelsLast') { - filterShape = [filterHeight, filterWidth, inShape[3], inShape[3]]; - } - else if (dataFormat === 'channelsFirst') { - filterShape = [filterHeight, filterWidth, inShape[1], inShape[1]]; - } - else { - throw new Error("Unknown dataFormat " + dataFormat); - } - return computeConv2DInfo(inShape, filterShape, strides, dilations, pad, roundingMode, false, dataFormat); - } - /** - * Computes the information for a forward pass of a pooling3D operation. - */ - function computePool3DInfo(inShape, filterSize, strides, dilations, pad, roundingMode, dataFormat) { - if (dataFormat === void 0) { dataFormat = 'NDHWC'; } - var _a = parse3TupleParam(filterSize), filterDepth = _a[0], filterHeight = _a[1], filterWidth = _a[2]; - var filterShape; - var $dataFormat; - if (dataFormat === 'NDHWC') { - $dataFormat = 'channelsLast'; - filterShape = - [filterDepth, filterHeight, filterWidth, inShape[4], inShape[4]]; - } - else if (dataFormat === 'NCDHW') { - $dataFormat = 'channelsFirst'; - filterShape = - [filterDepth, filterHeight, filterWidth, inShape[1], inShape[1]]; - } - else { - throw new Error("Unknown dataFormat " + dataFormat); - } - return computeConv3DInfo(inShape, filterShape, strides, dilations, pad, false, $dataFormat, roundingMode); - } - /** - * Computes the information for a forward pass of a convolution/pooling - * operation. - */ - function computeConv2DInfo(inShape, filterShape, strides, dilations, pad, roundingMode, depthwise, dataFormat) { - if (depthwise === void 0) { depthwise = false; } - if (dataFormat === void 0) { dataFormat = 'channelsLast'; } - var _a = [-1, -1, -1, -1], batchSize = _a[0], inHeight = _a[1], inWidth = _a[2], inChannels = _a[3]; - if (dataFormat === 'channelsLast') { - batchSize = inShape[0], inHeight = inShape[1], inWidth = inShape[2], inChannels = inShape[3]; - } - else if (dataFormat === 'channelsFirst') { - batchSize = inShape[0], inChannels = inShape[1], inHeight = inShape[2], inWidth = inShape[3]; - } - else { - throw new Error("Unknown dataFormat " + dataFormat); - } - var filterHeight = filterShape[0], filterWidth = filterShape[1], filterChannels = filterShape[3]; - var _b = parseTupleParam(strides), strideHeight = _b[0], strideWidth = _b[1]; - var _c = parseTupleParam(dilations), dilationHeight = _c[0], dilationWidth = _c[1]; - var effectiveFilterHeight = getEffectiveFilterSize(filterHeight, dilationHeight); - var effectiveFilterWidth = getEffectiveFilterSize(filterWidth, dilationWidth); - var _d = getPadAndOutInfo(pad, inHeight, inWidth, strideHeight, strideWidth, effectiveFilterHeight, effectiveFilterWidth, roundingMode, dataFormat), padInfo = _d.padInfo, outHeight = _d.outHeight, outWidth = _d.outWidth; - var outChannels = depthwise ? filterChannels * inChannels : filterChannels; - var outShape; - if (dataFormat === 'channelsFirst') { - outShape = [batchSize, outChannels, outHeight, outWidth]; - } - else if (dataFormat === 'channelsLast') { - outShape = [batchSize, outHeight, outWidth, outChannels]; - } - return { - batchSize: batchSize, - dataFormat: dataFormat, - inHeight: inHeight, - inWidth: inWidth, - inChannels: inChannels, - outHeight: outHeight, - outWidth: outWidth, - outChannels: outChannels, - padInfo: padInfo, - strideHeight: strideHeight, - strideWidth: strideWidth, - filterHeight: filterHeight, - filterWidth: filterWidth, - effectiveFilterHeight: effectiveFilterHeight, - effectiveFilterWidth: effectiveFilterWidth, - dilationHeight: dilationHeight, - dilationWidth: dilationWidth, - inShape: inShape, - outShape: outShape, - filterShape: filterShape - }; - } - /** - * Computes the information for a forward pass of a 3D convolution/pooling - * operation. - */ - function computeConv3DInfo(inShape, filterShape, strides, dilations, pad, depthwise, dataFormat, roundingMode) { - if (depthwise === void 0) { depthwise = false; } - if (dataFormat === void 0) { dataFormat = 'channelsLast'; } - var _a = [-1, -1, -1, -1, -1], batchSize = _a[0], inDepth = _a[1], inHeight = _a[2], inWidth = _a[3], inChannels = _a[4]; - if (dataFormat === 'channelsLast') { - batchSize = inShape[0], inDepth = inShape[1], inHeight = inShape[2], inWidth = inShape[3], inChannels = inShape[4]; - } - else if (dataFormat === 'channelsFirst') { - batchSize = inShape[0], inChannels = inShape[1], inDepth = inShape[2], inHeight = inShape[3], inWidth = inShape[4]; - } - else { - throw new Error("Unknown dataFormat " + dataFormat); - } - var filterDepth = filterShape[0], filterHeight = filterShape[1], filterWidth = filterShape[2], filterChannels = filterShape[4]; - var _b = parse3TupleParam(strides), strideDepth = _b[0], strideHeight = _b[1], strideWidth = _b[2]; - var _c = parse3TupleParam(dilations), dilationDepth = _c[0], dilationHeight = _c[1], dilationWidth = _c[2]; - var effectiveFilterDepth = getEffectiveFilterSize(filterDepth, dilationDepth); - var effectiveFilterHeight = getEffectiveFilterSize(filterHeight, dilationHeight); - var effectiveFilterWidth = getEffectiveFilterSize(filterWidth, dilationWidth); - var _d = get3DPadAndOutInfo(pad, inDepth, inHeight, inWidth, strideDepth, strideHeight, strideWidth, effectiveFilterDepth, effectiveFilterHeight, effectiveFilterWidth, roundingMode), padInfo = _d.padInfo, outDepth = _d.outDepth, outHeight = _d.outHeight, outWidth = _d.outWidth; - var outChannels = depthwise ? filterChannels * inChannels : filterChannels; - var outShape; - if (dataFormat === 'channelsFirst') { - outShape = [batchSize, outChannels, outDepth, outHeight, outWidth]; - } - else if (dataFormat === 'channelsLast') { - outShape = [batchSize, outDepth, outHeight, outWidth, outChannels]; - } - return { - batchSize: batchSize, - dataFormat: dataFormat, - inDepth: inDepth, - inHeight: inHeight, - inWidth: inWidth, - inChannels: inChannels, - outDepth: outDepth, - outHeight: outHeight, - outWidth: outWidth, - outChannels: outChannels, - padInfo: padInfo, - strideDepth: strideDepth, - strideHeight: strideHeight, - strideWidth: strideWidth, - filterDepth: filterDepth, - filterHeight: filterHeight, - filterWidth: filterWidth, - effectiveFilterDepth: effectiveFilterDepth, - effectiveFilterHeight: effectiveFilterHeight, - effectiveFilterWidth: effectiveFilterWidth, - dilationDepth: dilationDepth, - dilationHeight: dilationHeight, - dilationWidth: dilationWidth, - inShape: inShape, - outShape: outShape, - filterShape: filterShape - }; - } - function computeOutputShape2D(inShape, fieldSize, stride, zeroPad, roundingMode) { - if (zeroPad == null) { - zeroPad = computeDefaultPad(inShape, fieldSize, stride); - } - var inputRows = inShape[0]; - var inputCols = inShape[1]; - var outputRows = conditionalRound((inputRows - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); - assert(isInt(outputRows), function () { return "The output # of rows (" + outputRows + ") must be an integer. " + - "Change the stride and/or zero pad parameters"; }); - var outputCols = conditionalRound((inputCols - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); - assert(isInt(outputCols), function () { return "The output # of columns (" + outputCols + ") must be an integer. " + - "Change the stride and/or zero pad parameters"; }); - return [outputRows, outputCols]; - } - function computeOutputShape4D(inShape, fieldSize, outChannels, stride, zeroPad, roundingMode) { - if (zeroPad == null) { - zeroPad = computeDefaultPad(inShape, fieldSize, stride); - } - var inputDepth = inShape[0]; - var inputRows = inShape[1]; - var inputCols = inShape[2]; - var outputDepths = conditionalRound((inputDepth - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); - assert(isInt(outputDepths), function () { return "The output # of depths (" + outputDepths + ") must be an integer. " + - "Change the stride and/or zero pad parameters"; }); - var outputRows = conditionalRound((inputRows - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); - assert(isInt(outputRows), function () { return "The output # of rows (" + outputRows + ") must be an integer. " + - "Change the stride and/or zero pad parameters"; }); - var outputCols = conditionalRound((inputCols - fieldSize + 2 * zeroPad) / stride + 1, roundingMode); - assert(isInt(outputCols), function () { return "The output # of columns (" + outputCols + ") must be an integer. " + - "Change the stride and/or zero pad parameters"; }); - return [outputDepths, outputRows, outputCols, outChannels]; - } - function computeDefaultPad(inputShape, fieldSize, stride, dilation) { - if (dilation === void 0) { dilation = 1; } - var effectiveFieldSize = getEffectiveFilterSize(fieldSize, dilation); - return Math.floor((inputShape[0] * (stride - 1) - stride + effectiveFieldSize) / 2); - } - function parseTupleParam(param) { - if (typeof param === 'number') { - return [param, param, param]; - } - if (param.length === 2) { - return [param[0], param[1], 1]; - } - return param; - } - function parse3TupleParam(param) { - return typeof param === 'number' ? [param, param, param] : param; - } - /* See https://www.tensorflow.org/api_docs/python/tf/nn/atrous_conv2d - * Atrous convolution is equivalent to standard convolution with upsampled - * filters with effective_filter_height = - * filter_height + (filter_height - 1) * (dilation - 1) - * and effective_filter_width = - * filter_width + (filter_width - 1) * (dilation - 1), - * produced by inserting dilation - 1 zeros along consecutive elements across - * the filters' spatial dimensions. - * When there is a dilation, this converts a filter dimension to the - * effective filter dimension, so it can be used in a standard convolution. - */ - function getEffectiveFilterSize(filterSize, dilation) { - if (dilation <= 1) { - return filterSize; - } - return filterSize + (filterSize - 1) * (dilation - 1); - } - function getPadAndOutInfo(pad, inHeight, inWidth, strideHeight, strideWidth, filterHeight, filterWidth, roundingMode, dataFormat) { - var padInfo; - var outHeight; - var outWidth; - if (typeof pad === 'number') { - var padType = (pad === 0) ? 'VALID' : 'NUMBER'; - padInfo = { top: pad, bottom: pad, left: pad, right: pad, type: padType }; - var outShape = computeOutputShape2D([inHeight, inWidth], filterHeight, strideHeight, pad, roundingMode); - outHeight = outShape[0]; - outWidth = outShape[1]; - } - else if (pad === 'same') { - outHeight = Math.ceil(inHeight / strideHeight); - outWidth = Math.ceil(inWidth / strideWidth); - var padAlongHeight = Math.max(0, (outHeight - 1) * strideHeight + filterHeight - inHeight); - var padAlongWidth = Math.max(0, (outWidth - 1) * strideWidth + filterWidth - inWidth); - var top_1 = Math.floor(padAlongHeight / 2); - var bottom = padAlongHeight - top_1; - var left = Math.floor(padAlongWidth / 2); - var right = padAlongWidth - left; - padInfo = { top: top_1, bottom: bottom, left: left, right: right, type: 'SAME' }; - } - else if (pad === 'valid') { - padInfo = { top: 0, bottom: 0, left: 0, right: 0, type: 'VALID' }; - outHeight = Math.ceil((inHeight - filterHeight + 1) / strideHeight); - outWidth = Math.ceil((inWidth - filterWidth + 1) / strideWidth); - } - else if (typeof pad === 'object') { - var top_2 = dataFormat === 'channelsLast' ? pad[1][0] : pad[2][0]; - var bottom = dataFormat === 'channelsLast' ? pad[1][1] : pad[2][1]; - var left = dataFormat === 'channelsLast' ? pad[2][0] : pad[3][0]; - var right = dataFormat === 'channelsLast' ? pad[2][1] : pad[3][1]; - var padType = (top_2 === 0 && bottom === 0 && left === 0 && right === 0) ? - 'VALID' : - 'EXPLICIT'; - padInfo = { top: top_2, bottom: bottom, left: left, right: right, type: padType }; - outHeight = conditionalRound((inHeight - filterHeight + top_2 + bottom) / strideHeight + 1, roundingMode); - outWidth = conditionalRound((inWidth - filterWidth + left + right) / strideWidth + 1, roundingMode); - } - else { - throw Error("Unknown padding parameter: " + pad); - } - return { padInfo: padInfo, outHeight: outHeight, outWidth: outWidth }; - } - function get3DPadAndOutInfo(pad, inDepth, inHeight, inWidth, strideDepth, strideHeight, strideWidth, filterDepth, filterHeight, filterWidth, roundingMode) { - var padInfo; - var outDepth; - var outHeight; - var outWidth; - if (typeof pad === 'number') { - var padType = (pad === 0) ? 'VALID' : 'NUMBER'; - padInfo = { - top: pad, - bottom: pad, - left: pad, - right: pad, - front: pad, - back: pad, - type: padType - }; - var outShape = computeOutputShape4D([inDepth, inHeight, inWidth, 1], filterDepth, 1, strideDepth, pad, roundingMode); - outDepth = outShape[0]; - outHeight = outShape[1]; - outWidth = outShape[2]; - } - else if (pad === 'same') { - outDepth = Math.ceil(inDepth / strideDepth); - outHeight = Math.ceil(inHeight / strideHeight); - outWidth = Math.ceil(inWidth / strideWidth); - var padAlongDepth = (outDepth - 1) * strideDepth + filterDepth - inDepth; - var padAlongHeight = (outHeight - 1) * strideHeight + filterHeight - inHeight; - var padAlongWidth = (outWidth - 1) * strideWidth + filterWidth - inWidth; - var front = Math.floor(padAlongDepth / 2); - var back = padAlongDepth - front; - var top_3 = Math.floor(padAlongHeight / 2); - var bottom = padAlongHeight - top_3; - var left = Math.floor(padAlongWidth / 2); - var right = padAlongWidth - left; - padInfo = { top: top_3, bottom: bottom, left: left, right: right, front: front, back: back, type: 'SAME' }; - } - else if (pad === 'valid') { - padInfo = { - top: 0, - bottom: 0, - left: 0, - right: 0, - front: 0, - back: 0, - type: 'VALID' - }; - outDepth = Math.ceil((inDepth - filterDepth + 1) / strideDepth); - outHeight = Math.ceil((inHeight - filterHeight + 1) / strideHeight); - outWidth = Math.ceil((inWidth - filterWidth + 1) / strideWidth); - } - else { - throw Error("Unknown padding parameter: " + pad); - } - return { padInfo: padInfo, outDepth: outDepth, outHeight: outHeight, outWidth: outWidth }; - } - /** - * Rounds a value depending on the rounding mode - * @param value - * @param roundingMode - */ - function conditionalRound(value, roundingMode) { - if (!roundingMode) { - return value; - } - switch (roundingMode) { - case 'round': - // used for Caffe Conv - return Math.round(value); - case 'ceil': - // used for Caffe Pool - return Math.ceil(value); - case 'floor': - return Math.floor(value); - default: - throw new Error("Unknown roundingMode " + roundingMode); - } - } - function tupleValuesAreOne(param) { - var _a = parseTupleParam(param), dimA = _a[0], dimB = _a[1], dimC = _a[2]; - return dimA === 1 && dimB === 1 && dimC === 1; - } - function eitherStridesOrDilationsAreOne(strides, dilations) { - return tupleValuesAreOne(strides) || tupleValuesAreOne(dilations); - } - /** - * Convert Conv2D dataFormat from 'NHWC'|'NCHW' to - * 'channelsLast'|'channelsFirst' - * @param dataFormat in 'NHWC'|'NCHW' mode - * @return dataFormat in 'channelsLast'|'channelsFirst' mode - * @throws unknown dataFormat - */ - function convertConv2DDataFormat(dataFormat) { - if (dataFormat === 'NHWC') { - return 'channelsLast'; - } - else if (dataFormat === 'NCHW') { - return 'channelsFirst'; - } - else { - throw new Error("Unknown dataFormat " + dataFormat); - } - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the backprop of a 3d avg pool. - * - * @param dy The dy error, of rank 5 of shape - * [batchSize, depth, height, width, channels]. - * assumed. - * @param input The original input image, of rank 5 or rank4 of shape - * [batchSize, depth, height, width, channels]. - * @param filterSize The filter size: - * `[filterDepth, filterHeight, filterWidth]`. - * `filterSize` is a single number, - * then `filterDepth == filterHeight == filterWidth`. - * @param strides The strides of the pooling: - * `[strideDepth, strideHeight, strideWidth]`. If - * `strides` is a single number, then `strideHeight == strideWidth`. - * @param dilations Deprecated, this field will be gone in v3.0.0. The dilation - * rates: `[dilationDepth, dilationHeight, dilationWidth]` - * in which we sample input values across the depth, height and width - * dimensions in dilated pooling. - * Defaults to `[1, 1, 1]`. If `dilations` is a single number, - * then `dilationDepth == dilationHeight == dilationWidth`. - * If it is greater than 1, then all values of `strides` must be 1. - * @param pad A string from: 'same', 'valid'. The type of padding algorithm - * used in the forward prop of the op. - * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The - * rounding mode used when computing output dimensions if pad is a - * number. If none is provided, it will not round and error if the output - * is of fractional size. - */ - function avgPool3dBackprop_(dy, input, filterSize, strides, dilations, pad, dimRoundingMode) { - if (dilations === void 0) { dilations = [1, 1, 1]; } - var $dy = convertToTensor(dy, 'dy', 'avgPool3dBackprop'); - var $input = convertToTensor(input, 'input', 'avgPool3dBackprop'); - var dy5D = $dy; - var input5D = $input; - var reshapedTo5D = false; - if ($input.rank === 4) { - reshapedTo5D = true; - dy5D = reshape($dy, [1, $dy.shape[0], $dy.shape[1], $dy.shape[2], $dy.shape[3]]); - input5D = reshape($input, [ - 1, $input.shape[0], $input.shape[1], $input.shape[2], $input.shape[3] - ]); - } - assert(dy5D.rank === 5, function () { return "Error in avgPool3dBackprop: dy must be rank 5 but got rank " + - (dy5D.rank + "."); }); - assert(input5D.rank === 5, function () { return "Error in avgPool3dBackprop: input must be rank 5 but got rank " + - (input5D.rank + "."); }); - assert(eitherStridesOrDilationsAreOne(strides, dilations), function () { return 'Error in avgPool3dBackprop: Either strides or dilations ' + - ("must be 1. Got strides " + strides + " and dilations '" + dilations + "'"); }); - if (dimRoundingMode != null) { - assert(isInt(pad), function () { return "Error in maxPool3dBackprop: pad must be an integer when " + - ("using, dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); - } - var forward = function (backend) { - var convInfo = computePool3DInfo(input5D.shape, filterSize, strides, dilations, pad, dimRoundingMode); - return backend.avgPool3dBackprop(dy5D, input5D, convInfo); - }; - var inputs = { dy: dy5D, input: input5D }; - var attrs = { filterSize: filterSize, strides: strides, dilations: dilations, pad: pad, dimRoundingMode: dimRoundingMode }; - var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, AvgPool3DBackprop, attrs); - if (reshapedTo5D) { - return reshape(res, [res.shape[1], res.shape[2], res.shape[3], res.shape[4]]); - } - return res; - } - var avgPool3dBackprop = op({ avgPool3dBackprop_: avgPool3dBackprop_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var avgPool3DGradConfig = { - kernelName: AvgPool3D, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0]; - var _a = attrs, filterSize = _a.filterSize, strides = _a.strides, dilations = _a.dilations, pad = _a.pad, dimRoundingMode = _a.dimRoundingMode; - var $dilations = dilations == null ? [1, 1, 1] : dilations; - return { - x: function () { return avgPool3dBackprop(dy, x, filterSize, strides, $dilations, pad, dimRoundingMode); } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the backprop of an 2D avg pool. - * - * @param dy The dy error, of rank 4 or rank 3 of shape - * [batchSize, height, width, channels]. If rank 3, batch of 1 is - * assumed. - * @param input The input image, of rank 4 or rank 3 of shape - * [batchSize, height, width, channels]. If rank 3, batch of 1 is - * assumed. - * @param filterSize The filter size: `[filterHeight, filterWidth]`. If - * `filterSize` is a single number, then `filterHeight == filterWidth`. - * @param strides The strides of the pooling: `[strideHeight, strideWidth]`. If - * `strides` is a single number, then `strideHeight == strideWidth`. - * @param pad A string from: 'same', 'valid'. The type of padding algorithm - * used in the forward prop of the op. - */ - function avgPoolBackprop_(dy, input, filterSize, strides, pad) { - var $dy = convertToTensor(dy, 'dy', 'avgPoolBackprop'); - var $input = convertToTensor(input, 'input', 'avgPoolBackprop'); - assert($input.rank === $dy.rank, function () { return "Rank of input (" + $input.rank + ") does not match rank of dy (" + $dy.rank + ")"; }); - var input4D = $input; - var dy4D = $dy; - var reshapedTo4D = false; - if ($input.rank === 3) { - reshapedTo4D = true; - input4D = - reshape($input, [1, $input.shape[0], $input.shape[1], $input.shape[2]]); - dy4D = reshape($dy, [1, $dy.shape[0], $dy.shape[1], $dy.shape[2]]); - } - assert(dy4D.rank === 4, function () { return "Error in avgPoolBackprop: dy must be rank 4 but got rank " + - (dy4D.rank + "."); }); - assert(input4D.rank === 4, function () { return "Error in avgPoolBackprop: input must be rank 4 but got rank " + - (input4D.rank + "."); }); - var forward = function (backend) { - var convInfo = computePool2DInfo(input4D.shape, filterSize, strides, 1 /* dilations */, pad); - return backend.avgPoolBackprop(dy4D, input4D, convInfo); - }; - var inputs = { dy: dy4D, input: input4D }; - var attrs = { filterSize: filterSize, strides: strides, pad: pad }; - var res = ENGINE.runKernelFunc(forward, inputs, null, AvgPoolBackprop, attrs); - if (reshapedTo4D) { - return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); - } - return res; - } - var avgPoolBackprop = op({ avgPoolBackprop_: avgPoolBackprop_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var avgPoolGradConfig = { - kernelName: AvgPool, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0]; - var _a = attrs, filterSize = _a.filterSize, strides = _a.strides, pad = _a.pad; - return { - x: function () { return avgPoolBackprop(dy, x, filterSize, strides, pad); } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the dot product of two matrices, A * B. These must be matrices. - * - * ```js - * const a = tf.tensor2d([1, 2], [1, 2]); - * const b = tf.tensor2d([1, 2, 3, 4], [2, 2]); - * - * a.matMul(b).print(); // or tf.matMul(a, b) - * ``` - * @param a First matrix in dot product operation. - * @param b Second matrix in dot product operation. - * @param transposeA If true, `a` is transposed before multiplication. - * @param transposeB If true, `b` is transposed before multiplication. - */ - /** @doc {heading: 'Operations', subheading: 'Matrices'} */ - function matMul_(a, b, transposeA, transposeB) { - var _a; - if (transposeA === void 0) { transposeA = false; } - if (transposeB === void 0) { transposeB = false; } - var $a = convertToTensor(a, 'a', 'matMul'); - var $b = convertToTensor(b, 'b', 'matMul'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - assert($a.rank >= 2 && $b.rank >= 2 && $a.rank === $b.rank, function () { return "Error in matMul: inputs must have the same rank of at least 2, " + - ("got ranks " + $a.rank + " and " + $b.rank + "."); }); - var innerShapeA = transposeA ? $a.shape[$a.rank - 2] : $a.shape[$a.rank - 1]; - var innerShapeB = transposeB ? $b.shape[$b.rank - 1] : $b.shape[$b.rank - 2]; - var outerShapeA = transposeA ? $a.shape[$a.rank - 1] : $a.shape[$a.rank - 2]; - var outerShapeB = transposeB ? $b.shape[$b.rank - 2] : $b.shape[$b.rank - 1]; - var outerDimsA = $a.shape.slice(0, -2); - var outerDimsB = $b.shape.slice(0, -2); - var batchDimA = sizeFromShape(outerDimsA); - var batchDimB = sizeFromShape(outerDimsB); - assert(arraysEqual(outerDimsA, outerDimsB), function () { return "Error in matMul: outer dimensions (" + outerDimsA + ") and (" + - (outerDimsB + ") of Tensors with shapes " + $a.shape + " and ") + - ($b.shape + " must match."); }); - assert(innerShapeA === innerShapeB, function () { return "Error in matMul: inner shapes (" + innerShapeA + ") and (" + - (innerShapeB + ") of Tensors with shapes " + $a.shape + " and ") + - ($b.shape + " and transposeA=" + transposeA) + - (" and transposeB=" + transposeB + " must match."); }); - var outShape = $a.shape.slice(0, -2).concat([outerShapeA, outerShapeB]); - var a3D = transposeA ? reshape($a, [batchDimA, innerShapeA, outerShapeA]) : - reshape($a, [batchDimA, outerShapeA, innerShapeA]); - var b3D = transposeB ? reshape($b, [batchDimB, outerShapeB, innerShapeB]) : - reshape($b, [batchDimB, innerShapeB, outerShapeB]); - var forward = function (backend, save) { - save([a3D, b3D]); - return backend.batchMatMul(a3D, b3D, transposeA, transposeB); - }; - var inputs = { a: a3D, b: b3D }; - var attrs = { transposeA: transposeA, transposeB: transposeB }; - var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, BatchMatMul, attrs); - return reshape(res, outShape); - } - var matMul = op({ matMul_: matMul_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var batchMatMulGradConfig = { - kernelName: BatchMatMul, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved, attrs) { - var _a = saved, a = _a[0], b = _a[1]; - var _b = attrs, transposeA = _b.transposeA, transposeB = _b.transposeB; - if (!transposeA && !transposeB) { - return { - a: function () { return matMul(dy, b, false, true); }, - b: function () { return matMul(a, dy, true, false); } - }; - } - else if (!transposeA && transposeB) { - return { - a: function () { return matMul(dy, b, false, false); }, - b: function () { return matMul(dy, a, true, false); } - }; - } - else if (transposeA && !transposeB) { - return { - a: function () { return matMul(b, dy, false, true); }, - b: function () { return matMul(a, dy, false, false); } - }; - } - else { - return { - a: function () { return matMul(b, dy, true, true); }, - b: function () { return matMul(dy, a, true, true); } - }; - } - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * This operation divides "spatial" dimensions `[1, ..., M]` of the input into - * a grid of blocks of shape `blockShape`, and interleaves these blocks with - * the "batch" dimension (0) such that in the output, the spatial - * dimensions `[1, ..., M]` correspond to the position within the grid, - * and the batch dimension combines both the position within a spatial block - * and the original batch position. Prior to division into blocks, - * the spatial dimensions of the input are optionally zero padded - * according to `paddings`. See below for a precise description. - * - * ```js - * const x = tf.tensor4d([1, 2, 3, 4], [1, 2, 2, 1]); - * const blockShape = [2, 2]; - * const paddings = [[0, 0], [0, 0]]; - * - * x.spaceToBatchND(blockShape, paddings).print(); - * ``` - * - * @param x A `tf.Tensor`. N-D with `x.shape` = `[batch] + spatialShape + - * remainingShape`, where spatialShape has `M` dimensions. - * @param blockShape A 1-D array. Must have shape `[M]`, all values must - * be >= 1. - * @param paddings A 2-D array. Must have shape `[M, 2]`, all values must be >= - * 0. `paddings[i] = [padStart, padEnd]` specifies the amount to zero-pad - * from input dimension `i + 1`, which corresponds to spatial dimension `i`. It - * is required that - * `(inputShape[i + 1] + padStart + padEnd) % blockShape[i] === 0` - * - * This operation is equivalent to the following steps: - * - * 1. Zero-pad the start and end of dimensions `[1, ..., M]` of the input - * according to `paddings` to produce `padded` of shape paddedShape. - * - * 2. Reshape `padded` to `reshapedPadded` of shape: - * `[batch] + [paddedShape[1] / blockShape[0], blockShape[0], ..., - * paddedShape[M] / blockShape[M-1], blockShape[M-1]] + remainingShape` - * - * 3. Permute dimensions of `reshapedPadded` to produce `permutedReshapedPadded` - * of shape: `blockShape + [batch] + [paddedShape[1] / blockShape[0], ..., - * paddedShape[M] / blockShape[M-1]] + remainingShape` - * - * 4. Reshape `permutedReshapedPadded` to flatten `blockShape` into the - * batch dimension, producing an output tensor of shape: - * `[batch * prod(blockShape)] + [paddedShape[1] / blockShape[0], ..., - * paddedShape[M] / blockShape[M-1]] + remainingShape` - */ - /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ - function spaceToBatchND_(x, blockShape, paddings) { - var $x = convertToTensor(x, 'x', 'spaceToBatchND'); - assert($x.rank >= 1 + blockShape.length, function () { return "input rank " + $x.rank + " should be > than [blockShape] " + blockShape.length; }); - assert(paddings.length === blockShape.length, function () { return "paddings.shape[0] " + paddings.length + " must be equal to [blockShape] " + blockShape.length; }); - assert($x.shape.reduce(function (a, b, i) { - if (i > 0 && i <= blockShape.length) { - return a && - ((b + paddings[i - 1][0] + paddings[i - 1][1]) % - blockShape[i - 1] === - 0); - } - return a; - }, true), function () { return "input spatial dimensions " + $x.shape.slice(1) + " with paddings " + paddings.toString() + " must be divisible by blockShapes " + blockShape.toString(); }); - var forward = function (backend) { - return backend.spaceToBatchND($x, blockShape, paddings); - }; - var inputs = { x: $x }; - var attrs = { blockShape: blockShape, paddings: paddings }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, SpaceToBatchND, attrs); - } - var spaceToBatchND = op({ spaceToBatchND_: spaceToBatchND_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var batchToSpaceNDGradConfig = { - kernelName: BatchToSpaceND, - gradFunc: function (dy, saved, attrs) { - var _a = attrs, blockShape = _a.blockShape, crops = _a.crops; - return { x: function () { return spaceToBatchND(dy, blockShape, crops); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var broadcastToGradConfig = { - kernelName: BroadcastTo, - gradFunc: function (dy, saved, attrs) { - var broadCastToAttrs = attrs; - var inputShape = broadCastToAttrs.inputShape; - var outputShape = broadCastToAttrs.shape; - var reps = Array.from(outputShape); - for (var i = inputShape.length - 1; i >= 0; i--) { - if (inputShape[i] === outputShape[i]) { - reps[i] = 1; - } - else if (inputShape[i] !== 1) { - throw new Error("broadcastTo(): [" + inputShape + "] cannot be broadcast to [" + outputShape + "]."); - } - } - var axes = []; - for (var i = 0; i < reps.length; i++) { - if (reps[i] > 1) { - axes.push(i); - } - } - return { x: function () { return sum$1(dy, axes, true /* keepDims */); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var castGradConfig = { - kernelName: Cast, - gradFunc: function (dy) { - return { x: function () { return dy.clone(); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var ceilGradConfig = { - kernelName: Ceil, - gradFunc: function (dy) { - // TODO(manrajgrover): Return null for gradients when backprop supports it. - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the truth value of (a >= b) element-wise. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([1, 2, 3]); - * const b = tf.tensor1d([2, 2, 2]); - * - * a.greaterEqual(b).print(); - * ``` - * - * @param a The first input tensor. - * @param b The second input tensor. Must have the same dtype as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function greaterEqual_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'greaterEqual'); - var $b = convertToTensor(b, 'b', 'greaterEqual'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - assertAndGetBroadcastShape($a.shape, $b.shape); - var forward = function (backend, save) { - var res = backend.greaterEqual($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, GreaterEqual); - } - var greaterEqual = op({ greaterEqual_: greaterEqual_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the truth value of (a <= b) element-wise. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([1, 2, 3]); - * const b = tf.tensor1d([2, 2, 2]); - * - * a.lessEqual(b).print(); - * ``` - * - * @param a The first input tensor. - * @param b The second input tensor. Must have the same dtype as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function lessEqual_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'lessEqual'); - var $b = convertToTensor(b, 'b', 'lessEqual'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - assertAndGetBroadcastShape($a.shape, $b.shape); - var forward = function (backend, save) { - var res = backend.lessEqual($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, LessEqual); - } - var lessEqual = op({ lessEqual_: lessEqual_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the truth value of `a AND b` element-wise. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([false, false, true, true], 'bool'); - * const b = tf.tensor1d([false, true, false, true], 'bool'); - * - * a.logicalAnd(b).print(); - * ``` - * - * @param a The first input tensor. Must be of dtype bool. - * @param b The second input tensor. Must be of dtype bool. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function logicalAnd_(a, b) { - var $a = convertToTensor(a, 'a', 'logicalAnd', 'bool'); - var $b = convertToTensor(b, 'b', 'logicalAnd', 'bool'); - assertAndGetBroadcastShape($a.shape, $b.shape); - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(function (backend) { return backend.logicalAnd($a, $b); }, inputs, null /* grad */, LogicalAnd); - } - var logicalAnd = op({ logicalAnd_: logicalAnd_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the elements, either `a` or `b` depending on the `condition`. - * - * If the condition is true, select from `a`, otherwise select from `b`. - * - * ```js - * const cond = tf.tensor1d([false, false, true], 'bool'); - * const a = tf.tensor1d([1 , 2, 3]); - * const b = tf.tensor1d([-1, -2, -3]); - * - * a.where(cond, b).print(); - * ``` - * - * @param condition The input condition. Must be of dtype bool. - * @param a If `condition` is rank 1, `a` may have a higher rank but - * its first dimension must match the size of `condition`. - * @param b A tensor with the same dtype as `a` and with shape that is - * compatible with `a`. - * @return A tensor with same dtype as `a` and `b`, and shape that is - * broadcastable from `a` and `b`. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function where_(condition, a, b) { - var $a = convertToTensor(a, 'a', 'where'); - var $b = convertToTensor(b, 'b', 'where'); - var $condition = convertToTensor(condition, 'condition', 'where', 'bool'); - // TODO: move this logic to forward function when the broadcastTo op is - // implemented in WASM. - // Find the broadcastable shape for $a and $b. - var broadcastShape = assertAndGetBroadcastShape($a.shape, $b.shape); - var $broadcastedA = $a.broadcastTo(broadcastShape); - var $broadcastedB = $b.broadcastTo(broadcastShape); - if ($condition.rank === 1) { - // If condition rank is 1, then the first dimension must match the size of - // condition. - assert($condition.shape[0] === $a.shape[0], function () { return 'The first dimension of `a` must match the size of `condition`.'; }); - } - if ($condition.rank !== 1) { - // A must have the same shape as condition. - assertShapesMatch($condition.shape, $broadcastedB.shape, 'Error in where: '); - } - var forward = function (backend, save) { - var res = backend.select($condition, $broadcastedA, $broadcastedB); - save([$condition]); - return res; - }; - var inputs = { - condition: $condition, - t: $broadcastedA, - e: $broadcastedB - }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, SelectV2); - } - var where = op({ where_: where_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var clipByValueGradConfig = { - kernelName: ClipByValue, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0]; - var _a = attrs, clipValueMin = _a.clipValueMin, clipValueMax = _a.clipValueMax; - return { - x: function () { return where(logicalAnd(greaterEqual(x, clipValueMin), lessEqual(x, clipValueMax)), dy, zerosLike(dy)); }, - }; - } - }; - - /** - * Prepare the split size array. When the input is a number, the axis is evenly - * divided among the split size. When the input contains the negative value, the - * rest of the axis is allocated toward that. - */ - function prepareSplitSize(x, numOrSizeSplits, axis) { - if (axis === void 0) { axis = 0; } - var splitSizes = []; - if (typeof (numOrSizeSplits) === 'number') { - assert(x.shape[axis] % numOrSizeSplits === 0, function () { return 'Number of splits must evenly divide the axis.'; }); - splitSizes = - new Array(numOrSizeSplits).fill(x.shape[axis] / numOrSizeSplits); - } - else { - var numOfNegs = numOrSizeSplits.reduce(function (count, value) { - if (value === -1) { - count += 1; - } - return count; - }, 0); - assert(numOfNegs <= 1, function () { return 'There should be only one negative value in split array.'; }); - var negIndex = numOrSizeSplits.indexOf(-1); - // Allow the number of split array to be -1, which indicates the rest - // of dimension is allocated to that split. - if (negIndex !== -1) { - var total = numOrSizeSplits.reduce(function (a, b) { return b > 0 ? a + b : a; }); - numOrSizeSplits[negIndex] = x.shape[axis] - total; - } - assert(x.shape[axis] === numOrSizeSplits.reduce(function (a, b) { return a + b; }), function () { return 'The sum of sizes must match the size of the axis dimension.'; }); - splitSizes = numOrSizeSplits; - } - return splitSizes; - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Splits a `tf.Tensor` into sub tensors. - * - * If `numOrSizeSplits` is a number, splits `x` along dimension `axis` - * into `numOrSizeSplits` smaller tensors. - * Requires that `numOrSizeSplits` evenly divides `x.shape[axis]`. - * - * If `numOrSizeSplits` is a number array, splits `x` into - * `numOrSizeSplits.length` pieces. The shape of the `i`-th piece has the - * same size as `x` except along dimension `axis` where the size is - * `numOrSizeSplits[i]`. - * - * ```js - * const x = tf.tensor2d([1, 2, 3, 4, 5, 6, 7, 8], [2, 4]); - * const [a, b] = tf.split(x, 2, 1); - * a.print(); - * b.print(); - * - * const [c, d, e] = tf.split(x, [1, 2, 1], 1); - * c.print(); - * d.print(); - * e.print(); - * ``` - * - * @param x The input tensor to split. - * @param numOrSizeSplits Either an integer indicating the number of - * splits along the axis or an array of integers containing the sizes of - * each output tensor along the axis. If a number then it must evenly divide - * `x.shape[axis]`; otherwise the sum of sizes must match `x.shape[axis]`. - * Can contain one -1 indicating that dimension is to be inferred. - * @param axis The dimension along which to split. Defaults to 0 (the first - * dim). - */ - /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ - function split_(x, numOrSizeSplits, axis) { - if (axis === void 0) { axis = 0; } - var $x = convertToTensor(x, 'x', 'split'); - var forward = function (backend, _) { - var $axis = parseAxisParam(axis, $x.shape)[0]; - var splitSizes = prepareSplitSize($x, numOrSizeSplits, $axis); - return backend.split($x, splitSizes, $axis); - }; - var inputs = { x: $x }; - var attr = { numOrSizeSplits: numOrSizeSplits, axis: axis }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, SplitV, attr); - } - var split = op({ split_: split_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var concatGradConfig = { - kernelName: Concat, - saveAllInputs: true, - gradFunc: function (dy, saved, attrs) { - var shapes = saved.map(function (t) { return t.shape; }); - var axis = attrs.axis; - var $axis = parseAxisParam(axis, saved[0].shape)[0]; - var sizeSplits = shapes.map(function (s) { return s[$axis]; }); - var derTensors = split(dy, sizeSplits, $axis); - return derTensors.map(function (t) { return function () { return t; }; }); - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the derivative of the filter of a 2D convolution. - * - * @param x The input tensor, of rank 4 or rank 3 of shape - * [batch, height, width, inChannels]. If rank 3, batch of 1 is assumed. - * @param dy The dy image, of rank 4 or rank 3, of shape - * [batch, height, width, outDepth]. If rank 3, batch of 1 is assumed. - * @param filterShape The shape of the filter, length 4, - * [filterHeight, filterWidth, inDepth, outDepth]. - * @param strides The strides of the convolution: [strideHeight, - * strideWidth]. - * @param pad A string from: 'same', 'valid'. The type of padding algorithm - * used in the forward prop of the op. - * @param dataFormat: An optional string from: "NHWC", "NCHW". Defaults to - * "NHWC". Specify the data format of the input and output data. With the - * default format "NHWC", the data is stored in the order of: [batch, - * height, width, channels]. - * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The - * rounding mode used when computing output dimensions if pad is a - * number. If none is provided, it will not round and error if the output - * is of fractional size. - */ - function conv2DBackpropFilter_(x, dy, filterShape, strides, pad, dataFormat, dimRoundingMode) { - if (dataFormat === void 0) { dataFormat = 'NHWC'; } - var x4D = x; - if (x.rank === 3) { - x4D = reshape(x, [1, x.shape[0], x.shape[1], x.shape[2]]); - } - var dy4D = dy; - if (dy4D.rank === 3) { - dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); - } - assert(x4D.rank === 4, function () { return "Error in conv2dDerFilter: input must be rank 4, but got shape " + - (x4D.shape + "."); }); - assert(dy4D.rank === 4, function () { return "Error in conv2dDerFilter: dy must be rank 4, but got shape " + - (dy4D.shape + "."); }); - assert(filterShape.length === 4, function () { return "Error in conv2dDerFilter: filterShape must be length 4, but got " + - (filterShape + "."); }); - var inDepth = dataFormat === 'NHWC' ? x4D.shape[3] : x4D.shape[1]; - var outDepth = dataFormat === 'NHWC' ? dy4D.shape[3] : dy4D.shape[1]; - assert(inDepth === filterShape[2], function () { return "Error in conv2dDerFilter: depth of input " + inDepth + ") must " + - ("match input depth in filter (" + filterShape[2] + "."); }); - assert(outDepth === filterShape[3], function () { return "Error in conv2dDerFilter: depth of dy (" + outDepth + ") must " + - ("match output depth for filter (" + filterShape[3] + ")."); }); - if (dimRoundingMode != null) { - assert(isInt(pad), function () { return "Error in conv2dDerFilter: pad must be an integer when using, " + - ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); - } - var forward = function (backend) { - var dilations = 1; - var $dataFormat = convertConv2DDataFormat(dataFormat); - var convInfo = computeConv2DInfo(x4D.shape, filterShape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); - return backend.conv2dDerFilter(x4D, dy4D, convInfo); - }; - var inputs = { x: x4D, dy: dy4D }; - var attrs = { strides: strides, pad: pad, dataFormat: dataFormat, dimRoundingMode: dimRoundingMode }; - return ENGINE.runKernelFunc(forward, inputs, null, Conv2DBackpropFilter, attrs); - } - var conv2DBackpropFilter = op({ conv2DBackpropFilter_: conv2DBackpropFilter_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the derivative of the input of a 2D convolution. - * - * @param xShape The shape of the input: [batch, height, width, inDepth]. - * If length of 3, batch of 1 is assumed. - * @param dy The derivative of the output, of rank 4 or rank 3 of shape - * `[batch, outHeight, outWidth, outDepth]`. If rank 3, batch of 1 is - * assumed. - * @param filter The filter, rank 4, of shape - * `[filterHeight, filterWidth, inDepth, outDepth]`. - * @param strides The strides of the convolution: `[strideHeight, - * strideWidth]`. - * @param pad The type of padding algorithm used: - * - `same` and stride 1: output will be of same size as input, - * regardless of filter size. - * - `valid`: output will be smaller than input if filter is larger - * than 1x1. - * @param dataFormat: An optional string from: "NHWC", "NCHW". Defaults to - * "NHWC". Specify the data format of the input and output data. With the - * default format "NHWC", the data is stored in the order of: [batch, - * height, width, channels]. - * @param dimRoundingMode The rounding mode used when computing output - * dimensions if pad is a number. If none is provided, it will not round - * and error if the output is of fractional size. - */ - function conv2DBackpropInput_(xShape, dy, filter, strides, pad, dataFormat, dimRoundingMode) { - if (dataFormat === void 0) { dataFormat = 'NHWC'; } - assert(xShape.length === dy.rank, function () { return "Length of inShape " + - ("(" + xShape.length + ") and rank of dy (" + dy.rank + ") must match"); }); - var xShape4D = xShape; - var dy4D = dy; - var reshapedTo4D = false; - if (dy.rank === 3) { - reshapedTo4D = true; - dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); - xShape4D = [1, xShape[0], xShape[1], xShape[2]]; - } - assert(xShape4D.length === 4, function () { - return "Error in conv2dDerInput: inShape must be length 4, but got length " + - (xShape4D.length + "."); - }); - assert(dy4D.rank === 4, function () { return "Error in conv2dDerInput: dy must be rank 4, but got " + - ("rank " + dy4D.rank); }); - assert(filter.rank === 4, function () { return "Error in conv2dDerInput: filter must be rank 4, but got " + - ("rank " + filter.rank); }); - var inDepth = dataFormat === 'NHWC' ? xShape4D[3] : xShape4D[1]; - var outDepth = dataFormat === 'NHWC' ? dy4D.shape[3] : dy4D.shape[1]; - assert(inDepth === filter.shape[2], function () { return "Error in conv2dDerInput: depth of input (" + inDepth + ") must " + - ("match input depth for filter " + filter.shape[2] + "."); }); - assert(outDepth === filter.shape[3], function () { return "Error in conv2dDerInput: depth of output (" + outDepth + ") must " + - ("match output depth for filter " + filter.shape[3] + "."); }); - if (dimRoundingMode != null) { - assert(isInt(pad), function () { return "Error in conv2dDerInput: pad must be an integer when using, " + - ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); - } - var forward = function (backend, save) { - var dilations = 1; - var $dataFormat = convertConv2DDataFormat(dataFormat); - var convInfo = computeConv2DInfo(xShape4D, filter.shape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); - var res = backend.conv2dDerInput(dy4D, filter, convInfo); - save([dy4D, filter]); - return res; - }; - var inputs = { dy: dy4D, filter: filter }; - var attrs = { strides: strides, pad: pad, dataFormat: dataFormat, dimRoundingMode: dimRoundingMode, inputShape: xShape4D }; - var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, Conv2DBackpropInput, attrs); - if (reshapedTo4D) { - return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); - } - return res; - } - var conv2DBackpropInput = op({ conv2DBackpropInput_: conv2DBackpropInput_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var conv2DGradConfig = { - kernelName: Conv2D, - inputsToSave: ['x', 'filter'], - gradFunc: function (dy, saved, attrs) { - var _a = saved, x4D = _a[0], $filter = _a[1]; - var _b = attrs, dilations = _b.dilations, strides = _b.strides, pad = _b.pad, dataFormat = _b.dataFormat; - assert(tupleValuesAreOne(dilations), function () { return 'Error in gradient of conv2D: dilation rates greater than 1 ' + - ("are not yet supported in gradients. Got dilations '" + dilations + "'"); }); - return { - x: function () { - return conv2DBackpropInput(x4D.shape, dy, $filter, strides, pad, dataFormat); - }, - filter: function () { - return conv2DBackpropFilter(x4D, dy, $filter.shape, strides, pad, dataFormat); - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes a 2D convolution over the input x. - * - * @param x The input tensor, of rank 4 or rank 3, of shape - * `[batch, height, width, inChannels]`. If rank 3, batch of 1 is - * assumed. - * @param filter The filter, rank 4, of shape - * `[filterHeight, filterWidth, inDepth, outDepth]`. - * @param strides The strides of the convolution: `[strideHeight, - * strideWidth]`. - * @param pad The type of padding algorithm. - * - `same` and stride 1: output will be of same size as input, - * regardless of filter size. - * - `valid`: output will be smaller than input if filter is larger - * than 1x1. - * - For more info, see this guide: - * [https://www.tensorflow.org/api_guides/python/nn#Convolution]( - * https://www.tensorflow.org/api_guides/python/nn#Convolution) - * @param dataFormat: An optional string from: "NHWC", "NCHW". Defaults to - * "NHWC". Specify the data format of the input and output data. With the - * default format "NHWC", the data is stored in the order of: [batch, - * height, width, channels]. - * @param dilations The dilation rates: `[dilationHeight, dilationWidth]` - * in which we sample input values across the height and width dimensions - * in atrous convolution. Defaults to `[1, 1]`. If `dilations` is a single - * number, then `dilationHeight == dilationWidth`. If it is greater than - * 1, then all values of `strides` must be 1. - * @param dimRoundingMode The rounding mode used when computing output - * dimensions if pad is a number. If none is provided, it will not round - * and error if the output is of fractional size. - */ - /** @doc {heading: 'Operations', subheading: 'Convolution'} */ - function conv2d_(x, filter, strides, pad, dataFormat, dilations, dimRoundingMode) { - if (dataFormat === void 0) { dataFormat = 'NHWC'; } - if (dilations === void 0) { dilations = [1, 1]; } - var $x = convertToTensor(x, 'x', 'conv2d'); - var $filter = convertToTensor(filter, 'filter', 'conv2d'); - var x4D = $x; - var reshapedTo4D = false; - if ($x.rank === 3) { - reshapedTo4D = true; - x4D = reshape($x, [1, $x.shape[0], $x.shape[1], $x.shape[2]]); - } - assert(x4D.rank === 4, function () { return "Error in conv2d: input must be rank 4, but got rank " + x4D.rank + "."; }); - assert($filter.rank === 4, function () { return "Error in conv2d: filter must be rank 4, but got rank " + - ($filter.rank + "."); }); - if (dimRoundingMode != null) { - assert(isInt(pad), function () { return "Error in conv2d: pad must be an integer when using, " + - ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); - } - var inDepth = dataFormat === 'NHWC' ? x4D.shape[3] : x4D.shape[1]; - assert(inDepth === $filter.shape[2], function () { return "Error in conv2d: depth of input (" + inDepth + ") must match " + - ("input depth for filter " + $filter.shape[2] + "."); }); - assert(eitherStridesOrDilationsAreOne(strides, dilations), function () { return 'Error in conv2D: Either strides or dilations must be 1. ' + - ("Got strides " + strides + " and dilations '" + dilations + "'"); }); - var forward = function (backend, save) { - var $dataFormat = convertConv2DDataFormat(dataFormat); - var convInfo = computeConv2DInfo(x4D.shape, $filter.shape, strides, dilations, pad, dimRoundingMode, false, $dataFormat); - var res = backend.conv2d(x4D, $filter, convInfo); - save([x4D, $filter]); - return res; - }; - var inputs = { x: x4D, filter: $filter }; - var attrs = { strides: strides, pad: pad, dataFormat: dataFormat, dilations: dilations, dimRoundingMode: dimRoundingMode }; - var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, Conv2D, attrs); - if (reshapedTo4D) { - return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); - } - return res; - } - var conv2d = op({ conv2d_: conv2d_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var conv2DBackpropInputGradConfig = { - kernelName: Conv2DBackpropInput, - inputsToSave: ['dy', 'filter'], - gradFunc: function (ddx, saved, attrs) { - var _a = saved, dy = _a[0], filter = _a[1]; - var _b = attrs, strides = _b.strides, pad = _b.pad, dataFormat = _b.dataFormat, dimRoundingMode = _b.dimRoundingMode; - return { - dy: function () { return conv2d(ddx, filter, strides, pad, dataFormat, 1 /* dilations */, dimRoundingMode); }, - filter: function () { return conv2DBackpropFilter(ddx, dy, filter.shape, strides, pad, dataFormat, dimRoundingMode); } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the derivative of the filter of a 3D convolution. - * - * @param x The input tensor, of rank 5 or rank 4 of shape - * [batch, depth, height, width, inChannels]. If rank 4, batch of 1 is - * assumed. - * @param dy The dy image, of rank 5 or rank 4, of shape - * [batch, depth, height, width, outDepth]. If rank 4, batch of 1 is - * assumed. - * @param filterShape The shape of the filter, length 5, - * [filterDepth, filterHeight, filterWidth, inDepth, outDepth]. - * @param strides The strides of the convolution: [strideDepth, strideHeight, - * strideWidth]. - * @param pad A string from: 'same', 'valid'. The type of padding algorithm - * used in the forward prop of the op. - */ - function conv3DBackpropFilter_(x, dy, filterShape, strides, pad) { - var x5D = x; - if (x.rank === 4) { - x5D = reshape(x, [1, x.shape[0], x.shape[1], x.shape[2], x.shape[3]]); - } - var dy5D = dy; - if (dy5D.rank === 4) { - dy5D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2], dy.shape[3]]); - } - assert(x5D.rank === 5, function () { return "Error in conv3dDerFilter: input must be rank 5, but got shape " + - (x5D.shape + "."); }); - assert(dy5D.rank === 5, function () { return "Error in conv3dDerFilter: dy must be rank 5, but got shape " + - (dy5D.shape + "."); }); - assert(filterShape.length === 5, function () { return "Error in conv3dDerFilter: filterShape must be length 5, but got " + - (filterShape + "."); }); - assert(x5D.shape[4] === filterShape[3], function () { return "Error in conv3dDerFilter: depth of input " + x5D.shape[4] + ") must " + - ("match input depth in filter (" + filterShape[3] + "."); }); - assert(dy5D.shape[4] === filterShape[4], function () { return "Error in conv3dDerFilter: depth of dy (" + dy5D.shape[4] + ") must " + - ("match output depth for filter (" + filterShape[4] + ")."); }); - var forward = function (backend) { - var dilations = 1; - var convInfo = computeConv3DInfo(x5D.shape, filterShape, strides, dilations, pad); - return backend.conv3dDerFilter(x5D, dy5D, convInfo); - }; - var inputs = { x: x5D, y: dy5D }; - var attrs = { strides: strides, pad: pad }; - return ENGINE.runKernelFunc(forward, inputs, null, Conv3DBackpropFilterV2, attrs); - } - var conv3DBackpropFilter = op({ conv3DBackpropFilter_: conv3DBackpropFilter_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the derivative of the input of a 3D convolution. - * - * @param xShape The shape of the input: [batch, depth, height, width, - * in_channels]. If length of 4, batch of 1 is assumed. - * @param dy The derivative of the output, of rank 5 or rank 4 of shape - * `[batch, outDepth, outHeight, outWidth, in_channels]`. - * If rank 4, batch of 1 is assumed. - * @param filter The filter, rank 5, of shape - * `[filterDepth, filterHeight, filterWidth, inDepth, outDepth]`. - * @param strides The strides of the convolution: `[strideDepth, strideHeight, - * strideWidth]`. - * @param pad The type of padding algorithm used: - * - `same` and stride 1: output will be of same size as input, - * regardless of filter size. - * - `valid`: output will be smaller than input if filter is larger - * than 1x1. - */ - function conv3DBackpropInput_(xShape, dy, filter, strides, pad) { - assert(xShape.length === dy.rank, function () { return "Length of inShape " + - ("(" + xShape.length + ") and rank of dy (" + dy.rank + ") must match"); }); - var xShape5D = xShape; - var dy5D = dy; - var reshapedTo5D = false; - if (dy.rank === 4) { - reshapedTo5D = true; - dy5D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2], dy.shape[3]]); - xShape5D = [1, xShape[0], xShape[1], xShape[2], xShape[3]]; - } - var inDepth = xShape5D[4]; - var outDepth = dy5D.shape[4]; - assert(xShape5D.length === 5, function () { - return "Error in conv3dDerInput: inShape must be length 5, but got length " + - (xShape5D.length + "."); - }); - assert(dy5D.rank === 5, function () { return "Error in conv3dDerInput: dy must be rank 5, but got " + - ("rank " + dy5D.rank); }); - assert(filter.rank === 5, function () { return "Error in conv3dDerInput: filter must be rank 5, but got " + - ("rank " + filter.rank); }); - assert(inDepth === filter.shape[3], function () { return "Error in conv3dDerInput: depth of input (" + inDepth + ") must " + - ("match input depth for filter " + filter.shape[3] + "."); }); - assert(outDepth === filter.shape[4], function () { return "Error in conv3dDerInput: depth of output (" + outDepth + ") must " + - ("match output depth for filter " + filter.shape[4] + "."); }); - var forward = function (backend) { - var dilations = 1; - var convInfo = computeConv3DInfo(xShape5D, filter.shape, strides, dilations, pad); - return backend.conv3dDerInput(dy5D, filter, convInfo); - }; - var inputs = { dy: dy5D }; - var attrs = { pad: pad }; - var res = ENGINE.runKernelFunc(forward, inputs, null, Conv3DBackpropInputV2, attrs); - if (reshapedTo5D) { - return reshape(res, [res.shape[1], res.shape[2], res.shape[3], res.shape[4]]); - } - return res; - } - var conv3DBackpropInput = op({ conv3DBackpropInput_: conv3DBackpropInput_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var conv3DGradConfig = { - kernelName: Conv3D, - inputsToSave: ['x', 'filter'], - gradFunc: function (dy, saved, attrs) { - var _a = attrs, dilations = _a.dilations, strides = _a.strides, pad = _a.pad; - assert(tupleValuesAreOne(dilations), function () { - return 'Error in gradient of conv3D: dilation rates greater than 1 are ' + - ("not yet supported in gradients. Got dilations '" + dilations + "'"); - }); - var x5D = saved[0], $filter = saved[1]; - return { - x: function () { return conv3DBackpropInput(x5D.shape, dy, $filter, strides, pad); }, - filter: function () { return conv3DBackpropFilter(x5D, dy, $filter.shape, strides, pad); } - }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes sin of the input Tensor element-wise: `sin(x)` - * - * ```js - * const x = tf.tensor1d([0, Math.PI / 2, Math.PI * 3 / 4]); - * - * x.sin().print(); // or tf.sin(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function sin_(x) { - var $x = convertToTensor(x, 'x', 'sin'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.sin($x); - save([$x]); - return res; - }, inputs, null /* grad */, Sin); - } - var sin = op({ sin_: sin_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var cosGradConfig = { - kernelName: Cos, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(neg(sin(cast(x, 'float32'))), dy); } }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes hyperbolic sin of the input `tf.Tensor` element-wise: `sinh(x)` - * - * ```js - * const x = tf.tensor1d([0, 1, -1, .7]); - * - * x.sinh().print(); // or tf.sinh(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function sinh_(x) { - var $x = convertToTensor(x, 'x', 'sinh'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.sinh($x); - save([$x]); - return res; - }, inputs, null /* grad */, Sinh); - } - var sinh = op({ sinh_: sinh_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var coshGradConfig = { - kernelName: Cosh, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(sinh(cast(x, 'float32')), dy); } }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Transposes the `tf.Tensor`. Permutes the dimensions according to `perm`. - * - * The returned `tf.Tensor`'s dimension `i` will correspond to the input - * dimension `perm[i]`. If `perm` is not given, it is set to `[n-1...0]`, - * where `n` is the rank of the input `tf.Tensor`. Hence by default, this - * operation performs a regular matrix transpose on 2-D input `tf.Tensor`s. - * - * ```js - * const a = tf.tensor2d([1, 2, 3, 4, 5, 6], [2, 3]); - * - * a.transpose().print(); // or tf.transpose(a) - * ``` - * - * @param x The tensor to transpose. - * @param perm The permutation of the dimensions of a. - */ - /** @doc {heading: 'Operations', subheading: 'Matrices'} */ - function transpose_(x, perm) { - var $x = convertToTensor(x, 'x', 'transpose'); - if (perm == null) { - perm = $x.shape.map(function (s, i) { return i; }).reverse(); - } - assert($x.rank === perm.length, function () { return "Error in transpose: rank of input " + $x.rank + " " + - ("must match length of perm " + perm + "."); }); - perm.forEach(function (axis) { - assert(axis >= 0 && axis < $x.rank, function () { return "All entries in 'perm' must be between 0 and " + ($x.rank - 1) + - (" but got " + perm); }); - }); - if ($x.rank <= 1) { - return $x.clone(); - } - var inputs = { x: $x }; - var attrs = { perm: perm }; - return ENGINE.runKernelFunc(function (backend) { return backend.transpose($x, perm); }, inputs, null /* gradient */, Transpose, attrs); - } - var transpose = op({ transpose_: transpose_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the cumulative sum of a `tf.Tensor` along `axis`. - * - * ```js - * const x = tf.tensor([1, 2, 3, 4]); - * x.cumsum().print(); - * ``` - * ```js - * const x = tf.tensor([[1, 2], [3, 4]]); - * x.cumsum().print(); - * ``` - * - * @param x The input tensor to be summed. - * @param axis The axis along which to sum. Optional. Defaults to 0. - * @param exclusive Whether to perform exclusive cumulative sum. Optional. - * Defaults to false. If set to true then the sum of each tensor entry - * does not include its own value, but only the values previous to it - * along the specified axis. - * @param reverse Whether to sum in the opposite direction. Optional. - * Defaults to false. - */ - /** @doc {heading: 'Operations', subheading: 'Scan'} */ - function cumsum_(x, axis, exclusive, reverse) { - if (axis === void 0) { axis = 0; } - if (exclusive === void 0) { exclusive = false; } - if (reverse === void 0) { reverse = false; } - var $x = convertToTensor(x, 'x', 'cumsum'); - var forward = function (backend, save) { - var permutation = getAxesPermutation([axis], $x.rank); - var permutedX = $x; - if (permutation != null) { - permutedX = transpose($x, permutation); - } - var permutedAxis = getInnerMostAxes(1, $x.rank)[0]; - var value = backend.cumsum(permutedX, permutedAxis, exclusive, reverse); - save([$x]); - if (permutation != null) { - var reversePermutation = getUndoAxesPermutation(permutation); - value = transpose(value, reversePermutation); - } - return value; - }; - var inputs = { x: $x }; - var attrs = { axis: axis, exclusive: exclusive, reverse: reverse }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Cumsum, attrs); - } - var cumsum = op({ cumsum_: cumsum_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var cumsumGradConfig = { - kernelName: Cumsum, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0]; - var _a = attrs, axis = _a.axis, exclusive = _a.exclusive, reverse = _a.reverse; - return { - x: function () { - var permutation = getAxesPermutation([axis], x.rank); - var out = cumsum(dy, axis, exclusive, !reverse); - if (permutation != null) { - out = transpose(out, permutation); - } - return out; - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function depthwiseConv2dNativeBackpropFilter_(x, dy, filterShape, convInfo) { - var x4D = x; - if (x.rank === 3) { - x4D = reshape(x, [1, x.shape[0], x.shape[1], x.shape[2]]); - } - var dy4D = dy; - if (dy4D.rank === 3) { - dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); - } - var forward = function (backend) { - return backend.depthwiseConv2DDerFilter(x4D, dy4D, convInfo); - }; - var inputs = { x: x4D, dy: dy4D }; - return ENGINE.runKernelFunc(forward, inputs, null, DepthwiseConv2dNativeBackpropFilter); - } - var depthwiseConv2dNativeBackpropFilter = op({ depthwiseConv2dNativeBackpropFilter_: depthwiseConv2dNativeBackpropFilter_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function depthwiseConv2dNativeBackpropInput_(xShape, dy, filter, convInfo) { - var dy4D = dy; - var reshapedTo4D = false; - if (dy.rank === 3) { - reshapedTo4D = true; - dy4D = reshape(dy, [1, dy.shape[0], dy.shape[1], dy.shape[2]]); - } - var forward = function (backend) { - return backend.depthwiseConv2DDerInput(dy4D, filter, convInfo); - }; - var inputs = { dy: dy4D }; - var res = ENGINE.runKernelFunc(forward, inputs, null, DepthwiseConv2dNativeBackpropInput); - if (reshapedTo4D) { - return reshape(res, [res.shape[1], res.shape[2], res.shape[3]]); - } - return res; - } - var depthwiseConv2dNativeBackpropInput = op({ depthwiseConv2dNativeBackpropInput_: depthwiseConv2dNativeBackpropInput_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var depthwiseConv2dNativeGradConfig = { - kernelName: DepthwiseConv2dNative, - inputsToSave: ['x', 'filter'], - gradFunc: function (dy, saved, attrs) { - var _a = attrs, dilations = _a.dilations, strides = _a.strides, pad = _a.pad, dimRoundingMode = _a.dimRoundingMode; - var $dilations = dilations == null ? [1, 1] : dilations; - assert(tupleValuesAreOne($dilations), function () { return 'Error in gradient of depthwiseConv2dNative: dilation rates ' + - "greater than 1 are not yet supported. Got dilations " + - ("'" + $dilations + "'"); }); - var _b = saved, x = _b[0], filter = _b[1]; - assert(x.rank === 4, function () { return "Error in gradient of depthwiseConv2dNative: input must be " + - ("rank 4, but got rank " + x.rank + "."); }); - assert(filter.rank === 4, function () { return "Error in gradient of depthwiseConv2dNative: filter must be " + - ("rank 4, but got rank " + filter.rank + "."); }); - assert(x.shape[3] === filter.shape[2], function () { return "Error in gradient of depthwiseConv2d: number of input " + - ("channels (" + x.shape[3] + ") must match the inChannels dimension ") + - ("in filter " + filter.shape[2] + "."); }); - assert(eitherStridesOrDilationsAreOne(strides, $dilations), function () { return 'Error in gradient of depthwiseConv2d: Either strides or ' + - ("dilations must be 1. Got strides " + strides + " and dilations ") + - ("'" + $dilations + "'."); }); - if (dimRoundingMode != null) { - assert(isInt(pad), function () { - return "Error in depthwiseConv2d: pad must be an integer when using, " + - ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); - }); - } - var convInfo = computeConv2DInfo(x.shape, filter.shape, strides, $dilations, pad, dimRoundingMode, true /* depthwise */); - return { - x: function () { - return depthwiseConv2dNativeBackpropInput(x.shape, dy, filter, convInfo); - }, - filter: function () { - return depthwiseConv2dNativeBackpropFilter(x, dy, filter.shape, convInfo); - }, - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var dilation2dGradConfig = { - kernelName: Dilation2D, - inputsToSave: ['x', 'filter'], - gradFunc: function (dy, saved, attrs) { - var _a = saved, x = _a[0], filter = _a[1]; - var inputInputs = { x: x, filter: filter, dy: dy }; - var filterInputs = { x: x, filter: filter, dy: dy }; - return { - x: function () { return ENGINE.runKernel(Dilation2DBackpropInput, inputInputs, attrs); }, - filter: function () { return ENGINE.runKernel(Dilation2DBackpropFilter, filterInputs, attrs); } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var divGradConfig = { - kernelName: Div, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var outShape = assertAndGetBroadcastShape(a.shape, b.shape); - var derA = function () { - var res = div(dy, b.toFloat()); - var reduceAxes = getReductionAxes(a.shape, outShape); - if (reduceAxes.length > 0) { - return sum$1(res, reduceAxes).reshape(a.shape); - } - return res; - }; - var derB = function () { - var res = mul(dy, a.toFloat()); - var reduceAxes = getReductionAxes(b.shape, outShape); - if (reduceAxes.length > 0) { - res = reshape(sum$1(res, reduceAxes), b.shape); - } - var tmp = square(b); - return neg(div(res, tmp.toFloat())); - }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var eluGradConfig = { - kernelName: Elu, - outputsToSave: [true], - gradFunc: function (dy, saved) { - var y = saved[0]; - var backPropKernelFunc = function (backend) { - return backend.eluDer(dy, y); - }; - var inputs = { dy: dy, y: y }; - return { - x: function () { return ENGINE.runKernelFunc(backPropKernelFunc, inputs, null /* grad */, EluGrad); } - }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes exponential of the input `tf.Tensor` element-wise. `e ^ x` - * - * ```js - * const x = tf.tensor1d([1, 2, -3]); - * - * x.exp().print(); // or tf.exp(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function exp_(x) { - var $x = convertToTensor(x, 'x', 'exp'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.exp($x); - save([res]); - return res; - }, inputs, null /* grad */, Exp); - } - var exp = op({ exp_: exp_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var erfGradConfig = { - kernelName: Erf, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - var a = mul(exp(neg(square(x))), 2 / Math.sqrt(Math.PI)); - return { x: function () { return mul(dy, a); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var expGradConfig = { - kernelName: Exp, - outputsToSave: [true], - gradFunc: function (dy, saved) { - var y = saved[0]; - return { x: function () { return mul(dy, y); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var expm1GradConfig = { - kernelName: Expm1, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(dy, exp(x)); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var floorGradConfig = { - kernelName: Floor, - gradFunc: function (dy) { - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var floorDivGradConfig = { - kernelName: FloorDiv, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var outShape = assertAndGetBroadcastShape(a.shape, b.shape); - var derA = function () { - var res = dy.div(b.toFloat()); - var reduceAxes = getReductionAxes(a.shape, outShape); - if (reduceAxes.length > 0) { - return res.sum(reduceAxes).reshape(a.shape); - } - return res; - }; - var derB = function () { - var res = dy.mul(a.toFloat()); - var reduceAxes = getReductionAxes(b.shape, outShape); - if (reduceAxes.length > 0) { - res = res.sum(reduceAxes).reshape(b.shape); - } - var tmp = b.square(); - return res.div(tmp.toFloat()).neg(); - }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes reciprocal of square root of the input `tf.Tensor` element-wise: - * `y = 1 / sqrt(x)` - * - * ```js - * const x = tf.tensor1d([1, 2, 4, -1]); - * - * x.rsqrt().print(); // or tf.rsqrt(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function rsqrt_(x) { - var $x = convertToTensor(x, 'x', 'rsqrt'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.rsqrt($x); - save([$x]); - return res; - }, inputs, null /* grad */, Rsqrt); - } - var rsqrt = op({ rsqrt_: rsqrt_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Construct a tensor by repeating it the number of times given by reps. - * - * This operation creates a new tensor by replicating `input` `reps` - * times. The output tensor's i'th dimension has `input.shape[i] * - * reps[i]` elements, and the values of `input` are replicated - * `reps[i]` times along the i'th dimension. For example, tiling - * `[a, b, c, d]` by `[2]` produces `[a, b, c, d, a, b, c, d]`. - * - * ```js - * const a = tf.tensor1d([1, 2]); - * - * a.tile([2]).print(); // or a.tile([2]) - * ``` - * - * ```js - * const a = tf.tensor2d([1, 2, 3, 4], [2, 2]); - * - * a.tile([1, 2]).print(); // or a.tile([1, 2]) - * ``` - * @param x The tensor to tile. - * @param reps Determines the number of replications per dimension. - */ - /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ - function tile_(x, reps) { - var parseAs = null; - var $x = convertToTensor(x, 'x', 'tile', parseAs); - assert($x.rank === reps.length, function () { return "Error in transpose: rank of input " + $x.rank + " " + - ("must match length of reps " + reps + "."); }); - var forward = function (backend, save) { - var res = backend.tile($x, reps); - save([$x]); - return res; - }; - var inputsToSave = [$x]; - var inputs = { x: $x }; - var attrs = { reps: reps }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Tile, attrs, inputsToSave); - } - var tile = op({ tile_: tile_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var fusedBatchNormGradConfig = { - kernelName: FusedBatchNorm, - inputsToSave: ['x', 'mean', 'variance', 'scale'], - gradFunc: function (dy, saved, attrs) { - var varianceEpsilon = attrs.varianceEpsilon; - var x = saved[0], mean = saved[1], variance = saved[2], scale = saved[3]; - var scaleValue = scale == null ? scalar(1) : scale; - var reductionAxes = getReductionAxes(mean.shape, x.shape); - var tileShape = []; - if (mean.rank === 1) { - for (var i = 0; i < x.shape.length - 1; ++i) { - tileShape.push(x.shape[i]); - } - tileShape.push(1); - } - var xMinusMean = sub(x, mean); - var dyTimesScaleValue = mul(dy, scaleValue); - var oneOverSqrtVariance = rsqrt(add(variance, scalar(varianceEpsilon))); - var minusHalfRCube = mul(mul(mul(oneOverSqrtVariance, oneOverSqrtVariance), oneOverSqrtVariance), scalar(-0.5)); - var derX = function () { - if (mean.rank === 1) { - return reshape(mul(mul(dy, tile(oneOverSqrtVariance.as4D(1, 1, 1, mean.shape[0]), tileShape)), scaleValue), x.shape); - } - else { - return reshape(mul(mul(dy, oneOverSqrtVariance), scaleValue), x.shape); - } - }; - var derMean = function () { - var meanDer = mul(mul(oneOverSqrtVariance, scalar(-1)), dyTimesScaleValue); - if (mean.rank === 1) { - meanDer = sum$1(meanDer, reductionAxes); - } - return reshape(meanDer, mean.shape); - }; - var derVariance = function () { - var varianceDer = mul(mul(minusHalfRCube, xMinusMean), dyTimesScaleValue); - if (mean.rank === 1) { - varianceDer = sum$1(varianceDer, reductionAxes); - } - return reshape(varianceDer, mean.shape); - }; - var derScale = function () { - var xMinusMean2TimesRsqrt = mul(xMinusMean, oneOverSqrtVariance); - var scaleDer = mul(dy, xMinusMean2TimesRsqrt); - if (mean.rank === 1) { - scaleDer = sum$1(scaleDer, reductionAxes); - } - return reshape(scaleDer, mean.shape); - }; - var derOffset = function () { - var offsetDer = dy; - if (mean.rank === 1) { - offsetDer = sum$1(offsetDer, reductionAxes); - } - return reshape(offsetDer, mean.shape); - }; - return { - x: derX, - mean: derMean, - variance: derVariance, - scale: derScale, - offset: derOffset - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the sum along segments of a `tf.Tensor`. - * - * ```js - * const x = tf.tensor1d([1, 2, 3, 4]); - * const segmentIds = tf.tensor1d([1, 2, 0, 1], 'int32'); - * const numSegments = 3; - * - * x.unsortedSegmentSum(segmentIds, numSegments).print() - * //or tf.unsortedSegmentSum(x, segmentIds, numSegments) - * ``` - * @param x The `tf.Tensor` that will be summed along its segments. - * @param segmentIds A `tf.Tensor1D` whose rank is equal to the rank of `x`'s - * dimension along the `axis`. Maps each element of `x` to a segment. - * @param numSegments The number of distinct `segmentIds`. - */ - /** @doc {heading: 'Operations', subheading: 'Segment'} */ - function unsortedSegmentSum_(x, segmentIds, numSegments) { - var $x = convertToTensor(x, 'x', 'unsortedSegmentSum'); - var $segmentIds = convertToTensor(segmentIds, 'segmentIds', 'unsortedSegmentSum', 'int32'); - assert(isInt(numSegments), function () { return 'numSegments must be of dtype int'; }); - var inputs = { x: $x, segmentIds: $segmentIds }; - var attrs = { numSegments: numSegments }; - var forward = function (backend, save) { - var res = backend.unsortedSegmentSum($x, $segmentIds, numSegments); - save([$segmentIds]); - return res; - }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, UnsortedSegmentSum, attrs); - } - var unsortedSegmentSum = op({ unsortedSegmentSum_: unsortedSegmentSum_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var gatherGradConfig = { - kernelName: GatherV2, - inputsToSave: ['x', 'indices'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0], indices = saved[1]; - var axis = attrs.axis; - var parsedAxis = parseAxisParam(axis, x.shape)[0]; - var derX = function () { - var paramsShape = x.shape; - var indicesSize = indices.size; - var outerShape = paramsShape.slice(0, parsedAxis); - var outerDims = outerShape.length; - var innerShape = paramsShape.slice(axis, paramsShape.length).slice(1); - var innerDims = innerShape.length; - var outerAxesIndices = arrayRange(0, outerDims); - var innerAxesIndices = arrayRange(outerDims + 1, outerDims + 1 + innerDims); - var valuesShape = arrayConcat([outerShape, [indicesSize], innerShape]); - var values = reshape(dy, valuesShape); - var reshapedIndices = reshape(indices, [indicesSize]); - var transposeDims = arrayConcat([[outerDims], outerAxesIndices, innerAxesIndices]); - var valuesTranspose = transpose(values, transposeDims); - var paramsGrad = unsortedSegmentSum(valuesTranspose, reshapedIndices, x.shape[parsedAxis]); - var invertTransposeDims = getUndoAxesPermutation(transposeDims); - paramsGrad = transpose(paramsGrad, invertTransposeDims); - return paramsGrad; - }; - return { x: derX, indices: function () { return indices; } }; - } - }; - function arrayRange(start, stop) { - var result = []; - for (var i = start; i < stop; ++i) { - result.push(i); - } - return result; - } - function arrayConcat(arrays) { - var result = []; - for (var i = 0; i < arrays.length; ++i) { - for (var j = 0; j < arrays[i].length; ++j) { - result.push(arrays[i][j]); - } - } - return result; - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var greaterEqualGradConfig = { - kernelName: GreaterEqual, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - return { a: function () { return zerosLike(a); }, b: function () { return zerosLike(b); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var identityGradConfig = { - kernelName: Identity, - gradFunc: function (dy) { - return { x: function () { return dy.toFloat(); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var isFiniteGradConfig = { - kernelName: IsFinite, - gradFunc: function (dy) { - // TODO(nsthorat): Let gradients be null for cases where we want to stop - // backpropgation. - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var isInfGradConfig = { - kernelName: IsInf, - gradFunc: function (dy) { - // TODO(nsthorat): Let gradients be null for cases where we want to stop - // backpropgation. - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var isNanGradConfig = { - kernelName: IsNan, - gradFunc: function (dy) { - // TODO(nsthorat): Let gradients be null for cases where we want to stop - // backpropgation. - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var log1pGradConfig = { - kernelName: Log1p, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, add(x, 1)); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var logGradConfig = { - kernelName: Log, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, cast(x, 'float32')); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var logSoftmaxGradConfig = { - kernelName: LogSoftmax, - inputsToSave: [], - outputsToSave: [true], - gradFunc: function (dy, saved, attrs) { - var value = saved[0]; - var axis = attrs.axis; - return { - logits: function () { - var keepDims = true; - var softmax = value.exp(); - return dy.sub(dy.sum(axis, keepDims).mul(softmax)); - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function localResponseNormalizationBackprop_(x, y, dy, depthRadius, bias, alpha, beta) { - if (depthRadius === void 0) { depthRadius = 5; } - if (bias === void 0) { bias = 1; } - if (alpha === void 0) { alpha = 1; } - if (beta === void 0) { beta = 0.5; } - var forward = function (backend) { - return backend.LRNGrad(dy, x, y, depthRadius, bias, alpha, beta); - }; - var inputs = { x: x, y: y, dy: dy }; - var attrs = { depthRadius: depthRadius, bias: bias, alpha: alpha, beta: beta }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, LRNBackprop, attrs); - } - var localResponseNormalizationBackprop = op({ localResponseNormalizationBackprop_: localResponseNormalizationBackprop_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var lrnGradConfig = { - kernelName: LRN, - inputsToSave: ['x'], - outputsToSave: [true], - gradFunc: function (dy, saved, attrs) { - var _a = saved, x = _a[0], y = _a[1]; - var _b = attrs, depthRadius = _b.depthRadius, bias = _b.bias, alpha = _b.alpha, beta = _b.beta; - return { - x: function () { return localResponseNormalizationBackprop(x, y, dy, depthRadius, bias, alpha, beta); } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the truth value of (a == b) element-wise. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([1, 2, 3]); - * const b = tf.tensor1d([2, 2, 2]); - * - * a.equal(b).print(); - * ``` - * - * @param a The first input tensor. - * @param b The second input tensor. Must have the same dtype as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function equal_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'equal'); - var $b = convertToTensor(b, 'b', 'equal'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - assertAndGetBroadcastShape($a.shape, $b.shape); - var forward = function (backend) { return backend.equal($a, $b); }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null, Equal); - } - var equal = op({ equal_: equal_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Gradient helper function for the min and max operations. - */ - function gradForMinAndMax(dy, y, xOrig, origAxes, permutedAxes) { - if (y.rank < xOrig.rank) { - y = reshape(y, expandShapeToKeepDim(y.shape, origAxes)); - } - if (dy.rank < xOrig.rank) { - dy = reshape(dy, expandShapeToKeepDim(dy.shape, origAxes)); - } - return { - x: function () { - var dx = mul(dy, cast(equal(xOrig, y), dy.dtype)); - return permutedAxes == null ? dx : transpose(dx, permutedAxes); - } - }; - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var maxGradConfig = { - kernelName: Max, - inputsToSave: ['x'], - outputsToSave: [true], - gradFunc: function (dy, saved, attrs) { - var maxAttrs = attrs; - var reductionIndices = maxAttrs.reductionIndices; - var x = saved[0], y = saved[1]; - var origAxes = parseAxisParam(reductionIndices, x.shape); - var permutedAxes = getAxesPermutation(origAxes, x.rank); - var maxGrad = gradForMinAndMax(dy, y, x, origAxes, permutedAxes); - return { - x: function () { - var out = maxGrad['x'](); - if (permutedAxes != null) { - out = transpose(out); - } - return out; - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the truth value of (a < b) element-wise. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([1, 2, 3]); - * const b = tf.tensor1d([2, 2, 2]); - * - * a.less(b).print(); - * ``` - * @param a The first input tensor. - * @param b The second input tensor. Must have the same dtype as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function less_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'less'); - var $b = convertToTensor(b, 'b', 'less'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - assertAndGetBroadcastShape($a.shape, $b.shape); - var forward = function (backend) { return backend.less($a, $b); }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Less); - } - var less = op({ less_: less_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var maximumGradConfig = { - kernelName: Maximum, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var derA = function () { return mul(dy, cast(greaterEqual(a, b), 'float32')); }; - var derB = function () { return mul(dy, cast(less(a, b), 'float32')); }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the backprop of a 3d max pool. - * - * @param dy The dy error, of rank 5 of shape - * [batchSize, depth, height, width, channels]. - * assumed. - * @param input The original input image, of rank 5 or rank 4 of shape - * [batchSize, depth, height, width, channels]. - * @param output The original output image, of rank 5 of shape - * [batchSize, outDepth, outHeight, outWidth, channels]. - * @param filterSize The filter size: - * `[filterDepth, filterHeight, filterWidth]`. - * `filterSize` is a single number, - * then `filterDepth == filterHeight == filterWidth`. - * @param strides The strides of the pooling: - * `[strideDepth, strideHeight, strideWidth]`. If - * `strides` is a single number, then `strideHeight == strideWidth`. - * @param dilations Deprecated, this field will be gone in v3.0.0. - * The dilation rates: `[dilationDepth, dilationHeight, dilationWidth]` - * in which we sample input values across the depth, height and width - * dimensions in dilated pooling. - * Defaults to `[1, 1, 1]`. If `dilations` is a single number, - * then `dilationDepth == dilationHeight == dilationWidth`. - * If it is greater than 1, then all values of `strides` must be 1. - * @param pad A string from: 'same', 'valid'. The type of padding algorithm - * used in the forward prop of the op. - * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The - * rounding mode used when computing output dimensions if pad is a - * number. If none is provided, it will not round and error if the output - * is of fractional size. - */ - function maxPool3dBackprop_(dy, input, output, filterSize, strides, dilations, pad, dimRoundingMode) { - if (dilations === void 0) { dilations = [1, 1, 1]; } - var $dy = convertToTensor(dy, 'dy', 'maxPool3dBackprop'); - var $input = convertToTensor(input, 'input', 'maxPool3dBackprop'); - var $output = convertToTensor(output, 'output', 'maxPool3dBackprop'); - var dy5D = $dy; - var input5D = $input; - var output5D = $output; - var reshapedTo5D = false; - if ($input.rank === 4) { - reshapedTo5D = true; - dy5D = reshape($dy, [1, $dy.shape[0], $dy.shape[1], $dy.shape[2], $dy.shape[3]]); - input5D = reshape($input, [ - 1, $input.shape[0], $input.shape[1], $input.shape[2], $input.shape[3] - ]); - output5D = reshape($output, [ - 1, $output.shape[0], $output.shape[1], $output.shape[2], $output.shape[3] - ]); - } - assert(dy5D.rank === 5, function () { return "Error in maxPool3dBackprop: dy must be rank 5 but got rank " + - (dy5D.rank + "."); }); - assert(input5D.rank === 5, function () { return "Error in maxPool3dBackprop: input must be rank 5 but got rank " + - (input5D.rank + "."); }); - assert(output5D.rank === 5, function () { return "Error in maxPool3dBackprop: output must be rank 5 but got rank " + - (output5D.rank + "."); }); - assert(eitherStridesOrDilationsAreOne(strides, dilations), function () { return 'Error in maxPool3dBackprop: Either strides or dilations ' + - ("must be 1. Got strides " + strides + " and dilations '" + dilations + "'"); }); - if (dimRoundingMode != null) { - assert(isInt(pad), function () { return "Error in maxPool3dBackprop: pad must be an integer when " + - ("using, dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); - } - var forward = function (backend) { - var convInfo = computePool3DInfo(input5D.shape, filterSize, strides, dilations, pad, dimRoundingMode); - return backend.maxPool3dBackprop(dy5D, input5D, output5D, convInfo); - }; - var inputs = { dy: dy5D, input: input5D, output: output5D }; - var attrs = { filterSize: filterSize, strides: strides, dilations: dilations, pad: pad, dimRoundingMode: dimRoundingMode }; - var res = ENGINE.runKernelFunc(forward, inputs, null /* grad */, MaxPool3DBackprop, attrs); - if (reshapedTo5D) { - return reshape(res, [res.shape[1], res.shape[2], res.shape[3], res.shape[4]]); - } - return res; - } - var maxPool3dBackprop = op({ maxPool3dBackprop_: maxPool3dBackprop_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var maxPool3DGradConfig = { - kernelName: MaxPool3D, - inputsToSave: ['x'], - outputsToSave: [true], - gradFunc: function (dy, saved, attrs) { - var _a = saved, x = _a[0], y = _a[1]; - var _b = attrs, filterSize = _b.filterSize, strides = _b.strides, dilations = _b.dilations, pad = _b.pad, dimRoundingMode = _b.dimRoundingMode; - var $dilations = dilations == null ? [1, 1, 1] : dilations; - return { - x: function () { return maxPool3dBackprop(dy, x, y, filterSize, strides, $dilations, pad, dimRoundingMode); } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the backprop of a 2D max pool. - * - * @param dy The dy error, of rank 4 or rank 3 of shape - * [batchSize, height, width, channels]. If rank 3, batch of 1 is - * assumed. - * @param input The original input image, of rank 4, of shape - * [batchSize, height, width, channels]. - * @param output The original output image, of rank 4, of shape - * [batchSize, outHeight, outWidth, channels]. - * @param filterSize The filter size: `[filterHeight, filterWidth]`. If - * `filterSize` is a single number, then `filterHeight == filterWidth`. - * @param strides The strides of the pooling: `[strideHeight, strideWidth]`. If - * `strides` is a single number, then `strideHeight == strideWidth`. - * @param pad A string from: 'same', 'valid'. The type of padding algorithm - * used in the forward prop of the op. - * @param dimRoundingMode A string from: 'ceil', 'round', 'floor'. The - * rounding mode used when computing output dimensions if pad is a - * number. If none is provided, it will not round and error if the output - * is of fractional size. - */ - function maxPoolBackprop_(dy, input, output, filterSize, strides, pad, dimRoundingMode) { - var $dy = convertToTensor(dy, 'dy', 'maxPoolBackprop'); - var $input = convertToTensor(input, 'input', 'maxPoolBackprop'); - var $output = convertToTensor(output, 'output', 'maxPoolBackprop'); - assert($input.rank === $dy.rank, function () { return "Rank of input (" + $input.rank + ") does not match rank of dy " + - ("(" + $dy.rank + ")"); }); - assert($dy.rank === 4, function () { return "Error in maxPoolBackprop: dy must be rank 4 but got rank " + - ($dy.rank + "."); }); - assert($input.rank === 4, function () { return "Error in maxPoolBackprop: input must be rank 4 but got rank " + - ($input.rank + "."); }); - if (dimRoundingMode != null) { - assert(isInt(pad), function () { return "Error in maxPoolBackprop: pad must be an integer when using, " + - ("dimRoundingMode " + dimRoundingMode + " but got pad " + pad + "."); }); - } - var forward = function (backend) { - var convInfo = computePool2DInfo($input.shape, filterSize, strides, 1 /* dilations */, pad, dimRoundingMode); - return backend.maxPoolBackprop($dy, $input, $output, convInfo); - }; - var inputs = { dy: $dy, input: $input, output: $output }; - var attrs = { filterSize: filterSize, strides: strides, pad: pad, dimRoundingMode: dimRoundingMode }; - return ENGINE.runKernelFunc(forward, inputs, null, MaxPoolBackprop, attrs); - } - var maxPoolBackprop = op({ maxPoolBackprop_: maxPoolBackprop_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var maxPoolGradConfig = { - kernelName: MaxPool, - inputsToSave: ['x'], - outputsToSave: [true], - gradFunc: function (dy, saved, attrs) { - var _a = saved, x = _a[0], y = _a[1]; - var _b = attrs, filterSize = _b.filterSize, strides = _b.strides, pad = _b.pad; - return { - x: function () { return maxPoolBackprop(dy, x, y, filterSize, strides, pad); } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var minGradConfig = { - kernelName: Min, - inputsToSave: ['x'], - outputsToSave: [true], - gradFunc: function (dy, saved, attrs) { - var minAttrs = attrs; - var axis = minAttrs.axis; - var x = saved[0], y = saved[1]; - var origAxes = parseAxisParam(axis, x.shape); - var permutedAxes = getAxesPermutation(origAxes, x.rank); - var minGrad = gradForMinAndMax(dy, y, x, origAxes, permutedAxes); - return { - x: function () { - var out = minGrad['x'](); - if (permutedAxes != null) { - out = transpose(out); - } - return out; - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the truth value of (a > b) element-wise. Supports broadcasting. - * - * ```js - * const a = tf.tensor1d([1, 2, 3]); - * const b = tf.tensor1d([2, 2, 2]); - * - * a.greater(b).print(); - * ``` - * - * @param a The first input tensor. - * @param b The second input tensor. Must have the same dtype as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function greater_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'greater'); - var $b = convertToTensor(b, 'b', 'greater'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - assertAndGetBroadcastShape($a.shape, $b.shape); - var forward = function (backend) { return backend.greater($a, $b); }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Greater); - } - var greater = op({ greater_: greater_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var minimumGradConfig = { - kernelName: Minimum, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var derA = function () { return mul(dy, cast(lessEqual(a, b), 'float32')); }; - var derB = function () { return mul(dy, cast(greater(a, b), 'float32')); }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes floor of input `tf.Tensor` element-wise: `floor(x)`. - * - * ```js - * const x = tf.tensor1d([.6, 1.1, -3.3]); - * - * x.floor().print(); // or tf.floor(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function floor_(x) { - var $x = convertToTensor(x, 'x', 'floor'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend) { return backend.floor($x); }, inputs, null /* grad */, Floor); - } - var floor = op({ floor_: floor_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var modGradConfig = { - kernelName: Mod, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var outShape = assertAndGetBroadcastShape(a.shape, b.shape); - var derA = function () { - var reduceAxes = getReductionAxes(a.shape, outShape); - if (reduceAxes.length > 0) { - return reshape(sum$1(dy, reduceAxes), a.shape); - } - return dy; - }; - var derB = function () { - var res = mul(dy, neg(floor(div(a, b)))); - var reduceAxes = getReductionAxes(b.shape, outShape); - if (reduceAxes.length > 0) { - return reshape(sum$1(res, reduceAxes), b.shape); - } - return res; - }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var multiplyGradConfig = { - kernelName: Multiply, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var outShape = assertAndGetBroadcastShape(a.shape, b.shape); - var derA = function () { - var res = mul(dy, cast(b, 'float32')); - var reduceAxes = getReductionAxes(a.shape, outShape); - if (reduceAxes.length > 0) { - return reshape(sum$1(res, reduceAxes), a.shape); - } - return res; - }; - var derB = function () { - var res = mul(dy, cast(a, 'float32')); - var reduceAxes = getReductionAxes(b.shape, outShape); - if (reduceAxes.length > 0) { - return reshape(sum$1(res, reduceAxes), b.shape); - } - return res; - }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var negateGradConfig = { - kernelName: Negate, - gradFunc: function (dy) { - return { x: function () { return neg(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Converts two real numbers to a complex number. - * - * Given a tensor `real` representing the real part of a complex number, and a - * tensor `imag` representing the imaginary part of a complex number, this - * operation returns complex numbers elementwise of the form [r0, i0, r1, i1], - * where r represents the real part and i represents the imag part. - * - * The input tensors real and imag must have the same shape. - * - * ```js - * const real = tf.tensor1d([2.25, 3.25]); - * const imag = tf.tensor1d([4.75, 5.75]); - * const complex = tf.complex(real, imag); - * - * complex.print(); - * ``` - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function complex_(real, imag) { - var $real = convertToTensor(real, 'real', 'complex'); - var $imag = convertToTensor(imag, 'imag', 'complex'); - assertShapesMatch($real.shape, $imag.shape, "real and imag shapes, " + $real.shape + " and " + $imag.shape + ", " + - "must match in call to tf.complex()."); - var forward = function (backend) { - return backend.complex($real, $imag); - }; - var inputs = { real: $real, imag: $imag }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Complex); - } - var complex = op({ complex_: complex_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates a `tf.Tensor` with all elements set to 0. - * - * ```js - * tf.zeros([2, 2]).print(); - * ``` - * - * @param shape An array of integers defining the output tensor shape. - * @param dtype The type of an element in the resulting tensor. Can - * be 'float32', 'int32' or 'bool'. Defaults to 'float'. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function zeros(shape, dtype) { - if (dtype === void 0) { dtype = 'float32'; } - if (dtype === 'complex64') { - var real = zeros(shape, 'float32'); - var imag = zeros(shape, 'float32'); - return complex(real, imag); - } - var values = makeZerosTypedArray(sizeFromShape(shape), dtype); - return ENGINE.makeTensor(values, shape, dtype); - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var oneHotGradConfig = { - kernelName: OneHot, - inputsToSave: ['indices'], - gradFunc: function (dy, saved) { - var indices = saved[0]; - return { indices: function () { return zeros(indices.shape, 'float32'); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var onesLikeGradConfig = { - kernelName: OnesLike, - gradFunc: function (dy) { - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var padV2GradConfig = { - kernelName: PadV2, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - // Pad introduces values around the original tensor, so the gradient - // slices the original shape out of the gradient. - var x = saved[0]; - var paddings = attrs.paddings; - var begin = paddings.map(function (p) { return p[0]; }); - return { x: function () { return dy.slice(begin, x.shape); } }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes natural logarithm of the input `tf.Tensor` element-wise: `ln(x)` - * - * ```js - * const x = tf.tensor1d([1, 2, Math.E]); - * - * x.log().print(); // or tf.log(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function log_(x) { - var $x = convertToTensor(x, 'x', 'log'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.log($x); - save([$x]); - return res; - }, inputs, null /* grad */, Log); - } - var log = op({ log_: log_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the power of one `tf.Tensor` to another. Supports broadcasting. - * - * Given a `tf.Tensor` x and a `tf.Tensor` y, this operation computes x^y for - * corresponding elements in x and y. The result's dtype will be the upcasted - * type of the `base` and `exp` dtypes. - * - * ```js - * const a = tf.tensor([[2, 3], [4, 5]]) - * const b = tf.tensor([[1, 2], [3, 0]]).toInt(); - * - * a.pow(b).print(); // or tf.pow(a, b) - * ``` - * - * ```js - * const a = tf.tensor([[1, 2], [3, 4]]) - * const b = tf.tensor(2).toInt(); - * - * a.pow(b).print(); // or tf.pow(a, b) - * ``` - * We also expose `powStrict` which has the same signature as this op and - * asserts that `base` and `exp` are the same shape (does not broadcast). - * - * @param base The base `tf.Tensor` to pow element-wise. - * @param exp The exponent `tf.Tensor` to pow element-wise. - */ - /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ - function pow_(base, exp) { - var _a; - var $base = convertToTensor(base, 'base', 'pow'); - var $exp = convertToTensor(exp, 'exp', 'pow'); - _a = makeTypesMatch($base, $exp), $base = _a[0], $exp = _a[1]; - var inputs = { a: $base, b: $exp }; - var forward = function (backend, save) { - var y = backend.pow($base, $exp); - save([$base, $exp, y]); - return y; - }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Pow); - } - var pow = op({ pow_: pow_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var powGradConfig = { - kernelName: Pow, - inputsToSave: ['a', 'b'], - outputsToSave: [true], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1], y = saved[2]; - var base = a; - var exp = b; - var outShape = assertAndGetBroadcastShape(base.shape, exp.shape); - var derBase = function () { - var expFloat = cast(exp, 'float32'); - var res = mul(dy, mul(expFloat, pow(base, sub(expFloat, scalar(1))))); - var reduceAxes = getReductionAxes(base.shape, outShape); - if (reduceAxes.length > 0) { - res = sum$1(res, reduceAxes); - } - return reshape(res, base.shape); - }; - var derExp = function () { - var condition = greater(base, 0); - var logBase = where(condition, log(base), zerosLike(base)); - var res = mul(dy, mul(y, logBase)); - var reduceAxes = getReductionAxes(exp.shape, outShape); - if (reduceAxes.length > 0) { - res = sum$1(res, reduceAxes); - } - return reshape(res, exp.shape); - }; - return { a: derBase, b: derExp }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var preluGradConfig = { - kernelName: Prelu, - inputsToSave: ['x', 'alpha'], - gradFunc: function (dy, saved) { - var x = saved[0], alpha = saved[1]; - var mask = greater(x, 0); - return { - x: function () { return where(mask, dy, mul(dy, alpha)); }, - alpha: function () { - var res = where(mask, zerosLike(dy), mul(dy, x)); - var reduceAxes = getReductionAxes(alpha.shape, dy.shape); - if (reduceAxes.length > 0) { - res = sum$1(res, reduceAxes); - } - return reshape(res, alpha.shape); - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var reciprocalGradConfig = { - kernelName: Reciprocal, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, neg(square(x))); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var relu6GradConfig = { - kernelName: Relu6, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - var mask = mul(lessEqual(x, 6), step(x)); - return { x: function () { return mul(dy, cast(mask, 'float32')); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var reluGradConfig = { - kernelName: Relu, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(dy, cast(step(x), 'float32')); } }; - } - }; - - /** - * @license - * Copyright 2020 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var reshapeGradConfig = { - kernelName: Reshape, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return reshape(dy, x.shape); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var resizeBilinearGradConfig = { - kernelName: ResizeBilinear, - inputsToSave: ['images'], - gradFunc: function (dy, saved, attrs) { - var images = saved[0]; - var backPropKernelFunc = function (backend) { - var alignCorners = attrs.alignCorners; - return backend.resizeBilinearBackprop(dy, images, alignCorners); - }; - var inputs = { images: images }; - var imagesDer = function () { return ENGINE.runKernelFunc(backPropKernelFunc, inputs, null /* gradient */, ResizeBilinearGrad, attrs); }; - return { images: imagesDer }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var resizeNearestNeighborGradConfig = { - kernelName: ResizeNearestNeighbor, - inputsToSave: ['images'], - gradFunc: function (dy, saved, attrs) { - var images = saved[0]; - var backPropKernelFunc = function (backend) { - var alignCorners = attrs.alignCorners; - return backend.resizeNearestNeighborBackprop(dy, images, alignCorners); - }; - var inputs = { images: images }; - var imagesDer = function () { return ENGINE.runKernelFunc(backPropKernelFunc, inputs, null /* gradient */, ResizeNearestNeighborGrad, attrs); }; - return { images: imagesDer }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates a new tensor with the same values and shape as the specified - * tensor. - * - * ```js - * const x = tf.tensor([1, 2]); - * - * x.clone().print(); - * ``` - * - * @param x The tensor to clone. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function clone_(x) { - var $x = convertToTensor(x, 'x', 'clone', null); - var forward = function () { - return ENGINE.makeTensorFromDataId($x.dataId, $x.shape, $x.dtype); - }; - var inputs = { x: $x }; - // Note this op is called tf.identity in python. Hence the kernel name used - // here. - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Identity); - } - var clone = op({ clone_: clone_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Reverses a `tf.Tensor` along a specified axis. - * - * Also available are stricter rank-specific methods that assert that `x` is - * of the given rank: - * - `tf.reverse1d` - * - `tf.reverse2d` - * - `tf.reverse3d` - * - `tf.reverse4d` - * - * Except `tf.reverse1d` (which does not have axis param), all methods have - * same signature as this method. - * - * ```js - * const x = tf.tensor1d([1, 2, 3, 4]); - * - * x.reverse().print(); - * ``` - * - * ```js - * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); - * - * const axis = 1; - * x.reverse(axis).print(); - * ``` - * @param x The input tensor to be reversed. - * @param axis The set of dimensions to reverse. Must be in the - * range [-rank(x), rank(x)). Defaults to all axes. - */ - /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ - function reverse_(x, axis) { - var $x = convertToTensor(x, 'x', 'reverse'); - var forward = function (backend) { - var axes = parseAxisParam(axis, $x.shape); - if ($x.rank === 0) { - return clone($x); - } - var res = backend.reverse($x, axes); - return reshape(res, $x.shape); - }; - var inputs = { x: $x }; - var attrs = { dims: axis }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Reverse, attrs); - } - var reverse = op({ reverse_: reverse_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var reverseGradConfig = { - kernelName: Reverse, - gradFunc: function (dy, saved, attrs) { - var dims = attrs.dims; - var axes = parseAxisParam(dims, dy.shape); - return { x: function () { return reverse(dy, axes); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var roundGradConfig = { - kernelName: Round, - gradFunc: function (dy) { - // TODO(nsthorat): Let gradients be null for cases where we want to stop - // backpropgation. - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var rsqrtGradConfig = { - kernelName: Rsqrt, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return neg(div(dy, mul(pow(x, 1.5), 2))); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the truth value of `NOT x` element-wise. - * - * ```js - * const a = tf.tensor1d([false, true], 'bool'); - * - * a.logicalNot().print(); - * ``` - * - * @param x The input tensor. Must be of dtype 'bool'. - */ - /** @doc {heading: 'Operations', subheading: 'Logical'} */ - function logicalNot_(x) { - var $x = convertToTensor(x, 'x', 'logicalNot', 'bool'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend) { return backend.logicalNot($x); }, inputs, null /* grad */, LogicalNot); - } - var logicalNot = op({ logicalNot_: logicalNot_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var selectV2PoolGradConfig = { - kernelName: SelectV2, - inputsToSave: ['condition'], - gradFunc: function (dy, saved) { - var condition = saved[0]; - return { - // TODO(julianoks): Return null for condition gradient - // when backprop supports it. - condition: function () { return cast(zerosLike(condition), 'float32'); }, - t: function () { return mul(dy, cast(condition, dy.dtype)); }, - e: function () { return mul(dy, cast(logicalNot(condition), dy.dtype)); } - }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var SELU_SCALEALPHA = 1.7580993408473768599402175208123; - var SELU_SCALE = 1.0507009873554804934193349852946; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var seluGradConfig = { - kernelName: Selu, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { - x: function () { - var mask = greater(x, scalar(0)); - var scaleAlpha = scalar(SELU_SCALEALPHA); - var scale = scalar(SELU_SCALE); - var greaterThanZeroDer = mul(dy, scale); - var lessEqualZeroDer = mul(mul(dy, scaleAlpha), exp(cast(x, 'float32'))); - return where(mask, greaterThanZeroDer, lessEqualZeroDer); - } - }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var sigmoidGradConfig = { - kernelName: Sigmoid, - outputsToSave: [true], - gradFunc: function (dy, saved) { - var y = saved[0]; - return { x: function () { return mul(dy, mul(y, sub(scalar(1), y))); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var signGradConfig = { - kernelName: Sign, - gradFunc: function (dy) { - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes cos of the input `tf.Tensor` element-wise: `cos(x)` - * - * ```js - * const x = tf.tensor1d([0, Math.PI / 2, Math.PI * 3 / 4]); - * - * x.cos().print(); // or tf.cos(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function cos_(x) { - var $x = convertToTensor(x, 'x', 'cos'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.cos($x); - save([$x]); - return res; - }, inputs, null /* grad */, Cos); - } - var cos = op({ cos_: cos_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var sinGradConfig = { - kernelName: Sin, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(cos(cast(x, 'float32')), dy); } }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes hyperbolic cos of the input `tf.Tensor` element-wise: `cosh(x)` - * - * ```js - * const x = tf.tensor1d([0, 1, -1, .7]); - * - * x.cosh().print(); // or tf.cosh(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function cosh_(x) { - var $x = convertToTensor(x, 'x', 'cosh'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.cosh($x); - save([$x]); - return res; - }, inputs, null /* grad */, Cosh); - } - var cosh = op({ cosh_: cosh_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var sinhGradConfig = { - kernelName: Sinh, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(cosh(cast(x, 'float32')), dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Pads a `tf.Tensor` with a given value and paddings. - * - * This operation currently only implements the `CONSTANT` mode. - * - * Also available are stricter rank-specific methods with the same signature - * as this method that assert that `paddings` is of given length. - * - `tf.pad1d` - * - `tf.pad2d` - * - `tf.pad3d` - * - `tf.pad4d` - * - * ```js - * const x = tf.tensor1d([1, 2, 3, 4]); - * x.pad([[1, 2]]).print(); - * ``` - * @param x The tensor to pad. - * @param paddings An array of length `R` (the rank of the tensor), where - * each element is a length-2 tuple of ints `[padBefore, padAfter]`, - * specifying how much to pad along each dimension of the tensor. - * @param constantValue The pad value to use. Defaults to 0. - */ - /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ - function pad_(x, paddings, constantValue) { - if (constantValue === void 0) { constantValue = 0; } - var $x = convertToTensor(x, 'x', 'pad'); - if ($x.rank === 0) { - throw new Error('pad(scalar) is not defined. Pass non-scalar to pad'); - } - var forward = function (backend, save) { - save([$x]); - return backend.pad($x, paddings, constantValue); - }; - var attrs = { paddings: paddings, constantValue: constantValue }; - var inputs = { x: $x }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, PadV2, attrs); - } - var pad = op({ pad_: pad_ }); - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function assertParamsValid(input, begin, size) { - assert(input.rank === begin.length, function () { return "Error in slice" + input.rank + "D: Length of begin " + begin + " must " + - ("match the rank of the array (" + input.rank + ")."); }); - assert(input.rank === size.length, function () { return "Error in slice" + input.rank + "D: Length of size " + size + " must " + - ("match the rank of the array (" + input.rank + ")."); }); - var _loop_1 = function (i) { - assert(begin[i] + size[i] <= input.shape[i], function () { return "Error in slice" + input.rank + "D: begin[" + i + "] + size[" + i + "] " + - ("(" + (begin[i] + size[i]) + ") would overflow input.shape[" + i + "] (" + input.shape[i] + ")"); }); - }; - for (var i = 0; i < input.rank; ++i) { - _loop_1(i); - } - } - /** Converts a binary mask to an array of axes. Used in stridedSlice(). */ - function maskToAxes(mask) { - var axes = []; - var axis = 0; - while (mask > 0) { - if (mask & 1) { - axes.push(axis); - } - mask /= 2; - axis++; - } - return axes; - } - /** Computes the output shape given the strided slice params. */ - function computeOutShape(begin, end, strides) { - var size = []; - for (var axis = 0; axis < begin.length; axis++) { - size[axis] = Math.ceil((end[axis] - begin[axis]) / strides[axis]); - } - return size; - } - // Creates full selection at the elided dimensions. If the dimension matches - // the ellipsis mask, override the current stride value. Otherwise, insert. - function stridesWithElidedDims(strides, ellipsisInsertionIndex, numElidedAxes, inputShape) { - var newStrides = strides.slice(); - for (var i = newStrides.length; i < inputShape.length; i++) { - newStrides.push(1); - } - for (var i = 0; i < numElidedAxes; i++) { - if (i === 0) { - newStrides[ellipsisInsertionIndex] = 1; - } - else { - newStrides.splice(ellipsisInsertionIndex, 0 /* num elements to delete */, 1 /* element to add */); - newStrides.pop(); - } - } - return newStrides; - } - function unnormalizeAxis(ellipsisInsertionIndex, numElidedAxes, normalizedAxis) { - if (normalizedAxis <= ellipsisInsertionIndex) { - return normalizedAxis; - } - return normalizedAxis - (numElidedAxes - 1); - } - function getElidedAxes(numElidedAxes, ellipsisInsertionIndex) { - var elidedAxes = []; - for (var i = 0; i < numElidedAxes; i++) { - elidedAxes.push(ellipsisInsertionIndex + i); - } - return elidedAxes; - } - // Creates full selection at the elided dimensions. If the dimension matches - // the ellipsis mask, override the current start value. Otherwise, insert. - function startIndicesWithElidedDims(beginMask, ellipsisInsertionIndex, numElidedAxes, originalBegin, inputShape) { - var newIndices = inputShape.slice(); - var elidedAxes = getElidedAxes(numElidedAxes, ellipsisInsertionIndex); - for (var axis = 0; axis < newIndices.length; axis++) { - if (elidedAxes.indexOf(axis) > -1) { - newIndices[axis] = 0; - } - else { - var originalAxis = unnormalizeAxis(ellipsisInsertionIndex, numElidedAxes, axis); - var originalValue = originalBegin[originalAxis]; - if (beginMask & 1 << originalAxis) { - originalValue = 0; - } - newIndices[axis] = originalValue; - } - } - return newIndices; - } - // Creates full selection at the elided dimensions. If the dimension matches - // the ellipsis mask, override the current stop value. Otherwise, insert. - function stopIndicesWithElidedDims(endMask, ellipsisInsertionIndex, numElidedAxes, originalEnd, inputShape) { - var newIndices = inputShape.slice(); - var elidedAxes = getElidedAxes(numElidedAxes, ellipsisInsertionIndex); - for (var axis = 0; axis < newIndices.length; axis++) { - if (elidedAxes.indexOf(axis) > -1) { - newIndices[axis] = Number.MAX_SAFE_INTEGER; - } - else { - var originalAxis = unnormalizeAxis(ellipsisInsertionIndex, numElidedAxes, axis); - var originalValue = originalEnd[originalAxis]; - if (endMask & 1 << originalAxis) { - originalValue = Number.MAX_SAFE_INTEGER; - } - newIndices[axis] = originalValue; - } - } - for (var i = 0; i < newIndices.length; i++) { - // Handle negative indices - var axisSize = inputShape[i]; - if (newIndices[i] < 0) { - newIndices[i] += axisSize; - } - newIndices[i] = clamp(0, newIndices[i], inputShape[i]); - } - return newIndices; - } - function stridesForAxis(strides, axis, ellipsisMask) { - var stride = strides[axis]; - if (ellipsisMask & (1 << axis) || stride == null) { - stride = 1; - } - return stride; - } - function startForAxis(beginMask, startIndices, strides, inputShape, axis, ellipsisMask) { - // Begin with the specified index - var start = startIndices[axis]; - var stride = strides[axis] || 1; - // Check the axis bit from right of masked axes, or the begin index is not set - // for the axis. - if (beginMask & 1 << axis || ellipsisMask & 1 << axis || start == null) { - if (stride > 0) { - // Forward iteration - use the first element. These values will get - // clamped below (Note: We could have set them to 0 and axis_size-1, but - // use lowest() and max() to maintain symmetry with StopForAxis()) - start = Number.MIN_SAFE_INTEGER; - } - else { - // Backward iteration - use the last element. - start = Number.MAX_SAFE_INTEGER; - } - } - // Handle negative indices - var axisSize = inputShape[axis]; - if (start < 0) { - start += axisSize; - } - // Clamping - start = clamp(0, start, axisSize - 1); - return start; - } - function stopForAxis(endMask, stopIndices, strides, inputShape, axis, ellipsisMask) { - // Begin with the specified index - var stop = stopIndices[axis]; - var stride = strides[axis] || 1; - // Check the axis bit from right of masked axes, or if the stop index is not - // set for this axis. - if (endMask & (1 << axis) || ellipsisMask & (1 << axis) || stop == null) { - if (stride > 0) { - // Forward iteration - use the last element. These values will get - // clamped below - stop = Number.MAX_SAFE_INTEGER; - } - else { - // Backward iteration - use the first element. - stop = Number.MIN_SAFE_INTEGER; - } - } - // Handle negative indices - var axisSize = inputShape[axis]; - if (stop < 0) { - stop += axisSize; - } - // Clamping - // Because the end index points one past the last element, we need slightly - // different clamping ranges depending on the direction. - if (stride > 0) { - // Forward iteration - stop = clamp(0, stop, axisSize); - } - else { - // Backward iteration - stop = clamp(-1, stop, axisSize - 1); - } - return stop; - } - /** - * Returns true if the slice occupies a continous set of elements in the - * 'flat' space. - */ - function isSliceContinous(shape, begin, size) { - // Index of the first axis that has size > 1. - var firstNonOneAxis = size.length; - for (var i = 0; i < size.length; i++) { - if (size[i] > 1) { - firstNonOneAxis = i; - break; - } - } - for (var i = firstNonOneAxis + 1; i < size.length; i++) { - if (begin[i] > 0 || size[i] !== shape[i]) { - return false; - } - } - return true; - } - function computeFlatOffset(begin, strides) { - var flatOffset = begin.length > 0 ? begin[begin.length - 1] : 1; - for (var i = 0; i < begin.length - 1; i++) { - flatOffset += begin[i] * strides[i]; - } - return flatOffset; - } - function parseSliceParams(x, begin, size) { - // The following logic allows for more ergonomic calls. - var begin_; - if (typeof begin === 'number') { - begin_ = [begin].concat(new Array(x.rank - 1).fill(0)); - } - else if (begin.length < x.rank) { - begin_ = begin.concat(new Array(x.rank - begin.length).fill(0)); - } - else { - begin_ = begin.slice(); - } - begin_.forEach(function (d) { - assert(d !== -1, function () { return 'slice() does not support negative begin indexing.'; }); - }); - var size_; - if (size == null) { - size_ = new Array(x.rank).fill(-1); - } - else if (typeof size === 'number') { - size_ = [size].concat(new Array(x.rank - 1).fill(-1)); - } - else if (size.length < x.rank) { - size_ = size.concat(new Array(x.rank - size.length).fill(-1)); - } - else { - size_ = size; - } - size_ = size_.map(function (d, i) { - if (d >= 0) { - return d; - } - else { - assert(d === -1, function () { return "Negative size values should be exactly -1 but got " + - (d + " for the slice() size at index " + i + "."); }); - return x.shape[i] - begin_[i]; - } - }); - return [begin_, size_]; - } - - var slice_util = { - __proto__: null, - assertParamsValid: assertParamsValid, - maskToAxes: maskToAxes, - computeOutShape: computeOutShape, - stridesWithElidedDims: stridesWithElidedDims, - startIndicesWithElidedDims: startIndicesWithElidedDims, - stopIndicesWithElidedDims: stopIndicesWithElidedDims, - stridesForAxis: stridesForAxis, - startForAxis: startForAxis, - stopForAxis: stopForAxis, - isSliceContinous: isSliceContinous, - computeFlatOffset: computeFlatOffset, - parseSliceParams: parseSliceParams - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var sliceGradConfig = { - kernelName: Slice, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0]; - var _a = attrs, begin = _a.begin, size = _a.size; - var inputShape = x.shape; - var _b = parseSliceParams(x, begin, size), begin_ = _b[0], size_ = _b[1]; - // Create an Nx2 padding where the first column represents how many - // zeros are prepended (at start) for each dimension, and the second - // column indicates how many zeros are appended (at end). - // The number of zeros to append is the shape of the input - // elementwise-subtracted by both the begin vector and sizes vector. - var paddings = []; - for (var i = 0; i < dy.rank; i++) { - paddings.push([begin_[i], inputShape[i] - begin_[i] - size_[i]]); - } - return { x: function () { return pad(dy, paddings); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var softmaxGradConfig = { - kernelName: Softmax, - outputsToSave: [true], - gradFunc: function (dy, saved, attrs) { - var y = saved[0]; - var dim = attrs.dim; - var keepDims = true; - var dyTimesY = mul(dy, y); - return { - logits: function () { return sub(dyTimesY, mul(sum$1(dyTimesY, [dim], keepDims), y)); } - }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes sigmoid element-wise, `1 / (1 + exp(-x))` - * - * ```js - * const x = tf.tensor1d([0, -1, 2, -3]); - * - * x.sigmoid().print(); // or tf.sigmoid(x) - * ``` - * @param x The input tensor. - */ - /** @doc {heading: 'Operations', subheading: 'Basic math'} */ - function sigmoid_(x) { - var $x = convertToTensor(x, 'x', 'sigmoid'); - var inputs = { x: $x }; - return ENGINE.runKernelFunc(function (backend, save) { - var res = backend.sigmoid($x); - save([res]); - return res; - }, inputs, null /* grad */, Sigmoid); - } - var sigmoid = op({ sigmoid_: sigmoid_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var softplusGradConfig = { - kernelName: Softplus, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(dy, sigmoid(x)); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * This operation reshapes the "batch" dimension 0 into `M + 1` dimensions of - * shape `blockShape + [batch]`, interleaves these blocks back into the grid - * defined by the spatial dimensions `[1, ..., M]`, to obtain a result with - * the same rank as the input. The spatial dimensions of this intermediate - * result are then optionally cropped according to `crops` to produce the - * output. This is the reverse of `tf.spaceToBatchND`. See below for a precise - * description. - * - * ```js - * const x = tf.tensor4d([1, 2, 3, 4], [4, 1, 1, 1]); - * const blockShape = [2, 2]; - * const crops = [[0, 0], [0, 0]]; - * - * x.batchToSpaceND(blockShape, crops).print(); - * ``` - * - * @param x A `tf.Tensor`. N-D with `x.shape` = `[batch] + spatialShape + - * remainingShape`, where spatialShape has `M` dimensions. - * @param blockShape A 1-D array. Must have shape `[M]`, all values must - * be >= 1. - * @param crops A 2-D array. Must have shape `[M, 2]`, all values must be >= 0. - * `crops[i] = [cropStart, cropEnd]` specifies the amount to crop from input - * dimension `i + 1`, which corresponds to spatial dimension `i`. It is required - * that `cropStart[i] + cropEnd[i] <= blockShape[i] * inputShape[i + 1]` - * - * This operation is equivalent to the following steps: - * - * 1. Reshape `x` to `reshaped` of shape: `[blockShape[0], ..., - * blockShape[M-1], batch / prod(blockShape), x.shape[1], ..., - * x.shape[N-1]]` - * - * 2. Permute dimensions of `reshaped`to produce `permuted` of shape `[batch / - * prod(blockShape),x.shape[1], blockShape[0], ..., x.shape[M], - * blockShape[M-1],x.shape[M+1], ..., x.shape[N-1]]` - * - * 3. Reshape `permuted` to produce `reshapedPermuted` of shape `[batch / - * prod(blockShape),x.shape[1] * blockShape[0], ..., x.shape[M] * - * blockShape[M-1],x.shape[M+1], ..., x.shape[N-1]]` - * - * 4. Crop the start and end of dimensions `[1, ..., M]` of `reshapedPermuted` - * according to `crops` to produce the output of shape: `[batch / - * prod(blockShape),x.shape[1] * blockShape[0] - crops[0,0] - crops[0,1], - * ..., x.shape[M] * blockShape[M-1] - crops[M-1,0] - - * crops[M-1,1],x.shape[M+1], ..., x.shape[N-1]]` - */ - /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ - function batchToSpaceND_(x, blockShape, crops) { - var $x = convertToTensor(x, 'x', 'batchToSpaceND'); - var prod = blockShape.reduce(function (a, b) { return a * b; }); - assert($x.rank >= 1 + blockShape.length, function () { return "input rank is " + $x.rank + " but should be > than blockShape.length " + blockShape.length; }); - assert(crops.length === blockShape.length, function () { return "crops.length is " + crops.length + " but should be equal to blockShape.length " + blockShape.length; }); - assert($x.shape[0] % prod === 0, function () { return "input tensor batch is " + $x.shape[0] + " but is not divisible by the product of " + - ("the elements of blockShape " + blockShape.join(' * ') + " === " + prod); }); - var forward = function (backend) { - return backend.batchToSpaceND($x, blockShape, crops); - }; - var inputs = { x: $x }; - var attrs = { blockShape: blockShape, crops: crops }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, BatchToSpaceND, attrs); - } - var batchToSpaceND = op({ batchToSpaceND_: batchToSpaceND_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var spaceToBatchNDGradConfig = { - kernelName: SpaceToBatchND, - gradFunc: function (dy, saved, attrs) { - var _a = attrs, blockShape = _a.blockShape, paddings = _a.paddings; - return { x: function () { return batchToSpaceND(dy, blockShape, paddings); } }; - } - }; - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function assertParamsConsistent(shapes, axis) { - var rank = shapes[0].length; - shapes.forEach(function (shape, i) { - assert(shape.length === rank, function () { - return "Error in concat" + rank + "D: rank of tensors[" + i + "] must be the same " + - ("as the rank of the rest (" + rank + ")"); - }); - }); - assert(axis >= 0 && axis < rank, function () { return "Error in concat" + rank + "D: axis must be between 0 and " + (rank - 1) + "."; }); - var firstShape = shapes[0]; - shapes.forEach(function (shape, i) { - for (var r = 0; r < rank; r++) { - assert((r === axis) || (shape[r] === firstShape[r]), function () { return "Error in concat" + rank + "D: Shape of tensors[" + i + "] (" + shape + ") " + - ("does not match the shape of the rest (" + firstShape + ") ") + - ("along the non-concatenated axis " + i + "."); }); - } - }); - } - function computeOutShape$1(shapes, axis) { - var outputShape = shapes[0].slice(); - for (var i = 1; i < shapes.length; i++) { - outputShape[axis] += shapes[i][axis]; - } - return outputShape; - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates a `tf.Tensor` with the provided values, shape and dtype. - * - * ```js - * // Pass an array of values to create a vector. - * tf.tensor([1, 2, 3, 4]).print(); - * ``` - * - * ```js - * // Pass a nested array of values to make a matrix or a higher - * // dimensional tensor. - * tf.tensor([[1, 2], [3, 4]]).print(); - * ``` - * - * ```js - * // Pass a flat array and specify a shape yourself. - * tf.tensor([1, 2, 3, 4], [2, 2]).print(); - * ``` - * - * @param values The values of the tensor. Can be nested array of numbers, - * or a flat array, or a `TypedArray`. If the values are strings, - * they will be encoded as utf-8 and kept as `Uint8Array[]`. - * @param shape The shape of the tensor. Optional. If not provided, - * it is inferred from `values`. - * @param dtype The data type. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function tensor(values, shape, dtype) { - var inferredShape = inferShape(values, dtype); - return makeTensor(values, shape, inferredShape, dtype); - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Concatenates a list of `tf.Tensor`s along a given axis. - * - * The tensors ranks and types must match, and their sizes must match in all - * dimensions except `axis`. - * - * Also available are stricter rank-specific methods that assert that - * `tensors` are of the given rank: - * - `tf.concat1d` - * - `tf.concat2d` - * - `tf.concat3d` - * - `tf.concat4d` - * - * Except `tf.concat1d` (which does not have axis param), all methods have - * same signature as this method. - * - * ```js - * const a = tf.tensor1d([1, 2]); - * const b = tf.tensor1d([3, 4]); - * a.concat(b).print(); // or a.concat(b) - * ``` - * - * ```js - * const a = tf.tensor1d([1, 2]); - * const b = tf.tensor1d([3, 4]); - * const c = tf.tensor1d([5, 6]); - * tf.concat([a, b, c]).print(); - * ``` - * - * ```js - * const a = tf.tensor2d([[1, 2], [10, 20]]); - * const b = tf.tensor2d([[3, 4], [30, 40]]); - * const axis = 1; - * tf.concat([a, b], axis).print(); - * ``` - * @param tensors A list of tensors to concatenate. - * @param axis The axis to concate along. Defaults to 0 (the first dim). - */ - /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ - function concat_(tensors, axis) { - if (axis === void 0) { axis = 0; } - assert(tensors.length >= 1, function () { return 'Pass at least one tensor to concat'; }); - var $tensors = convertToTensorArray(tensors, 'tensors', 'concat'); - if ($tensors[0].dtype === 'complex64') { - $tensors.forEach(function (tensor) { - if (tensor.dtype !== 'complex64') { - throw new Error("Cannot concatenate complex64 tensors with a tensor\n with dtype " + tensor.dtype + ". "); - } - }); - } - var $axis = parseAxisParam(axis, $tensors[0].shape)[0]; - var outShape = computeOutShape$1($tensors.map(function (t) { return t.shape; }), $axis); - if (sizeFromShape(outShape) === 0) { - return tensor([], outShape); - } - // Keep only non-empty tensors (ignore tensors with 0 in their shape). - $tensors = $tensors.filter(function (t) { return t.size > 0; }); - if ($tensors.length === 1) { - return $tensors[0]; - } - var shapes = $tensors.map(function (t) { return t.shape; }); - assertParamsConsistent(shapes, $axis); - var forward = function (backend, save) { - var res = backend.concat($tensors, $axis); - save($tensors); - return res; - }; - var inputs = $tensors; - var attr = { axis: axis }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Concat, attr); - } - var concat = op({ concat_: concat_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var splitVGradConfig = { - kernelName: SplitV, - gradFunc: function (dy, saved, attrs) { - var axis = attrs.axis; - return { x: function () { return concat(dy, axis); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var sqrtGradConfig = { - kernelName: Sqrt, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, mul(sqrt(cast(x, 'float32')), 2)); } }; - } - }; - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var squareGradConfig = { - kernelName: Square, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return mul(dy, mul(x.toFloat(), 2)); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var squaredDifferenceGradConfig = { - kernelName: SquaredDifference, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var two = scalar(2); - var derA = function () { return mul(dy, mul(two, sub(a, b))); }; - var derB = function () { return mul(dy, mul(two, sub(b, a))); }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var stepGradConfig = { - kernelName: Step, - gradFunc: function (dy) { - // TODO(manrajgrover): Return null for gradients when backprop supports - // it. - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var subGradConfig = { - kernelName: Sub, - inputsToSave: ['a', 'b'], - gradFunc: function (dy, saved) { - var a = saved[0], b = saved[1]; - var outShape = assertAndGetBroadcastShape(a.shape, b.shape); - var derA = function () { - var res = dy; - var reduceAxes = getReductionAxes(a.shape, outShape); - if (reduceAxes.length > 0) { - res = sum$1(res, reduceAxes); - } - return reshape(res, a.shape); - }; - var derB = function () { - var res = dy; - var reduceAxes = getReductionAxes(b.shape, outShape); - if (reduceAxes.length > 0) { - res = sum$1(res, reduceAxes); - } - return reshape(neg(res), b.shape); - }; - return { a: derA, b: derB }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates a `tf.Tensor` with all elements set to 1. - * - * ```js - * tf.ones([2, 2]).print(); - * ``` - * - * @param shape An array of integers defining the output tensor shape. - * @param dtype The type of an element in the resulting tensor. Defaults to - * 'float'. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function ones$1(shape, dtype) { - if (dtype === void 0) { dtype = 'float32'; } - if (dtype === 'complex64') { - var real = ones$1(shape, 'float32'); - var imag = zeros(shape, 'float32'); - return complex(real, imag); - } - var values = makeOnesTypedArray(sizeFromShape(shape), dtype); - return ENGINE.makeTensor(values, shape, dtype); - } - - /** - * @license - * Copyright 2020 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var sumGradConfig = { - kernelName: Sum, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0]; - var expandedDyShape = x.shape.slice(); - var axis = attrs.axis; - var axes = parseAxisParam(axis, x.shape); - axes.forEach(function (axis) { - expandedDyShape[axis] = 1; - }); - var expandedDy = reshape(dy, expandedDyShape); - var derX = mul(expandedDy, ones$1(x.shape, 'float32')); - return { x: function () { return derX; } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var tanGradConfig = { - kernelName: Tan, - inputsToSave: ['x'], - gradFunc: function (dy, saved) { - var x = saved[0]; - return { x: function () { return div(dy, square(cos(x))); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var tanhGradConfig = { - kernelName: Tanh, - outputsToSave: [true], - gradFunc: function (dy, saved) { - var y = saved[0]; - return { x: function () { return mul(sub(scalar(1), square(y)), dy); } }; - } - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Extracts a slice from a `tf.Tensor` starting at coordinates `begin` - * and is of size `size`. - * - * Also available are stricter rank-specific methods with the same signature - * as this method that assert that `x` is of the given rank: - * - `tf.slice1d` - * - `tf.slice2d` - * - `tf.slice3d` - * - `tf.slice4d` - * - * ```js - * const x = tf.tensor1d([1, 2, 3, 4]); - * - * x.slice([1], [2]).print(); - * ``` - * - * ```js - * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); - * - * x.slice([1, 0], [1, 2]).print(); - * ``` - * @param x The input `tf.Tensor` to slice from. - * @param begin The coordinates to start the slice from. The length can be - * less than the rank of x - the rest of the axes will have implicit 0 as - * start. Can also be a single number, in which case it specifies the - * first axis. - * @param size The size of the slice. The length can be less than the rank of - * x - the rest of the axes will have implicit -1. A value of -1 requests - * the rest of the dimensions in the axis. Can also be a single number, - * in which case it specifies the size of the first axis. - */ - /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ - function slice_(x, begin, size) { - var $x = convertToTensor(x, 'x', 'slice'); - if ($x.rank === 0) { - throw new Error('Slicing scalar is not possible'); - } - var _a = parseSliceParams($x, begin, size), begin_ = _a[0], size_ = _a[1]; - assertParamsValid($x, begin_, size_); - var forward = function (backend, save) { - save([$x]); - return backend.slice($x, begin_, size_); - }; - var inputs = { x: $x }; - var attrs = { begin: begin, size: size }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, Slice, attrs); - } - var slice = op({ slice_: slice_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var tileGradConfig = { - kernelName: Tile, - inputsToSave: ['x'], - gradFunc: function (dy, saved, attrs) { - var x = saved[0]; - var reps = attrs.reps; - var derX = function () { - var xGrad = zerosLike(x); - // TODO(cais): Maybe reduce memory footprint by avoiding repeated - // slicing. - if (x.rank === 1) { - for (var i = 0; i < reps[0]; ++i) { - xGrad = add(xGrad, slice(dy, [i * x.shape[0]], [x.shape[0]])); - } - } - else if (x.rank === 2) { - for (var i = 0; i < reps[0]; ++i) { - for (var j = 0; j < reps[1]; ++j) { - xGrad = add(xGrad, slice(dy, [i * x.shape[0], j * x.shape[1]], [ - x.shape[0], x.shape[1] - ])); - } - } - } - else if (x.rank === 3) { - for (var i = 0; i < reps[0]; ++i) { - for (var j = 0; j < reps[1]; ++j) { - for (var k = 0; k < reps[2]; ++k) { - xGrad = - add(xGrad, slice(dy, [i * x.shape[0], j * x.shape[1], k * x.shape[2]], [x.shape[0], x.shape[1], x.shape[2]])); - } - } - } - } - else if (x.rank === 4) { - for (var i = 0; i < reps[0]; ++i) { - for (var j = 0; j < reps[1]; ++j) { - for (var k = 0; k < reps[2]; ++k) { - for (var l = 0; l < reps[3]; ++l) { - xGrad = - add(xGrad, slice(dy, [ - i * x.shape[0], j * x.shape[1], k * x.shape[2], - l * x.shape[3] - ], [x.shape[0], x.shape[1], x.shape[2], x.shape[3]])); - } - } - } - } - } - else { - throw new Error("Gradient for tile operation is not implemented for rank-" + - (x.rank + " tensors yet.")); - } - return xGrad; - }; - return { x: derX }; - }, - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var transposeGradConfig = { - kernelName: Transpose, - gradFunc: function (dy, saved, attrs) { - var transposeAttrs = attrs; - var perm = transposeAttrs.perm; - var undoPerm = getUndoAxesPermutation(perm); - return { x: function () { return transpose(dy, undoPerm); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns a `tf.Tensor` that has expanded rank, by inserting a dimension - * into the tensor's shape. - * - * ```js - * const x = tf.tensor1d([1, 2, 3, 4]); - * const axis = 1; - * x.expandDims(axis).print(); - * ``` - * - * @param x The input tensor whose dimensions to be expanded. - * @param axis The dimension index at which to insert shape of `1`. Defaults - * to 0 (the first dimension). - */ - /** @doc {heading: 'Tensors', subheading: 'Transformations'} */ - function expandDims_(x, axis) { - if (axis === void 0) { axis = 0; } - var parseAs = null; - var $x = convertToTensor(x, 'x', 'expandDims', parseAs); - assert(axis <= $x.rank, function () { return 'Axis must be <= rank of the tensor'; }); - var newShape = $x.shape.slice(); - if (axis < 0) { - // Negative value is counted from the tail of rank. - assert(-($x.rank + 1) <= axis, function () { return "Axis must be in the interval [" + -($x.rank + 1) + ", " + $x.rank + "]"; }); - axis = $x.rank + axis + 1; - } - newShape.splice(axis, 0, 1); - return reshape($x, newShape); - } - var expandDims = op({ expandDims_: expandDims_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Stacks a list of rank-`R` `tf.Tensor`s into one rank-`(R+1)` `tf.Tensor`. - * - * ```js - * const a = tf.tensor1d([1, 2]); - * const b = tf.tensor1d([3, 4]); - * const c = tf.tensor1d([5, 6]); - * tf.stack([a, b, c]).print(); - * ``` - * - * @param tensors A list of tensor objects with the same shape and dtype. - * @param axis The axis to stack along. Defaults to 0 (the first dim). - */ - /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ - function stack_(tensors, axis) { - if (axis === void 0) { axis = 0; } - var $tensors = convertToTensorArray(tensors, 'tensors', 'stack'); - assert($tensors.length >= 1, function () { return 'Pass at least one tensor to tf.stack'; }); - if ($tensors.length === 1) { - return expandDims($tensors[0], axis); - } - var rank = $tensors[0].rank; - var shape = $tensors[0].shape; - var dtype = $tensors[0].dtype; - assert(axis <= rank, function () { return 'Axis must be <= rank of the tensor'; }); - $tensors.forEach(function (t) { - assertShapesMatch(shape, t.shape, 'All tensors passed to stack must have matching shapes'); - assert(dtype === t.dtype, function () { return 'All tensors passed to stack must have matching dtypes'; }); - }); - var expandedTensors = $tensors.map(function (t) { return expandDims(t, axis); }); - // Stack exists in the TensorFlow C++ API - // (https://www.tensorflow.org/api_docs/cc/class/tensorflow/ops/stack) but not - // in - // https://raw.githubusercontent.com/tensorflow/tensorflow/master/tensorflow/core/ops/ops.pbtxt. - // Therefore we are treating it like a high-level op rather than - // creating a dedicated stack kernel. - return concat(expandedTensors, axis); - } - var stack = op({ stack_: stack_ }); - - /** - * @license - * Copyright 2020 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var unpackGradConfig = { - kernelName: Unpack, - gradFunc: function (dy, saved, attrs) { - var unpackAttrs = attrs; - var axis = unpackAttrs.axis; - return { value: function () { return stack(dy, axis); } }; - } - }; - - /** - * @license - * Copyright 2017 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var PARALLELIZE_THRESHOLD = 30; - function computeOptimalWindowSize(inSize) { - if (inSize <= PARALLELIZE_THRESHOLD) { - return inSize; - } - return nearestDivisor(inSize, Math.floor(Math.sqrt(inSize))); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - function segOpComputeOptimalWindowSize(inSize, numSegments) { - var done = false; - var res; - if (inSize <= PARALLELIZE_THRESHOLD) { - res = inSize; - done = true; - } - else { - res = nearestDivisor(inSize, Math.floor(Math.sqrt(inSize))); - } - while (!done) { - if (res > numSegments || res === inSize) { - done = true; - } - else { - res = nearestDivisor(inSize, res + 1); - } - } - return res; - } - function computeOutShape$2(aShape, axis, numSegments) { - var outShape = []; - var rank = aShape.length; - for (var dim = 0; dim < rank; dim++) { - if (dim !== axis) { - outShape.push(aShape[dim]); - } - else { - outShape.push(numSegments); - } - } - return outShape; - } - function collectGatherOpShapeInfo(x, indices, axis) { - var dimSize = x.shape[axis]; - var outputShape = []; - var batchSize = 1; - var sliceSize = 1; - for (var i = 0; i < axis; i++) { - outputShape.push(x.shape[i]); - batchSize *= x.shape[i]; - } - for (var i = 0; i < indices.rank; i++) { - outputShape.push(indices.shape[i]); - } - for (var i = axis + 1; i < x.rank; i++) { - outputShape.push(x.shape[i]); - sliceSize *= x.shape[i]; - } - return { batchSize: batchSize, sliceSize: sliceSize, dimSize: dimSize, outputShape: outputShape }; - } - - var segment_util = { - __proto__: null, - segOpComputeOptimalWindowSize: segOpComputeOptimalWindowSize, - computeOutShape: computeOutShape$2, - collectGatherOpShapeInfo: collectGatherOpShapeInfo - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Gather slices from tensor `x`'s axis `axis` according to `indices`. - * - * ```js - * const x = tf.tensor1d([1, 2, 3, 4]); - * const indices = tf.tensor1d([1, 3, 3], 'int32'); - * - * x.gather(indices).print(); - * ``` - * - * ```js - * const x = tf.tensor2d([1, 2, 3, 4], [2, 2]); - * const indices = tf.tensor1d([1, 1, 0], 'int32'); - * - * x.gather(indices).print(); - * ``` - * @param x The input tensor whose slices to be gathered. - * @param indices The indices of the values to extract. - * @param axis The axis over which to select values. Defaults to 0. - */ - /** @doc {heading: 'Tensors', subheading: 'Slicing and Joining'} */ - function gather_(x, indices, axis) { - if (axis === void 0) { axis = 0; } - var $x = convertToTensor(x, 'x', 'gather'); - var $indices = convertToTensor(indices, 'indices', 'gather', 'int32'); - var inputs = { x: $x, indices: $indices }; - var attrs = { axis: axis }; - var forward = function (backend, save) { - var parsedAxis = parseAxisParam(axis, $x.shape)[0]; - var shapeInfo = collectGatherOpShapeInfo($x, $indices, parsedAxis); - var res = backend.gather($x, $indices.flatten(), parsedAxis); - save([$x, $indices]); - return res.reshape(shapeInfo.outputShape); - }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, GatherV2, attrs); - } - var gather = op({ gather_: gather_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Returns the max of a and b (`a > b ? a : b`) element-wise. - * Supports broadcasting. - * - * We also expose `tf.maximumStrict` which has the same signature as this op and - * asserts that `a` and `b` are the same shape (does not broadcast). - * - * ```js - * const a = tf.tensor1d([1, 4, 3, 16]); - * const b = tf.tensor1d([1, 2, 9, 4]); - * - * a.maximum(b).print(); // or tf.maximum(a, b) - * ``` - * - * ```js - * // Broadcast maximum a with b. - * const a = tf.tensor1d([2, 4, 6, 8]); - * const b = tf.scalar(5); - * - * a.maximum(b).print(); // or tf.maximum(a, b) - * ``` - * - * @param a The first tensor. - * @param b The second tensor. Must have the same type as `a`. - */ - /** @doc {heading: 'Operations', subheading: 'Arithmetic'} */ - function maximum_(a, b) { - var _a; - var $a = convertToTensor(a, 'a', 'maximum'); - var $b = convertToTensor(b, 'b', 'maximum'); - _a = makeTypesMatch($a, $b), $a = _a[0], $b = _a[1]; - if ($a.dtype === 'bool') { - $a = cast($a, 'int32'); - $b = cast($b, 'int32'); - } - assertAndGetBroadcastShape($a.shape, $b.shape); - var forward = function (backend, save) { - var res = backend.maximum($a, $b); - save([$a, $b]); - return res; - }; - var inputs = { a: $a, b: $b }; - return ENGINE.runKernelFunc(forward, inputs, null /* gradient */, Maximum); - } - var maximum = op({ maximum_: maximum_ }); - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var unsortedSegmentSumGradConfig = { - kernelName: UnsortedSegmentSum, - inputsToSave: ['segmentIds'], - gradFunc: function (dy, saved) { - var segmentIds = saved[0]; - var derX = function () { - return gatherDropNegatives(dy, segmentIds); - }; - return { x: derX }; - } - }; - function gatherDropNegatives(x, indices) { - // Helper function for unsorted segment ops. Gathers params for - // positive segment ids and gathers 0 for inputs with negative segment id. - // Mirrors _GatherDropNegatives from tensorflow/python/ops/math_grad.py - var zeroClippedIndices = maximum(indices, zerosLike(indices)); - var gathered = gather(x, zeroClippedIndices); - var isPositive = greaterEqual(indices, scalar(0, 'int32')); - var numIters = gathered.rank - isPositive.rank; - for (var i = 0; i < numIters; ++i) { - isPositive = expandDims(isPositive, i + 1); - } - isPositive = logicalAnd(isPositive, ones$1(gathered.shape, 'bool')); - var zeroSlice = zerosLike(gathered); - return where(isPositive, gathered, zeroSlice); - } - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var zerosLikeGradConfig = { - kernelName: ZerosLike, - gradFunc: function (dy) { - return { x: function () { return zerosLike(dy); } }; - } - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // Export all kernel configs here so that the package can auto register them - var gradConfigs = [ - absGradConfig, - acosGradConfig, - acoshGradConfig, - addGradConfig, - addNGradConfig, - argMaxGradConfig, - argMinGradConfig, - asinGradConfig, - asinhGradConfig, - atan2GradConfig, - atanGradConfig, - atanhGradConfig, - avgPool3DGradConfig, - avgPoolGradConfig, - batchMatMulGradConfig, - batchToSpaceNDGradConfig, - broadcastToGradConfig, - castGradConfig, - ceilGradConfig, - clipByValueGradConfig, - concatGradConfig, - conv2DBackpropInputGradConfig, - conv2DGradConfig, - conv3DGradConfig, - cosGradConfig, - coshGradConfig, - cumsumGradConfig, - depthwiseConv2dNativeGradConfig, - dilation2dGradConfig, - divGradConfig, - eluGradConfig, - erfGradConfig, - expGradConfig, - expm1GradConfig, - floorDivGradConfig, - floorGradConfig, - fusedBatchNormGradConfig, - gatherGradConfig, - greaterEqualGradConfig, - identityGradConfig, - isFiniteGradConfig, - isInfGradConfig, - isNanGradConfig, - log1pGradConfig, - logGradConfig, - logSoftmaxGradConfig, - lrnGradConfig, - maxGradConfig, - maxGradConfig, - maximumGradConfig, - maxPool3DGradConfig, - maxPoolGradConfig, - minGradConfig, - minimumGradConfig, - modGradConfig, - multiplyGradConfig, - negateGradConfig, - oneHotGradConfig, - onesLikeGradConfig, - padV2GradConfig, - padV2GradConfig, - powGradConfig, - preluGradConfig, - reciprocalGradConfig, - relu6GradConfig, - reluGradConfig, - reshapeGradConfig, - resizeBilinearGradConfig, - resizeNearestNeighborGradConfig, - reverseGradConfig, - roundGradConfig, - rsqrtGradConfig, - selectV2PoolGradConfig, - seluGradConfig, - sigmoidGradConfig, - signGradConfig, - sinGradConfig, - sinhGradConfig, - sliceGradConfig, - softmaxGradConfig, - softplusGradConfig, - spaceToBatchNDGradConfig, - spaceToBatchNDGradConfig, - splitVGradConfig, - splitVGradConfig, - sqrtGradConfig, - squaredDifferenceGradConfig, - squareGradConfig, - stepGradConfig, - subGradConfig, - sumGradConfig, - tanGradConfig, - tanhGradConfig, - tileGradConfig, - transposeGradConfig, - unpackGradConfig, - unsortedSegmentSumGradConfig, - zerosLikeGradConfig - ]; - for (var _i = 0, gradConfigs_1 = gradConfigs; _i < gradConfigs_1.length; _i++) { - var gradientConfig = gradConfigs_1[_i]; - registerGradient(gradientConfig); - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var PlatformBrowser = /** @class */ (function () { - function PlatformBrowser() { - } - PlatformBrowser.prototype.fetch = function (path, init) { - return fetch(path, init); - }; - PlatformBrowser.prototype.now = function () { - return performance.now(); - }; - PlatformBrowser.prototype.encode = function (text, encoding) { - if (encoding !== 'utf-8' && encoding !== 'utf8') { - throw new Error("Browser's encoder only supports utf-8, but got " + encoding); - } - if (this.textEncoder == null) { - this.textEncoder = new TextEncoder(); - } - return this.textEncoder.encode(text); - }; - PlatformBrowser.prototype.decode = function (bytes, encoding) { - return new TextDecoder(encoding).decode(bytes); - }; - return PlatformBrowser; - }()); - if (env().get('IS_BROWSER')) { - env().setPlatform('browser', new PlatformBrowser()); - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - // We are wrapping this within an object so it can be stubbed by Jasmine. - var getNodeFetch = { - // tslint:disable-next-line:no-require-imports - importFetch: function () { return require('node-fetch'); } - }; - var systemFetch; - var PlatformNode = /** @class */ (function () { - function PlatformNode() { - // tslint:disable-next-line:no-require-imports - this.util = require('util'); - // According to the spec, the built-in encoder can do only UTF-8 encoding. - // https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder/TextEncoder - this.textEncoder = new this.util.TextEncoder(); - } - PlatformNode.prototype.fetch = function (path, requestInits) { - if (env().global.fetch != null) { - return env().global.fetch(path, requestInits); - } - if (systemFetch == null) { - systemFetch = getNodeFetch.importFetch(); - } - return systemFetch(path, requestInits); - }; - PlatformNode.prototype.now = function () { - var time = process.hrtime(); - return time[0] * 1000 + time[1] / 1000000; - }; - PlatformNode.prototype.encode = function (text, encoding) { - if (encoding !== 'utf-8' && encoding !== 'utf8') { - throw new Error("Node built-in encoder only supports utf-8, but got " + encoding); - } - return this.textEncoder.encode(text); - }; - PlatformNode.prototype.decode = function (bytes, encoding) { - if (bytes.length === 0) { - return ''; - } - return new this.util.TextDecoder(encoding).decode(bytes); - }; - return PlatformNode; - }()); - if (env().get('IS_NODE')) { - env().setPlatform('node', new PlatformNode()); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /* Type definitions for exporting and importing of models. */ - /** - * A map from Tensor dtype to number of bytes per element of the Tensor. - */ - var DTYPE_VALUE_SIZE_MAP = { - 'float32': 4, - 'float16': 2, - 'int32': 4, - 'uint16': 2, - 'uint8': 1, - 'bool': 1, - 'complex64': 8 - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** Number of bytes reserved for the length of the string. (32bit integer). */ - var NUM_BYTES_STRING_LENGTH = 4; - /** - * Encode a map from names to weight values as an ArrayBuffer, along with an - * `Array` of `WeightsManifestEntry` as specification of the encoded weights. - * - * This function does not perform sharding. - * - * This function is the reverse of `decodeWeights`. - * - * @param tensors A map ("dict") from names to tensors. - * @param group Group to which the weights belong (optional). - * @returns A `Promise` of - * - A flat `ArrayBuffer` with all the binary values of the `Tensor`s - * concatenated. - * - An `Array` of `WeightManifestEntry`s, carrying information including - * tensor names, `dtype`s and shapes. - * @throws Error: on unsupported tensor `dtype`. - */ - function encodeWeights(tensors, group) { - return __awaiter(this, void 0, void 0, function () { - var specs, dataPromises, names, _loop_1, i, tensorValues; - var _this = this; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - specs = []; - dataPromises = []; - names = Array.isArray(tensors) ? - tensors.map(function (tensor) { return tensor.name; }) : - Object.keys(tensors); - _loop_1 = function (i) { - var name_1 = names[i]; - var t = Array.isArray(tensors) ? tensors[i].tensor : tensors[name_1]; - if (t.dtype !== 'float32' && t.dtype !== 'int32' && t.dtype !== 'bool' && - t.dtype !== 'string' && t.dtype !== 'complex64') { - throw new Error("Unsupported dtype in weight '" + name_1 + "': " + t.dtype); - } - var spec = { name: name_1, shape: t.shape, dtype: t.dtype }; - if (t.dtype === 'string') { - var utf8bytes = new Promise(function (resolve) { return __awaiter(_this, void 0, void 0, function () { - var vals, totalNumBytes, bytes, offset, i_1, val, bytesOfLength; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, t.bytes()]; - case 1: - vals = _a.sent(); - totalNumBytes = vals.reduce(function (p, c) { return p + c.length; }, 0) + - NUM_BYTES_STRING_LENGTH * vals.length; - bytes = new Uint8Array(totalNumBytes); - offset = 0; - for (i_1 = 0; i_1 < vals.length; i_1++) { - val = vals[i_1]; - bytesOfLength = new Uint8Array(new Uint32Array([val.length]).buffer); - bytes.set(bytesOfLength, offset); - offset += NUM_BYTES_STRING_LENGTH; - bytes.set(val, offset); - offset += val.length; - } - resolve(bytes); - return [2 /*return*/]; - } - }); - }); }); - dataPromises.push(utf8bytes); - } - else { - dataPromises.push(t.data()); - } - if (group != null) { - spec.group = group; - } - specs.push(spec); - }; - for (i = 0; i < names.length; ++i) { - _loop_1(i); - } - return [4 /*yield*/, Promise.all(dataPromises)]; - case 1: - tensorValues = _a.sent(); - return [2 /*return*/, { data: concatenateTypedArrays(tensorValues), specs: specs }]; - } - }); - }); - } - /** - * Decode flat ArrayBuffer as weights. - * - * This function does not handle sharding. - * - * This function is the reverse of `encodeWeights`. - * - * @param buffer A flat ArrayBuffer carrying the binary values of the tensors - * concatenated in the order specified in `specs`. - * @param specs Specifications of the names, dtypes and shapes of the tensors - * whose value are encoded by `buffer`. - * @return A map from tensor name to tensor value, with the names corresponding - * to names in `specs`. - * @throws Error, if any of the tensors has unsupported dtype. - */ - function decodeWeights(buffer, specs) { - // TODO(adarob, cais): Support quantization. - var out = {}; - var float16Decode; - var offset = 0; - for (var _i = 0, specs_1 = specs; _i < specs_1.length; _i++) { - var spec = specs_1[_i]; - var name_2 = spec.name; - var dtype = spec.dtype; - var shape = spec.shape; - var size = sizeFromShape(shape); - var values = void 0; - if ('quantization' in spec) { - var quantization = spec.quantization; - if (quantization.dtype === 'uint8' || quantization.dtype === 'uint16') { - if (!('min' in quantization && 'scale' in quantization)) { - throw new Error("Weight " + spec.name + " with quantization " + quantization.dtype + " " + - "doesn't have corresponding metadata min and scale."); - } - } - else if (quantization.dtype === 'float16') { - if (dtype !== 'float32') { - throw new Error("Weight " + spec.name + " is quantized with " + quantization.dtype + " " + - ("which only supports weights of type float32 not " + dtype + ".")); - } - } - else { - throw new Error("Weight " + spec.name + " has unknown " + - ("quantization dtype " + quantization.dtype + ". ") + - "Supported quantization dtypes are: " + - "'uint8', 'uint16', and 'float16'."); - } - var quantizationSizeFactor = DTYPE_VALUE_SIZE_MAP[quantization.dtype]; - var byteBuffer = buffer.slice(offset, offset + size * quantizationSizeFactor); - var quantizedArray = (quantization.dtype === 'uint8') ? - new Uint8Array(byteBuffer) : - new Uint16Array(byteBuffer); - if (dtype === 'float32') { - if (quantization.dtype === 'uint8' || quantization.dtype === 'uint16') { - values = new Float32Array(quantizedArray.length); - for (var i = 0; i < quantizedArray.length; i++) { - var v = quantizedArray[i]; - values[i] = v * quantization.scale + quantization.min; - } - } - else if (quantization.dtype === 'float16') { - if (float16Decode === undefined) { - float16Decode = getFloat16Decoder(); - } - values = float16Decode(quantizedArray); - } - else { - throw new Error("Unsupported quantization type " + quantization.dtype + " " + - "for weight type float32."); - } - } - else if (dtype === 'int32') { - if (quantization.dtype !== 'uint8' && quantization.dtype !== 'uint16') { - throw new Error("Unsupported quantization type " + quantization.dtype + " " + - "for weight type int32."); - } - values = new Int32Array(quantizedArray.length); - for (var i = 0; i < quantizedArray.length; i++) { - var v = quantizedArray[i]; - values[i] = Math.round(v * quantization.scale + quantization.min); - } - } - else { - throw new Error("Unsupported dtype in weight '" + name_2 + "': " + dtype); - } - offset += size * quantizationSizeFactor; - } - else if (dtype === 'string') { - var size_1 = sizeFromShape(spec.shape); - values = []; - for (var i = 0; i < size_1; i++) { - var byteLength = new Uint32Array(buffer.slice(offset, offset + NUM_BYTES_STRING_LENGTH))[0]; - offset += NUM_BYTES_STRING_LENGTH; - var bytes = new Uint8Array(buffer.slice(offset, offset + byteLength)); - values.push(bytes); - offset += byteLength; - } - } - else { - var dtypeFactor = DTYPE_VALUE_SIZE_MAP[dtype]; - var byteBuffer = buffer.slice(offset, offset + size * dtypeFactor); - if (dtype === 'float32') { - values = new Float32Array(byteBuffer); - } - else if (dtype === 'int32') { - values = new Int32Array(byteBuffer); - } - else if (dtype === 'bool') { - values = new Uint8Array(byteBuffer); - } - else if (dtype === 'complex64') { - values = new Float32Array(byteBuffer); - var real = new Float32Array(values.length / 2); - var image = new Float32Array(values.length / 2); - for (var i = 0; i < real.length; i++) { - real[i] = values[i * 2]; - image[i] = values[i * 2 + 1]; - } - var realTensor = tensor(real, shape, 'float32'); - var imageTensor = tensor(image, shape, 'float32'); - out[name_2] = complex(realTensor, imageTensor); - } - else { - throw new Error("Unsupported dtype in weight '" + name_2 + "': " + dtype); - } - offset += size * dtypeFactor; - } - if (dtype !== 'complex64') { - out[name_2] = tensor(values, shape, dtype); - } - } - return out; - } - /** - * Concatenate TypedArrays into an ArrayBuffer. - */ - function concatenateTypedArrays(xs) { - // TODO(adarob, cais): Support quantization. - if (xs === null) { - throw new Error("Invalid input value: " + JSON.stringify(xs)); - } - var totalByteLength = 0; - // `normalizedXs` is here for this reason: a `TypedArray`'s `buffer' - // can have a different byte length from that of the `TypedArray` itself, - // for example, when the `TypedArray` is created from an offset in an - // `ArrayBuffer`. `normliazedXs` holds `TypedArray`s whose `buffer`s match - // the `TypedArray` in byte length. If an element of `xs` does not show - // this property, a new `TypedArray` that satisfy this property will be - // constructed and pushed into `normalizedXs`. - var normalizedXs = []; - xs.forEach(function (x) { - totalByteLength += x.byteLength; - // tslint:disable:no-any - normalizedXs.push(x.byteLength === x.buffer.byteLength ? x : - new x.constructor(x)); - if (!(x instanceof Float32Array || x instanceof Int32Array || - x instanceof Uint8Array)) { - throw new Error("Unsupported TypedArray subtype: " + x.constructor.name); - } - // tslint:enable:no-any - }); - var y = new Uint8Array(totalByteLength); - var offset = 0; - normalizedXs.forEach(function (x) { - y.set(new Uint8Array(x.buffer), offset); - offset += x.byteLength; - }); - return y.buffer; - } - // Use Buffer on Node.js instead of Blob/atob/btoa - var useNodeBuffer = typeof Buffer !== 'undefined' && - (typeof Blob === 'undefined' || typeof atob === 'undefined' || - typeof btoa === 'undefined'); - /** - * Calculate the byte length of a JavaScript string. - * - * Note that a JavaScript string can contain wide characters, therefore the - * length of the string is not necessarily equal to the byte length. - * - * @param str Input string. - * @returns Byte length. - */ - function stringByteLength(str) { - if (useNodeBuffer) { - return Buffer.byteLength(str); - } - return new Blob([str]).size; - } - /** - * Encode an ArrayBuffer as a base64 encoded string. - * - * @param buffer `ArrayBuffer` to be converted. - * @returns A string that base64-encodes `buffer`. - */ - function arrayBufferToBase64String(buffer) { - if (useNodeBuffer) { - return Buffer.from(buffer).toString('base64'); - } - var buf = new Uint8Array(buffer); - var s = ''; - for (var i = 0, l = buf.length; i < l; i++) { - s += String.fromCharCode(buf[i]); - } - return btoa(s); - } - /** - * Decode a base64 string as an ArrayBuffer. - * - * @param str Base64 string. - * @returns Decoded `ArrayBuffer`. - */ - function base64StringToArrayBuffer(str) { - if (useNodeBuffer) { - var buf = Buffer.from(str, 'base64'); - return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); - } - var s = atob(str); - var buffer = new Uint8Array(s.length); - for (var i = 0; i < s.length; ++i) { - buffer.set([s.charCodeAt(i)], i); - } - return buffer.buffer; - } - /** - * Concatenate a number of ArrayBuffers into one. - * - * @param buffers A number of array buffers to concatenate. - * @returns Result of concatenating `buffers` in order. - */ - function concatenateArrayBuffers(buffers) { - if (buffers.length === 1) { - return buffers[0]; - } - var totalByteLength = 0; - buffers.forEach(function (buffer) { - totalByteLength += buffer.byteLength; - }); - var temp = new Uint8Array(totalByteLength); - var offset = 0; - buffers.forEach(function (buffer) { - temp.set(new Uint8Array(buffer), offset); - offset += buffer.byteLength; - }); - return temp.buffer; - } - /** - * Get the basename of a path. - * - * Behaves in a way analogous to Linux's basename command. - * - * @param path - */ - function basename(path) { - var SEPARATOR = '/'; - path = path.trim(); - while (path.endsWith(SEPARATOR)) { - path = path.slice(0, path.length - 1); - } - var items = path.split(SEPARATOR); - return items[items.length - 1]; - } - /** - * Populate ModelArtifactsInfo fields for a model with JSON topology. - * @param modelArtifacts - * @returns A ModelArtifactsInfo object. - */ - function getModelArtifactsInfoForJSON(modelArtifacts) { - if (modelArtifacts.modelTopology instanceof ArrayBuffer) { - throw new Error('Expected JSON model topology, received ArrayBuffer.'); - } - return { - dateSaved: new Date(), - modelTopologyType: 'JSON', - modelTopologyBytes: modelArtifacts.modelTopology == null ? - 0 : - stringByteLength(JSON.stringify(modelArtifacts.modelTopology)), - weightSpecsBytes: modelArtifacts.weightSpecs == null ? - 0 : - stringByteLength(JSON.stringify(modelArtifacts.weightSpecs)), - weightDataBytes: modelArtifacts.weightData == null ? - 0 : - modelArtifacts.weightData.byteLength, - }; - } - /** - * Computes mantisa table for casting Float16 to Float32 - * See http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf - * - * @returns Uint32Array, 2048 mantissa lookup values. - */ - function computeFloat16MantisaTable() { - var convertMantissa = function (i) { - var m = i << 13; - var e = 0; - while ((m & 0x00800000) === 0) { - e -= 0x00800000; - m <<= 1; - } - m &= ~0x00800000; - e += 0x38800000; - return m | e; - }; - var mantisaTable = new Uint32Array(2048); - mantisaTable[0] = 0; - for (var i = 1; i < 1024; i++) { - mantisaTable[i] = convertMantissa(i); - } - for (var i = 1024; i < 2048; i++) { - mantisaTable[i] = 0x38000000 + ((i - 1024) << 13); - } - return mantisaTable; - } - /** - * Computes exponent table for casting Float16 to Float32 - * See http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf - * - * @returns Uint32Array, 64 exponent lookup values. - */ - function computeFloat16ExponentTable() { - var exponentTable = new Uint32Array(64); - exponentTable[0] = 0; - exponentTable[31] = 0x47800000; - exponentTable[32] = 0x80000000; - exponentTable[63] = 0xc7800000; - for (var i = 1; i < 31; i++) { - exponentTable[i] = i << 23; - } - for (var i = 33; i < 63; i++) { - exponentTable[i] = 0x80000000 + ((i - 32) << 23); - } - return exponentTable; - } - /** - * Computes offset table for casting Float16 to Float32 - * See http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf - * - * @returns Uint32Array, 6d offset values. - */ - function computeFloat16OffsetTable() { - var offsetTable = new Uint32Array(64); - for (var i = 0; i < 64; i++) { - offsetTable[i] = 1024; - } - offsetTable[0] = offsetTable[32] = 0; - return offsetTable; - } - /** - * Retrieve a Float16 decoder which will decode a ByteArray of Float16 values - * to a Float32Array. - * - * @returns Function (buffer: Uint16Array) => Float32Array which decodes - * the Uint16Array of Float16 bytes to a Float32Array. - */ - function getFloat16Decoder() { - // Algorithm is based off of - // http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf - // Cache lookup tables - var mantisaTable = computeFloat16MantisaTable(); - var exponentTable = computeFloat16ExponentTable(); - var offsetTable = computeFloat16OffsetTable(); - return function (quantizedArray) { - var buffer = new ArrayBuffer(4 * quantizedArray.length); - var bufferUint32View = new Uint32Array(buffer); - for (var index = 0; index < quantizedArray.length; index++) { - var float16Bits = quantizedArray[index]; - var float32Bits = mantisaTable[offsetTable[float16Bits >> 10] + (float16Bits & 0x3ff)] + - exponentTable[float16Bits >> 10]; - bufferUint32View[index] = float32Bits; - } - return new Float32Array(buffer); - }; - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var IORouterRegistry = /** @class */ (function () { - function IORouterRegistry() { - this.saveRouters = []; - this.loadRouters = []; - } - IORouterRegistry.getInstance = function () { - if (IORouterRegistry.instance == null) { - IORouterRegistry.instance = new IORouterRegistry(); - } - return IORouterRegistry.instance; - }; - /** - * Register a save-handler router. - * - * @param saveRouter A function that maps a URL-like string onto an instance - * of `IOHandler` with the `save` method defined or `null`. - */ - IORouterRegistry.registerSaveRouter = function (saveRouter) { - IORouterRegistry.getInstance().saveRouters.push(saveRouter); - }; - /** - * Register a load-handler router. - * - * @param loadRouter A function that maps a URL-like string onto an instance - * of `IOHandler` with the `load` method defined or `null`. - */ - IORouterRegistry.registerLoadRouter = function (loadRouter) { - IORouterRegistry.getInstance().loadRouters.push(loadRouter); - }; - /** - * Look up IOHandler for saving, given a URL-like string. - * - * @param url - * @returns If only one match is found, an instance of IOHandler with the - * `save` method defined. If no match is found, `null`. - * @throws Error, if more than one match is found. - */ - IORouterRegistry.getSaveHandlers = function (url) { - return IORouterRegistry.getHandlers(url, 'save'); - }; - /** - * Look up IOHandler for loading, given a URL-like string. - * - * @param url - * @param loadOptions Optional, custom load options. - * @returns All valid handlers for `url`, given the currently registered - * handler routers. - */ - IORouterRegistry.getLoadHandlers = function (url, loadOptions) { - return IORouterRegistry.getHandlers(url, 'load', loadOptions); - }; - IORouterRegistry.getHandlers = function (url, handlerType, loadOptions) { - var validHandlers = []; - var routers = handlerType === 'load' ? - IORouterRegistry.getInstance().loadRouters : - IORouterRegistry.getInstance().saveRouters; - routers.forEach(function (router) { - var handler = router(url, loadOptions); - if (handler !== null) { - validHandlers.push(handler); - } - }); - return validHandlers; - }; - return IORouterRegistry; - }()); - var registerSaveRouter = function (loudRouter) { - return IORouterRegistry.registerSaveRouter(loudRouter); - }; - var registerLoadRouter = function (loudRouter) { - return IORouterRegistry.registerLoadRouter(loudRouter); - }; - var getSaveHandlers = function (url) { - return IORouterRegistry.getSaveHandlers(url); - }; - var getLoadHandlers = function (url, loadOptions) { - return IORouterRegistry.getLoadHandlers(url, loadOptions); - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var URL_SCHEME_SUFFIX = '://'; - var ModelStoreManagerRegistry = /** @class */ (function () { - function ModelStoreManagerRegistry() { - this.managers = {}; - } - ModelStoreManagerRegistry.getInstance = function () { - if (ModelStoreManagerRegistry.instance == null) { - ModelStoreManagerRegistry.instance = new ModelStoreManagerRegistry(); - } - return ModelStoreManagerRegistry.instance; - }; - /** - * Register a save-handler router. - * - * @param saveRouter A function that maps a URL-like string onto an instance - * of `IOHandler` with the `save` method defined or `null`. - */ - ModelStoreManagerRegistry.registerManager = function (scheme, manager) { - assert(scheme != null, function () { return 'scheme must not be undefined or null.'; }); - if (scheme.endsWith(URL_SCHEME_SUFFIX)) { - scheme = scheme.slice(0, scheme.indexOf(URL_SCHEME_SUFFIX)); - } - assert(scheme.length > 0, function () { return 'scheme must not be an empty string.'; }); - var registry = ModelStoreManagerRegistry.getInstance(); - assert(registry.managers[scheme] == null, function () { return "A model store manager is already registered for scheme '" + scheme + "'."; }); - registry.managers[scheme] = manager; - }; - ModelStoreManagerRegistry.getManager = function (scheme) { - var manager = this.getInstance().managers[scheme]; - if (manager == null) { - throw new Error("Cannot find model manager for scheme '" + scheme + "'"); - } - return manager; - }; - ModelStoreManagerRegistry.getSchemes = function () { - return Object.keys(this.getInstance().managers); - }; - return ModelStoreManagerRegistry; - }()); - /** - * Helper method for parsing a URL string into a scheme and a path. - * - * @param url E.g., 'localstorage://my-model' - * @returns A dictionary with two fields: scheme and path. - * Scheme: e.g., 'localstorage' in the example above. - * Path: e.g., 'my-model' in the example above. - */ - function parseURL(url) { - if (url.indexOf(URL_SCHEME_SUFFIX) === -1) { - throw new Error("The url string provided does not contain a scheme. " + - "Supported schemes are: " + - ("" + ModelStoreManagerRegistry.getSchemes().join(','))); - } - return { - scheme: url.split(URL_SCHEME_SUFFIX)[0], - path: url.split(URL_SCHEME_SUFFIX)[1], - }; - } - function cloneModelInternal(sourceURL, destURL, deleteSource) { - if (deleteSource === void 0) { deleteSource = false; } - return __awaiter(this, void 0, void 0, function () { - var loadHandlers, loadHandler, saveHandlers, saveHandler, sourceScheme, sourcePath, sameMedium, modelArtifacts, saveResult; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - assert(sourceURL !== destURL, function () { return "Old path and new path are the same: '" + sourceURL + "'"; }); - loadHandlers = IORouterRegistry.getLoadHandlers(sourceURL); - assert(loadHandlers.length > 0, function () { return "Copying failed because no load handler is found for source URL " + sourceURL + "."; }); - assert(loadHandlers.length < 2, function () { return "Copying failed because more than one (" + loadHandlers.length + ") " + - ("load handlers for source URL " + sourceURL + "."); }); - loadHandler = loadHandlers[0]; - saveHandlers = IORouterRegistry.getSaveHandlers(destURL); - assert(saveHandlers.length > 0, function () { return "Copying failed because no save handler is found for destination " + - ("URL " + destURL + "."); }); - assert(saveHandlers.length < 2, function () { return "Copying failed because more than one (" + loadHandlers.length + ") " + - ("save handlers for destination URL " + destURL + "."); }); - saveHandler = saveHandlers[0]; - sourceScheme = parseURL(sourceURL).scheme; - sourcePath = parseURL(sourceURL).path; - sameMedium = sourceScheme === parseURL(sourceURL).scheme; - return [4 /*yield*/, loadHandler.load()]; - case 1: - modelArtifacts = _a.sent(); - if (!(deleteSource && sameMedium)) return [3 /*break*/, 3]; - return [4 /*yield*/, ModelStoreManagerRegistry.getManager(sourceScheme) - .removeModel(sourcePath)]; - case 2: - _a.sent(); - _a.label = 3; - case 3: return [4 /*yield*/, saveHandler.save(modelArtifacts)]; - case 4: - saveResult = _a.sent(); - if (!(deleteSource && !sameMedium)) return [3 /*break*/, 6]; - return [4 /*yield*/, ModelStoreManagerRegistry.getManager(sourceScheme) - .removeModel(sourcePath)]; - case 5: - _a.sent(); - _a.label = 6; - case 6: return [2 /*return*/, saveResult.modelArtifactsInfo]; - } - }); - }); - } - /** - * List all models stored in registered storage mediums. - * - * For a web browser environment, the registered mediums are Local Storage and - * IndexedDB. - * - * ```js - * // First create and save a model. - * const model = tf.sequential(); - * model.add(tf.layers.dense( - * {units: 1, inputShape: [10], activation: 'sigmoid'})); - * await model.save('localstorage://demo/management/model1'); - * - * // Then list existing models. - * console.log(JSON.stringify(await tf.io.listModels())); - * - * // Delete the model. - * await tf.io.removeModel('localstorage://demo/management/model1'); - * - * // List models again. - * console.log(JSON.stringify(await tf.io.listModels())); - * ``` - * - * @returns A `Promise` of a dictionary mapping URLs of existing models to - * their model artifacts info. URLs include medium-specific schemes, e.g., - * 'indexeddb://my/model/1'. Model artifacts info include type of the - * model's topology, byte sizes of the topology, weights, etc. - */ - /** - * @doc { - * heading: 'Models', - * subheading: 'Management', - * namespace: 'io', - * ignoreCI: true - * } - */ - function listModels() { - return __awaiter(this, void 0, void 0, function () { - var schemes, out, _i, schemes_1, scheme, schemeOut, path, url; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - schemes = ModelStoreManagerRegistry.getSchemes(); - out = {}; - _i = 0, schemes_1 = schemes; - _a.label = 1; - case 1: - if (!(_i < schemes_1.length)) return [3 /*break*/, 4]; - scheme = schemes_1[_i]; - return [4 /*yield*/, ModelStoreManagerRegistry.getManager(scheme).listModels()]; - case 2: - schemeOut = _a.sent(); - for (path in schemeOut) { - url = scheme + URL_SCHEME_SUFFIX + path; - out[url] = schemeOut[path]; - } - _a.label = 3; - case 3: - _i++; - return [3 /*break*/, 1]; - case 4: return [2 /*return*/, out]; - } - }); - }); - } - /** - * Remove a model specified by URL from a reigstered storage medium. - * - * ```js - * // First create and save a model. - * const model = tf.sequential(); - * model.add(tf.layers.dense( - * {units: 1, inputShape: [10], activation: 'sigmoid'})); - * await model.save('localstorage://demo/management/model1'); - * - * // Then list existing models. - * console.log(JSON.stringify(await tf.io.listModels())); - * - * // Delete the model. - * await tf.io.removeModel('localstorage://demo/management/model1'); - * - * // List models again. - * console.log(JSON.stringify(await tf.io.listModels())); - * ``` - * - * @param url A URL to a stored model, with a scheme prefix, e.g., - * 'localstorage://my-model-1', 'indexeddb://my/model/2'. - * @returns ModelArtifactsInfo of the deleted model (if and only if deletion - * is successful). - * @throws Error if deletion fails, e.g., if no model exists at `path`. - */ - /** - * @doc { - * heading: 'Models', - * subheading: 'Management', - * namespace: 'io', - * ignoreCI: true - * } - */ - function removeModel(url) { - return __awaiter(this, void 0, void 0, function () { - var schemeAndPath, manager; - return __generator(this, function (_a) { - schemeAndPath = parseURL(url); - manager = ModelStoreManagerRegistry.getManager(schemeAndPath.scheme); - return [2 /*return*/, manager.removeModel(schemeAndPath.path)]; - }); - }); - } - /** - * Copy a model from one URL to another. - * - * This function supports: - * - * 1. Copying within a storage medium, e.g., - * `tf.io.copyModel('localstorage://model-1', 'localstorage://model-2')` - * 2. Copying between two storage mediums, e.g., - * `tf.io.copyModel('localstorage://model-1', 'indexeddb://model-1')` - * - * ```js - * // First create and save a model. - * const model = tf.sequential(); - * model.add(tf.layers.dense( - * {units: 1, inputShape: [10], activation: 'sigmoid'})); - * await model.save('localstorage://demo/management/model1'); - * - * // Then list existing models. - * console.log(JSON.stringify(await tf.io.listModels())); - * - * // Copy the model, from Local Storage to IndexedDB. - * await tf.io.copyModel( - * 'localstorage://demo/management/model1', - * 'indexeddb://demo/management/model1'); - * - * // List models again. - * console.log(JSON.stringify(await tf.io.listModels())); - * - * // Remove both models. - * await tf.io.removeModel('localstorage://demo/management/model1'); - * await tf.io.removeModel('indexeddb://demo/management/model1'); - * ``` - * - * @param sourceURL Source URL of copying. - * @param destURL Destination URL of copying. - * @returns ModelArtifactsInfo of the copied model (if and only if copying - * is successful). - * @throws Error if copying fails, e.g., if no model exists at `sourceURL`, or - * if `oldPath` and `newPath` are identical. - */ - /** - * @doc { - * heading: 'Models', - * subheading: 'Management', - * namespace: 'io', - * ignoreCI: true - * } - */ - function copyModel(sourceURL, destURL) { - return __awaiter(this, void 0, void 0, function () { - var deleteSource; - return __generator(this, function (_a) { - deleteSource = false; - return [2 /*return*/, cloneModelInternal(sourceURL, destURL, deleteSource)]; - }); - }); - } - /** - * Move a model from one URL to another. - * - * This function supports: - * - * 1. Moving within a storage medium, e.g., - * `tf.io.moveModel('localstorage://model-1', 'localstorage://model-2')` - * 2. Moving between two storage mediums, e.g., - * `tf.io.moveModel('localstorage://model-1', 'indexeddb://model-1')` - * - * ```js - * // First create and save a model. - * const model = tf.sequential(); - * model.add(tf.layers.dense( - * {units: 1, inputShape: [10], activation: 'sigmoid'})); - * await model.save('localstorage://demo/management/model1'); - * - * // Then list existing models. - * console.log(JSON.stringify(await tf.io.listModels())); - * - * // Move the model, from Local Storage to IndexedDB. - * await tf.io.moveModel( - * 'localstorage://demo/management/model1', - * 'indexeddb://demo/management/model1'); - * - * // List models again. - * console.log(JSON.stringify(await tf.io.listModels())); - * - * // Remove the moved model. - * await tf.io.removeModel('indexeddb://demo/management/model1'); - * ``` - * - * @param sourceURL Source URL of moving. - * @param destURL Destination URL of moving. - * @returns ModelArtifactsInfo of the copied model (if and only if copying - * is successful). - * @throws Error if moving fails, e.g., if no model exists at `sourceURL`, or - * if `oldPath` and `newPath` are identical. - */ - /** - * @doc { - * heading: 'Models', - * subheading: 'Management', - * namespace: 'io', - * ignoreCI: true - * } - */ - function moveModel(sourceURL, destURL) { - return __awaiter(this, void 0, void 0, function () { - var deleteSource; - return __generator(this, function (_a) { - deleteSource = true; - return [2 /*return*/, cloneModelInternal(sourceURL, destURL, deleteSource)]; - }); - }); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var DATABASE_NAME = 'tensorflowjs'; - var DATABASE_VERSION = 1; - // Model data and ModelArtifactsInfo (metadata) are stored in two separate - // stores for efficient access of the list of stored models and their metadata. - // 1. The object store for model data: topology, weights and weight manifests. - var MODEL_STORE_NAME = 'models_store'; - // 2. The object store for ModelArtifactsInfo, including meta-information such - // as the type of topology (JSON vs binary), byte size of the topology, byte - // size of the weights, etc. - var INFO_STORE_NAME = 'model_info_store'; - function getIndexedDBFactory() { - if (!env().getBool('IS_BROWSER')) { - // TODO(cais): Add more info about what IOHandler subtypes are available. - // Maybe point to a doc page on the web and/or automatically determine - // the available IOHandlers and print them in the error message. - throw new Error('Failed to obtain IndexedDB factory because the current environment' + - 'is not a web browser.'); - } - // tslint:disable-next-line:no-any - var theWindow = typeof window === 'undefined' ? self : window; - var factory = theWindow.indexedDB || theWindow.mozIndexedDB || - theWindow.webkitIndexedDB || theWindow.msIndexedDB || - theWindow.shimIndexedDB; - if (factory == null) { - throw new Error('The current browser does not appear to support IndexedDB.'); - } - return factory; - } - function setUpDatabase(openRequest) { - var db = openRequest.result; - db.createObjectStore(MODEL_STORE_NAME, { keyPath: 'modelPath' }); - db.createObjectStore(INFO_STORE_NAME, { keyPath: 'modelPath' }); - } - /** - * IOHandler subclass: Browser IndexedDB. - * - * See the doc string of `browserIndexedDB` for more details. - */ - var BrowserIndexedDB = /** @class */ (function () { - function BrowserIndexedDB(modelPath) { - this.indexedDB = getIndexedDBFactory(); - if (modelPath == null || !modelPath) { - throw new Error('For IndexedDB, modelPath must not be null, undefined or empty.'); - } - this.modelPath = modelPath; - } - BrowserIndexedDB.prototype.save = function (modelArtifacts) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - // TODO(cais): Support saving GraphDef models. - if (modelArtifacts.modelTopology instanceof ArrayBuffer) { - throw new Error('BrowserLocalStorage.save() does not support saving model topology ' + - 'in binary formats yet.'); - } - return [2 /*return*/, this.databaseAction(this.modelPath, modelArtifacts)]; - }); - }); - }; - BrowserIndexedDB.prototype.load = function () { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.databaseAction(this.modelPath)]; - }); - }); - }; - /** - * Perform database action to put model artifacts into or read model artifacts - * from IndexedDB object store. - * - * Whether the action is put or get depends on whether `modelArtifacts` is - * specified. If it is specified, the action will be put; otherwise the action - * will be get. - * - * @param modelPath A unique string path for the model. - * @param modelArtifacts If specified, it will be the model artifacts to be - * stored in IndexedDB. - * @returns A `Promise` of `SaveResult`, if the action is put, or a `Promise` - * of `ModelArtifacts`, if the action is get. - */ - BrowserIndexedDB.prototype.databaseAction = function (modelPath, modelArtifacts) { - var _this = this; - return new Promise(function (resolve, reject) { - var openRequest = _this.indexedDB.open(DATABASE_NAME, DATABASE_VERSION); - openRequest.onupgradeneeded = function () { return setUpDatabase(openRequest); }; - openRequest.onsuccess = function () { - var db = openRequest.result; - if (modelArtifacts == null) { - // Read model out from object store. - var modelTx = db.transaction(MODEL_STORE_NAME, 'readonly'); - var modelStore = modelTx.objectStore(MODEL_STORE_NAME); - var getRequest_1 = modelStore.get(_this.modelPath); - getRequest_1.onsuccess = function () { - if (getRequest_1.result == null) { - db.close(); - return reject(new Error("Cannot find model with path '" + _this.modelPath + "' " + - "in IndexedDB.")); - } - else { - resolve(getRequest_1.result.modelArtifacts); - } - }; - getRequest_1.onerror = function (error) { - db.close(); - return reject(getRequest_1.error); - }; - modelTx.oncomplete = function () { return db.close(); }; - } - else { - // Put model into object store. - var modelArtifactsInfo_1 = getModelArtifactsInfoForJSON(modelArtifacts); - // First, put ModelArtifactsInfo into info store. - var infoTx_1 = db.transaction(INFO_STORE_NAME, 'readwrite'); - var infoStore_1 = infoTx_1.objectStore(INFO_STORE_NAME); - var putInfoRequest_1 = infoStore_1.put({ modelPath: _this.modelPath, modelArtifactsInfo: modelArtifactsInfo_1 }); - var modelTx_1; - putInfoRequest_1.onsuccess = function () { - // Second, put model data into model store. - modelTx_1 = db.transaction(MODEL_STORE_NAME, 'readwrite'); - var modelStore = modelTx_1.objectStore(MODEL_STORE_NAME); - var putModelRequest = modelStore.put({ - modelPath: _this.modelPath, - modelArtifacts: modelArtifacts, - modelArtifactsInfo: modelArtifactsInfo_1 - }); - putModelRequest.onsuccess = function () { return resolve({ modelArtifactsInfo: modelArtifactsInfo_1 }); }; - putModelRequest.onerror = function (error) { - // If the put-model request fails, roll back the info entry as - // well. - infoStore_1 = infoTx_1.objectStore(INFO_STORE_NAME); - var deleteInfoRequest = infoStore_1.delete(_this.modelPath); - deleteInfoRequest.onsuccess = function () { - db.close(); - return reject(putModelRequest.error); - }; - deleteInfoRequest.onerror = function (error) { - db.close(); - return reject(putModelRequest.error); - }; - }; - }; - putInfoRequest_1.onerror = function (error) { - db.close(); - return reject(putInfoRequest_1.error); - }; - infoTx_1.oncomplete = function () { - if (modelTx_1 == null) { - db.close(); - } - else { - modelTx_1.oncomplete = function () { return db.close(); }; - } - }; - } - }; - openRequest.onerror = function (error) { return reject(openRequest.error); }; - }); - }; - BrowserIndexedDB.URL_SCHEME = 'indexeddb://'; - return BrowserIndexedDB; - }()); - var indexedDBRouter = function (url) { - if (!env().getBool('IS_BROWSER')) { - return null; - } - else { - if (!Array.isArray(url) && url.startsWith(BrowserIndexedDB.URL_SCHEME)) { - return browserIndexedDB(url.slice(BrowserIndexedDB.URL_SCHEME.length)); - } - else { - return null; - } - } - }; - IORouterRegistry.registerSaveRouter(indexedDBRouter); - IORouterRegistry.registerLoadRouter(indexedDBRouter); - /** - * Creates a browser IndexedDB IOHandler for saving and loading models. - * - * ```js - * const model = tf.sequential(); - * model.add( - * tf.layers.dense({units: 1, inputShape: [100], activation: 'sigmoid'})); - * - * const saveResult = await model.save('indexeddb://MyModel')); - * console.log(saveResult); - * ``` - * - * @param modelPath A unique identifier for the model to be saved. Must be a - * non-empty string. - * @returns An instance of `BrowserIndexedDB` (sublcass of `IOHandler`), - * which can be used with, e.g., `tf.Model.save`. - */ - function browserIndexedDB(modelPath) { - return new BrowserIndexedDB(modelPath); - } - function maybeStripScheme(key) { - return key.startsWith(BrowserIndexedDB.URL_SCHEME) ? - key.slice(BrowserIndexedDB.URL_SCHEME.length) : - key; - } - var BrowserIndexedDBManager = /** @class */ (function () { - function BrowserIndexedDBManager() { - this.indexedDB = getIndexedDBFactory(); - } - BrowserIndexedDBManager.prototype.listModels = function () { - return __awaiter(this, void 0, void 0, function () { - var _this = this; - return __generator(this, function (_a) { - return [2 /*return*/, new Promise(function (resolve, reject) { - var openRequest = _this.indexedDB.open(DATABASE_NAME, DATABASE_VERSION); - openRequest.onupgradeneeded = function () { return setUpDatabase(openRequest); }; - openRequest.onsuccess = function () { - var db = openRequest.result; - var tx = db.transaction(INFO_STORE_NAME, 'readonly'); - var store = tx.objectStore(INFO_STORE_NAME); - // tslint:disable:max-line-length - // Need to cast `store` as `any` here because TypeScript's DOM - // library does not have the `getAll()` method even though the - // method is supported in the latest version of most mainstream - // browsers: - // https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/getAll - // tslint:enable:max-line-length - // tslint:disable-next-line:no-any - var getAllInfoRequest = store.getAll(); - getAllInfoRequest.onsuccess = function () { - var out = {}; - for (var _i = 0, _a = getAllInfoRequest.result; _i < _a.length; _i++) { - var item = _a[_i]; - out[item.modelPath] = item.modelArtifactsInfo; - } - resolve(out); - }; - getAllInfoRequest.onerror = function (error) { - db.close(); - return reject(getAllInfoRequest.error); - }; - tx.oncomplete = function () { return db.close(); }; - }; - openRequest.onerror = function (error) { return reject(openRequest.error); }; - })]; - }); - }); - }; - BrowserIndexedDBManager.prototype.removeModel = function (path) { - return __awaiter(this, void 0, void 0, function () { - var _this = this; - return __generator(this, function (_a) { - path = maybeStripScheme(path); - return [2 /*return*/, new Promise(function (resolve, reject) { - var openRequest = _this.indexedDB.open(DATABASE_NAME, DATABASE_VERSION); - openRequest.onupgradeneeded = function () { return setUpDatabase(openRequest); }; - openRequest.onsuccess = function () { - var db = openRequest.result; - var infoTx = db.transaction(INFO_STORE_NAME, 'readwrite'); - var infoStore = infoTx.objectStore(INFO_STORE_NAME); - var getInfoRequest = infoStore.get(path); - var modelTx; - getInfoRequest.onsuccess = function () { - if (getInfoRequest.result == null) { - db.close(); - return reject(new Error("Cannot find model with path '" + path + "' " + - "in IndexedDB.")); - } - else { - // First, delete the entry in the info store. - var deleteInfoRequest = infoStore.delete(path); - var deleteModelData_1 = function () { - // Second, delete the entry in the model store. - modelTx = db.transaction(MODEL_STORE_NAME, 'readwrite'); - var modelStore = modelTx.objectStore(MODEL_STORE_NAME); - var deleteModelRequest = modelStore.delete(path); - deleteModelRequest.onsuccess = function () { - return resolve(getInfoRequest.result.modelArtifactsInfo); - }; - deleteModelRequest.onerror = function (error) { - return reject(getInfoRequest.error); - }; - }; - // Proceed with deleting model data regardless of whether deletion - // of info data succeeds or not. - deleteInfoRequest.onsuccess = deleteModelData_1; - deleteInfoRequest.onerror = function (error) { - deleteModelData_1(); - db.close(); - return reject(getInfoRequest.error); - }; - } - }; - getInfoRequest.onerror = function (error) { - db.close(); - return reject(getInfoRequest.error); - }; - infoTx.oncomplete = function () { - if (modelTx == null) { - db.close(); - } - else { - modelTx.oncomplete = function () { return db.close(); }; - } - }; - }; - openRequest.onerror = function (error) { return reject(openRequest.error); }; - })]; - }); - }); - }; - return BrowserIndexedDBManager; - }()); - if (env().getBool('IS_BROWSER')) { - // Wrap the construction and registration, to guard against browsers that - // don't support Local Storage. - try { - ModelStoreManagerRegistry.registerManager(BrowserIndexedDB.URL_SCHEME, new BrowserIndexedDBManager()); - } - catch (err) { - } - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var PATH_SEPARATOR = '/'; - var PATH_PREFIX = 'tensorflowjs_models'; - var INFO_SUFFIX = 'info'; - var MODEL_TOPOLOGY_SUFFIX = 'model_topology'; - var WEIGHT_SPECS_SUFFIX = 'weight_specs'; - var WEIGHT_DATA_SUFFIX = 'weight_data'; - var MODEL_METADATA_SUFFIX = 'model_metadata'; - function getModelKeys(path) { - return { - info: [PATH_PREFIX, path, INFO_SUFFIX].join(PATH_SEPARATOR), - topology: [PATH_PREFIX, path, MODEL_TOPOLOGY_SUFFIX].join(PATH_SEPARATOR), - weightSpecs: [PATH_PREFIX, path, WEIGHT_SPECS_SUFFIX].join(PATH_SEPARATOR), - weightData: [PATH_PREFIX, path, WEIGHT_DATA_SUFFIX].join(PATH_SEPARATOR), - modelMetadata: [PATH_PREFIX, path, MODEL_METADATA_SUFFIX].join(PATH_SEPARATOR) - }; - } - /** - * Get model path from a local-storage key. - * - * E.g., 'tensorflowjs_models/my/model/1/info' --> 'my/model/1' - * - * @param key - */ - function getModelPathFromKey(key) { - var items = key.split(PATH_SEPARATOR); - if (items.length < 3) { - throw new Error("Invalid key format: " + key); - } - return items.slice(1, items.length - 1).join(PATH_SEPARATOR); - } - function maybeStripScheme$1(key) { - return key.startsWith(BrowserLocalStorage.URL_SCHEME) ? - key.slice(BrowserLocalStorage.URL_SCHEME.length) : - key; - } - /** - * IOHandler subclass: Browser Local Storage. - * - * See the doc string to `browserLocalStorage` for more details. - */ - var BrowserLocalStorage = /** @class */ (function () { - function BrowserLocalStorage(modelPath) { - if (!env().getBool('IS_BROWSER') || - typeof window === 'undefined' || - typeof window.localStorage === 'undefined') { - // TODO(cais): Add more info about what IOHandler subtypes are - // available. - // Maybe point to a doc page on the web and/or automatically determine - // the available IOHandlers and print them in the error message. - throw new Error('The current environment does not support local storage.'); - } - this.LS = window.localStorage; - if (modelPath == null || !modelPath) { - throw new Error('For local storage, modelPath must not be null, undefined or empty.'); - } - this.modelPath = modelPath; - this.keys = getModelKeys(this.modelPath); - } - /** - * Save model artifacts to browser local storage. - * - * See the documentation to `browserLocalStorage` for details on the saved - * artifacts. - * - * @param modelArtifacts The model artifacts to be stored. - * @returns An instance of SaveResult. - */ - BrowserLocalStorage.prototype.save = function (modelArtifacts) { - return __awaiter(this, void 0, void 0, function () { - var topology, weightSpecs, modelArtifactsInfo; - return __generator(this, function (_a) { - if (modelArtifacts.modelTopology instanceof ArrayBuffer) { - throw new Error('BrowserLocalStorage.save() does not support saving model topology ' + - 'in binary formats yet.'); - } - else { - topology = JSON.stringify(modelArtifacts.modelTopology); - weightSpecs = JSON.stringify(modelArtifacts.weightSpecs); - modelArtifactsInfo = getModelArtifactsInfoForJSON(modelArtifacts); - try { - this.LS.setItem(this.keys.info, JSON.stringify(modelArtifactsInfo)); - this.LS.setItem(this.keys.topology, topology); - this.LS.setItem(this.keys.weightSpecs, weightSpecs); - this.LS.setItem(this.keys.weightData, arrayBufferToBase64String(modelArtifacts.weightData)); - this.LS.setItem(this.keys.modelMetadata, JSON.stringify({ - format: modelArtifacts.format, - generatedBy: modelArtifacts.generatedBy, - convertedBy: modelArtifacts.convertedBy, - userDefinedMetadata: modelArtifacts.userDefinedMetadata - })); - return [2 /*return*/, { modelArtifactsInfo: modelArtifactsInfo }]; - } - catch (err) { - // If saving failed, clean up all items saved so far. - this.LS.removeItem(this.keys.info); - this.LS.removeItem(this.keys.topology); - this.LS.removeItem(this.keys.weightSpecs); - this.LS.removeItem(this.keys.weightData); - this.LS.removeItem(this.keys.modelMetadata); - throw new Error("Failed to save model '" + this.modelPath + "' to local storage: " + - "size quota being exceeded is a possible cause of this failure: " + - ("modelTopologyBytes=" + modelArtifactsInfo.modelTopologyBytes + ", ") + - ("weightSpecsBytes=" + modelArtifactsInfo.weightSpecsBytes + ", ") + - ("weightDataBytes=" + modelArtifactsInfo.weightDataBytes + ".")); - } - } - return [2 /*return*/]; - }); - }); - }; - /** - * Load a model from local storage. - * - * See the documentation to `browserLocalStorage` for details on the saved - * artifacts. - * - * @returns The loaded model (if loading succeeds). - */ - BrowserLocalStorage.prototype.load = function () { - return __awaiter(this, void 0, void 0, function () { - var info, out, topology, weightSpecs, metadataString, metadata, weightDataBase64; - return __generator(this, function (_a) { - info = JSON.parse(this.LS.getItem(this.keys.info)); - if (info == null) { - throw new Error("In local storage, there is no model with name '" + this.modelPath + "'"); - } - if (info.modelTopologyType !== 'JSON') { - throw new Error('BrowserLocalStorage does not support loading non-JSON model ' + - 'topology yet.'); - } - out = {}; - topology = JSON.parse(this.LS.getItem(this.keys.topology)); - if (topology == null) { - throw new Error("In local storage, the topology of model '" + this.modelPath + "' " + - "is missing."); - } - out.modelTopology = topology; - weightSpecs = JSON.parse(this.LS.getItem(this.keys.weightSpecs)); - if (weightSpecs == null) { - throw new Error("In local storage, the weight specs of model '" + this.modelPath + "' " + - "are missing."); - } - out.weightSpecs = weightSpecs; - metadataString = this.LS.getItem(this.keys.modelMetadata); - if (metadataString != null) { - metadata = JSON.parse(metadataString); - out.format = metadata['format']; - out.generatedBy = metadata['generatedBy']; - out.convertedBy = metadata['convertedBy']; - out.userDefinedMetadata = metadata['userDefinedMetadata']; - } - weightDataBase64 = this.LS.getItem(this.keys.weightData); - if (weightDataBase64 == null) { - throw new Error("In local storage, the binary weight values of model " + - ("'" + this.modelPath + "' are missing.")); - } - out.weightData = base64StringToArrayBuffer(weightDataBase64); - return [2 /*return*/, out]; - }); - }); - }; - BrowserLocalStorage.URL_SCHEME = 'localstorage://'; - return BrowserLocalStorage; - }()); - var localStorageRouter = function (url) { - if (!env().getBool('IS_BROWSER')) { - return null; - } - else { - if (!Array.isArray(url) && url.startsWith(BrowserLocalStorage.URL_SCHEME)) { - return browserLocalStorage(url.slice(BrowserLocalStorage.URL_SCHEME.length)); - } - else { - return null; - } - } - }; - IORouterRegistry.registerSaveRouter(localStorageRouter); - IORouterRegistry.registerLoadRouter(localStorageRouter); - /** - * Factory function for local storage IOHandler. - * - * This `IOHandler` supports both `save` and `load`. - * - * For each model's saved artifacts, four items are saved to local storage. - * - `${PATH_SEPARATOR}/${modelPath}/info`: Contains meta-info about the - * model, such as date saved, type of the topology, size in bytes, etc. - * - `${PATH_SEPARATOR}/${modelPath}/topology`: Model topology. For Keras- - * style models, this is a stringized JSON. - * - `${PATH_SEPARATOR}/${modelPath}/weight_specs`: Weight specs of the - * model, can be used to decode the saved binary weight values (see - * item below). - * - `${PATH_SEPARATOR}/${modelPath}/weight_data`: Concatenated binary - * weight values, stored as a base64-encoded string. - * - * Saving may throw an `Error` if the total size of the artifacts exceed the - * browser-specific quota. - * - * @param modelPath A unique identifier for the model to be saved. Must be a - * non-empty string. - * @returns An instance of `IOHandler`, which can be used with, e.g., - * `tf.Model.save`. - */ - function browserLocalStorage(modelPath) { - return new BrowserLocalStorage(modelPath); - } - var BrowserLocalStorageManager = /** @class */ (function () { - function BrowserLocalStorageManager() { - assert(env().getBool('IS_BROWSER'), function () { return 'Current environment is not a web browser'; }); - assert(typeof window === 'undefined' || - typeof window.localStorage !== 'undefined', function () { return 'Current browser does not appear to support localStorage'; }); - this.LS = window.localStorage; - } - BrowserLocalStorageManager.prototype.listModels = function () { - return __awaiter(this, void 0, void 0, function () { - var out, prefix, suffix, i, key, modelPath; - return __generator(this, function (_a) { - out = {}; - prefix = PATH_PREFIX + PATH_SEPARATOR; - suffix = PATH_SEPARATOR + INFO_SUFFIX; - for (i = 0; i < this.LS.length; ++i) { - key = this.LS.key(i); - if (key.startsWith(prefix) && key.endsWith(suffix)) { - modelPath = getModelPathFromKey(key); - out[modelPath] = JSON.parse(this.LS.getItem(key)); - } - } - return [2 /*return*/, out]; - }); - }); - }; - BrowserLocalStorageManager.prototype.removeModel = function (path) { - return __awaiter(this, void 0, void 0, function () { - var keys, info; - return __generator(this, function (_a) { - path = maybeStripScheme$1(path); - keys = getModelKeys(path); - if (this.LS.getItem(keys.info) == null) { - throw new Error("Cannot find model at path '" + path + "'"); - } - info = JSON.parse(this.LS.getItem(keys.info)); - this.LS.removeItem(keys.info); - this.LS.removeItem(keys.topology); - this.LS.removeItem(keys.weightSpecs); - this.LS.removeItem(keys.weightData); - return [2 /*return*/, info]; - }); - }); - }; - return BrowserLocalStorageManager; - }()); - if (env().getBool('IS_BROWSER')) { - // Wrap the construction and registration, to guard against browsers that - // don't support Local Storage. - try { - ModelStoreManagerRegistry.registerManager(BrowserLocalStorage.URL_SCHEME, new BrowserLocalStorageManager()); - } - catch (err) { - } - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var DEFAULT_FILE_NAME_PREFIX = 'model'; - var DEFAULT_JSON_EXTENSION_NAME = '.json'; - var DEFAULT_WEIGHT_DATA_EXTENSION_NAME = '.weights.bin'; - function defer(f) { - return new Promise(function (resolve) { return setTimeout(resolve); }).then(f); - } - var BrowserDownloads = /** @class */ (function () { - function BrowserDownloads(fileNamePrefix) { - if (!env().getBool('IS_BROWSER')) { - // TODO(cais): Provide info on what IOHandlers are available under the - // current environment. - throw new Error('browserDownloads() cannot proceed because the current environment ' + - 'is not a browser.'); - } - if (fileNamePrefix.startsWith(BrowserDownloads.URL_SCHEME)) { - fileNamePrefix = fileNamePrefix.slice(BrowserDownloads.URL_SCHEME.length); - } - if (fileNamePrefix == null || fileNamePrefix.length === 0) { - fileNamePrefix = DEFAULT_FILE_NAME_PREFIX; - } - this.modelTopologyFileName = fileNamePrefix + DEFAULT_JSON_EXTENSION_NAME; - this.weightDataFileName = - fileNamePrefix + DEFAULT_WEIGHT_DATA_EXTENSION_NAME; - } - BrowserDownloads.prototype.save = function (modelArtifacts) { - return __awaiter(this, void 0, void 0, function () { - var weightsURL, weightsManifest, modelTopologyAndWeightManifest, modelTopologyAndWeightManifestURL, jsonAnchor_1, weightDataAnchor_1; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (typeof (document) === 'undefined') { - throw new Error('Browser downloads are not supported in ' + - 'this environment since `document` is not present'); - } - weightsURL = window.URL.createObjectURL(new Blob([modelArtifacts.weightData], { type: 'application/octet-stream' })); - if (!(modelArtifacts.modelTopology instanceof ArrayBuffer)) return [3 /*break*/, 1]; - throw new Error('BrowserDownloads.save() does not support saving model topology ' + - 'in binary formats yet.'); - case 1: - weightsManifest = [{ - paths: ['./' + this.weightDataFileName], - weights: modelArtifacts.weightSpecs - }]; - modelTopologyAndWeightManifest = { - modelTopology: modelArtifacts.modelTopology, - format: modelArtifacts.format, - generatedBy: modelArtifacts.generatedBy, - convertedBy: modelArtifacts.convertedBy, - weightsManifest: weightsManifest - }; - modelTopologyAndWeightManifestURL = window.URL.createObjectURL(new Blob([JSON.stringify(modelTopologyAndWeightManifest)], { type: 'application/json' })); - jsonAnchor_1 = this.jsonAnchor == null ? document.createElement('a') : - this.jsonAnchor; - jsonAnchor_1.download = this.modelTopologyFileName; - jsonAnchor_1.href = modelTopologyAndWeightManifestURL; - // Trigger downloads by evoking a click event on the download anchors. - // When multiple downloads are started synchronously, Firefox will only - // save the last one. - return [4 /*yield*/, defer(function () { return jsonAnchor_1.dispatchEvent(new MouseEvent('click')); })]; - case 2: - // Trigger downloads by evoking a click event on the download anchors. - // When multiple downloads are started synchronously, Firefox will only - // save the last one. - _a.sent(); - if (!(modelArtifacts.weightData != null)) return [3 /*break*/, 4]; - weightDataAnchor_1 = this.weightDataAnchor == null ? - document.createElement('a') : - this.weightDataAnchor; - weightDataAnchor_1.download = this.weightDataFileName; - weightDataAnchor_1.href = weightsURL; - return [4 /*yield*/, defer(function () { return weightDataAnchor_1.dispatchEvent(new MouseEvent('click')); })]; - case 3: - _a.sent(); - _a.label = 4; - case 4: return [2 /*return*/, { modelArtifactsInfo: getModelArtifactsInfoForJSON(modelArtifacts) }]; - } - }); - }); - }; - BrowserDownloads.URL_SCHEME = 'downloads://'; - return BrowserDownloads; - }()); - var BrowserFiles = /** @class */ (function () { - function BrowserFiles(files) { - if (files == null || files.length < 1) { - throw new Error("When calling browserFiles, at least 1 file is required, " + - ("but received " + files)); - } - this.files = files; - } - BrowserFiles.prototype.load = function () { - return __awaiter(this, void 0, void 0, function () { - var jsonFile, weightFiles; - var _this = this; - return __generator(this, function (_a) { - jsonFile = this.files[0]; - weightFiles = this.files.slice(1); - return [2 /*return*/, new Promise(function (resolve, reject) { - var jsonReader = new FileReader(); - jsonReader.onload = function (event) { - // tslint:disable-next-line:no-any - var modelJSON = JSON.parse(event.target.result); - var modelTopology = modelJSON.modelTopology; - if (modelTopology == null) { - reject(new Error("modelTopology field is missing from file " + jsonFile.name)); - return; - } - if (weightFiles.length === 0) { - resolve({ modelTopology: modelTopology }); - } - var weightsManifest = modelJSON.weightsManifest; - if (weightsManifest == null) { - reject(new Error("weightManifest field is missing from file " + jsonFile.name)); - return; - } - var pathToFile; - try { - pathToFile = - _this.checkManifestAndWeightFiles(weightsManifest, weightFiles); - } - catch (err) { - reject(err); - return; - } - var weightSpecs = []; - var paths = []; - var perFileBuffers = []; - weightsManifest.forEach(function (weightsGroup) { - weightsGroup.paths.forEach(function (path) { - paths.push(path); - perFileBuffers.push(null); - }); - weightSpecs.push.apply(weightSpecs, weightsGroup.weights); - }); - weightsManifest.forEach(function (weightsGroup) { - weightsGroup.paths.forEach(function (path) { - var weightFileReader = new FileReader(); - weightFileReader.onload = function (event) { - // tslint:disable-next-line:no-any - var weightData = event.target.result; - var index = paths.indexOf(path); - perFileBuffers[index] = weightData; - if (perFileBuffers.indexOf(null) === -1) { - resolve({ - modelTopology: modelTopology, - weightSpecs: weightSpecs, - weightData: concatenateArrayBuffers(perFileBuffers), - format: modelJSON.format, - generatedBy: modelJSON.generatedBy, - convertedBy: modelJSON.convertedBy, - userDefinedMetadata: modelJSON.userDefinedMetadata - }); - } - }; - weightFileReader.onerror = function (error) { - return reject("Failed to weights data from file of path '" + path + "'."); - }; - weightFileReader.readAsArrayBuffer(pathToFile[path]); - }); - }); - }; - jsonReader.onerror = function (error) { return reject("Failed to read model topology and weights manifest JSON " + - ("from file '" + jsonFile.name + "'. BrowserFiles supports loading ") + - "Keras-style tf.Model artifacts only."); }; - jsonReader.readAsText(jsonFile); - })]; - }); - }); - }; - /** - * Check the compatibility between weights manifest and weight files. - */ - BrowserFiles.prototype.checkManifestAndWeightFiles = function (manifest, files) { - var basenames = []; - var fileNames = files.map(function (file) { return basename(file.name); }); - var pathToFile = {}; - for (var _i = 0, manifest_1 = manifest; _i < manifest_1.length; _i++) { - var group = manifest_1[_i]; - group.paths.forEach(function (path) { - var pathBasename = basename(path); - if (basenames.indexOf(pathBasename) !== -1) { - throw new Error("Duplicate file basename found in weights manifest: " + - ("'" + pathBasename + "'")); - } - basenames.push(pathBasename); - if (fileNames.indexOf(pathBasename) === -1) { - throw new Error("Weight file with basename '" + pathBasename + "' is not provided."); - } - else { - pathToFile[path] = files[fileNames.indexOf(pathBasename)]; - } - }); - } - if (basenames.length !== files.length) { - throw new Error("Mismatch in the number of files in weights manifest " + - ("(" + basenames.length + ") and the number of weight files provided ") + - ("(" + files.length + ").")); - } - return pathToFile; - }; - return BrowserFiles; - }()); - var browserDownloadsRouter = function (url) { - if (!env().getBool('IS_BROWSER')) { - return null; - } - else { - if (!Array.isArray(url) && url.startsWith(BrowserDownloads.URL_SCHEME)) { - return browserDownloads(url.slice(BrowserDownloads.URL_SCHEME.length)); - } - else { - return null; - } - } - }; - IORouterRegistry.registerSaveRouter(browserDownloadsRouter); - /** - * Creates an IOHandler that triggers file downloads from the browser. - * - * The returned `IOHandler` instance can be used as model exporting methods such - * as `tf.Model.save` and supports only saving. - * - * ```js - * const model = tf.sequential(); - * model.add(tf.layers.dense( - * {units: 1, inputShape: [10], activation: 'sigmoid'})); - * const saveResult = await model.save('downloads://mymodel'); - * // This will trigger downloading of two files: - * // 'mymodel.json' and 'mymodel.weights.bin'. - * console.log(saveResult); - * ``` - * - * @param fileNamePrefix Prefix name of the files to be downloaded. For use with - * `tf.Model`, `fileNamePrefix` should follow either of the following two - * formats: - * 1. `null` or `undefined`, in which case the default file - * names will be used: - * - 'model.json' for the JSON file containing the model topology and - * weights manifest. - * - 'model.weights.bin' for the binary file containing the binary weight - * values. - * 2. A single string or an Array of a single string, as the file name prefix. - * For example, if `'foo'` is provided, the downloaded JSON - * file and binary weights file will be named 'foo.json' and - * 'foo.weights.bin', respectively. - * @param config Additional configuration for triggering downloads. - * @returns An instance of `BrowserDownloads` `IOHandler`. - */ - /** - * @doc { - * heading: 'Models', - * subheading: 'Loading', - * namespace: 'io', - * ignoreCI: true - * } - */ - function browserDownloads(fileNamePrefix) { - if (fileNamePrefix === void 0) { fileNamePrefix = 'model'; } - return new BrowserDownloads(fileNamePrefix); - } - /** - * Creates an IOHandler that loads model artifacts from user-selected files. - * - * This method can be used for loading from files such as user-selected files - * in the browser. - * When used in conjunction with `tf.loadLayersModel`, an instance of - * `tf.LayersModel` (Keras-style) can be constructed from the loaded artifacts. - * - * ```js - * // Note: This code snippet won't run properly without the actual file input - * // elements in the HTML DOM. - * - * // Suppose there are two HTML file input (``) - * // elements. - * const uploadJSONInput = document.getElementById('upload-json'); - * const uploadWeightsInput = document.getElementById('upload-weights'); - * const model = await tf.loadLayersModel(tf.io.browserFiles( - * [uploadJSONInput.files[0], uploadWeightsInput.files[0]])); - * ``` - * - * @param files `File`s to load from. Currently, this function supports only - * loading from files that contain Keras-style models (i.e., `tf.Model`s), for - * which an `Array` of `File`s is expected (in that order): - * - A JSON file containing the model topology and weight manifest. - * - Optionally, One or more binary files containing the binary weights. - * These files must have names that match the paths in the `weightsManifest` - * contained by the aforementioned JSON file, or errors will be thrown - * during loading. These weights files have the same format as the ones - * generated by `tensorflowjs_converter` that comes with the `tensorflowjs` - * Python PIP package. If no weights files are provided, only the model - * topology will be loaded from the JSON file above. - * @returns An instance of `Files` `IOHandler`. - */ - /** - * @doc { - * heading: 'Models', - * subheading: 'Loading', - * namespace: 'io', - * ignoreCI: true - * } - */ - function browserFiles(files) { - return new BrowserFiles(files); - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Monitor Promise.all progress, fire onProgress callback function. - * - * @param promises Promise list going to be monitored - * @param onProgress Callback function. Fired when a promise resolved. - * @param startFraction Optional fraction start. Default to 0. - * @param endFraction Optional fraction end. Default to 1. - */ - function monitorPromisesProgress(promises, onProgress, startFraction, endFraction) { - checkPromises(promises); - startFraction = startFraction == null ? 0 : startFraction; - endFraction = endFraction == null ? 1 : endFraction; - checkFraction(startFraction, endFraction); - var resolvedPromise = 0; - var registerMonitor = function (promise) { - promise.then(function (value) { - var fraction = startFraction + - ++resolvedPromise / promises.length * (endFraction - startFraction); - // pass fraction as parameter to callback function. - onProgress(fraction); - return value; - }); - return promise; - }; - function checkPromises(promises) { - assert(promises != null && Array.isArray(promises) && promises.length > 0, function () { return 'promises must be a none empty array'; }); - } - function checkFraction(startFraction, endFraction) { - assert(startFraction >= 0 && startFraction <= 1, function () { return "Progress fraction must be in range [0, 1], but " + - ("got startFraction " + startFraction); }); - assert(endFraction >= 0 && endFraction <= 1, function () { return "Progress fraction must be in range [0, 1], but " + - ("got endFraction " + endFraction); }); - assert(endFraction >= startFraction, function () { return "startFraction must be no more than endFraction, but " + - ("got startFraction " + startFraction + " and endFraction ") + - ("" + endFraction); }); - } - return Promise.all(promises.map(registerMonitor)); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Reads binary weights data from a number of URLs. - * - * @param fetchURLs URLs to send the HTTP requests at, using `fetch` calls. - * @param requestOptions RequestInit (options) for the HTTP requests. - * @param fetchFunc Optional overriding value for the `window.fetch` function. - * @param onProgress Optional, progress callback function, fired periodically - * before the load is completed. - * @returns A `Promise` of an Array of `ArrayBuffer`. The Array has the same - * length as `fetchURLs`. - */ - function loadWeightsAsArrayBuffer(fetchURLs, loadOptions) { - return __awaiter(this, void 0, void 0, function () { - var fetchFunc, requests, fetchStartFraction, fetchEndFraction, responses, _a, bufferPromises, bufferStartFraction, bufferEndFraction, buffers, _b; - return __generator(this, function (_c) { - switch (_c.label) { - case 0: - if (loadOptions == null) { - loadOptions = {}; - } - fetchFunc = loadOptions.fetchFunc == null ? env().platform.fetch : - loadOptions.fetchFunc; - requests = fetchURLs.map(function (fetchURL) { - return fetchFunc(fetchURL, loadOptions.requestInit, { isBinary: true }); - }); - fetchStartFraction = 0; - fetchEndFraction = 0.5; - if (!(loadOptions.onProgress == null)) return [3 /*break*/, 2]; - return [4 /*yield*/, Promise.all(requests)]; - case 1: - _a = _c.sent(); - return [3 /*break*/, 4]; - case 2: return [4 /*yield*/, monitorPromisesProgress(requests, loadOptions.onProgress, fetchStartFraction, fetchEndFraction)]; - case 3: - _a = _c.sent(); - _c.label = 4; - case 4: - responses = _a; - bufferPromises = responses.map(function (response) { return response.arrayBuffer(); }); - bufferStartFraction = 0.5; - bufferEndFraction = 1; - if (!(loadOptions.onProgress == null)) return [3 /*break*/, 6]; - return [4 /*yield*/, Promise.all(bufferPromises)]; - case 5: - _b = _c.sent(); - return [3 /*break*/, 8]; - case 6: return [4 /*yield*/, monitorPromisesProgress(bufferPromises, loadOptions.onProgress, bufferStartFraction, bufferEndFraction)]; - case 7: - _b = _c.sent(); - _c.label = 8; - case 8: - buffers = _b; - return [2 /*return*/, buffers]; - } - }); - }); - } - /** - * Reads a weights manifest JSON configuration, fetches the weights and - * returns them as `Tensor`s. - * - * @param manifest The weights manifest JSON. - * @param filePathPrefix The path prefix for filenames given in the manifest. - * Defaults to the empty string. - * @param weightNames The names of the weights to be fetched. - */ - function loadWeights(manifest, filePathPrefix, weightNames, requestInit) { - if (filePathPrefix === void 0) { filePathPrefix = ''; } - return __awaiter(this, void 0, void 0, function () { - var fetchWeights, loadWeights; - return __generator(this, function (_a) { - fetchWeights = function (fetchUrls) { - return loadWeightsAsArrayBuffer(fetchUrls, { requestInit: requestInit }); - }; - loadWeights = weightsLoaderFactory(fetchWeights); - return [2 /*return*/, loadWeights(manifest, filePathPrefix, weightNames)]; - }); - }); - } - /** - * Creates a function, which reads a weights manifest JSON configuration, - * fetches the weight files using the specified function and returns them as - * `Tensor`s. - * - * ```js - * // example for creating a nodejs weight loader, which reads the weight files - * // from disk using fs.readFileSync - * - * import * as fs from 'fs' - * - * const fetchWeightsFromDisk = (filePaths: string[]) => - * filePaths.map(filePath => fs.readFileSync(filePath).buffer) - * - * const loadWeights = tf.io.weightsLoaderFactory(fetchWeightsFromDisk) - * - * const manifest = JSON.parse( - * fs.readFileSync('./my_model-weights_manifest').toString() - * ) - * const weightMap = await loadWeights(manifest, './') - * ``` - * @param fetchWeightsFunction The function used for fetching the weight files. - * @returns Weight loading function. - */ - function weightsLoaderFactory(fetchWeightsFunction) { - var _this = this; - return function (manifest, filePathPrefix, weightNames) { - if (filePathPrefix === void 0) { filePathPrefix = ''; } - return __awaiter(_this, void 0, void 0, function () { - var groupIndicesToFetchMap, groupWeightsToFetch, weightsFound, allManifestWeightNames, weightsNotFound, groupIndicesToFetch, fetchUrls, buffers, weightsTensorMap, bufferIndexOffset; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - groupIndicesToFetchMap = manifest.map(function () { return false; }); - groupWeightsToFetch = {}; - weightsFound = weightNames != null ? weightNames.map(function () { return false; }) : []; - allManifestWeightNames = []; - manifest.forEach(function (manifestGroupConfig, groupIndex) { - var groupOffset = 0; - manifestGroupConfig.weights.forEach(function (weightsEntry) { - var rawDtype = ('quantization' in weightsEntry) ? - weightsEntry.quantization.dtype : - weightsEntry.dtype; - var weightsBytes = DTYPE_VALUE_SIZE_MAP[rawDtype] * - sizeFromShape(weightsEntry.shape); - var enqueueWeightsForFetchingFn = function () { - groupIndicesToFetchMap[groupIndex] = true; - if (groupWeightsToFetch[groupIndex] == null) { - groupWeightsToFetch[groupIndex] = []; - } - groupWeightsToFetch[groupIndex].push({ - manifestEntry: weightsEntry, - groupOffset: groupOffset, - sizeBytes: weightsBytes - }); - }; - if (weightNames != null) { - weightNames.forEach(function (weightName, weightIndex) { - if (weightName === weightsEntry.name) { - enqueueWeightsForFetchingFn(); - weightsFound[weightIndex] = true; - } - }); - } - else { - enqueueWeightsForFetchingFn(); - } - allManifestWeightNames.push(weightsEntry.name); - groupOffset += weightsBytes; - }); - }); - if (!weightsFound.every(function (found) { return found; })) { - weightsNotFound = weightNames.filter(function (_, i) { return !weightsFound[i]; }); - throw new Error("Could not find weights in manifest with names: " + - (weightsNotFound.join(', ') + ". \n") + - "Manifest JSON has weights with names: " + - (allManifestWeightNames.join(', ') + ".")); - } - groupIndicesToFetch = groupIndicesToFetchMap.reduce(function (accumulator, shouldFetch, i) { - if (shouldFetch) { - accumulator.push(i); - } - return accumulator; - }, []); - fetchUrls = []; - groupIndicesToFetch.forEach(function (i) { - manifest[i].paths.forEach(function (filepath) { - var fetchUrl = filePathPrefix + - (!filePathPrefix.endsWith('/') ? '/' : '') + filepath; - fetchUrls.push(fetchUrl); - }); - }); - return [4 /*yield*/, fetchWeightsFunction(fetchUrls)]; - case 1: - buffers = _a.sent(); - weightsTensorMap = {}; - bufferIndexOffset = 0; - groupIndicesToFetch.forEach(function (i) { - var numBuffers = manifest[i].paths.length; - var groupBytes = 0; - for (var i_1 = 0; i_1 < numBuffers; i_1++) { - groupBytes += buffers[bufferIndexOffset + i_1].byteLength; - } - // Create a buffer for the whole group. - var groupBuffer = new ArrayBuffer(groupBytes); - var groupByteBuffer = new Uint8Array(groupBuffer); - var groupBufferOffset = 0; - for (var i_2 = 0; i_2 < numBuffers; i_2++) { - var buffer = new Uint8Array(buffers[bufferIndexOffset + i_2]); - groupByteBuffer.set(buffer, groupBufferOffset); - groupBufferOffset += buffer.byteLength; - } - var weightsEntries = groupWeightsToFetch[i]; - weightsEntries.forEach(function (weightsEntry) { - var byteBuffer = groupBuffer.slice(weightsEntry.groupOffset, weightsEntry.groupOffset + weightsEntry.sizeBytes); - var nameToTensorMap = decodeWeights(byteBuffer, [weightsEntry.manifestEntry]); - for (var name_1 in nameToTensorMap) { - weightsTensorMap[name_1] = nameToTensorMap[name_1]; - } - }); - bufferIndexOffset += numBuffers; - }); - return [2 /*return*/, weightsTensorMap]; - } - }); - }); - }; - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var OCTET_STREAM_MIME_TYPE = 'application/octet-stream'; - var JSON_TYPE = 'application/json'; - var HTTPRequest = /** @class */ (function () { - function HTTPRequest(path, loadOptions) { - this.DEFAULT_METHOD = 'POST'; - if (loadOptions == null) { - loadOptions = {}; - } - this.weightPathPrefix = loadOptions.weightPathPrefix; - this.onProgress = loadOptions.onProgress; - if (loadOptions.fetchFunc != null) { - assert(typeof loadOptions.fetchFunc === 'function', function () { return 'Must pass a function that matches the signature of ' + - '`fetch` (see ' + - 'https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)'; }); - this.fetch = loadOptions.fetchFunc; - } - else { - this.fetch = env().platform.fetch; - } - assert(path != null && path.length > 0, function () { return 'URL path for http must not be null, undefined or ' + - 'empty.'; }); - if (Array.isArray(path)) { - assert(path.length === 2, function () { return 'URL paths for http must have a length of 2, ' + - ("(actual length is " + path.length + ")."); }); - } - this.path = path; - if (loadOptions.requestInit != null && - loadOptions.requestInit.body != null) { - throw new Error('requestInit is expected to have no pre-existing body, but has one.'); - } - this.requestInit = loadOptions.requestInit || {}; - } - HTTPRequest.prototype.save = function (modelArtifacts) { - return __awaiter(this, void 0, void 0, function () { - var init, weightsManifest, modelTopologyAndWeightManifest, response; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (modelArtifacts.modelTopology instanceof ArrayBuffer) { - throw new Error('BrowserHTTPRequest.save() does not support saving model topology ' + - 'in binary formats yet.'); - } - init = Object.assign({ method: this.DEFAULT_METHOD }, this.requestInit); - init.body = new FormData(); - weightsManifest = [{ - paths: ['./model.weights.bin'], - weights: modelArtifacts.weightSpecs, - }]; - modelTopologyAndWeightManifest = { - modelTopology: modelArtifacts.modelTopology, - format: modelArtifacts.format, - generatedBy: modelArtifacts.generatedBy, - convertedBy: modelArtifacts.convertedBy, - userDefinedMetadata: modelArtifacts.userDefinedMetadata, - weightsManifest: weightsManifest - }; - init.body.append('model.json', new Blob([JSON.stringify(modelTopologyAndWeightManifest)], { type: JSON_TYPE }), 'model.json'); - if (modelArtifacts.weightData != null) { - init.body.append('model.weights.bin', new Blob([modelArtifacts.weightData], { type: OCTET_STREAM_MIME_TYPE }), 'model.weights.bin'); - } - return [4 /*yield*/, this.fetch(this.path, init)]; - case 1: - response = _a.sent(); - if (response.ok) { - return [2 /*return*/, { - modelArtifactsInfo: getModelArtifactsInfoForJSON(modelArtifacts), - responses: [response], - }]; - } - else { - throw new Error("BrowserHTTPRequest.save() failed due to HTTP response status " + - (response.status + ".")); - } - } - }); - }); - }; - /** - * Load model artifacts via HTTP request(s). - * - * See the documentation to `tf.io.http` for details on the saved - * artifacts. - * - * @returns The loaded model artifacts (if loading succeeds). - */ - HTTPRequest.prototype.load = function () { - return __awaiter(this, void 0, void 0, function () { - var modelConfigRequest, modelConfig, e_1, message, modelTopology, weightsManifest, generatedBy, convertedBy, format, userDefinedMetadata, weightSpecs, weightData, results; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, this.fetch(this.path, this.requestInit)]; - case 1: - modelConfigRequest = _a.sent(); - if (!modelConfigRequest.ok) { - throw new Error("Request to " + this.path + " failed with status code " + - (modelConfigRequest.status + ". Please verify this URL points to ") + - "the model JSON of the model to load."); - } - _a.label = 2; - case 2: - _a.trys.push([2, 4, , 5]); - return [4 /*yield*/, modelConfigRequest.json()]; - case 3: - modelConfig = _a.sent(); - return [3 /*break*/, 5]; - case 4: - e_1 = _a.sent(); - message = "Failed to parse model JSON of response from " + this.path + "."; - // TODO(nsthorat): Remove this after some time when we're comfortable that - // .pb files are mostly gone. - if (this.path.endsWith('.pb')) { - message += ' Your path contains a .pb file extension. ' + - 'Support for .pb models have been removed in TensorFlow.js 1.0 ' + - 'in favor of .json models. You can re-convert your Python ' + - 'TensorFlow model using the TensorFlow.js 1.0 conversion scripts ' + - 'or you can convert your.pb models with the \'pb2json\'' + - 'NPM script in the tensorflow/tfjs-converter repository.'; - } - else { - message += ' Please make sure the server is serving valid ' + - 'JSON for this request.'; - } - throw new Error(message); - case 5: - modelTopology = modelConfig.modelTopology; - weightsManifest = modelConfig.weightsManifest; - generatedBy = modelConfig.generatedBy; - convertedBy = modelConfig.convertedBy; - format = modelConfig.format; - userDefinedMetadata = modelConfig.userDefinedMetadata; - // We do not allow both modelTopology and weightsManifest to be missing. - if (modelTopology == null && weightsManifest == null) { - throw new Error("The JSON from HTTP path " + this.path + " contains neither model " + - "topology or manifest for weights."); - } - if (!(weightsManifest != null)) return [3 /*break*/, 7]; - return [4 /*yield*/, this.loadWeights(weightsManifest)]; - case 6: - results = _a.sent(); - weightSpecs = results[0], weightData = results[1]; - _a.label = 7; - case 7: return [2 /*return*/, { - modelTopology: modelTopology, - weightSpecs: weightSpecs, - weightData: weightData, - userDefinedMetadata: userDefinedMetadata, - generatedBy: generatedBy, - convertedBy: convertedBy, - format: format - }]; - } - }); - }); - }; - HTTPRequest.prototype.loadWeights = function (weightsManifest) { - return __awaiter(this, void 0, void 0, function () { - var weightPath, _a, prefix, suffix, pathPrefix, weightSpecs, _i, weightsManifest_1, entry, fetchURLs, buffers; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: - weightPath = Array.isArray(this.path) ? this.path[1] : this.path; - _a = parseUrl(weightPath), prefix = _a[0], suffix = _a[1]; - pathPrefix = this.weightPathPrefix || prefix; - weightSpecs = []; - for (_i = 0, weightsManifest_1 = weightsManifest; _i < weightsManifest_1.length; _i++) { - entry = weightsManifest_1[_i]; - weightSpecs.push.apply(weightSpecs, entry.weights); - } - fetchURLs = []; - weightsManifest.forEach(function (weightsGroup) { - weightsGroup.paths.forEach(function (path) { - fetchURLs.push(pathPrefix + path + suffix); - }); - }); - return [4 /*yield*/, loadWeightsAsArrayBuffer(fetchURLs, { - requestInit: this.requestInit, - fetchFunc: this.fetch, - onProgress: this.onProgress - })]; - case 1: - buffers = _b.sent(); - return [2 /*return*/, [weightSpecs, concatenateArrayBuffers(buffers)]]; - } - }); - }); - }; - HTTPRequest.URL_SCHEME_REGEX = /^https?:\/\//; - return HTTPRequest; - }()); - /** - * Extract the prefix and suffix of the url, where the prefix is the path before - * the last file, and suffix is the search params after the last file. - * ``` - * const url = 'http://tfhub.dev/model/1/tensorflowjs_model.pb?tfjs-format=file' - * [prefix, suffix] = parseUrl(url) - * // prefix = 'http://tfhub.dev/model/1/' - * // suffix = '?tfjs-format=file' - * ``` - * @param url the model url to be parsed. - */ - function parseUrl(url) { - var lastSlash = url.lastIndexOf('/'); - var lastSearchParam = url.lastIndexOf('?'); - var prefix = url.substring(0, lastSlash); - var suffix = lastSearchParam > lastSlash ? url.substring(lastSearchParam) : ''; - return [prefix + '/', suffix]; - } - function isHTTPScheme(url) { - return url.match(HTTPRequest.URL_SCHEME_REGEX) != null; - } - var httpRouter = function (url, loadOptions) { - if (typeof fetch === 'undefined' && - (loadOptions == null || loadOptions.fetchFunc == null)) { - // `http` uses `fetch` or `node-fetch`, if one wants to use it in - // an environment that is not the browser or node they have to setup a - // global fetch polyfill. - return null; - } - else { - var isHTTP = true; - if (Array.isArray(url)) { - isHTTP = url.every(function (urlItem) { return isHTTPScheme(urlItem); }); - } - else { - isHTTP = isHTTPScheme(url); - } - if (isHTTP) { - return http(url, loadOptions); - } - } - return null; - }; - IORouterRegistry.registerSaveRouter(httpRouter); - IORouterRegistry.registerLoadRouter(httpRouter); - /** - * Creates an IOHandler subtype that sends model artifacts to HTTP server. - * - * An HTTP request of the `multipart/form-data` mime type will be sent to the - * `path` URL. The form data includes artifacts that represent the topology - * and/or weights of the model. In the case of Keras-style `tf.Model`, two - * blobs (files) exist in form-data: - * - A JSON file consisting of `modelTopology` and `weightsManifest`. - * - A binary weights file consisting of the concatenated weight values. - * These files are in the same format as the one generated by - * [tfjs_converter](https://js.tensorflow.org/tutorials/import-keras.html). - * - * The following code snippet exemplifies the client-side code that uses this - * function: - * - * ```js - * const model = tf.sequential(); - * model.add( - * tf.layers.dense({units: 1, inputShape: [100], activation: 'sigmoid'})); - * - * const saveResult = await model.save(tf.io.http( - * 'http://model-server:5000/upload', {requestInit: {method: 'PUT'}})); - * console.log(saveResult); - * ``` - * - * If the default `POST` method is to be used, without any custom parameters - * such as headers, you can simply pass an HTTP or HTTPS URL to `model.save`: - * - * ```js - * const saveResult = await model.save('http://model-server:5000/upload'); - * ``` - * - * The following GitHub Gist - * https://gist.github.com/dsmilkov/1b6046fd6132d7408d5257b0976f7864 - * implements a server based on [flask](https://github.com/pallets/flask) that - * can receive the request. Upon receiving the model artifacts via the requst, - * this particular server reconsistutes instances of [Keras - * Models](https://keras.io/models/model/) in memory. - * - * - * @param path A URL path to the model. - * Can be an absolute HTTP path (e.g., - * 'http://localhost:8000/model-upload)') or a relative path (e.g., - * './model-upload'). - * @param requestInit Request configurations to be used when sending - * HTTP request to server using `fetch`. It can contain fields such as - * `method`, `credentials`, `headers`, `mode`, etc. See - * https://developer.mozilla.org/en-US/docs/Web/API/Request/Request - * for more information. `requestInit` must not have a body, because the - * body will be set by TensorFlow.js. File blobs representing the model - * topology (filename: 'model.json') and the weights of the model (filename: - * 'model.weights.bin') will be appended to the body. If `requestInit` has a - * `body`, an Error will be thrown. - * @param loadOptions Optional configuration for the loading. It includes the - * following fields: - * - weightPathPrefix Optional, this specifies the path prefix for weight - * files, by default this is calculated from the path param. - * - fetchFunc Optional, custom `fetch` function. E.g., in Node.js, - * the `fetch` from node-fetch can be used here. - * - onProgress Optional, progress callback function, fired periodically - * before the load is completed. - * @returns An instance of `IOHandler`. - */ - /** - * @doc { - * heading: 'Models', - * subheading: 'Loading', - * namespace: 'io', - * ignoreCI: true - * } - */ - function http(path, loadOptions) { - return new HTTPRequest(path, loadOptions); - } - /** - * Deprecated. Use `tf.io.http`. - * @param path - * @param loadOptions - */ - function browserHTTPRequest(path, loadOptions) { - return http(path, loadOptions); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var PassthroughLoader = /** @class */ (function () { - function PassthroughLoader(modelArtifacts) { - this.modelArtifacts = modelArtifacts; - } - PassthroughLoader.prototype.load = function () { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.modelArtifacts]; - }); - }); - }; - return PassthroughLoader; - }()); - var PassthroughSaver = /** @class */ (function () { - function PassthroughSaver(saveHandler) { - this.saveHandler = saveHandler; - } - PassthroughSaver.prototype.save = function (modelArtifacts) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - return [2 /*return*/, this.saveHandler(modelArtifacts)]; - }); - }); - }; - return PassthroughSaver; - }()); - /** - * Creates an IOHandler that loads model artifacts from memory. - * - * When used in conjunction with `tf.loadLayersModel`, an instance of - * `tf.LayersModel` (Keras-style) can be constructed from the loaded artifacts. - * - * ```js - * const model = await tf.loadLayersModel(tf.io.fromMemory( - * modelTopology, weightSpecs, weightData)); - * ``` - * - * @param modelArtifacts a object containing model topology (i.e., parsed from - * the JSON format). - * @param weightSpecs An array of `WeightsManifestEntry` objects describing the - * names, shapes, types, and quantization of the weight data. - * @param weightData A single `ArrayBuffer` containing the weight data, - * concatenated in the order described by the weightSpecs. - * @param trainingConfig Model training configuration. Optional. - * - * @returns A passthrough `IOHandler` that simply loads the provided data. - */ - function fromMemory(modelArtifacts, weightSpecs, weightData, trainingConfig) { - if (arguments.length === 1) { - var isModelArtifacts = modelArtifacts.modelTopology != null || - modelArtifacts.weightSpecs != null; - if (isModelArtifacts) { - return new PassthroughLoader(modelArtifacts); - } - else { - // Legacy support: with only modelTopology. - // TODO(cais): Remove this deprecated API. - console.warn('Please call tf.io.fromMemory() with only one argument. ' + - 'The argument should be of type ModelArtifacts. ' + - 'The multi-argument signature of tf.io.fromMemory() has been ' + - 'deprecated and will be removed in a future release.'); - return new PassthroughLoader({ modelTopology: modelArtifacts }); - } - } - else { - // Legacy support. - // TODO(cais): Remove this deprecated API. - console.warn('Please call tf.io.fromMemory() with only one argument. ' + - 'The argument should be of type ModelArtifacts. ' + - 'The multi-argument signature of tf.io.fromMemory() has been ' + - 'deprecated and will be removed in a future release.'); - return new PassthroughLoader({ - modelTopology: modelArtifacts, - weightSpecs: weightSpecs, - weightData: weightData, - trainingConfig: trainingConfig - }); - } - } - /** - * Creates an IOHandler that passes saved model artifacts to a callback. - * - * ```js - * function handleSave(artifacts) { - * // ... do something with the artifacts ... - * return {modelArtifactsInfo: {...}, ...}; - * } - * - * const saveResult = model.save(tf.io.withSaveHandler(handleSave)); - * ``` - * - * @param saveHandler A function that accepts a `ModelArtifacts` and returns a - * `SaveResult`. - */ - function withSaveHandler(saveHandler) { - return new PassthroughSaver(saveHandler); - } - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - - var io = { - __proto__: null, - browserFiles: browserFiles, - browserHTTPRequest: browserHTTPRequest, - concatenateArrayBuffers: concatenateArrayBuffers, - decodeWeights: decodeWeights, - encodeWeights: encodeWeights, - fromMemory: fromMemory, - getLoadHandlers: getLoadHandlers, - getModelArtifactsInfoForJSON: getModelArtifactsInfoForJSON, - getSaveHandlers: getSaveHandlers, - http: http, - isHTTPScheme: isHTTPScheme, - loadWeights: loadWeights, - registerLoadRouter: registerLoadRouter, - registerSaveRouter: registerSaveRouter, - weightsLoaderFactory: weightsLoaderFactory, - withSaveHandler: withSaveHandler, - copyModel: copyModel, - listModels: listModels, - moveModel: moveModel, - removeModel: removeModel - }; - - /** - * @license - * Copyright 2020 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates a one-hot `tf.Tensor`. The locations represented by `indices` take - * value `onValue` (defaults to 1), while all other locations take value - * `offValue` (defaults to 0). If `indices` is rank `R`, the output has rank - * `R+1` with the last axis of size `depth`. - * - * ```js - * tf.oneHot(tf.tensor1d([0, 1], 'int32'), 3).print(); - * ``` - * - * @param indices `tf.Tensor` of indices with dtype `int32`. - * @param depth The depth of the one hot dimension. - * @param onValue A number used to fill in the output when the index matches - * the location. - * @param offValue A number used to fill in the output when the index does - * not match the location. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function oneHot_(indices, depth, onValue, offValue) { - if (onValue === void 0) { onValue = 1; } - if (offValue === void 0) { offValue = 0; } - if (depth < 2) { - throw new Error("Error in oneHot: depth must be >=2, but it is " + depth); - } - var $indices = convertToTensor(indices, 'indices', 'oneHot', 'int32'); - var outShape = $indices.shape.concat([depth]); - var forward = function (backend, save) { - save([$indices]); - return reshape(backend.oneHot($indices.flatten(), depth, onValue, offValue), outShape); - }; - var inputs = { indices: $indices }; - var attrs = { depth: depth, onValue: onValue, offValue: offValue }; - return ENGINE.runKernelFunc(forward, inputs, null /* grad */, OneHot, attrs); - } - var oneHot = op({ oneHot_: oneHot_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Computes the confusion matrix from true labels and predicted labels. - * - * ```js - * const labels = tf.tensor1d([0, 1, 2, 1, 0], 'int32'); - * const predictions = tf.tensor1d([0, 2, 2, 1, 0], 'int32'); - * const numClasses = 3; - * const out = tf.math.confusionMatrix(labels, predictions, numClasses); - * out.print(); - * // Expected output matrix: - * // [[2, 0, 0], - * // [0, 1, 1], - * // [0, 0, 1]] - * ``` - * - * @param labels The target labels, assumed to be 0-based integers - * for the classes. The shape is `[numExamples]`, where - * `numExamples` is the number of examples included. - * @param predictions The predicted classes, assumed to be - * 0-based integers for the classes. Must have the same shape as `labels`. - * @param numClasses Number of all classes, as an integer. - * Its value must be larger than the largest element in `labels` and - * `predictions`. - * @returns The confusion matrix as a int32-type 2D tensor. The value at - * row `r` and column `c` is the number of times examples of actual class - * `r` were predicted as class `c`. - */ - /** @doc {heading: 'Operations', subheading: 'Evaluation'} */ - function confusionMatrix_(labels, predictions, numClasses) { - var $labels = convertToTensor(labels, 'labels', 'confusionMatrix'); - var $predictions = convertToTensor(predictions, 'predictions', 'confusionMatrix'); - assert(numClasses == null || numClasses > 0 && Number.isInteger(numClasses), function () { return "If provided, numClasses must be a positive integer, " + - ("but got " + numClasses); }); - assert($labels.rank === 1, function () { return "Expected the rank of labels to be 1, but got " + $labels.rank; }); - assert($predictions.rank === 1, function () { return "Expected the rank of predictions to be 1, " + - ("but got " + $predictions.rank); }); - assert($labels.shape[0] === $predictions.shape[0], function () { return "Mismatch in the number of examples: " + - ($labels.shape[0] + " vs. " + $predictions.shape[0] + ". ") + - "Labels and predictions should have the same number of elements."; }); - assert(numClasses > 0 && Number.isInteger(numClasses), function () { return "numClasses is required to be a positive integer, but got " + - ("" + numClasses); }); - // TODO(cais): In the future, if oneHot supports tensors inputs for - // `numClasses`, `confusionMatrix` can make `numClasses` optional. - var oneHotLabels = oneHot($labels.asType('int32'), numClasses); - var oneHotPredictions = oneHot($predictions.asType('int32'), numClasses); - var oneHotLabelsT = oneHotLabels.transpose(); - return oneHotLabelsT.matMul(oneHotPredictions).asType('int32'); - } - var confusionMatrix = op({ confusionMatrix_: confusionMatrix_ }); - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - - var math = { - __proto__: null, - confusionMatrix: confusionMatrix - }; - - /** - * @license - * Copyright 2018 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - /** - * Creates rank-3 `tf.Tensor` with the provided values, shape and dtype. - * - * The same functionality can be achieved with `tf.tensor`, but in general - * we recommend using `tf.tensor3d` as it makes the code more readable. - * - * ```js - * // Pass a nested array. - * tf.tensor3d([[[1], [2]], [[3], [4]]]).print(); - * ``` - * ```js - * // Pass a flat array and specify a shape. - * tf.tensor3d([1, 2, 3, 4], [2, 2, 1]).print(); - * ``` - * - * @param values The values of the tensor. Can be nested array of numbers, - * or a flat array, or a `TypedArray`. - * @param shape The shape of the tensor. If not provided, it is inferred from - * `values`. - * @param dtype The data type. - */ - /** @doc {heading: 'Tensors', subheading: 'Creation'} */ - function tensor3d(values, shape, dtype) { - assertNonNull(values); - if (shape != null && shape.length !== 3) { - throw new Error('tensor3d() requires shape to have three numbers'); - } - var inferredShape = inferShape(values, dtype); - if (inferredShape.length !== 3 && inferredShape.length !== 1) { - throw new Error('tensor3d() requires values to be number[][][] or flat/TypedArray'); - } - if (inferredShape.length === 1 && shape == null) { - throw new Error('tensor3d() requires shape to be provided when `values` ' + - 'are a flat array'); - } - return makeTensor(values, shape, inferredShape, dtype); - } - - /** - * @license - * Copyright 2019 Google LLC. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================================= - */ - var fromPixels2DContext; - /** - * Creates a `tf.Tensor` from an image. - * - * ```js - * const image = new ImageData(1, 1); - * image.data[0] = 100; - * image.data[1] = 150; - * image.data[2] = 200; - * image.data[3] = 255; - * - * tf.browser.fromPixels(image).print(); - * ``` - * - * @param pixels The input image to construct the tensor from. The - * supported image types are all 4-channel. You can also pass in an image - * object with following attributes: - * `{data: Uint8Array; width: number; height: number}` - * @param numChannels The number of channels of the output tensor. A - * numChannels value less than 4 allows you to ignore channels. Defaults to - * 3 (ignores alpha channel of input image). - */ - /** @doc {heading: 'Browser', namespace: 'browser', ignoreCI: true} */ - function fromPixels_(pixels, numChannels) { - if (numChannels === void 0) { numChannels = 3; } - // Sanity checks. - if (numChannels > 4) { - throw new Error('Cannot construct Tensor with more than 4 channels from pixels.'); - } - if (pixels == null) { - throw new Error('pixels passed to tf.browser.fromPixels() can not be null'); - } - var isPixelData = false; - var isImageData = false; - var isVideo = false; - var isImage = false; - var isCanvasLike = false; - if (pixels.data instanceof Uint8Array) { - isPixelData = true; - } - else if (typeof (ImageData) !== 'undefined' && pixels instanceof ImageData) { - isImageData = true; - } - else if (typeof (HTMLVideoElement) !== 'undefined' && - pixels instanceof HTMLVideoElement) { - isVideo = true; - } - else if (typeof (HTMLImageElement) !== 'undefined' && - pixels instanceof HTMLImageElement) { - isImage = true; - // tslint:disable-next-line: no-any - } - else if (pixels.getContext != null) { - isCanvasLike = true; - } - else { - throw new Error('pixels passed to tf.browser.fromPixels() must be either an ' + - "HTMLVideoElement, HTMLImageElement, HTMLCanvasElement, ImageData " + - "in browser, or OffscreenCanvas, ImageData in webworker" + - " or {data: Uint32Array, width: number, height: number}, " + - ("but was " + pixels.constructor.name)); - } - if (isVideo) { - var HAVE_CURRENT_DATA_READY_STATE = 2; - if (isVideo && - pixels.readyState < - HAVE_CURRENT_DATA_READY_STATE) { - throw new Error('The video element has not loaded data yet. Please wait for ' + - '`loadeddata` event on the