1// Copyright 2021 Google LLC 2// 3// This source code is licensed under the BSD-style license found in the 4// LICENSE file in the root directory of this source tree. 5 6$assert BATCH_TILE >= 1 7#include <assert.h> 8 9#include <xnnpack/common.h> 10#include <xnnpack/math.h> 11#include <xnnpack/vcvt.h> 12 13 14$XINT8_T = {"QS8": "int8_t", "QU8": "uint8_t"}[DATATYPE] 15$MIN_F32 = "__builtin_wasm_min_f32" if WASM else "math_min_f32" 16$MAX_F32 = "__builtin_wasm_max_f32" if WASM else "math_max_f32" 17void xnn_f32_${DATATYPE.lower()}_vcvt_ukernel__${"wasm" if WASM else "scalar"}_fmagic_x${BATCH_TILE}( 18 size_t n, 19 const float* x, 20 ${XINT8_T}* y, 21 const union xnn_f32_${DATATYPE.lower()}_cvt_params params[restrict XNN_MIN_ELEMENTS(1)]) 22{ 23 assert(n != 0); 24 assert(n % sizeof(float) == 0); 25 assert(x != NULL); 26 assert(y != NULL); 27 28 const float vscale = params->scalar_fmagic.scale; 29 const float voutput_min_less_zero_point = params->scalar_fmagic.output_min_less_zero_point; 30 const float voutput_max_less_zero_point = params->scalar_fmagic.output_max_less_zero_point; 31 const float vmagic_bias = params->scalar_fmagic.magic_bias; 32 const int32_t vmagic_bias_less_zero_point = params->scalar_fmagic.magic_bias_less_zero_point; 33 34 $if BATCH_TILE > 1: 35 for (; n >= ${BATCH_TILE} * sizeof(float); n -= ${BATCH_TILE} * sizeof(float)) { 36 $for N in range(BATCH_TILE): 37 float vx${N} = x[${N}]; 38 x += ${BATCH_TILE}; 39 40 $for N in range(BATCH_TILE): 41 vx${N} *= vscale; 42 43 $for N in range(BATCH_TILE): 44 vx${N} = ${MAX_F32}(vx${N}, voutput_min_less_zero_point); 45 46 $for N in range(BATCH_TILE): 47 vx${N} = ${MIN_F32}(vx${N}, voutput_max_less_zero_point); 48 49 $for N in range(BATCH_TILE): 50 vx${N} += vmagic_bias; 51 52 $for N in range(BATCH_TILE): 53 int32_t vy${N} = (int32_t) float_as_uint32(vx${N}); 54 55 $for N in range(BATCH_TILE): 56 vy${N} -= vmagic_bias_less_zero_point; 57 58 $for N in range(BATCH_TILE): 59 y[${N}] = (${XINT8_T}) vy${N}; 60 y += ${BATCH_TILE}; 61 } 62 $if BATCH_TILE == 1: 63 do { 64 float vx = *x++; 65 vx *= vscale; 66 vx = ${MAX_F32}(vx, voutput_min_less_zero_point); 67 vx = ${MIN_F32}(vx, voutput_max_less_zero_point); 68 vx += vmagic_bias; 69 70 int32_t vy = (int32_t) float_as_uint32(vx); 71 vy -= vmagic_bias_less_zero_point; 72 73 *y++ = (${XINT8_T}) vy; 74 75 n -= sizeof(float); 76 } while (n != 0); 77 $elif BATCH_TILE == 2: 78 if XNN_UNLIKELY(n != 0) { 79 float vx = *x; 80 vx *= vscale; 81 vx = ${MAX_F32}(vx, voutput_min_less_zero_point); 82 vx = ${MIN_F32}(vx, voutput_max_less_zero_point); 83 vx += vmagic_bias; 84 85 int32_t vy = (int32_t) float_as_uint32(vx); 86 vy -= vmagic_bias_less_zero_point; 87 88 *y = (${XINT8_T}) vy; 89 } 90 $else: 91 if XNN_UNLIKELY(n != 0) { 92 do { 93 float vx = *x++; 94 vx *= vscale; 95 vx = ${MAX_F32}(vx, voutput_min_less_zero_point); 96 vx = ${MIN_F32}(vx, voutput_max_less_zero_point); 97 vx += vmagic_bias; 98 99 int32_t vy = (int32_t) float_as_uint32(vx); 100 vy -= vmagic_bias_less_zero_point; 101 102 *y++ = (${XINT8_T}) vy; 103 104 n -= sizeof(float); 105 } while (n != 0); 106 } 107} 108