/****************************************************************************** * * * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ***************************************************************************** * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore */ #ifndef IXHEAACD_BASIC_OPS32_H #define IXHEAACD_BASIC_OPS32_H static PLATFORM_INLINE WORD32 ixheaacd_min32(WORD32 a, WORD32 b) { WORD32 min_val; min_val = (a < b) ? a : b; return min_val; } static PLATFORM_INLINE WORD32 ixheaacd_max32(WORD32 a, WORD32 b) { WORD32 max_val; max_val = (a > b) ? a : b; return max_val; } static PLATFORM_INLINE WORD32 ixheaacd_shl32(WORD32 a, WORD b) { WORD32 out_val; b = ((UWORD32)(b << 24) >> 24); if (b > 31) out_val = 0; else out_val = (WORD32)a << b; return out_val; } static PLATFORM_INLINE WORD32 ixheaacd_shr32(WORD32 a, WORD b) { WORD32 out_val; b = ((UWORD32)(b << 24) >> 24); if (b >= 31) { if (a < 0) out_val = -1; else out_val = 0; } else { out_val = (WORD32)a >> b; } return out_val; } static PLATFORM_INLINE WORD32 ixheaacd_shl32_sat(WORD32 a, WORD b) { WORD32 out_val = a; for (; b > 0; b--) { if (a > (WORD32)0X3fffffffL) { out_val = MAX_32; break; } else if (a < (WORD32)0xc0000000L) { out_val = MIN_32; break; } a = ixheaacd_shl32(a, 1); out_val = a; } return (out_val); } static PLATFORM_INLINE WORD32 ixheaacd_shl32_dir(WORD32 a, WORD b) { WORD32 out_val; if (b < 0) { out_val = ixheaacd_shr32(a, -b); } else { out_val = ixheaacd_shl32(a, b); } return out_val; } static PLATFORM_INLINE WORD32 ixheaacd_shl32_dir_sat(WORD32 a, WORD b) { WORD32 out_val; if (b < 0) { out_val = ixheaacd_shr32(a, -b); } else { out_val = ixheaacd_shl32_sat(a, b); } return out_val; } static PLATFORM_INLINE WORD32 ixheaacd_shr32_dir(WORD32 a, WORD b) { WORD32 out_val; if (b < 0) { out_val = ixheaacd_shl32(a, -b); } else { out_val = ixheaacd_shr32(a, b); } return out_val; } static PLATFORM_INLINE WORD32 shr32_dir_sat(WORD32 a, WORD b) { WORD32 out_val; if (b < 0) { out_val = ixheaacd_shl32_sat(a, -b); } else { out_val = ixheaacd_shr32(a, b); } return out_val; } static PLATFORM_INLINE WORD32 ixheaacd_mult16x16in32(WORD16 a, WORD16 b) { WORD32 product; product = (WORD32)a * (WORD32)b; return product; } static PLATFORM_INLINE WORD32 mult16x16in32_32(WORD32 a, WORD32 b) { WORD32 product; product = (WORD32)a * (WORD32)b; return product; } static PLATFORM_INLINE WORD32 ixheaacd_mult16x16in32_shl(WORD16 a, WORD16 b) { WORD32 product; product = ixheaacd_shl32(ixheaacd_mult16x16in32(a, b), 1); return product; } static PLATFORM_INLINE WORD32 ixheaacd_mult16x16in32_shl_sat(WORD16 a, WORD16 b) { WORD32 product; product = (WORD32)a * (WORD32)b; if (product != (WORD32)0x40000000L) { product = ixheaacd_shl32(product, 1); } else { product = MAX_32; } return product; } static PLATFORM_INLINE WORD32 ixheaacd_add32(WORD32 a, WORD32 b) { WORD32 sum; sum = (WORD32)a + (WORD32)b; return sum; } static PLATFORM_INLINE WORD32 ixheaacd_sub32(WORD32 a, WORD32 b) { WORD32 diff; diff = (WORD32)a - (WORD32)b; return diff; } static PLATFORM_INLINE WORD32 ixheaacd_add32_sat(WORD32 a, WORD32 b) { WORD64 sum; sum = (WORD64)a + (WORD64)b; if ((((WORD32)a ^ (WORD32)b) & (WORD32)MIN_32) == 0) { if (((WORD32)sum ^ (WORD32)a) & (WORD32)MIN_32) { sum = (a < 0) ? MIN_32 : MAX_32; } } return (WORD32)sum; } static PLATFORM_INLINE WORD32 ixheaacd_add32_sat3(WORD32 a, WORD32 b, WORD32 c) { WORD64 sum; sum = (WORD64)a + (WORD64)b; sum = (WORD64)sum + (WORD64)c; if (sum > MAX_32) { sum = MAX_32; } if (sum < MIN_32) { sum = MIN_32; } return (WORD32)sum; } static PLATFORM_INLINE WORD32 ixheaacd_sub32_sat(WORD32 a, WORD32 b) { WORD64 diff; diff = (WORD64)a - (WORD64)b; if ((((WORD32)a ^ (WORD32)b) & (WORD32)MIN_32) != 0) { if (((WORD32)diff ^ (WORD32)a) & (WORD32)MIN_32) { diff = (a < 0L) ? MIN_32 : MAX_32; } } return (WORD32)diff; } static PLATFORM_INLINE WORD ixheaacd_norm32(WORD32 a) { WORD norm_val; if (a == 0) { norm_val = 31; } else { if (a == (WORD32)0xffffffffL) { norm_val = 31; } else { if (a < 0) { a = ~a; } for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) { a <<= 1; } } } return norm_val; } static PLATFORM_INLINE WORD ixheaacd_pnorm32(WORD32 a) { WORD norm_val; if (a == 0) { norm_val = 31; } else { for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) { a <<= 1; } } return norm_val; } static PLATFORM_INLINE WORD bin_expo32(WORD32 a) { WORD bin_expo_val; bin_expo_val = 31 - ixheaacd_norm32(a); return bin_expo_val; } static PLATFORM_INLINE WORD32 ixheaacd_abs32(WORD32 a) { WORD32 abs_val; abs_val = a; if (a < 0) { abs_val = -a; } return abs_val; } static PLATFORM_INLINE WORD32 ixheaacd_abs32_nrm(WORD32 a) { WORD32 abs_val; abs_val = a; if (a < 0) { abs_val = ~a; } return abs_val; } static PLATFORM_INLINE WORD32 ixheaacd_abs32_sat(WORD32 a) { WORD32 abs_val; abs_val = a; if (a == MIN_32) { abs_val = MAX_32; } else if (a < 0) { abs_val = -a; } return abs_val; } static PLATFORM_INLINE WORD32 ixheaacd_negate32(WORD32 a) { WORD32 neg_val; neg_val = -a; return neg_val; } static PLATFORM_INLINE WORD32 ixheaacd_negate32_sat(WORD32 a) { WORD32 neg_val; if (a == MIN_32) { neg_val = MAX_32; } else { neg_val = -a; } return neg_val; } static PLATFORM_INLINE WORD32 div32(WORD32 a, WORD32 b, WORD *q_format) { WORD32 quotient; UWORD32 mantissa_nr, mantissa_dr; WORD16 sign = 0; LOOPINDEX i; WORD q_nr, q_dr; mantissa_nr = a; mantissa_dr = b; quotient = 0; if ((a < 0) && (0 != b)) { a = -a; sign = (WORD16)(sign ^ -1); } if (b < 0) { b = -b; sign = (WORD16)(sign ^ -1); } if (0 == b) { *q_format = 0; return (a); } quotient = 0; q_nr = ixheaacd_norm32(a); mantissa_nr = (UWORD32)a << (q_nr); q_dr = ixheaacd_norm32(b); mantissa_dr = (UWORD32)b << (q_dr); *q_format = (WORD)(30 + q_nr - q_dr); for (i = 0; i < 31; i++) { quotient = quotient << 1; if (mantissa_nr >= mantissa_dr) { mantissa_nr = mantissa_nr - mantissa_dr; quotient += 1; } mantissa_nr = (UWORD32)mantissa_nr << 1; } if (sign < 0) { quotient = -quotient; } return quotient; } static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32(WORD32 a, WORD16 b, WORD16 c) { WORD32 acc; acc = ixheaacd_mult16x16in32(b, c); acc = ixheaacd_add32(a, acc); return acc; } static PLATFORM_INLINE WORD32 mac16x16hin32(WORD32 a, WORD32 b, WORD32 c) { WORD32 acc; acc = ixheaacd_mult16x16in32((WORD16)b, (WORD16)(c >> 16)); acc = ixheaacd_add32(a, acc); return acc; } static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_shl(WORD32 a, WORD16 b, WORD16 c) { WORD32 acc; acc = ixheaacd_mult16x16in32_shl(b, c); acc = ixheaacd_add32(a, acc); return acc; } static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_shl_sat(WORD32 a, WORD16 b, WORD16 c) { WORD32 acc; acc = ixheaacd_mult16x16in32_shl_sat(b, c); acc = ixheaacd_add32_sat(a, acc); return acc; } static PLATFORM_INLINE WORD32 msu16x16in32(WORD32 a, WORD16 b, WORD16 c) { WORD32 acc; acc = ixheaacd_mult16x16in32(b, c); acc = ixheaacd_sub32(a, acc); return acc; } static PLATFORM_INLINE WORD32 msu16x16in32_shl(WORD32 a, WORD16 b, WORD16 c) { WORD32 acc; acc = ixheaacd_mult16x16in32_shl(b, c); acc = ixheaacd_sub32(a, acc); return acc; } static PLATFORM_INLINE WORD32 msu16x16in32_shl_sat(WORD32 a, WORD16 b, WORD16 c) { WORD32 acc; acc = ixheaacd_mult16x16in32_shl_sat(b, c); acc = ixheaacd_sub32_sat(a, acc); return acc; } static PLATFORM_INLINE WORD32 add32_shr(WORD32 a, WORD32 b) { WORD32 sum; a = ixheaacd_shr32(a, 1); b = ixheaacd_shr32(b, 1); sum = ixheaacd_add32(a, b); return sum; } static PLATFORM_INLINE WORD32 sub32_shr(WORD32 a, WORD32 b) { WORD32 diff; a = ixheaacd_shr32(a, 1); b = ixheaacd_shr32(b, 1); diff = ixheaacd_sub32(a, b); return diff; } #endif