license import { GPGPUProgram } from './gpgpu_math' ; export class ResizeBilinearProgram implements GPGPUProgram { variableNames = [ 'A' ] ; outputShape : number [ ] = [ ] ; userCode : string ; constructor ( inputShape , newHeight , newWidth , alignCorners , halfPixelCenters ) { const [ batch , oldHeight , oldWidth , depth ] = inputShape ; this . outputShape = [ batch , newHeight , newWidth , depth ] ; const effectiveInSize = [ ( alignCorners && newHeight > 1 ) ? oldHeight - 1 : oldHeight , ( alignCorners && newWidth > 1 ) ? oldWidth - 1 : oldWidth ] ; const effectiveOutSize = [ ( alignCorners && newHeight > 1 ) ? newHeight - 1 : newHeight , ( alignCorners && newWidth > 1 ) ? newWidth - 1 : newWidth ] ; let sourceFracIndexRC ; if ( halfPixelCenters ) { sourceFracIndexRC = `(vec2(yRC) + vec2(0.5)) * effectiveInputOverOutputRatioRC` + ` - vec2(0.5)` ; } else { sourceFracIndexRC = `vec2(yRC) * effectiveInputOverOutputRatioRC` ; } this . userCode = `
      const vec2 effectiveInputOverOutputRatioRC = vec2(
          ${ effectiveInSize [ 0 ] / effectiveOutSize [ 0 ] },
          ${ effectiveInSize [ 1 ] / effectiveOutSize [ 1 ] });
      const vec2 inputShapeRC = vec2(${ oldHeight }.0, ${ oldWidth }.0);

      void main() {
        ivec4 coords = getOutputCoords();
        int b = coords[0];
        int d = coords[3];
        ivec2 yRC = coords.yz;

        // Fractional source index.
        vec2 sourceFracIndexRC = ${ sourceFracIndexRC };

        // Compute the four integer indices.
        ivec2 sourceFloorRC = ivec2(max(sourceFracIndexRC, vec2(0.0)));
        ivec2 sourceCeilRC = ivec2(
          min(inputShapeRC - 1.0, ceil(sourceFracIndexRC)));

        float topLeft = getA(b, sourceFloorRC.x, sourceFloorRC.y, d);
        float bottomLeft = getA(b, sourceCeilRC.x, sourceFloorRC.y, d);
        float topRight = getA(b, sourceFloorRC.x, sourceCeilRC.y, d);
        float bottomRight = getA(b, sourceCeilRC.x, sourceCeilRC.y, d);

        vec2 fracRC = sourceFracIndexRC - vec2(sourceFloorRC);

        float top = topLeft + (topRight - topLeft) * fracRC.y;
        float bottom = bottomLeft + (bottomRight - bottomLeft) * fracRC.y;
        float newValue = top + (bottom - top) * fracRC.x;

        setOutput(newValue);
      }
    ` ; } }