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] 15void xnn_f32_${DATATYPE.lower()}_vcvt_ukernel__scalar_imagic_x${BATCH_TILE}( 16 size_t n, 17 const float* x, 18 ${XINT8_T}* y, 19 const union xnn_f32_${DATATYPE.lower()}_cvt_params params[restrict XNN_MIN_ELEMENTS(1)]) 20{ 21 assert(n != 0); 22 assert(n % sizeof(float) == 0); 23 assert(x != NULL); 24 assert(y != NULL); 25 26 const float vscale = params->scalar_imagic.scale; 27 const float vmagic_bias = params->scalar_imagic.magic_bias; 28 const int32_t vmagic_min = params->scalar_imagic.magic_min; 29 const int32_t vmagic_max = params->scalar_imagic.magic_max; 30 const int32_t vmagic_bias_less_zero_point = params->scalar_imagic.magic_bias_less_zero_point; 31 32 $if BATCH_TILE > 1: 33 for (; n >= ${BATCH_TILE} * sizeof(float); n -= ${BATCH_TILE} * sizeof(float)) { 34 $for N in range(BATCH_TILE): 35 float vx${N} = x[${N}]; 36 x += ${BATCH_TILE}; 37 38 $for N in range(BATCH_TILE): 39 vx${N} *= vscale; 40 41 $for N in range(BATCH_TILE): 42 vx${N} += vmagic_bias; 43 44 $for N in range(BATCH_TILE): 45 int32_t vy${N} = (int32_t) float_as_uint32(vx${N}); 46 47 $for N in range(BATCH_TILE): 48 vy${N} = math_max_s32(vy${N}, vmagic_min); 49 50 $for N in range(BATCH_TILE): 51 vy${N} = math_min_s32(vy${N}, vmagic_max); 52 53 $for N in range(BATCH_TILE): 54 vy${N} -= vmagic_bias_less_zero_point; 55 56 $for N in range(BATCH_TILE): 57 y[${N}] = (${XINT8_T}) vy${N}; 58 y += ${BATCH_TILE}; 59 } 60 $if BATCH_TILE == 1: 61 do { 62 float vx = *x++; 63 vx *= vscale; 64 vx += vmagic_bias; 65 66 int32_t vy = (int32_t) float_as_uint32(vx); 67 vy = math_max_s32(vy, vmagic_min); 68 vy = math_min_s32(vy, vmagic_max); 69 vy -= vmagic_bias_less_zero_point; 70 71 *y++ = (${XINT8_T}) vy; 72 73 n -= sizeof(float); 74 } while (n != 0); 75 $elif BATCH_TILE == 2: 76 if XNN_UNLIKELY(n != 0) { 77 float vx = *x; 78 vx *= vscale; 79 vx += vmagic_bias; 80 81 int32_t vy = (int32_t) float_as_uint32(vx); 82 vy = math_max_s32(vy, vmagic_min); 83 vy = math_min_s32(vy, vmagic_max); 84 vy -= vmagic_bias_less_zero_point; 85 86 *y = (${XINT8_T}) vy; 87 } 88 $else: 89 if XNN_UNLIKELY(n != 0) { 90 do { 91 float vx = *x++; 92 vx *= vscale; 93 vx += vmagic_bias; 94 95 int32_t vy = (int32_t) float_as_uint32(vx); 96 vy = math_max_s32(vy, vmagic_min); 97 vy = math_min_s32(vy, vmagic_max); 98 vy -= vmagic_bias_less_zero_point; 99 100 *y++ = (${XINT8_T}) vy; 101 102 n -= sizeof(float); 103 } while (n != 0); 104 } 105} 106