blob: 85270f5c0a7c823d78e2f46e329c876703ed45d6 [file] [log] [blame]
Jean-Marc Valin41af4212007-11-30 18:35:37 +11001/* (C) 2007 Jean-Marc Valin, CSIRO
2*/
3/*
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
15 - Neither the name of the Xiph.org Foundation nor the names of its
16 contributors may be used to endorse or promote products derived from
17 this software without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*/
31
32#include <math.h>
33#include <stdlib.h>
Jean-Marc Valin29ccab82007-12-06 15:39:38 +110034#include "cwrs.h"
Jean-Marc Valin9cace642007-12-06 17:44:09 +110035#include "vq.h"
Jean-Marc Valin41af4212007-11-30 18:35:37 +110036
Jean-Marc Valin41af4212007-11-30 18:35:37 +110037
38/* Improved algebraic pulse-base quantiser. The signal x is replaced by the sum of the pitch
39 a combination of pulses such that its norm is still equal to 1. The only difference with
40 the quantiser above is that the search is more complete. */
Jean-Marc Valin46014ca2007-12-14 13:47:04 +110041void alg_quant(float *x, float *W, int N, int K, float *p, float alpha, ec_enc *enc)
Jean-Marc Valin41af4212007-11-30 18:35:37 +110042{
Jean-Marc Valin4a897682007-12-12 00:45:15 +110043 int L = 3;
Jean-Marc Valin41af4212007-11-30 18:35:37 +110044 //float tata[200];
Jean-Marc Valinfe419832008-02-12 15:05:01 +110045 float _y[L][N];
46 int _iy[L][N];
Jean-Marc Valin41af4212007-11-30 18:35:37 +110047 //float tata2[200];
Jean-Marc Valinfe419832008-02-12 15:05:01 +110048 float _ny[L][N];
49 int _iny[L][N];
50 float *(ny[L]), *(y[L]);
51 int *(iny[L]), *(iy[L]);
Jean-Marc Valin41af4212007-11-30 18:35:37 +110052 int i, j, m;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +110053 int pulsesLeft;
Jean-Marc Valin41af4212007-11-30 18:35:37 +110054 float xy[L], nxy[L];
55 float yy[L], nyy[L];
56 float yp[L], nyp[L];
57 float best_scores[L];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +110058 float Rpp=0, Rxp=0;
Jean-Marc Valin41af4212007-11-30 18:35:37 +110059 float gain[L];
60 int maxL = 1;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +110061
Jean-Marc Valinfe419832008-02-12 15:05:01 +110062 for (m=0;m<L;m++)
63 {
64 ny[m] = _ny[m];
65 iny[m] = _iny[m];
66 y[m] = _y[m];
67 iy[m] = _iy[m];
68 }
69
Jean-Marc Valin41af4212007-11-30 18:35:37 +110070 for (j=0;j<N;j++)
71 Rpp += p[j]*p[j];
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +110072 //if (Rpp>.01)
73 // alpha = (1-sqrt(1-Rpp))/Rpp;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +110074 for (j=0;j<N;j++)
75 Rxp += x[j]*p[j];
Jean-Marc Valin41af4212007-11-30 18:35:37 +110076 for (m=0;m<L;m++)
77 for (i=0;i<N;i++)
78 y[m][i] = 0;
79
80 for (m=0;m<L;m++)
81 for (i=0;i<N;i++)
82 ny[m][i] = 0;
83
84 for (m=0;m<L;m++)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +110085 for (i=0;i<N;i++)
86 iy[m][i] = iny[m][i] = 0;
87
88 for (m=0;m<L;m++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +110089 xy[m] = yy[m] = yp[m] = gain[m] = 0;
90
Jean-Marc Valin846d4e22008-02-12 13:48:48 +110091 pulsesLeft = K;
92 while (pulsesLeft > 0)
Jean-Marc Valin41af4212007-11-30 18:35:37 +110093 {
Jean-Marc Valin846d4e22008-02-12 13:48:48 +110094 int pulsesAtOnce=1;
Jean-Marc Valincab576e2008-02-12 17:21:14 +110095 int Lupdate = L;
Jean-Marc Valin41af4212007-11-30 18:35:37 +110096 int L2 = L;
Jean-Marc Valincab576e2008-02-12 17:21:14 +110097 pulsesAtOnce = pulsesLeft/N;
98 if (pulsesAtOnce<1)
99 pulsesAtOnce = 1;
100 if (pulsesLeft-pulsesAtOnce > 3 || N > 30)
101 Lupdate = 1;
102 //printf ("%d %d %d/%d %d\n", Lupdate, pulsesAtOnce, pulsesLeft, K, N);
103 L2 = Lupdate;
104 if (L2>maxL)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100105 {
106 L2 = maxL;
107 maxL *= N;
108 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100109
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100110 for (m=0;m<L;m++)
111 best_scores[m] = -1e10;
112
113 for (m=0;m<L2;m++)
114 {
115 for (j=0;j<N;j++)
116 {
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100117 int sign;
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100118 //if (x[j]>0) sign=1; else sign=-1;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100119 for (sign=-1;sign<=1;sign+=2)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100120 {
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100121 /* All pulses at one location must have the same size */
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100122 if (iy[m][j]*sign < 0 || (x[j]*sign<0 && pulsesLeft>((K+1)>>1)))
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100123 continue;
124 //fprintf (stderr, "%d/%d %d/%d %d/%d\n", i, K, m, L2, j, N);
125 float tmp_xy, tmp_yy, tmp_yp;
126 float score;
127 float g;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100128 float s = sign*pulsesAtOnce;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100129
130 /* Updating the sums the the new pulse(s) */
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100131 tmp_xy = xy[m] + s*x[j] - alpha*s*p[j]*Rxp;
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100132 tmp_yy = yy[m] + 2*s*y[m][j] + s*s +s*s*alpha*alpha*p[j]*p[j]*Rpp - 2*alpha*s*p[j]*yp[m] - 2*s*s*alpha*p[j]*p[j];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100133 tmp_yp = yp[m] + s*p[j] *(1-alpha*Rpp);
134 g = (sqrt(tmp_yp*tmp_yp + tmp_yy - tmp_yy*Rpp) - tmp_yp)/tmp_yy;
135 score = 2*g*tmp_xy - g*g*tmp_yy;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100136
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100137 if (score>best_scores[Lupdate-1])
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100138 {
139 int k, n;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100140 int id = Lupdate-1;
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100141 float *tmp_ny;
142 int *tmp_iny;
143
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100144 tmp_ny = ny[Lupdate-1];
145 tmp_iny = iny[Lupdate-1];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100146 while (id > 0 && score > best_scores[id-1])
147 id--;
148
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100149 for (k=Lupdate-1;k>id;k--)
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100150 {
151 nxy[k] = nxy[k-1];
152 nyy[k] = nyy[k-1];
153 nyp[k] = nyp[k-1];
154 //fprintf(stderr, "%d %d \n", N, k);
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100155 ny[k] = ny[k-1];
156 iny[k] = iny[k-1];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100157 gain[k] = gain[k-1];
158 best_scores[k] = best_scores[k-1];
159 }
160
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100161 ny[id] = tmp_ny;
162 iny[id] = tmp_iny;
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100163
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100164 nxy[id] = tmp_xy;
165 nyy[id] = tmp_yy;
166 nyp[id] = tmp_yp;
167 gain[id] = g;
168 for (n=0;n<N;n++)
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100169 ny[id][n] = y[m][n] - alpha*s*p[j]*p[n];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100170 ny[id][j] += s;
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100171
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100172 for (n=0;n<N;n++)
173 iny[id][n] = iy[m][n];
174 if (s>0)
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100175 iny[id][j] += pulsesAtOnce;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100176 else
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100177 iny[id][j] -= pulsesAtOnce;
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100178 best_scores[id] = score;
179 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100180 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100181 }
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100182
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100183 }
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100184 int k;
Jean-Marc Valincab576e2008-02-12 17:21:14 +1100185 for (k=0;k<Lupdate;k++)
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100186 {
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100187 float *tmp_ny;
188 int *tmp_iny;
189
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100190 xy[k] = nxy[k];
191 yy[k] = nyy[k];
192 yp[k] = nyp[k];
Jean-Marc Valinfe419832008-02-12 15:05:01 +1100193
194 tmp_ny = ny[k];
195 ny[k] = y[k];
196 y[k] = tmp_ny;
197 tmp_iny = iny[k];
198 iny[k] = iy[k];
199 iy[k] = tmp_iny;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100200 }
Jean-Marc Valin846d4e22008-02-12 13:48:48 +1100201 pulsesLeft -= pulsesAtOnce;
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100202 }
203
Jean-Marc Valinac1e03d2008-02-12 23:00:18 +1100204 if (0) {
205 float err=0;
206 for (i=0;i<N;i++)
207 err += (x[i]-gain[0]*y[0][i])*(x[i]-gain[0]*y[0][i]);
208 //if (N<=10)
209 //printf ("%f %d %d\n", err, K, N);
210 }
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100211 for (i=0;i<N;i++)
212 x[i] = p[i]+gain[0]*y[0][i];
Jean-Marc Valin1e7087e2007-12-04 13:05:43 +1100213 if (0) {
214 float E=1e-15;
215 int ABS = 0;
216 for (i=0;i<N;i++)
217 ABS += abs(iy[0][i]);
218 //if (K != ABS)
219 // printf ("%d %d\n", K, ABS);
220 for (i=0;i<N;i++)
221 E += x[i]*x[i];
222 //printf ("%f\n", E);
223 E = 1/sqrt(E);
224 for (i=0;i<N;i++)
225 x[i] *= E;
226 }
Jean-Marc Valin29ccab82007-12-06 15:39:38 +1100227 int comb[K];
228 int signs[K];
Jean-Marc Valin70c8ffd2007-12-07 14:20:01 +1100229 //for (i=0;i<N;i++)
230 // printf ("%d ", iy[0][i]);
Jean-Marc Valin29ccab82007-12-06 15:39:38 +1100231 pulse2comb(N, K, comb, signs, iy[0]);
Jean-Marc Valinf8db8002007-12-11 14:52:56 +1100232 ec_enc_uint64(enc,icwrs64(N, K, comb, signs),ncwrs64(N, K));
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100233 //printf ("%llu ", icwrs64(N, K, comb, signs));
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100234 /* Recompute the gain in one pass to reduce the encoder-decoder mismatch
Jean-Marc Valin636f5c82008-02-12 17:40:27 +1100235 due to the recursive computation used in quantisation.
236 Not quite sure whether we need that or not */
Jean-Marc Valina4833ff2008-01-10 15:34:00 +1100237 if (1) {
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100238 float Ryp=0;
239 float Rpp=0;
240 float Ryy=0;
241 float g=0;
242 for (i=0;i<N;i++)
243 Rpp += p[i]*p[i];
244
245 for (i=0;i<N;i++)
246 Ryp += iy[0][i]*p[i];
247
248 for (i=0;i<N;i++)
249 y[0][i] = iy[0][i] - alpha*Ryp*p[i];
250
Jean-Marc Valin4a897682007-12-12 00:45:15 +1100251 Ryp = 0;
252 for (i=0;i<N;i++)
253 Ryp += y[0][i]*p[i];
254
255 for (i=0;i<N;i++)
256 Ryy += y[0][i]*y[0][i];
257
258 g = (sqrt(Ryp*Ryp + Ryy - Ryy*Rpp) - Ryp)/Ryy;
259
260 for (i=0;i<N;i++)
261 x[i] = p[i] + g*y[0][i];
262
263 }
264
Jean-Marc Valin41af4212007-11-30 18:35:37 +1100265}
266
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100267void alg_unquant(float *x, int N, int K, float *p, float alpha, ec_dec *dec)
268{
269 int i;
270 celt_uint64_t id;
271 int comb[K];
272 int signs[K];
273 int iy[N];
274 float y[N];
275 float Rpp=0, Ryp=0, Ryy=0;
276 float g;
Jean-Marc Valin25298f22007-12-03 15:24:11 +1100277
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100278 id = ec_dec_uint64(dec, ncwrs64(N, K));
Jean-Marc Valina76a0b22008-01-17 22:43:05 +1100279 //printf ("%llu ", id);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100280 cwrsi64(N, K, id, comb, signs);
281 comb2pulse(N, K, iy, comb, signs);
282 //for (i=0;i<N;i++)
283 // printf ("%d ", iy[i]);
284 for (i=0;i<N;i++)
285 Rpp += p[i]*p[i];
286
287 for (i=0;i<N;i++)
288 Ryp += iy[i]*p[i];
289
290 for (i=0;i<N;i++)
291 y[i] = iy[i] - alpha*Ryp*p[i];
292
293 /* Recompute after the projection (I think it's right) */
294 Ryp = 0;
295 for (i=0;i<N;i++)
296 Ryp += y[i]*p[i];
297
298 for (i=0;i<N;i++)
299 Ryy += y[i]*y[i];
300
301 g = (sqrt(Ryp*Ryp + Ryy - Ryy*Rpp) - Ryp)/Ryy;
302
303 for (i=0;i<N;i++)
304 x[i] = p[i] + g*y[i];
305}
306
307
308static const float pg[11] = {1.f, .75f, .65f, 0.6f, 0.6f, .6f, .55f, .55f, .5f, .5f, .5f};
309
310void intra_prediction(float *x, float *W, int N, int K, float *Y, float *P, int B, int N0, ec_enc *enc)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100311{
312 int i,j;
313 int best=0;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100314 float best_score=0;
315 float s = 1;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100316 int sign;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100317 float E;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100318 int max_pos = N0-N/B;
319 if (max_pos > 32)
320 max_pos = 32;
321
322 for (i=0;i<max_pos*B;i+=B)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100323 {
324 int j;
325 float xy=0, yy=0;
326 float score;
327 for (j=0;j<N;j++)
328 {
329 xy += x[j]*Y[i+j];
330 yy += Y[i+j]*Y[i+j];
331 }
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100332 score = xy*xy/(.001+yy);
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100333 if (score > best_score)
334 {
335 best_score = score;
336 best = i;
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100337 if (xy>0)
338 s = 1;
339 else
340 s = -1;
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100341 }
342 }
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100343 if (s<0)
344 sign = 1;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100345 else
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100346 sign = 0;
347 //printf ("%d %d ", sign, best);
348 ec_enc_uint(enc,sign,2);
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100349 ec_enc_uint(enc,best/B,max_pos);
Jean-Marc Valin50d11162007-12-03 14:34:52 +1100350 //printf ("%d %f\n", best, best_score);
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100351
352 float pred_gain;
353 if (K>10)
354 pred_gain = pg[10];
355 else
356 pred_gain = pg[K];
357 E = 1e-10;
358 for (j=0;j<N;j++)
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100359 {
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100360 P[j] = s*Y[best+j];
361 E += P[j]*P[j];
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100362 }
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100363 E = pred_gain/sqrt(E);
364 for (j=0;j<N;j++)
365 P[j] *= E;
366 if (K>0)
367 {
368 for (j=0;j<N;j++)
369 x[j] -= P[j];
370 } else {
371 for (j=0;j<N;j++)
372 x[j] = P[j];
373 }
374 //printf ("quant ");
375 //for (j=0;j<N;j++) printf ("%f ", P[j]);
376
Jean-Marc Valin4841a0a2007-12-03 13:54:30 +1100377}
Jean-Marc Valinfc08d0a2007-12-07 13:26:15 +1100378
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100379void intra_unquant(float *x, int N, int K, float *Y, float *P, int B, int N0, ec_dec *dec)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100380{
Jean-Marc Valin11f01722007-12-09 01:19:36 +1100381 int j;
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100382 int sign;
383 float s;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100384 int best;
385 float E;
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100386 int max_pos = N0-N/B;
387 if (max_pos > 32)
388 max_pos = 32;
389
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100390 sign = ec_dec_uint(dec, 2);
391 if (sign == 0)
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100392 s = 1;
393 else
394 s = -1;
395
Jean-Marc Valin8f0f4b92008-02-11 13:52:44 +1100396 best = B*ec_dec_uint(dec, max_pos);
Jean-Marc Valin0aa39032007-12-07 15:09:58 +1100397 //printf ("%d %d ", sign, best);
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100398
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100399 float pred_gain;
400 if (K>10)
401 pred_gain = pg[10];
402 else
403 pred_gain = pg[K];
404 E = 1e-10;
405 for (j=0;j<N;j++)
406 {
407 P[j] = s*Y[best+j];
408 E += P[j]*P[j];
409 }
410 E = pred_gain/sqrt(E);
411 for (j=0;j<N;j++)
412 P[j] *= E;
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100413 if (K==0)
414 {
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100415 for (j=0;j<N;j++)
Jean-Marc Valin0d227d82007-12-31 16:12:12 +1100416 x[j] = P[j];
Jean-Marc Valin6e9058a2007-12-07 14:59:06 +1100417 }
418}
Jean-Marc Valin0e20ca02008-02-11 15:33:53 +1100419
420void intra_fold(float *x, int N, int K, float *Y, float *P, int B, int N0)
421{
422 int j;
423 float E;
424
425 E = 1e-10;
426 for (j=0;j<N;j++)
427 {
428 P[j] = Y[j];
429 E += P[j]*P[j];
430 }
431 E = 1.f/sqrt(E);
432 for (j=0;j<N;j++)
433 P[j] *= E;
434 for (j=0;j<N;j++)
435 x[j] = P[j];
436}
437