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_OPS40_H
21 #define IXHEAACD_BASIC_OPS40_H
22 #define lo64(a) (((unsigned *)&a)[0])
23 #define hi64(a) (((WORD32 *)&a)[1])
24
norm40(WORD40 * in)25 static PLATFORM_INLINE WORD16 norm40(WORD40 *in) {
26 WORD16 expo;
27 WORD32 tempo;
28
29 if (0 == (*in)) return 31;
30
31 if (((*in) <= 0x7fffffff) && ((WORD40)(*in) >= (WORD40)0xFFFFFFFF80000000)) {
32 tempo = (WORD32)(*in);
33 expo = ixheaacd_norm32(tempo);
34 *in = tempo << expo;
35
36 return (expo);
37 }
38
39 tempo = (WORD32)((*in) >> 31);
40 expo = 31 - (ixheaacd_norm32(tempo));
41 *in = (*in) >> expo;
42
43 return (-expo);
44 }
45
add32_shr40(WORD32 a,WORD32 b)46 static PLATFORM_INLINE WORD32 add32_shr40(WORD32 a, WORD32 b) {
47 WORD40 sum;
48
49 sum = (WORD40)a + (WORD40)b;
50 sum = sum >> 1;
51
52 return ((WORD32)sum);
53 }
54
sub32_shr40(WORD32 a,WORD32 b)55 static PLATFORM_INLINE WORD32 sub32_shr40(WORD32 a, WORD32 b) {
56 WORD40 sum;
57
58 sum = (WORD40)a - (WORD40)b;
59 sum = sum >> 1;
60
61 return ((WORD32)sum);
62 }
63
ixheaacd_mult32x16in32_shl(WORD32 a,WORD16 b)64 static PLATFORM_INLINE WORD32 ixheaacd_mult32x16in32_shl(WORD32 a, WORD16 b) {
65 WORD32 result;
66 WORD64 temp_result;
67
68 temp_result = (WORD64)a * (WORD64)b;
69
70 result = (WORD32)(temp_result >> 16);
71
72 return (result << 1);
73 }
74
mult32x16hin32_shl(WORD32 a,WORD32 b)75 static PLATFORM_INLINE WORD32 mult32x16hin32_shl(WORD32 a, WORD32 b) {
76 WORD32 product;
77 WORD64 temp_product;
78
79 temp_product = (WORD64)a * (WORD64)(b >> 16);
80 product = (WORD32)(temp_product >> 16);
81
82 return (product << 1);
83 }
84
ixheaacd_mult32x16in32(WORD32 a,WORD16 b)85 static PLATFORM_INLINE WORD32 ixheaacd_mult32x16in32(WORD32 a, WORD16 b) {
86 WORD32 result;
87 WORD64 temp_result;
88
89 temp_result = (WORD64)a * (WORD64)b;
90
91 result = (WORD32)(temp_result >> 16);
92
93 return (result);
94 }
95
ixheaacd_mult32x16in32_shl_sat(WORD32 a,WORD16 b)96 static PLATFORM_INLINE WORD32 ixheaacd_mult32x16in32_shl_sat(WORD32 a,
97 WORD16 b) {
98 WORD32 result;
99
100 if (a == (WORD32)0x80000000 && b == (WORD16)0x8000) {
101 result = (WORD32)0x7fffffff;
102 } else {
103 result = ixheaacd_mult32x16in32_shl(a, b);
104 }
105
106 return (result);
107 }
108
ixheaacd_mult32_shl(WORD32 a,WORD32 b)109 static PLATFORM_INLINE WORD32 ixheaacd_mult32_shl(WORD32 a, WORD32 b) {
110 WORD32 result;
111 WORD64 temp_result;
112
113 temp_result = (WORD64)a * (WORD64)b;
114 result = (WORD32)(temp_result >> 32);
115
116 return (result << 1);
117 }
118
ixheaacd_mult32(WORD32 a,WORD32 b)119 static PLATFORM_INLINE WORD32 ixheaacd_mult32(WORD32 a, WORD32 b) {
120 WORD32 result;
121 WORD64 temp_result;
122
123 temp_result = (WORD64)a * (WORD64)b;
124 result = (WORD32)(temp_result >> 32);
125
126 return (result);
127 }
128
ixheaacd_mult32_shl_sat(WORD32 a,WORD32 b)129 static PLATFORM_INLINE WORD32 ixheaacd_mult32_shl_sat(WORD32 a, WORD32 b) {
130 WORD32 result;
131
132 if (a == (WORD32)0x80000000 && b == (WORD32)0x80000000) {
133 result = 0x7fffffff;
134 } else {
135 result = ixheaacd_mult32_shl(a, b);
136 }
137
138 return (result);
139 }
140
ixheaacd_mac32x16in32(WORD32 a,WORD32 b,WORD16 c)141 static PLATFORM_INLINE WORD32 ixheaacd_mac32x16in32(WORD32 a, WORD32 b,
142 WORD16 c) {
143 WORD32 result;
144
145 result = a + ixheaacd_mult32x16in32(b, c);
146
147 return (result);
148 }
149
ixheaacd_mac32x16in32_shl(WORD32 a,WORD32 b,WORD16 c)150 static PLATFORM_INLINE WORD32 ixheaacd_mac32x16in32_shl(WORD32 a, WORD32 b,
151 WORD16 c) {
152 WORD32 result;
153
154 result = a + ixheaacd_mult32x16in32_shl(b, c);
155
156 return (result);
157 }
158
ixheaacd_mac32x16in32_shl_sat(WORD32 a,WORD32 b,WORD16 c)159 static PLATFORM_INLINE WORD32 ixheaacd_mac32x16in32_shl_sat(WORD32 a, WORD32 b,
160 WORD16 c) {
161 return (ixheaacd_add32_sat(a, ixheaacd_mult32x16in32_shl_sat(b, c)));
162 }
163
ixheaacd_mac32(WORD32 a,WORD32 b,WORD32 c)164 static PLATFORM_INLINE WORD32 ixheaacd_mac32(WORD32 a, WORD32 b, WORD32 c) {
165 WORD32 result;
166
167 result = a + ixheaacd_mult32(b, c);
168
169 return (result);
170 }
171
mac32_shl(WORD32 a,WORD32 b,WORD32 c)172 static PLATFORM_INLINE WORD32 mac32_shl(WORD32 a, WORD32 b, WORD32 c) {
173 WORD32 result;
174
175 result = a + ixheaacd_mult32_shl(b, c);
176
177 return (result);
178 }
179
mac32_shl_sat(WORD32 a,WORD32 b,WORD32 c)180 static PLATFORM_INLINE WORD32 mac32_shl_sat(WORD32 a, WORD32 b, WORD32 c) {
181 return (ixheaacd_add32_sat(a, ixheaacd_mult32_shl_sat(b, c)));
182 }
183
msu32x16in32(WORD32 a,WORD32 b,WORD16 c)184 static PLATFORM_INLINE WORD32 msu32x16in32(WORD32 a, WORD32 b, WORD16 c) {
185 WORD32 result;
186
187 result = a - ixheaacd_mult32x16in32(b, c);
188
189 return (result);
190 }
191
msu32x16in32_shl(WORD32 a,WORD32 b,WORD16 c)192 static PLATFORM_INLINE WORD32 msu32x16in32_shl(WORD32 a, WORD32 b, WORD16 c) {
193 WORD32 result;
194
195 result = a - ixheaacd_mult32x16in32_shl(b, c);
196
197 return (result);
198 }
199
msu32x16in32_shl_sat(WORD32 a,WORD32 b,WORD16 c)200 static PLATFORM_INLINE WORD32 msu32x16in32_shl_sat(WORD32 a, WORD32 b,
201 WORD16 c) {
202 return (ixheaacd_sub32_sat(a, ixheaacd_mult32x16in32_shl_sat(b, c)));
203 }
204
msu32(WORD32 a,WORD32 b,WORD32 c)205 static PLATFORM_INLINE WORD32 msu32(WORD32 a, WORD32 b, WORD32 c) {
206 WORD32 result;
207
208 result = a - ixheaacd_mult32(b, c);
209
210 return (result);
211 }
212
msu32_shl(WORD32 a,WORD32 b,WORD32 c)213 static PLATFORM_INLINE WORD32 msu32_shl(WORD32 a, WORD32 b, WORD32 c) {
214 WORD32 result;
215
216 result = a - ixheaacd_mult32_shl(b, c);
217
218 return (result);
219 }
220
msu32_shl_sat(WORD32 a,WORD32 b,WORD32 c)221 static PLATFORM_INLINE WORD32 msu32_shl_sat(WORD32 a, WORD32 b, WORD32 c) {
222 return (ixheaacd_sub32_sat(a, ixheaacd_mult32_shl_sat(b, c)));
223 }
224
mac3216_arr40(WORD32 * x,WORD16 * y,LOOPINDEX length,WORD16 * q_val)225 static PLATFORM_INLINE WORD32 mac3216_arr40(WORD32 *x, WORD16 *y,
226 LOOPINDEX length, WORD16 *q_val) {
227 LOOPINDEX i;
228 WORD40 sum = 0;
229
230 for (i = 0; i < length; i++) {
231 sum += (WORD40)(ixheaacd_mult32x16in32(x[i], y[i]));
232 }
233
234 *q_val = norm40(&sum);
235
236 return (WORD32)sum;
237 }
238
mac32_arr40(WORD32 * x,WORD32 * y,LOOPINDEX length,WORD16 * q_val)239 static PLATFORM_INLINE WORD32 mac32_arr40(WORD32 *x, WORD32 *y,
240 LOOPINDEX length, WORD16 *q_val) {
241 LOOPINDEX i;
242 WORD40 sum = 0;
243
244 for (i = 0; i < length; i++) {
245 sum += (WORD40)(ixheaacd_mult32(x[i], y[i]));
246 }
247
248 *q_val = norm40(&sum);
249
250 return ((WORD32)sum);
251 }
252
mac16_arr40(WORD16 * x,WORD16 * y,LOOPINDEX length,WORD16 * q_val)253 static PLATFORM_INLINE WORD32 mac16_arr40(WORD16 *x, WORD16 *y,
254 LOOPINDEX length, WORD16 *q_val) {
255 LOOPINDEX i;
256 WORD40 sum = 0;
257
258 for (i = 0; i < length; i++) {
259 sum += (WORD40)((WORD32)x[i] * (WORD32)y[i]);
260 }
261
262 *q_val = norm40(&sum);
263
264 return ((WORD32)sum);
265 }
266
add32_arr40(WORD32 * in_arr,LOOPINDEX length,WORD16 * q_val)267 static PLATFORM_INLINE WORD32 add32_arr40(WORD32 *in_arr, LOOPINDEX length,
268 WORD16 *q_val) {
269 LOOPINDEX i;
270 WORD40 sum = 0;
271
272 for (i = 0; i < length; i++) {
273 sum += (WORD40)in_arr[i];
274 }
275
276 *q_val = norm40(&sum);
277
278 return ((WORD32)sum);
279 }
280
ixheaacd_mult32x32in64(WORD32 a,WORD32 b)281 static PLATFORM_INLINE WORD64 ixheaacd_mult32x32in64(WORD32 a, WORD32 b) {
282 WORD64 result;
283
284 result = (WORD64)a * (WORD64)b;
285
286 return (result);
287 }
288
ixheaacd_mac32x32in64(WORD64 sum,WORD32 a,WORD32 b)289 static PLATFORM_INLINE WORD64 ixheaacd_mac32x32in64(WORD64 sum, WORD32 a,
290 WORD32 b) {
291 sum += (WORD64)a * (WORD64)b;
292
293 return (sum);
294 }
295
ixheaacd_mac32x32in64_7(const WORD32 * a,const WORD16 * b)296 static PLATFORM_INLINE WORD64 ixheaacd_mac32x32in64_7(const WORD32 *a,
297 const WORD16 *b) {
298 WORD64 sum;
299 sum = (WORD64)a[0] * (WORD64)b[0];
300 sum += (WORD64)a[1] * (WORD64)b[1];
301 sum += (WORD64)a[2] * (WORD64)b[2];
302 sum += (WORD64)a[3] * (WORD64)b[3];
303 sum += (WORD64)a[4] * (WORD64)b[4];
304 sum += (WORD64)a[5] * (WORD64)b[5];
305 sum += (WORD64)a[6] * (WORD64)b[6];
306
307 return (sum);
308 }
309
ixheaacd_mac32x32in64_n(WORD64 sum,const WORD32 * a,const WORD16 * b,WORD32 n)310 static PLATFORM_INLINE WORD64 ixheaacd_mac32x32in64_n(WORD64 sum,
311 const WORD32 *a,
312 const WORD16 *b,
313 WORD32 n) {
314 WORD32 k;
315
316 sum += (WORD64)a[0] * (WORD64)b[0];
317 for (k = 1; k < n; k++) sum += (WORD64)a[k] * (WORD64)b[k];
318 return (sum);
319 }
320
ixheaacd_mult64(WORD32 a,WORD32 b)321 static PLATFORM_INLINE WORD64 ixheaacd_mult64(WORD32 a, WORD32 b) {
322 WORD64 result;
323 result = (WORD64)a * (WORD64)b;
324 return (result);
325 }
326
ixheaacd_mult64_sat(WORD64 a,WORD64 b)327 static PLATFORM_INLINE WORD64 ixheaacd_mult64_sat(WORD64 a, WORD64 b) {
328 WORD64 result;
329
330 if (a > 0 && b > 0 && a > MAX_64 / b) return MAX_64;
331 if (a < 0 && b > 0 && a < MIN_64 / b) return MIN_64;
332 if (a > 0 && b < 0 && b < MIN_64 / a) return MIN_64;
333 if (a < 0 && b < 0 && a < MAX_64 / b) return MAX_64;
334
335 result = a * b;
336 return (result);
337 }
338
ixheaacd_add64_sat(WORD64 a,WORD64 b)339 static PLATFORM_INLINE WORD64 ixheaacd_add64_sat(WORD64 a, WORD64 b) {
340 WORD64 result, comp;
341 result = (a < 0) ? MIN_64 : MAX_64;
342 comp = result - a;
343 if ((a < 0) == (b > comp)) result = a + b;
344
345 return (result);
346 }
347
ixheaacd_sat64_32(WORD64 a)348 static PLATFORM_INLINE WORD32 ixheaacd_sat64_32(WORD64 a) {
349 WORD32 result;
350 if (a >= MAX_32) {
351 result = MAX_32;
352 } else if (a <= MIN_32) {
353 result = MIN_32;
354 } else
355 result = (WORD32)a;
356
357 return (result);
358 }
359
ixheaacd_add64(WORD64 a,WORD64 b)360 static PLATFORM_INLINE WORD64 ixheaacd_add64(WORD64 a, WORD64 b) {
361 WORD64 result;
362 result = a + b;
363 return (result);
364 }
365
ixheaacd_sub64(WORD64 a,WORD64 b)366 static PLATFORM_INLINE WORD64 ixheaacd_sub64(WORD64 a, WORD64 b) {
367 WORD64 diff;
368
369 diff = (WORD64)a - (WORD64)b;
370
371 return diff;
372 }
373
ixheaacd_sub64_sat(WORD64 a,WORD64 b)374 static PLATFORM_INLINE WORD64 ixheaacd_sub64_sat(WORD64 a, WORD64 b) {
375 WORD64 diff;
376
377 diff = ixheaacd_sub64(a, b);
378
379 if ((((WORD64)a ^ (WORD64)b) & (WORD64)MIN_64) != 0) {
380 if (((WORD64)diff ^ (WORD64)a) & (WORD64)MIN_64) {
381 diff = (a < 0L) ? MIN_64 : MAX_64;
382 }
383 }
384
385 return (diff);
386 }
387
ixheaacd_mul32_sh(WORD32 a,WORD32 b,WORD8 shift)388 static PLATFORM_INLINE WORD32 ixheaacd_mul32_sh(WORD32 a, WORD32 b,
389 WORD8 shift) {
390 WORD32 result;
391 WORD64 temp_result;
392
393 temp_result = (WORD64)a * (WORD64)b;
394 result = (WORD32)(temp_result >> shift);
395
396 return (result);
397 }
398
399 #endif
400