diff options
Diffstat (limited to 'pseudocode/operators/AVG_POOL2D.tosac')
-rw-r--r-- | pseudocode/operators/AVG_POOL2D.tosac | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/pseudocode/operators/AVG_POOL2D.tosac b/pseudocode/operators/AVG_POOL2D.tosac new file mode 100644 index 0000000..f452d12 --- /dev/null +++ b/pseudocode/operators/AVG_POOL2D.tosac @@ -0,0 +1,50 @@ +// +// This confidential and proprietary software may be used only as +// authorised by a licensing agreement from ARM Limited +// (C) COPYRIGHT 2020-2024 ARM Limited +// ALL RIGHTS RESERVED +// The entire notice above must be reproduced on all authorised +// copies and copies may only be made to the extent permitted +// by a licensing agreement from ARM Limited. + +ERROR_IF(in_out_t != i8_t && input_zp != 0); // Zero point only for int8_t +ERROR_IF(in_out_t != i8_t && output_zp != 0); // Zero point only for int8_t +ERROR_IF(kernel_y < 1 || kernel_x < 1); // kernel size must be >= 1 +ERROR_IF(stride_y < 1 || stride_x < 1); +ERROR_IF(pad_top < 0 || pad_bottom < 0 || pad_left < 0 || pad_right < 0); +// Padding must be less than kernel size to avoid +// a divide-by-zero. +ERROR_IF(pad_right >= kernel_x || pad_left >= kernel_x); +ERROR_IF(pad_top >= kernel_y || pad_bottom >= kernel_y); +ERROR_IF(OH != idiv_check(IH + pad_top + pad_bottom - kernel_y, stride_y) + 1); +ERROR_IF(OW != idiv_check(IW + pad_left + pad_right - kernel_x, stride_x) + 1); + +for_each(0 <= n < N, 0 <= oy < OH, 0 <= ox < OW, 0 <= c < C ) { + in_out_t output_val; + acc_t acc = 0; + int count = 0; + index_t iy = oy * stride_y - pad_top; + index_t ix = ox * stride_x - pad_left; + for_each(0 <= ky < kernel_y, 0 <= kx < kernel_x) { + index_t y = iy + ky; + index_t x = ix + kx; + // Only values from the input tensor are used to calculate the + // average, padding does not count + if (0 <= y < IH and 0 <= x < IW) { + count++; + acc_t value = sign_extend<acc_t>(tensor_read<in_out_t>(input, [N,IH,IW,C], [n,y,x,c])); + value = apply_sub_s<acc_t>(value, sign_extend<acc_t>(input_zp)); + acc = apply_add_s<acc_t>(acc, value); + } + } + if (is_float(in_out_t)) { + output_val = acc / static_cast<in_out_t>(count); + } else { + scale_t scale = reciprocal_scale(count); + acc = apply_scale_32(acc, scale.multiplier, scale.shift, false); + acc = apply_add_s<acc_t>(acc, sign_extend<acc_t>(output_zp)); + acc = apply_clip_s<acc_t>(acc, minimum_s<in_out_t>, maximum_s<in_out_t>); + output_val = static_cast<in_out_t>(acc); + } + tensor_write<in_out_t>(output, [N,OH,OW,C], [n,oy,ox,c], output_val); +} |