/****************************************************************************** * * * 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 IXHEAAC_BASIC_OPS32_H #define IXHEAAC_BASIC_OPS32_H static PLATFORM_INLINE WORD32 ixheaac_min32(WORD32 a, WORD32 b) { WORD32 min_val; min_val = (a < b) ? a : b; return min_val; } static PLATFORM_INLINE WORD32 ixheaac_max32(WORD32 a, WORD32 b) { WORD32 max_val; max_val = (a > b) ? a : b; return max_val; } static PLATFORM_INLINE WORD32 ixheaac_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 ixheaac_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 ixheaac_shl32_sat(WORD32 a, WORD b) { WORD32 out_val; if (a > (MAX_32 >> b)) out_val = MAX_32; else if (a < (MIN_32 >> b)) out_val = MIN_32; else out_val = a << b; return (out_val); } static PLATFORM_INLINE WORD32 ixheaac_shl32_dir(WORD32 a, WORD b) { WORD32 out_val; if (b < 0) { out_val = ixheaac_shr32(a, -b); } else { out_val = ixheaac_shl32(a, b); } return out_val; } static PLATFORM_INLINE WORD32 ixheaac_shl32_dir_sat(WORD32 a, WORD b) { WORD32 out_val; if (b < 0) { out_val = ixheaac_shr32(a, -b); } else { out_val = ixheaac_shl32_sat(a, b); } return out_val; } static PLATFORM_INLINE WORD32 ixheaac_shr32_dir(WORD32 a, WORD b) { WORD32 out_val; if (b < 0) { out_val = ixheaac_shl32(a, -b); } else { out_val = ixheaac_shr32(a, b); } return out_val; } static PLATFORM_INLINE WORD32 ixheaac_shr32_dir_sat(WORD32 a, WORD b) { WORD32 out_val; if (b < 0) { out_val = ixheaac_shl32_sat(a, -b); } else { out_val = ixheaac_shr32(a, b); } return out_val; } static PLATFORM_INLINE WORD32 ixheaac_mult16x16in32(WORD16 a, WORD16 b) { WORD32 product; product = (WORD32)a * (WORD32)b; return product; } static PLATFORM_INLINE WORD32 ixheaac_mult32x16hin32(WORD32 a, WORD32 b) { WORD32 result; WORD64 temp_result; temp_result = (WORD64)(a) * (WORD64)(b >> 16); result = (WORD32)(temp_result >> 16); return (result); } static PLATFORM_INLINE WORD32 ixheaac_mult32x16in32_sat(WORD32 a, WORD16 b) { WORD32 result; WORD64 temp_result; temp_result = (WORD64)a * (WORD64)b; if (temp_result < (WORD64)MIN_32) result = MIN_32; else if (temp_result > (WORD64)MAX_32) result = MAX_32; else result = (WORD32)(temp_result); return (result); } static PLATFORM_INLINE WORD32 ixheaac_mult16x16in32_shl(WORD16 a, WORD16 b) { WORD32 product; product = ixheaac_shl32(ixheaac_mult16x16in32(a, b), 1); return product; } static PLATFORM_INLINE WORD32 ixheaac_mult16x16in32_shl_sat(WORD16 a, WORD16 b) { WORD32 product; product = (WORD32)a * (WORD32)b; if (product != (WORD32)0x40000000L) { product = ixheaac_shl32(product, 1); } else { product = MAX_32; } return product; } static PLATFORM_INLINE WORD32 ixheaac_add32(WORD32 a, WORD32 b) { WORD32 sum; sum = (WORD32)a + (WORD32)b; return sum; } static PLATFORM_INLINE WORD32 ixheaac_sub32(WORD32 a, WORD32 b) { WORD32 diff; diff = (WORD32)a - (WORD32)b; return diff; } static PLATFORM_INLINE WORD32 ixheaac_add32_sat(WORD32 a, WORD32 b) { WORD64 sum; sum = (WORD64)a + (WORD64)b; if (sum >= MAX_32) return MAX_32; if (sum <= MIN_32) return MIN_32; return (WORD32)sum; } static PLATFORM_INLINE WORD32 ixheaac_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 ixheaac_sub32_sat(WORD32 a, WORD32 b) { WORD64 diff; diff = (WORD64)a - (WORD64)b; if (diff >= MAX_32) return MAX_32; if (diff <= MIN_32) return MIN_32; return (WORD32)diff; } static PLATFORM_INLINE WORD ixheaac_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 ixheaac_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 WORD32 ixheaac_abs32(WORD32 a) { WORD32 abs_val; abs_val = a; if (a < 0) { abs_val = -a; } return abs_val; } static PLATFORM_INLINE WORD32 ixheaac_abs32_nrm(WORD32 a) { WORD32 abs_val; abs_val = a; if (a < 0) { abs_val = ~a; } return abs_val; } static PLATFORM_INLINE WORD32 ixheaac_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 ixheaac_negate32(WORD32 a) { WORD32 neg_val; neg_val = -a; return neg_val; } static PLATFORM_INLINE WORD32 ixheaac_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 ixheaac_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; 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 = ixheaac_norm32(a); mantissa_nr = (UWORD32)a << (q_nr); q_dr = ixheaac_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 ixheaac_shr32_sat(WORD32 a, WORD32 b) { WORD32 out_val; b = ((UWORD32)(b << 24) >> 24); if (b >= 31) { if (a < 0) out_val = -1; else out_val = 0; } else if (b <= 0) { return a; } else { a = ixheaac_add32_sat(a, (1 << (b - 1))); out_val = (WORD32)a >> b; } return out_val; } static PLATFORM_INLINE WORD32 ixheaac_mac16x16in32_sat(WORD32 a, WORD16 b, WORD16 c) { WORD32 acc; acc = ixheaac_mult16x16in32(b, c); acc = ixheaac_add32_sat(a, acc); return acc; } static PLATFORM_INLINE WORD32 ixheaac_mac16x16in32_shl(WORD32 a, WORD16 b, WORD16 c) { WORD32 acc; acc = ixheaac_mult16x16in32_shl(b, c); acc = ixheaac_add32(a, acc); return acc; } static PLATFORM_INLINE WORD32 ixheaac_mac16x16in32_shl_sat(WORD32 a, WORD16 b, WORD16 c) { WORD32 acc; acc = ixheaac_mult16x16in32_shl_sat(b, c); acc = ixheaac_add32_sat(a, acc); return acc; } static PLATFORM_INLINE WORD32 ixheaac_msu16x16in32(WORD32 a, WORD16 b, WORD16 c) { WORD32 acc; acc = ixheaac_mult16x16in32(b, c); acc = ixheaac_sub32(a, acc); return acc; } #endif /* IXHEAAC_BASIC_OPS32_H */