1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 /****************************************************************************************
19 Portions of this file are derived from the following 3GPP standard:
20
21 3GPP TS 26.073
22 ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
23 Available from http://www.3gpp.org
24
25 (C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
26 Permission to distribute, modify and use this file under the standard license
27 terms listed above has been obtained from the copyright holder.
28 ****************************************************************************************/
29 /*
30 ------------------------------------------------------------------------------
31
32
33
34 Pathname: ./audio/gsm-amr/c/src/c3_14pf.c
35 Functions:
36
37 Date: 05/26/2000
38
39 ------------------------------------------------------------------------------
40 REVISION HISTORY
41
42 Description: Modified to pass overflow flag through to basic math function.
43 The flag is passed back to the calling function by pointer reference.
44
45 Description: Optimized file to reduce clock cycle usage. Updated copyright
46 year. Removed unneccesary include files and added only the
47 include files for the math functions used. Removed unused
48 #defines.
49
50 Description: Changed round function name to pv_round to avoid conflict with
51 round function in C standard library.
52
53 Description: Replaced "int" and/or "char" with OSCL defined types.
54
55 Description:
56
57 ------------------------------------------------------------------------------
58 MODULE DESCRIPTION
59
60 ------------------------------------------------------------------------------
61 */
62
63 /*----------------------------------------------------------------------------
64 ; INCLUDES
65 ----------------------------------------------------------------------------*/
66 #include "c3_14pf.h"
67 #include "typedef.h"
68 #include "inv_sqrt.h"
69 #include "cnst.h"
70 #include "cor_h.h"
71 #include "set_sign.h"
72 #include "basic_op.h"
73
74 /*----------------------------------------------------------------------------
75 ; MACROS
76 ; Define module specific macros here
77 ----------------------------------------------------------------------------*/
78
79 /*----------------------------------------------------------------------------
80 ; DEFINES
81 ; Include all pre-processor statements here. Include conditional
82 ; compile variables also.
83 ----------------------------------------------------------------------------*/
84
85 #define NB_PULSE 3
86
87 /*----------------------------------------------------------------------------
88 ; LOCAL FUNCTION DEFINITIONS
89 ; Function Prototype declaration
90 ----------------------------------------------------------------------------*/
91 static void search_3i40(
92 Word16 dn[], /* i : correlation between target and h[] */
93 Word16 dn2[], /* i : maximum of corr. in each track. */
94 Word16 rr[][L_CODE],/* i : matrix of autocorrelation */
95 Word16 codvec[], /* o : algebraic codebook vector */
96 Flag * pOverflow /* o : Flag set when overflow occurs */
97 );
98
99 static Word16 build_code(
100 Word16 codvec[], /* i : algebraic codebook vector */
101 Word16 dn_sign[], /* i : sign of dn[] */
102 Word16 cod[], /* o : algebraic (fixed) codebook excitation */
103 Word16 h[], /* i : impulse response of weighted synthesis filter */
104 Word16 y[], /* o : filtered fixed codebook excitation */
105 Word16 sign[], /* o : sign of 3 pulses */
106 Flag * pOverflow /* o : Flag set when overflow occurs */
107 );
108
109 /*----------------------------------------------------------------------------
110 ; LOCAL VARIABLE DEFINITIONS
111 ; Variable declaration - defined here and used outside this module
112 ----------------------------------------------------------------------------*/
113
114 /*----------------------------------------------------------------------------
115 ; EXTERNAL GLOBAL STORE/BUFFER/POINTER REFERENCES
116 ; Declare variables used in this module but defined elsewhere
117 ----------------------------------------------------------------------------*/
118
119 /*
120 ------------------------------------------------------------------------------
121 FUNCTION NAME: code_3i40_14bits
122 ------------------------------------------------------------------------------
123 INPUT AND OUTPUT DEFINITIONS
124
125 Inputs:
126 x[] Array of type Word16 -- target vector
127 h[] Array of type Word16 -- impulse response of weighted synthesis filter
128 h[-L_subfr..-1] must be set to zero.
129
130 T0 Array of type Word16 -- Pitch lag
131 pitch_sharp, Array of type Word16 -- Last quantized pitch gain
132
133 Outputs:
134 code[] Array of type Word16 -- Innovative codebook
135 y[] Array of type Word16 -- filtered fixed codebook excitation
136 * sign Pointer of type Word16 -- Pointer to the signs of 3 pulses
137 pOverflow Pointer to Flag -- set when overflow occurs
138
139 Returns:
140 index
141
142 Global Variables Used:
143 None
144
145 Local Variables Needed:
146 None
147
148 ------------------------------------------------------------------------------
149 FUNCTION DESCRIPTION
150
151 PURPOSE: Searches a 14 bit algebraic codebook containing 3 pulses
152 in a frame of 40 samples.
153
154 DESCRIPTION:
155 The code length is 40, containing 3 nonzero pulses: i0...i2.
156 All pulses can have two possible amplitudes: +1 or -1.
157 Pulse i0 can have 8 possible positions, pulses i1 and i2 can have
158 2x8=16 positions.
159
160 i0 : 0, 5, 10, 15, 20, 25, 30, 35.
161 i1 : 1, 6, 11, 16, 21, 26, 31, 36.
162 3, 8, 13, 18, 23, 28, 33, 38.
163 i2 : 2, 7, 12, 17, 22, 27, 32, 37.
164 4, 9, 14, 19, 24, 29, 34, 39.
165
166 ------------------------------------------------------------------------------
167 REQUIREMENTS
168
169 None
170
171 ------------------------------------------------------------------------------
172 REFERENCES
173
174 [1] c3_14pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
175
176 ------------------------------------------------------------------------------
177 PSEUDO-CODE
178
179 ------------------------------------------------------------------------------
180 RESOURCES USED [optional]
181
182 When the code is written for a specific target processor the
183 the resources used should be documented below.
184
185 HEAP MEMORY USED: x bytes
186
187 STACK MEMORY USED: x bytes
188
189 CLOCK CYCLES: (cycle count equation for this function) + (variable
190 used to represent cycle count for each subroutine
191 called)
192 where: (cycle count variable) = cycle count for [subroutine
193 name]
194
195 ------------------------------------------------------------------------------
196 CAUTION [optional]
197 [State any special notes, constraints or cautions for users of this function]
198
199 ------------------------------------------------------------------------------
200 */
201
code_3i40_14bits(Word16 x[],Word16 h[],Word16 T0,Word16 pitch_sharp,Word16 code[],Word16 y[],Word16 * sign,Flag * pOverflow)202 Word16 code_3i40_14bits(
203 Word16 x[], /* i : target vector */
204 Word16 h[], /* i : impulse response of weighted synthesis filter */
205 /* h[-L_subfr..-1] must be set to zero. */
206 Word16 T0, /* i : Pitch lag */
207 Word16 pitch_sharp, /* i : Last quantized pitch gain */
208 Word16 code[], /* o : Innovative codebook */
209 Word16 y[], /* o : filtered fixed codebook excitation */
210 Word16 * sign, /* o : Signs of 3 pulses */
211 Flag * pOverflow /* o : Flag set when overflow occurs */
212 )
213 {
214 Word16 codvec[NB_PULSE];
215 Word16 dn[L_CODE];
216 Word16 dn2[L_CODE];
217 Word16 dn_sign[L_CODE];
218 Word16 rr[L_CODE][L_CODE];
219 Word16 i;
220 Word16 index;
221 Word16 sharp;
222 Word16 tempWord;
223
224 /* sharp = shl(pitch_sharp, 1, pOverflow); */
225 sharp = pitch_sharp << 1;
226
227 if (T0 < L_CODE)
228 {
229 for (i = T0; i < L_CODE; i++)
230 {
231 tempWord =
232 mult(
233 h[i - T0],
234 sharp,
235 pOverflow);
236
237 h[i] =
238 add(
239 h[i],
240 tempWord,
241 pOverflow);
242 }
243 }
244
245 cor_h_x(
246 h,
247 x,
248 dn,
249 1,
250 pOverflow);
251
252 set_sign(
253 dn,
254 dn_sign,
255 dn2,
256 6);
257
258 cor_h(
259 h,
260 dn_sign,
261 rr,
262 pOverflow);
263
264 search_3i40(
265 dn,
266 dn2,
267 rr,
268 codvec,
269 pOverflow);
270
271 /* function result */
272 index =
273 build_code(
274 codvec,
275 dn_sign,
276 code,
277 h,
278 y,
279 sign,
280 pOverflow);
281
282 /*-----------------------------------------------------------------*
283 * Compute innovation vector gain. *
284 * Include fixed-gain pitch contribution into code[]. *
285 *-----------------------------------------------------------------*/
286
287 if (T0 < L_CODE)
288 {
289 for (i = T0; i < L_CODE; i++)
290 {
291 tempWord =
292 mult(
293 code[i - T0],
294 sharp,
295 pOverflow);
296
297 code[i] =
298 add(
299 code[i],
300 tempWord,
301 pOverflow);
302 }
303 }
304 return index;
305 }
306
307 /****************************************************************************/
308
309 /*
310 ------------------------------------------------------------------------------
311 FUNCTION NAME: search_3i40
312 ------------------------------------------------------------------------------
313 INPUT AND OUTPUT DEFINITIONS
314
315 Inputs:
316 dn[] Array of type Word16 -- correlation between target and h[]
317 dn2[] Array of type Word16 -- maximum of corr. in each track.
318 rr[][L_CODE] Double Array of type Word16 -- autocorrelation matrix
319
320 Outputs:
321 codvec[] Array of type Word16 -- algebraic codebook vector
322 pOverflow Pointer to Flag -- set when overflow occurs
323
324 Returns:
325 None
326
327 Global Variables Used:
328 None
329
330 Local Variables Needed:
331 None
332
333 ------------------------------------------------------------------------------
334 FUNCTION DESCRIPTION
335
336 PURPOSE: Search the best codevector; determine positions of the 3 pulses
337 in the 40-sample frame.
338 ------------------------------------------------------------------------------
339 REQUIREMENTS
340
341 None
342
343 ------------------------------------------------------------------------------
344 REFERENCES
345
346 [1] c3_14pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
347
348 ------------------------------------------------------------------------------
349 PSEUDO-CODE
350
351 ------------------------------------------------------------------------------
352 RESOURCES USED [optional]
353
354 When the code is written for a specific target processor the
355 the resources used should be documented below.
356
357 HEAP MEMORY USED: x bytes
358
359 STACK MEMORY USED: x bytes
360
361 CLOCK CYCLES: (cycle count equation for this function) + (variable
362 used to represent cycle count for each subroutine
363 called)
364 where: (cycle count variable) = cycle count for [subroutine
365 name]
366
367 ------------------------------------------------------------------------------
368 CAUTION [optional]
369 [State any special notes, constraints or cautions for users of this function]
370
371 ------------------------------------------------------------------------------
372 */
search_3i40(Word16 dn[],Word16 dn2[],Word16 rr[][L_CODE],Word16 codvec[],Flag * pOverflow)373 static void search_3i40(
374 Word16 dn[], /* i : correlation between target and h[] */
375 Word16 dn2[], /* i : maximum of corr. in each track. */
376 Word16 rr[][L_CODE], /* i : matrix of autocorrelation */
377 Word16 codvec[], /* o : algebraic codebook vector */
378 Flag * pOverflow /* o : Flag set when overflow occurs */
379 )
380 {
381 Word16 i0;
382 Word16 i1;
383 Word16 i2;
384
385 Word16 ix = 0; /* initialization only needed to keep gcc silent */
386 Word16 ps = 0; /* initialization only needed to keep gcc silent */
387
388 Word16 i;
389 Word16 pos;
390 Word16 track1;
391 Word16 track2;
392 Word16 ipos[NB_PULSE];
393
394 Word16 psk;
395 Word16 ps0;
396 Word16 ps1;
397 Word16 sq;
398 Word16 sq1;
399 Word16 alpk;
400 Word16 alp;
401 Word16 alp_16;
402
403 Word16 *p_codvec = &codvec[0];
404
405 Word32 s;
406 Word32 mul;
407 Word32 alp0;
408 Word32 alp1;
409
410 psk = -1;
411 alpk = 1;
412
413 for (i = 0; i < NB_PULSE; i++)
414 {
415 *(p_codvec++) = i;
416 }
417
418 for (track1 = 1; track1 < 4; track1 += 2)
419 {
420 for (track2 = 2; track2 < 5; track2 += 2)
421 {
422 /* fix starting position */
423
424 ipos[0] = 0;
425 ipos[1] = track1;
426 ipos[2] = track2;
427
428 /*------------------------------------------------------------------*
429 * main loop: try 3 tracks. *
430 *------------------------------------------------------------------*/
431
432 for (i = 0; i < NB_PULSE; i++)
433 {
434 /*----------------------------------------------------------------*
435 * i0 loop: try 8 positions. *
436 *----------------------------------------------------------------*/
437
438 /* account for ptr. init. (rr[io]) */
439 for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP)
440 {
441 if (dn2[i0] >= 0)
442 {
443 ps0 = dn[i0];
444
445 /* alp0 = L_mult(rr[i0][i0],_1_4, pOverflow); */
446 alp0 = (Word32) rr[i0][i0] << 14;
447
448 /*----------------------------------------------------------------*
449 * i1 loop: 8 positions. *
450 *----------------------------------------------------------------*/
451
452 sq = -1;
453 alp = 1;
454 ps = 0;
455 ix = ipos[1];
456
457 /* initialize 4 index for next loop. */
458 /*-------------------------------------------------------------------*
459 * These index have low complexity address computation because *
460 * they are, in fact, pointers with fixed increment. For example, *
461 * "rr[i0][i2]" is a pointer initialized to "&rr[i0][ipos[2]]" *
462 * and incremented by "STEP". *
463 *-------------------------------------------------------------------*/
464
465 for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP)
466 {
467 /* idx increment = STEP */
468 /* ps1 = add(ps0, dn[i1], pOverflow); */
469 ps1 = ps0 + dn[i1];
470
471 /* alp1 = alp0 + rr[i0][i1] + 1/2*rr[i1][i1]; */
472
473 /* idx incr = STEP */
474 /* alp1 = L_mac(alp0, rr[i1][i1], _1_4, pOverflow); */
475 alp1 = alp0 + ((Word32) rr[i1][i1] << 14);
476
477 /* idx incr = STEP */
478 /* alp1 = L_mac(alp1, rr[i0][i1], _1_2, pOverflow); */
479 alp1 += (Word32) rr[i0][i1] << 15;
480
481 /* sq1 = mult(ps1, ps1, pOverflow); */
482 sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
483
484 /* alp_16 = pv_round(alp1, pOverflow); */
485 alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
486
487 /* s = L_mult(alp, sq1, pOverflow); */
488 s = ((Word32) alp * sq1) << 1;
489
490 /* s = L_msu(s, sq, alp_16, pOverflow); */
491 __builtin_mul_overflow(sq, alp_16, &mul);
492 __builtin_sub_overflow(s, (mul << 1), &s);
493
494 if (s > 0)
495 {
496 sq = sq1;
497 ps = ps1;
498 alp = alp_16;
499 ix = i1;
500 }
501 }
502 i1 = ix;
503
504 /*----------------------------------------------------------------*
505 * i2 loop: 8 positions. *
506 *----------------------------------------------------------------*/
507
508 ps0 = ps;
509
510 /* alp0 = L_mult(alp, _1_4, pOverflow); */
511 alp0 = (Word32) alp << 14;
512
513 sq = -1;
514 alp = 1;
515 ps = 0;
516 ix = ipos[2];
517
518 /* initialize 4 index for next loop (see i1 loop) */
519
520 for (i2 = ipos[2]; i2 < L_CODE; i2 += STEP)
521 {
522 /* index increment = STEP */
523 /* ps1 = add(ps0, dn[i2], pOverflow); */
524 ps1 = ps0 + dn[i2];
525
526 /* alp1 = alp0 + rr[i0][i2] + rr[i1][i2] + 1/2*rr[i2][i2]; */
527
528 /* idx incr = STEP */
529 /* alp1 = L_mac(alp0, rr[i2][i2], _1_16, pOverflow); */
530 alp1 = alp0 + ((Word32) rr[i2][i2] << 12);
531
532 /* idx incr = STEP */
533 /* alp1 = L_mac(alp1, rr[i1][i2], _1_8, pOverflow); */
534 alp1 += (Word32) rr[i1][i2] << 13;
535
536 /* idx incr = STEP */
537 /* alp1 = L_mac(alp1,rr[i0][i2], _1_8, pOverflow); */
538 alp1 += (Word32) rr[i0][i2] << 13;
539
540 /* sq1 = mult(ps1, ps1, pOverflow); */
541 sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
542
543 /* alp_16 = pv_round(alp1, pOverflow); */
544 alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
545
546 /* s = L_mult(alp, sq1, pOverflow); */
547 s = ((Word32) alp * sq1) << 1;
548
549 /* s = L_msu(s, sq, alp_16, pOverflow); */
550 s -= (((Word32) sq * alp_16) << 1);
551
552 if (s > 0)
553 {
554 sq = sq1;
555 ps = ps1;
556 alp = alp_16;
557 ix = i2;
558 }
559 }
560 i2 = ix;
561
562 /* memorize codevector if this one
563 * is better than the last one.
564 */
565
566 s = L_mult(alpk, sq, pOverflow);
567 //s = ((Word32) alpk * sq) << 1;
568
569 s = L_msu(s, psk, alp, pOverflow);
570 //s -= (((Word32) psk * alp) << 1);
571
572 if (s > 0)
573 {
574 psk = sq;
575 alpk = alp;
576 p_codvec = &codvec[0];
577
578 *(p_codvec++) = i0;
579 *(p_codvec++) = i1;
580 *(p_codvec) = i2;
581 }
582 }
583 }
584 /*----------------------------------------------------------------*
585 * Cyclic permutation of i0, i1 and i2. *
586 *----------------------------------------------------------------*/
587
588 pos = ipos[2];
589 ipos[2] = ipos[1];
590 ipos[1] = ipos[0];
591 ipos[0] = pos;
592 }
593 }
594 }
595 return;
596 }
597
598 /****************************************************************************/
599
600 /*
601 ------------------------------------------------------------------------------
602 FUNCTION NAME: build_code()
603 ------------------------------------------------------------------------------
604 INPUT AND OUTPUT DEFINITIONS
605
606 Inputs:
607 codvec[] Array of type Word16 -- position of pulses
608 dn_sign[] Array of type Word16 -- sign of pulses
609 h[] Array of type Word16 -- impulse response of
610 weighted synthesis filter
611
612 Outputs:
613 cod[] Array of type Word16 -- innovative code vector
614 y[] Array of type Word16 -- filtered innovative code
615 sign[] Array of type Word16 -- sign of 3 pulses
616 pOverflow Pointer to Flag -- set when overflow occurs
617
618 Returns:
619 indx
620
621 Global Variables Used:
622 None
623
624 Local Variables Needed:
625 None
626
627 ------------------------------------------------------------------------------
628 FUNCTION DESCRIPTION
629
630 PURPOSE: Builds the codeword, the filtered codeword and index of the
631 codevector, based on the signs and positions of 3 pulses.
632
633 ------------------------------------------------------------------------------
634 REQUIREMENTS
635
636 None
637
638 ------------------------------------------------------------------------------
639 REFERENCES
640
641 [1] c3_14pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
642
643 ------------------------------------------------------------------------------
644 PSEUDO-CODE
645
646 ------------------------------------------------------------------------------
647 RESOURCES USED [optional]
648
649 When the code is written for a specific target processor the
650 the resources used should be documented below.
651
652 HEAP MEMORY USED: x bytes
653
654 STACK MEMORY USED: x bytes
655
656 CLOCK CYCLES: (cycle count equation for this function) + (variable
657 used to represent cycle count for each subroutine
658 called)
659 where: (cycle count variable) = cycle count for [subroutine
660 name]
661
662 ------------------------------------------------------------------------------
663 CAUTION [optional]
664 [State any special notes, constraints or cautions for users of this function]
665
666 ------------------------------------------------------------------------------
667 */
668
669 static Word16
build_code(Word16 codvec[],Word16 dn_sign[],Word16 cod[],Word16 h[],Word16 y[],Word16 sign[],Flag * pOverflow)670 build_code(
671 Word16 codvec[], /* i : position of pulses */
672 Word16 dn_sign[], /* i : sign of pulses */
673 Word16 cod[], /* o : innovative code vector */
674 Word16 h[], /* i : impulse response of weighted synthesis filter */
675 Word16 y[], /* o : filtered innovative code */
676 Word16 sign[], /* o : sign of 3 pulses */
677 Flag *pOverflow /* o : Flag set when overflow occurs */
678 )
679 {
680 Word16 i;
681 Word16 j;
682 Word16 k;
683 Word16 track;
684 Word16 index;
685 Word16 _sign[NB_PULSE];
686 Word16 indx;
687 Word16 rsign;
688
689 Word16 *p0;
690 Word16 *p1;
691 Word16 *p2;
692
693 Word32 s;
694
695 for (i = 0; i < L_CODE; i++)
696 {
697 cod[i] = 0;
698 }
699
700 indx = 0;
701 rsign = 0;
702
703 for (k = 0; k < NB_PULSE; k++)
704 {
705 i = codvec[k]; /* read pulse position */
706 j = dn_sign[i]; /* read sign */
707
708 /* index = pos/5 */
709 /* index = mult(i, 6554, pOverflow); */
710 index = (Word16)(((Word32) i * 6554) >> 15);
711
712 /* track = pos%5 */
713 /* s = L_mult(index, 5, pOverflow); */
714 s = ((Word32) index * 5) << 1;
715
716 /* s = L_shr(s, 1, pOverflow); */
717 s >>= 1;
718
719 /* track = sub(i, (Word16) s, pOverflow); */
720 track = i - (Word16) s;
721
722 if (track == 1)
723 {
724 /* index = shl(index, 4, pOverflow); */
725 index <<= 4;
726 }
727 else if (track == 2)
728 {
729 track = 2;
730
731 /* index = shl(index, 8, pOverflow); */
732 index <<= 8;
733 }
734 else if (track == 3)
735 {
736 track = 1;
737
738 /* index = shl(index, 4, pOverflow); */
739 index <<= 4;
740
741 /* index = add(index, 8, pOverflow); */
742 index += 8;
743 }
744 else if (track == 4)
745 {
746 track = 2;
747
748 /* index = shl(index, 8, pOverflow); */
749 index <<= 8;
750
751 /* index = add(index, 128, pOverflow); */
752 index += 128;
753 }
754
755 if (j > 0)
756 {
757 cod[i] = 8191;
758 _sign[k] = 32767;
759
760 /* track = shl(1, track, pOverflow); */
761 track = 1 << track;
762
763 /* rsign = add(rsign, track, pOverflow); */
764 rsign += track;
765 }
766 else
767 {
768 cod[i] = -8192;
769 _sign[k] = (Word16) - 32768L;
770 }
771
772 /* indx = add(indx, index, pOverflow); */
773 indx += index;
774 }
775 *sign = rsign;
776
777 p0 = h - codvec[0];
778 p1 = h - codvec[1];
779 p2 = h - codvec[2];
780
781 for (i = 0; i < L_CODE; i++)
782 {
783 s = 0;
784 s =
785 L_mac(
786 s,
787 *p0++,
788 _sign[0],
789 pOverflow);
790
791 s =
792 L_mac(
793 s,
794 *p1++,
795 _sign[1],
796 pOverflow);
797
798 s =
799 L_mac(
800 s,
801 *p2++,
802 _sign[2],
803 pOverflow);
804
805 y[i] =
806 pv_round(
807 s,
808 pOverflow);
809 }
810
811 return indx;
812 }
813
814
815
816
817
818
819
820