tf-backend-wasm.js
/**
   * @license
   * Copyright 2019 Google LLC. All Rights Reserved.
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   * =============================================================================
   */
@license
Copyright 2019 Google LLC. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at



Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
@license Copyright 2019 Google LLC . All Rights Reserved . Licensed under the Apache License Version 2 . 0 ( the " License " ) ; you may not use this file except in compliance with the License . You may obtain a copy of the License at Unless required by applicable law or agreed to in writing software distributed under the License is distributed on an " AS IS " BASIS WITHOUT 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) {
      var inputs = args.inputs, backend = args.backend;
      var axis = tfjsCore.util.parseAxisParam(args.attrs.axis, inputs[0].shape)[0];
      var outShape = tfjsCore.backend_util.computeOutShape(inputs.map(function (t) { return t.shape; }), axis);
      var $inputs = inputs.filter(function (t) { return tfjsCore.util.sizeFromShape(t.shape) > 0; });
      if ($inputs.length === 1) {
          return identity({ inputs: { x: $inputs[0] }, backend: backend });
      }
      var out = backend.makeOutput(outShape, inputs[0].dtype);
      if (tfjsCore.util.sizeFromShape(outShape) === 0) {
          return out;
      }
      var shapes = $inputs.map(function (t) { return t.shape; });
      tfjsCore.backend_util.assertParamsConsistent(shapes, axis);
      if ($inputs[0].dtype === 'string') {
          var inputs2D = $inputs.map(function (t) {
              var innerSize = tfjsCore.util.sizeFromShape(t.shape.slice(axis));
              var shape = [-1, innerSize];
              return reshape({ inputs: { x: t }, backend: backend, attrs: { shape: shape } });
          });
          var inputsValShapes = inputs2D.map(function (t) {
              return { vals: backend.readSync(t.dataId), shape: t.shape };
          });
          outShape =
              tfjsCore.backend_util.computeOutShape(inputs2D.map(function (t) { return t.shape; }), 1 );
          var simplyConcat = inputs2D[0].shape[0] === 1;
          var outVals_1 = concatImpl(inputsValShapes, outShape, inputs[0].dtype, simplyConcat);
          var finalOutShape = tfjsCore.backend_util.computeOutShape($inputs.map(function (t) { return t.shape; }), axis);
          out.shape = finalOutShape;
          var outData = backend.dataIdMap.get(out.dataId);
          outData.stringBytes = tfjsCore.backend_util.fromStringArrayToUint8(outVals_1);
          inputs2D.forEach(function (t) { return backend.disposeData(t.dataId); });
          return out;
      }
      var batchDim = tfjsCore.util.sizeFromShape($inputs[0].shape.slice(0, axis));
      var sumInnerDims = 0;
      var innerDims = $inputs.map(function (input) {
          var innerDim = tfjsCore.util.sizeFromShape(input.shape.slice(axis));
          sumInnerDims += innerDim;
          return innerDim;
      });
      var inVals = $inputs.map(function (input) { return backend.typedArrayFromHeap(input); });
      var outVals = backend.typedArrayFromHeap(out);
      for (var b = 0; b < batchDim; b++) {
          var outOffset = b * sumInnerDims;
          for (var i = 0; i < inVals.length; i++) {
              var innerDim = innerDims[i];
              var inOffset = b * innerDim;
              var vals = inVals[i].subarray(inOffset, inOffset + innerDim);
              outVals.set(vals, outOffset);
              outOffset += innerDim;
          }
      }
      return out;
  }
function concat ( args ) { var inputs = args . inputs , backend = args . backend ; var axis = tfjsCore . util . parseAxisParam ( args . attrs . axis , inputs [ 0 ] . shape ) [ 0 ] ; var outShape = tfjsCore . backend_util . computeOutShape ( inputs . map ( function ( t ) { return t . shape ; } ) , axis ) ; var $inputs = inputs . filter ( function ( t ) { return tfjsCore . util . sizeFromShape ( t . shape ) > 0 ; } ) ; if ( $inputs . length === 1 ) { return identity ( { inputs : { x : $inputs [ 0 ] } , backend : backend } ) ; } var out = backend . makeOutput ( outShape , inputs [ 0 ] . dtype ) ; if ( tfjsCore . util . sizeFromShape ( outShape ) === 0 ) { return out ; } var shapes = $inputs . map ( function ( t ) { return t . shape ; } ) ; tfjsCore . backend_util . assertParamsConsistent ( shapes , axis ) ; if ( $inputs [ 0 ] . dtype === 'string' ) { var inputs2D = $inputs . map ( function ( t ) { var innerSize = tfjsCore . util . sizeFromShape ( t . shape . slice ( axis ) ) ; var shape = [ - 1 , innerSize ] ; return reshape ( { inputs : { x : t } , backend : backend , attrs : { shape : shape } } ) ; } ) ; var inputsValShapes = inputs2D . map ( function ( t ) { return { vals : backend . readSync ( t . dataId ) , shape : t . shape } ; } ) ; outShape = tfjsCore . backend_util . computeOutShape ( inputs2D . map ( function ( t ) { return t . shape ; } ) , 1 ) ; var simplyConcat = inputs2D [ 0 ] . shape [ 0 ] === 1 ; var outVals_1 = concatImpl ( inputsValShapes , outShape , inputs [ 0 ] . dtype , simplyConcat ) ; var finalOutShape = tfjsCore . backend_util . computeOutShape ( $inputs . map ( function ( t ) { return t . shape ; } ) , axis ) ; out . shape = finalOutShape ; var outData = backend . dataIdMap . get ( out . dataId ) ; outData . stringBytes = tfjsCore . backend_util . fromStringArrayToUint8 ( outVals_1 ) ; inputs2D . forEach ( function ( t ) { return backend . disposeData ( t . dataId ) ; } ) ; return out ; } var batchDim = tfjsCore . util . sizeFromShape ( $inputs [ 0 ] . shape . slice ( 0 , axis ) ) ; var sumInnerDims = 0 ; var innerDims = $inputs . map ( function ( input ) { var innerDim = tfjsCore . util . sizeFromShape ( input . shape . slice ( axis ) ) ; sumInnerDims += innerDim ; return innerDim ; } ) ; var inVals = $inputs . map ( function ( input ) { return backend . typedArrayFromHeap ( input ) ; } ) ; var outVals = backend . typedArrayFromHeap ( out ) ; for ( var b = 0 ; b < batchDim ; b ++ ) { var outOffset = b * sumInnerDims ; for ( var i = 0 ; i < inVals . length ; i ++ ) { var innerDim = innerDims [ i ] ; var inOffset = b * innerDim ; var vals = inVals [ i ] . subarray ( inOffset , inOffset + innerDim ) ; outVals . set ( vals , outOffset ) ; outOffset += innerDim ; } } return out ; }
@license
 Copyright 2019 Google LLC.
@license Copyright 2019 Google LLC .
// Keep only non-empty tensors (ignore tensors with 0 in their shape). // Any concat of n-dimensional tensors across any axis can be reduced to // a concatenation of two-dimensional tensors across the axis 1 by first // partitioning the axes of the original tensors into those less than the // axis to be concatenated and the rest. Then reshape the tensors // into a two-dimensional tensor by collapsing these two sets of axes and // concatenate the resulting matrices across the axis 1, finally reshaping // the result to have the proper shape. // Concats 2d tensors along axis=1. /* axis */