You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
466 lines
8.9 KiB
466 lines
8.9 KiB
/******************************************************************************
|
|
* *
|
|
* 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;
|
|
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 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 (sum >= MAX_32) return MAX_32;
|
|
if (sum <= MIN_32) return MIN_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 (diff >= MAX_32) return MAX_32;
|
|
if (diff <= MIN_32) return MIN_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_sat(WORD32 a, WORD16 b,
|
|
WORD16 c) {
|
|
WORD32 acc;
|
|
|
|
acc = ixheaacd_mult16x16in32(b, c);
|
|
|
|
acc = ixheaacd_add32_sat(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 |