updated top-level README and version_decl for V4.5 (#1847)
[WRF.git] / var / external / wavelet / awaprogs / chap05 / qf.c
blobacf20baef25c88c7ee5ed76b65d5177834e2be6e
1 /*
2 * These functions calculate the values for quadrature mirror filter
3 * coefficient arrays.
5 * Copyright (C) 1991--94 Wickerhauser Consulting. All Rights Reserved.
6 * May be freely copied for noncommercial use. See
7 * ``Adapted Wavelet Analysis from Theory to Software'' ISBN 1-56881-041-5
8 * by Mladen Victor Wickerhauser [AK Peters, Ltd., Wellesley, Mass., 1994]
9 *
12 #include <assert.h>
13 #include <stdlib.h>
14 #include "real.h"
15 #include "common.h"
16 #include "qf.h" /* Data structs and function prototypes */
17 #include "oqfs.h" /* Orthogonal filter coefficients. */
19 /********************************************************************
20 * mkpqf()
22 * Function `mkpqf()' returns a pointer to a `pqf' data structure
23 * containing the coefficients, length and the pre-periodized filter
24 * named by the input parameters.
26 * Calling sequence:
27 * mkpqf( coefs, alpha, omega, flags )
29 * Inputs:
30 * (const real *)coefs These are the filter coefficients,
31 * assumed to be given in the array
32 * `coefs[0],...,coefs[omega-alpha]'
33 * are the only nonzero values.
35 * (int)alpha These are to be the first and last valid
36 * (int)omega indices of the pqf->f struct member.
38 * (int)flags This is reserved for later uses, such as
39 * indicating when to generate a full QF
40 * sequence from just one symmetric half.
42 * Return value:
43 * (pqf *)mkpqf The return value is a pointer to a newly
44 * allocated pqf struct containing `coefs[]',
45 * `alpha', `omega', and the preperiodized
46 * version of `coefs[]'.
47 * Assumptions:
48 * (1) Conventional indexing: `alpha <= 0 <= omega'.
50 extern pqf *
51 mkpqf(
52 const real *coefs, /* Original filter coefficients. */
53 int alpha, /* Least valid index of `?->f[]'. */
54 int omega, /* Greatest valid index of `?->f[]'. */
55 int flags) /* Reserved for future use. */
57 pqf *qm;
58 int M;
60 assert(alpha <= 0); /* Conventional indexing. */
61 assert(0 <= omega); /* Conventional indexing. */
63 qm = (pqf *)calloc(1,sizeof(pqf)); assert(qm);
64 qm->alpha = alpha;
65 qm->omega = omega;
66 qm->f = coefs-alpha;
67 M = IFH( omega-alpha );
68 qm->fp = (real *)calloc( PQFL(M), sizeof(real)); assert(qm->fp);
69 qfcirc( qm->fp, qm->f, alpha, omega );
71 qm->center = coe( qm->f, alpha, omega );
72 qm->deviation = lphdev( qm->f, alpha, omega );
73 return(qm);
76 /********************************************************************
77 * qf()
79 * Function `qf()' returns a pointer to a `pqf' data structure
80 * containing the coefficients, name, length and kind of the filter
81 * named by the input parameters.
83 * Calling sequence:
84 * qf( name, range, kind )
86 * Inputs:
87 * (const char *)name This is the name of the filter, specified as
88 * at least the first letter of "Beylkin",
89 * "Coifman", "Vaidyanathan", or "Daubechies",
90 * written as a string (enclosed in " marks).
91 * Case is ignored, only the first letter
92 * matters, and "Standard" is an alias for "D".
94 * (int)range This is the length of the requested filter. Allowed
95 * values depend on what `name' is.
97 * (int)kind If kind==LOW_PASS_QF, qf() returns the summing or
98 * low-pass filter `pqf' structure.
99 * If kind==HIGH_PASS_QF, qf() returns the differencing
100 * or high-pass filter `pqf' structure.
102 * Return value:
103 * (pqf *)qf If a `name'd filter of the requested `range' and
104 * `kind' is listed, then the return value is
105 * a pointer to a newly-allocated pqf struct
106 * specifying a conventionally-indexed filter
107 * to be used for convolution-decimation.
108 * Otherwise, the returned pointer is NULL.
111 extern pqf *
112 qf( /* Coefficient struct or NULL pointer. */
113 const char *name, /* String "B", "C", "D", or "V". */
114 int range, /* Length of coefficient array. */
115 int kind) /* LOW_PASS_QF or HIGH_PASS_QF. */
117 pqf *qm;
119 /* These macros call `mkpqf()' with the right arguments: */
120 #define MKMKPQF(n, sd) mkpqf( n##sd##oqf, n##sd##alpha, n##sd##omega, 0 )
121 #define SETSDPQF(n, k) ( k==LOW_PASS_QF ) ? MKMKPQF(n, s) : MKMKPQF(n, d)
123 qm = 0; /* Return NULL pointer if unsuccessful. */
125 /* Choose an orthogonal filter based on the first letter of
126 * the filter name: `name' argument starts with B, C, D, V
128 switch( name[0] ) {
130 case 'b':
131 case 'B':
132 /* Beylkin filters.
134 * Here are the coefficients for Gregory BEYLKIN'S wave packets.
136 switch( range )
138 case 18: qm = SETSDPQF( b18, kind ); break;
139 default: break; /* Fall out: the length is unavailable. */
141 break; /* Beylkin type. */
143 case 'c':
144 case 'C':
145 /* Coiflet filters.
147 * Here are the coefficients for COIFLETS with respectively
148 * 2, 4, 6, 8 and 10 moments vanishing for phi. Filter Q has
149 * range/3 moments vanishing. Filter P has range/3 moments
150 * vanishing with the appropriate shift.
152 switch( range )
154 case 6: qm = SETSDPQF( c06, kind ); break;
155 case 12: qm = SETSDPQF( c12, kind ); break;
156 case 18: qm = SETSDPQF( c18, kind ); break;
157 case 24: qm = SETSDPQF( c24, kind ); break;
158 case 30: qm = SETSDPQF( c30, kind ); break;
159 default: break; /* Fall out: the length is unavailable. */
161 break; /* Coifman type. */
163 case 's':
164 case 'S': /* STANDARD filters, in old terminology. */
165 case 'd':
166 case 'D':
167 /* Daubechies filters.
169 * Initialize quadrature mirror filters P,Q of length 'range' with
170 * smooth limits and minimal phase, as in DAUBECHIES:
172 switch( range )
174 case 2: qm = SETSDPQF( d02, kind ); break;
175 case 4: qm = SETSDPQF( d04, kind ); break;
176 case 6: qm = SETSDPQF( d06, kind ); break;
177 case 8: qm = SETSDPQF( d08, kind ); break;
178 case 10: qm = SETSDPQF( d10, kind ); break;
179 case 12: qm = SETSDPQF( d12, kind ); break;
180 case 14: qm = SETSDPQF( d14, kind ); break;
181 case 16: qm = SETSDPQF( d16, kind ); break;
182 case 18: qm = SETSDPQF( d18, kind ); break;
183 case 20: qm = SETSDPQF( d20, kind ); break;
184 default: break; /* Fall out: the length is unavailable. */
186 break; /* Standard or Daubechies type. */
188 case 'v':
189 case 'V':
190 /* Vaidyanathan filters
192 * The following coefficients correspond to one of the filters
193 * constructed by Vaidyanathan (Filter #24B from his paper
194 * in IEEE Trans. ASSP Vol.36, pp 81-94 (1988). These coefficients
195 * give an exact reconstruction scheme, but they don't satisfy ANY
196 * moment condition (not even the normalization : the sum of the c_n
197 * is close to 1, but not equal to 1). The function one obtains after
198 * iterating the reconstruction procedure 9 times looks continuous,
199 * but is of course not differentiable. It would be interesting to
200 * see how such a filter performs. It has been optimized, for its
201 * filter length, for the standard requirements that speech people
202 * impose.
204 switch( range )
206 case 24: qm = SETSDPQF( v24, kind ); break;
207 default: break; /* Fall out: the length is unavailable. */
209 break; /* Vaidyanathan type. */
211 default: break; /* Fall out: the filter is unavailable. */
213 return(qm);
216 /*******************************************************************
217 * coe()
219 * Compute the center-of-energy for a sequence.
221 * Basic algorithm:
222 * center = ( Sum_k k*in[x]^2 ) / (Sum_k in[k]^2 )
224 * Calling sequence:
225 * coe( in, alpha, omega )
227 * Inputs:
228 * (const real *)in The sequence is `in[alpha],...,in[omega]'
230 * (int)alpha These are to be the first and last
231 * (int)omega valid indices of the array `in[]'.
233 * Output:
234 * (real)coe This is in the interval `[alpha, omega]'.
236 * Assumptions:
237 * (1) Conventional indexing: `alpha <= 0 <= omega'.
239 extern real
240 coe( /* Center of energy. */
241 const real *in, /* Sequence of coefficients. */
242 int alpha, /* First valid `in[]' index. */
243 int omega) /* Last valid `in[]' index. */
245 real center, energy;
246 int k;
248 assert(alpha <= 0); /* Conventional indexing. */
249 assert(0 <= omega); /* Conventional indexing. */
251 center = 0; energy = 0;
252 for( k=alpha; k<=omega; k++)
254 center += k*in[k]*in[k];
255 energy += in[k]*in[k];
257 if( energy>0 ) center /= energy;
258 return(center);
261 /*******************************************************************
262 * lphdev()
264 * Compute the maximum deviation from linear phase of the
265 * convolution-decimation operator associated to a sequence.
266 * Basic algorithm:
267 * Sum_{x>0} (-1)^x Sum_k k*in[k-x]*in[k+x]
268 * deviation = 2 * ----------------------------------------
269 * Sum_k in[k]^2
271 * Calling sequence:
272 * lphdev( in, alpha, omega )
274 * Inputs:
275 * (const real *)in The sequence is `in[alpha],...,in[omega]'
277 * (int)alpha These are to be the first and last valid
278 * (int)omega indices of the `pqf->f[]' struct member.
280 * Output:
281 * (real)lphdev This is the absolute value of the maximum.
283 * Assumptions:
284 * (1) Conventional indexing: `alpha <= 0 <= omega'.
286 extern real
287 lphdev( /* Center of energy. */
288 const real *in, /* Sequence of coefficients. */
289 int alpha, /* First valid `in[]' index. */
290 int omega) /* Last valid `in[]' index. */
292 real energy, fx, deviation;
293 int k, x, sgn;
295 assert(alpha <= 0); /* Conventional indexing. */
296 assert(0 <= omega); /* Conventional indexing. */
298 /* First compute the sum of the squares of the sequence elements: */
299 energy = 0;
300 for( k=alpha; k<omega; k++) energy += in[k]*in[k];
302 /* If the sum of the squares in nonzero, compute the deviation: */
303 deviation = 0;
304 if( energy>0 )
306 sgn= -1;
307 for( x=1; x <= (omega-alpha)/2; x++ )
309 fx = 0;
310 for( k=x+alpha; k<=omega-x; k++ )
312 fx += k*in[k-x]*in[k+x];
314 deviation += sgn*fx;
315 sgn = -sgn;
317 deviation = absval(deviation);
318 deviation /= energy; /* Normalize. */
319 deviation *= 2; /* Final factor from the formula. */
321 /* If `energy==0' then `deviation' is trivially 0 */
323 return(deviation);
326 /***************************************************************
327 * periodize()
329 * Periodize an array into a shorter-length array.
331 * Calling sequence and basic algorithm:
333 * periodize(FQ, Q, F, ALPHA, OMEGA)
334 * For K = 0 to Q-1
335 * Let FQ[K] = 0
336 * Let J = (ALPHA-K)/Q
337 * While K+J*Q <= OMEGA
338 * FQ[K] += F[K+J*Q]
339 * J += 1
341 * Inputs:
342 * (real *)fq Preallocated array of length `q'.
343 * (int)q This is the period of `fq[]'.
344 * (const real *)f This array holds the original function.
345 * (int)alpha These are to be the first and last valid
346 * (int)omega indices of the array `f[]'.
348 * Output:
349 * (real *)fq The array `fq[]' is assigned as follows:
350 * fq[k] = f[k+j0*q]+...+f[k+j1*q],
351 * k = 0, 1, ..., q-1;
352 * j0 = ceil[(alpha-k)/q];
353 * j1 = floor[(omega-k)/q].
355 * Assumptions:
356 * (1) `omega-alpha >= q > 0',
357 * (2) `alpha <= 0 <= omega'
359 static void
360 periodize(
361 real *fq, /* Preallocated output array. */
362 int q, /* Length of `fq[]'. */
363 const real *f, /* Input array. */
364 int alpha, /* First valid `f[]' index. */
365 int omega) /* Last valid `f[]' index. */
367 int j, k;
369 assert(q>0); /* Nontrivial period. */
370 assert(q<=omega-alpha); /* Periodization needed. */
371 assert(alpha <= 0); /* Conventional indexing. */
372 assert(0 <= omega); /* Conventional indexing. */
374 for(k=0; k<q; k++)
376 fq[k] = 0;
377 j = (alpha-k)/q; /* `j==ceil((alpha-k)/q)' */
378 while( (k+j*q) <= omega )
380 fq[k] += f[k+j*q];
381 j++;
384 return;
387 /***************************************************************
388 * qfcirc()
390 * This function computes the periodized filter coefficients
391 * associated to the input array of quadrature mirror filter
392 * coefficients, for lengths 2, 4, 6,... It then fills an array
393 * with these periodized coefficients, duplicating some of them
394 * to facilitate circular convolution. If the input array is
395 * f[alpha], f[alpha+1], ..., f[omega],
396 * and M is the largest integer satisfying `2M<=omega-alpha',
397 * then the output array is the concatenation of:
399 * Start Contents End
400 * ----- -------------------------------------------------- -----
401 * 0 f2[0],f2[1],f2[0],f2[1]; 3
402 * 4 f4[0],f4[1],f4[2],f4[3],f4[0],f4[1],f4[2],f4[3]; 11
403 * 12 f6[0],f6[1],f6[2],...,f6[5],f6[0],f6[1],...,f6[5]; 23
404 * 24 f8[0],f8[1],f8[2],...,f8[7],f8[0],f8[1],...,f8[7]; 39
405 * . ... ... ... ; .
406 * S(m-1) f{2m}[0],...,f{2m}[2m-1],f{2m}[0],...,f{2m}[2m-1]; S(m)-1
407 * . ... ... ... ; .
408 * S(M-1) f{2M}[0],...,f{2M}[2M-1],f{2M}[0],...,f{2M}[2M-1]; S(M)-1
410 * where S(m)= 4+8+16+...+ 4(m-1) = 2m(m-1) gives the
411 * starting index of the m-th segment.
413 * The "midpoint" or "origin" of the m-th periodic subarray is:
414 * PQFO(m) = S(m-1)+2m = 2m*m.
416 * The total length of concatenated periodic subarrays `1,...,M' is
417 * PQFL(M) = S(M-1)+4M = 2M*(M+1).
419 * Calling sequence and basic algorithm:
421 * qfcirc(FP, F, ALPHA, OMEGA)
422 * Let M = IFH(omega-alpha)
423 * For N = 1 to M
424 * Let Q = 2*N
425 * Let FQ = FP + PQFO(N)
426 * periodize( FQ, Q, F, ALPHA, OMEGA )
427 * For K = 0 to Q-1
428 * Let FQ[K-Q] = FQ[K]
430 * Inputs:
431 * (real *)fp This must point to a preallocated array
432 * with at least `PQFL(M)' memory
433 * locations. This function call fills
434 * those locations, beginning with 0.
436 * (const real *)f This is an array of quadrature mirror
437 * filter coefficients.
439 * (int)alpha These are to be the first and last valid
440 * (int)omega indices of the array `f[]'.
442 * Output:
443 * (real *)fp This array is filled with periodized,
444 * partially duplicated arrays with
445 * lengths 4, 8, ..., 4M.
447 * Assumptions:
448 * (1) Conventional indexing: `alpha <= 0 <= omega'.
450 extern void
451 qfcirc(
452 real *fp, /* Preallocated output array */
453 const real *f, /* Filter coefficients */
454 int alpha, /* First valid `f[]' index */
455 int omega) /* Last valid `f[]' index */
457 int k, m, M, q;
458 real *fq;
460 assert(alpha <= 0); /* Conventional indexing */
461 assert(0 <= omega); /* Conventional indexing */
463 M = IFH(omega-alpha); /* Max with `2*M <= omega-alpha' */
465 for( m=1; m<=M; m++ )
467 q = 2*m;
468 fq = fp+PQFO(m);
469 periodize( fq, q, f, alpha, omega);
470 for( k=0; k<q; k++ )
471 fq[k-q] = fq[k];
473 return;