400 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			400 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
	
| /******************************************************************************
 | |
|  *                                                                            *
 | |
|  * 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_OPS40_H
 | |
| #define IXHEAACD_BASIC_OPS40_H
 | |
| #define lo64(a) (((unsigned *)&a)[0])
 | |
| #define hi64(a) (((WORD32 *)&a)[1])
 | |
| 
 | |
| static PLATFORM_INLINE WORD16 norm40(WORD40 *in) {
 | |
|   WORD16 expo;
 | |
|   WORD32 tempo;
 | |
| 
 | |
|   if (0 == (*in)) return 31;
 | |
| 
 | |
|   if (((*in) <= 0x7fffffff) && ((WORD40)(*in) >= (WORD40)0xFFFFFFFF80000000)) {
 | |
|     tempo = (WORD32)(*in);
 | |
|     expo = ixheaacd_norm32(tempo);
 | |
|     *in = tempo << expo;
 | |
| 
 | |
|     return (expo);
 | |
|   }
 | |
| 
 | |
|   tempo = (WORD32)((*in) >> 31);
 | |
|   expo = 31 - (ixheaacd_norm32(tempo));
 | |
|   *in = (*in) >> expo;
 | |
| 
 | |
|   return (-expo);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 add32_shr40(WORD32 a, WORD32 b) {
 | |
|   WORD40 sum;
 | |
| 
 | |
|   sum = (WORD40)a + (WORD40)b;
 | |
|   sum = sum >> 1;
 | |
| 
 | |
|   return ((WORD32)sum);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 sub32_shr40(WORD32 a, WORD32 b) {
 | |
|   WORD40 sum;
 | |
| 
 | |
|   sum = (WORD40)a - (WORD40)b;
 | |
|   sum = sum >> 1;
 | |
| 
 | |
|   return ((WORD32)sum);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 ixheaacd_mult32x16in32_shl(WORD32 a, WORD16 b) {
 | |
|   WORD32 result;
 | |
|   WORD64 temp_result;
 | |
| 
 | |
|   temp_result = (WORD64)a * (WORD64)b;
 | |
| 
 | |
|   result = (WORD32)(temp_result >> 16);
 | |
| 
 | |
|   return (result << 1);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 mult32x16hin32_shl(WORD32 a, WORD32 b) {
 | |
|   WORD32 product;
 | |
|   WORD64 temp_product;
 | |
| 
 | |
|   temp_product = (WORD64)a * (WORD64)(b >> 16);
 | |
|   product = (WORD32)(temp_product >> 16);
 | |
| 
 | |
|   return (product << 1);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 ixheaacd_mult32x16in32(WORD32 a, WORD16 b) {
 | |
|   WORD32 result;
 | |
|   WORD64 temp_result;
 | |
| 
 | |
|   temp_result = (WORD64)a * (WORD64)b;
 | |
| 
 | |
|   result = (WORD32)(temp_result >> 16);
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 ixheaacd_mult32x16in32_shl_sat(WORD32 a,
 | |
|                                                              WORD16 b) {
 | |
|   WORD32 result;
 | |
| 
 | |
|   if (a == (WORD32)0x80000000 && b == (WORD16)0x8000) {
 | |
|     result = (WORD32)0x7fffffff;
 | |
|   } else {
 | |
|     result = ixheaacd_mult32x16in32_shl(a, b);
 | |
|   }
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 ixheaacd_mult32_shl(WORD32 a, WORD32 b) {
 | |
|   WORD32 result;
 | |
|   WORD64 temp_result;
 | |
| 
 | |
|   temp_result = (WORD64)a * (WORD64)b;
 | |
|   result = (WORD32)(temp_result >> 32);
 | |
| 
 | |
|   return (result << 1);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 ixheaacd_mult32(WORD32 a, WORD32 b) {
 | |
|   WORD32 result;
 | |
|   WORD64 temp_result;
 | |
| 
 | |
|   temp_result = (WORD64)a * (WORD64)b;
 | |
|   result = (WORD32)(temp_result >> 32);
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 ixheaacd_mult32_shl_sat(WORD32 a, WORD32 b) {
 | |
|   WORD32 result;
 | |
| 
 | |
|   if (a == (WORD32)0x80000000 && b == (WORD32)0x80000000) {
 | |
|     result = 0x7fffffff;
 | |
|   } else {
 | |
|     result = ixheaacd_mult32_shl(a, b);
 | |
|   }
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 ixheaacd_mac32x16in32(WORD32 a, WORD32 b,
 | |
|                                                     WORD16 c) {
 | |
|   WORD32 result;
 | |
| 
 | |
|   result = a + ixheaacd_mult32x16in32(b, c);
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 ixheaacd_mac32x16in32_shl(WORD32 a, WORD32 b,
 | |
|                                                         WORD16 c) {
 | |
|   WORD32 result;
 | |
| 
 | |
|   result = a + ixheaacd_mult32x16in32_shl(b, c);
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 ixheaacd_mac32x16in32_shl_sat(WORD32 a, WORD32 b,
 | |
|                                                             WORD16 c) {
 | |
|   return (ixheaacd_add32_sat(a, ixheaacd_mult32x16in32_shl_sat(b, c)));
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 ixheaacd_mac32(WORD32 a, WORD32 b, WORD32 c) {
 | |
|   WORD32 result;
 | |
| 
 | |
|   result = a + ixheaacd_mult32(b, c);
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 mac32_shl(WORD32 a, WORD32 b, WORD32 c) {
 | |
|   WORD32 result;
 | |
| 
 | |
|   result = a + ixheaacd_mult32_shl(b, c);
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 mac32_shl_sat(WORD32 a, WORD32 b, WORD32 c) {
 | |
|   return (ixheaacd_add32_sat(a, ixheaacd_mult32_shl_sat(b, c)));
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 msu32x16in32(WORD32 a, WORD32 b, WORD16 c) {
 | |
|   WORD32 result;
 | |
| 
 | |
|   result = a - ixheaacd_mult32x16in32(b, c);
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 msu32x16in32_shl(WORD32 a, WORD32 b, WORD16 c) {
 | |
|   WORD32 result;
 | |
| 
 | |
|   result = a - ixheaacd_mult32x16in32_shl(b, c);
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 msu32x16in32_shl_sat(WORD32 a, WORD32 b,
 | |
|                                                    WORD16 c) {
 | |
|   return (ixheaacd_sub32_sat(a, ixheaacd_mult32x16in32_shl_sat(b, c)));
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 msu32(WORD32 a, WORD32 b, WORD32 c) {
 | |
|   WORD32 result;
 | |
| 
 | |
|   result = a - ixheaacd_mult32(b, c);
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 msu32_shl(WORD32 a, WORD32 b, WORD32 c) {
 | |
|   WORD32 result;
 | |
| 
 | |
|   result = a - ixheaacd_mult32_shl(b, c);
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 msu32_shl_sat(WORD32 a, WORD32 b, WORD32 c) {
 | |
|   return (ixheaacd_sub32_sat(a, ixheaacd_mult32_shl_sat(b, c)));
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 mac3216_arr40(WORD32 *x, WORD16 *y,
 | |
|                                             LOOPINDEX length, WORD16 *q_val) {
 | |
|   LOOPINDEX i;
 | |
|   WORD40 sum = 0;
 | |
| 
 | |
|   for (i = 0; i < length; i++) {
 | |
|     sum += (WORD40)(ixheaacd_mult32x16in32(x[i], y[i]));
 | |
|   }
 | |
| 
 | |
|   *q_val = norm40(&sum);
 | |
| 
 | |
|   return (WORD32)sum;
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 mac32_arr40(WORD32 *x, WORD32 *y,
 | |
|                                           LOOPINDEX length, WORD16 *q_val) {
 | |
|   LOOPINDEX i;
 | |
|   WORD40 sum = 0;
 | |
| 
 | |
|   for (i = 0; i < length; i++) {
 | |
|     sum += (WORD40)(ixheaacd_mult32(x[i], y[i]));
 | |
|   }
 | |
| 
 | |
|   *q_val = norm40(&sum);
 | |
| 
 | |
|   return ((WORD32)sum);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 mac16_arr40(WORD16 *x, WORD16 *y,
 | |
|                                           LOOPINDEX length, WORD16 *q_val) {
 | |
|   LOOPINDEX i;
 | |
|   WORD40 sum = 0;
 | |
| 
 | |
|   for (i = 0; i < length; i++) {
 | |
|     sum += (WORD40)((WORD32)x[i] * (WORD32)y[i]);
 | |
|   }
 | |
| 
 | |
|   *q_val = norm40(&sum);
 | |
| 
 | |
|   return ((WORD32)sum);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 add32_arr40(WORD32 *in_arr, LOOPINDEX length,
 | |
|                                           WORD16 *q_val) {
 | |
|   LOOPINDEX i;
 | |
|   WORD40 sum = 0;
 | |
| 
 | |
|   for (i = 0; i < length; i++) {
 | |
|     sum += (WORD40)in_arr[i];
 | |
|   }
 | |
| 
 | |
|   *q_val = norm40(&sum);
 | |
| 
 | |
|   return ((WORD32)sum);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD64 ixheaacd_mult32x32in64(WORD32 a, WORD32 b) {
 | |
|   WORD64 result;
 | |
| 
 | |
|   result = (WORD64)a * (WORD64)b;
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD64 ixheaacd_mac32x32in64(WORD64 sum, WORD32 a,
 | |
|                                                     WORD32 b) {
 | |
|   sum += (WORD64)a * (WORD64)b;
 | |
| 
 | |
|   return (sum);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD64 ixheaacd_mac32x32in64_7(const WORD32 *a,
 | |
|                                                       const WORD16 *b) {
 | |
|   WORD64 sum;
 | |
|   sum = (WORD64)a[0] * (WORD64)b[0];
 | |
|   sum += (WORD64)a[1] * (WORD64)b[1];
 | |
|   sum += (WORD64)a[2] * (WORD64)b[2];
 | |
|   sum += (WORD64)a[3] * (WORD64)b[3];
 | |
|   sum += (WORD64)a[4] * (WORD64)b[4];
 | |
|   sum += (WORD64)a[5] * (WORD64)b[5];
 | |
|   sum += (WORD64)a[6] * (WORD64)b[6];
 | |
| 
 | |
|   return (sum);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD64 ixheaacd_mac32x32in64_n(WORD64 sum,
 | |
|                                                       const WORD32 *a,
 | |
|                                                       const WORD16 *b,
 | |
|                                                       WORD32 n) {
 | |
|   WORD32 k;
 | |
| 
 | |
|   sum += (WORD64)a[0] * (WORD64)b[0];
 | |
|   for (k = 1; k < n; k++) sum += (WORD64)a[k] * (WORD64)b[k];
 | |
|   return (sum);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD64 ixheaacd_mult64(WORD32 a, WORD32 b) {
 | |
|   WORD64 result;
 | |
|   result = (WORD64)a * (WORD64)b;
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD64 ixheaacd_mult64_sat(WORD64 a, WORD64 b) {
 | |
|   WORD64 result;
 | |
| 
 | |
|   if (a > 0 && b > 0 && a > MAX_64 / b) return MAX_64;
 | |
|   if (a < 0 && b > 0 && a < MIN_64 / b) return MIN_64;
 | |
|   if (a > 0 && b < 0 && b < MIN_64 / a) return MIN_64;
 | |
|   if (a < 0 && b < 0 && a < MAX_64 / b) return MAX_64;
 | |
| 
 | |
|   result = a * b;
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD64 ixheaacd_add64_sat(WORD64 a, WORD64 b) {
 | |
|   WORD64 result, comp;
 | |
|   result = (a < 0) ? MIN_64 : MAX_64;
 | |
|   comp = result - a;
 | |
|   if ((a < 0) == (b > comp)) result = a + b;
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 ixheaacd_sat64_32(WORD64 a) {
 | |
|   WORD32 result;
 | |
|   if (a >= MAX_32) {
 | |
|     result = MAX_32;
 | |
|   } else if (a <= MIN_32) {
 | |
|     result = MIN_32;
 | |
|   } else
 | |
|     result = (WORD32)a;
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD64 ixheaacd_add64(WORD64 a, WORD64 b) {
 | |
|   WORD64 result;
 | |
|   result = a + b;
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD64 ixheaacd_sub64(WORD64 a, WORD64 b) {
 | |
|   WORD64 diff;
 | |
| 
 | |
|   diff = (WORD64)a - (WORD64)b;
 | |
| 
 | |
|   return diff;
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD64 ixheaacd_sub64_sat(WORD64 a, WORD64 b) {
 | |
|   WORD64 diff;
 | |
| 
 | |
|   diff = ixheaacd_sub64(a, b);
 | |
| 
 | |
|   if ((((WORD64)a ^ (WORD64)b) & (WORD64)MIN_64) != 0) {
 | |
|     if (((WORD64)diff ^ (WORD64)a) & (WORD64)MIN_64) {
 | |
|       diff = (a < 0L) ? MIN_64 : MAX_64;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return (diff);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 ixheaacd_mul32_sh(WORD32 a, WORD32 b,
 | |
|                                                 WORD8 shift) {
 | |
|   WORD32 result;
 | |
|   WORD64 temp_result;
 | |
| 
 | |
|   temp_result = (WORD64)a * (WORD64)b;
 | |
|   result = (WORD32)(temp_result >> shift);
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| #endif
 |