/* SIMD wrapper used by polar encoder and decoder Copyright 2020 Ahmet Inan */ #pragma once #include "simd.hh" namespace CODE { template struct PolarHelper { typedef TYPE PATH; static TYPE one() { return 1; } static TYPE zero() { return 0; } static TYPE signum(TYPE v) { return (v > 0) - (v < 0); } template static TYPE quant(IN in) { return in; } static TYPE qabs(TYPE a) { return std::abs(a); } static TYPE qmin(TYPE a, TYPE b) { return std::min(a, b); } static TYPE qadd(TYPE a, TYPE b) { return a + b; } static TYPE qmul(TYPE a, TYPE b) { return a * b; } static TYPE prod(TYPE a, TYPE b) { return signum(a) * signum(b) * qmin(qabs(a), qabs(b)); } static TYPE madd(TYPE a, TYPE b, TYPE c) { return a * b + c; } }; template struct PolarHelper> { typedef SIMD TYPE; typedef VALUE PATH; typedef SIMD MAP; static TYPE one() { return vdup(1); } static TYPE zero() { return vzero(); } static TYPE signum(TYPE a) { return vsignum(a); } static TYPE qabs(TYPE a) { return vabs(a); } static TYPE qmin(TYPE a, TYPE b) { return vmin(a, b); } static TYPE qadd(TYPE a, TYPE b) { return vadd(a, b); } static TYPE qmul(TYPE a, TYPE b) { return vmul(a, b); } static TYPE prod(TYPE a, TYPE b) { return vmul(vmul(vsignum(a), vsignum(b)), vmin(vabs(a), vabs(b))); } static TYPE madd(TYPE a, TYPE b, TYPE c) { return vadd(vmul(a, b), c); } }; template struct PolarHelper> { typedef SIMD TYPE; typedef int PATH; typedef SIMD MAP; static TYPE one() { return vdup(1); } static TYPE zero() { return vzero(); } static TYPE signum(TYPE a) { return vsignum(a); } static TYPE qabs(TYPE a) { return vqabs(a); } static TYPE qadd(TYPE a, TYPE b) { return vqadd(a, b); } static TYPE qmul(TYPE a, TYPE b) { #ifdef __ARM_NEON__ return vmul(a, b); #else return vsign(a, b); #endif } static TYPE prod(TYPE a, TYPE b) { #ifdef __ARM_NEON__ return vmul(vmul(vsignum(a), vsignum(b)), vmin(vqabs(a), vqabs(b))); #else return vsign(vmin(vqabs(a), vqabs(b)), vsign(vsignum(a), b)); #endif } static TYPE madd(TYPE a, TYPE b, TYPE c) { #ifdef __ARM_NEON__ return vqadd(vmul(a, vmax(b, vdup(-127))), c); #else return vqadd(vsign(vmax(b, vdup(-127)), a), c); #endif } }; template <> struct PolarHelper { typedef int PATH; static int8_t one() { return 1; } static int8_t zero() { return 0; } static int8_t signum(int8_t v) { return (v > 0) - (v < 0); } template static int8_t quant(IN in) { return std::min(std::max(std::nearbyint(in), -128), 127); } static int8_t qabs(int8_t a) { return std::abs(std::max(a, -127)); } static int8_t qmin(int8_t a, int8_t b) { return std::min(a, b); } static int8_t qadd(int8_t a, int8_t b) { return std::min(std::max(int16_t(a) + int16_t(b), -128), 127); } static int8_t qmul(int8_t a, int8_t b) { // return std::min(std::max(int16_t(a) * int16_t(b), -128), 127); // only used for hard decision values anyway return a * b; } static int8_t prod(int8_t a, int8_t b) { return signum(a) * signum(b) * qmin(qabs(a), qabs(b)); } static int8_t madd(int8_t a, int8_t b, int8_t c) { return std::min(std::max(int16_t(a) * int16_t(b) + int16_t(c), -128), 127); } }; }