Line data Source code
1 : /******************************************************************************************************
2 :
3 : (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
4 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
5 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
6 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
7 : contributors to this repository. All Rights Reserved.
8 :
9 : This software is protected by copyright law and by international treaties.
10 : The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
11 : Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
12 : Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
13 : Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
14 : contributors to this repository retain full ownership rights in their respective contributions in
15 : the software. This notice grants no license of any kind, including but not limited to patent
16 : license, nor is any license granted by implication, estoppel or otherwise.
17 :
18 : Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
19 : contributions.
20 :
21 : This software is provided "AS IS", without any express or implied warranties. The software is in the
22 : development stage. It is intended exclusively for experts who have experience with such software and
23 : solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
24 : and fitness for a particular purpose are hereby disclaimed and excluded.
25 :
26 : Any dispute, controversy or claim arising under or in relation to providing this software shall be
27 : submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
28 : accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
29 : the United Nations Convention on Contracts on the International Sales of Goods.
30 :
31 : *******************************************************************************************************/
32 :
33 : #include <assert.h>
34 : #include <stdint.h>
35 : #include "options.h"
36 : #include <math.h>
37 : #include "prot_fx.h"
38 : #include "wmc_auto.h"
39 : #include "ivas_rom_com.h"
40 : #include "ivas_prot_fx.h"
41 :
42 : #define ANGLE_90_DEG_Q22 377487360
43 : #define ANGLE_180_DEG_Q22 754974720
44 : #define ANGLE_360_DEG_Q22 1509949440
45 :
46 : /*---------------------------------------------------------------
47 : * sumAbs()
48 : *
49 : * sum of absolute values
50 : * ---------------------------------------------------------------*/
51 :
52 0 : Word32 sumAbs_fx(
53 : const Word32 *vec, /* i : input vector Qx*/
54 : const Word16 lvec /* i : length of input vector Q0*/
55 : )
56 : {
57 : Word16 i;
58 : Word32 tmp; /*Qx*/
59 :
60 0 : tmp = 0;
61 0 : move32();
62 0 : FOR( i = 0; i < lvec; i++ )
63 : {
64 0 : tmp = L_add( tmp, L_abs( vec[i] ) ); /*Qx*/
65 : }
66 :
67 0 : return tmp;
68 : }
69 :
70 : /*---------------------------------------------------------------------*
71 : * mvc2c()
72 : *
73 : * Transfer the contents of vector x[] to vector y[] in char format
74 : *---------------------------------------------------------------------*/
75 :
76 38621 : void mvc2c(
77 : const UWord8 x[], /* i : input vector */
78 : UWord8 y[], /* o : output vector */
79 : const Word16 n /* i : vector size */
80 : )
81 : {
82 : Word16 i;
83 :
84 38621 : IF( n <= 0 )
85 : {
86 : /* no need to transfer vectors with size 0 */
87 0 : return;
88 : }
89 :
90 38621 : IF( y < x )
91 : {
92 3748610 : FOR( i = 0; i < n; i++ )
93 : {
94 3730323 : y[i] = x[i];
95 3730323 : move16();
96 : }
97 : }
98 : ELSE
99 : {
100 87405 : FOR( i = n - 1; i >= 0; i-- )
101 : {
102 67071 : y[i] = x[i];
103 67071 : move16();
104 : }
105 : }
106 :
107 38621 : return;
108 : }
109 :
110 :
111 : /*-------------------------------------------------------------------*
112 : * ivas_syn_output()
113 : *
114 : * Output ivas synthesis signal with compensation for saturation
115 : * returns number of clipped samples
116 : *-------------------------------------------------------------------*/
117 :
118 : /*! r: number of clipped samples */
119 412070 : UWord32 ivas_syn_output_fx(
120 : Word32 *synth[], /* i/o: float synthesis signal q_synth*/
121 : const Word16 q_synth,
122 : const Word16 output_frame, /* i : output frame length (one channel) Q0*/
123 : const Word16 n_channels, /* i : number of output channels Q0*/
124 : Word16 *synth_out /* o : integer 16 bits synthesis signal Q0*/
125 : )
126 : {
127 : Word16 i, n;
128 : Word16 synth_loc[MAX_JBM_L_FRAME48k];
129 : UWord32 tmp;
130 412070 : UWord32 noClipping = 0;
131 412070 : move32();
132 :
133 : /*-----------------------------------------------------------------*
134 : * float to integer conversion with saturation control
135 : *-----------------------------------------------------------------*/
136 :
137 1880415 : FOR( n = 0; n < n_channels; n++ )
138 : {
139 1468345 : tmp = mvl2s_r( synth[n], q_synth, synth_loc, output_frame ); /*Q0*/
140 1468345 : noClipping = UL_addNsD( noClipping, tmp );
141 :
142 1172866425 : FOR( i = 0; i < output_frame; i++ )
143 : {
144 1171398080 : synth_out[( ( i * n_channels ) + n )] = synth_loc[i]; /*q_synth*/
145 1171398080 : move16();
146 : }
147 : }
148 :
149 412070 : return noClipping; /*Q0*/
150 : }
151 :
152 :
153 : /*-------------------------------------------------------------------*
154 : * ivas_syn_output_f()
155 : *
156 : * Output ivas synthesis signal with compensation for saturation
157 : * returns number of clipped samples
158 : *-------------------------------------------------------------------*/
159 :
160 : /*! r: number of clipped samples */
161 19405 : void ivas_syn_output_f_fx(
162 : Word32 *synth[], /* i/o: float synthesis signal Q11*/
163 : const Word16 output_frame, /* i : output frame length (one channel) Q0*/
164 : const Word16 n_channels, /* i : number of output channels Q0*/
165 : Word32 *synth_out /* o : integer 16 bits synthesis signal Q11*/
166 : )
167 : {
168 : Word16 i, n;
169 :
170 : /*-----------------------------------------------------------------*
171 : * float to integer conversion with saturation control
172 : *-----------------------------------------------------------------*/
173 :
174 63116 : FOR( n = 0; n < n_channels; n++ )
175 : {
176 34908031 : FOR( i = 0; i < output_frame; i++ )
177 : {
178 34864320 : synth_out[( ( i * n_channels ) + n )] = synth[n][i]; /*Q11*/
179 34864320 : move16();
180 : }
181 : }
182 :
183 19405 : return;
184 : }
185 :
186 :
187 : /*-------------------------------------------------------------------*
188 : * mvr2r_inc()
189 : *
190 : *
191 : *-------------------------------------------------------------------*/
192 0 : void mvr2r_inc_fixed_one(
193 : const Word32 x_fx[], /* i : input vector Q29*/
194 : const Word16 x_inc, /* i : increment for vector x[] Q0*/
195 : Word32 y_fx[], /* o : output vector Q29*/
196 : const Word16 y_inc, /* i : increment for vector y[] Q0*/
197 : const Word16 n /* i : vector size Q0*/
198 : )
199 : {
200 : Word16 i;
201 : Word16 ix;
202 : Word16 iy;
203 :
204 0 : IF( n <= 0 )
205 : {
206 : /* cannot transfer vectors with size 0 */
207 0 : return;
208 : }
209 :
210 0 : IF( y_fx < x_fx )
211 : {
212 0 : ix = 0;
213 0 : move16();
214 0 : iy = 0;
215 0 : move16();
216 0 : FOR( i = 0; i < n; i++ )
217 : {
218 0 : y_fx[iy] = x_fx[ix]; /*Q29*/
219 0 : move32();
220 :
221 0 : ix = ix + x_inc;
222 0 : iy = iy + y_inc;
223 : }
224 : }
225 : ELSE
226 : {
227 0 : ix = imult1616( sub( n, 1 ), x_inc ); /*Q0*/
228 0 : iy = imult1616( sub( n, 1 ), y_inc ); /*Q0*/
229 0 : FOR( i = ( n - 1 ); i >= 0; i-- )
230 : {
231 0 : y_fx[iy] = x_fx[ix]; /*Q29*/
232 0 : move32();
233 :
234 0 : ix = ix - x_inc;
235 0 : iy = iy - y_inc;
236 : }
237 : }
238 :
239 0 : return;
240 : }
241 :
242 80852919 : void mvr2r_inc_fixed(
243 : const Word32 x_fx[], /* i : input vector Q29*/
244 : const Word16 x_inc, /* i : increment for vector x[] Q0*/
245 : Word32 y_fx[], /* o : output vector Q29*/
246 : const Word16 y_inc, /* i : increment for vector y[] Q0*/
247 : const Word16 n /* i : vector size Q0*/
248 : )
249 : {
250 : Word16 i;
251 : Word16 ix;
252 : Word16 iy;
253 :
254 80852919 : IF( n <= 0 )
255 : {
256 : /* cannot transfer vectors with size 0 */
257 0 : return;
258 : }
259 :
260 80852919 : IF( y_fx < x_fx )
261 : {
262 73209942 : ix = 0;
263 73209942 : move16();
264 73209942 : iy = 0;
265 73209942 : move16();
266 1127534682 : FOR( i = 0; i < n; i++ )
267 : {
268 1054324740 : y_fx[iy] = x_fx[ix]; /*Q29*/
269 1054324740 : move32();
270 :
271 1054324740 : ix = ix + x_inc;
272 1054324740 : iy = iy + y_inc;
273 : }
274 : }
275 : ELSE
276 : {
277 7642977 : ix = i_mult( sub( n, 1 ), x_inc ); /*Q0*/
278 7642977 : iy = i_mult( sub( n, 1 ), y_inc );
279 57807899 : FOR( i = sub( n, 1 ); i >= 0; i-- )
280 : {
281 50164922 : y_fx[iy] = x_fx[ix]; /*Q29*/
282 50164922 : move32();
283 :
284 50164922 : ix = ix - x_inc;
285 50164922 : iy = iy - y_inc;
286 : }
287 : }
288 :
289 80852919 : return;
290 : }
291 :
292 : /*-------------------------------------------------------------------*
293 : * v_add_inc()
294 : *
295 : * Addition of two vectors sample by sample with explicit increments
296 : *-------------------------------------------------------------------*/
297 :
298 : // for same q//
299 8094690 : void v_add_inc_fx(
300 : const Word32 x1[], /* i : Input vector 1 Qx*/
301 : const Word16 x_inc, /* i : Increment for input vector 1 Q0*/
302 : const Word32 x2[], /* i : Input vector 2 Qx*/
303 : const Word16 x2_inc, /* i : Increment for input vector 2 Q0*/
304 : Word32 y[], /* o : Output vector that contains vector 1 + vector 2 Qx*/
305 : const Word16 y_inc, /* i : increment for vector y[] Q0*/
306 : const Word16 N /* i : Vector length Q0*/
307 : )
308 : {
309 : Word16 i, ix1, ix2, iy;
310 :
311 : /* The use of this function is currently always for the interleaved input format, */
312 : /* that means, the following conditions are always true and thus obsolete. */
313 8094690 : test();
314 8094690 : test();
315 8094690 : test();
316 8094690 : test();
317 8094690 : IF( ( sub( x_inc, 2 ) == 0 ) && ( sub( x2_inc, 2 ) == 0 ) && ( sub( y_inc, 1 ) == 0 ) && ( &x1[1] == &x2[0] ) )
318 : {
319 : /* Interleaved input case, linear output */
320 189560046 : FOR( i = 0; i < N; i++ )
321 : {
322 181465356 : y[i] = L_add( x1[2 * i + 0], x1[2 * i + 1] ); /*Qx*/
323 181465356 : move32();
324 : }
325 8094690 : return;
326 : }
327 :
328 0 : ix1 = 0;
329 0 : ix2 = 0;
330 0 : iy = 0;
331 0 : move16();
332 0 : move16();
333 0 : move16();
334 0 : FOR( i = 0; i < N; i++ )
335 : {
336 0 : y[iy] = L_add( x1[ix1], x2[ix2] ); /*Qx*/
337 0 : move32();
338 0 : ix1 = add( ix1, x_inc ); /*Q0*/
339 0 : ix2 = add( ix2, x2_inc ); /*Q0*/
340 0 : iy = add( iy, y_inc ); /*Q0*/
341 : }
342 0 : return;
343 : }
344 :
345 : /*-------------------------------------------------------------------*
346 : * v_mult_inc_fx()
347 : *
348 : * Multiplication of two vectors with explicit increments
349 : *-------------------------------------------------------------------*/
350 :
351 0 : void v_mult_inc_fx(
352 : const Word32 x1_fx[], /* i : Input vector 1 x1_q_fx*/
353 : Word16 *x1_q_fx,
354 : const Word16 x1_inc, /* i : Increment for input vector 1 Q0*/
355 : const Word32 x2_fx[], /* i : Input vector 2 x2_q_fx*/
356 : Word16 *x2_q_fx,
357 : const Word16 x2_inc, /* i : Increment for input vector 1 Q0*/
358 : Word32 y_fx[], /* o : Output vector that contains vector 1 .* vector 2 y_q_fx*/
359 : Word16 *y_q_fx,
360 : const Word16 y_inc, /* i : increment for vector y[i] Q0*/
361 : const Word16 N /* i : Vector length Q0*/
362 : )
363 : {
364 : Word16 i;
365 0 : Word16 ix1 = 0;
366 0 : Word16 ix2 = 0;
367 0 : Word16 iy = 0;
368 :
369 0 : move16();
370 0 : move16();
371 0 : move16();
372 :
373 0 : FOR( i = 0; i < N; i++ )
374 : {
375 0 : y_fx[iy] = Mpy_32_32( x1_fx[ix1], x2_fx[ix2] ); /* x1_q_fx + x2_q_fx - 31 */
376 0 : move32();
377 0 : y_q_fx[iy] = sub( add( x1_q_fx[ix1], x2_q_fx[ix2] ), 31 );
378 0 : move16();
379 :
380 0 : ix1 = add( ix1, x1_inc ); /*Q0*/
381 0 : ix2 = add( ix2, x2_inc ); /*Q0*/
382 0 : iy = add( iy, y_inc ); /*Q0*/
383 : }
384 :
385 0 : return;
386 : }
387 :
388 : // when buffers have constant q/
389 4284440 : void v_mult_inc_fixed(
390 : const Word32 x1_fx[], /* i : Input vector 1 Qx1*/
391 : const Word16 x1_inc, /* i : Increment for input vector 1 Q0*/
392 : const Word32 x2_fx[], /* i : Input vector 2 Qx2*/
393 : const Word16 x2_inc, /* i : Increment for input vector 1 Q0*/
394 : Word32 y_fx[], /* o : Output vector that contains vector 1 .* vector 2 Qx1 + Qx2 - 31*/
395 : const Word16 y_inc, /* i : increment for vector y[i] Q0*/
396 : const Word16 N /* i : Vector length Q0*/
397 : )
398 : {
399 : Word16 i;
400 4284440 : Word16 ix1 = 0;
401 4284440 : Word16 ix2 = 0;
402 4284440 : Word16 iy = 0;
403 :
404 4284440 : move16();
405 4284440 : move16();
406 4284440 : move16();
407 :
408 73489728 : FOR( i = 0; i < N; i++ )
409 : {
410 69205288 : y_fx[iy] = Mpy_32_32( x1_fx[ix1], x2_fx[ix2] ); /*Qx1 + Qx2 - 31*/
411 69205288 : move32();
412 :
413 69205288 : ix1 = add( ix1, x1_inc );
414 69205288 : ix2 = add( ix2, x2_inc );
415 69205288 : iy = add( iy, y_inc );
416 : }
417 :
418 4284440 : return;
419 : }
420 :
421 : /*-------------------------------------------------------------------*
422 : * v_addc_fx()
423 : *
424 : * Addition of constant to vector
425 : *-------------------------------------------------------------------*/
426 :
427 0 : void v_addc_fx(
428 : const Word32 x_fx[], /* i : Input vector Qx*/
429 : const Word32 c_fx, /* i : Constant Qx*/
430 : Word32 y_fx[], /* o : Output vector that contains c*x Qx*/
431 : const Word16 N /* i : Vector length Q0*/
432 : )
433 : {
434 : Word16 i;
435 :
436 0 : FOR( i = 0; i < N; i++ )
437 : {
438 0 : y_fx[i] = L_add( c_fx, x_fx[i] ); /*Qx*/
439 0 : move32();
440 : }
441 :
442 0 : return;
443 : }
444 : /*-------------------------------------------------------------------*
445 : * v_addc()
446 : *
447 : * Addition of constant to vector
448 : *-------------------------------------------------------------------*/
449 2047467 : void v_addc_fixed(
450 : const Word32 x[], /* i : Input vector Qx*/
451 : const Word32 c, /* i : Constant Qx*/
452 : Word32 y[], /* o : Output vector that contains c*x Qx*/
453 : const Word16 N /* i : Vector length Q0*/
454 : )
455 : {
456 : Word16 i;
457 :
458 58173287 : FOR( i = 0; i < N; i++ )
459 : {
460 56125820 : y[i] = L_add( c, x[i] ); /*Qx*/
461 56125820 : move32();
462 : }
463 :
464 2047467 : return;
465 : }
466 :
467 : /*-------------------------------------------------------------------*
468 : * v_min_fx()
469 : *
470 : * minimum of two vectors
471 : *-------------------------------------------------------------------*/
472 :
473 2400 : void v_min_fx(
474 : const Word32 x1_fx[], /* i : Input vector 1 x1_q_fx*/
475 : Word16 *x1_q_fx,
476 : const Word32 x2_fx[], /* i : Input vector 2 x2_q_fx*/
477 : Word16 *x2_q_fx,
478 : Word32 y_fx[], /* o : Output vector that contains vector 1 .* vector 2 y_q_fx*/
479 : Word16 *y_q_fx,
480 : const Word16 N /* i : Vector length Q0*/
481 : )
482 : {
483 : Word16 i;
484 :
485 60000 : FOR( i = 0; i < N; i++ )
486 : {
487 57600 : IF( GT_16( x1_q_fx[i], x2_q_fx[i] ) )
488 : {
489 0 : IF( LT_32( L_shr( x1_fx[i], sub( x1_q_fx[i], x2_q_fx[i] ) ), x2_fx[i] ) )
490 : {
491 0 : y_fx[i] = x1_fx[i]; /*x1_q_fx*/
492 0 : move32();
493 0 : y_q_fx[i] = x1_q_fx[i];
494 0 : move16();
495 : }
496 : ELSE
497 : {
498 0 : y_fx[i] = x2_fx[i]; /*x2_q_fx*/
499 0 : move32();
500 0 : y_q_fx[i] = x2_q_fx[i];
501 0 : move16();
502 : }
503 : }
504 : ELSE
505 : {
506 57600 : IF( LT_32( x1_fx[i], L_shr( x2_fx[i], sub( x2_q_fx[i], x1_q_fx[i] ) ) ) )
507 : {
508 52216 : y_fx[i] = x1_fx[i]; /*x1_q_fx*/
509 52216 : move32();
510 52216 : y_q_fx[i] = x1_q_fx[i];
511 52216 : move16();
512 : }
513 : ELSE
514 : {
515 5384 : y_fx[i] = x2_fx[i]; /*x2_q_fx*/
516 5384 : move32();
517 5384 : y_q_fx[i] = x2_q_fx[i];
518 5384 : move16();
519 : }
520 : }
521 : }
522 :
523 2400 : return;
524 : }
525 :
526 : /*-------------------------------------------------------------------*
527 : * v_sqrt()
528 : *
529 : * square root of vector
530 : *-------------------------------------------------------------------*/
531 315180 : void v_sqrt_fx(
532 : const Word32 x[], /* i : Input vector Qx*/
533 : Word16 exp[],
534 : Word32 y[], /* o : Output vector that contains sqrt(x) Q31 - exp[]*/
535 : const Word16 N /* i : Vector length Q0*/
536 : )
537 : {
538 : Word16 i;
539 :
540 945540 : FOR( i = 0; i < N; i++ )
541 : {
542 630360 : y[i] = Sqrt32( x[i], &exp[i] ); /*Q31 - exp[i]*/
543 630360 : move32();
544 : }
545 :
546 315180 : return;
547 : }
548 :
549 : /*-------------------------------------------------------------------*
550 : * v_sub_s()
551 : *
552 : * Subtraction of two vectors
553 : *-------------------------------------------------------------------*/
554 :
555 0 : void v_sub_s16_fx(
556 : const Word16 x1[], /* i : Input vector 1 Qx*/
557 : const Word16 x2[], /* i : Input vector 2 Qx*/
558 : Word16 y[], /* o : Output vector that contains vector 1 - vector 2 Qx*/
559 : const Word16 N /* i : Vector length Q0*/
560 : )
561 : {
562 : Word16 i;
563 :
564 0 : FOR( i = 0; i < N; i++ )
565 : {
566 0 : y[i] = sub( x1[i], x2[i] ); /*Qx*/
567 0 : move16();
568 : }
569 :
570 0 : return;
571 : }
572 :
573 :
574 0 : void v_sub32_fx(
575 : const Word32 x1[], /* i : Input vector 1 Qx*/
576 : const Word32 x2[], /* i : Input vector 2 Qx*/
577 : Word32 y[], /* o : Output vector that contains vector 1 - vector 2 Qx*/
578 : const Word16 N /* i : Vector length Q0*/
579 : )
580 : {
581 : Word16 i;
582 :
583 0 : FOR( i = 0; i < N; i++ )
584 : {
585 0 : y[i] = L_sub( x1[i], x2[i] ); /*Qx*/
586 0 : move32();
587 : }
588 :
589 0 : return;
590 : }
591 :
592 : /*---------------------------------------------------------------------*
593 : * dot_product_cholesky()
594 : *
595 : * Calculates dot product of type x'*A*A'*x, where x is column vector of size m,
596 : * and A is a Cholesky decomposition of some Hermitian matrix S whose size is m*m.
597 : * Therefore, S=A*A' where A is upper triangular matrix of size (m*m+m)/2 (zeros ommitted, column-wise)
598 : *---------------------------------------------------------------------*/
599 :
600 : /*! r: the dot product x'*A*A'*x */
601 0 : Word64 dot_product_cholesky_fixed(
602 : const Word32 *x, /* i : vector x Q31 - exp_x*/
603 : const Word32 *A, /* i : Cholesky matrix A Q31 - exp_A*/
604 : const Word16 N /* i : vector & matrix size Q0*/
605 : )
606 : {
607 : Word16 i, j;
608 : Word64 suma, tmp_sum;
609 : Word32 mul;
610 : Word32 tmp;
611 : const Word32 *pt_x, *pt_A;
612 0 : pt_A = A;
613 0 : suma = 0;
614 0 : move64();
615 :
616 0 : FOR( i = 0; i < N; i++ )
617 : {
618 0 : tmp_sum = 0;
619 0 : move32();
620 0 : pt_x = x;
621 :
622 0 : FOR( j = 0; j <= i; j++ )
623 : {
624 0 : mul = Mpy_32_32( *pt_x++, *pt_A++ );
625 0 : tmp_sum = W_add( tmp_sum, W_deposit32_l( mul ) );
626 : }
627 :
628 0 : tmp_sum = W_shr( tmp_sum, 4 ); // to make sure that the tmp_sum will not overflow
629 0 : tmp = W_extract_l( tmp_sum );
630 0 : suma = W_mac_32_32( suma, tmp, tmp );
631 : }
632 :
633 0 : return suma;
634 : }
635 :
636 0 : void v_mult_mat_fixed(
637 : Word32 *y, /* o : the product x*A Qx - guardbits*/
638 : const Word32 *x, /* i : vector x Qx*/
639 : const Word32 *A, /* i : matrix A Q31*/
640 : const Word16 Nr, /* i : number of rows Q0*/
641 : const Word16 Nc, /* i : number of columns Q0*/
642 : Word16 guardbits )
643 : {
644 : Word16 i, j;
645 : const Word32 *pt_x, *pt_A;
646 : Word32 tmp_y[MAX_V_MULT_MAT];
647 : Word32 *pt_y;
648 :
649 0 : pt_y = tmp_y;
650 0 : pt_A = A; /*Q31*/
651 :
652 0 : FOR( i = 0; i < Nc; i++ )
653 : {
654 0 : pt_x = x; /*Qx*/
655 0 : *pt_y = 0;
656 0 : move32();
657 0 : FOR( j = 0; j < Nr; j++ )
658 : {
659 0 : *pt_y = L_add( *pt_y, L_shr( Mpy_32_32( ( *pt_x++ ), ( *pt_A++ ) ), guardbits ) ); /*Qx - guardbits*/
660 0 : move32();
661 : }
662 0 : pt_y++;
663 : }
664 :
665 0 : MVR2R_WORD32( tmp_y, y, Nc ); /*Qx - guardbits*/
666 0 : }
667 :
668 0 : Word32 dot_product_cholesky_fx(
669 : const Word32 *x, /* i : vector x Qx1*/
670 : const Word32 *A, /* i : Cholesky matrix A Qx2*/
671 : const Word16 N /* i : vector & matrix size Q0*/
672 : )
673 : {
674 : Word16 i, j;
675 : Word32 suma, tmp_sum;
676 : const Word32 *pt_x, *pt_A;
677 :
678 0 : pt_A = A;
679 0 : suma = 0;
680 0 : move32();
681 :
682 0 : FOR( i = 0; i < N; i++ )
683 : {
684 0 : tmp_sum = 0;
685 0 : move32();
686 0 : pt_x = x;
687 0 : FOR( j = 0; j <= i; j++ )
688 : {
689 0 : tmp_sum = L_add( tmp_sum, Mpy_32_32( *pt_x++, *pt_A++ ) ); /*Qx1 + Qx2 - 31*/
690 : }
691 :
692 0 : suma = L_add( suma, Mpy_32_32( tmp_sum, tmp_sum ) );
693 : }
694 :
695 0 : return suma;
696 : }
697 :
698 :
699 : /*---------------------------------------------------------------------*
700 : * v_mult_mat_fx()
701 : *
702 : * Multiplication of row vector x by matrix A, where x has size Nr and
703 : * A has size Nr x Nc ans it is stored column-wise in memory.
704 : * The resulting row vector y has size Nc
705 : *---------------------------------------------------------------------*/
706 :
707 0 : void v_mult_mat_fx(
708 : Word32 *y_fx, /* o : the product x*A y_q_fx*/
709 : Word16 *y_q_fx,
710 : const Word32 *x_fx, /* i : vector x x_q_fx*/
711 : Word16 *x_q_fx,
712 : const Word32 *A_fx, /* i : matrix A A_q_fx*/
713 : Word16 *A_q_fx,
714 : const Word16 Nr, /* i : number of rows Q0*/
715 : const Word16 Nc /* i : number of columns Q0*/
716 : )
717 : {
718 : Word16 i, j;
719 : const Word32 *pt_x_fx, *pt_A_fx;
720 : Word32 *pt_y_fx;
721 : Word32 tmp_y_fx[MAX_V_MULT_MAT];
722 : Word32 temp;
723 : Word16 temp_q;
724 :
725 0 : pt_y_fx = tmp_y_fx;
726 0 : pt_A_fx = A_fx; /*A_q_fx*/
727 0 : pt_x_fx = x_fx; /*x_q_fx*/
728 :
729 0 : FOR( i = 0; i < Nc; i++ )
730 : {
731 0 : pt_x_fx = x_fx; /*x_q_fx*/
732 0 : *pt_y_fx = 0;
733 0 : move32();
734 0 : y_q_fx[i] = 0;
735 0 : move32();
736 0 : FOR( j = 0; j < Nr; j++ )
737 : {
738 0 : temp = Mpy_32_32( *pt_x_fx++, *pt_A_fx++ ); /*x_q_fx + A_q_fx - 31*/
739 0 : temp_q = sub( add( x_q_fx[j], A_q_fx[Nr * i + j] ), 31 );
740 0 : IF( j == 0 )
741 : {
742 0 : *pt_y_fx = temp;
743 0 : move32();
744 0 : y_q_fx[i] = temp_q;
745 0 : move16();
746 : }
747 : ELSE
748 : {
749 0 : IF( GT_16( y_q_fx[i], temp_q ) )
750 : {
751 0 : *pt_y_fx = L_add( L_shr( *pt_y_fx, sub( y_q_fx[i], temp_q ) ), temp );
752 0 : move32();
753 0 : y_q_fx[i] = temp_q;
754 0 : move16();
755 : }
756 : ELSE
757 : {
758 0 : *pt_y_fx = L_add( *pt_y_fx, L_shr( temp, sub( temp_q, y_q_fx[i] ) ) );
759 0 : move32();
760 : }
761 : }
762 : }
763 0 : pt_y_fx++;
764 : }
765 :
766 0 : MVR2R_WORD32( tmp_y_fx, y_fx, Nc ); /*y_q_fx*/
767 :
768 0 : return;
769 : }
770 :
771 : /*---------------------------------------------------------------------*
772 : * logsumexp()
773 : *
774 : * Compute logarithm of the sum of exponentials of input vector in a numerically stable way
775 : *---------------------------------------------------------------------*/
776 :
777 : /*! r: log(sum(exp(x)) of the input array x */
778 0 : Word32 logsumexp_fx(
779 : const Word32 x[], /* i : input array x Q31 - x_e*/
780 : const Word16 x_e,
781 : const Word16 N /* i : number of elements in array x Q0*/
782 : )
783 : {
784 : Word32 max_exp, temp32_sub;
785 : Word32 sum, temp32, pow_temp;
786 0 : Word32 log2_e_fx = 1549082005; // Q30 of log2(e);
787 0 : Word16 log2_e_fx_e = 1;
788 0 : move16();
789 0 : move16();
790 : Word16 i;
791 0 : Word16 pow_e, sum_e = 0;
792 0 : move16();
793 0 : max_exp = x[0]; /*Q31 - x_e*/
794 0 : move32();
795 0 : sum = 0;
796 0 : move32();
797 0 : FOR( i = 1; i < N; i++ )
798 : {
799 0 : IF( GT_32( x[i], max_exp ) )
800 : {
801 0 : max_exp = x[i]; /*Q31 - x_e*/
802 0 : move32();
803 : }
804 : }
805 :
806 0 : FOR( i = 0; i < N; i++ )
807 : {
808 0 : temp32_sub = L_sub( x[i], max_exp ); /*Q31 - x_e*/
809 0 : pow_e = 0;
810 0 : move16();
811 0 : temp32 = Mpy_32_32( log2_e_fx, temp32_sub ); /*Q30 - x_e*/
812 0 : pow_temp = BASOP_util_Pow2( temp32, add( x_e, log2_e_fx_e ), &pow_e ); /*Q31 - pow_e*/
813 0 : sum = BASOP_Util_Add_Mant32Exp( sum, sum_e, pow_temp, pow_e, &sum_e ); /*Q31 - sum_e*/
814 : }
815 0 : temp32 = L_add( BASOP_Util_Log2( sum ), L_shl( sum_e, Q25 ) ); /*Q25*/
816 0 : temp32 = Mpy_32_32( temp32, 1488522239 ); /*logf(x) = log2(x)*logf(2) Q25*/
817 0 : temp32 = L_add( L_shr( temp32, sub( x_e, 6 ) ), max_exp ); // q = 31-x_e
818 0 : return temp32; /*31-x_e*/
819 : }
820 :
821 : /*---------------------------------------------------------------------*
822 : * lin_interp()
823 : *
824 : * Linearly maps x from source range <x1, x2> to the target range <y1, y2>
825 : *---------------------------------------------------------------------*/
826 : /*! r: mapped output value */
827 0 : Word32 lin_interp32_fx(
828 : const Word32 x, /* i : the value to be mapped Qx */
829 : const Word32 x1, /* i : source range interval: low end Qx */
830 : const Word32 y1, /* i : source range interval: high end Q31 */
831 : const Word32 x2, /* i : target range interval: low Qx */
832 : const Word32 y2, /* i : target range interval: high Q31 */
833 : const Word16 flag_sat /* i : flag to indicate whether to apply saturation */
834 : )
835 : {
836 : Word32 temp32;
837 : Word32 temp_div;
838 : Word16 exp_out;
839 :
840 0 : IF( L_sub( x2, x1 ) == 0 )
841 : {
842 0 : return y1;
843 : }
844 0 : ELSE IF( flag_sat )
845 : {
846 0 : IF( GE_32( x, L_max( x1, x2 ) ) )
847 : {
848 0 : return GT_32( x1, x2 ) ? y1 : y2;
849 : }
850 0 : ELSE IF( LE_32( x, L_min( x1, x2 ) ) )
851 : {
852 0 : return LT_32( x1, x2 ) ? y1 : y2;
853 : }
854 : }
855 :
856 0 : temp32 = Mpy_32_32( L_sub( x, x1 ), L_sub( y2, y1 ) ); /* Qx */
857 0 : temp_div = L_deposit_h( BASOP_Util_Divide3232_Scale( temp32, L_sub( x2, x1 ), &exp_out ) );
858 0 : temp32 = BASOP_Util_Add_Mant32Exp( y1, 0, temp_div, exp_out, &exp_out );
859 0 : temp32 = L_shl_sat( temp32, exp_out ); /* Q31 */
860 :
861 0 : return temp32;
862 : }
863 :
864 : /*-------------------------------------------------------------------*
865 : * check_bounds_s_fx()
866 : *
867 : * Ensure the input value is within the given limits
868 : *-------------------------------------------------------------------*/
869 :
870 : /*! r: Adjusted value */
871 839434 : Word16 check_bounds_s_fx(
872 : const Word16 value, /* i : Input value Q0*/
873 : const Word16 low, /* i : Low limit Q0*/
874 : const Word16 high /* i : High limit Q0*/
875 : )
876 : {
877 : Word16 value_adj;
878 :
879 839434 : value_adj = s_min( s_max( value, low ), high ); /*Q0*/
880 :
881 839434 : return value_adj; /*Q0*/
882 : }
883 :
884 : /*-------------------------------------------------------------------*
885 : * check_bounds_l()
886 : *
887 : * Ensure the input value is within the given limits
888 : *-------------------------------------------------------------------*/
889 :
890 : /*! r: Adjusted value */
891 521900 : Word32 check_bounds_l(
892 : const Word32 value, /* i : Input value Q0*/
893 : const Word32 low, /* i : Low limit Q0*/
894 : const Word32 high /* i : High limit Q0*/
895 : )
896 : {
897 : Word32 value_adj;
898 :
899 521900 : value_adj = L_min( L_max( value, low ), high ); /*Q0*/
900 :
901 521900 : return value_adj; /*Q0*/
902 : }
903 :
904 : /****************************************************************************/
905 : /* matrix functions */
906 : /* matrices are ordered column-wise in memory */
907 : /****************************************************************************/
908 :
909 : /*---------------------------------------------------------------------*
910 : * matrix product
911 : *
912 : * comput the matrix product of two matrices (Z=X*Y)
913 : *---------------------------------------------------------------------*/
914 :
915 2008120 : Word16 matrix_product_mant_exp_fx(
916 : const Word32 *X_fx, /* i : left hand matrix Q31 - X_fx_e*/
917 : const Word16 X_fx_e, /* i : left hand matrix */
918 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
919 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
920 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
921 : const Word32 *Y_fx, /* i : right hand matrix Q31 - Y_fx_e*/
922 : const Word16 Y_fx_e, /* i : right hand matrix */
923 : const Word16 rowsY, /* i : number of rows of the right hand matrix Q0*/
924 : const Word16 colsY, /* i : number of columns of the right hand matrix Q0*/
925 : const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/
926 : Word32 *Z_fx, /* o : resulting matrix after the matrix multiplication Q31 - Z_fx_e*/
927 : Word16 *Z_fx_e /* o : resulting matrix after the matrix multiplication */
928 : )
929 : {
930 : Word16 i, j, k;
931 2008120 : Word32 *Zp_fx = Z_fx;
932 : Word16 out_e[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
933 2008120 : Word16 *Zp_fx_e = out_e;
934 : Word16 row, col;
935 : Word64 temp;
936 : Word16 temp_e;
937 2008120 : Word16 prod_e = add( X_fx_e, Y_fx_e );
938 :
939 2008120 : Word16 max_exp = -31;
940 2008120 : move16();
941 :
942 : /* Processing */
943 2008120 : test();
944 2008120 : test();
945 2008120 : test();
946 2008120 : IF( EQ_16( transpX, 1 ) && transpY == 0 ) /* We use X transpose */
947 : {
948 0 : IF( NE_16( rowsX, rowsY ) )
949 : {
950 0 : return EXIT_FAILURE;
951 : }
952 0 : FOR( j = 0; j < colsY; ++j )
953 : {
954 0 : FOR( i = 0; i < colsX; ++i )
955 : {
956 0 : temp = 0;
957 0 : move64();
958 :
959 0 : FOR( k = 0; k < rowsX; ++k )
960 : {
961 0 : temp = W_mac_32_32( temp, X_fx[k + i * rowsX], Y_fx[k + j * rowsY] ); // X_fx_e + Y_fx_e
962 : }
963 : /* Maximize accumulated value to 32-bit */
964 0 : temp_e = W_norm( temp );
965 0 : temp = W_shl( temp, temp_e );
966 0 : if ( 0 == temp )
967 : {
968 0 : temp_e = prod_e;
969 0 : move16();
970 : }
971 0 : *Zp_fx_e = sub( prod_e, temp_e );
972 0 : move16();
973 0 : ( *Zp_fx ) = W_extract_h( temp );
974 0 : move32();
975 0 : max_exp = s_max( max_exp, *Zp_fx_e ); // Find the max exp
976 0 : Zp_fx++;
977 0 : Zp_fx_e++;
978 : }
979 : }
980 0 : row = colsY; /*Q0*/
981 0 : move16();
982 0 : col = colsX; /*Q0*/
983 0 : move16();
984 : }
985 2008120 : ELSE IF( transpX == 0 && EQ_16( transpY, 1 ) ) /* We use Y transpose */
986 : {
987 834380 : IF( NE_16( colsX, colsY ) )
988 : {
989 0 : return EXIT_FAILURE;
990 : }
991 5032904 : FOR( j = 0; j < rowsY; ++j )
992 : {
993 37245276 : FOR( i = 0; i < rowsX; ++i )
994 : {
995 33046752 : temp = 0;
996 33046752 : move64();
997 106886472 : FOR( k = 0; k < colsX; ++k )
998 : {
999 73839720 : temp = W_mac_32_32( temp, X_fx[i + k * rowsX], Y_fx[j + k * rowsY] ); // X_fx_e + Y_fx_e
1000 : }
1001 : /* Maximize accumulated value to 32-bit */
1002 33046752 : temp_e = W_norm( temp );
1003 33046752 : temp = W_shl( temp, temp_e );
1004 33046752 : if ( 0 == temp )
1005 : {
1006 15085835 : temp_e = prod_e;
1007 15085835 : move16();
1008 : }
1009 33046752 : *Zp_fx_e = sub( prod_e, temp_e );
1010 33046752 : move16();
1011 33046752 : ( *Zp_fx ) = W_extract_h( temp );
1012 33046752 : move32();
1013 33046752 : max_exp = s_max( max_exp, *Zp_fx_e ); // Find the max exp
1014 33046752 : Zp_fx++;
1015 33046752 : Zp_fx_e++;
1016 : }
1017 : }
1018 834380 : row = rowsY; /*Q0*/
1019 834380 : move16();
1020 834380 : col = rowsX; /*Q0*/
1021 834380 : move16();
1022 : }
1023 1173740 : ELSE IF( EQ_16( transpX, 1 ) && EQ_16( transpY, 1 ) ) /* We use both transpose */
1024 : {
1025 113120 : IF( NE_16( rowsX, colsY ) )
1026 : {
1027 0 : return EXIT_FAILURE;
1028 : }
1029 688444 : FOR( j = 0; j < rowsY; ++j )
1030 : {
1031 1732172 : FOR( i = 0; i < colsX; ++i )
1032 : {
1033 1156848 : temp = 0;
1034 1156848 : move64();
1035 3489144 : FOR( k = 0; k < colsX; ++k )
1036 : {
1037 2332296 : temp = W_mac_32_32( temp, X_fx[k + i * rowsX], Y_fx[j + k * rowsY] ); // X_fx_e + Y_fx_e
1038 : }
1039 : /* Maximize accumulated value to 32-bit */
1040 1156848 : temp_e = W_norm( temp );
1041 1156848 : temp = W_shl( temp, temp_e );
1042 1156848 : if ( 0 == temp )
1043 : {
1044 400 : temp_e = prod_e;
1045 400 : move16();
1046 : }
1047 1156848 : *Zp_fx_e = sub( prod_e, temp_e );
1048 1156848 : move16();
1049 1156848 : ( *Zp_fx ) = W_extract_h( temp );
1050 1156848 : move32();
1051 1156848 : max_exp = s_max( max_exp, *Zp_fx_e ); // Find the max exp
1052 1156848 : Zp_fx++;
1053 1156848 : Zp_fx_e++;
1054 : }
1055 : }
1056 113120 : row = rowsY; /*Q0*/
1057 113120 : move16();
1058 113120 : col = colsX; /*Q0*/
1059 113120 : move16();
1060 : }
1061 : ELSE /* Regular case */
1062 : {
1063 1060620 : IF( NE_16( colsX, rowsY ) )
1064 : {
1065 0 : return EXIT_FAILURE;
1066 : }
1067 :
1068 3819908 : FOR( j = 0; j < colsY; ++j )
1069 : {
1070 15641696 : FOR( i = 0; i < rowsX; ++i )
1071 : {
1072 12882408 : temp = 0;
1073 12882408 : move64();
1074 62919424 : FOR( k = 0; k < colsX; ++k )
1075 : {
1076 50037016 : temp = W_mac_32_32( temp, X_fx[i + k * rowsX], Y_fx[k + j * rowsY] ); // X_fx_e + Y_fx_e
1077 : }
1078 : /* Maximize accumulated value to 32-bit */
1079 12882408 : temp_e = W_norm( temp );
1080 12882408 : temp = W_shl( temp, temp_e );
1081 12882408 : if ( 0 == temp )
1082 : {
1083 2422111 : temp_e = prod_e;
1084 : }
1085 12882408 : *Zp_fx_e = sub( prod_e, temp_e );
1086 12882408 : move16();
1087 12882408 : ( *Zp_fx ) = W_extract_h( temp );
1088 12882408 : move32();
1089 12882408 : max_exp = s_max( max_exp, *Zp_fx_e ); // Find the max exp
1090 12882408 : Zp_fx++;
1091 12882408 : Zp_fx_e++;
1092 : }
1093 : }
1094 1060620 : row = colsY; /*Q0*/
1095 1060620 : move16();
1096 1060620 : col = rowsX; /*Q0*/
1097 1060620 : move16();
1098 : }
1099 2008120 : Zp_fx = Z_fx; /*Q31 - Zp_fx_e*/
1100 :
1101 2008120 : Zp_fx_e = out_e;
1102 2008120 : move16();
1103 :
1104 :
1105 2008120 : *Z_fx_e = max_exp;
1106 2008120 : move16();
1107 9541256 : FOR( j = 0; j < row; ++j )
1108 : {
1109 54619144 : FOR( i = 0; i < col; ++i )
1110 : {
1111 47086008 : *Zp_fx = L_shr_r( *Zp_fx, sub( *Z_fx_e, *Zp_fx_e ) ); /*Q31 - Zp_fx_e*/
1112 47086008 : move32();
1113 47086008 : Zp_fx++;
1114 47086008 : Zp_fx_e++;
1115 : }
1116 : }
1117 :
1118 2008120 : return EXIT_SUCCESS;
1119 : }
1120 :
1121 340403 : Word16 matrix_product_fx(
1122 : const Word32 *X_fx, /* i : left hand matrix Qx*/
1123 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
1124 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
1125 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
1126 : const Word32 *Y_fx, /* i : right hand matrix Qy*/
1127 : const Word16 rowsY, /* i : number of rows of the right hand matrix Q0*/
1128 : const Word16 colsY, /* i : number of columns of the right hand matrix Q0*/
1129 : const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/
1130 : Word32 *Z_fx /* o : resulting matrix after the matrix multiplication Qx + Qy - 31*/
1131 : )
1132 : {
1133 : Word16 i, j, k;
1134 340403 : Word32 *Zp_fx = Z_fx;
1135 :
1136 : /* Processing */
1137 340403 : test();
1138 340403 : test();
1139 340403 : test();
1140 340403 : IF( EQ_16( transpX, 1 ) && transpY == 0 ) /* We use X transpose */
1141 : {
1142 1040 : IF( NE_16( rowsX, rowsY ) )
1143 : {
1144 0 : return EXIT_FAILURE;
1145 : }
1146 5200 : FOR( j = 0; j < colsY; ++j )
1147 : {
1148 24960 : FOR( i = 0; i < colsX; ++i )
1149 : {
1150 20800 : ( *Zp_fx ) = 0;
1151 20800 : move32();
1152 124800 : FOR( k = 0; k < rowsX; ++k )
1153 : {
1154 104000 : ( *Zp_fx ) = Madd_32_32( *Zp_fx, X_fx[k + i * rowsX], Y_fx[k + j * rowsY] ); /*Qx + Qy - 31*/
1155 104000 : move32();
1156 : }
1157 20800 : Zp_fx++;
1158 : }
1159 : }
1160 : }
1161 339363 : ELSE IF( transpX == 0 && EQ_16( transpY, 1 ) ) /* We use Y transpose */
1162 : {
1163 113120 : IF( NE_16( colsX, colsY ) )
1164 : {
1165 0 : return EXIT_FAILURE;
1166 : }
1167 804960 : FOR( j = 0; j < rowsY; ++j )
1168 : {
1169 4961280 : FOR( i = 0; i < rowsX; ++i )
1170 : {
1171 4269440 : ( *Zp_fx ) = 0;
1172 4269440 : move32();
1173 12888960 : FOR( k = 0; k < colsX; ++k )
1174 : {
1175 8619520 : ( *Zp_fx ) = Madd_32_32( *Zp_fx, X_fx[i + k * rowsX], Y_fx[j + k * rowsY] ); /*Qx + Qy - 31*/
1176 8619520 : move32();
1177 : }
1178 4269440 : Zp_fx++;
1179 : }
1180 : }
1181 : }
1182 226243 : ELSE IF( EQ_16( transpX, 1 ) && EQ_16( transpY, 1 ) ) /* We use both transpose */
1183 : {
1184 0 : IF( NE_16( rowsX, colsY ) )
1185 : {
1186 0 : return EXIT_FAILURE;
1187 : }
1188 0 : FOR( j = 0; j < rowsY; ++j )
1189 : {
1190 0 : FOR( i = 0; i < colsX; ++i )
1191 : {
1192 0 : ( *Zp_fx ) = 0;
1193 0 : move32();
1194 0 : FOR( k = 0; k < colsX; ++k )
1195 : {
1196 0 : ( *Zp_fx ) = Madd_32_32( *Zp_fx, X_fx[k + i * rowsX], Y_fx[j + k * rowsY] ); /*Qx + Qy - 31*/
1197 0 : move32();
1198 : }
1199 :
1200 0 : Zp_fx++;
1201 : }
1202 : }
1203 : }
1204 : ELSE /* Regular case */
1205 : {
1206 226243 : IF( NE_16( colsX, rowsY ) )
1207 : {
1208 0 : return EXIT_FAILURE;
1209 : }
1210 :
1211 679851 : FOR( j = 0; j < colsY; ++j )
1212 : {
1213 3000880 : FOR( i = 0; i < rowsX; ++i )
1214 : {
1215 2547272 : ( *Zp_fx ) = 0;
1216 2547272 : move32();
1217 7680768 : FOR( k = 0; k < colsX; ++k )
1218 : {
1219 5133496 : ( *Zp_fx ) = L_add_sat( *Zp_fx, Mpy_32_32( X_fx[i + k * rowsX], Y_fx[k + j * rowsY] ) ); /*Qx + Qy - 31*/
1220 : // TODO: overflow of Z_fx to be checked
1221 5133496 : move32();
1222 : }
1223 2547272 : Zp_fx++;
1224 : }
1225 : }
1226 : }
1227 :
1228 340403 : return EXIT_SUCCESS;
1229 : }
1230 :
1231 1597 : Word16 matrix_product_q30_fx(
1232 : const Word32 *X_fx, /* i : left hand matrix Q31*/
1233 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
1234 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
1235 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
1236 : const Word32 *Y_fx, /* i : right hand matrix Q25*/
1237 : const Word16 rowsY, /* i : number of rows of the right hand matrix Q0*/
1238 : const Word16 colsY, /* i : number of columns of the right hand matrix Q0*/
1239 : const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/
1240 : Word32 *Z_fx /* o : resulting matrix after the matrix multiplication Q30*/
1241 : )
1242 : {
1243 : Word16 i, j, k;
1244 1597 : Word32 *Zp_fx = Z_fx;
1245 : Word64 W_tmp;
1246 :
1247 : /* Processing */
1248 1597 : test();
1249 1597 : test();
1250 1597 : test();
1251 1597 : IF( EQ_16( transpX, 1 ) && transpY == 0 ) /* We use X transpose */
1252 : {
1253 557 : IF( NE_16( rowsX, rowsY ) )
1254 : {
1255 0 : return EXIT_FAILURE;
1256 : }
1257 1114 : FOR( j = 0; j < colsY; ++j )
1258 : {
1259 5863 : FOR( i = 0; i < colsX; ++i )
1260 : {
1261 : //( *Zp_fx ) = 0;
1262 5306 : W_tmp = 0;
1263 5306 : move64();
1264 62248 : FOR( k = 0; k < rowsX; ++k )
1265 : {
1266 56942 : W_tmp = W_add( W_tmp, W_mult0_32_32( X_fx[k + i * rowsX], Y_fx[k + j * rowsY] ) ); // Q56
1267 : }
1268 5306 : W_tmp = W_shl( W_tmp, 6 ); /*Q62*/
1269 5306 : ( *Zp_fx ) = W_round64_L( W_tmp ); /*Q30*/
1270 5306 : move32();
1271 5306 : Zp_fx++;
1272 : }
1273 : }
1274 : }
1275 1040 : ELSE IF( transpX == 0 && EQ_16( transpY, 1 ) ) /* We use Y transpose */
1276 : {
1277 0 : IF( NE_16( colsX, colsY ) )
1278 : {
1279 0 : return EXIT_FAILURE;
1280 : }
1281 0 : FOR( j = 0; j < rowsY; ++j )
1282 : {
1283 0 : FOR( i = 0; i < rowsX; ++i )
1284 : {
1285 : //( *Zp_fx ) = 0;
1286 0 : W_tmp = 0;
1287 0 : move64();
1288 0 : FOR( k = 0; k < colsX; ++k )
1289 : {
1290 0 : W_tmp = W_add( W_tmp, W_mult0_32_32( X_fx[i + k * rowsX], Y_fx[j + k * rowsY] ) ); // Q56
1291 : }
1292 0 : W_tmp = W_shl( W_tmp, 6 ); /*Q62*/
1293 0 : ( *Zp_fx ) = W_round64_L( W_tmp ); /*Q30*/
1294 0 : move32();
1295 0 : Zp_fx++;
1296 : }
1297 : }
1298 : }
1299 1040 : ELSE IF( EQ_16( transpX, 1 ) && EQ_16( transpY, 1 ) ) /* We use both transpose */
1300 : {
1301 0 : IF( NE_16( rowsX, colsY ) )
1302 : {
1303 0 : return EXIT_FAILURE;
1304 : }
1305 0 : FOR( j = 0; j < rowsY; ++j )
1306 : {
1307 0 : FOR( i = 0; i < colsX; ++i )
1308 : {
1309 : //( *Zp_fx ) = 0;
1310 0 : W_tmp = 0;
1311 0 : move64();
1312 0 : FOR( k = 0; k < colsX; ++k )
1313 : {
1314 0 : W_tmp = W_add( W_tmp, W_mult0_32_32( X_fx[k + i * rowsX], Y_fx[j + k * rowsY] ) ); // Q56
1315 : }
1316 :
1317 0 : W_tmp = W_shl( W_tmp, 6 ); /*Q62*/
1318 0 : ( *Zp_fx ) = W_round64_L( W_tmp ); /*Q30*/
1319 0 : move32();
1320 0 : Zp_fx++;
1321 : }
1322 : }
1323 : }
1324 : ELSE /* Regular case */
1325 : {
1326 1040 : IF( NE_16( colsX, rowsY ) )
1327 : {
1328 0 : return EXIT_FAILURE;
1329 : }
1330 :
1331 5200 : FOR( j = 0; j < colsY; ++j )
1332 : {
1333 24960 : FOR( i = 0; i < rowsX; ++i )
1334 : {
1335 : //( *Zp_fx ) = 0;
1336 20800 : W_tmp = 0;
1337 20800 : move64();
1338 104000 : FOR( k = 0; k < colsX; ++k )
1339 : {
1340 83200 : W_tmp = W_add( W_tmp, W_mult0_32_32( X_fx[i + k * rowsX], Y_fx[k + j * rowsY] ) ); // Q56
1341 : }
1342 20800 : W_tmp = W_shl( W_tmp, 6 ); /*Q62*/
1343 20800 : ( *Zp_fx ) = W_round64_L( W_tmp ); /*Q30*/
1344 20800 : move32();
1345 20800 : Zp_fx++;
1346 : }
1347 : }
1348 : }
1349 :
1350 1597 : return EXIT_SUCCESS;
1351 : }
1352 : /*takes input matrices in mantissa and exponent forms*/
1353 343560 : Word16 matrix_product_mant_exp(
1354 : const Word32 *X_fx, /* i : left hand matrix Q31 - X_e*/
1355 : const Word16 *X_e, /* i : left hand matrix */
1356 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
1357 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
1358 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
1359 : const Word32 *Y_fx, /* i : right hand matrix Q31 - Y_e*/
1360 : const Word16 *Y_e, /* i : right hand matrix */
1361 : const Word16 rowsY, /* i : number of rows of the right hand matrix Q0*/
1362 : const Word16 colsY, /* i : number of columns of the right hand matrix Q0*/
1363 : const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/
1364 : Word32 *Z_fx, /* o : resulting matrix after the matrix multiplication Q31 - Z_e*/
1365 : Word16 *Z_e /* o : resulting matrix after the matrix multiplication */
1366 : )
1367 : {
1368 : Word16 i, j, k;
1369 343560 : Word32 *Zp = Z_fx;
1370 343560 : Word16 *Zp_e = Z_e;
1371 : Word32 L_tmp;
1372 : Word16 tmp_e;
1373 :
1374 : /* Processing */
1375 343560 : test();
1376 343560 : test();
1377 343560 : test();
1378 343560 : IF( EQ_16( transpX, 1 ) && transpY == 0 ) /* We use X transpose */
1379 : {
1380 0 : IF( NE_16( rowsX, rowsY ) )
1381 : {
1382 0 : return EXIT_FAILURE;
1383 : }
1384 0 : FOR( j = 0; j < colsY; ++j )
1385 : {
1386 0 : FOR( i = 0; i < colsX; ++i )
1387 : {
1388 0 : ( *Zp ) = 0;
1389 0 : move32();
1390 0 : ( *Zp_e ) = 0;
1391 0 : move16();
1392 0 : FOR( k = 0; k < rowsX; ++k )
1393 : {
1394 0 : L_tmp = Mpy_32_32( X_fx[k + i * rowsX], Y_fx[k + j * rowsY] ); /*Q31 - (X_e + Y_e)*/
1395 0 : tmp_e = add( X_e[k + i * rowsX], Y_e[k + j * rowsY] );
1396 :
1397 0 : ( *Zp ) = BASOP_Util_Add_Mant32Exp( *Zp, *Zp_e, L_tmp, tmp_e, &tmp_e );
1398 0 : move32();
1399 0 : ( *Zp_e ) = tmp_e;
1400 0 : move16();
1401 : }
1402 0 : Zp++;
1403 0 : Zp_e++;
1404 : }
1405 : }
1406 : }
1407 343560 : ELSE IF( transpX == 0 && EQ_16( transpY, 1 ) ) /* We use Y transpose */
1408 : {
1409 115220 : IF( NE_16( colsX, colsY ) )
1410 : {
1411 0 : return EXIT_FAILURE;
1412 : }
1413 703144 : FOR( j = 0; j < rowsY; ++j )
1414 : {
1415 3622168 : FOR( i = 0; i < rowsX; ++i )
1416 : {
1417 3034244 : ( *Zp ) = 0;
1418 3034244 : move32();
1419 3034244 : ( *Zp_e ) = 0;
1420 3034244 : move16();
1421 9625012 : FOR( k = 0; k < colsX; ++k )
1422 : {
1423 6590768 : L_tmp = Mpy_32_32( X_fx[i + k * rowsX], Y_fx[j + k * rowsY] ); /*Q31 - (X_e + Y_e)*/
1424 6590768 : tmp_e = add( X_e[i + k * rowsX], Y_e[j + k * rowsY] );
1425 :
1426 6590768 : ( *Zp ) = BASOP_Util_Add_Mant32Exp( *Zp, *Zp_e, L_tmp, tmp_e, &tmp_e );
1427 6590768 : ( *Zp_e ) = tmp_e;
1428 6590768 : move16();
1429 : }
1430 3034244 : Zp++;
1431 3034244 : Zp_e++;
1432 : }
1433 : }
1434 : }
1435 228340 : ELSE IF( EQ_16( transpX, 1 ) && EQ_16( transpY, 1 ) ) /* We use both transpose */
1436 : {
1437 0 : IF( NE_16( rowsX, colsY ) )
1438 : {
1439 0 : return EXIT_FAILURE;
1440 : }
1441 0 : FOR( j = 0; j < rowsY; ++j )
1442 : {
1443 0 : FOR( i = 0; i < colsX; ++i )
1444 : {
1445 0 : ( *Zp ) = 0;
1446 0 : move32();
1447 0 : ( *Zp_e ) = 0;
1448 0 : move16();
1449 0 : FOR( k = 0; k < colsX; ++k )
1450 : {
1451 0 : L_tmp = Mpy_32_32( X_fx[k + i * rowsX], Y_fx[j + k * rowsY] ); /*Q31 - (X_e + Y_e)*/
1452 0 : tmp_e = add( X_e[k + i * rowsX], Y_e[j + k * rowsY] );
1453 :
1454 0 : ( *Zp ) = BASOP_Util_Add_Mant32Exp( *Zp, *Zp_e, L_tmp, tmp_e, &tmp_e );
1455 0 : move32();
1456 0 : ( *Zp_e ) = tmp_e;
1457 0 : move16();
1458 : }
1459 :
1460 0 : Zp++;
1461 0 : Zp_e++;
1462 : }
1463 : }
1464 : }
1465 : ELSE /* Regular case */
1466 : {
1467 228340 : IF( NE_16( colsX, rowsY ) )
1468 : {
1469 0 : return EXIT_FAILURE;
1470 : }
1471 :
1472 698740 : FOR( j = 0; j < colsY; ++j )
1473 : {
1474 2884896 : FOR( i = 0; i < rowsX; ++i )
1475 : {
1476 2414496 : ( *Zp ) = 0;
1477 2414496 : move32();
1478 2414496 : ( *Zp_e ) = 0;
1479 2414496 : move16();
1480 7885488 : FOR( k = 0; k < colsX; ++k )
1481 : {
1482 5470992 : L_tmp = Mpy_32_32( X_fx[i + k * rowsX], Y_fx[k + j * rowsY] ); /*Q31 - (X_e + Y_e)*/
1483 5470992 : tmp_e = add( X_e[i + k * rowsX], Y_e[k + j * rowsY] );
1484 :
1485 5470992 : ( *Zp ) = BASOP_Util_Add_Mant32Exp( *Zp, *Zp_e, L_tmp, tmp_e, &tmp_e );
1486 5470992 : move32();
1487 5470992 : ( *Zp_e ) = tmp_e;
1488 5470992 : move16();
1489 : }
1490 2414496 : Zp++;
1491 2414496 : Zp_e++;
1492 : }
1493 : }
1494 : }
1495 :
1496 343560 : return EXIT_SUCCESS;
1497 : }
1498 :
1499 :
1500 1575900 : Word16 matrix_diag_product_fx(
1501 : const Word32 *X, /* i : left hand matrix Q31 - X_e*/
1502 : Word16 X_e,
1503 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
1504 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
1505 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
1506 : const Word32 *Y, /* i : right hand diagonal matrix as vector containing the diagonal elements Q31 - Y_e*/
1507 : Word16 Y_e,
1508 : const Word16 entriesY, /* i : number of entries in the diagonal Q0*/
1509 : Word32 *Z, /* o : resulting matrix after the matrix multiplication Q31 - Z_e*/
1510 : Word16 *Z_e )
1511 : {
1512 : Word16 i, j;
1513 1575900 : Word32 *Zp = Z;
1514 :
1515 : /* Processing */
1516 1575900 : IF( EQ_16( transpX, 1 ) ) /* We use X transpose */
1517 : {
1518 0 : IF( NE_16( rowsX, entriesY ) )
1519 : {
1520 0 : return EXIT_FAILURE;
1521 : }
1522 0 : FOR( j = 0; j < entriesY; ++j )
1523 : {
1524 0 : FOR( i = 0; i < colsX; ++i )
1525 : {
1526 0 : *( Zp ) = Mpy_32_32( X[j + i * rowsX], Y[j] ); /*Q31 - (X_e + Y_e)*/
1527 0 : move32();
1528 0 : Zp++;
1529 : }
1530 : }
1531 : }
1532 : ELSE /* Regular case */
1533 : {
1534 1575900 : IF( NE_16( colsX, entriesY ) )
1535 : {
1536 0 : return EXIT_FAILURE;
1537 : }
1538 :
1539 6983460 : FOR( j = 0; j < entriesY; ++j )
1540 : {
1541 34250760 : FOR( i = 0; i < rowsX; ++i )
1542 : {
1543 28843200 : *( Zp ) = Mpy_32_32( *( X ), Y[j] ); /*Q31 - (X_e + Y_e)*/
1544 28843200 : move32();
1545 28843200 : Zp++;
1546 28843200 : X++;
1547 : }
1548 : }
1549 : }
1550 :
1551 1575900 : *Z_e = add( X_e, Y_e );
1552 1575900 : move16();
1553 :
1554 1575900 : return EXIT_SUCCESS;
1555 : }
1556 :
1557 113120 : Word16 matrix_diag_product_fx_2(
1558 : const Word32 *X, /* i : left hand matrix Q31 - X_e*/
1559 : const Word16 X_e,
1560 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
1561 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
1562 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
1563 : const Word32 *Y, /* i : right hand diagonal matrix as vector containing the diagonal elements Q31 - Y_e*/
1564 : const Word16 *Y_e,
1565 : const Word16 entriesY, /* i : number of entries in the diagonal Q0*/
1566 : Word32 *Z, /* o : resulting matrix after the matrix multiplication Q31 - Z_e*/
1567 : Word16 *Z_e )
1568 : {
1569 : Word16 i, j;
1570 113120 : Word32 *Zp = Z;
1571 113120 : Word16 *Z_ep = Z_e;
1572 : Word16 tmp;
1573 113120 : Word16 max_exp = -31;
1574 113120 : move16();
1575 :
1576 : /* Processing */
1577 113120 : IF( EQ_16( transpX, 1 ) ) /* We use X transpose */
1578 : {
1579 0 : IF( NE_16( rowsX, entriesY ) )
1580 : {
1581 0 : return EXIT_FAILURE;
1582 : }
1583 0 : FOR( j = 0; j < entriesY; ++j )
1584 : {
1585 0 : FOR( i = 0; i < colsX; ++i )
1586 : {
1587 0 : tmp = j + i * rowsX; /*Q0*/
1588 0 : *( Zp ) = Mpy_32_32( X[tmp], Y[j] ); /*Q31 - (X_e + Y_e)*/
1589 0 : move32();
1590 0 : Zp++;
1591 0 : *( Z_ep ) = add( X_e, Y_e[j] );
1592 0 : move16();
1593 0 : max_exp = s_max( max_exp, *Z_ep ); // Find the max exp
1594 0 : Z_ep++;
1595 : }
1596 : }
1597 :
1598 0 : Zp = Z;
1599 0 : Z_ep = Z_e;
1600 0 : FOR( j = 0; j < entriesY; ++j )
1601 : {
1602 0 : FOR( i = 0; i < colsX; ++i )
1603 : {
1604 0 : *Zp = L_shr( *Zp, sub( max_exp, *Z_ep ) );
1605 0 : *Z_ep = max_exp;
1606 0 : Zp++;
1607 0 : Z_ep++;
1608 : }
1609 : }
1610 : }
1611 : ELSE /* Regular case */
1612 : {
1613 113120 : IF( NE_16( colsX, entriesY ) )
1614 : {
1615 0 : return EXIT_FAILURE;
1616 : }
1617 :
1618 688444 : FOR( j = 0; j < entriesY; ++j )
1619 : {
1620 1732172 : FOR( i = 0; i < rowsX; ++i )
1621 : {
1622 1156848 : *( Zp ) = Mpy_32_32( *( X ), Y[j] ); /*Q31 - (X_e + Y_e)*/
1623 1156848 : move32();
1624 1156848 : Zp++;
1625 1156848 : *( Z_ep ) = add( X_e, Y_e[j] );
1626 1156848 : move16();
1627 1156848 : max_exp = s_max( max_exp, *Z_ep ); // Find the max exp
1628 1156848 : Z_ep++;
1629 1156848 : X++;
1630 : }
1631 : }
1632 113120 : Zp = Z;
1633 113120 : Z_ep = Z_e;
1634 688444 : FOR( j = 0; j < entriesY; ++j )
1635 : {
1636 1732172 : FOR( i = 0; i < rowsX; ++i )
1637 : {
1638 1156848 : *Zp = L_shr( *Zp, sub( max_exp, *Z_ep ) );
1639 1156848 : *Z_ep = max_exp;
1640 1156848 : Zp++;
1641 1156848 : Z_ep++;
1642 : }
1643 : }
1644 : }
1645 :
1646 113120 : return EXIT_SUCCESS;
1647 : }
1648 :
1649 90900 : Word16 matrix_diag_product_fx_1(
1650 : const Word32 *X, /* i : left hand matrix Q31 - X_e*/
1651 : const Word16 *X_e,
1652 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
1653 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
1654 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
1655 : const Word32 *Y, /* i : right hand diagonal matrix as vector containing the diagonal elements Q31 - Y_e*/
1656 : const Word16 *Y_e,
1657 : const Word16 entriesY, /* i : number of entries in the diagonal Q0*/
1658 : Word32 *Z, /* o : resulting matrix after the matrix multiplication Q31 - Z_e*/
1659 : Word16 *Z_e )
1660 : {
1661 : Word16 i, j;
1662 90900 : Word32 *Zp = Z;
1663 90900 : Word16 *Z_ep = Z_e;
1664 :
1665 : /* Processing */
1666 90900 : IF( EQ_16( transpX, 1 ) ) /* We use X transpose */
1667 : {
1668 0 : IF( NE_16( rowsX, entriesY ) )
1669 : {
1670 0 : return EXIT_FAILURE;
1671 : }
1672 0 : FOR( j = 0; j < entriesY; ++j )
1673 : {
1674 0 : FOR( i = 0; i < colsX; ++i )
1675 : {
1676 0 : *( Zp ) = Mpy_32_32( X[j + i * rowsX], Y[j] ); /*Q31 - (X_e + Y_e)*/
1677 0 : move32();
1678 0 : Zp++;
1679 0 : *( Z_ep ) = add( X_e[j + i * rowsX], Y_e[j] );
1680 0 : move16();
1681 0 : Z_ep++;
1682 : }
1683 : }
1684 : }
1685 : ELSE /* Regular case */
1686 : {
1687 90900 : IF( NE_16( colsX, entriesY ) )
1688 : {
1689 0 : return EXIT_FAILURE;
1690 : }
1691 :
1692 553344 : FOR( j = 0; j < entriesY; ++j )
1693 : {
1694 2841348 : FOR( i = 0; i < rowsX; ++i )
1695 : {
1696 2378904 : *( Zp ) = Mpy_32_32( *( X ), Y[j] ); /*Q31 - (X_e + Y_e)*/
1697 2378904 : move32();
1698 2378904 : Zp++;
1699 2378904 : *( Z_ep ) = add( *( X_e ), Y_e[j] );
1700 2378904 : move16();
1701 2378904 : Z_ep++;
1702 2378904 : X++;
1703 2378904 : X_e++;
1704 : }
1705 : }
1706 : }
1707 :
1708 90900 : return EXIT_SUCCESS;
1709 : }
1710 :
1711 743480 : Word16 diag_matrix_product_fx(
1712 : const Word32 *Y, /* i : left hand diagonal matrix as vector containing the diagonal elements Q31 - Y_e*/
1713 : Word16 Y_e,
1714 : const Word16 entriesY, /* i : length of the diagonal of the left hand matrix Q0*/
1715 : const Word32 *X, /* i : right hand matrix Q31 - X_e*/
1716 : Word16 X_e,
1717 : const Word16 rowsX, /* i : number of rows of the right hand matrix Q0*/
1718 : const Word16 colsX, /* i : number of columns of the right hand matrix Q0*/
1719 : const Word16 transpX, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/
1720 : Word32 *Z, /* o : resulting matrix after the matrix multiplication Q31 - Z_e*/
1721 : Word16 *Z_e )
1722 : {
1723 : Word16 i, j;
1724 743480 : Word32 *Zp = Z;
1725 :
1726 : /* Processing */
1727 743480 : IF( EQ_16( transpX, 1 ) ) /* We use X transpose */
1728 : {
1729 315180 : IF( NE_16( colsX, entriesY ) )
1730 : {
1731 0 : return EXIT_FAILURE;
1732 : }
1733 3194100 : FOR( i = 0; i < rowsX; ++i )
1734 : {
1735 8636760 : FOR( j = 0; j < entriesY; ++j )
1736 : {
1737 5757840 : *( Zp ) = Mpy_32_32( X[i + j * rowsX], Y[j] ); /*Q31 - (X_e + Y_e)*/
1738 5757840 : move32();
1739 5757840 : Zp++;
1740 : }
1741 : }
1742 : }
1743 : ELSE /* Regular case */
1744 : {
1745 428300 : IF( NE_16( rowsX, entriesY ) )
1746 : {
1747 0 : return EXIT_FAILURE;
1748 : }
1749 1565664 : FOR( i = 0; i < colsX; ++i )
1750 : {
1751 9501188 : FOR( j = 0; j < entriesY; ++j )
1752 : {
1753 8363824 : *( Zp ) = Mpy_32_32( *( X ), Y[j] ); /*Q31 - (X_e + Y_e)*/
1754 8363824 : move32();
1755 8363824 : Zp++;
1756 8363824 : X++;
1757 : }
1758 : }
1759 : }
1760 :
1761 743480 : *Z_e = add( Y_e, X_e );
1762 743480 : move16();
1763 :
1764 743480 : return EXIT_SUCCESS;
1765 : }
1766 :
1767 749206 : Word16 matrix_product_diag_fx(
1768 : const Word32 *X, /* i : left hand matrix Q31 - X_e*/
1769 : Word16 X_e,
1770 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
1771 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
1772 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
1773 : const Word32 *Y, /* i : right hand matrix Q31 - Y_e*/
1774 : Word16 Y_e,
1775 : const Word16 rowsY, /* i : number of rows of the right hand matrix Q0*/
1776 : const Word16 colsY, /* i : number of columns of the right hand matrix Q0*/
1777 : const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/
1778 : Word32 *Z, /* o : resulting matrix after the matrix multiplication Q31 - Z_e*/
1779 : Word16 *Z_e )
1780 : {
1781 : Word16 j, k;
1782 749206 : Word32 *Zp = Z;
1783 :
1784 : /* Processing */
1785 749206 : test();
1786 749206 : test();
1787 749206 : test();
1788 749206 : IF( EQ_16( transpX, 1 ) && transpY == 0 ) /* We use X transpose */
1789 : {
1790 0 : IF( NE_16( rowsX, rowsY ) )
1791 : {
1792 0 : return EXIT_FAILURE;
1793 : }
1794 :
1795 0 : FOR( j = 0; j < colsY; ++j )
1796 : {
1797 0 : ( *Zp ) = 0;
1798 0 : move32();
1799 0 : FOR( k = 0; k < rowsX; ++k )
1800 : {
1801 0 : ( *Zp ) = Madd_32_32( ( *Zp ), X[k + j * rowsX], Y[k + j * rowsY] ); /*Q31 - (X_e + Y_e)*/
1802 0 : move32();
1803 : }
1804 0 : Zp++;
1805 : }
1806 : }
1807 749206 : ELSE IF( transpX == 0 && EQ_16( transpY, 1 ) ) /* We use Y transpose */
1808 : {
1809 632320 : IF( NE_16( colsX, colsY ) )
1810 : {
1811 0 : return EXIT_FAILURE;
1812 : }
1813 5124332 : FOR( j = 0; j < rowsY; ++j )
1814 : {
1815 4492012 : ( *Zp ) = 0;
1816 4492012 : move32();
1817 14942452 : FOR( k = 0; k < colsX; ++k )
1818 : {
1819 10450440 : ( *Zp ) = Madd_32_32( ( *Zp ), X[j + k * rowsX], Y[j + k * rowsY] ); /*Q31 - (X_e + Y_e)*/
1820 10450440 : move32();
1821 : }
1822 4492012 : Zp++;
1823 : }
1824 : }
1825 116886 : ELSE IF( EQ_16( transpX, 1 ) && EQ_16( transpY, 1 ) ) /* We use both transpose */
1826 : {
1827 0 : IF( NE_16( rowsX, colsY ) )
1828 : {
1829 0 : return EXIT_FAILURE;
1830 : }
1831 :
1832 0 : FOR( j = 0; j < rowsY; ++j )
1833 : {
1834 :
1835 0 : ( *Zp ) = 0;
1836 0 : move32();
1837 0 : FOR( k = 0; k < colsX; ++k )
1838 : {
1839 0 : ( *Zp ) = Madd_32_32( ( *Zp ), X[k + j * rowsX], Y[j + k * rowsY] ); /*Q31 - (X_e + Y_e)*/
1840 0 : move32();
1841 : }
1842 :
1843 0 : Zp++;
1844 : }
1845 : }
1846 : ELSE /* Regular case */
1847 : {
1848 116886 : IF( NE_16( colsX, rowsY ) )
1849 : {
1850 0 : return EXIT_FAILURE;
1851 : }
1852 :
1853 1182390 : FOR( j = 0; j < colsY; ++j )
1854 : {
1855 1065504 : ( *Zp ) = 0;
1856 1065504 : move32();
1857 2131008 : FOR( k = 0; k < colsX; ++k )
1858 : {
1859 1065504 : ( *Zp ) = Madd_32_32( ( *Zp ), X[j + k * rowsX], Y[k + j * rowsY] ); /*Q31 - (X_e + Y_e)*/
1860 1065504 : move32();
1861 : }
1862 1065504 : Zp++;
1863 : }
1864 : }
1865 :
1866 749206 : *Z_e = add( X_e, Y_e );
1867 749206 : move16();
1868 :
1869 749206 : return EXIT_SUCCESS;
1870 : }
1871 :
1872 : /*---------------------------------------------------------------------*
1873 : * matrix_product_diag()
1874 : *
1875 : * compute only the main diagonal of X*Y (Z=diag(X*Y))
1876 : *---------------------------------------------------------------------*/
1877 :
1878 1776710 : void cmplx_matrix_square_fx(
1879 : const Word32 *realX, /* i : real part of the matrix Q31 - input_exp*/
1880 : const Word32 *imagX, /* i : imaginary part of the matrix Q31 - input_exp*/
1881 : const Word16 mRows, /* i : number of rows of the matrix Q0*/
1882 : const Word16 nCols, /* i : number of columns of the matrix Q0*/
1883 : Word32 *realZ, /* o : real part of the resulting matrix Q31 - output_exp*/
1884 : Word32 *imagZ, /* o : imaginary part of the resulting matrix Q31 - output_exp*/
1885 : Word16 input_exp,
1886 : Word16 *output_exp )
1887 : {
1888 : Word16 i, j, k;
1889 : Word32 *realZp, *imagZp;
1890 : const Word32 *p_real1, *p_real2, *p_imag1, *p_imag2;
1891 : Word16 tmp1, tmp2;
1892 :
1893 : /* resulting matrix is hermitean, we only need to calc the upper triangle */
1894 : /* we assume transposition needed */
1895 :
1896 : /* column*column = column/column */
1897 5338398 : FOR( i = 0; i < nCols; i++ )
1898 : {
1899 8916622 : FOR( j = i; j < nCols; j++ )
1900 : {
1901 5354934 : p_real1 = realX + imult1616( i, mRows ); /*Q31 - input_exp*/
1902 5354934 : p_imag1 = imagX + imult1616( i, mRows ); /*Q31 - input_exp*/
1903 5354934 : p_real2 = realX + imult1616( j, mRows ); /*Q31 - input_exp*/
1904 5354934 : p_imag2 = imagX + imult1616( j, mRows ); /*Q31 - input_exp*/
1905 5354934 : realZp = realZ + add( i, imult1616( nCols, j ) ); /*Q31 - output_exp*/
1906 5354934 : imagZp = imagZ + add( i, imult1616( nCols, j ) ); /*Q31 - output_exp*/
1907 5354934 : *( realZp ) = 0;
1908 5354934 : move32();
1909 5354934 : *( imagZp ) = 0;
1910 5354934 : move32();
1911 :
1912 28343694 : FOR( k = 0; k < mRows; k++ )
1913 : {
1914 22988760 : *( imagZp ) = L_add( *( imagZp ), L_sub( Mpy_32_32( *( p_real1 ), *( p_imag2 ) ), Mpy_32_32( *( p_real2 ), *( p_imag1 ) ) ) ); /* Q31 - 2*input_exp */
1915 22988760 : move32();
1916 22988760 : *( realZp ) = L_add( *( realZp ), L_add( Mpy_32_32( *( p_real1 ), *( p_real2 ) ), Mpy_32_32( *( p_imag1 ), *( p_imag2 ) ) ) ); /* Q31 - 2*input_exp */
1917 22988760 : move32();
1918 22988760 : p_real1++;
1919 22988760 : p_real2++;
1920 22988760 : p_imag1++;
1921 22988760 : p_imag2++;
1922 : }
1923 : }
1924 : }
1925 :
1926 : /* fill lower triangle */
1927 3561688 : FOR( i = 1; i < nCols; i++ )
1928 : {
1929 3578224 : FOR( j = 0; j < i; j++ )
1930 : {
1931 1793246 : tmp1 = add( i, imult1616( nCols, j ) ); /*Q0*/
1932 1793246 : tmp2 = add( j, imult1616( nCols, i ) ); /*Q0*/
1933 1793246 : realZ[tmp1] = realZ[tmp2]; /*Q31 - output_exp*/
1934 1793246 : move32();
1935 1793246 : imagZ[tmp1] = imagZ[tmp2]; /*Q31 - output_exp*/
1936 1793246 : move32();
1937 : }
1938 : }
1939 :
1940 1776710 : *output_exp = shl( input_exp, 1 );
1941 1776710 : move16();
1942 :
1943 1776710 : return;
1944 : }
1945 :
1946 :
1947 739020 : void v_multc_acc_32_16(
1948 : const Word32 x[], /* i : Input vector Qx*/
1949 : const Word16 c, /* i : Constant Q31*/
1950 : Word32 y[], /* o : Output vector that contains y + c*x Qx*/
1951 : const Word16 N /* i : Vector length Q0*/
1952 : )
1953 : {
1954 : Word16 i;
1955 :
1956 39585340 : FOR( i = 0; i < N; i++ )
1957 : {
1958 38846320 : y[i] = L_add( y[i], Mpy_32_16_1( x[i], c ) );
1959 38846320 : move32();
1960 : }
1961 :
1962 739020 : return;
1963 : }
1964 240000 : void v_multc_acc_32_32(
1965 : const Word32 x[], /* i : Input vector Qx*/
1966 : const Word32 c, /* i : Constant Q31*/
1967 : Word32 y[], /* o : Output vector that contains y + c*x Qx*/
1968 : const Word16 N /* i : Vector length Q0*/
1969 : )
1970 : {
1971 : Word16 i;
1972 :
1973 14640000 : FOR( i = 0; i < N; i++ )
1974 : {
1975 14400000 : y[i] = L_add( y[i], Mpy_32_32( x[i], c ) ); /*Qx*/
1976 14400000 : move32();
1977 : }
1978 :
1979 240000 : return;
1980 : }
1981 :
1982 : /*---------------------------------------------------------------------*
1983 : * lls_interp_n()
1984 : *
1985 : * Linear least squares interpolation of an input vector
1986 : * The function calculates the slope 'a' and the offset 'b' of a LLS estimate for an input vector x such that
1987 : * y_i = a*i + b where i=1,..,N and (a,b) = min(a,b) [sum_N[(y_i - x_i)^2]]
1988 : * the interpolated vector is return as x[], if requested
1989 : *---------------------------------------------------------------------*/
1990 :
1991 4106 : void lls_interp_n_fx(
1992 : Word16 x_fx[], /* i/o: input/output vector Q15*/
1993 : const Word16 N, /* i : length of the input vector Q0*/
1994 : Word16 *a_fx, /* o : calculated slope Q15*/
1995 : Word16 *b_fx, /* o : calculated offset Q15*/
1996 : const Word16 upd /* i : use 1 to update x[] with the interpolated output Q0*/
1997 : )
1998 : {
1999 : Word16 i;
2000 4106 : const Word16 n_i_fx[11] = { 0, 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480 }; // Q11
2001 4106 : move16();
2002 4106 : move16();
2003 4106 : move16();
2004 4106 : move16();
2005 4106 : move16();
2006 4106 : move16();
2007 4106 : move16();
2008 4106 : move16();
2009 4106 : move16();
2010 4106 : move16();
2011 4106 : move16();
2012 :
2013 4106 : const Word16 one_by_n_fx[11] = { 0, 32767, 16384, 10911, 8192, 6553, 5459, 4681, 4096, 3640, 3276 }; /*Q15*/
2014 4106 : move16();
2015 4106 : move16();
2016 4106 : move16();
2017 4106 : move16();
2018 4106 : move16();
2019 4106 : move16();
2020 4106 : move16();
2021 4106 : move16();
2022 4106 : move16();
2023 4106 : move16();
2024 4106 : move16();
2025 :
2026 4106 : const Word16 sum_i_fx[12] = { 0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55 }; /*Q0*/
2027 4106 : move16();
2028 4106 : move16();
2029 4106 : move16();
2030 4106 : move16();
2031 4106 : move16();
2032 4106 : move16();
2033 4106 : move16();
2034 4106 : move16();
2035 4106 : move16();
2036 4106 : move16();
2037 4106 : move16();
2038 4106 : move16();
2039 :
2040 : // 1.0f/ ( N * sum_ii[N] - sum_i[N] * sum_i[N] )
2041 4106 : const Word32 res_table[12] = { 0, 0, 0, 357913952, 107374184, 42949672, 20452226, 10956549, 6391320, 3976821, 2603010, 385 }; /*Q31*/
2042 4106 : move16();
2043 4106 : move16();
2044 4106 : move16();
2045 4106 : move16();
2046 4106 : move16();
2047 4106 : move16();
2048 4106 : move16();
2049 4106 : move16();
2050 4106 : move16();
2051 4106 : move16();
2052 4106 : move16();
2053 4106 : move16();
2054 :
2055 : Word32 sum_x_fx, sum_ix_fx, slope_fx, offset_fx;
2056 4106 : Word16 dot_exp = 0, sum_ix_q = 0;
2057 4106 : move16();
2058 4106 : move16();
2059 :
2060 : Word32 num;
2061 4106 : assert( N > 0 && LE_16( N, 10 ) );
2062 :
2063 4106 : sum_x_fx = 0;
2064 4106 : move32();
2065 : Word16 idx;
2066 20530 : FOR( idx = 0; idx < N; idx++ )
2067 : {
2068 16424 : sum_x_fx = L_add( sum_x_fx, x_fx[idx] ); /*Q15*/
2069 : }
2070 4106 : sum_ix_fx = dotp_fx( x_fx, n_i_fx, N, &dot_exp ); /*sum_ix_q*/
2071 4106 : sum_ix_q = sub( 30, sub( dot_exp, ( 11 + 15 ) ) );
2072 :
2073 4106 : sum_ix_fx = L_shr( sum_ix_fx, sub( sum_ix_q, 15 ) ); /*Q15*/
2074 4106 : num = L_sub( imult3216( sum_ix_fx, N ), imult3216( sum_x_fx, sum_i_fx[N] ) ); /*Q15*/
2075 4106 : slope_fx = Mpy_32_32( num, res_table[N] ); /*Q15*/
2076 4106 : offset_fx = Mpy_32_16_1( L_sub( sum_x_fx, imult3216( slope_fx, sum_i_fx[N] ) ), one_by_n_fx[N] ); /*Q15*/
2077 :
2078 4106 : IF( upd )
2079 : {
2080 20530 : FOR( i = 0; i < N; i++ )
2081 : {
2082 16424 : IF( GT_32( imult3216( slope_fx, i ), MAX_WORD16 ) )
2083 : {
2084 0 : x_fx[i] = MAX_WORD16; /*Q15*/
2085 0 : move16();
2086 : }
2087 : ELSE
2088 : {
2089 16424 : x_fx[i] = extract_l( L_add_sat( imult3216( slope_fx, i ), offset_fx ) ); /*Q15*/
2090 16424 : move16();
2091 : }
2092 : }
2093 : }
2094 :
2095 4106 : IF( a_fx != NULL )
2096 : {
2097 4106 : *a_fx = extract_l( slope_fx ); /*Q15*/
2098 4106 : move16();
2099 : }
2100 :
2101 4106 : IF( b_fx != NULL )
2102 : {
2103 4106 : *b_fx = extract_l( offset_fx ); /*Q15*/
2104 4106 : move16();
2105 : }
2106 :
2107 4106 : return;
2108 : }
2109 :
2110 :
2111 : /* helper function for panning_wrap_angles */
2112 1776 : static float wrap_azi(
2113 : const float azi_deg )
2114 : {
2115 1776 : float azi = azi_deg;
2116 :
2117 : /* Wrap azimuth value */
2118 1776 : while ( azi > 180 )
2119 : {
2120 0 : azi -= 360.0f;
2121 : }
2122 :
2123 1827 : while ( azi <= -180 )
2124 : {
2125 51 : azi += 360;
2126 : }
2127 :
2128 1776 : return azi;
2129 : }
2130 : /* helper function for panning_wrap_angles */
2131 6830268 : static Word32 wrap_azi_fx(
2132 : const Word32 azi_deg /* Q22 */ )
2133 : {
2134 6830268 : Word32 azi = azi_deg; /*Q22*/
2135 6830268 : move32();
2136 :
2137 : /* Wrap azimuth value */
2138 8670789 : WHILE( GT_32( azi, ANGLE_180_DEG_Q22 ) )
2139 : {
2140 1840521 : azi = L_sub( azi, ANGLE_360_DEG_Q22 ); /*Q22*/
2141 : }
2142 :
2143 6869040 : WHILE( LE_32( azi, -ANGLE_180_DEG_Q22 ) )
2144 : {
2145 38772 : azi = L_add( azi, ANGLE_360_DEG_Q22 ); /*Q22*/
2146 : }
2147 :
2148 6830268 : return azi; /*Q22*/
2149 : }
2150 : /*-------------------------------------------------------------------*
2151 : * panning_wrap_angles()
2152 : *
2153 : * Wrap angles for amplitude panning to the range:
2154 : * azimuth = (-180, 180]
2155 : * elevation = [-90, 90]
2156 : * Considers direction changes from large elevation values
2157 : *-------------------------------------------------------------------*/
2158 1776 : void panning_wrap_angles(
2159 : const float azi_deg, /* i : azimuth in degrees for panning direction (positive left) */
2160 : const float ele_deg, /* i : elevation in degrees for panning direction (positive up) */
2161 : float *azi_wrapped, /* o : wrapped azimuth component */
2162 : float *ele_wrapped /* o : wrapped elevation component */
2163 : )
2164 : {
2165 : float azi, ele;
2166 :
2167 1776 : azi = azi_deg;
2168 1776 : ele = ele_deg;
2169 :
2170 1776 : if ( fabsf( ele ) < 90 )
2171 : {
2172 1776 : *ele_wrapped = ele;
2173 1776 : *azi_wrapped = wrap_azi( azi );
2174 1776 : return;
2175 : }
2176 : else
2177 : {
2178 : /* Special case when elevation is a multiple of 90; azimuth is irrelevant */
2179 0 : if ( ( fmodf( ele, 90 ) == 0 ) && ( fmodf( ele, 180 ) != 0 ) )
2180 : {
2181 0 : *azi_wrapped = 0;
2182 0 : while ( ele > 90 )
2183 : {
2184 0 : ele -= 360;
2185 : }
2186 0 : while ( ele < -90 )
2187 : {
2188 0 : ele += 360;
2189 : }
2190 0 : *ele_wrapped = ele;
2191 : }
2192 : else
2193 : {
2194 : /* Wrap elevation and adjust azimuth accordingly */
2195 0 : while ( fabsf( ele ) > 90 )
2196 : {
2197 : /* Flip to other hemisphere */
2198 0 : azi += 180;
2199 :
2200 : /* Compensate elevation accordingly */
2201 0 : if ( ele > 90 )
2202 : {
2203 0 : ele = 180 - ele;
2204 : }
2205 0 : else if ( ele < -90 )
2206 : {
2207 0 : ele = -180 - ele;
2208 : }
2209 : }
2210 0 : *azi_wrapped = wrap_azi( azi );
2211 0 : *ele_wrapped = ele;
2212 : }
2213 :
2214 0 : return;
2215 : }
2216 : }
2217 : /*-------------------------------------------------------------------*
2218 : * panning_wrap_angles_fx()
2219 : *
2220 : * Wrap angles for amplitude panning to the range:
2221 : * azimuth = (-180, 180]
2222 : * elevation = [-90, 90]
2223 : * Considers direction changes from large elevation values
2224 : *-------------------------------------------------------------------*/
2225 6833930 : void panning_wrap_angles_fx(
2226 : const Word32 azi_deg, /* i : azimuth in degrees for panning direction (positive left) Q22 */
2227 : const Word32 ele_deg, /* i : elevation in degrees for panning direction (positive up) Q22 */
2228 : Word32 *azi_wrapped, /* o : wrapped azimuth component Q22 */
2229 : Word32 *ele_wrapped /* o : wrapped elevation component Q22 */
2230 : )
2231 : {
2232 : Word32 azi, ele;
2233 :
2234 6833930 : azi = azi_deg; /*Q22*/
2235 6833930 : move32();
2236 6833930 : ele = ele_deg; /*Q22*/
2237 6833930 : move32();
2238 :
2239 6833930 : IF( LT_32( L_abs( ele ), ANGLE_90_DEG_Q22 ) )
2240 : {
2241 6830268 : *ele_wrapped = ele; /*Q22*/
2242 6830268 : move32();
2243 6830268 : *azi_wrapped = wrap_azi_fx( azi ); /*Q22*/
2244 6830268 : move32();
2245 6830268 : return;
2246 : }
2247 : ELSE
2248 : {
2249 : /* Special case when elevation is a multiple of 90; azimuth is irrelevant */
2250 3662 : IF( ( ( ele % ANGLE_90_DEG_Q22 ) == 0 ) && ( ( ele % ANGLE_180_DEG_Q22 ) != 0 ) )
2251 : {
2252 3662 : *azi_wrapped = 0;
2253 3662 : move32();
2254 3662 : WHILE( GT_32( ele, ANGLE_90_DEG_Q22 ) )
2255 : {
2256 0 : ele = L_sub( ele, ANGLE_360_DEG_Q22 );
2257 : }
2258 3662 : WHILE( LT_32( ele, -ANGLE_90_DEG_Q22 ) )
2259 : {
2260 0 : ele = L_add( ele, ANGLE_360_DEG_Q22 );
2261 : }
2262 3662 : *ele_wrapped = ele;
2263 3662 : move32();
2264 : }
2265 : ELSE
2266 : {
2267 : /* Wrap elevation and adjust azimuth accordingly */
2268 0 : WHILE( GT_32( L_abs( ele ), ANGLE_90_DEG_Q22 ) )
2269 : {
2270 : /* Flip to other hemisphere */
2271 0 : azi = L_add( azi, ANGLE_180_DEG_Q22 );
2272 :
2273 : /* Compensate elevation accordingly */
2274 0 : IF( GT_32( ele, ANGLE_90_DEG_Q22 ) )
2275 : {
2276 0 : ele = L_sub( ANGLE_180_DEG_Q22, ele );
2277 : }
2278 0 : ELSE IF( LT_32( ele, -ANGLE_90_DEG_Q22 ) )
2279 : {
2280 0 : ele = L_sub( -ANGLE_180_DEG_Q22, ele );
2281 : }
2282 : }
2283 0 : *azi_wrapped = wrap_azi_fx( azi ); /*Q22*/
2284 0 : move32();
2285 0 : *ele_wrapped = ele; /*Q22*/
2286 0 : move32();
2287 : }
2288 :
2289 3662 : return;
2290 : }
2291 : }
2292 :
2293 : /*-------------------------------------------------------------------------*
2294 : * v_sort_ind_fixed()
2295 : *
2296 : * Sort a float array
2297 : * (modified version of v_sort() to return an index array)
2298 : *-------------------------------------------------------------------------*/
2299 :
2300 16711 : void v_sort_ind_fixed(
2301 : Word32 *x, /* i/o: Vector to be sorted Qx*/
2302 : Word16 *idx, /* o : Original index positions Q0*/
2303 : const Word16 len /* i : vector length Q0*/
2304 : )
2305 : {
2306 : Word16 i, j;
2307 : Word32 tempr;
2308 : Word16 tempi;
2309 :
2310 75999 : FOR( i = 0; i < len; i++ )
2311 : {
2312 59288 : idx[i] = i;
2313 59288 : move16();
2314 : }
2315 :
2316 59288 : FOR( i = len - 2; i >= 0; i-- )
2317 : {
2318 42577 : tempr = x[i]; /*Qx*/
2319 42577 : move32();
2320 42577 : tempi = idx[i]; /*Qx*/
2321 42577 : move16();
2322 42577 : test();
2323 96593 : FOR( j = ( i + 1 ); LT_16( j, len ) && GT_32( tempr, x[j] ); j++ )
2324 : {
2325 54016 : test();
2326 54016 : x[j - 1] = x[j]; /*Qx*/
2327 54016 : move32();
2328 54016 : idx[j - 1] = idx[j]; /*Qx*/
2329 54016 : move16();
2330 : }
2331 42577 : x[j - 1] = tempr; /*Qx*/
2332 42577 : move32();
2333 42577 : idx[j - 1] = tempi; /*Qx*/
2334 42577 : move16();
2335 : }
2336 :
2337 16711 : return;
2338 : }
2339 :
2340 : /*-------------------------------------------------------------------*
2341 : * is_IVAS_bitrate()
2342 : *
2343 : * check if the bitrate is IVAS supported active bitrate
2344 : *-------------------------------------------------------------------*/
2345 :
2346 : /*! r: flag indicating a valid bitrate */
2347 0 : Word16 is_IVAS_bitrate_fx(
2348 : const Word32 ivas_total_brate /* i : IVAS total bitrate Q0*/
2349 : )
2350 : {
2351 : Word16 j;
2352 :
2353 0 : j = SIZE_IVAS_BRATE_TBL - IVAS_NUM_ACTIVE_BRATES; /* skip NO_DATA and SID bitrates */
2354 0 : move16();
2355 :
2356 0 : test();
2357 0 : WHILE( LE_16( j, SIZE_IVAS_BRATE_TBL ) && NE_32( ivas_total_brate, ivas_brate_tbl[j] ) )
2358 : {
2359 0 : test();
2360 0 : j = add( j, 1 );
2361 : }
2362 :
2363 0 : IF( GE_16( j, SIZE_IVAS_BRATE_TBL ) )
2364 : {
2365 0 : return 0;
2366 : }
2367 :
2368 0 : return 1;
2369 : }
2370 :
2371 : /*-------------------------------------------------------------------*
2372 : * is_DTXrate()
2373 : *
2374 : * identify DTX frame bitrates
2375 : *-------------------------------------------------------------------*/
2376 :
2377 4123317 : Word16 is_DTXrate(
2378 : const Word32 ivas_total_brate /* i : IVAS total bitrate Q0*/
2379 : )
2380 : {
2381 4123317 : Word16 dtx_rate_flag = 0;
2382 4123317 : move16();
2383 :
2384 4123317 : test();
2385 4123317 : IF( is_SIDrate( ivas_total_brate ) || ( EQ_32( ivas_total_brate, FRAME_NO_DATA ) ) )
2386 : {
2387 169534 : dtx_rate_flag = 1;
2388 169534 : move16();
2389 : }
2390 :
2391 4123317 : return dtx_rate_flag; /*Q0*/
2392 : }
2393 :
2394 : /*-------------------------------------------------------------------*
2395 : * is_SIDrate()
2396 : *
2397 : * identify SID frame bitrates
2398 : *-------------------------------------------------------------------*/
2399 :
2400 4523302 : Word16 is_SIDrate(
2401 : const Word32 ivas_total_brate /* i : IVAS total bitrate Q0*/
2402 : )
2403 : {
2404 4523302 : Word16 sid_rate_flag = 0;
2405 4523302 : move16();
2406 :
2407 4523302 : test();
2408 4523302 : test();
2409 9046604 : if ( EQ_32( ivas_total_brate, SID_1k75 ) ||
2410 9046604 : EQ_32( ivas_total_brate, SID_2k40 ) ||
2411 4523302 : EQ_32( ivas_total_brate, IVAS_SID_5k2 ) )
2412 : {
2413 29148 : sid_rate_flag = 1;
2414 29148 : move16();
2415 : }
2416 :
2417 4523302 : return sid_rate_flag; /*Q0*/
2418 : }
2419 :
2420 :
2421 : /*-------------------------------------------------------------------*
2422 : * rand_triangular_signed()
2423 : *
2424 : * generate a random value with a triangular pdf in [-0.5, 0.5]
2425 : *-------------------------------------------------------------------*/
2426 :
2427 24038576 : Word16 rand_triangular_signed_fx(
2428 : Word16 *seed, /*Q0*/
2429 : Word16 *exp_fac )
2430 : {
2431 : Word16 rand_val;
2432 24038576 : rand_val = Random( seed ); // q15
2433 : Word16 tmp1, tmp2;
2434 24038576 : Word16 exp1, exp = 1;
2435 24038576 : move16();
2436 24038576 : IF( rand_val <= 0 )
2437 : {
2438 : /* rand_val in [-1, 0] */
2439 : /*0.5f * (sqrtf(rand_val + 1.0f) - 1)*/
2440 12015506 : tmp1 = Sqrt16( add( shr( rand_val, 1 ), ONE_IN_Q14 ), &exp ); /*Q15 - exp*/
2441 12015506 : exp1 = BASOP_Util_Add_MantExp( tmp1, exp, negate( ONE_IN_Q14 ), 1, &tmp2 ); /*Q15 - exp1*/
2442 12015506 : tmp2 = shr( tmp2, 1 ); /*Q15 - exp1*/
2443 12015506 : *exp_fac = exp1;
2444 12015506 : move16();
2445 12015506 : return tmp2;
2446 : }
2447 : ELSE
2448 : {
2449 : /* rand_val in (0, 1) */
2450 : /*0.5f * ( 1 - sqrtf(1.0f - rand_val))*/
2451 12023070 : Word16 one_minus_rand = sub( MAX16B, rand_val ); /*Q15*/
2452 12023070 : exp = 0;
2453 12023070 : move16();
2454 12023070 : tmp1 = Sqrt16( one_minus_rand, &exp ); // q15 - exp
2455 12023070 : exp1 = BASOP_Util_Add_MantExp( ONE_IN_Q14, 1, negate( tmp1 ), exp, &tmp2 ); /*Q15 - exp1*/
2456 12023070 : tmp2 = shr( tmp2, 1 ); /*Q15 - exp1*/
2457 12023070 : *exp_fac = exp1;
2458 12023070 : move16();
2459 :
2460 12023070 : return tmp2; /*Q15 - exp_fac*/
2461 : }
2462 : }
2463 :
2464 : /*-------------------------------------------------------------------*
2465 : * ceil_log_2()
2466 : *
2467 : * calculates ceil(log2(val))
2468 : *-------------------------------------------------------------------*/
2469 50649 : Word16 ceil_log_2(
2470 : UWord64 val /*Q0*/ )
2471 : {
2472 :
2473 50649 : IF( val <= 0 )
2474 : {
2475 0 : assert( 0 );
2476 : }
2477 50649 : ELSE IF( LE_64( val, 1 ) )
2478 : {
2479 285 : return 0;
2480 : }
2481 50364 : ELSE IF( LE_64( val, 2 ) )
2482 : {
2483 2909 : return 1;
2484 : }
2485 47455 : ELSE IF( LE_64( val, 4 ) )
2486 : {
2487 4034 : return 2;
2488 : }
2489 43421 : ELSE IF( LE_64( val, 8 ) )
2490 : {
2491 2652 : return 3;
2492 : }
2493 40769 : ELSE IF( LE_64( val, 16 ) )
2494 : {
2495 1311 : return 4;
2496 : }
2497 39458 : ELSE IF( LE_64( val, 32 ) )
2498 : {
2499 1371 : return 5;
2500 : }
2501 38087 : ELSE IF( LE_64( val, 64 ) )
2502 : {
2503 1313 : return 6;
2504 : }
2505 36774 : ELSE IF( LE_64( val, 128 ) )
2506 : {
2507 3534 : return 7;
2508 : }
2509 33240 : ELSE IF( LE_64( val, 256 ) )
2510 : {
2511 5583 : return 8;
2512 : }
2513 27657 : ELSE IF( LE_64( val, 512 ) )
2514 : {
2515 4934 : return 9;
2516 : }
2517 22723 : ELSE IF( LE_64( val, 1024 ) )
2518 : {
2519 6894 : return 10;
2520 : }
2521 15829 : ELSE IF( LE_64( val, 2048 ) )
2522 : {
2523 2074 : return 11;
2524 : }
2525 13755 : ELSE IF( LE_64( val, 4096 ) )
2526 : {
2527 1663 : return 12;
2528 : }
2529 12092 : ELSE IF( LE_64( val, 8192 ) )
2530 : {
2531 1247 : return 13;
2532 : }
2533 10845 : ELSE IF( LE_64( val, 16384 ) )
2534 : {
2535 1543 : return 14;
2536 : }
2537 9302 : ELSE IF( LE_64( val, 32768 ) )
2538 : {
2539 3074 : return 15;
2540 : }
2541 6228 : ELSE IF( LE_64( val, 65536 ) )
2542 : {
2543 472 : return 16;
2544 : }
2545 5756 : ELSE IF( LE_64( val, 131072 ) )
2546 : {
2547 192 : return 17;
2548 : }
2549 5564 : ELSE IF( LE_64( val, 262144 ) )
2550 : {
2551 259 : return 18;
2552 : }
2553 5305 : ELSE IF( LE_64( val, 524288 ) )
2554 : {
2555 248 : return 19;
2556 : }
2557 5057 : ELSE IF( LE_64( val, 1048576 ) )
2558 : {
2559 92 : return 20;
2560 : }
2561 4965 : ELSE IF( LE_64( val, 2097152 ) )
2562 : {
2563 109 : return 21;
2564 : }
2565 4856 : ELSE IF( LE_64( val, 4194304 ) )
2566 : {
2567 327 : return 22;
2568 : }
2569 4529 : ELSE IF( LE_64( val, 8388608 ) )
2570 : {
2571 438 : return 23;
2572 : }
2573 4091 : ELSE IF( LE_64( val, 16777216 ) )
2574 : {
2575 792 : return 24;
2576 : }
2577 3299 : ELSE IF( LE_64( val, 33554432 ) )
2578 : {
2579 485 : return 25;
2580 : }
2581 2814 : ELSE IF( LE_64( val, 67108864 ) )
2582 : {
2583 329 : return 26;
2584 : }
2585 2485 : ELSE IF( LE_64( val, 134217728 ) )
2586 : {
2587 135 : return 27;
2588 : }
2589 2350 : ELSE IF( LE_64( val, 268435456 ) )
2590 : {
2591 121 : return 28;
2592 : }
2593 2229 : ELSE IF( LE_64( val, 536870912 ) )
2594 : {
2595 51 : return 29;
2596 : }
2597 2178 : ELSE IF( LE_64( val, 1073741824 ) )
2598 : {
2599 60 : return 30;
2600 : }
2601 2118 : ELSE IF( LE_64( val, 2147483648 ) )
2602 : {
2603 91 : return 31;
2604 : }
2605 2027 : ELSE IF( LE_64( val, 4294967296 ) )
2606 : {
2607 145 : return 32;
2608 : }
2609 1882 : ELSE IF( LE_64( val, 8589934592 ) )
2610 : {
2611 59 : return 33;
2612 : }
2613 1823 : ELSE IF( LE_64( val, 17179869184 ) )
2614 : {
2615 200 : return 34;
2616 : }
2617 1623 : ELSE IF( LE_64( val, 34359738368 ) )
2618 : {
2619 216 : return 35;
2620 : }
2621 1407 : ELSE IF( LE_64( val, 68719476736 ) )
2622 : {
2623 166 : return 36;
2624 : }
2625 1241 : ELSE IF( LE_64( val, 137438953472 ) )
2626 : {
2627 136 : return 37;
2628 : }
2629 1105 : ELSE IF( LE_64( val, 274877906944 ) )
2630 : {
2631 144 : return 38;
2632 : }
2633 961 : ELSE IF( LE_64( val, 549755813888 ) )
2634 : {
2635 117 : return 39;
2636 : }
2637 844 : ELSE IF( LE_64( val, 1099511627776 ) )
2638 : {
2639 116 : return 40;
2640 : }
2641 728 : ELSE IF( LE_64( val, 2199023255552 ) )
2642 : {
2643 112 : return 41;
2644 : }
2645 616 : ELSE IF( LE_64( val, 4398046511104 ) )
2646 : {
2647 163 : return 42;
2648 : }
2649 453 : ELSE IF( LE_64( val, 8796093022208 ) )
2650 : {
2651 80 : return 43;
2652 : }
2653 373 : ELSE IF( LE_64( val, 17592186044416 ) )
2654 : {
2655 58 : return 44;
2656 : }
2657 315 : ELSE IF( LE_64( val, 35184372088832 ) )
2658 : {
2659 122 : return 45;
2660 : }
2661 193 : ELSE IF( LE_64( val, 70368744177664 ) )
2662 : {
2663 90 : return 46;
2664 : }
2665 103 : ELSE IF( LE_64( val, 140737488355328 ) )
2666 : {
2667 64 : return 47;
2668 : }
2669 39 : ELSE IF( LE_64( val, 281474976710656 ) )
2670 : {
2671 39 : return 48;
2672 : }
2673 0 : ELSE IF( LE_64( val, 562949953421312 ) )
2674 : {
2675 0 : return 49;
2676 : }
2677 0 : ELSE IF( LE_64( val, 1125899906842624 ) )
2678 : {
2679 0 : return 50;
2680 : }
2681 0 : ELSE IF( LE_64( val, 2251799813685248 ) )
2682 : {
2683 0 : return 51;
2684 : }
2685 0 : ELSE IF( LE_64( val, 4503599627370496 ) )
2686 : {
2687 0 : return 52;
2688 : }
2689 0 : ELSE IF( LE_64( val, 9007199254740992 ) )
2690 : {
2691 0 : return 53;
2692 : }
2693 0 : ELSE IF( LE_64( val, 18014398509481984 ) )
2694 : {
2695 0 : return 54;
2696 : }
2697 0 : ELSE IF( LE_64( val, 36028797018963968 ) )
2698 : {
2699 0 : return 55;
2700 : }
2701 0 : ELSE IF( LE_64( val, 72057594037927936 ) )
2702 : {
2703 0 : return 56;
2704 : }
2705 0 : ELSE IF( LE_64( val, 144115188075855872 ) )
2706 : {
2707 0 : return 57;
2708 : }
2709 0 : ELSE IF( LE_64( val, 288230376151711744 ) )
2710 : {
2711 0 : return 58;
2712 : }
2713 0 : ELSE IF( LE_64( val, 576460752303423488 ) )
2714 : {
2715 0 : return 59;
2716 : }
2717 0 : ELSE IF( LE_64( val, 1152921504606846976 ) )
2718 : {
2719 0 : return 60;
2720 : }
2721 0 : ELSE IF( LE_64( val, 2305843009213693952 ) )
2722 : {
2723 0 : return 61;
2724 : }
2725 0 : ELSE IF( LE_64( val, 4611686018427387904 ) )
2726 : {
2727 0 : return 62;
2728 : }
2729 0 : ELSE IF( LE_64( val, 9223372036854775807 ) )
2730 : {
2731 0 : return 63;
2732 : }
2733 0 : return 64;
2734 : }
2735 :
2736 :
2737 : /*-------------------------------------------------------------------*
2738 : * var_32_fx()
2739 : *
2740 : * calculates variance of 32-bit array
2741 : * Currently using direct division.
2742 : * Needs update once required basops are implemented.
2743 : *-------------------------------------------------------------------*/
2744 :
2745 129221 : Word64 var_32_fx(
2746 : const Word32 *x, /* i : input vector q*/
2747 : const Word16 len, /* i : length of inputvector Q0*/
2748 : Word16 q /* q : q-factor for the array */
2749 : )
2750 : {
2751 : Word16 i;
2752 : Word64 mean, var;
2753 :
2754 129221 : mean = 0;
2755 129221 : move64();
2756 129221 : var = 0;
2757 129221 : move64();
2758 :
2759 646105 : FOR( i = 0; i < len; i++ )
2760 : {
2761 516884 : mean = W_add( mean, x[i] ); /*q*/
2762 : }
2763 :
2764 129221 : mean = mean / len; /* NOTE: No BASOP for 64 bit division q*/
2765 :
2766 646105 : FOR( i = 0; i < len; i++ )
2767 : {
2768 516884 : var = W_add( var, Mpy_32_32( L_sub( x[i], W_extract_l( mean ) ), L_sub( x[i], W_extract_l( mean ) ) ) ); /*q + q - 31*/
2769 : }
2770 :
2771 129221 : var = W_shl( var, sub( 31, q ) ); /*q*/
2772 :
2773 129221 : var = var / len; /* NOTE: No BASOP for 64 bit division q*/
2774 :
2775 129221 : return var; /*q*/
2776 : }
|