comparison libgsmefr/basicops.c @ 347:1c514150c033

libgsmefr: first big perf opt: inline most basic_op.h functions
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 21 Apr 2024 23:17:21 +0000
parents libgsmefr/basicop2.c@38326102fc43
children
comparison
equal deleted inserted replaced
346:9a8b5c9a3b4a 347:1c514150c033
1 /*
2 * This C module is a stripped-down version made from ETSI basicop2.c,
3 * reduced to just those functions which we are not inlining.
4 */
5
6 /*___________________________________________________________________________
7 | |
8 | Include-Files |
9 |___________________________________________________________________________|
10 */
11
12 #include <stdint.h>
13 #include "typedef.h"
14 #include "namespace.h"
15 #include "basic_op.h"
16
17 /*___________________________________________________________________________
18 | |
19 | Functions |
20 |___________________________________________________________________________|
21 */
22
23 /*___________________________________________________________________________
24 | |
25 | Function Name : L_macNs |
26 | |
27 | Purpose : |
28 | |
29 | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit |
30 | result to L_var3 without saturation, return a 32 bit result. Generate |
31 | carry and overflow values : |
32 | L_macNs(L_var3,var1,var2) = L_add_c(L_var3,L_mult(var1,var2)). |
33 | |
34 | Complexity weight : 1 |
35 | |
36 | Inputs : |
37 | |
38 | L_var3 32 bit long signed integer (Word32) whose value falls in the |
39 | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
40 | |
41 | var1 |
42 | 16 bit short signed integer (Word16) whose value falls in the |
43 | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
44 | |
45 | var2 |
46 | 16 bit short signed integer (Word16) whose value falls in the |
47 | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
48 | |
49 | Outputs : |
50 | |
51 | none |
52 | |
53 | Return Value : |
54 | |
55 | L_var_out |
56 | 32 bit long signed integer (Word32) whose value falls in the |
57 | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
58 | |
59 | Caution : |
60 | |
61 | In some cases the Carry flag has to be cleared or set before using |
62 | operators which take into account its value. |
63 |___________________________________________________________________________|
64 */
65
66 Word32 L_macNs (Word32 L_var3, Word16 var1, Word16 var2)
67 {
68 Word32 L_var_out;
69
70 L_var_out = L_mult (var1, var2);
71 L_var_out = L_add_c (L_var3, L_var_out);
72 return (L_var_out);
73 }
74
75 /*___________________________________________________________________________
76 | |
77 | Function Name : L_msuNs |
78 | |
79 | Purpose : |
80 | |
81 | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 |
82 | bit result from L_var3 without saturation, return a 32 bit result. Ge- |
83 | nerate carry and overflow values : |
84 | L_msuNs(L_var3,var1,var2) = L_sub_c(L_var3,L_mult(var1,var2)). |
85 | |
86 | Complexity weight : 1 |
87 | |
88 | Inputs : |
89 | |
90 | L_var3 32 bit long signed integer (Word32) whose value falls in the |
91 | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
92 | |
93 | var1 |
94 | 16 bit short signed integer (Word16) whose value falls in the |
95 | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
96 | |
97 | var2 |
98 | 16 bit short signed integer (Word16) whose value falls in the |
99 | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
100 | |
101 | Outputs : |
102 | |
103 | none |
104 | |
105 | Return Value : |
106 | |
107 | L_var_out |
108 | 32 bit long signed integer (Word32) whose value falls in the |
109 | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
110 | |
111 | Caution : |
112 | |
113 | In some cases the Carry flag has to be cleared or set before using |
114 | operators which take into account its value. |
115 |___________________________________________________________________________|
116 */
117
118 Word32 L_msuNs (Word32 L_var3, Word16 var1, Word16 var2)
119 {
120 Word32 L_var_out;
121
122 L_var_out = L_mult (var1, var2);
123 L_var_out = L_sub_c (L_var3, L_var_out);
124 return (L_var_out);
125 }
126
127 /*___________________________________________________________________________
128 | |
129 | Function Name : L_add_c |
130 | |
131 | Purpose : |
132 | |
133 | Performs 32 bits addition of the two 32 bits variables (L_var1+L_var2+C)|
134 | with carry. No saturation. Generate carry and Overflow values. The car- |
135 | ry and overflow values are binary variables which can be tested and as- |
136 | signed values. |
137 | |
138 | Complexity weight : 2 |
139 | |
140 | Inputs : |
141 | |
142 | L_var1 32 bit long signed integer (Word32) whose value falls in the |
143 | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
144 | |
145 | L_var2 32 bit long signed integer (Word32) whose value falls in the |
146 | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
147 | |
148 | Outputs : |
149 | |
150 | none |
151 | |
152 | Return Value : |
153 | |
154 | L_var_out |
155 | 32 bit long signed integer (Word32) whose value falls in the |
156 | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
157 | |
158 | Caution : |
159 | |
160 | In some cases the Carry flag has to be cleared or set before using |
161 | operators which take into account its value. |
162 |___________________________________________________________________________|
163 */
164 Word32 L_add_c (Word32 L_var1, Word32 L_var2)
165 {
166 Word32 L_var_out;
167 Word32 L_test;
168 Flag carry_int = 0;
169
170 L_var_out = L_var1 + L_var2 + Carry;
171
172 L_test = L_var1 + L_var2;
173
174 if ((L_var1 > 0) && (L_var2 > 0) && (L_test < 0))
175 {
176 Overflow = 1;
177 carry_int = 0;
178 }
179 else
180 {
181 if ((L_var1 < 0) && (L_var2 < 0))
182 {
183 if (L_test >= 0)
184 {
185 Overflow = 1;
186 carry_int = 1;
187 }
188 else
189 {
190 Overflow = 0;
191 carry_int = 1;
192 }
193 }
194 else
195 {
196 if (((L_var1 ^ L_var2) < 0) && (L_test >= 0))
197 {
198 Overflow = 0;
199 carry_int = 1;
200 }
201 else
202 {
203 Overflow = 0;
204 carry_int = 0;
205 }
206 }
207 }
208
209 if (Carry)
210 {
211 if (L_test == MAX_32)
212 {
213 Overflow = 1;
214 Carry = carry_int;
215 }
216 else
217 {
218 if (L_test == (Word32) 0xFFFFFFFFL)
219 {
220 Carry = 1;
221 }
222 else
223 {
224 Carry = carry_int;
225 }
226 }
227 }
228 else
229 {
230 Carry = carry_int;
231 }
232
233 return (L_var_out);
234 }
235
236 /*___________________________________________________________________________
237 | |
238 | Function Name : L_sub_c |
239 | |
240 | Purpose : |
241 | |
242 | Performs 32 bits subtraction of the two 32 bits variables with carry |
243 | (borrow) : L_var1-L_var2-C. No saturation. Generate carry and Overflow |
244 | values. The carry and overflow values are binary variables which can |
245 | be tested and assigned values. |
246 | |
247 | Complexity weight : 2 |
248 | |
249 | Inputs : |
250 | |
251 | L_var1 32 bit long signed integer (Word32) whose value falls in the |
252 | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
253 | |
254 | L_var2 32 bit long signed integer (Word32) whose value falls in the |
255 | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
256 | |
257 | Outputs : |
258 | |
259 | none |
260 | |
261 | Return Value : |
262 | |
263 | L_var_out |
264 | 32 bit long signed integer (Word32) whose value falls in the |
265 | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
266 | |
267 | Caution : |
268 | |
269 | In some cases the Carry flag has to be cleared or set before using |
270 | operators which take into account its value. |
271 |___________________________________________________________________________|
272 */
273
274 Word32 L_sub_c (Word32 L_var1, Word32 L_var2)
275 {
276 Word32 L_var_out;
277 Word32 L_test;
278 Flag carry_int = 0;
279
280 if (Carry)
281 {
282 Carry = 0;
283 if (L_var2 != MIN_32)
284 {
285 L_var_out = L_add_c (L_var1, -L_var2);
286 }
287 else
288 {
289 L_var_out = L_var1 - L_var2;
290 if (L_var1 > 0L)
291 {
292 Overflow = 1;
293 Carry = 0;
294 }
295 }
296 }
297 else
298 {
299 L_var_out = L_var1 - L_var2 - (Word32) 0X00000001L;
300 L_test = L_var1 - L_var2;
301
302 if ((L_test < 0) && (L_var1 > 0) && (L_var2 < 0))
303 {
304 Overflow = 1;
305 carry_int = 0;
306 }
307 else if ((L_test > 0) && (L_var1 < 0) && (L_var2 > 0))
308 {
309 Overflow = 1;
310 carry_int = 1;
311 }
312 else if ((L_test > 0) && ((L_var1 ^ L_var2) > 0))
313 {
314 Overflow = 0;
315 carry_int = 1;
316 }
317 if (L_test == MIN_32)
318 {
319 Overflow = 1;
320 Carry = carry_int;
321 }
322 else
323 {
324 Carry = carry_int;
325 }
326 }
327
328 return (L_var_out);
329 }
330
331 /*___________________________________________________________________________
332 | |
333 | Function Name : shr_r |
334 | |
335 | Purpose : |
336 | |
337 | Same as shr(var1,var2) but with rounding. Saturate the result in case of|
338 | underflows or overflows : |
339 | - If var2 is greater than zero : |
340 | if (sub(shl(shr(var1,var2),1),shr(var1,sub(var2,1)))) |
341 | is equal to zero |
342 | then |
343 | shr_r(var1,var2) = shr(var1,var2) |
344 | else |
345 | shr_r(var1,var2) = add(shr(var1,var2),1) |
346 | - If var2 is less than or equal to zero : |
347 | shr_r(var1,var2) = shr(var1,var2). |
348 | |
349 | Complexity weight : 2 |
350 | |
351 | Inputs : |
352 | |
353 | var1 |
354 | 16 bit short signed integer (Word16) whose value falls in the |
355 | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
356 | |
357 | var2 |
358 | 16 bit short signed integer (Word16) whose value falls in the |
359 | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
360 | |
361 | Outputs : |
362 | |
363 | none |
364 | |
365 | Return Value : |
366 | |
367 | var_out |
368 | 16 bit short signed integer (Word16) whose value falls in the |
369 | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
370 |___________________________________________________________________________|
371 */
372
373 Word16 shr_r (Word16 var1, Word16 var2)
374 {
375 Word16 var_out;
376
377 if (var2 > 15)
378 {
379 var_out = 0;
380 }
381 else
382 {
383 var_out = shr (var1, var2);
384
385 if (var2 > 0)
386 {
387 if ((var1 & ((Word16) 1 << (var2 - 1))) != 0)
388 {
389 var_out++;
390 }
391 }
392 }
393 return (var_out);
394 }
395
396 /*___________________________________________________________________________
397 | |
398 | Function Name : mac_r |
399 | |
400 | Purpose : |
401 | |
402 | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit |
403 | result to L_var3 with saturation. Round the LS 16 bits of the result |
404 | into the MS 16 bits with saturation and shift the result right by 16. |
405 | Return a 16 bit result. |
406 | mac_r(L_var3,var1,var2) = round(L_mac(L_var3,var1,var2)) |
407 | |
408 | Complexity weight : 2 |
409 | |
410 | Inputs : |
411 | |
412 | L_var3 32 bit long signed integer (Word32) whose value falls in the |
413 | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
414 | |
415 | var1 |
416 | 16 bit short signed integer (Word16) whose value falls in the |
417 | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
418 | |
419 | var2 |
420 | 16 bit short signed integer (Word16) whose value falls in the |
421 | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
422 | |
423 | Outputs : |
424 | |
425 | none |
426 | |
427 | Return Value : |
428 | |
429 | var_out |
430 | 16 bit short signed integer (Word16) whose value falls in the |
431 | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. |
432 |___________________________________________________________________________|
433 */
434
435 Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2)
436 {
437 Word16 var_out;
438
439 L_var3 = L_mac (L_var3, var1, var2);
440 L_var3 = L_add (L_var3, (Word32) 0x00008000L);
441 var_out = extract_h (L_var3);
442 return (var_out);
443 }
444
445 /*___________________________________________________________________________
446 | |
447 | Function Name : msu_r |
448 | |
449 | Purpose : |
450 | |
451 | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 |
452 | bit result to L_var3 with saturation. Round the LS 16 bits of the res- |
453 | ult into the MS 16 bits with saturation and shift the result right by |
454 | 16. Return a 16 bit result. |
455 | msu_r(L_var3,var1,var2) = round(L_msu(L_var3,var1,var2)) |
456 | |
457 | Complexity weight : 2 |
458 | |
459 | Inputs : |
460 | |
461 | L_var3 32 bit long signed integer (Word32) whose value falls in the |
462 | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
463 | |
464 | var1 |
465 | 16 bit short signed integer (Word16) whose value falls in the |
466 | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
467 | |
468 | var2 |
469 | 16 bit short signed integer (Word16) whose value falls in the |
470 | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
471 | |
472 | Outputs : |
473 | |
474 | none |
475 | |
476 | Return Value : |
477 | |
478 | var_out |
479 | 16 bit short signed integer (Word16) whose value falls in the |
480 | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. |
481 |___________________________________________________________________________|
482 */
483
484 Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2)
485 {
486 Word16 var_out;
487
488 L_var3 = L_msu (L_var3, var1, var2);
489 L_var3 = L_add (L_var3, (Word32) 0x00008000L);
490 var_out = extract_h (L_var3);
491 return (var_out);
492 }
493
494 /*___________________________________________________________________________
495 | |
496 | Function Name : L_shr_r |
497 | |
498 | Purpose : |
499 | |
500 | Same as L_shr(L_var1,var2) but with rounding. Saturate the result in |
501 | case of underflows or overflows : |
502 | - If var2 is greater than zero : |
503 | if (L_sub(L_shl(L_shr(L_var1,var2),1),L_shr(L_var1,sub(var2,1))))|
504 | is equal to zero |
505 | then |
506 | L_shr_r(L_var1,var2) = L_shr(L_var1,var2) |
507 | else |
508 | L_shr_r(L_var1,var2) = L_add(L_shr(L_var1,var2),1) |
509 | - If var2 is less than or equal to zero : |
510 | L_shr_r(L_var1,var2) = L_shr(L_var1,var2). |
511 | |
512 | Complexity weight : 3 |
513 | |
514 | Inputs : |
515 | |
516 | L_var1 |
517 | 32 bit long signed integer (Word32) whose value falls in the |
518 | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
519 | |
520 | var2 |
521 | 16 bit short signed integer (Word16) whose value falls in the |
522 | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
523 | |
524 | Outputs : |
525 | |
526 | none |
527 | |
528 | Return Value : |
529 | |
530 | L_var_out |
531 | 32 bit long signed integer (Word32) whose value falls in the |
532 | range : 0x8000 0000 <= var_out <= 0x7fff ffff. |
533 |___________________________________________________________________________|
534 */
535
536 Word32 L_shr_r (Word32 L_var1, Word16 var2)
537 {
538 Word32 L_var_out;
539
540 if (var2 > 31)
541 {
542 L_var_out = 0;
543 }
544 else
545 {
546 L_var_out = L_shr (L_var1, var2);
547 if (var2 > 0)
548 {
549 if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0)
550 {
551 L_var_out++;
552 }
553 }
554 }
555 return (L_var_out);
556 }
557
558 /*___________________________________________________________________________
559 | |
560 | Function Name : L_sat |
561 | |
562 | Purpose : |
563 | |
564 | 32 bit L_var1 is set to 2147483647 if an overflow occured or to |
565 | -2147483648 if an underflow occured on the most recent L_add_c, |
566 | L_sub_c, L_macNs or L_msuNs operations. The carry and overflow values |
567 | are binary values which can be tested and assigned values. |
568 | |
569 | Complexity weight : 4 |
570 | |
571 | Inputs : |
572 | |
573 | L_var1 |
574 | 32 bit long signed integer (Word32) whose value falls in the |
575 | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
576 | |
577 | Outputs : |
578 | |
579 | none |
580 | |
581 | Return Value : |
582 | |
583 | L_var_out |
584 | 32 bit long signed integer (Word32) whose value falls in the |
585 | range : 0x8000 0000 <= var_out <= 0x7fff ffff. |
586 |___________________________________________________________________________|
587 */
588
589 Word32 L_sat (Word32 L_var1)
590 {
591 Word32 L_var_out;
592
593 L_var_out = L_var1;
594
595 if (Overflow)
596 {
597 if (Carry)
598 {
599 L_var_out = MIN_32;
600 }
601 else
602 {
603 L_var_out = MAX_32;
604 }
605
606 Carry = 0;
607 Overflow = 0;
608 }
609 return (L_var_out);
610 }
611
612 /*___________________________________________________________________________
613 | |
614 | Function Name : div_s |
615 | |
616 | Purpose : |
617 | |
618 | Produces a result which is the fractional integer division of var1 by |
619 | var2; var1 and var2 must be positive and var2 must be greater or equal |
620 | to var1; the result is positive (leading bit equal to 0) and truncated |
621 | to 16 bits. |
622 | If var1 = var2 then div(var1,var2) = 32767. |
623 | |
624 | Complexity weight : 18 |
625 | |
626 | Inputs : |
627 | |
628 | var1 |
629 | 16 bit short signed integer (Word16) whose value falls in the |
630 | range : 0x0000 0000 <= var1 <= var2 and var2 != 0. |
631 | |
632 | var2 |
633 | 16 bit short signed integer (Word16) whose value falls in the |
634 | range : var1 <= var2 <= 0x0000 7fff and var2 != 0. |
635 | |
636 | Outputs : |
637 | |
638 | none |
639 | |
640 | Return Value : |
641 | |
642 | var_out |
643 | 16 bit short signed integer (Word16) whose value falls in the |
644 | range : 0x0000 0000 <= var_out <= 0x0000 7fff. |
645 | It's a Q15 value (point between b15 and b14). |
646 |___________________________________________________________________________|
647 */
648
649 Word16 div_s (Word16 var1, Word16 var2)
650 {
651 Word16 var_out = 0;
652 Word16 iteration;
653 Word32 L_num;
654 Word32 L_denom;
655
656 #if 0
657 if ((var1 > var2) || (var1 < 0) || (var2 < 0))
658 {
659 printf ("Division Error var1=%d var2=%d\n", var1, var2);
660 exit (0);
661 }
662 if (var2 == 0)
663 {
664 printf ("Division by 0, Fatal error \n");
665 exit (0);
666 }
667 #endif
668
669 if (var1 == 0)
670 {
671 var_out = 0;
672 }
673 else
674 {
675 if (var1 == var2)
676 {
677 var_out = MAX_16;
678 }
679 else
680 {
681 L_num = L_deposit_l (var1);
682 L_denom = L_deposit_l (var2);
683
684 for (iteration = 0; iteration < 15; iteration++)
685 {
686 var_out <<= 1;
687 L_num <<= 1;
688
689 if (L_num >= L_denom)
690 {
691 L_num = L_sub (L_num, L_denom);
692 var_out = add (var_out, 1);
693 }
694 }
695 }
696 }
697
698 return (var_out);
699 }