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 
ixheaacd_min32(WORD32 a,WORD32 b)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 
ixheaacd_max32(WORD32 a,WORD32 b)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 
ixheaacd_shl32(WORD32 a,WORD b)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 
ixheaacd_shr32(WORD32 a,WORD b)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 
ixheaacd_shl32_sat(WORD32 a,WORD b)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 
ixheaacd_shl32_dir(WORD32 a,WORD b)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 
ixheaacd_shl32_dir_sat(WORD32 a,WORD b)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 
ixheaacd_shr32_dir(WORD32 a,WORD b)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 
shr32_dir_sat(WORD32 a,WORD b)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 
ixheaacd_mult16x16in32(WORD16 a,WORD16 b)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 
mult16x16in32_32(WORD32 a,WORD32 b)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 
ixheaacd_mult16x16in32_shl(WORD16 a,WORD16 b)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 
ixheaacd_mult16x16in32_shl_sat(WORD16 a,WORD16 b)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 
ixheaacd_add32(WORD32 a,WORD32 b)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 
ixheaacd_sub32(WORD32 a,WORD32 b)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 
ixheaacd_add32_sat(WORD32 a,WORD32 b)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 (sum >= MAX_32) return MAX_32;
184   if (sum <= MIN_32) return MIN_32;
185 
186   return (WORD32)sum;
187 }
188 
ixheaacd_add32_sat3(WORD32 a,WORD32 b,WORD32 c)189 static PLATFORM_INLINE WORD32 ixheaacd_add32_sat3(WORD32 a, WORD32 b,
190                                                   WORD32 c) {
191   WORD64 sum;
192 
193   sum = (WORD64)a + (WORD64)b;
194 
195   sum = (WORD64)sum + (WORD64)c;
196 
197   if (sum > MAX_32) {
198     sum = MAX_32;
199   }
200   if (sum < MIN_32) {
201     sum = MIN_32;
202   }
203 
204   return (WORD32)sum;
205 }
206 
ixheaacd_sub32_sat(WORD32 a,WORD32 b)207 static PLATFORM_INLINE WORD32 ixheaacd_sub32_sat(WORD32 a, WORD32 b) {
208   WORD64 diff;
209 
210   diff = (WORD64)a - (WORD64)b;
211 
212   if (diff >= MAX_32) return MAX_32;
213   if (diff <= MIN_32) return MIN_32;
214 
215   return (WORD32)diff;
216 }
217 
ixheaacd_norm32(WORD32 a)218 static PLATFORM_INLINE WORD ixheaacd_norm32(WORD32 a) {
219   WORD norm_val;
220 
221   if (a == 0) {
222     norm_val = 31;
223   } else {
224     if (a == (WORD32)0xffffffffL) {
225       norm_val = 31;
226     } else {
227       if (a < 0) {
228         a = ~a;
229       }
230       for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) {
231         a <<= 1;
232       }
233     }
234   }
235 
236   return norm_val;
237 }
238 
ixheaacd_pnorm32(WORD32 a)239 static PLATFORM_INLINE WORD ixheaacd_pnorm32(WORD32 a) {
240   WORD norm_val;
241 
242   if (a == 0) {
243     norm_val = 31;
244   } else {
245     for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) {
246       a <<= 1;
247     }
248   }
249 
250   return norm_val;
251 }
252 
bin_expo32(WORD32 a)253 static PLATFORM_INLINE WORD bin_expo32(WORD32 a) {
254   WORD bin_expo_val;
255 
256   bin_expo_val = 31 - ixheaacd_norm32(a);
257 
258   return bin_expo_val;
259 }
260 
ixheaacd_abs32(WORD32 a)261 static PLATFORM_INLINE WORD32 ixheaacd_abs32(WORD32 a) {
262   WORD32 abs_val;
263 
264   abs_val = a;
265 
266   if (a < 0) {
267     abs_val = -a;
268   }
269 
270   return abs_val;
271 }
272 
ixheaacd_abs32_nrm(WORD32 a)273 static PLATFORM_INLINE WORD32 ixheaacd_abs32_nrm(WORD32 a) {
274   WORD32 abs_val;
275 
276   abs_val = a;
277 
278   if (a < 0) {
279     abs_val = ~a;
280   }
281 
282   return abs_val;
283 }
284 
ixheaacd_abs32_sat(WORD32 a)285 static PLATFORM_INLINE WORD32 ixheaacd_abs32_sat(WORD32 a) {
286   WORD32 abs_val;
287 
288   abs_val = a;
289 
290   if (a == MIN_32) {
291     abs_val = MAX_32;
292   } else if (a < 0) {
293     abs_val = -a;
294   }
295 
296   return abs_val;
297 }
298 
ixheaacd_negate32(WORD32 a)299 static PLATFORM_INLINE WORD32 ixheaacd_negate32(WORD32 a) {
300   WORD32 neg_val;
301 
302   neg_val = -a;
303 
304   return neg_val;
305 }
306 
ixheaacd_negate32_sat(WORD32 a)307 static PLATFORM_INLINE WORD32 ixheaacd_negate32_sat(WORD32 a) {
308   WORD32 neg_val;
309 
310   if (a == MIN_32) {
311     neg_val = MAX_32;
312   } else {
313     neg_val = -a;
314   }
315   return neg_val;
316 }
317 
div32(WORD32 a,WORD32 b,WORD * q_format)318 static PLATFORM_INLINE WORD32 div32(WORD32 a, WORD32 b, WORD *q_format) {
319   WORD32 quotient;
320   UWORD32 mantissa_nr, mantissa_dr;
321   WORD16 sign = 0;
322 
323   LOOPINDEX i;
324   WORD q_nr, q_dr;
325 
326   mantissa_nr = a;
327   mantissa_dr = b;
328   quotient = 0;
329 
330   if ((a < 0) && (0 != b)) {
331     a = -a;
332     sign = (WORD16)(sign ^ -1);
333   }
334 
335   if (b < 0) {
336     b = -b;
337     sign = (WORD16)(sign ^ -1);
338   }
339 
340   if (0 == b) {
341     *q_format = 0;
342     return (a);
343   }
344 
345   quotient = 0;
346 
347   q_nr = ixheaacd_norm32(a);
348   mantissa_nr = (UWORD32)a << (q_nr);
349   q_dr = ixheaacd_norm32(b);
350   mantissa_dr = (UWORD32)b << (q_dr);
351   *q_format = (WORD)(30 + q_nr - q_dr);
352 
353   for (i = 0; i < 31; i++) {
354     quotient = quotient << 1;
355 
356     if (mantissa_nr >= mantissa_dr) {
357       mantissa_nr = mantissa_nr - mantissa_dr;
358       quotient += 1;
359     }
360 
361     mantissa_nr = (UWORD32)mantissa_nr << 1;
362   }
363 
364   if (sign < 0) {
365     quotient = -quotient;
366   }
367 
368   return quotient;
369 }
370 
ixheaacd_mac16x16in32_sat(WORD32 a,WORD16 b,WORD16 c)371 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_sat(WORD32 a, WORD16 b,
372                                                         WORD16 c) {
373   WORD32 acc;
374 
375   acc = ixheaacd_mult16x16in32(b, c);
376 
377   acc = ixheaacd_add32_sat(a, acc);
378 
379   return acc;
380 }
381 
mac16x16hin32(WORD32 a,WORD32 b,WORD32 c)382 static PLATFORM_INLINE WORD32 mac16x16hin32(WORD32 a, WORD32 b, WORD32 c) {
383   WORD32 acc;
384 
385   acc = ixheaacd_mult16x16in32((WORD16)b, (WORD16)(c >> 16));
386 
387   acc = ixheaacd_add32(a, acc);
388 
389   return acc;
390 }
391 
ixheaacd_mac16x16in32_shl(WORD32 a,WORD16 b,WORD16 c)392 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_shl(WORD32 a, WORD16 b,
393                                                         WORD16 c) {
394   WORD32 acc;
395 
396   acc = ixheaacd_mult16x16in32_shl(b, c);
397 
398   acc = ixheaacd_add32(a, acc);
399 
400   return acc;
401 }
402 
ixheaacd_mac16x16in32_shl_sat(WORD32 a,WORD16 b,WORD16 c)403 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_shl_sat(WORD32 a, WORD16 b,
404                                                             WORD16 c) {
405   WORD32 acc;
406 
407   acc = ixheaacd_mult16x16in32_shl_sat(b, c);
408 
409   acc = ixheaacd_add32_sat(a, acc);
410 
411   return acc;
412 }
413 
msu16x16in32(WORD32 a,WORD16 b,WORD16 c)414 static PLATFORM_INLINE WORD32 msu16x16in32(WORD32 a, WORD16 b, WORD16 c) {
415   WORD32 acc;
416 
417   acc = ixheaacd_mult16x16in32(b, c);
418 
419   acc = ixheaacd_sub32(a, acc);
420 
421   return acc;
422 }
423 
msu16x16in32_shl(WORD32 a,WORD16 b,WORD16 c)424 static PLATFORM_INLINE WORD32 msu16x16in32_shl(WORD32 a, WORD16 b, WORD16 c) {
425   WORD32 acc;
426 
427   acc = ixheaacd_mult16x16in32_shl(b, c);
428 
429   acc = ixheaacd_sub32(a, acc);
430 
431   return acc;
432 }
433 
msu16x16in32_shl_sat(WORD32 a,WORD16 b,WORD16 c)434 static PLATFORM_INLINE WORD32 msu16x16in32_shl_sat(WORD32 a, WORD16 b,
435                                                    WORD16 c) {
436   WORD32 acc;
437 
438   acc = ixheaacd_mult16x16in32_shl_sat(b, c);
439 
440   acc = ixheaacd_sub32_sat(a, acc);
441 
442   return acc;
443 }
444 
add32_shr(WORD32 a,WORD32 b)445 static PLATFORM_INLINE WORD32 add32_shr(WORD32 a, WORD32 b) {
446   WORD32 sum;
447 
448   a = ixheaacd_shr32(a, 1);
449   b = ixheaacd_shr32(b, 1);
450 
451   sum = ixheaacd_add32(a, b);
452 
453   return sum;
454 }
455 
sub32_shr(WORD32 a,WORD32 b)456 static PLATFORM_INLINE WORD32 sub32_shr(WORD32 a, WORD32 b) {
457   WORD32 diff;
458 
459   a = ixheaacd_shr32(a, 1);
460   b = ixheaacd_shr32(b, 1);
461 
462   diff = ixheaacd_sub32(a, b);
463 
464   return diff;
465 }
466 #endif