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