(convInfo: backend_util.Conv2DInfo)
| 24 | userCode: string; |
| 25 | |
| 26 | constructor(convInfo: backend_util.Conv2DInfo) { |
| 27 | this.outputShape = convInfo.outShape; |
| 28 | |
| 29 | const { |
| 30 | inHeight, |
| 31 | inWidth, |
| 32 | padInfo, |
| 33 | strideHeight, |
| 34 | strideWidth, |
| 35 | filterHeight, |
| 36 | filterWidth, |
| 37 | dilationHeight, |
| 38 | dilationWidth |
| 39 | } = convInfo; |
| 40 | |
| 41 | const {top: padTop, left: padLeft} = padInfo; |
| 42 | |
| 43 | this.userCode = ` |
| 44 | const ivec2 strides = ivec2(${strideHeight}, ${strideWidth}); |
| 45 | const ivec2 pads = ivec2(${padTop}, ${padLeft}); |
| 46 | const float neg_infinity = -3.4e38; |
| 47 | |
| 48 | void main() { |
| 49 | ivec4 coords = getOutputCoords(); |
| 50 | int batch = coords.x; |
| 51 | int d1 = coords.w; |
| 52 | ivec2 outTopLeftCorner = |
| 53 | coords.yz * strides - pads; |
| 54 | int hBeg = outTopLeftCorner.x; |
| 55 | int wBeg = outTopLeftCorner.y; |
| 56 | |
| 57 | float curVal = neg_infinity; |
| 58 | for (int h = 0; h < ${filterHeight}; h++) { |
| 59 | int hIn = hBeg + h * ${dilationHeight}; |
| 60 | |
| 61 | if (hIn >= 0 && hIn < ${inHeight}) { |
| 62 | for (int w = 0; w < ${filterWidth}; w++) { |
| 63 | int wIn = wBeg + w * ${dilationWidth}; |
| 64 | |
| 65 | if (wIn >= 0 && wIn < ${inWidth}) { |
| 66 | float xVal = getX(batch, hIn, wIn, d1); |
| 67 | float wVal = getW(h, w, d1); |
| 68 | |
| 69 | float val = xVal + wVal; |
| 70 | if (val > curVal) { |
| 71 | curVal = val; |
| 72 | } |
| 73 | } |
| 74 | } |
| 75 | } |
| 76 | } |
| 77 | |
| 78 | float result = curVal; |
| 79 | setOutput(result); |
| 80 | } |
| 81 | `; |
| 82 | } |
| 83 | } |
nothing calls this directly
no outgoing calls
no test coverage detected