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#include <fp16.h> 14 15 16$XINT8_T = {"QS8": "int8_t", "QU8": "uint8_t"}[DATATYPE] 17void xnn_f32_${DATATYPE.lower()}_vcvt_ukernel__scalar_imagic_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_imagic.scale; 29 const float vmagic_bias = params->scalar_imagic.magic_bias; 30 const int32_t vmagic_min = params->scalar_imagic.magic_min; 31 const int32_t vmagic_max = params->scalar_imagic.magic_max; 32 const int32_t vmagic_bias_less_zero_point = params->scalar_imagic.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} += vmagic_bias; 45 46 $for N in range(BATCH_TILE): 47 int32_t vy${N} = (int32_t) fp32_to_bits(vx${N}); 48 49 $for N in range(BATCH_TILE): 50 vy${N} = math_max_s32(vy${N}, vmagic_min); 51 52 $for N in range(BATCH_TILE): 53 vy${N} = math_min_s32(vy${N}, vmagic_max); 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 += vmagic_bias; 67 68 int32_t vy = (int32_t) fp32_to_bits(vx); 69 vy = math_max_s32(vy, vmagic_min); 70 vy = math_min_s32(vy, vmagic_max); 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 += vmagic_bias; 82 83 int32_t vy = (int32_t) fp32_to_bits(vx); 84 vy = math_max_s32(vy, vmagic_min); 85 vy = math_min_s32(vy, vmagic_max); 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 += vmagic_bias; 96 97 int32_t vy = (int32_t) fp32_to_bits(vx); 98 vy = math_max_s32(vy, vmagic_min); 99 vy = math_min_s32(vy, vmagic_max); 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