Home | History | Annotate | Download | only in decoder
      1 /******************************************************************************
      2  *                                                                            *
      3  * Copyright (C) 2018 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at:
      8  *
      9  * http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  *
     17  *****************************************************************************
     18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
     19 */
     20 #ifndef IXHEAACD_BASIC_OPS32_H
     21 #define IXHEAACD_BASIC_OPS32_H
     22 
     23 static PLATFORM_INLINE WORD32 ixheaacd_min32(WORD32 a, WORD32 b) {
     24   WORD32 min_val;
     25 
     26   min_val = (a < b) ? a : b;
     27 
     28   return min_val;
     29 }
     30 
     31 static PLATFORM_INLINE WORD32 ixheaacd_max32(WORD32 a, WORD32 b) {
     32   WORD32 max_val;
     33 
     34   max_val = (a > b) ? a : b;
     35 
     36   return max_val;
     37 }
     38 
     39 static PLATFORM_INLINE WORD32 ixheaacd_shl32(WORD32 a, WORD b) {
     40   WORD32 out_val;
     41 
     42   b = ((UWORD32)(b << 24) >> 24);
     43   if (b > 31)
     44     out_val = 0;
     45   else
     46     out_val = (WORD32)a << b;
     47 
     48   return out_val;
     49 }
     50 
     51 static PLATFORM_INLINE WORD32 ixheaacd_shr32(WORD32 a, WORD b) {
     52   WORD32 out_val;
     53 
     54   b = ((UWORD32)(b << 24) >> 24);
     55   if (b >= 31) {
     56     if (a < 0)
     57       out_val = -1;
     58     else
     59       out_val = 0;
     60   } else {
     61     out_val = (WORD32)a >> b;
     62   }
     63 
     64   return out_val;
     65 }
     66 
     67 static PLATFORM_INLINE WORD32 ixheaacd_shl32_sat(WORD32 a, WORD b) {
     68   WORD32 out_val;
     69   if (a > (MAX_32 >> b))
     70     out_val = MAX_32;
     71   else if (a < (MIN_32 >> b))
     72     out_val = MIN_32;
     73   else
     74     out_val = a << b;
     75   return (out_val);
     76 }
     77 
     78 static PLATFORM_INLINE WORD32 ixheaacd_shl32_dir(WORD32 a, WORD b) {
     79   WORD32 out_val;
     80 
     81   if (b < 0) {
     82     out_val = ixheaacd_shr32(a, -b);
     83   } else {
     84     out_val = ixheaacd_shl32(a, b);
     85   }
     86 
     87   return out_val;
     88 }
     89 
     90 static PLATFORM_INLINE WORD32 ixheaacd_shl32_dir_sat(WORD32 a, WORD b) {
     91   WORD32 out_val;
     92 
     93   if (b < 0) {
     94     out_val = ixheaacd_shr32(a, -b);
     95   } else {
     96     out_val = ixheaacd_shl32_sat(a, b);
     97   }
     98 
     99   return out_val;
    100 }
    101 
    102 static PLATFORM_INLINE WORD32 ixheaacd_shr32_dir(WORD32 a, WORD b) {
    103   WORD32 out_val;
    104 
    105   if (b < 0) {
    106     out_val = ixheaacd_shl32(a, -b);
    107   } else {
    108     out_val = ixheaacd_shr32(a, b);
    109   }
    110 
    111   return out_val;
    112 }
    113 
    114 static PLATFORM_INLINE WORD32 shr32_dir_sat(WORD32 a, WORD b) {
    115   WORD32 out_val;
    116 
    117   if (b < 0) {
    118     out_val = ixheaacd_shl32_sat(a, -b);
    119   } else {
    120     out_val = ixheaacd_shr32(a, b);
    121   }
    122 
    123   return out_val;
    124 }
    125 
    126 static PLATFORM_INLINE WORD32 ixheaacd_mult16x16in32(WORD16 a, WORD16 b) {
    127   WORD32 product;
    128 
    129   product = (WORD32)a * (WORD32)b;
    130 
    131   return product;
    132 }
    133 
    134 static PLATFORM_INLINE WORD32 mult16x16in32_32(WORD32 a, WORD32 b) {
    135   WORD32 product;
    136 
    137   product = (WORD32)a * (WORD32)b;
    138 
    139   return product;
    140 }
    141 
    142 static PLATFORM_INLINE WORD32 ixheaacd_mult16x16in32_shl(WORD16 a, WORD16 b) {
    143   WORD32 product;
    144 
    145   product = ixheaacd_shl32(ixheaacd_mult16x16in32(a, b), 1);
    146 
    147   return product;
    148 }
    149 
    150 static PLATFORM_INLINE WORD32 ixheaacd_mult16x16in32_shl_sat(WORD16 a,
    151                                                              WORD16 b) {
    152   WORD32 product;
    153   product = (WORD32)a * (WORD32)b;
    154   if (product != (WORD32)0x40000000L) {
    155     product = ixheaacd_shl32(product, 1);
    156   } else {
    157     product = MAX_32;
    158   }
    159   return product;
    160 }
    161 
    162 static PLATFORM_INLINE WORD32 ixheaacd_add32(WORD32 a, WORD32 b) {
    163   WORD32 sum;
    164 
    165   sum = (WORD32)a + (WORD32)b;
    166 
    167   return sum;
    168 }
    169 
    170 static PLATFORM_INLINE WORD32 ixheaacd_sub32(WORD32 a, WORD32 b) {
    171   WORD32 diff;
    172 
    173   diff = (WORD32)a - (WORD32)b;
    174 
    175   return diff;
    176 }
    177 
    178 static PLATFORM_INLINE WORD32 ixheaacd_add32_sat(WORD32 a, WORD32 b) {
    179   WORD64 sum;
    180 
    181   sum = (WORD64)a + (WORD64)b;
    182 
    183   if ((((WORD32)a ^ (WORD32)b) & (WORD32)MIN_32) == 0) {
    184     if (((WORD32)sum ^ (WORD32)a) & (WORD32)MIN_32) {
    185       sum = (a < 0) ? MIN_32 : MAX_32;
    186     }
    187   }
    188 
    189   return (WORD32)sum;
    190 }
    191 
    192 static PLATFORM_INLINE WORD32 ixheaacd_add32_sat3(WORD32 a, WORD32 b,
    193                                                   WORD32 c) {
    194   WORD64 sum;
    195 
    196   sum = (WORD64)a + (WORD64)b;
    197 
    198   sum = (WORD64)sum + (WORD64)c;
    199 
    200   if (sum > MAX_32) {
    201     sum = MAX_32;
    202   }
    203   if (sum < MIN_32) {
    204     sum = MIN_32;
    205   }
    206 
    207   return (WORD32)sum;
    208 }
    209 
    210 static PLATFORM_INLINE WORD32 ixheaacd_sub32_sat(WORD32 a, WORD32 b) {
    211   WORD64 diff;
    212 
    213   diff = (WORD64)a - (WORD64)b;
    214 
    215   if ((((WORD32)a ^ (WORD32)b) & (WORD32)MIN_32) != 0) {
    216     if (((WORD32)diff ^ (WORD32)a) & (WORD32)MIN_32) {
    217       diff = (a < 0L) ? MIN_32 : MAX_32;
    218     }
    219   }
    220 
    221   return (WORD32)diff;
    222 }
    223 
    224 static PLATFORM_INLINE WORD ixheaacd_norm32(WORD32 a) {
    225   WORD norm_val;
    226 
    227   if (a == 0) {
    228     norm_val = 31;
    229   } else {
    230     if (a == (WORD32)0xffffffffL) {
    231       norm_val = 31;
    232     } else {
    233       if (a < 0) {
    234         a = ~a;
    235       }
    236       for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) {
    237         a <<= 1;
    238       }
    239     }
    240   }
    241 
    242   return norm_val;
    243 }
    244 
    245 static PLATFORM_INLINE WORD ixheaacd_pnorm32(WORD32 a) {
    246   WORD norm_val;
    247 
    248   if (a == 0) {
    249     norm_val = 31;
    250   } else {
    251     for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) {
    252       a <<= 1;
    253     }
    254   }
    255 
    256   return norm_val;
    257 }
    258 
    259 static PLATFORM_INLINE WORD bin_expo32(WORD32 a) {
    260   WORD bin_expo_val;
    261 
    262   bin_expo_val = 31 - ixheaacd_norm32(a);
    263 
    264   return bin_expo_val;
    265 }
    266 
    267 static PLATFORM_INLINE WORD32 ixheaacd_abs32(WORD32 a) {
    268   WORD32 abs_val;
    269 
    270   abs_val = a;
    271 
    272   if (a < 0) {
    273     abs_val = -a;
    274   }
    275 
    276   return abs_val;
    277 }
    278 
    279 static PLATFORM_INLINE WORD32 ixheaacd_abs32_nrm(WORD32 a) {
    280   WORD32 abs_val;
    281 
    282   abs_val = a;
    283 
    284   if (a < 0) {
    285     abs_val = ~a;
    286   }
    287 
    288   return abs_val;
    289 }
    290 
    291 static PLATFORM_INLINE WORD32 ixheaacd_abs32_sat(WORD32 a) {
    292   WORD32 abs_val;
    293 
    294   abs_val = a;
    295 
    296   if (a == MIN_32) {
    297     abs_val = MAX_32;
    298   } else if (a < 0) {
    299     abs_val = -a;
    300   }
    301 
    302   return abs_val;
    303 }
    304 
    305 static PLATFORM_INLINE WORD32 ixheaacd_negate32(WORD32 a) {
    306   WORD32 neg_val;
    307 
    308   neg_val = -a;
    309 
    310   return neg_val;
    311 }
    312 
    313 static PLATFORM_INLINE WORD32 ixheaacd_negate32_sat(WORD32 a) {
    314   WORD32 neg_val;
    315 
    316   if (a == MIN_32) {
    317     neg_val = MAX_32;
    318   } else {
    319     neg_val = -a;
    320   }
    321   return neg_val;
    322 }
    323 
    324 static PLATFORM_INLINE WORD32 div32(WORD32 a, WORD32 b, WORD *q_format) {
    325   WORD32 quotient;
    326   UWORD32 mantissa_nr, mantissa_dr;
    327   WORD16 sign = 0;
    328 
    329   LOOPINDEX i;
    330   WORD q_nr, q_dr;
    331 
    332   mantissa_nr = a;
    333   mantissa_dr = b;
    334   quotient = 0;
    335 
    336   if ((a < 0) && (0 != b)) {
    337     a = -a;
    338     sign = (WORD16)(sign ^ -1);
    339   }
    340 
    341   if (b < 0) {
    342     b = -b;
    343     sign = (WORD16)(sign ^ -1);
    344   }
    345 
    346   if (0 == b) {
    347     *q_format = 0;
    348     return (a);
    349   }
    350 
    351   quotient = 0;
    352 
    353   q_nr = ixheaacd_norm32(a);
    354   mantissa_nr = (UWORD32)a << (q_nr);
    355   q_dr = ixheaacd_norm32(b);
    356   mantissa_dr = (UWORD32)b << (q_dr);
    357   *q_format = (WORD)(30 + q_nr - q_dr);
    358 
    359   for (i = 0; i < 31; i++) {
    360     quotient = quotient << 1;
    361 
    362     if (mantissa_nr >= mantissa_dr) {
    363       mantissa_nr = mantissa_nr - mantissa_dr;
    364       quotient += 1;
    365     }
    366 
    367     mantissa_nr = (UWORD32)mantissa_nr << 1;
    368   }
    369 
    370   if (sign < 0) {
    371     quotient = -quotient;
    372   }
    373 
    374   return quotient;
    375 }
    376 
    377 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_sat(WORD32 a, WORD16 b,
    378                                                         WORD16 c) {
    379   WORD32 acc;
    380 
    381   acc = ixheaacd_mult16x16in32(b, c);
    382 
    383   acc = ixheaacd_add32_sat(a, acc);
    384 
    385   return acc;
    386 }
    387 
    388 static PLATFORM_INLINE WORD32 mac16x16hin32(WORD32 a, WORD32 b, WORD32 c) {
    389   WORD32 acc;
    390 
    391   acc = ixheaacd_mult16x16in32((WORD16)b, (WORD16)(c >> 16));
    392 
    393   acc = ixheaacd_add32(a, acc);
    394 
    395   return acc;
    396 }
    397 
    398 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_shl(WORD32 a, WORD16 b,
    399                                                         WORD16 c) {
    400   WORD32 acc;
    401 
    402   acc = ixheaacd_mult16x16in32_shl(b, c);
    403 
    404   acc = ixheaacd_add32(a, acc);
    405 
    406   return acc;
    407 }
    408 
    409 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_shl_sat(WORD32 a, WORD16 b,
    410                                                             WORD16 c) {
    411   WORD32 acc;
    412 
    413   acc = ixheaacd_mult16x16in32_shl_sat(b, c);
    414 
    415   acc = ixheaacd_add32_sat(a, acc);
    416 
    417   return acc;
    418 }
    419 
    420 static PLATFORM_INLINE WORD32 msu16x16in32(WORD32 a, WORD16 b, WORD16 c) {
    421   WORD32 acc;
    422 
    423   acc = ixheaacd_mult16x16in32(b, c);
    424 
    425   acc = ixheaacd_sub32(a, acc);
    426 
    427   return acc;
    428 }
    429 
    430 static PLATFORM_INLINE WORD32 msu16x16in32_shl(WORD32 a, WORD16 b, WORD16 c) {
    431   WORD32 acc;
    432 
    433   acc = ixheaacd_mult16x16in32_shl(b, c);
    434 
    435   acc = ixheaacd_sub32(a, acc);
    436 
    437   return acc;
    438 }
    439 
    440 static PLATFORM_INLINE WORD32 msu16x16in32_shl_sat(WORD32 a, WORD16 b,
    441                                                    WORD16 c) {
    442   WORD32 acc;
    443 
    444   acc = ixheaacd_mult16x16in32_shl_sat(b, c);
    445 
    446   acc = ixheaacd_sub32_sat(a, acc);
    447 
    448   return acc;
    449 }
    450 
    451 static PLATFORM_INLINE WORD32 add32_shr(WORD32 a, WORD32 b) {
    452   WORD32 sum;
    453 
    454   a = ixheaacd_shr32(a, 1);
    455   b = ixheaacd_shr32(b, 1);
    456 
    457   sum = ixheaacd_add32(a, b);
    458 
    459   return sum;
    460 }
    461 
    462 static PLATFORM_INLINE WORD32 sub32_shr(WORD32 a, WORD32 b) {
    463   WORD32 diff;
    464 
    465   a = ixheaacd_shr32(a, 1);
    466   b = ixheaacd_shr32(b, 1);
    467 
    468   diff = ixheaacd_sub32(a, b);
    469 
    470   return diff;
    471 }
    472 #endif