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
mac32x16in32_shl_sat(WORD32 a,WORD32 b,WORD16 c)159 static PLATFORM_INLINE WORD32 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(WORD64 sum,const WORD32 * a,const WORD16 * b)296 static PLATFORM_INLINE WORD64 ixheaacd_mac32x32in64_7(WORD64 sum,
297 const WORD32 *a,
298 const WORD16 *b) {
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_add64(WORD64 a,WORD64 b)348 static PLATFORM_INLINE WORD64 ixheaacd_add64(WORD64 a, WORD64 b) {
349 WORD64 result;
350 result = a + b;
351 return (result);
352 }
353
ixheaacd_sub64(WORD64 a,WORD64 b)354 static PLATFORM_INLINE WORD64 ixheaacd_sub64(WORD64 a, WORD64 b) {
355 WORD64 diff;
356
357 diff = (WORD64)a - (WORD64)b;
358
359 return diff;
360 }
361
ixheaacd_sub64_sat(WORD64 a,WORD64 b)362 static PLATFORM_INLINE WORD64 ixheaacd_sub64_sat(WORD64 a, WORD64 b) {
363 WORD64 diff;
364
365 diff = ixheaacd_sub64(a, b);
366
367 if ((((WORD64)a ^ (WORD64)b) & (WORD64)MIN_64) != 0) {
368 if (((WORD64)diff ^ (WORD64)a) & (WORD64)MIN_64) {
369 diff = (a < 0L) ? MIN_64 : MAX_64;
370 }
371 }
372
373 return (diff);
374 }
375
ixheaacd_mul32_sh(WORD32 a,WORD32 b,WORD8 shift)376 static PLATFORM_INLINE WORD32 ixheaacd_mul32_sh(WORD32 a, WORD32 b,
377 WORD8 shift) {
378 WORD32 result;
379 WORD64 temp_result;
380
381 temp_result = (WORD64)a * (WORD64)b;
382 result = (WORD32)(temp_result >> shift);
383
384 return (result);
385 }
386
387 #endif
388