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
ixheaacd_shr32_dir_sat(WORD32 a,WORD b)114 static PLATFORM_INLINE WORD32 ixheaacd_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
ixheaacd_mult32x16hin32(WORD32 a,WORD32 b)134 static PLATFORM_INLINE WORD32 ixheaacd_mult32x16hin32(WORD32 a, WORD32 b) {
135 WORD32 result;
136 WORD64 temp_result;
137
138 temp_result = (WORD64)(a) * (WORD64)(b >> 16);
139 result = (WORD32)(temp_result >> 16);
140
141 return (result);
142 }
143
ixheaacd_mult32x16in32_sat(WORD32 a,WORD16 b)144 static PLATFORM_INLINE WORD32 ixheaacd_mult32x16in32_sat(WORD32 a, WORD16 b) {
145 WORD32 result;
146 WORD64 temp_result;
147
148 temp_result = (WORD64)a * (WORD64)b;
149
150 if (temp_result < (WORD64)MIN_32)
151 result = MIN_32;
152
153 else if (temp_result > (WORD64)MAX_32)
154 result = MAX_32;
155
156 else
157 result = (WORD32)(temp_result);
158
159 return(result);
160 }
161
ixheaacd_mult16x16in32_shl(WORD16 a,WORD16 b)162 static PLATFORM_INLINE WORD32 ixheaacd_mult16x16in32_shl(WORD16 a, WORD16 b) {
163 WORD32 product;
164
165 product = ixheaacd_shl32(ixheaacd_mult16x16in32(a, b), 1);
166
167 return product;
168 }
169
ixheaacd_mult16x16in32_shl_sat(WORD16 a,WORD16 b)170 static PLATFORM_INLINE WORD32 ixheaacd_mult16x16in32_shl_sat(WORD16 a,
171 WORD16 b) {
172 WORD32 product;
173 product = (WORD32)a * (WORD32)b;
174 if (product != (WORD32)0x40000000L) {
175 product = ixheaacd_shl32(product, 1);
176 } else {
177 product = MAX_32;
178 }
179 return product;
180 }
181
ixheaacd_add32(WORD32 a,WORD32 b)182 static PLATFORM_INLINE WORD32 ixheaacd_add32(WORD32 a, WORD32 b) {
183 WORD32 sum;
184
185 sum = (WORD32)a + (WORD32)b;
186
187 return sum;
188 }
189
ixheaacd_sub32(WORD32 a,WORD32 b)190 static PLATFORM_INLINE WORD32 ixheaacd_sub32(WORD32 a, WORD32 b) {
191 WORD32 diff;
192
193 diff = (WORD32)a - (WORD32)b;
194
195 return diff;
196 }
197
ixheaacd_add32_sat(WORD32 a,WORD32 b)198 static PLATFORM_INLINE WORD32 ixheaacd_add32_sat(WORD32 a, WORD32 b) {
199 WORD64 sum;
200
201 sum = (WORD64)a + (WORD64)b;
202
203 if (sum >= MAX_32) return MAX_32;
204 if (sum <= MIN_32) return MIN_32;
205
206 return (WORD32)sum;
207 }
208
ixheaacd_add32_sat3(WORD32 a,WORD32 b,WORD32 c)209 static PLATFORM_INLINE WORD32 ixheaacd_add32_sat3(WORD32 a, WORD32 b,
210 WORD32 c) {
211 WORD64 sum;
212
213 sum = (WORD64)a + (WORD64)b;
214
215 sum = (WORD64)sum + (WORD64)c;
216
217 if (sum > MAX_32) {
218 sum = MAX_32;
219 }
220 if (sum < MIN_32) {
221 sum = MIN_32;
222 }
223
224 return (WORD32)sum;
225 }
226
ixheaacd_sub32_sat(WORD32 a,WORD32 b)227 static PLATFORM_INLINE WORD32 ixheaacd_sub32_sat(WORD32 a, WORD32 b) {
228 WORD64 diff;
229
230 diff = (WORD64)a - (WORD64)b;
231
232 if (diff >= MAX_32) return MAX_32;
233 if (diff <= MIN_32) return MIN_32;
234
235 return (WORD32)diff;
236 }
237
ixheaacd_norm32(WORD32 a)238 static PLATFORM_INLINE WORD ixheaacd_norm32(WORD32 a) {
239 WORD norm_val;
240
241 if (a == 0) {
242 norm_val = 31;
243 } else {
244 if (a == (WORD32)0xffffffffL) {
245 norm_val = 31;
246 } else {
247 if (a < 0) {
248 a = ~a;
249 }
250 for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) {
251 a <<= 1;
252 }
253 }
254 }
255
256 return norm_val;
257 }
258
ixheaacd_pnorm32(WORD32 a)259 static PLATFORM_INLINE WORD ixheaacd_pnorm32(WORD32 a) {
260 WORD norm_val;
261
262 if (a == 0) {
263 norm_val = 31;
264 } else {
265 for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) {
266 a <<= 1;
267 }
268 }
269
270 return norm_val;
271 }
272
ixheaacd_abs32(WORD32 a)273 static PLATFORM_INLINE WORD32 ixheaacd_abs32(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_nrm(WORD32 a)285 static PLATFORM_INLINE WORD32 ixheaacd_abs32_nrm(WORD32 a) {
286 WORD32 abs_val;
287
288 abs_val = a;
289
290 if (a < 0) {
291 abs_val = ~a;
292 }
293
294 return abs_val;
295 }
296
ixheaacd_abs32_sat(WORD32 a)297 static PLATFORM_INLINE WORD32 ixheaacd_abs32_sat(WORD32 a) {
298 WORD32 abs_val;
299
300 abs_val = a;
301
302 if (a == MIN_32) {
303 abs_val = MAX_32;
304 } else if (a < 0) {
305 abs_val = -a;
306 }
307
308 return abs_val;
309 }
310
ixheaacd_negate32(WORD32 a)311 static PLATFORM_INLINE WORD32 ixheaacd_negate32(WORD32 a) {
312 WORD32 neg_val;
313
314 neg_val = -a;
315
316 return neg_val;
317 }
318
ixheaacd_negate32_sat(WORD32 a)319 static PLATFORM_INLINE WORD32 ixheaacd_negate32_sat(WORD32 a) {
320 WORD32 neg_val;
321
322 if (a == MIN_32) {
323 neg_val = MAX_32;
324 } else {
325 neg_val = -a;
326 }
327 return neg_val;
328 }
329
ixheaacd_div32(WORD32 a,WORD32 b,WORD * q_format)330 static PLATFORM_INLINE WORD32 ixheaacd_div32(WORD32 a, WORD32 b,
331 WORD *q_format) {
332 WORD32 quotient;
333 UWORD32 mantissa_nr, mantissa_dr;
334 WORD16 sign = 0;
335
336 LOOPINDEX i;
337 WORD q_nr, q_dr;
338
339 mantissa_nr = a;
340 mantissa_dr = b;
341 quotient = 0;
342
343 if ((a < 0) && (0 != b)) {
344 a = -a;
345 sign = (WORD16)(sign ^ -1);
346 }
347
348 if (b < 0) {
349 b = -b;
350 sign = (WORD16)(sign ^ -1);
351 }
352
353 if (0 == b) {
354 *q_format = 0;
355 return (a);
356 }
357
358 quotient = 0;
359
360 q_nr = ixheaacd_norm32(a);
361 mantissa_nr = (UWORD32)a << (q_nr);
362 q_dr = ixheaacd_norm32(b);
363 mantissa_dr = (UWORD32)b << (q_dr);
364 *q_format = (WORD)(30 + q_nr - q_dr);
365
366 for (i = 0; i < 31; i++) {
367 quotient = quotient << 1;
368
369 if (mantissa_nr >= mantissa_dr) {
370 mantissa_nr = mantissa_nr - mantissa_dr;
371 quotient += 1;
372 }
373
374 mantissa_nr = (UWORD32)mantissa_nr << 1;
375 }
376
377 if (sign < 0) {
378 quotient = -quotient;
379 }
380
381 return quotient;
382 }
383
ixheaacd_shr32_sat(WORD32 a,WORD32 b)384 static PLATFORM_INLINE WORD32 ixheaacd_shr32_sat(WORD32 a, WORD32 b) {
385 WORD32 out_val;
386
387 b = ((UWORD32)(b << 24) >> 24);
388 if (b >= 31) {
389 if (a < 0)
390 out_val = -1;
391 else
392 out_val = 0;
393 }
394 else if (b <= 0) {
395 return a;
396 }
397 else {
398 a = ixheaacd_add32_sat(a, (1 << (b - 1)));
399 out_val = (WORD32)a >> b;
400 }
401
402 return out_val;
403 }
404
ixheaacd_mac16x16in32_sat(WORD32 a,WORD16 b,WORD16 c)405 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_sat(WORD32 a, WORD16 b,
406 WORD16 c) {
407 WORD32 acc;
408
409 acc = ixheaacd_mult16x16in32(b, c);
410
411 acc = ixheaacd_add32_sat(a, acc);
412
413 return acc;
414 }
415
ixheaacd_mac16x16in32_shl(WORD32 a,WORD16 b,WORD16 c)416 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_shl(WORD32 a, WORD16 b,
417 WORD16 c) {
418 WORD32 acc;
419
420 acc = ixheaacd_mult16x16in32_shl(b, c);
421
422 acc = ixheaacd_add32(a, acc);
423
424 return acc;
425 }
426
ixheaacd_mac16x16in32_shl_sat(WORD32 a,WORD16 b,WORD16 c)427 static PLATFORM_INLINE WORD32 ixheaacd_mac16x16in32_shl_sat(WORD32 a, WORD16 b,
428 WORD16 c) {
429 WORD32 acc;
430
431 acc = ixheaacd_mult16x16in32_shl_sat(b, c);
432
433 acc = ixheaacd_add32_sat(a, acc);
434
435 return acc;
436 }
437
ixheaacd_msu16x16in32(WORD32 a,WORD16 b,WORD16 c)438 static PLATFORM_INLINE WORD32 ixheaacd_msu16x16in32(WORD32 a, WORD16 b, WORD16 c) {
439 WORD32 acc;
440
441 acc = ixheaacd_mult16x16in32(b, c);
442
443 acc = ixheaacd_sub32(a, acc);
444
445 return acc;
446 }
447
448 #endif
449