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 alp0;
407 Word32 alp1;
408
409 psk = -1;
410 alpk = 1;
411
412 for (i = 0; i < NB_PULSE; i++)
413 {
414 *(p_codvec++) = i;
415 }
416
417 for (track1 = 1; track1 < 4; track1 += 2)
418 {
419 for (track2 = 2; track2 < 5; track2 += 2)
420 {
421 /* fix starting position */
422
423 ipos[0] = 0;
424 ipos[1] = track1;
425 ipos[2] = track2;
426
427 /*------------------------------------------------------------------*
428 * main loop: try 3 tracks. *
429 *------------------------------------------------------------------*/
430
431 for (i = 0; i < NB_PULSE; i++)
432 {
433 /*----------------------------------------------------------------*
434 * i0 loop: try 8 positions. *
435 *----------------------------------------------------------------*/
436
437 /* account for ptr. init. (rr[io]) */
438 for (i0 = ipos[0]; i0 < L_CODE; i0 += STEP)
439 {
440 if (dn2[i0] >= 0)
441 {
442 ps0 = dn[i0];
443
444 /* alp0 = L_mult(rr[i0][i0],_1_4, pOverflow); */
445 alp0 = (Word32) rr[i0][i0] << 14;
446
447 /*----------------------------------------------------------------*
448 * i1 loop: 8 positions. *
449 *----------------------------------------------------------------*/
450
451 sq = -1;
452 alp = 1;
453 ps = 0;
454 ix = ipos[1];
455
456 /* initialize 4 index for next loop. */
457 /*-------------------------------------------------------------------*
458 * These index have low complexity address computation because *
459 * they are, in fact, pointers with fixed increment. For example, *
460 * "rr[i0][i2]" is a pointer initialized to "&rr[i0][ipos[2]]" *
461 * and incremented by "STEP". *
462 *-------------------------------------------------------------------*/
463
464 for (i1 = ipos[1]; i1 < L_CODE; i1 += STEP)
465 {
466 /* idx increment = STEP */
467 /* ps1 = add(ps0, dn[i1], pOverflow); */
468 ps1 = ps0 + dn[i1];
469
470 /* alp1 = alp0 + rr[i0][i1] + 1/2*rr[i1][i1]; */
471
472 /* idx incr = STEP */
473 /* alp1 = L_mac(alp0, rr[i1][i1], _1_4, pOverflow); */
474 alp1 = alp0 + ((Word32) rr[i1][i1] << 14);
475
476 /* idx incr = STEP */
477 /* alp1 = L_mac(alp1, rr[i0][i1], _1_2, pOverflow); */
478 alp1 += (Word32) rr[i0][i1] << 15;
479
480 /* sq1 = mult(ps1, ps1, pOverflow); */
481 sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
482
483 /* alp_16 = pv_round(alp1, pOverflow); */
484 alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
485
486 /* s = L_mult(alp, sq1, pOverflow); */
487 s = ((Word32) alp * sq1) << 1;
488
489 /* s = L_msu(s, sq, alp_16, pOverflow); */
490 s -= (((Word32) sq * alp_16) << 1);
491
492 if (s > 0)
493 {
494 sq = sq1;
495 ps = ps1;
496 alp = alp_16;
497 ix = i1;
498 }
499 }
500 i1 = ix;
501
502 /*----------------------------------------------------------------*
503 * i2 loop: 8 positions. *
504 *----------------------------------------------------------------*/
505
506 ps0 = ps;
507
508 /* alp0 = L_mult(alp, _1_4, pOverflow); */
509 alp0 = (Word32) alp << 14;
510
511 sq = -1;
512 alp = 1;
513 ps = 0;
514 ix = ipos[2];
515
516 /* initialize 4 index for next loop (see i1 loop) */
517
518 for (i2 = ipos[2]; i2 < L_CODE; i2 += STEP)
519 {
520 /* index increment = STEP */
521 /* ps1 = add(ps0, dn[i2], pOverflow); */
522 ps1 = ps0 + dn[i2];
523
524 /* alp1 = alp0 + rr[i0][i2] + rr[i1][i2] + 1/2*rr[i2][i2]; */
525
526 /* idx incr = STEP */
527 /* alp1 = L_mac(alp0, rr[i2][i2], _1_16, pOverflow); */
528 alp1 = alp0 + ((Word32) rr[i2][i2] << 12);
529
530 /* idx incr = STEP */
531 /* alp1 = L_mac(alp1, rr[i1][i2], _1_8, pOverflow); */
532 alp1 += (Word32) rr[i1][i2] << 13;
533
534 /* idx incr = STEP */
535 /* alp1 = L_mac(alp1,rr[i0][i2], _1_8, pOverflow); */
536 alp1 += (Word32) rr[i0][i2] << 13;
537
538 /* sq1 = mult(ps1, ps1, pOverflow); */
539 sq1 = (Word16)(((Word32) ps1 * ps1) >> 15);
540
541 /* alp_16 = pv_round(alp1, pOverflow); */
542 alp_16 = (Word16)((alp1 + (Word32) 0x00008000L) >> 16);
543
544 /* s = L_mult(alp, sq1, pOverflow); */
545 s = ((Word32) alp * sq1) << 1;
546
547 /* s = L_msu(s, sq, alp_16, pOverflow); */
548 s -= (((Word32) sq * alp_16) << 1);
549
550 if (s > 0)
551 {
552 sq = sq1;
553 ps = ps1;
554 alp = alp_16;
555 ix = i2;
556 }
557 }
558 i2 = ix;
559
560 /* memorize codevector if this one
561 * is better than the last one.
562 */
563
564 s = L_mult(alpk, sq, pOverflow);
565 //s = ((Word32) alpk * sq) << 1;
566
567 s = L_msu(s, psk, alp, pOverflow);
568 //s -= (((Word32) psk * alp) << 1);
569
570 if (s > 0)
571 {
572 psk = sq;
573 alpk = alp;
574 p_codvec = &codvec[0];
575
576 *(p_codvec++) = i0;
577 *(p_codvec++) = i1;
578 *(p_codvec) = i2;
579 }
580 }
581 }
582 /*----------------------------------------------------------------*
583 * Cyclic permutation of i0, i1 and i2. *
584 *----------------------------------------------------------------*/
585
586 pos = ipos[2];
587 ipos[2] = ipos[1];
588 ipos[1] = ipos[0];
589 ipos[0] = pos;
590 }
591 }
592 }
593 return;
594 }
595
596 /****************************************************************************/
597
598 /*
599 ------------------------------------------------------------------------------
600 FUNCTION NAME: build_code()
601 ------------------------------------------------------------------------------
602 INPUT AND OUTPUT DEFINITIONS
603
604 Inputs:
605 codvec[] Array of type Word16 -- position of pulses
606 dn_sign[] Array of type Word16 -- sign of pulses
607 h[] Array of type Word16 -- impulse response of
608 weighted synthesis filter
609
610 Outputs:
611 cod[] Array of type Word16 -- innovative code vector
612 y[] Array of type Word16 -- filtered innovative code
613 sign[] Array of type Word16 -- sign of 3 pulses
614 pOverflow Pointer to Flag -- set when overflow occurs
615
616 Returns:
617 indx
618
619 Global Variables Used:
620 None
621
622 Local Variables Needed:
623 None
624
625 ------------------------------------------------------------------------------
626 FUNCTION DESCRIPTION
627
628 PURPOSE: Builds the codeword, the filtered codeword and index of the
629 codevector, based on the signs and positions of 3 pulses.
630
631 ------------------------------------------------------------------------------
632 REQUIREMENTS
633
634 None
635
636 ------------------------------------------------------------------------------
637 REFERENCES
638
639 [1] c3_14pf.c, UMTS GSM AMR speech codec, R99 - Version 3.2.0, March 2, 2001
640
641 ------------------------------------------------------------------------------
642 PSEUDO-CODE
643
644 ------------------------------------------------------------------------------
645 RESOURCES USED [optional]
646
647 When the code is written for a specific target processor the
648 the resources used should be documented below.
649
650 HEAP MEMORY USED: x bytes
651
652 STACK MEMORY USED: x bytes
653
654 CLOCK CYCLES: (cycle count equation for this function) + (variable
655 used to represent cycle count for each subroutine
656 called)
657 where: (cycle count variable) = cycle count for [subroutine
658 name]
659
660 ------------------------------------------------------------------------------
661 CAUTION [optional]
662 [State any special notes, constraints or cautions for users of this function]
663
664 ------------------------------------------------------------------------------
665 */
666
667 static Word16
build_code(Word16 codvec[],Word16 dn_sign[],Word16 cod[],Word16 h[],Word16 y[],Word16 sign[],Flag * pOverflow)668 build_code(
669 Word16 codvec[], /* i : position of pulses */
670 Word16 dn_sign[], /* i : sign of pulses */
671 Word16 cod[], /* o : innovative code vector */
672 Word16 h[], /* i : impulse response of weighted synthesis filter */
673 Word16 y[], /* o : filtered innovative code */
674 Word16 sign[], /* o : sign of 3 pulses */
675 Flag *pOverflow /* o : Flag set when overflow occurs */
676 )
677 {
678 Word16 i;
679 Word16 j;
680 Word16 k;
681 Word16 track;
682 Word16 index;
683 Word16 _sign[NB_PULSE];
684 Word16 indx;
685 Word16 rsign;
686
687 Word16 *p0;
688 Word16 *p1;
689 Word16 *p2;
690
691 Word32 s;
692
693 for (i = 0; i < L_CODE; i++)
694 {
695 cod[i] = 0;
696 }
697
698 indx = 0;
699 rsign = 0;
700
701 for (k = 0; k < NB_PULSE; k++)
702 {
703 i = codvec[k]; /* read pulse position */
704 j = dn_sign[i]; /* read sign */
705
706 /* index = pos/5 */
707 /* index = mult(i, 6554, pOverflow); */
708 index = (Word16)(((Word32) i * 6554) >> 15);
709
710 /* track = pos%5 */
711 /* s = L_mult(index, 5, pOverflow); */
712 s = ((Word32) index * 5) << 1;
713
714 /* s = L_shr(s, 1, pOverflow); */
715 s >>= 1;
716
717 /* track = sub(i, (Word16) s, pOverflow); */
718 track = i - (Word16) s;
719
720 if (track == 1)
721 {
722 /* index = shl(index, 4, pOverflow); */
723 index <<= 4;
724 }
725 else if (track == 2)
726 {
727 track = 2;
728
729 /* index = shl(index, 8, pOverflow); */
730 index <<= 8;
731 }
732 else if (track == 3)
733 {
734 track = 1;
735
736 /* index = shl(index, 4, pOverflow); */
737 index <<= 4;
738
739 /* index = add(index, 8, pOverflow); */
740 index += 8;
741 }
742 else if (track == 4)
743 {
744 track = 2;
745
746 /* index = shl(index, 8, pOverflow); */
747 index <<= 8;
748
749 /* index = add(index, 128, pOverflow); */
750 index += 128;
751 }
752
753 if (j > 0)
754 {
755 cod[i] = 8191;
756 _sign[k] = 32767;
757
758 /* track = shl(1, track, pOverflow); */
759 track = 1 << track;
760
761 /* rsign = add(rsign, track, pOverflow); */
762 rsign += track;
763 }
764 else
765 {
766 cod[i] = -8192;
767 _sign[k] = (Word16) - 32768L;
768 }
769
770 /* indx = add(indx, index, pOverflow); */
771 indx += index;
772 }
773 *sign = rsign;
774
775 p0 = h - codvec[0];
776 p1 = h - codvec[1];
777 p2 = h - codvec[2];
778
779 for (i = 0; i < L_CODE; i++)
780 {
781 s = 0;
782 s =
783 L_mac(
784 s,
785 *p0++,
786 _sign[0],
787 pOverflow);
788
789 s =
790 L_mac(
791 s,
792 *p1++,
793 _sign[1],
794 pOverflow);
795
796 s =
797 L_mac(
798 s,
799 *p2++,
800 _sign[2],
801 pOverflow);
802
803 y[i] =
804 pv_round(
805 s,
806 pOverflow);
807 }
808
809 return indx;
810 }
811
812
813
814
815
816
817
818