(
xValues: TypedArray, xShape: number[], dtype: DataType,
convInfo: backend_util.Conv2DInfo, flattenPositions = false,
includeBatchInIndex = false)
| 87 | } |
| 88 | |
| 89 | export function maxPoolPositions( |
| 90 | xValues: TypedArray, xShape: number[], dtype: DataType, |
| 91 | convInfo: backend_util.Conv2DInfo, flattenPositions = false, |
| 92 | includeBatchInIndex = false): TensorBuffer<Rank, 'int32'> { |
| 93 | const maxPositions = buffer(convInfo.outShape, 'int32'); |
| 94 | const strideHeight = convInfo.strideHeight; |
| 95 | const strideWidth = convInfo.strideWidth; |
| 96 | const dilationHeight = convInfo.dilationHeight; |
| 97 | const dilationWidth = convInfo.dilationWidth; |
| 98 | const effectiveFilterHeight = convInfo.effectiveFilterHeight; |
| 99 | const effectiveFilterWidth = convInfo.effectiveFilterWidth; |
| 100 | const padTop = convInfo.padInfo.top; |
| 101 | const padLeft = convInfo.padInfo.left; |
| 102 | |
| 103 | const xBuf = buffer(xShape, dtype, xValues); |
| 104 | for (let b = 0; b < convInfo.batchSize; ++b) { |
| 105 | for (let d = 0; d < convInfo.inChannels; ++d) { |
| 106 | for (let yR = 0; yR < convInfo.outHeight; ++yR) { |
| 107 | const xRCorner = yR * strideHeight - padTop; |
| 108 | let xRMin = xRCorner; |
| 109 | while (xRMin < 0) { |
| 110 | xRMin += dilationHeight; |
| 111 | } |
| 112 | // const xRMin = Math.max(0, xRCorner); |
| 113 | const xRMax = |
| 114 | Math.min(convInfo.inHeight, effectiveFilterHeight + xRCorner); |
| 115 | for (let yC = 0; yC < convInfo.outWidth; ++yC) { |
| 116 | const xCCorner = yC * strideWidth - padLeft; |
| 117 | let xCMin = xCCorner; |
| 118 | while (xCMin < 0) { |
| 119 | xCMin += dilationWidth; |
| 120 | } |
| 121 | const xCMax = |
| 122 | Math.min(convInfo.inWidth, effectiveFilterWidth + xCCorner); |
| 123 | let maxValue = Number.NEGATIVE_INFINITY; |
| 124 | let maxPosition = -1; |
| 125 | |
| 126 | for (let xR = xRMin; xR < xRMax; xR += dilationHeight) { |
| 127 | const wR = xR - xRCorner; |
| 128 | for (let xC = xCMin; xC < xCMax; xC += dilationWidth) { |
| 129 | const wC = xC - xCCorner; |
| 130 | // For some reason, disable-next-line is not working |
| 131 | // TODO(mattsoulanille): Remove this when switching to TS5. |
| 132 | /* tslint:disable: no-unnecessary-type-assertion */ |
| 133 | const pixel = xBuf.get(b, xR, xC, d) as number; |
| 134 | if (pixel > maxValue) { |
| 135 | maxValue = pixel as number; |
| 136 | if (flattenPositions) { |
| 137 | maxPosition = includeBatchInIndex ? |
| 138 | ((b * convInfo.inHeight + xR) * convInfo.inWidth + xC) * |
| 139 | convInfo.inChannels + |
| 140 | d : |
| 141 | (xR * convInfo.inWidth + xC) * convInfo.inChannels + d; |
| 142 | } else { |
| 143 | maxPosition = wR * effectiveFilterWidth + wC; |
| 144 | } |
| 145 | } |
| 146 | } |
no test coverage detected
searching dependent graphs…