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 IXHEAAC_BASIC_OPS32_H
21 #define IXHEAAC_BASIC_OPS32_H
22
ixheaac_min32(WORD32 a,WORD32 b)23 static PLATFORM_INLINE WORD32 ixheaac_min32(WORD32 a, WORD32 b) {
24 WORD32 min_val;
25
26 min_val = (a < b) ? a : b;
27
28 return min_val;
29 }
30
ixheaac_max32(WORD32 a,WORD32 b)31 static PLATFORM_INLINE WORD32 ixheaac_max32(WORD32 a, WORD32 b) {
32 WORD32 max_val;
33
34 max_val = (a > b) ? a : b;
35
36 return max_val;
37 }
38
ixheaac_shl32(WORD32 a,WORD b)39 static PLATFORM_INLINE WORD32 ixheaac_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
ixheaac_shr32(WORD32 a,WORD b)51 static PLATFORM_INLINE WORD32 ixheaac_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
ixheaac_shl32_sat(WORD32 a,WORD b)67 static PLATFORM_INLINE WORD32 ixheaac_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
ixheaac_shl32_dir(WORD32 a,WORD b)78 static PLATFORM_INLINE WORD32 ixheaac_shl32_dir(WORD32 a, WORD b) {
79 WORD32 out_val;
80
81 if (b < 0) {
82 out_val = ixheaac_shr32(a, -b);
83 } else {
84 out_val = ixheaac_shl32(a, b);
85 }
86
87 return out_val;
88 }
89
ixheaac_shl32_dir_sat(WORD32 a,WORD b)90 static PLATFORM_INLINE WORD32 ixheaac_shl32_dir_sat(WORD32 a, WORD b) {
91 WORD32 out_val;
92
93 if (b < 0) {
94 out_val = ixheaac_shr32(a, -b);
95 } else {
96 out_val = ixheaac_shl32_sat(a, b);
97 }
98
99 return out_val;
100 }
101
ixheaac_shr32_dir(WORD32 a,WORD b)102 static PLATFORM_INLINE WORD32 ixheaac_shr32_dir(WORD32 a, WORD b) {
103 WORD32 out_val;
104
105 if (b < 0) {
106 out_val = ixheaac_shl32(a, -b);
107 } else {
108 out_val = ixheaac_shr32(a, b);
109 }
110
111 return out_val;
112 }
113
ixheaac_shr32_dir_sat(WORD32 a,WORD b)114 static PLATFORM_INLINE WORD32 ixheaac_shr32_dir_sat(WORD32 a, WORD b) {
115 WORD32 out_val;
116
117 if (b < 0) {
118 out_val = ixheaac_shl32_sat(a, -b);
119 } else {
120 out_val = ixheaac_shr32(a, b);
121 }
122
123 return out_val;
124 }
125
ixheaac_mult16x16in32(WORD16 a,WORD16 b)126 static PLATFORM_INLINE WORD32 ixheaac_mult16x16in32(WORD16 a, WORD16 b) {
127 WORD32 product;
128
129 product = (WORD32)a * (WORD32)b;
130
131 return product;
132 }
133
ixheaac_mult32x16hin32(WORD32 a,WORD32 b)134 static PLATFORM_INLINE WORD32 ixheaac_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
ixheaac_mult32x16in32_sat(WORD32 a,WORD16 b)144 static PLATFORM_INLINE WORD32 ixheaac_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
ixheaac_mult16x16in32_shl(WORD16 a,WORD16 b)162 static PLATFORM_INLINE WORD32 ixheaac_mult16x16in32_shl(WORD16 a, WORD16 b) {
163 WORD32 product;
164
165 product = ixheaac_shl32(ixheaac_mult16x16in32(a, b), 1);
166
167 return product;
168 }
169
ixheaac_mult16x16in32_shl_sat(WORD16 a,WORD16 b)170 static PLATFORM_INLINE WORD32 ixheaac_mult16x16in32_shl_sat(WORD16 a, WORD16 b) {
171 WORD32 product;
172 product = (WORD32)a * (WORD32)b;
173 if (product != (WORD32)0x40000000L) {
174 product = ixheaac_shl32(product, 1);
175 } else {
176 product = MAX_32;
177 }
178 return product;
179 }
180
ixheaac_add32(WORD32 a,WORD32 b)181 static PLATFORM_INLINE WORD32 ixheaac_add32(WORD32 a, WORD32 b) {
182 WORD32 sum;
183
184 sum = (WORD32)a + (WORD32)b;
185
186 return sum;
187 }
188
ixheaac_sub32(WORD32 a,WORD32 b)189 static PLATFORM_INLINE WORD32 ixheaac_sub32(WORD32 a, WORD32 b) {
190 WORD32 diff;
191
192 diff = (WORD32)a - (WORD32)b;
193
194 return diff;
195 }
196
ixheaac_add32_sat(WORD32 a,WORD32 b)197 static PLATFORM_INLINE WORD32 ixheaac_add32_sat(WORD32 a, WORD32 b) {
198 WORD64 sum;
199
200 sum = (WORD64)a + (WORD64)b;
201
202 if (sum >= MAX_32) return MAX_32;
203 if (sum <= MIN_32) return MIN_32;
204
205 return (WORD32)sum;
206 }
207
ixheaac_add32_sat3(WORD32 a,WORD32 b,WORD32 c)208 static PLATFORM_INLINE WORD32 ixheaac_add32_sat3(WORD32 a, WORD32 b, WORD32 c) {
209 WORD64 sum;
210
211 sum = (WORD64)a + (WORD64)b;
212
213 sum = (WORD64)sum + (WORD64)c;
214
215 if (sum > MAX_32) {
216 sum = MAX_32;
217 }
218 if (sum < MIN_32) {
219 sum = MIN_32;
220 }
221
222 return (WORD32)sum;
223 }
224
ixheaac_sub32_sat(WORD32 a,WORD32 b)225 static PLATFORM_INLINE WORD32 ixheaac_sub32_sat(WORD32 a, WORD32 b) {
226 WORD64 diff;
227
228 diff = (WORD64)a - (WORD64)b;
229
230 if (diff >= MAX_32) return MAX_32;
231 if (diff <= MIN_32) return MIN_32;
232
233 return (WORD32)diff;
234 }
235
ixheaac_norm32(WORD32 a)236 static PLATFORM_INLINE WORD ixheaac_norm32(WORD32 a) {
237 WORD norm_val;
238
239 if (a == 0) {
240 norm_val = 31;
241 } else {
242 if (a == (WORD32)0xffffffffL) {
243 norm_val = 31;
244 } else {
245 if (a < 0) {
246 a = ~a;
247 }
248 for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) {
249 a <<= 1;
250 }
251 }
252 }
253
254 return norm_val;
255 }
256
ixheaac_pnorm32(WORD32 a)257 static PLATFORM_INLINE WORD ixheaac_pnorm32(WORD32 a) {
258 WORD norm_val;
259
260 if (a == 0) {
261 norm_val = 31;
262 } else {
263 for (norm_val = 0; a < (WORD32)0x40000000L; norm_val++) {
264 a <<= 1;
265 }
266 }
267
268 return norm_val;
269 }
270
ixheaac_abs32(WORD32 a)271 static PLATFORM_INLINE WORD32 ixheaac_abs32(WORD32 a) {
272 WORD32 abs_val;
273
274 abs_val = a;
275
276 if (a < 0) {
277 abs_val = -a;
278 }
279
280 return abs_val;
281 }
282
ixheaac_abs32_nrm(WORD32 a)283 static PLATFORM_INLINE WORD32 ixheaac_abs32_nrm(WORD32 a) {
284 WORD32 abs_val;
285
286 abs_val = a;
287
288 if (a < 0) {
289 abs_val = ~a;
290 }
291
292 return abs_val;
293 }
294
ixheaac_abs32_sat(WORD32 a)295 static PLATFORM_INLINE WORD32 ixheaac_abs32_sat(WORD32 a) {
296 WORD32 abs_val;
297
298 abs_val = a;
299
300 if (a == MIN_32) {
301 abs_val = MAX_32;
302 } else if (a < 0) {
303 abs_val = -a;
304 }
305
306 return abs_val;
307 }
308
ixheaac_negate32(WORD32 a)309 static PLATFORM_INLINE WORD32 ixheaac_negate32(WORD32 a) {
310 WORD32 neg_val;
311
312 neg_val = -a;
313
314 return neg_val;
315 }
316
ixheaac_negate32_sat(WORD32 a)317 static PLATFORM_INLINE WORD32 ixheaac_negate32_sat(WORD32 a) {
318 WORD32 neg_val;
319
320 if (a == MIN_32) {
321 neg_val = MAX_32;
322 } else {
323 neg_val = -a;
324 }
325 return neg_val;
326 }
327
ixheaac_div32(WORD32 a,WORD32 b,WORD * q_format)328 static PLATFORM_INLINE WORD32 ixheaac_div32(WORD32 a, WORD32 b, WORD *q_format) {
329 WORD32 quotient;
330 UWORD32 mantissa_nr, mantissa_dr;
331 WORD16 sign = 0;
332
333 LOOPINDEX i;
334 WORD q_nr, q_dr;
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 = ixheaac_norm32(a);
354 mantissa_nr = (UWORD32)a << (q_nr);
355 q_dr = ixheaac_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
ixheaac_shr32_sat(WORD32 a,WORD32 b)377 static PLATFORM_INLINE WORD32 ixheaac_shr32_sat(WORD32 a, WORD32 b) {
378 WORD32 out_val;
379
380 b = ((UWORD32)(b << 24) >> 24);
381 if (b >= 31) {
382 if (a < 0)
383 out_val = -1;
384 else
385 out_val = 0;
386 } else if (b <= 0) {
387 return a;
388 } else {
389 a = ixheaac_add32_sat(a, (1 << (b - 1)));
390 out_val = (WORD32)a >> b;
391 }
392
393 return out_val;
394 }
395
ixheaac_mac16x16in32_sat(WORD32 a,WORD16 b,WORD16 c)396 static PLATFORM_INLINE WORD32 ixheaac_mac16x16in32_sat(WORD32 a, WORD16 b, WORD16 c) {
397 WORD32 acc;
398
399 acc = ixheaac_mult16x16in32(b, c);
400
401 acc = ixheaac_add32_sat(a, acc);
402
403 return acc;
404 }
405
ixheaac_mac16x16in32_shl(WORD32 a,WORD16 b,WORD16 c)406 static PLATFORM_INLINE WORD32 ixheaac_mac16x16in32_shl(WORD32 a, WORD16 b, WORD16 c) {
407 WORD32 acc;
408
409 acc = ixheaac_mult16x16in32_shl(b, c);
410
411 acc = ixheaac_add32(a, acc);
412
413 return acc;
414 }
415
ixheaac_mac16x16in32_shl_sat(WORD32 a,WORD16 b,WORD16 c)416 static PLATFORM_INLINE WORD32 ixheaac_mac16x16in32_shl_sat(WORD32 a, WORD16 b, WORD16 c) {
417 WORD32 acc;
418
419 acc = ixheaac_mult16x16in32_shl_sat(b, c);
420
421 acc = ixheaac_add32_sat(a, acc);
422
423 return acc;
424 }
425
ixheaac_msu16x16in32(WORD32 a,WORD16 b,WORD16 c)426 static PLATFORM_INLINE WORD32 ixheaac_msu16x16in32(WORD32 a, WORD16 b, WORD16 c) {
427 WORD32 acc;
428
429 acc = ixheaac_mult16x16in32(b, c);
430
431 acc = ixheaac_sub32(a, acc);
432
433 return acc;
434 }
435
436 #endif /* IXHEAAC_BASIC_OPS32_H */
437