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 38131 : 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 38131 : IF( n <= 0 )
85 : {
86 : /* no need to transfer vectors with size 0 */
87 0 : return;
88 : }
89 :
90 38131 : IF( y < x )
91 : {
92 3779842 : FOR( i = 0; i < n; i++ )
93 : {
94 3762171 : y[i] = x[i];
95 3762171 : move16();
96 : }
97 : }
98 : ELSE
99 : {
100 88035 : FOR( i = n - 1; i >= 0; i-- )
101 : {
102 67575 : y[i] = x[i];
103 67575 : move16();
104 : }
105 : }
106 :
107 38131 : 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 424456 : 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 424456 : UWord32 noClipping = 0;
131 424456 : move32();
132 :
133 : /*-----------------------------------------------------------------*
134 : * float to integer conversion with saturation control
135 : *-----------------------------------------------------------------*/
136 :
137 1957181 : FOR( n = 0; n < n_channels; n++ )
138 : {
139 1532725 : tmp = mvl2s_r( synth[n], q_synth, synth_loc, output_frame ); /*Q0*/
140 1532725 : noClipping = UL_addNsD( noClipping, tmp );
141 :
142 1227499805 : FOR( i = 0; i < output_frame; i++ )
143 : {
144 1225967080 : synth_out[( ( i * n_channels ) + n )] = synth_loc[i]; /*q_synth*/
145 1225967080 : move16();
146 : }
147 : }
148 :
149 424456 : 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 19553 : 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 64444 : FOR( n = 0; n < n_channels; n++ )
175 : {
176 35835931 : FOR( i = 0; i < output_frame; i++ )
177 : {
178 35791040 : synth_out[( ( i * n_channels ) + n )] = synth[n][i]; /*Q11*/
179 35791040 : move16();
180 : }
181 : }
182 :
183 19553 : 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 82213179 : 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 82213179 : IF( n <= 0 )
255 : {
256 : /* cannot transfer vectors with size 0 */
257 0 : return;
258 : }
259 :
260 82213179 : IF( y_fx < x_fx )
261 : {
262 74488348 : ix = 0;
263 74488348 : move16();
264 74488348 : iy = 0;
265 74488348 : move16();
266 1152055005 : FOR( i = 0; i < n; i++ )
267 : {
268 1077566657 : y_fx[iy] = x_fx[ix]; /*Q29*/
269 1077566657 : move32();
270 :
271 1077566657 : ix = ix + x_inc;
272 1077566657 : iy = iy + y_inc;
273 : }
274 : }
275 : ELSE
276 : {
277 7724831 : ix = i_mult( sub( n, 1 ), x_inc ); /*Q0*/
278 7724831 : iy = i_mult( sub( n, 1 ), y_inc );
279 58652057 : FOR( i = sub( n, 1 ); i >= 0; i-- )
280 : {
281 50927226 : y_fx[iy] = x_fx[ix]; /*Q29*/
282 50927226 : move32();
283 :
284 50927226 : ix = ix - x_inc;
285 50927226 : iy = iy - y_inc;
286 : }
287 : }
288 :
289 82213179 : 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 8471993 : 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 8471993 : test();
314 8471993 : test();
315 8471993 : test();
316 8471993 : test();
317 8471993 : 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 200320650 : FOR( i = 0; i < N; i++ )
321 : {
322 191848657 : y[i] = L_add( x1[2 * i + 0], x1[2 * i + 1] ); /*Qx*/
323 191848657 : move32();
324 : }
325 8471993 : 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 4469236 : 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 4469236 : Word16 ix1 = 0;
401 4469236 : Word16 ix2 = 0;
402 4469236 : Word16 iy = 0;
403 :
404 4469236 : move16();
405 4469236 : move16();
406 4469236 : move16();
407 :
408 77151842 : FOR( i = 0; i < N; i++ )
409 : {
410 72682606 : y_fx[iy] = Mpy_32_32( x1_fx[ix1], x2_fx[ix2] ); /*Qx1 + Qx2 - 31*/
411 72682606 : move32();
412 :
413 72682606 : ix1 = add( ix1, x1_inc );
414 72682606 : ix2 = add( ix2, x2_inc );
415 72682606 : iy = add( iy, y_inc );
416 : }
417 :
418 4469236 : 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 2067438 : 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 57804083 : FOR( i = 0; i < N; i++ )
459 : {
460 55736645 : y[i] = L_add( c, x[i] ); /*Qx*/
461 55736645 : move32();
462 : }
463 :
464 2067438 : 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 54849 : y_fx[i] = x1_fx[i]; /*x1_q_fx*/
509 54849 : move32();
510 54849 : y_q_fx[i] = x1_q_fx[i];
511 54849 : move16();
512 : }
513 : ELSE
514 : {
515 2751 : y_fx[i] = x2_fx[i]; /*x2_q_fx*/
516 2751 : move32();
517 2751 : y_q_fx[i] = x2_q_fx[i];
518 2751 : 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 tmp;
610 : const Word32 *pt_x, *pt_A;
611 0 : pt_A = A;
612 0 : suma = 0;
613 0 : move64();
614 :
615 0 : FOR( i = 0; i < N; i++ )
616 : {
617 0 : tmp_sum = 0;
618 0 : move32();
619 0 : pt_x = x;
620 :
621 0 : FOR( j = 0; j <= i; j++ )
622 : {
623 0 : tmp_sum = W_add( tmp_sum, Mpy_32_32( *pt_x++, *pt_A++ ) );
624 : }
625 :
626 0 : tmp = W_shl_sat_l( tmp_sum, -4 ); // to make sure that the tmp_sum will not overflow
627 0 : suma = W_mac_32_32( suma, tmp, tmp );
628 : }
629 :
630 0 : return suma;
631 : }
632 :
633 0 : void v_mult_mat_fixed(
634 : Word32 *y, /* o : the product x*A Qx - guardbits*/
635 : const Word32 *x, /* i : vector x Qx*/
636 : const Word32 *A, /* i : matrix A Q31*/
637 : const Word16 Nr, /* i : number of rows Q0*/
638 : const Word16 Nc, /* i : number of columns Q0*/
639 : Word16 guardbits )
640 : {
641 : Word16 i, j;
642 : const Word32 *pt_x, *pt_A;
643 : Word32 tmp_y[MAX_V_MULT_MAT];
644 : Word32 *pt_y;
645 :
646 0 : pt_y = tmp_y;
647 0 : pt_A = A; /*Q31*/
648 :
649 0 : FOR( i = 0; i < Nc; i++ )
650 : {
651 0 : pt_x = x; /*Qx*/
652 0 : *pt_y = 0;
653 0 : move32();
654 0 : FOR( j = 0; j < Nr; j++ )
655 : {
656 0 : *pt_y = L_add( *pt_y, L_shr( Mpy_32_32( ( *pt_x++ ), ( *pt_A++ ) ), guardbits ) ); /*Qx - guardbits*/
657 0 : move32();
658 : }
659 0 : pt_y++;
660 : }
661 :
662 0 : MVR2R_WORD32( tmp_y, y, Nc ); /*Qx - guardbits*/
663 0 : }
664 :
665 0 : Word32 dot_product_cholesky_fx(
666 : const Word32 *x, /* i : vector x Qx1*/
667 : const Word32 *A, /* i : Cholesky matrix A Qx2*/
668 : const Word16 N /* i : vector & matrix size Q0*/
669 : )
670 : {
671 : Word16 i, j;
672 : Word32 suma, tmp_sum;
673 : const Word32 *pt_x, *pt_A;
674 :
675 0 : pt_A = A;
676 0 : suma = 0;
677 0 : move32();
678 :
679 0 : FOR( i = 0; i < N; i++ )
680 : {
681 0 : tmp_sum = 0;
682 0 : move32();
683 0 : pt_x = x;
684 0 : FOR( j = 0; j <= i; j++ )
685 : {
686 0 : tmp_sum = L_add( tmp_sum, Mpy_32_32( *pt_x++, *pt_A++ ) ); /*Qx1 + Qx2 - 31*/
687 : }
688 :
689 0 : suma = L_add( suma, Mpy_32_32( tmp_sum, tmp_sum ) );
690 : }
691 :
692 0 : return suma;
693 : }
694 :
695 :
696 : /*---------------------------------------------------------------------*
697 : * v_mult_mat_fx()
698 : *
699 : * Multiplication of row vector x by matrix A, where x has size Nr and
700 : * A has size Nr x Nc ans it is stored column-wise in memory.
701 : * The resulting row vector y has size Nc
702 : *---------------------------------------------------------------------*/
703 :
704 0 : void v_mult_mat_fx(
705 : Word32 *y_fx, /* o : the product x*A y_q_fx*/
706 : Word16 *y_q_fx,
707 : const Word32 *x_fx, /* i : vector x x_q_fx*/
708 : Word16 *x_q_fx,
709 : const Word32 *A_fx, /* i : matrix A A_q_fx*/
710 : Word16 *A_q_fx,
711 : const Word16 Nr, /* i : number of rows Q0*/
712 : const Word16 Nc /* i : number of columns Q0*/
713 : )
714 : {
715 : Word16 i, j;
716 : const Word32 *pt_x_fx, *pt_A_fx;
717 : Word32 *pt_y_fx;
718 : Word32 tmp_y_fx[MAX_V_MULT_MAT];
719 : Word32 temp;
720 : Word16 temp_q;
721 :
722 0 : pt_y_fx = tmp_y_fx;
723 0 : pt_A_fx = A_fx; /*A_q_fx*/
724 0 : pt_x_fx = x_fx; /*x_q_fx*/
725 :
726 0 : FOR( i = 0; i < Nc; i++ )
727 : {
728 0 : pt_x_fx = x_fx; /*x_q_fx*/
729 0 : *pt_y_fx = 0;
730 0 : move32();
731 0 : y_q_fx[i] = 0;
732 0 : move32();
733 0 : FOR( j = 0; j < Nr; j++ )
734 : {
735 0 : temp = Mpy_32_32( *pt_x_fx++, *pt_A_fx++ ); /*x_q_fx + A_q_fx - 31*/
736 0 : temp_q = sub( add( x_q_fx[j], A_q_fx[Nr * i + j] ), 31 );
737 0 : IF( j == 0 )
738 : {
739 0 : *pt_y_fx = temp;
740 0 : move32();
741 0 : y_q_fx[i] = temp_q;
742 0 : move16();
743 : }
744 : ELSE
745 : {
746 0 : IF( GT_16( y_q_fx[i], temp_q ) )
747 : {
748 0 : *pt_y_fx = L_add( L_shr( *pt_y_fx, sub( y_q_fx[i], temp_q ) ), temp );
749 0 : move32();
750 0 : y_q_fx[i] = temp_q;
751 0 : move16();
752 : }
753 : ELSE
754 : {
755 0 : *pt_y_fx = L_add( *pt_y_fx, L_shr( temp, sub( temp_q, y_q_fx[i] ) ) );
756 0 : move32();
757 : }
758 : }
759 : }
760 0 : pt_y_fx++;
761 : }
762 :
763 0 : MVR2R_WORD32( tmp_y_fx, y_fx, Nc ); /*y_q_fx*/
764 :
765 0 : return;
766 : }
767 :
768 : /*---------------------------------------------------------------------*
769 : * logsumexp()
770 : *
771 : * Compute logarithm of the sum of exponentials of input vector in a numerically stable way
772 : *---------------------------------------------------------------------*/
773 :
774 : /*! r: log(sum(exp(x)) of the input array x */
775 0 : Word32 logsumexp_fx(
776 : const Word32 x[], /* i : input array x Q31 - x_e*/
777 : const Word16 x_e,
778 : const Word16 N /* i : number of elements in array x Q0*/
779 : )
780 : {
781 : Word32 max_exp, temp32_sub;
782 : Word32 sum, temp32, pow_temp;
783 0 : Word32 log2_e_fx = 1549082005; // Q30 of log2(e);
784 0 : Word16 log2_e_fx_e = 1;
785 0 : move16();
786 0 : move16();
787 : Word16 i;
788 0 : Word16 pow_e, sum_e = 0;
789 0 : move16();
790 0 : max_exp = x[0]; /*Q31 - x_e*/
791 0 : move32();
792 0 : sum = 0;
793 0 : move32();
794 0 : FOR( i = 1; i < N; i++ )
795 : {
796 0 : IF( GT_32( x[i], max_exp ) )
797 : {
798 0 : max_exp = x[i]; /*Q31 - x_e*/
799 0 : move32();
800 : }
801 : }
802 :
803 0 : FOR( i = 0; i < N; i++ )
804 : {
805 0 : temp32_sub = L_sub( x[i], max_exp ); /*Q31 - x_e*/
806 0 : pow_e = 0;
807 0 : move16();
808 0 : temp32 = Mpy_32_32( log2_e_fx, temp32_sub ); /*Q30 - x_e*/
809 0 : pow_temp = BASOP_util_Pow2( temp32, add( x_e, log2_e_fx_e ), &pow_e ); /*Q31 - pow_e*/
810 0 : sum = BASOP_Util_Add_Mant32Exp( sum, sum_e, pow_temp, pow_e, &sum_e ); /*Q31 - sum_e*/
811 : }
812 0 : temp32 = L_add( BASOP_Util_Log2( sum ), L_shl( sum_e, Q25 ) ); /*Q25*/
813 0 : temp32 = Mpy_32_32( temp32, 1488522239 ); /*logf(x) = log2(x)*logf(2) Q25*/
814 0 : temp32 = L_add( L_shr( temp32, sub( x_e, 6 ) ), max_exp ); // q = 31-x_e
815 0 : return temp32; /*31-x_e*/
816 : }
817 :
818 : /*---------------------------------------------------------------------*
819 : * lin_interp()
820 : *
821 : * Linearly maps x from source range <x1, x2> to the target range <y1, y2>
822 : *---------------------------------------------------------------------*/
823 : /*! r: mapped output value */
824 0 : Word32 lin_interp32_fx(
825 : const Word32 x, /* i : the value to be mapped Qx */
826 : const Word32 x1, /* i : source range interval: low end Qx */
827 : const Word32 y1, /* i : source range interval: high end Q31 */
828 : const Word32 x2, /* i : target range interval: low Qx */
829 : const Word32 y2, /* i : target range interval: high Q31 */
830 : const Word16 flag_sat /* i : flag to indicate whether to apply saturation */
831 : )
832 : {
833 : Word32 temp32;
834 : Word32 temp_div;
835 : Word16 exp_out;
836 :
837 0 : IF( L_sub( x2, x1 ) == 0 )
838 : {
839 0 : return y1;
840 : }
841 0 : ELSE IF( flag_sat )
842 : {
843 0 : IF( GE_32( x, L_max( x1, x2 ) ) )
844 : {
845 0 : return GT_32( x1, x2 ) ? y1 : y2;
846 : }
847 0 : ELSE IF( LE_32( x, L_min( x1, x2 ) ) )
848 : {
849 0 : return LT_32( x1, x2 ) ? y1 : y2;
850 : }
851 : }
852 :
853 0 : temp32 = Mpy_32_32( L_sub( x, x1 ), L_sub( y2, y1 ) ); /* Qx */
854 0 : temp_div = L_deposit_h( BASOP_Util_Divide3232_Scale( temp32, L_sub( x2, x1 ), &exp_out ) );
855 0 : temp32 = BASOP_Util_Add_Mant32Exp( y1, 0, temp_div, exp_out, &exp_out );
856 0 : temp32 = L_shl_sat( temp32, exp_out ); /* Q31 */
857 :
858 0 : return temp32;
859 : }
860 :
861 : /*-------------------------------------------------------------------*
862 : * check_bounds_s_fx()
863 : *
864 : * Ensure the input value is within the given limits
865 : *-------------------------------------------------------------------*/
866 :
867 : /*! r: Adjusted value */
868 851426 : Word16 check_bounds_s_fx(
869 : const Word16 value, /* i : Input value Q0*/
870 : const Word16 low, /* i : Low limit Q0*/
871 : const Word16 high /* i : High limit Q0*/
872 : )
873 : {
874 : Word16 value_adj;
875 :
876 851426 : value_adj = s_min( s_max( value, low ), high ); /*Q0*/
877 :
878 851426 : return value_adj; /*Q0*/
879 : }
880 :
881 : /*-------------------------------------------------------------------*
882 : * check_bounds_l()
883 : *
884 : * Ensure the input value is within the given limits
885 : *-------------------------------------------------------------------*/
886 :
887 : /*! r: Adjusted value */
888 531730 : Word32 check_bounds_l(
889 : const Word32 value, /* i : Input value Q0*/
890 : const Word32 low, /* i : Low limit Q0*/
891 : const Word32 high /* i : High limit Q0*/
892 : )
893 : {
894 : Word32 value_adj;
895 :
896 531730 : value_adj = L_min( L_max( value, low ), high ); /*Q0*/
897 :
898 531730 : return value_adj; /*Q0*/
899 : }
900 :
901 : /****************************************************************************/
902 : /* matrix functions */
903 : /* matrices are ordered column-wise in memory */
904 : /****************************************************************************/
905 :
906 : /*---------------------------------------------------------------------*
907 : * matrix product
908 : *
909 : * comput the matrix product of two matrices (Z=X*Y)
910 : *---------------------------------------------------------------------*/
911 :
912 2138353 : Word16 matrix_product_mant_exp_fx(
913 : const Word32 *X_fx, /* i : left hand matrix Q31 - X_fx_e*/
914 : const Word16 X_fx_e, /* i : left hand matrix */
915 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
916 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
917 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
918 : const Word32 *Y_fx, /* i : right hand matrix Q31 - Y_fx_e*/
919 : const Word16 Y_fx_e, /* i : right hand matrix */
920 : const Word16 rowsY, /* i : number of rows of the right hand matrix Q0*/
921 : const Word16 colsY, /* i : number of columns of the right hand matrix Q0*/
922 : const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/
923 : Word32 *Z_fx, /* o : resulting matrix after the matrix multiplication Q31 - Z_fx_e*/
924 : Word16 *Z_fx_e /* o : resulting matrix after the matrix multiplication */
925 : )
926 : {
927 : Word16 i, j, k;
928 2138353 : Word32 *Zp_fx = Z_fx;
929 : Word16 out_e[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS];
930 2138353 : Word16 *Zp_fx_e = out_e;
931 : Word16 row, col;
932 : Word64 temp;
933 : Word16 temp_e;
934 2138353 : Word16 prod_e = add( X_fx_e, Y_fx_e );
935 :
936 2138353 : Word16 max_exp = -31;
937 2138353 : move16();
938 :
939 : /* Processing */
940 2138353 : test();
941 2138353 : test();
942 2138353 : test();
943 2138353 : IF( EQ_16( transpX, 1 ) && transpY == 0 ) /* We use X transpose */
944 : {
945 0 : IF( NE_16( rowsX, rowsY ) )
946 : {
947 0 : return EXIT_FAILURE;
948 : }
949 0 : FOR( j = 0; j < colsY; ++j )
950 : {
951 0 : FOR( i = 0; i < colsX; ++i )
952 : {
953 0 : temp = 0;
954 0 : move64();
955 :
956 0 : FOR( k = 0; k < rowsX; ++k )
957 : {
958 0 : temp = W_mac_32_32( temp, X_fx[k + i * rowsX], Y_fx[k + j * rowsY] ); // X_fx_e + Y_fx_e
959 : }
960 : /* Maximize accumulated value to 32-bit */
961 0 : temp_e = W_norm( temp );
962 0 : temp = W_shl( temp, temp_e );
963 0 : if ( 0 == temp )
964 : {
965 0 : temp_e = prod_e;
966 0 : move16();
967 : }
968 0 : *Zp_fx_e = sub( prod_e, temp_e );
969 0 : move16();
970 0 : ( *Zp_fx ) = W_extract_h( temp );
971 0 : move32();
972 0 : max_exp = s_max( max_exp, *Zp_fx_e ); // Find the max exp
973 0 : Zp_fx++;
974 0 : Zp_fx_e++;
975 : }
976 : }
977 0 : row = colsY; /*Q0*/
978 0 : move16();
979 0 : col = colsX; /*Q0*/
980 0 : move16();
981 : }
982 2138353 : ELSE IF( transpX == 0 && EQ_16( transpY, 1 ) ) /* We use Y transpose */
983 : {
984 869996 : IF( NE_16( colsX, colsY ) )
985 : {
986 0 : return EXIT_FAILURE;
987 : }
988 5193485 : FOR( j = 0; j < rowsY; ++j )
989 : {
990 38051404 : FOR( i = 0; i < rowsX; ++i )
991 : {
992 33727915 : temp = 0;
993 33727915 : move64();
994 110702540 : FOR( k = 0; k < colsX; ++k )
995 : {
996 76974625 : temp = W_mac_32_32( temp, X_fx[i + k * rowsX], Y_fx[j + k * rowsY] ); // X_fx_e + Y_fx_e
997 : }
998 : /* Maximize accumulated value to 32-bit */
999 33727915 : temp_e = W_norm( temp );
1000 33727915 : temp = W_shl( temp, temp_e );
1001 33727915 : if ( 0 == temp )
1002 : {
1003 15075146 : temp_e = prod_e;
1004 15075146 : move16();
1005 : }
1006 33727915 : *Zp_fx_e = sub( prod_e, temp_e );
1007 33727915 : move16();
1008 33727915 : ( *Zp_fx ) = W_extract_h( temp );
1009 33727915 : move32();
1010 33727915 : max_exp = s_max( max_exp, *Zp_fx_e ); // Find the max exp
1011 33727915 : Zp_fx++;
1012 33727915 : Zp_fx_e++;
1013 : }
1014 : }
1015 869996 : row = rowsY; /*Q0*/
1016 869996 : move16();
1017 869996 : col = rowsX; /*Q0*/
1018 869996 : move16();
1019 : }
1020 1268357 : ELSE IF( EQ_16( transpX, 1 ) && EQ_16( transpY, 1 ) ) /* We use both transpose */
1021 : {
1022 132787 : IF( NE_16( rowsX, colsY ) )
1023 : {
1024 0 : return EXIT_FAILURE;
1025 : }
1026 812472 : FOR( j = 0; j < rowsY; ++j )
1027 : {
1028 2052025 : FOR( i = 0; i < colsX; ++i )
1029 : {
1030 1372340 : temp = 0;
1031 1372340 : move64();
1032 4155930 : FOR( k = 0; k < colsX; ++k )
1033 : {
1034 2783590 : temp = W_mac_32_32( temp, X_fx[k + i * rowsX], Y_fx[j + k * rowsY] ); // X_fx_e + Y_fx_e
1035 : }
1036 : /* Maximize accumulated value to 32-bit */
1037 1372340 : temp_e = W_norm( temp );
1038 1372340 : temp = W_shl( temp, temp_e );
1039 1372340 : if ( 0 == temp )
1040 : {
1041 0 : temp_e = prod_e;
1042 0 : move16();
1043 : }
1044 1372340 : *Zp_fx_e = sub( prod_e, temp_e );
1045 1372340 : move16();
1046 1372340 : ( *Zp_fx ) = W_extract_h( temp );
1047 1372340 : move32();
1048 1372340 : max_exp = s_max( max_exp, *Zp_fx_e ); // Find the max exp
1049 1372340 : Zp_fx++;
1050 1372340 : Zp_fx_e++;
1051 : }
1052 : }
1053 132787 : row = rowsY; /*Q0*/
1054 132787 : move16();
1055 132787 : col = colsX; /*Q0*/
1056 132787 : move16();
1057 : }
1058 : ELSE /* Regular case */
1059 : {
1060 1135570 : IF( NE_16( colsX, rowsY ) )
1061 : {
1062 0 : return EXIT_FAILURE;
1063 : }
1064 :
1065 4164318 : FOR( j = 0; j < colsY; ++j )
1066 : {
1067 17023303 : FOR( i = 0; i < rowsX; ++i )
1068 : {
1069 13994555 : temp = 0;
1070 13994555 : move64();
1071 69572380 : FOR( k = 0; k < colsX; ++k )
1072 : {
1073 55577825 : temp = W_mac_32_32( temp, X_fx[i + k * rowsX], Y_fx[k + j * rowsY] ); // X_fx_e + Y_fx_e
1074 : }
1075 : /* Maximize accumulated value to 32-bit */
1076 13994555 : temp_e = W_norm( temp );
1077 13994555 : temp = W_shl( temp, temp_e );
1078 13994555 : if ( 0 == temp )
1079 : {
1080 2399484 : temp_e = prod_e;
1081 : }
1082 13994555 : *Zp_fx_e = sub( prod_e, temp_e );
1083 13994555 : move16();
1084 13994555 : ( *Zp_fx ) = W_extract_h( temp );
1085 13994555 : move32();
1086 13994555 : max_exp = s_max( max_exp, *Zp_fx_e ); // Find the max exp
1087 13994555 : Zp_fx++;
1088 13994555 : Zp_fx_e++;
1089 : }
1090 : }
1091 1135570 : row = colsY; /*Q0*/
1092 1135570 : move16();
1093 1135570 : col = rowsX; /*Q0*/
1094 1135570 : move16();
1095 : }
1096 2138353 : Zp_fx = Z_fx; /*Q31 - Zp_fx_e*/
1097 :
1098 2138353 : Zp_fx_e = out_e;
1099 2138353 : move16();
1100 :
1101 :
1102 2138353 : *Z_fx_e = max_exp;
1103 2138353 : move16();
1104 10170275 : FOR( j = 0; j < row; ++j )
1105 : {
1106 57126732 : FOR( i = 0; i < col; ++i )
1107 : {
1108 49094810 : *Zp_fx = L_shr_r( *Zp_fx, sub( *Z_fx_e, *Zp_fx_e ) ); /*Q31 - Zp_fx_e*/
1109 49094810 : move32();
1110 49094810 : Zp_fx++;
1111 49094810 : Zp_fx_e++;
1112 : }
1113 : }
1114 :
1115 2138353 : return EXIT_SUCCESS;
1116 : }
1117 :
1118 399444 : Word16 matrix_product_fx(
1119 : const Word32 *X_fx, /* i : left hand matrix Qx*/
1120 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
1121 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
1122 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
1123 : const Word32 *Y_fx, /* i : right hand matrix Qy*/
1124 : const Word16 rowsY, /* i : number of rows of the right hand matrix Q0*/
1125 : const Word16 colsY, /* i : number of columns of the right hand matrix Q0*/
1126 : const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/
1127 : Word32 *Z_fx /* o : resulting matrix after the matrix multiplication Qx + Qy - 31*/
1128 : )
1129 : {
1130 : Word16 i, j, k;
1131 399444 : Word32 *Zp_fx = Z_fx;
1132 :
1133 : /* Processing */
1134 399444 : test();
1135 399444 : test();
1136 399444 : test();
1137 399444 : IF( EQ_16( transpX, 1 ) && transpY == 0 ) /* We use X transpose */
1138 : {
1139 1080 : IF( NE_16( rowsX, rowsY ) )
1140 : {
1141 0 : return EXIT_FAILURE;
1142 : }
1143 5400 : FOR( j = 0; j < colsY; ++j )
1144 : {
1145 25920 : FOR( i = 0; i < colsX; ++i )
1146 : {
1147 21600 : ( *Zp_fx ) = 0;
1148 21600 : move32();
1149 129600 : FOR( k = 0; k < rowsX; ++k )
1150 : {
1151 108000 : ( *Zp_fx ) = Madd_32_32( *Zp_fx, X_fx[k + i * rowsX], Y_fx[k + j * rowsY] ); /*Qx + Qy - 31*/
1152 108000 : move32();
1153 : }
1154 21600 : Zp_fx++;
1155 : }
1156 : }
1157 : }
1158 398364 : ELSE IF( transpX == 0 && EQ_16( transpY, 1 ) ) /* We use Y transpose */
1159 : {
1160 132787 : IF( NE_16( colsX, colsY ) )
1161 : {
1162 0 : return EXIT_FAILURE;
1163 : }
1164 948409 : FOR( j = 0; j < rowsY; ++j )
1165 : {
1166 5880714 : FOR( i = 0; i < rowsX; ++i )
1167 : {
1168 5065092 : ( *Zp_fx ) = 0;
1169 5065092 : move32();
1170 15349516 : FOR( k = 0; k < colsX; ++k )
1171 : {
1172 10284424 : ( *Zp_fx ) = Madd_32_32( *Zp_fx, X_fx[i + k * rowsX], Y_fx[j + k * rowsY] ); /*Qx + Qy - 31*/
1173 10284424 : move32();
1174 : }
1175 5065092 : Zp_fx++;
1176 : }
1177 : }
1178 : }
1179 265577 : ELSE IF( EQ_16( transpX, 1 ) && EQ_16( transpY, 1 ) ) /* We use both transpose */
1180 : {
1181 0 : IF( NE_16( rowsX, colsY ) )
1182 : {
1183 0 : return EXIT_FAILURE;
1184 : }
1185 0 : FOR( j = 0; j < rowsY; ++j )
1186 : {
1187 0 : FOR( i = 0; i < colsX; ++i )
1188 : {
1189 0 : ( *Zp_fx ) = 0;
1190 0 : move32();
1191 0 : FOR( k = 0; k < colsX; ++k )
1192 : {
1193 0 : ( *Zp_fx ) = Madd_32_32( *Zp_fx, X_fx[k + i * rowsX], Y_fx[j + k * rowsY] ); /*Qx + Qy - 31*/
1194 0 : move32();
1195 : }
1196 :
1197 0 : Zp_fx++;
1198 : }
1199 : }
1200 : }
1201 : ELSE /* Regular case */
1202 : {
1203 265577 : IF( NE_16( colsX, rowsY ) )
1204 : {
1205 0 : return EXIT_FAILURE;
1206 : }
1207 :
1208 799453 : FOR( j = 0; j < colsY; ++j )
1209 : {
1210 3551724 : FOR( i = 0; i < rowsX; ++i )
1211 : {
1212 3017848 : ( *Zp_fx ) = 0;
1213 3017848 : move32();
1214 9135366 : FOR( k = 0; k < colsX; ++k )
1215 : {
1216 6117518 : ( *Zp_fx ) = L_add_sat( *Zp_fx, Mpy_32_32( X_fx[i + k * rowsX], Y_fx[k + j * rowsY] ) ); /*Qx + Qy - 31*/
1217 : // TODO: overflow of Z_fx to be checked
1218 6117518 : move32();
1219 : }
1220 3017848 : Zp_fx++;
1221 : }
1222 : }
1223 : }
1224 :
1225 399444 : return EXIT_SUCCESS;
1226 : }
1227 :
1228 1637 : Word16 matrix_product_q30_fx(
1229 : const Word32 *X_fx, /* i : left hand matrix Q31*/
1230 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
1231 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
1232 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
1233 : const Word32 *Y_fx, /* i : right hand matrix Q25*/
1234 : const Word16 rowsY, /* i : number of rows of the right hand matrix Q0*/
1235 : const Word16 colsY, /* i : number of columns of the right hand matrix Q0*/
1236 : const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/
1237 : Word32 *Z_fx /* o : resulting matrix after the matrix multiplication Q30*/
1238 : )
1239 : {
1240 : Word16 i, j, k;
1241 1637 : Word32 *Zp_fx = Z_fx;
1242 : Word64 W_tmp;
1243 :
1244 : /* Processing */
1245 1637 : test();
1246 1637 : test();
1247 1637 : test();
1248 1637 : IF( EQ_16( transpX, 1 ) && transpY == 0 ) /* We use X transpose */
1249 : {
1250 557 : IF( NE_16( rowsX, rowsY ) )
1251 : {
1252 0 : return EXIT_FAILURE;
1253 : }
1254 1114 : FOR( j = 0; j < colsY; ++j )
1255 : {
1256 5863 : FOR( i = 0; i < colsX; ++i )
1257 : {
1258 : //( *Zp_fx ) = 0;
1259 5306 : W_tmp = 0;
1260 5306 : move64();
1261 62248 : FOR( k = 0; k < rowsX; ++k )
1262 : {
1263 56942 : W_tmp = W_add( W_tmp, W_mult0_32_32( X_fx[k + i * rowsX], Y_fx[k + j * rowsY] ) ); // Q56
1264 : }
1265 5306 : W_tmp = W_shl( W_tmp, 6 ); /*Q62*/
1266 5306 : ( *Zp_fx ) = W_round64_L( W_tmp ); /*Q30*/
1267 5306 : move32();
1268 5306 : Zp_fx++;
1269 : }
1270 : }
1271 : }
1272 1080 : ELSE IF( transpX == 0 && EQ_16( transpY, 1 ) ) /* We use Y transpose */
1273 : {
1274 0 : IF( NE_16( colsX, colsY ) )
1275 : {
1276 0 : return EXIT_FAILURE;
1277 : }
1278 0 : FOR( j = 0; j < rowsY; ++j )
1279 : {
1280 0 : FOR( i = 0; i < rowsX; ++i )
1281 : {
1282 : //( *Zp_fx ) = 0;
1283 0 : W_tmp = 0;
1284 0 : move64();
1285 0 : FOR( k = 0; k < colsX; ++k )
1286 : {
1287 0 : W_tmp = W_add( W_tmp, W_mult0_32_32( X_fx[i + k * rowsX], Y_fx[j + k * rowsY] ) ); // Q56
1288 : }
1289 0 : W_tmp = W_shl( W_tmp, 6 ); /*Q62*/
1290 0 : ( *Zp_fx ) = W_round64_L( W_tmp ); /*Q30*/
1291 0 : move32();
1292 0 : Zp_fx++;
1293 : }
1294 : }
1295 : }
1296 1080 : ELSE IF( EQ_16( transpX, 1 ) && EQ_16( transpY, 1 ) ) /* We use both transpose */
1297 : {
1298 0 : IF( NE_16( rowsX, colsY ) )
1299 : {
1300 0 : return EXIT_FAILURE;
1301 : }
1302 0 : FOR( j = 0; j < rowsY; ++j )
1303 : {
1304 0 : FOR( i = 0; i < colsX; ++i )
1305 : {
1306 : //( *Zp_fx ) = 0;
1307 0 : W_tmp = 0;
1308 0 : move64();
1309 0 : FOR( k = 0; k < colsX; ++k )
1310 : {
1311 0 : W_tmp = W_add( W_tmp, W_mult0_32_32( X_fx[k + i * rowsX], Y_fx[j + k * rowsY] ) ); // Q56
1312 : }
1313 :
1314 0 : W_tmp = W_shl( W_tmp, 6 ); /*Q62*/
1315 0 : ( *Zp_fx ) = W_round64_L( W_tmp ); /*Q30*/
1316 0 : move32();
1317 0 : Zp_fx++;
1318 : }
1319 : }
1320 : }
1321 : ELSE /* Regular case */
1322 : {
1323 1080 : IF( NE_16( colsX, rowsY ) )
1324 : {
1325 0 : return EXIT_FAILURE;
1326 : }
1327 :
1328 5400 : FOR( j = 0; j < colsY; ++j )
1329 : {
1330 25920 : FOR( i = 0; i < rowsX; ++i )
1331 : {
1332 : //( *Zp_fx ) = 0;
1333 21600 : W_tmp = 0;
1334 21600 : move64();
1335 108000 : FOR( k = 0; k < colsX; ++k )
1336 : {
1337 86400 : W_tmp = W_add( W_tmp, W_mult0_32_32( X_fx[i + k * rowsX], Y_fx[k + j * rowsY] ) ); // Q56
1338 : }
1339 21600 : W_tmp = W_shl( W_tmp, 6 ); /*Q62*/
1340 21600 : ( *Zp_fx ) = W_round64_L( W_tmp ); /*Q30*/
1341 21600 : move32();
1342 21600 : Zp_fx++;
1343 : }
1344 : }
1345 : }
1346 :
1347 1637 : return EXIT_SUCCESS;
1348 : }
1349 : /*takes input matrices in mantissa and exponent forms*/
1350 402561 : Word16 matrix_product_mant_exp(
1351 : const Word32 *X_fx, /* i : left hand matrix Q31 - X_e*/
1352 : const Word16 *X_e, /* i : left hand matrix */
1353 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
1354 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
1355 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
1356 : const Word32 *Y_fx, /* i : right hand matrix Q31 - Y_e*/
1357 : const Word16 *Y_e, /* i : right hand matrix */
1358 : const Word16 rowsY, /* i : number of rows of the right hand matrix Q0*/
1359 : const Word16 colsY, /* i : number of columns of the right hand matrix Q0*/
1360 : const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/
1361 : Word32 *Z_fx, /* o : resulting matrix after the matrix multiplication Q31 - Z_e*/
1362 : Word16 *Z_e /* o : resulting matrix after the matrix multiplication */
1363 : )
1364 : {
1365 : Word16 i, j, k;
1366 402561 : Word32 *Zp = Z_fx;
1367 402561 : Word16 *Zp_e = Z_e;
1368 : Word32 L_tmp;
1369 : Word16 tmp_e;
1370 :
1371 : /* Processing */
1372 402561 : test();
1373 402561 : test();
1374 402561 : test();
1375 402561 : IF( EQ_16( transpX, 1 ) && transpY == 0 ) /* We use X transpose */
1376 : {
1377 0 : IF( NE_16( rowsX, rowsY ) )
1378 : {
1379 0 : return EXIT_FAILURE;
1380 : }
1381 0 : FOR( j = 0; j < colsY; ++j )
1382 : {
1383 0 : FOR( i = 0; i < colsX; ++i )
1384 : {
1385 0 : ( *Zp ) = 0;
1386 0 : move32();
1387 0 : ( *Zp_e ) = 0;
1388 0 : move16();
1389 0 : FOR( k = 0; k < rowsX; ++k )
1390 : {
1391 0 : L_tmp = Mpy_32_32( X_fx[k + i * rowsX], Y_fx[k + j * rowsY] ); /*Q31 - (X_e + Y_e)*/
1392 0 : tmp_e = add( X_e[k + i * rowsX], Y_e[k + j * rowsY] );
1393 :
1394 0 : ( *Zp ) = BASOP_Util_Add_Mant32Exp( *Zp, *Zp_e, L_tmp, tmp_e, &tmp_e );
1395 0 : move32();
1396 0 : ( *Zp_e ) = tmp_e;
1397 0 : move16();
1398 : }
1399 0 : Zp++;
1400 0 : Zp_e++;
1401 : }
1402 : }
1403 : }
1404 402561 : ELSE IF( transpX == 0 && EQ_16( transpY, 1 ) ) /* We use Y transpose */
1405 : {
1406 134887 : IF( NE_16( colsX, colsY ) )
1407 : {
1408 0 : return EXIT_FAILURE;
1409 : }
1410 827172 : FOR( j = 0; j < rowsY; ++j )
1411 : {
1412 4297870 : FOR( i = 0; i < rowsX; ++i )
1413 : {
1414 3605585 : ( *Zp ) = 0;
1415 3605585 : move32();
1416 3605585 : ( *Zp_e ) = 0;
1417 3605585 : move16();
1418 11399305 : FOR( k = 0; k < colsX; ++k )
1419 : {
1420 7793720 : L_tmp = Mpy_32_32( X_fx[i + k * rowsX], Y_fx[j + k * rowsY] ); /*Q31 - (X_e + Y_e)*/
1421 7793720 : tmp_e = add( X_e[i + k * rowsX], Y_e[j + k * rowsY] );
1422 :
1423 7793720 : ( *Zp ) = BASOP_Util_Add_Mant32Exp( *Zp, *Zp_e, L_tmp, tmp_e, &tmp_e );
1424 7793720 : ( *Zp_e ) = tmp_e;
1425 7793720 : move16();
1426 : }
1427 3605585 : Zp++;
1428 3605585 : Zp_e++;
1429 : }
1430 : }
1431 : }
1432 267674 : ELSE IF( EQ_16( transpX, 1 ) && EQ_16( transpY, 1 ) ) /* We use both transpose */
1433 : {
1434 0 : IF( NE_16( rowsX, colsY ) )
1435 : {
1436 0 : return EXIT_FAILURE;
1437 : }
1438 0 : FOR( j = 0; j < rowsY; ++j )
1439 : {
1440 0 : FOR( i = 0; i < colsX; ++i )
1441 : {
1442 0 : ( *Zp ) = 0;
1443 0 : move32();
1444 0 : ( *Zp_e ) = 0;
1445 0 : move16();
1446 0 : FOR( k = 0; k < colsX; ++k )
1447 : {
1448 0 : L_tmp = Mpy_32_32( X_fx[k + i * rowsX], Y_fx[j + k * rowsY] ); /*Q31 - (X_e + Y_e)*/
1449 0 : tmp_e = add( X_e[k + i * rowsX], Y_e[j + k * rowsY] );
1450 :
1451 0 : ( *Zp ) = BASOP_Util_Add_Mant32Exp( *Zp, *Zp_e, L_tmp, tmp_e, &tmp_e );
1452 0 : move32();
1453 0 : ( *Zp_e ) = tmp_e;
1454 0 : move16();
1455 : }
1456 :
1457 0 : Zp++;
1458 0 : Zp_e++;
1459 : }
1460 : }
1461 : }
1462 : ELSE /* Regular case */
1463 : {
1464 267674 : IF( NE_16( colsX, rowsY ) )
1465 : {
1466 0 : return EXIT_FAILURE;
1467 : }
1468 :
1469 818342 : FOR( j = 0; j < colsY; ++j )
1470 : {
1471 3396148 : FOR( i = 0; i < rowsX; ++i )
1472 : {
1473 2845480 : ( *Zp ) = 0;
1474 2845480 : move32();
1475 2845480 : ( *Zp_e ) = 0;
1476 2845480 : move16();
1477 9219060 : FOR( k = 0; k < colsX; ++k )
1478 : {
1479 6373580 : L_tmp = Mpy_32_32( X_fx[i + k * rowsX], Y_fx[k + j * rowsY] ); /*Q31 - (X_e + Y_e)*/
1480 6373580 : tmp_e = add( X_e[i + k * rowsX], Y_e[k + j * rowsY] );
1481 :
1482 6373580 : ( *Zp ) = BASOP_Util_Add_Mant32Exp( *Zp, *Zp_e, L_tmp, tmp_e, &tmp_e );
1483 6373580 : move32();
1484 6373580 : ( *Zp_e ) = tmp_e;
1485 6373580 : move16();
1486 : }
1487 2845480 : Zp++;
1488 2845480 : Zp_e++;
1489 : }
1490 : }
1491 : }
1492 :
1493 402561 : return EXIT_SUCCESS;
1494 : }
1495 :
1496 :
1497 1575900 : Word16 matrix_diag_product_fx(
1498 : const Word32 *X, /* i : left hand matrix Q31 - X_e*/
1499 : Word16 X_e,
1500 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
1501 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
1502 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
1503 : const Word32 *Y, /* i : right hand diagonal matrix as vector containing the diagonal elements Q31 - Y_e*/
1504 : Word16 Y_e,
1505 : const Word16 entriesY, /* i : number of entries in the diagonal Q0*/
1506 : Word32 *Z, /* o : resulting matrix after the matrix multiplication Q31 - Z_e*/
1507 : Word16 *Z_e )
1508 : {
1509 : Word16 i, j;
1510 1575900 : Word32 *Zp = Z;
1511 :
1512 : /* Processing */
1513 1575900 : IF( EQ_16( transpX, 1 ) ) /* We use X transpose */
1514 : {
1515 0 : IF( NE_16( rowsX, entriesY ) )
1516 : {
1517 0 : return EXIT_FAILURE;
1518 : }
1519 0 : FOR( j = 0; j < entriesY; ++j )
1520 : {
1521 0 : FOR( i = 0; i < colsX; ++i )
1522 : {
1523 0 : *( Zp ) = Mpy_32_32( X[j + i * rowsX], Y[j] ); /*Q31 - (X_e + Y_e)*/
1524 0 : move32();
1525 0 : Zp++;
1526 : }
1527 : }
1528 : }
1529 : ELSE /* Regular case */
1530 : {
1531 1575900 : IF( NE_16( colsX, entriesY ) )
1532 : {
1533 0 : return EXIT_FAILURE;
1534 : }
1535 :
1536 6983460 : FOR( j = 0; j < entriesY; ++j )
1537 : {
1538 34250760 : FOR( i = 0; i < rowsX; ++i )
1539 : {
1540 28843200 : *( Zp ) = Mpy_32_32( *( X ), Y[j] ); /*Q31 - (X_e + Y_e)*/
1541 28843200 : move32();
1542 28843200 : Zp++;
1543 28843200 : X++;
1544 : }
1545 : }
1546 : }
1547 :
1548 1575900 : *Z_e = add( X_e, Y_e );
1549 1575900 : move16();
1550 :
1551 1575900 : return EXIT_SUCCESS;
1552 : }
1553 :
1554 132787 : Word16 matrix_diag_product_fx_2(
1555 : const Word32 *X, /* i : left hand matrix Q31 - X_e*/
1556 : const Word16 X_e,
1557 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
1558 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
1559 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
1560 : const Word32 *Y, /* i : right hand diagonal matrix as vector containing the diagonal elements Q31 - Y_e*/
1561 : const Word16 *Y_e,
1562 : const Word16 entriesY, /* i : number of entries in the diagonal Q0*/
1563 : Word32 *Z, /* o : resulting matrix after the matrix multiplication Q31 - Z_e*/
1564 : Word16 *Z_e )
1565 : {
1566 : Word16 i, j;
1567 132787 : Word32 *Zp = Z;
1568 132787 : Word16 *Z_ep = Z_e;
1569 : Word16 tmp;
1570 132787 : Word16 max_exp = -31;
1571 132787 : move16();
1572 :
1573 : /* Processing */
1574 132787 : IF( EQ_16( transpX, 1 ) ) /* We use X transpose */
1575 : {
1576 0 : IF( NE_16( rowsX, entriesY ) )
1577 : {
1578 0 : return EXIT_FAILURE;
1579 : }
1580 0 : FOR( j = 0; j < entriesY; ++j )
1581 : {
1582 0 : FOR( i = 0; i < colsX; ++i )
1583 : {
1584 0 : tmp = j + i * rowsX; /*Q0*/
1585 0 : *( Zp ) = Mpy_32_32( X[tmp], Y[j] ); /*Q31 - (X_e + Y_e)*/
1586 0 : move32();
1587 0 : Zp++;
1588 0 : *( Z_ep ) = add( X_e, Y_e[j] );
1589 0 : move16();
1590 0 : max_exp = s_max( max_exp, *Z_ep ); // Find the max exp
1591 0 : Z_ep++;
1592 : }
1593 : }
1594 :
1595 0 : Zp = Z;
1596 0 : Z_ep = Z_e;
1597 0 : FOR( j = 0; j < entriesY; ++j )
1598 : {
1599 0 : FOR( i = 0; i < colsX; ++i )
1600 : {
1601 0 : *Zp = L_shr( *Zp, sub( max_exp, *Z_ep ) );
1602 0 : *Z_ep = max_exp;
1603 0 : Zp++;
1604 0 : Z_ep++;
1605 : }
1606 : }
1607 : }
1608 : ELSE /* Regular case */
1609 : {
1610 132787 : IF( NE_16( colsX, entriesY ) )
1611 : {
1612 0 : return EXIT_FAILURE;
1613 : }
1614 :
1615 812472 : FOR( j = 0; j < entriesY; ++j )
1616 : {
1617 2052025 : FOR( i = 0; i < rowsX; ++i )
1618 : {
1619 1372340 : *( Zp ) = Mpy_32_32( *( X ), Y[j] ); /*Q31 - (X_e + Y_e)*/
1620 1372340 : move32();
1621 1372340 : Zp++;
1622 1372340 : *( Z_ep ) = add( X_e, Y_e[j] );
1623 1372340 : move16();
1624 1372340 : max_exp = s_max( max_exp, *Z_ep ); // Find the max exp
1625 1372340 : Z_ep++;
1626 1372340 : X++;
1627 : }
1628 : }
1629 132787 : Zp = Z;
1630 132787 : Z_ep = Z_e;
1631 812472 : FOR( j = 0; j < entriesY; ++j )
1632 : {
1633 2052025 : FOR( i = 0; i < rowsX; ++i )
1634 : {
1635 1372340 : *Zp = L_shr( *Zp, sub( max_exp, *Z_ep ) );
1636 1372340 : *Z_ep = max_exp;
1637 1372340 : Zp++;
1638 1372340 : Z_ep++;
1639 : }
1640 : }
1641 : }
1642 :
1643 132787 : return EXIT_SUCCESS;
1644 : }
1645 :
1646 106849 : Word16 matrix_diag_product_fx_1(
1647 : const Word32 *X, /* i : left hand matrix Q31 - X_e*/
1648 : const Word16 *X_e,
1649 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
1650 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
1651 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
1652 : const Word32 *Y, /* i : right hand diagonal matrix as vector containing the diagonal elements Q31 - Y_e*/
1653 : const Word16 *Y_e,
1654 : const Word16 entriesY, /* i : number of entries in the diagonal Q0*/
1655 : Word32 *Z, /* o : resulting matrix after the matrix multiplication Q31 - Z_e*/
1656 : Word16 *Z_e )
1657 : {
1658 : Word16 i, j;
1659 106849 : Word32 *Zp = Z;
1660 106849 : Word16 *Z_ep = Z_e;
1661 :
1662 : /* Processing */
1663 106849 : IF( EQ_16( transpX, 1 ) ) /* We use X transpose */
1664 : {
1665 0 : IF( NE_16( rowsX, entriesY ) )
1666 : {
1667 0 : return EXIT_FAILURE;
1668 : }
1669 0 : FOR( j = 0; j < entriesY; ++j )
1670 : {
1671 0 : FOR( i = 0; i < colsX; ++i )
1672 : {
1673 0 : *( Zp ) = Mpy_32_32( X[j + i * rowsX], Y[j] ); /*Q31 - (X_e + Y_e)*/
1674 0 : move32();
1675 0 : Zp++;
1676 0 : *( Z_ep ) = add( X_e[j + i * rowsX], Y_e[j] );
1677 0 : move16();
1678 0 : Z_ep++;
1679 : }
1680 : }
1681 : }
1682 : ELSE /* Regular case */
1683 : {
1684 106849 : IF( NE_16( colsX, entriesY ) )
1685 : {
1686 0 : return EXIT_FAILURE;
1687 : }
1688 :
1689 654124 : FOR( j = 0; j < entriesY; ++j )
1690 : {
1691 3391850 : FOR( i = 0; i < rowsX; ++i )
1692 : {
1693 2844575 : *( Zp ) = Mpy_32_32( *( X ), Y[j] ); /*Q31 - (X_e + Y_e)*/
1694 2844575 : move32();
1695 2844575 : Zp++;
1696 2844575 : *( Z_ep ) = add( *( X_e ), Y_e[j] );
1697 2844575 : move16();
1698 2844575 : Z_ep++;
1699 2844575 : X++;
1700 2844575 : X_e++;
1701 : }
1702 : }
1703 : }
1704 :
1705 106849 : return EXIT_SUCCESS;
1706 : }
1707 :
1708 763147 : Word16 diag_matrix_product_fx(
1709 : const Word32 *Y, /* i : left hand diagonal matrix as vector containing the diagonal elements Q31 - Y_e*/
1710 : Word16 Y_e,
1711 : const Word16 entriesY, /* i : length of the diagonal of the left hand matrix Q0*/
1712 : const Word32 *X, /* i : right hand matrix Q31 - X_e*/
1713 : Word16 X_e,
1714 : const Word16 rowsX, /* i : number of rows of the right hand matrix Q0*/
1715 : const Word16 colsX, /* i : number of columns of the right hand matrix Q0*/
1716 : const Word16 transpX, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/
1717 : Word32 *Z, /* o : resulting matrix after the matrix multiplication Q31 - Z_e*/
1718 : Word16 *Z_e )
1719 : {
1720 : Word16 i, j;
1721 763147 : Word32 *Zp = Z;
1722 :
1723 : /* Processing */
1724 763147 : IF( EQ_16( transpX, 1 ) ) /* We use X transpose */
1725 : {
1726 315180 : IF( NE_16( colsX, entriesY ) )
1727 : {
1728 0 : return EXIT_FAILURE;
1729 : }
1730 3194100 : FOR( i = 0; i < rowsX; ++i )
1731 : {
1732 8636760 : FOR( j = 0; j < entriesY; ++j )
1733 : {
1734 5757840 : *( Zp ) = Mpy_32_32( X[i + j * rowsX], Y[j] ); /*Q31 - (X_e + Y_e)*/
1735 5757840 : move32();
1736 5757840 : Zp++;
1737 : }
1738 : }
1739 : }
1740 : ELSE /* Regular case */
1741 : {
1742 447967 : IF( NE_16( rowsX, entriesY ) )
1743 : {
1744 0 : return EXIT_FAILURE;
1745 : }
1746 1677758 : FOR( i = 0; i < colsX; ++i )
1747 : {
1748 10099706 : FOR( j = 0; j < entriesY; ++j )
1749 : {
1750 8869915 : *( Zp ) = Mpy_32_32( *( X ), Y[j] ); /*Q31 - (X_e + Y_e)*/
1751 8869915 : move32();
1752 8869915 : Zp++;
1753 8869915 : X++;
1754 : }
1755 : }
1756 : }
1757 :
1758 763147 : *Z_e = add( Y_e, X_e );
1759 763147 : move16();
1760 :
1761 763147 : return EXIT_SUCCESS;
1762 : }
1763 :
1764 804489 : Word16 matrix_product_diag_fx(
1765 : const Word32 *X, /* i : left hand matrix Q31 - X_e*/
1766 : Word16 X_e,
1767 : const Word16 rowsX, /* i : number of rows of the left hand matrix Q0*/
1768 : const Word16 colsX, /* i : number of columns of the left hand matrix Q0*/
1769 : const Word16 transpX, /* i : flag indicating the transposition of the left hand matrix prior to the multiplication Q0*/
1770 : const Word32 *Y, /* i : right hand matrix Q31 - Y_e*/
1771 : Word16 Y_e,
1772 : const Word16 rowsY, /* i : number of rows of the right hand matrix Q0*/
1773 : const Word16 colsY, /* i : number of columns of the right hand matrix Q0*/
1774 : const Word16 transpY, /* i : flag indicating the transposition of the right hand matrix prior to the multiplication Q0*/
1775 : Word32 *Z, /* o : resulting matrix after the matrix multiplication Q31 - Z_e*/
1776 : Word16 *Z_e )
1777 : {
1778 : Word16 j, k;
1779 804489 : Word32 *Zp = Z;
1780 :
1781 : /* Processing */
1782 804489 : test();
1783 804489 : test();
1784 804489 : test();
1785 804489 : IF( EQ_16( transpX, 1 ) && transpY == 0 ) /* We use X transpose */
1786 : {
1787 0 : IF( NE_16( rowsX, rowsY ) )
1788 : {
1789 0 : return EXIT_FAILURE;
1790 : }
1791 :
1792 0 : FOR( j = 0; j < colsY; ++j )
1793 : {
1794 0 : ( *Zp ) = 0;
1795 0 : move32();
1796 0 : FOR( k = 0; k < rowsX; ++k )
1797 : {
1798 0 : ( *Zp ) = Madd_32_32( ( *Zp ), X[k + j * rowsX], Y[k + j * rowsY] ); /*Q31 - (X_e + Y_e)*/
1799 0 : move32();
1800 : }
1801 0 : Zp++;
1802 : }
1803 : }
1804 804489 : ELSE IF( transpX == 0 && EQ_16( transpY, 1 ) ) /* We use Y transpose */
1805 : {
1806 687603 : IF( NE_16( colsX, colsY ) )
1807 : {
1808 0 : return EXIT_FAILURE;
1809 : }
1810 5473168 : FOR( j = 0; j < rowsY; ++j )
1811 : {
1812 4785565 : ( *Zp ) = 0;
1813 4785565 : move32();
1814 16132660 : FOR( k = 0; k < colsX; ++k )
1815 : {
1816 11347095 : ( *Zp ) = Madd_32_32( ( *Zp ), X[j + k * rowsX], Y[j + k * rowsY] ); /*Q31 - (X_e + Y_e)*/
1817 11347095 : move32();
1818 : }
1819 4785565 : Zp++;
1820 : }
1821 : }
1822 116886 : ELSE IF( EQ_16( transpX, 1 ) && EQ_16( transpY, 1 ) ) /* We use both transpose */
1823 : {
1824 0 : IF( NE_16( rowsX, colsY ) )
1825 : {
1826 0 : return EXIT_FAILURE;
1827 : }
1828 :
1829 0 : FOR( j = 0; j < rowsY; ++j )
1830 : {
1831 :
1832 0 : ( *Zp ) = 0;
1833 0 : move32();
1834 0 : FOR( k = 0; k < colsX; ++k )
1835 : {
1836 0 : ( *Zp ) = Madd_32_32( ( *Zp ), X[k + j * rowsX], Y[j + k * rowsY] ); /*Q31 - (X_e + Y_e)*/
1837 0 : move32();
1838 : }
1839 :
1840 0 : Zp++;
1841 : }
1842 : }
1843 : ELSE /* Regular case */
1844 : {
1845 116886 : IF( NE_16( colsX, rowsY ) )
1846 : {
1847 0 : return EXIT_FAILURE;
1848 : }
1849 :
1850 1182390 : FOR( j = 0; j < colsY; ++j )
1851 : {
1852 1065504 : ( *Zp ) = 0;
1853 1065504 : move32();
1854 2131008 : FOR( k = 0; k < colsX; ++k )
1855 : {
1856 1065504 : ( *Zp ) = Madd_32_32( ( *Zp ), X[j + k * rowsX], Y[k + j * rowsY] ); /*Q31 - (X_e + Y_e)*/
1857 1065504 : move32();
1858 : }
1859 1065504 : Zp++;
1860 : }
1861 : }
1862 :
1863 804489 : *Z_e = add( X_e, Y_e );
1864 804489 : move16();
1865 :
1866 804489 : return EXIT_SUCCESS;
1867 : }
1868 :
1869 : /*---------------------------------------------------------------------*
1870 : * matrix_product_diag()
1871 : *
1872 : * compute only the main diagonal of X*Y (Z=diag(X*Y))
1873 : *---------------------------------------------------------------------*/
1874 :
1875 2084371 : void cmplx_matrix_square_fx(
1876 : const Word32 *realX, /* i : real part of the matrix Q31 - input_exp*/
1877 : const Word32 *imagX, /* i : imaginary part of the matrix Q31 - input_exp*/
1878 : const Word16 mRows, /* i : number of rows of the matrix Q0*/
1879 : const Word16 nCols, /* i : number of columns of the matrix Q0*/
1880 : Word32 *realZ, /* o : real part of the resulting matrix Q31 - output_exp*/
1881 : Word32 *imagZ, /* o : imaginary part of the resulting matrix Q31 - output_exp*/
1882 : Word16 input_exp,
1883 : Word16 *output_exp )
1884 : {
1885 : Word16 i, j, k;
1886 : Word32 *realZp, *imagZp;
1887 : const Word32 *p_real1, *p_real2, *p_imag1, *p_imag2;
1888 : Word16 tmp1, tmp2;
1889 :
1890 : /* resulting matrix is hermitean, we only need to calc the upper triangle */
1891 : /* we assume transposition needed */
1892 :
1893 : /* column*column = column/column */
1894 6272881 : FOR( i = 0; i < nCols; i++ )
1895 : {
1896 10500927 : FOR( j = i; j < nCols; j++ )
1897 : {
1898 6312417 : p_real1 = realX + imult1616( i, mRows ); /*Q31 - input_exp*/
1899 6312417 : p_imag1 = imagX + imult1616( i, mRows ); /*Q31 - input_exp*/
1900 6312417 : p_real2 = realX + imult1616( j, mRows ); /*Q31 - input_exp*/
1901 6312417 : p_imag2 = imagX + imult1616( j, mRows ); /*Q31 - input_exp*/
1902 6312417 : realZp = realZ + add( i, imult1616( nCols, j ) ); /*Q31 - output_exp*/
1903 6312417 : imagZp = imagZ + add( i, imult1616( nCols, j ) ); /*Q31 - output_exp*/
1904 6312417 : *( realZp ) = 0;
1905 6312417 : move32();
1906 6312417 : *( imagZp ) = 0;
1907 6312417 : move32();
1908 :
1909 33082257 : FOR( k = 0; k < mRows; k++ )
1910 : {
1911 26769840 : *( imagZp ) = L_add( *( imagZp ), L_sub( Mpy_32_32( *( p_real1 ), *( p_imag2 ) ), Mpy_32_32( *( p_real2 ), *( p_imag1 ) ) ) ); /* Q31 - 2*input_exp */
1912 26769840 : move32();
1913 26769840 : *( realZp ) = L_add( *( realZp ), L_add( Mpy_32_32( *( p_real1 ), *( p_real2 ) ), Mpy_32_32( *( p_imag1 ), *( p_imag2 ) ) ) ); /* Q31 - 2*input_exp */
1914 26769840 : move32();
1915 26769840 : p_real1++;
1916 26769840 : p_real2++;
1917 26769840 : p_imag1++;
1918 26769840 : p_imag2++;
1919 : }
1920 : }
1921 : }
1922 :
1923 : /* fill lower triangle */
1924 4188510 : FOR( i = 1; i < nCols; i++ )
1925 : {
1926 4228046 : FOR( j = 0; j < i; j++ )
1927 : {
1928 2123907 : tmp1 = add( i, imult1616( nCols, j ) ); /*Q0*/
1929 2123907 : tmp2 = add( j, imult1616( nCols, i ) ); /*Q0*/
1930 2123907 : realZ[tmp1] = realZ[tmp2]; /*Q31 - output_exp*/
1931 2123907 : move32();
1932 2123907 : imagZ[tmp1] = imagZ[tmp2]; /*Q31 - output_exp*/
1933 2123907 : move32();
1934 : }
1935 : }
1936 :
1937 2084371 : *output_exp = shl( input_exp, 1 );
1938 2084371 : move16();
1939 :
1940 2084371 : return;
1941 : }
1942 :
1943 :
1944 731303 : void v_multc_acc_32_16(
1945 : const Word32 x[], /* i : Input vector Qx*/
1946 : const Word16 c, /* i : Constant Q31*/
1947 : Word32 y[], /* o : Output vector that contains y + c*x Qx*/
1948 : const Word16 N /* i : Vector length Q0*/
1949 : )
1950 : {
1951 : Word16 i;
1952 :
1953 39214143 : FOR( i = 0; i < N; i++ )
1954 : {
1955 38482840 : y[i] = Madd_32_16( y[i], x[i], c );
1956 38482840 : move32();
1957 : }
1958 :
1959 731303 : return;
1960 : }
1961 283200 : void v_multc_acc_32_32(
1962 : const Word32 x[], /* i : Input vector Qx*/
1963 : const Word32 c, /* i : Constant Q31*/
1964 : Word32 y[], /* o : Output vector that contains y + c*x Qx*/
1965 : const Word16 N /* i : Vector length Q0*/
1966 : )
1967 : {
1968 : Word16 i;
1969 :
1970 17275200 : FOR( i = 0; i < N; i++ )
1971 : {
1972 16992000 : y[i] = Madd_32_32( y[i], x[i], c ); /*Qx*/
1973 16992000 : move32();
1974 : }
1975 :
1976 283200 : return;
1977 : }
1978 :
1979 : /*---------------------------------------------------------------------*
1980 : * lls_interp_n()
1981 : *
1982 : * Linear least squares interpolation of an input vector
1983 : * The function calculates the slope 'a' and the offset 'b' of a LLS estimate for an input vector x such that
1984 : * y_i = a*i + b where i=1,..,N and (a,b) = min(a,b) [sum_N[(y_i - x_i)^2]]
1985 : * the interpolated vector is return as x[], if requested
1986 : *---------------------------------------------------------------------*/
1987 :
1988 4067 : void lls_interp_n_fx(
1989 : Word16 x_fx[], /* i/o: input/output vector Q15*/
1990 : const Word16 N, /* i : length of the input vector Q0*/
1991 : Word16 *a_fx, /* o : calculated slope Q15*/
1992 : Word16 *b_fx, /* o : calculated offset Q15*/
1993 : const Word16 upd /* i : use 1 to update x[] with the interpolated output Q0*/
1994 : )
1995 : {
1996 : Word16 i;
1997 4067 : const Word16 n_i_fx[11] = { 0, 2048, 4096, 6144, 8192, 10240, 12288, 14336, 16384, 18432, 20480 }; // Q11
1998 4067 : move16();
1999 4067 : move16();
2000 4067 : move16();
2001 4067 : move16();
2002 4067 : move16();
2003 4067 : move16();
2004 4067 : move16();
2005 4067 : move16();
2006 4067 : move16();
2007 4067 : move16();
2008 4067 : move16();
2009 :
2010 4067 : const Word16 one_by_n_fx[11] = { 0, 32767, 16384, 10911, 8192, 6553, 5459, 4681, 4096, 3640, 3276 }; /*Q15*/
2011 4067 : move16();
2012 4067 : move16();
2013 4067 : move16();
2014 4067 : move16();
2015 4067 : move16();
2016 4067 : move16();
2017 4067 : move16();
2018 4067 : move16();
2019 4067 : move16();
2020 4067 : move16();
2021 4067 : move16();
2022 :
2023 4067 : const Word16 sum_i_fx[12] = { 0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55 }; /*Q0*/
2024 4067 : move16();
2025 4067 : move16();
2026 4067 : move16();
2027 4067 : move16();
2028 4067 : move16();
2029 4067 : move16();
2030 4067 : move16();
2031 4067 : move16();
2032 4067 : move16();
2033 4067 : move16();
2034 4067 : move16();
2035 4067 : move16();
2036 :
2037 : // 1.0f/ ( N * sum_ii[N] - sum_i[N] * sum_i[N] )
2038 4067 : const Word32 res_table[12] = { 0, 0, 0, 357913952, 107374184, 42949672, 20452226, 10956549, 6391320, 3976821, 2603010, 385 }; /*Q31*/
2039 4067 : move16();
2040 4067 : move16();
2041 4067 : move16();
2042 4067 : move16();
2043 4067 : move16();
2044 4067 : move16();
2045 4067 : move16();
2046 4067 : move16();
2047 4067 : move16();
2048 4067 : move16();
2049 4067 : move16();
2050 4067 : move16();
2051 :
2052 : Word32 sum_x_fx, sum_ix_fx, slope_fx, offset_fx;
2053 4067 : Word16 dot_exp = 0, sum_ix_q = 0;
2054 4067 : move16();
2055 4067 : move16();
2056 :
2057 : Word32 num;
2058 4067 : assert( N > 0 && LE_16( N, 10 ) );
2059 :
2060 4067 : sum_x_fx = 0;
2061 4067 : move32();
2062 : Word16 idx;
2063 20335 : FOR( idx = 0; idx < N; idx++ )
2064 : {
2065 16268 : sum_x_fx = L_add( sum_x_fx, x_fx[idx] ); /*Q15*/
2066 : }
2067 4067 : sum_ix_fx = dotp_fx( x_fx, n_i_fx, N, &dot_exp ); /*sum_ix_q*/
2068 4067 : sum_ix_q = sub( 30, sub( dot_exp, ( 11 + 15 ) ) );
2069 :
2070 4067 : sum_ix_fx = L_shr( sum_ix_fx, sub( sum_ix_q, 15 ) ); /*Q15*/
2071 4067 : num = L_sub( imult3216( sum_ix_fx, N ), imult3216( sum_x_fx, sum_i_fx[N] ) ); /*Q15*/
2072 4067 : slope_fx = Mpy_32_32( num, res_table[N] ); /*Q15*/
2073 4067 : offset_fx = Mpy_32_16_1( L_sub( sum_x_fx, imult3216( slope_fx, sum_i_fx[N] ) ), one_by_n_fx[N] ); /*Q15*/
2074 :
2075 4067 : IF( upd )
2076 : {
2077 20335 : FOR( i = 0; i < N; i++ )
2078 : {
2079 16268 : IF( GT_32( imult3216( slope_fx, i ), MAX_WORD16 ) )
2080 : {
2081 0 : x_fx[i] = MAX_WORD16; /*Q15*/
2082 0 : move16();
2083 : }
2084 : ELSE
2085 : {
2086 16268 : x_fx[i] = extract_l( L_add_sat( imult3216( slope_fx, i ), offset_fx ) ); /*Q15*/
2087 16268 : move16();
2088 : }
2089 : }
2090 : }
2091 :
2092 4067 : IF( a_fx != NULL )
2093 : {
2094 4067 : *a_fx = extract_l( slope_fx ); /*Q15*/
2095 4067 : move16();
2096 : }
2097 :
2098 4067 : IF( b_fx != NULL )
2099 : {
2100 4067 : *b_fx = extract_l( offset_fx ); /*Q15*/
2101 4067 : move16();
2102 : }
2103 :
2104 4067 : return;
2105 : }
2106 :
2107 :
2108 : /* helper function for panning_wrap_angles */
2109 1872 : static float wrap_azi(
2110 : const float azi_deg )
2111 : {
2112 1872 : float azi = azi_deg;
2113 :
2114 : /* Wrap azimuth value */
2115 1872 : while ( azi > 180 )
2116 : {
2117 0 : azi -= 360.0f;
2118 : }
2119 :
2120 1927 : while ( azi <= -180 )
2121 : {
2122 55 : azi += 360;
2123 : }
2124 :
2125 1872 : return azi;
2126 : }
2127 : /* helper function for panning_wrap_angles */
2128 5967632 : static Word32 wrap_azi_fx(
2129 : const Word32 azi_deg /* Q22 */ )
2130 : {
2131 5967632 : Word32 azi = azi_deg; /*Q22*/
2132 5967632 : move32();
2133 :
2134 : /* Wrap azimuth value */
2135 7420547 : WHILE( GT_32( azi, ANGLE_180_DEG_Q22 ) )
2136 : {
2137 1452915 : azi = L_sub( azi, ANGLE_360_DEG_Q22 ); /*Q22*/
2138 : }
2139 :
2140 6007331 : WHILE( LE_32( azi, -ANGLE_180_DEG_Q22 ) )
2141 : {
2142 39699 : azi = L_add( azi, ANGLE_360_DEG_Q22 ); /*Q22*/
2143 : }
2144 :
2145 5967632 : return azi; /*Q22*/
2146 : }
2147 : /*-------------------------------------------------------------------*
2148 : * panning_wrap_angles()
2149 : *
2150 : * Wrap angles for amplitude panning to the range:
2151 : * azimuth = (-180, 180]
2152 : * elevation = [-90, 90]
2153 : * Considers direction changes from large elevation values
2154 : *-------------------------------------------------------------------*/
2155 1872 : void panning_wrap_angles(
2156 : const float azi_deg, /* i : azimuth in degrees for panning direction (positive left) */
2157 : const float ele_deg, /* i : elevation in degrees for panning direction (positive up) */
2158 : float *azi_wrapped, /* o : wrapped azimuth component */
2159 : float *ele_wrapped /* o : wrapped elevation component */
2160 : )
2161 : {
2162 : float azi, ele;
2163 :
2164 1872 : azi = azi_deg;
2165 1872 : ele = ele_deg;
2166 :
2167 1872 : if ( fabsf( ele ) < 90 )
2168 : {
2169 1872 : *ele_wrapped = ele;
2170 1872 : *azi_wrapped = wrap_azi( azi );
2171 1872 : return;
2172 : }
2173 : else
2174 : {
2175 : /* Special case when elevation is a multiple of 90; azimuth is irrelevant */
2176 0 : if ( ( fmodf( ele, 90 ) == 0 ) && ( fmodf( ele, 180 ) != 0 ) )
2177 : {
2178 0 : *azi_wrapped = 0;
2179 0 : while ( ele > 90 )
2180 : {
2181 0 : ele -= 360;
2182 : }
2183 0 : while ( ele < -90 )
2184 : {
2185 0 : ele += 360;
2186 : }
2187 0 : *ele_wrapped = ele;
2188 : }
2189 : else
2190 : {
2191 : /* Wrap elevation and adjust azimuth accordingly */
2192 0 : while ( fabsf( ele ) > 90 )
2193 : {
2194 : /* Flip to other hemisphere */
2195 0 : azi += 180;
2196 :
2197 : /* Compensate elevation accordingly */
2198 0 : if ( ele > 90 )
2199 : {
2200 0 : ele = 180 - ele;
2201 : }
2202 0 : else if ( ele < -90 )
2203 : {
2204 0 : ele = -180 - ele;
2205 : }
2206 : }
2207 0 : *azi_wrapped = wrap_azi( azi );
2208 0 : *ele_wrapped = ele;
2209 : }
2210 :
2211 0 : return;
2212 : }
2213 : }
2214 : /*-------------------------------------------------------------------*
2215 : * panning_wrap_angles_fx()
2216 : *
2217 : * Wrap angles for amplitude panning to the range:
2218 : * azimuth = (-180, 180]
2219 : * elevation = [-90, 90]
2220 : * Considers direction changes from large elevation values
2221 : *-------------------------------------------------------------------*/
2222 5971102 : void panning_wrap_angles_fx(
2223 : const Word32 azi_deg, /* i : azimuth in degrees for panning direction (positive left) Q22 */
2224 : const Word32 ele_deg, /* i : elevation in degrees for panning direction (positive up) Q22 */
2225 : Word32 *azi_wrapped, /* o : wrapped azimuth component Q22 */
2226 : Word32 *ele_wrapped /* o : wrapped elevation component Q22 */
2227 : )
2228 : {
2229 : Word32 azi, ele;
2230 :
2231 5971102 : azi = azi_deg; /*Q22*/
2232 5971102 : move32();
2233 5971102 : ele = ele_deg; /*Q22*/
2234 5971102 : move32();
2235 :
2236 5971102 : IF( LT_32( L_abs( ele ), ANGLE_90_DEG_Q22 ) )
2237 : {
2238 5967632 : *ele_wrapped = ele; /*Q22*/
2239 5967632 : move32();
2240 5967632 : *azi_wrapped = wrap_azi_fx( azi ); /*Q22*/
2241 5967632 : move32();
2242 5967632 : return;
2243 : }
2244 : ELSE
2245 : {
2246 : /* Special case when elevation is a multiple of 90; azimuth is irrelevant */
2247 3470 : IF( ( ( ele % ANGLE_90_DEG_Q22 ) == 0 ) && ( ( ele % ANGLE_180_DEG_Q22 ) != 0 ) )
2248 : {
2249 3470 : *azi_wrapped = 0;
2250 3470 : move32();
2251 3470 : WHILE( GT_32( ele, ANGLE_90_DEG_Q22 ) )
2252 : {
2253 0 : ele = L_sub( ele, ANGLE_360_DEG_Q22 );
2254 : }
2255 3470 : WHILE( LT_32( ele, -ANGLE_90_DEG_Q22 ) )
2256 : {
2257 0 : ele = L_add( ele, ANGLE_360_DEG_Q22 );
2258 : }
2259 3470 : *ele_wrapped = ele;
2260 3470 : move32();
2261 : }
2262 : ELSE
2263 : {
2264 : /* Wrap elevation and adjust azimuth accordingly */
2265 0 : WHILE( GT_32( L_abs( ele ), ANGLE_90_DEG_Q22 ) )
2266 : {
2267 : /* Flip to other hemisphere */
2268 0 : azi = L_add( azi, ANGLE_180_DEG_Q22 );
2269 :
2270 : /* Compensate elevation accordingly */
2271 0 : IF( GT_32( ele, ANGLE_90_DEG_Q22 ) )
2272 : {
2273 0 : ele = L_sub( ANGLE_180_DEG_Q22, ele );
2274 : }
2275 0 : ELSE IF( LT_32( ele, -ANGLE_90_DEG_Q22 ) )
2276 : {
2277 0 : ele = L_sub( -ANGLE_180_DEG_Q22, ele );
2278 : }
2279 : }
2280 0 : *azi_wrapped = wrap_azi_fx( azi ); /*Q22*/
2281 0 : move32();
2282 0 : *ele_wrapped = ele; /*Q22*/
2283 0 : move32();
2284 : }
2285 :
2286 3470 : return;
2287 : }
2288 : }
2289 :
2290 : /*-------------------------------------------------------------------------*
2291 : * v_sort_ind_fixed()
2292 : *
2293 : * Sort a float array
2294 : * (modified version of v_sort() to return an index array)
2295 : *-------------------------------------------------------------------------*/
2296 :
2297 16639 : void v_sort_ind_fixed(
2298 : Word32 *x, /* i/o: Vector to be sorted Qx*/
2299 : Word16 *idx, /* o : Original index positions Q0*/
2300 : const Word16 len /* i : vector length Q0*/
2301 : )
2302 : {
2303 : Word16 i, j;
2304 : Word32 tempr;
2305 : Word16 tempi;
2306 :
2307 76505 : FOR( i = 0; i < len; i++ )
2308 : {
2309 59866 : idx[i] = i;
2310 59866 : move16();
2311 : }
2312 :
2313 59866 : FOR( i = len - 2; i >= 0; i-- )
2314 : {
2315 43227 : tempr = x[i]; /*Qx*/
2316 43227 : move32();
2317 43227 : tempi = idx[i]; /*Qx*/
2318 43227 : move16();
2319 43227 : test();
2320 100197 : FOR( j = ( i + 1 ); LT_16( j, len ) && GT_32( tempr, x[j] ); j++ )
2321 : {
2322 56970 : test();
2323 56970 : x[j - 1] = x[j]; /*Qx*/
2324 56970 : move32();
2325 56970 : idx[j - 1] = idx[j]; /*Qx*/
2326 56970 : move16();
2327 : }
2328 43227 : x[j - 1] = tempr; /*Qx*/
2329 43227 : move32();
2330 43227 : idx[j - 1] = tempi; /*Qx*/
2331 43227 : move16();
2332 : }
2333 :
2334 16639 : return;
2335 : }
2336 :
2337 : /*-------------------------------------------------------------------*
2338 : * is_IVAS_bitrate()
2339 : *
2340 : * check if the bitrate is IVAS supported active bitrate
2341 : *-------------------------------------------------------------------*/
2342 :
2343 : /*! r: flag indicating a valid bitrate */
2344 0 : Word16 is_IVAS_bitrate_fx(
2345 : const Word32 ivas_total_brate /* i : IVAS total bitrate Q0*/
2346 : )
2347 : {
2348 : Word16 j;
2349 :
2350 0 : j = SIZE_IVAS_BRATE_TBL - IVAS_NUM_ACTIVE_BRATES; /* skip NO_DATA and SID bitrates */
2351 0 : move16();
2352 :
2353 0 : test();
2354 0 : WHILE( LE_16( j, SIZE_IVAS_BRATE_TBL ) && NE_32( ivas_total_brate, ivas_brate_tbl[j] ) )
2355 : {
2356 0 : test();
2357 0 : j = add( j, 1 );
2358 : }
2359 :
2360 0 : IF( GE_16( j, SIZE_IVAS_BRATE_TBL ) )
2361 : {
2362 0 : return 0;
2363 : }
2364 :
2365 0 : return 1;
2366 : }
2367 :
2368 : /*-------------------------------------------------------------------*
2369 : * is_DTXrate()
2370 : *
2371 : * identify DTX frame bitrates
2372 : *-------------------------------------------------------------------*/
2373 :
2374 4286172 : Word16 is_DTXrate(
2375 : const Word32 ivas_total_brate /* i : IVAS total bitrate Q0*/
2376 : )
2377 : {
2378 4286172 : Word16 dtx_rate_flag = 0;
2379 4286172 : move16();
2380 :
2381 4286172 : test();
2382 4286172 : IF( is_SIDrate( ivas_total_brate ) || ( EQ_32( ivas_total_brate, FRAME_NO_DATA ) ) )
2383 : {
2384 169620 : dtx_rate_flag = 1;
2385 169620 : move16();
2386 : }
2387 :
2388 4286172 : return dtx_rate_flag; /*Q0*/
2389 : }
2390 :
2391 : /*-------------------------------------------------------------------*
2392 : * is_SIDrate()
2393 : *
2394 : * identify SID frame bitrates
2395 : *-------------------------------------------------------------------*/
2396 :
2397 4698399 : Word16 is_SIDrate(
2398 : const Word32 ivas_total_brate /* i : IVAS total bitrate Q0*/
2399 : )
2400 : {
2401 4698399 : Word16 sid_rate_flag = 0;
2402 4698399 : move16();
2403 :
2404 4698399 : test();
2405 4698399 : test();
2406 9396798 : if ( EQ_32( ivas_total_brate, SID_1k75 ) ||
2407 9396798 : EQ_32( ivas_total_brate, SID_2k40 ) ||
2408 4698399 : EQ_32( ivas_total_brate, IVAS_SID_5k2 ) )
2409 : {
2410 29148 : sid_rate_flag = 1;
2411 29148 : move16();
2412 : }
2413 :
2414 4698399 : return sid_rate_flag; /*Q0*/
2415 : }
2416 :
2417 :
2418 : /*-------------------------------------------------------------------*
2419 : * rand_triangular_signed()
2420 : *
2421 : * generate a random value with a triangular pdf in [-0.5, 0.5]
2422 : *-------------------------------------------------------------------*/
2423 :
2424 25706776 : Word16 rand_triangular_signed_fx(
2425 : Word16 *seed, /*Q0*/
2426 : Word16 *exp_fac )
2427 : {
2428 : Word16 rand_val;
2429 25706776 : rand_val = Random( seed ); // q15
2430 : Word16 tmp1, tmp2;
2431 25706776 : Word16 exp1, exp = 1;
2432 25706776 : move16();
2433 25706776 : IF( rand_val <= 0 )
2434 : {
2435 : /* rand_val in [-1, 0] */
2436 : /*0.5f * (sqrtf(rand_val + 1.0f) - 1)*/
2437 12849459 : tmp1 = Sqrt16( add( shr( rand_val, 1 ), ONE_IN_Q14 ), &exp ); /*Q15 - exp*/
2438 12849459 : exp1 = BASOP_Util_Add_MantExp( tmp1, exp, negate( ONE_IN_Q14 ), 1, &tmp2 ); /*Q15 - exp1*/
2439 12849459 : tmp2 = shr( tmp2, 1 ); /*Q15 - exp1*/
2440 12849459 : *exp_fac = exp1;
2441 12849459 : move16();
2442 12849459 : return tmp2;
2443 : }
2444 : ELSE
2445 : {
2446 : /* rand_val in (0, 1) */
2447 : /*0.5f * ( 1 - sqrtf(1.0f - rand_val))*/
2448 12857317 : Word16 one_minus_rand = sub( MAX16B, rand_val ); /*Q15*/
2449 12857317 : exp = 0;
2450 12857317 : move16();
2451 12857317 : tmp1 = Sqrt16( one_minus_rand, &exp ); // q15 - exp
2452 12857317 : exp1 = BASOP_Util_Add_MantExp( ONE_IN_Q14, 1, negate( tmp1 ), exp, &tmp2 ); /*Q15 - exp1*/
2453 12857317 : tmp2 = shr( tmp2, 1 ); /*Q15 - exp1*/
2454 12857317 : *exp_fac = exp1;
2455 12857317 : move16();
2456 :
2457 12857317 : return tmp2; /*Q15 - exp_fac*/
2458 : }
2459 : }
2460 :
2461 : /*-------------------------------------------------------------------*
2462 : * ceil_log_2()
2463 : *
2464 : * calculates ceil(log2(val))
2465 : *-------------------------------------------------------------------*/
2466 54775 : Word16 ceil_log_2(
2467 : UWord64 val /*Q0*/ )
2468 : {
2469 :
2470 54775 : IF( val <= 0 )
2471 : {
2472 0 : assert( 0 );
2473 : }
2474 54775 : ELSE IF( LE_64( val, 1 ) )
2475 : {
2476 285 : return 0;
2477 : }
2478 54490 : ELSE IF( LE_64( val, 2 ) )
2479 : {
2480 2973 : return 1;
2481 : }
2482 51517 : ELSE IF( LE_64( val, 4 ) )
2483 : {
2484 4214 : return 2;
2485 : }
2486 47303 : ELSE IF( LE_64( val, 8 ) )
2487 : {
2488 2743 : return 3;
2489 : }
2490 44560 : ELSE IF( LE_64( val, 16 ) )
2491 : {
2492 1319 : return 4;
2493 : }
2494 43241 : ELSE IF( LE_64( val, 32 ) )
2495 : {
2496 1669 : return 5;
2497 : }
2498 41572 : ELSE IF( LE_64( val, 64 ) )
2499 : {
2500 1718 : return 6;
2501 : }
2502 39854 : ELSE IF( LE_64( val, 128 ) )
2503 : {
2504 4063 : return 7;
2505 : }
2506 35791 : ELSE IF( LE_64( val, 256 ) )
2507 : {
2508 6036 : return 8;
2509 : }
2510 29755 : ELSE IF( LE_64( val, 512 ) )
2511 : {
2512 5363 : return 9;
2513 : }
2514 24392 : ELSE IF( LE_64( val, 1024 ) )
2515 : {
2516 7298 : return 10;
2517 : }
2518 17094 : ELSE IF( LE_64( val, 2048 ) )
2519 : {
2520 2102 : return 11;
2521 : }
2522 14992 : ELSE IF( LE_64( val, 4096 ) )
2523 : {
2524 1669 : return 12;
2525 : }
2526 13323 : ELSE IF( LE_64( val, 8192 ) )
2527 : {
2528 1254 : return 13;
2529 : }
2530 12069 : ELSE IF( LE_64( val, 16384 ) )
2531 : {
2532 1705 : return 14;
2533 : }
2534 10364 : ELSE IF( LE_64( val, 32768 ) )
2535 : {
2536 3506 : return 15;
2537 : }
2538 6858 : ELSE IF( LE_64( val, 65536 ) )
2539 : {
2540 472 : return 16;
2541 : }
2542 6386 : ELSE IF( LE_64( val, 131072 ) )
2543 : {
2544 192 : return 17;
2545 : }
2546 6194 : ELSE IF( LE_64( val, 262144 ) )
2547 : {
2548 259 : return 18;
2549 : }
2550 5935 : ELSE IF( LE_64( val, 524288 ) )
2551 : {
2552 248 : return 19;
2553 : }
2554 5687 : ELSE IF( LE_64( val, 1048576 ) )
2555 : {
2556 92 : return 20;
2557 : }
2558 5595 : ELSE IF( LE_64( val, 2097152 ) )
2559 : {
2560 115 : return 21;
2561 : }
2562 5480 : ELSE IF( LE_64( val, 4194304 ) )
2563 : {
2564 349 : return 22;
2565 : }
2566 5131 : ELSE IF( LE_64( val, 8388608 ) )
2567 : {
2568 456 : return 23;
2569 : }
2570 4675 : ELSE IF( LE_64( val, 16777216 ) )
2571 : {
2572 810 : return 24;
2573 : }
2574 3865 : ELSE IF( LE_64( val, 33554432 ) )
2575 : {
2576 493 : return 25;
2577 : }
2578 3372 : ELSE IF( LE_64( val, 67108864 ) )
2579 : {
2580 337 : return 26;
2581 : }
2582 3035 : ELSE IF( LE_64( val, 134217728 ) )
2583 : {
2584 153 : return 27;
2585 : }
2586 2882 : ELSE IF( LE_64( val, 268435456 ) )
2587 : {
2588 139 : return 28;
2589 : }
2590 2743 : ELSE IF( LE_64( val, 536870912 ) )
2591 : {
2592 57 : return 29;
2593 : }
2594 2686 : ELSE IF( LE_64( val, 1073741824 ) )
2595 : {
2596 60 : return 30;
2597 : }
2598 2626 : ELSE IF( LE_64( val, 2147483648 ) )
2599 : {
2600 93 : return 31;
2601 : }
2602 2533 : ELSE IF( LE_64( val, 4294967296 ) )
2603 : {
2604 147 : return 32;
2605 : }
2606 2386 : ELSE IF( LE_64( val, 8589934592 ) )
2607 : {
2608 61 : return 33;
2609 : }
2610 2325 : ELSE IF( LE_64( val, 17179869184 ) )
2611 : {
2612 208 : return 34;
2613 : }
2614 2117 : ELSE IF( LE_64( val, 34359738368 ) )
2615 : {
2616 226 : return 35;
2617 : }
2618 1891 : ELSE IF( LE_64( val, 68719476736 ) )
2619 : {
2620 176 : return 36;
2621 : }
2622 1715 : ELSE IF( LE_64( val, 137438953472 ) )
2623 : {
2624 172 : return 37;
2625 : }
2626 1543 : ELSE IF( LE_64( val, 274877906944 ) )
2627 : {
2628 204 : return 38;
2629 : }
2630 1339 : ELSE IF( LE_64( val, 549755813888 ) )
2631 : {
2632 165 : return 39;
2633 : }
2634 1174 : ELSE IF( LE_64( val, 1099511627776 ) )
2635 : {
2636 158 : return 40;
2637 : }
2638 1016 : ELSE IF( LE_64( val, 2199023255552 ) )
2639 : {
2640 142 : return 41;
2641 : }
2642 874 : ELSE IF( LE_64( val, 4398046511104 ) )
2643 : {
2644 211 : return 42;
2645 : }
2646 663 : ELSE IF( LE_64( val, 8796093022208 ) )
2647 : {
2648 122 : return 43;
2649 : }
2650 541 : ELSE IF( LE_64( val, 17592186044416 ) )
2651 : {
2652 90 : return 44;
2653 : }
2654 451 : ELSE IF( LE_64( val, 35184372088832 ) )
2655 : {
2656 166 : return 45;
2657 : }
2658 285 : ELSE IF( LE_64( val, 70368744177664 ) )
2659 : {
2660 134 : return 46;
2661 : }
2662 151 : ELSE IF( LE_64( val, 140737488355328 ) )
2663 : {
2664 92 : return 47;
2665 : }
2666 59 : ELSE IF( LE_64( val, 281474976710656 ) )
2667 : {
2668 59 : return 48;
2669 : }
2670 0 : ELSE IF( LE_64( val, 562949953421312 ) )
2671 : {
2672 0 : return 49;
2673 : }
2674 0 : ELSE IF( LE_64( val, 1125899906842624 ) )
2675 : {
2676 0 : return 50;
2677 : }
2678 0 : ELSE IF( LE_64( val, 2251799813685248 ) )
2679 : {
2680 0 : return 51;
2681 : }
2682 0 : ELSE IF( LE_64( val, 4503599627370496 ) )
2683 : {
2684 0 : return 52;
2685 : }
2686 0 : ELSE IF( LE_64( val, 9007199254740992 ) )
2687 : {
2688 0 : return 53;
2689 : }
2690 0 : ELSE IF( LE_64( val, 18014398509481984 ) )
2691 : {
2692 0 : return 54;
2693 : }
2694 0 : ELSE IF( LE_64( val, 36028797018963968 ) )
2695 : {
2696 0 : return 55;
2697 : }
2698 0 : ELSE IF( LE_64( val, 72057594037927936 ) )
2699 : {
2700 0 : return 56;
2701 : }
2702 0 : ELSE IF( LE_64( val, 144115188075855872 ) )
2703 : {
2704 0 : return 57;
2705 : }
2706 0 : ELSE IF( LE_64( val, 288230376151711744 ) )
2707 : {
2708 0 : return 58;
2709 : }
2710 0 : ELSE IF( LE_64( val, 576460752303423488 ) )
2711 : {
2712 0 : return 59;
2713 : }
2714 0 : ELSE IF( LE_64( val, 1152921504606846976 ) )
2715 : {
2716 0 : return 60;
2717 : }
2718 0 : ELSE IF( LE_64( val, 2305843009213693952 ) )
2719 : {
2720 0 : return 61;
2721 : }
2722 0 : ELSE IF( LE_64( val, 4611686018427387904 ) )
2723 : {
2724 0 : return 62;
2725 : }
2726 0 : ELSE IF( LE_64( val, 9223372036854775807 ) )
2727 : {
2728 0 : return 63;
2729 : }
2730 0 : return 64;
2731 : }
2732 :
2733 :
2734 : /*-------------------------------------------------------------------*
2735 : * var_32_fx()
2736 : *
2737 : * calculates variance of 32-bit array
2738 : * Currently using direct division.
2739 : * Needs update once required basops are implemented.
2740 : *-------------------------------------------------------------------*/
2741 :
2742 142922 : Word64 var_32_fx(
2743 : const Word32 *x, /* i : input vector q*/
2744 : const Word16 len, /* i : length of inputvector Q0*/
2745 : Word16 q /* q : q-factor for the array */
2746 : )
2747 : {
2748 : Word16 i;
2749 : Word64 mean, var;
2750 :
2751 142922 : mean = 0;
2752 142922 : move64();
2753 142922 : var = 0;
2754 142922 : move64();
2755 :
2756 714610 : FOR( i = 0; i < len; i++ )
2757 : {
2758 571688 : mean = W_add( mean, x[i] ); /*q*/
2759 : }
2760 :
2761 142922 : mean = mean / len; /* NOTE: No BASOP for 64 bit division q*/
2762 :
2763 714610 : FOR( i = 0; i < len; i++ )
2764 : {
2765 571688 : 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*/
2766 : }
2767 :
2768 142922 : var = W_shl( var, sub( 31, q ) ); /*q*/
2769 :
2770 142922 : var = var / len; /* NOTE: No BASOP for 64 bit division q*/
2771 :
2772 142922 : return var; /*q*/
2773 : }
|