LAL  7.5.0.1-08ee4f4
CreateIIRFilter.c
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2007 Jolien Creighton, Teviet Creighton
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with with program; see the file COPYING. If not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 * MA 02110-1301 USA
18 */
19 
20 #include <complex.h>
21 #include <lal/LALStdlib.h>
22 #include <lal/LALConstants.h>
23 #include <lal/AVFactories.h>
24 #include <math.h>
25 #include <lal/IIRFilter.h>
26 
27 /**
28  * \addtogroup CreateIIRFilter_c
29  * \author Creighton, T. D.
30  *
31  * \brief Creates IIR filter objects.
32  *
33  * ### Description ###
34  *
35  * These functions create an object <tt>**output</tt> of type
36  * <tt><datatype>IIRFilter</tt>, where <tt><datatype></tt> is \c REAL4 or
37  * \c REAL8. The filter coefficients are computed from the zeroes,
38  * poles, and gain of an input object <tt>*input</tt> of type
39  * \c COMPLEX8ZPGFilter or \c COMPLEX16ZPGFilter, respectively;
40  * the sampling time interval is taken directly from
41  * <tt>input->deltaT</tt>. The ZPG filter should express the factored
42  * transfer function in the \f$z=\exp(2\pi if)\f$ plane. Initially the
43  * output handle must be a valid handle (\c output\f$\neq\f$\c NULL)
44  * but should not point to an existing object
45  * (<tt>*output</tt>=\c NULL)
46  *
47  * ### Algorithm ###
48  *
49  * An IIR filter is a real time-domain filter, which imposes certain
50  * constraints on the zeros, poles, and gain of the filter transfer
51  * function. The function <tt>Create<datatype>IIRFilter()</tt> deals with
52  * the constraints either by aborting if they are not met, or by
53  * adjusting the filter response so that they are met. In the latter
54  * case, warning messages will be issued if the external parameter
55  * \c lalDebugLevel is set to allow such messages. The specific
56  * constraints, and how they are dealt with, are as follows:
57  *
58  * First, the filter must be \e causal; that is, the output at any
59  * time can be generated entirely from the input at previous times. In
60  * practice this means that the number of (finite) poles in the \f$z\f$ plane
61  * must equal or exceed the number of (finite) zeros. If this is not the
62  * case, <tt>Create<datatype>IIRFilter()</tt> will add additional poles at
63  * \f$z=0\f$. Effectively this is just adding a delay to the filter response
64  * in order to make it causal.
65  *
66  * Second, the filter should be \e stable, which means that all poles
67  * should be located on or within the circle \f$|z|=1\f$. This is not
68  * enforced by <tt>Create<datatype>IIRFilter()</tt>, which can be used to
69  * make unstable filters; however, warnings will be issued. (In some
70  * sense the first condition is a special case of this one, since a
71  * transfer function with more zeros than poles actually has
72  * corresponding poles at infinity.)
73  *
74  * Third, the filter must be <em>physically realizable</em>; that is, the
75  * transfer function should expand to a rational function of \f$z\f$ with
76  * real coefficients. Necessary and sufficient conditions for this are
77  * that the gain be real, and that all zeros and poles either be real or
78  * come in complex conjugate pairs. The routine
79  * <tt>Create<datatype>IIRFilter()</tt> enforces this by using only the
80  * real part of the gain, and only the real or positive-imaginary zeros
81  * and poles; it assumes that the latter are paired with
82  * negative-imaginary conjugates. The routine will abort if this
83  * assumption results in a change in the given number of zeros or poles.
84  * If \c lalDebugLevel is set to allow warnings, the routine will
85  * actually check to see that each pair of nonreal poles or zeros are in
86  * fact complex conjugates, and will issue a warning if an unmatched pair
87  * is detected; however, the algorithm will then simply proceed as if the
88  * negative-imaginary points were relocated to the "correct" positions.
89  *
90  * The code associated with the warning messages is potentially rather
91  * cumbersome for production algorithms; therefore, the value of
92  * \c lalDebugLevel is tested before performing any other tests
93  * associated with warning messages.
94  *
95  */
96 /** @{ */
97 
98 /** \see See \ref CreateIIRFilter_c for documentation */
100 {
102  INT4 i; /* Index counter for zeros and poles. */
103  INT4 numZeros; /* The number of zeros. */
104  INT4 numPoles; /* The number of poles. */
105  INT4 numDirect; /* The number of direct filter coefficients. */
106  INT4 numRecurs; /* The number of recursive filter coefficients. */
107  INT4 num; /* An extra counter for error checking. */
108  COMPLEX8 *zeros; /* The zeros of the transfer function. */
109  COMPLEX8 *poles; /* The poles of the transfer function. */
110  REAL4 *direct; /* The direct filter coefficients. */
111  REAL4 *recurs; /* The recursive filter coefficients. */
112  REAL4 *history; /* The filter history. */
113 
114  /* Make sure all the input structures have been initialized. */
115  if ( ! input )
117  if ( ! input->zeros || ! input->poles
118  || ! input->zeros->data || ! input->poles->data )
120 
121  numZeros=input->zeros->length;
122  numPoles=input->poles->length;
123  zeros=input->zeros->data;
124  poles=input->poles->data;
125 
126  /* Check that zeros are appropriately paired. Also, keep track of
127  the number of zeros at z=0, since these will reduce the number of
128  direct coefficients required. */
129  numDirect=1;
130  for(i=0,num=0;i<numZeros;i++)
131  if(cimagf(zeros[i])==0.0){
132  num+=1;
133  if(crealf(zeros[i])==0.0)
134  numDirect-=1;
135  }
136  else if(cimagf(zeros[i])>0.0){
137  num+=2;
138 
140  /* Check to see that another zero is an actual conjugate.
141  This is not a foolproof test, as it can be fooled by
142  multiple zeros at the same location. */
143  INT4 j=0;
144  INT4 k=0;
145  REAL4 x = crealf(zeros[i]) - crealf(zeros[0]);
146  REAL4 y = cimagf(zeros[i]) + cimagf(zeros[0]);
147  REAL4 sep = x*x + y*y;
148  for(j=1;j<numZeros;j++){
149  x=crealf(zeros[i])-crealf(zeros[j]);
150  y=cimagf(zeros[i])+cimagf(zeros[j]);
151  if(sep>x*x+y*y){
152  sep=x*x+y*y;
153  k=j;
154  }
155  }
156  if(sep>LAL_REAL4_EPS){
157  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
158  XLALPrintWarning("Complex zero has no conjugate pair\n");
159  XLALPrintWarning("\tUnmatched zero z_%i = %.8e + i*%.8e\n",i,
160  crealf(zeros[i]),cimagf(zeros[i]));
161  XLALPrintWarning("\tNearest pair z_%i = %.8e + i*%.8e\n",k,
162  crealf(zeros[k]),cimagf(zeros[k]));
163  }
164  }
165  }
166 
167  if ( num != numZeros )
169 
170  /* Check that poles are appropriately paired. Also, keep track of
171  the number of poles at z=0, since these will reduce the number of
172  recursive coefficients required. */
173  numRecurs=1;
174  for(i=0,num=0;i<numPoles;i++)
175  if(cimagf(poles[i])==0.0){
176  num+=1;
177  if(crealf(poles[i])==0.0)
178  numRecurs-=1;
179  }
180  else if(cimagf(poles[i])>0.0){
181  num+=2;
182 
184  /* Check to see that another pole is an actual conjugate.
185  This is not a foolproof test, as it can be fooled by
186  multiple poles at the same location. */
187  INT4 j=0;
188  INT4 k=0;
189  REAL4 x = crealf(poles[i]) - crealf(poles[0]);
190  REAL4 y = cimagf(poles[i]) + cimagf(poles[0]);
191  REAL4 sep = x*x + y*y;
192  for(j=1;j<numPoles;j++){
193  x=crealf(poles[i])-crealf(poles[j]);
194  y=cimagf(poles[i])+cimagf(poles[j]);
195  if(sep>x*x+y*y){
196  sep=x*x+y*y;
197  k=j;
198  }
199  }
200  if(sep>LAL_REAL4_EPS){
201  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
202  XLALPrintWarning("Complex pole has no conjugate pair\n");
203  XLALPrintWarning("\tUnmatched pole p_%i = %.8e + i*%.8e\n",i,
204  crealf(poles[i]),cimagf(poles[i]));
205  XLALPrintWarning("\tNearest pair p_%i = %.8e + i*%.8e\n",k,
206  crealf(poles[k]),cimagf(poles[k]));
207  }
208  }
209  }
210 
211  if ( num != numPoles )
213 
215  /* Issue a warning if the gain is nonreal. */
216  if(fabs(cimag(input->gain))>fabs(LAL_REAL4_EPS*creal(input->gain))){
217  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
218  XLALPrintWarning("Gain is non-real\n");
219  XLALPrintWarning("\tg = %.8e + i*%.8e\n", crealf(input->gain), cimagf(input->gain));
220  }
221  /* Issue a warning if there are any ``removeable'' poles. */
222  for(i=0;i<numPoles;i++){
223  INT4 j=0;
224  for(;j<numZeros;j++)
225  if((crealf(poles[i])==crealf(zeros[j]))&&(cimagf(poles[i])==cimagf(zeros[j]))){
226  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
227  XLALPrintWarning("Removeable pole\n");
228  XLALPrintWarning("\tp_%i = z_%i = %.8e + i*%.8e\n",i,j,
229  crealf(poles[i]),cimagf(poles[i]));
230  }
231  }
232  /* Issue a warning if extra factors of 1/z will be applied. */
233  if(numPoles<numZeros){
234  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
235  XLALPrintWarning("Filter has more zeros than poles\n");
236  XLALPrintWarning("\t%i poles added at complex origin\n",
237  numZeros-numPoles);
238  }
239  /* Issue a warning if any poles are outside |z|=1. */
240  for(i=0;i<numPoles;i++){
241  REAL4 zAbs=crealf(poles[i])*crealf(poles[i])+cimagf(poles[i])*cimagf(poles[i]);
242  if(zAbs>1.0){
243  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
244  XLALPrintWarning("Filter has pole outside of unit circle\n");
245  XLALPrintWarning("\tp_%i = %.8e + i*%.8e, |p_%i| = %.8e\n",i,
246  crealf(poles[i]),cimagf(poles[i]),i,zAbs);
247  }
248  }
249  }
250 
251  /* Everything seems okay, so initialize the filter. */
252  output=LALCalloc(1,sizeof(*output));
253  if ( ! output )
255  num = (numPoles>=numZeros) ? numZeros : numPoles;
256  numDirect+=num;
257  numRecurs+=num;
258 
259  output->deltaT=input->deltaT;
260  output->directCoef = XLALCreateREAL4Vector( numDirect );
261  output->recursCoef = XLALCreateREAL4Vector( numRecurs );
262  if ( ! output->directCoef || ! output->recursCoef )
263  {
266  }
267  direct=output->directCoef->data;
268  recurs=output->recursCoef->data;
269 
270  /* Expand the denominator as a polynomial in z. */
271  *recurs=-1.0;
272  for(i=1;i<numRecurs;i++)
273  recurs[i]=0.0;
274  for(i=0;i<numPoles;i++){
275  INT4 j=numRecurs-1;
276  REAL4 x=crealf(poles[i]);
277  REAL4 y=cimagf(poles[i]);
278  if(y==0.0)
279  for(;j>0;j--)
280  recurs[j]-=x*recurs[j-1];
281  else if(y>0.0){
282  for(;j>1;j--)
283  recurs[j]-=2.0*x*recurs[j-1]-(x*x+y*y)*recurs[j-2];
284  recurs[j]-=2.0*x*recurs[j-1];
285  }
286  }
287 
288  /* Expand the numerator as a polynomial in z. */
289  for(i=0;i<numDirect;i++)
290  direct[i]=0.0;
291  direct[num-numZeros]=crealf(input->gain);
292  for(i=0;i<numZeros;i++){
293  INT4 j=numDirect-1;
294  REAL4 x=crealf(zeros[i]);
295  REAL4 y=cimagf(zeros[i]);
296  if(y==0.0)
297  for(;j>num-numZeros;j--)
298  direct[j]-=x*direct[j-1];
299  else if(y>0.0){
300  for(;j>num-numZeros+1;j--)
301  direct[j]-=2.0*x*direct[j-1]-(x*x+y*y)*direct[j-2];
302  direct[j]-=2.0*x*direct[j-1];
303  }
304  }
305 
306  /* Initialize filter history. */
307  if(numDirect>=numRecurs)
308  num=numDirect-1;
309  else
310  num=numRecurs-1;
311  output->history = XLALCreateREAL4Vector( numRecurs );
312  if ( ! output->history )
313  {
316  }
317  history=output->history->data;
318  for(i=0;i<num;i++)
319  history[i]=0.0;
320 
321  /* Normal exit */
322  return output;
323 }
324 
325 /** \see See \ref CreateIIRFilter_c for documentation */
327 {
329  INT4 i; /* Index counter for zeros and poles. */
330  INT4 numZeros; /* The number of zeros. */
331  INT4 numPoles; /* The number of poles. */
332  INT4 numDirect; /* The number of direct filter coefficients. */
333  INT4 numRecurs; /* The number of recursive filter coefficients. */
334  INT4 num; /* An extra counter for error checking. */
335  COMPLEX16 *zeros; /* The zeros of the transfer function. */
336  COMPLEX16 *poles; /* The poles of the transfer function. */
337  REAL8 *direct; /* The direct filter coefficients. */
338  REAL8 *recurs; /* The recursive filter coefficients. */
339  REAL8 *history; /* The filter history. */
340 
341  /* Make sure all the input structures have been initialized. */
342  if ( ! input )
344  if ( ! input->zeros || ! input->poles
345  || ! input->zeros->data || ! input->poles->data )
347 
348  numZeros=input->zeros->length;
349  numPoles=input->poles->length;
350  zeros=input->zeros->data;
351  poles=input->poles->data;
352 
353  /* Check that zeros are appropriately paired. Also, keep track of
354  the number of zeros at z=0, since these will reduce the number of
355  direct coefficients required. */
356  numDirect=1;
357  for(i=0,num=0;i<numZeros;i++)
358  if(cimag(zeros[i])==0.0){
359  num+=1;
360  if(creal(zeros[i])==0.0)
361  numDirect-=1;
362  }
363  else if(cimag(zeros[i])>0.0){
364  num+=2;
365 
367  /* Check to see that another zero is an actual conjugate.
368  This is not a foolproof test, as it can be fooled by
369  multiple zeros at the same location. */
370  INT4 j=0;
371  INT4 k=0;
372  REAL8 x = creal(zeros[i]) - creal(zeros[0]);
373  REAL8 y = cimag(zeros[i]) + cimag(zeros[0]);
374  REAL8 sep = x*x + y*y;
375  for(j=1;j<numZeros;j++){
376  x=creal(zeros[i])-creal(zeros[j]);
377  y=cimag(zeros[i])+cimag(zeros[j]);
378  if(sep>x*x+y*y){
379  sep=x*x+y*y;
380  k=j;
381  }
382  }
383  if(sep>LAL_REAL8_EPS){
384  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
385  XLALPrintWarning("Complex zero has no conjugate pair\n");
386  XLALPrintWarning("\tUnmatched zero z_%i = %.8e + i*%.8e\n",i,
387  creal(zeros[i]),cimag(zeros[i]));
388  XLALPrintWarning("\tNearest pair z_%i = %.8e + i*%.8e\n",k,
389  creal(zeros[k]),cimag(zeros[k]));
390  }
391  }
392  }
393 
394  if ( num != numZeros )
396 
397  /* Check that poles are appropriately paired. Also, keep track of
398  the number of poles at z=0, since these will reduce the number of
399  recursive coefficients required. */
400  numRecurs=1;
401  for(i=0,num=0;i<numPoles;i++)
402  if(cimag(poles[i])==0.0){
403  num+=1;
404  if(creal(poles[i])==0.0)
405  numRecurs-=1;
406  }
407  else if(cimag(poles[i])>0.0){
408  num+=2;
409 
411  /* Check to see that another pole is an actual conjugate.
412  This is not a foolproof test, as it can be fooled by
413  multiple poles at the same location. */
414  INT4 j=0;
415  INT4 k=0;
416  REAL8 x = creal(poles[i]) - creal(poles[0]);
417  REAL8 y = cimag(poles[i]) + cimag(poles[0]);
418  REAL8 sep = x*x + y*y;
419  for(j=1;j<numPoles;j++){
420  x=creal(poles[i])-creal(poles[j]);
421  y=cimag(poles[i])+cimag(poles[j]);
422  if(sep>x*x+y*y){
423  sep=x*x+y*y;
424  k=j;
425  }
426  }
427  if(sep>LAL_REAL8_EPS){
428  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
429  XLALPrintWarning("Complex pole has no conjugate pair\n");
430  XLALPrintWarning("\tUnmatched pole p_%i = %.8e + i*%.8e\n",i,
431  creal(poles[i]),cimag(poles[i]));
432  XLALPrintWarning("\tNearest pair p_%i = %.8e + i*%.8e\n",k,
433  creal(poles[k]),cimag(poles[k]));
434  }
435  }
436  }
437 
438  if ( num != numPoles )
440 
442  /* Issue a warning if the gain is nonreal. */
443  if(fabs(cimag(input->gain))>fabs(LAL_REAL8_EPS*creal(input->gain))){
444  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
445  XLALPrintWarning("Gain is non-real\n");
446  XLALPrintWarning("\tg = %.8e + i*%.8e\n", creal(input->gain), cimag(input->gain));
447  }
448  /* Issue a warning if there are any ``removeable'' poles. */
449  for(i=0;i<numPoles;i++){
450  INT4 j=0;
451  for(;j<numZeros;j++)
452  if((creal(poles[i])==creal(zeros[j]))&&(cimag(poles[i])==cimag(zeros[j]))){
453  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
454  XLALPrintWarning("Removeable pole\n");
455  XLALPrintWarning("\tp_%i = z_%i = %.8e + i*%.8e\n",i,j,
456  creal(poles[i]),cimag(poles[i]));
457  }
458  }
459  /* Issue a warning if extra factors of 1/z will be applied. */
460  if(numPoles<numZeros){
461  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
462  XLALPrintWarning("Filter has more zeros than poles\n");
463  XLALPrintWarning("\t%i poles added at complex origin\n",
464  numZeros-numPoles);
465  }
466  /* Issue a warning if any poles are outside |z|=1. */
467  for(i=0;i<numPoles;i++){
468  REAL8 zAbs=creal(poles[i])*creal(poles[i])+cimag(poles[i])*cimag(poles[i]);
469  if(zAbs>1.0){
470  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
471  XLALPrintWarning("Filter has pole outside of unit circle\n");
472  XLALPrintWarning("\tp_%i = %.8e + i*%.8e, |p_%i| = %.8e\n",i,
473  creal(poles[i]),cimag(poles[i]),i,zAbs);
474  }
475  }
476  }
477 
478  /* Everything seems okay, so initialize the filter. */
479  output=LALCalloc(1,sizeof(*output));
480  if ( ! output )
482  num = (numPoles>=numZeros) ? numZeros : numPoles;
483  numDirect+=num;
484  numRecurs+=num;
485 
486  output->deltaT=input->deltaT;
487  output->directCoef = XLALCreateREAL8Vector( numDirect );
488  output->recursCoef = XLALCreateREAL8Vector( numRecurs );
489  if ( ! output->directCoef || ! output->recursCoef )
490  {
493  }
494  direct=output->directCoef->data;
495  recurs=output->recursCoef->data;
496 
497  /* Expand the denominator as a polynomial in z. */
498  *recurs=-1.0;
499  for(i=1;i<numRecurs;i++)
500  recurs[i]=0.0;
501  for(i=0;i<numPoles;i++){
502  INT4 j=numRecurs-1;
503  REAL8 x=creal(poles[i]);
504  REAL8 y=cimag(poles[i]);
505  if(y==0.0)
506  for(;j>0;j--)
507  recurs[j]-=x*recurs[j-1];
508  else if(y>0.0){
509  for(;j>1;j--)
510  recurs[j]-=2.0*x*recurs[j-1]-(x*x+y*y)*recurs[j-2];
511  recurs[j]-=2.0*x*recurs[j-1];
512  }
513  }
514 
515  /* Expand the numerator as a polynomial in z. */
516  for(i=0;i<numDirect;i++)
517  direct[i]=0.0;
518  direct[num-numZeros]=creal(input->gain);
519  for(i=0;i<numZeros;i++){
520  INT4 j=numDirect-1;
521  REAL8 x=creal(zeros[i]);
522  REAL8 y=cimag(zeros[i]);
523  if(y==0.0)
524  for(;j>num-numZeros;j--)
525  direct[j]-=x*direct[j-1];
526  else if(y>0.0){
527  for(;j>num-numZeros+1;j--)
528  direct[j]-=2.0*x*direct[j-1]-(x*x+y*y)*direct[j-2];
529  direct[j]-=2.0*x*direct[j-1];
530  }
531  }
532 
533  /* Initialize filter history. */
534  if(numDirect>=numRecurs)
535  num=numDirect-1;
536  else
537  num=numRecurs-1;
538  output->history = XLALCreateREAL8Vector( numRecurs );
539  if ( ! output->history )
540  {
543  }
544  history=output->history->data;
545  for(i=0;i<num;i++)
546  history[i]=0.0;
547 
548  /* Normal exit */
549  return output;
550 }
551 
552 /** \see See \ref CreateIIRFilter_c for documentation */
554 {
556  INT4 i; /* Index counter for zeros and poles. */
557  INT4 numZeros; /* The number of zeros. */
558  INT4 numPoles; /* The number of poles. */
559  INT4 numDirect; /* The number of direct filter coefficients. */
560  INT4 numRecurs; /* The number of recursive filter coefficients. */
561  INT4 num; /* An extra counter for error checking. */
562  COMPLEX16 *zeros; /* The zeros of the transfer function. */
563  COMPLEX16 *poles; /* The poles of the transfer function. */
564  REAL8 *direct; /* The direct filter coefficients. */
565  REAL8 *recurs; /* The recursive filter coefficients. */
566  COMPLEX16 *history; /* The filter history. */
567 
568  /* Make sure all the input structures have been initialized. */
569  if ( ! input )
571  if ( ! input->zeros || ! input->poles
572  || ! input->zeros->data || ! input->poles->data )
574 
575  numZeros=input->zeros->length;
576  numPoles=input->poles->length;
577  zeros=input->zeros->data;
578  poles=input->poles->data;
579 
580  /* Check that zeros are appropriately paired. Also, keep track of
581  the number of zeros at z=0, since these will reduce the number of
582  direct coefficients required. */
583  numDirect=1;
584  for(i=0,num=0;i<numZeros;i++)
585  if(cimag(zeros[i])==0.0){
586  num+=1;
587  if(creal(zeros[i])==0.0)
588  numDirect-=1;
589  }
590  else if(cimag(zeros[i])>0.0){
591  num+=2;
592 
594  /* Check to see that another zero is an actual conjugate.
595  This is not a foolproof test, as it can be fooled by
596  multiple zeros at the same location. */
597  INT4 j=0;
598  INT4 k=0;
599  REAL8 x = creal(zeros[i]) - creal(zeros[0]);
600  REAL8 y = cimag(zeros[i]) + cimag(zeros[0]);
601  REAL8 sep = x*x + y*y;
602  for(j=1;j<numZeros;j++){
603  x=creal(zeros[i])-creal(zeros[j]);
604  y=cimag(zeros[i])+cimag(zeros[j]);
605  if(sep>x*x+y*y){
606  sep=x*x+y*y;
607  k=j;
608  }
609  }
610  if(sep>LAL_REAL8_EPS){
611  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
612  XLALPrintWarning("Complex zero has no conjugate pair\n");
613  XLALPrintWarning("\tUnmatched zero z_%i = %.8e + i*%.8e\n",i,
614  creal(zeros[i]),cimag(zeros[i]));
615  XLALPrintWarning("\tNearest pair z_%i = %.8e + i*%.8e\n",k,
616  creal(zeros[k]),cimag(zeros[k]));
617  }
618  }
619  }
620 
621  if ( num != numZeros )
623 
624  /* Check that poles are appropriately paired. Also, keep track of
625  the number of poles at z=0, since these will reduce the number of
626  recursive coefficients required. */
627  numRecurs=1;
628  for(i=0,num=0;i<numPoles;i++)
629  if(cimag(poles[i])==0.0){
630  num+=1;
631  if(creal(poles[i])==0.0)
632  numRecurs-=1;
633  }
634  else if(cimag(poles[i])>0.0){
635  num+=2;
636 
638  /* Check to see that another pole is an actual conjugate.
639  This is not a foolproof test, as it can be fooled by
640  multiple poles at the same location. */
641  INT4 j=0;
642  INT4 k=0;
643  REAL8 x = creal(poles[i]) - creal(poles[0]);
644  REAL8 y = cimag(poles[i]) + cimag(poles[0]);
645  REAL8 sep = x*x + y*y;
646  for(j=1;j<numPoles;j++){
647  x=creal(poles[i])-creal(poles[j]);
648  y=cimag(poles[i])+cimag(poles[j]);
649  if(sep>x*x+y*y){
650  sep=x*x+y*y;
651  k=j;
652  }
653  }
654  if(sep>LAL_REAL8_EPS){
655  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
656  XLALPrintWarning("Complex pole has no conjugate pair\n");
657  XLALPrintWarning("\tUnmatched pole p_%i = %.8e + i*%.8e\n",i,
658  creal(poles[i]),cimag(poles[i]));
659  XLALPrintWarning("\tNearest pair p_%i = %.8e + i*%.8e\n",k,
660  creal(poles[k]),cimag(poles[k]));
661  }
662  }
663  }
664 
665  if ( num != numPoles )
667 
669  /* Issue a warning if the gain is nonreal. */
670  if(fabs(cimag(input->gain))>fabs(LAL_REAL8_EPS*creal(input->gain))){
671  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
672  XLALPrintWarning("Gain is non-real\n");
673  XLALPrintWarning("\tg = %.8e + i*%.8e\n", creal(input->gain), cimag(input->gain));
674  }
675  /* Issue a warning if there are any ``removeable'' poles. */
676  for(i=0;i<numPoles;i++){
677  INT4 j=0;
678  for(;j<numZeros;j++)
679  if((creal(poles[i])==creal(zeros[j]))&&(cimag(poles[i])==cimag(zeros[j]))){
680  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
681  XLALPrintWarning("Removeable pole\n");
682  XLALPrintWarning("\tp_%i = z_%i = %.8e + i*%.8e\n",i,j,
683  creal(poles[i]),cimag(poles[i]));
684  }
685  }
686  /* Issue a warning if extra factors of 1/z will be applied. */
687  if(numPoles<numZeros){
688  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
689  XLALPrintWarning("Filter has more zeros than poles\n");
690  XLALPrintWarning("\t%i poles added at complex origin\n",
691  numZeros-numPoles);
692  }
693  /* Issue a warning if any poles are outside |z|=1. */
694  for(i=0;i<numPoles;i++){
695  REAL8 zAbs=creal(poles[i])*creal(poles[i])+cimag(poles[i])*cimag(poles[i]);
696  if(zAbs>1.0){
697  XLALPrintWarning( "XLAL Warning - %s: ", __func__ );
698  XLALPrintWarning("Filter has pole outside of unit circle\n");
699  XLALPrintWarning("\tp_%i = %.8e + i*%.8e, |p_%i| = %.8e\n",i,
700  creal(poles[i]),cimag(poles[i]),i,zAbs);
701  }
702  }
703  }
704 
705  /* Everything seems okay, so initialize the filter. */
706  output=LALCalloc(1,sizeof(*output));
707  if ( ! output )
709  num = (numPoles>=numZeros) ? numZeros : numPoles;
710  numDirect+=num;
711  numRecurs+=num;
712 
713  output->deltaT=input->deltaT;
714  output->directCoef = XLALCreateREAL8Vector( numDirect );
715  output->recursCoef = XLALCreateREAL8Vector( numRecurs );
716  if ( ! output->directCoef || ! output->recursCoef )
717  {
720  }
721  direct=output->directCoef->data;
722  recurs=output->recursCoef->data;
723 
724  /* Expand the denominator as a polynomial in z. */
725  *recurs=-1.0;
726  for(i=1;i<numRecurs;i++)
727  recurs[i]=0.0;
728  for(i=0;i<numPoles;i++){
729  INT4 j=numRecurs-1;
730  REAL8 x=creal(poles[i]);
731  REAL8 y=cimag(poles[i]);
732  if(y==0.0)
733  for(;j>0;j--)
734  recurs[j]-=x*recurs[j-1];
735  else if(y>0.0){
736  for(;j>1;j--)
737  recurs[j]-=2.0*x*recurs[j-1]-(x*x+y*y)*recurs[j-2];
738  recurs[j]-=2.0*x*recurs[j-1];
739  }
740  }
741 
742  /* Expand the numerator as a polynomial in z. */
743  for(i=0;i<numDirect;i++)
744  direct[i]=0.0;
745  direct[num-numZeros]=creal(input->gain);
746  for(i=0;i<numZeros;i++){
747  INT4 j=numDirect-1;
748  REAL8 x=creal(zeros[i]);
749  REAL8 y=cimag(zeros[i]);
750  if(y==0.0)
751  for(;j>num-numZeros;j--)
752  direct[j]-=x*direct[j-1];
753  else if(y>0.0){
754  for(;j>num-numZeros+1;j--)
755  direct[j]-=2.0*x*direct[j-1]-(x*x+y*y)*direct[j-2];
756  direct[j]-=2.0*x*direct[j-1];
757  }
758  }
759 
760  /* Initialize filter history. */
761  if(numDirect>=numRecurs)
762  num=numDirect-1;
763  else
764  num=numRecurs-1;
765  output->history = XLALCreateCOMPLEX16Vector( numRecurs );
766  if ( ! output->history )
767  {
770  }
771  history=output->history->data;
772  for(i=0;i<num;i++)
773  history[i]=0.0;
774 
775  /* Normal exit */
776  return output;
777 }
778 
779 
780 /**
781  * Deprecated.
782  * \deprecated Use XLALCreateREAL4IIRFilter() instead
783  */
786  COMPLEX8ZPGFilter *input )
787 {
788  INITSTATUS(stat);
789 
790  /* Make sure all the input structures have been initialized. */
791  ASSERT(input,stat,IIRFILTERH_ENUL,IIRFILTERH_MSGENUL);
792  ASSERT(input->zeros,stat,IIRFILTERH_ENUL,IIRFILTERH_MSGENUL);
793  ASSERT(input->zeros->data,stat,IIRFILTERH_ENUL,IIRFILTERH_MSGENUL);
794  ASSERT(input->poles,stat,IIRFILTERH_ENUL,IIRFILTERH_MSGENUL);
795  ASSERT(input->poles->data,stat,IIRFILTERH_ENUL,IIRFILTERH_MSGENUL);
796 
797  /* Make sure that the output handle exists, but points to a null
798  pointer. */
799  ASSERT(output,stat,IIRFILTERH_ENUL,IIRFILTERH_MSGENUL);
800  ASSERT(!*output,stat,IIRFILTERH_EOUT,IIRFILTERH_MSGEOUT);
801 
802  *output = XLALCreateREAL4IIRFilter( input );
803  if ( ! *output )
804  {
805  int code = xlalErrno & ~XLAL_EFUNC;
806  XLALClearErrno();
807  switch ( code )
808  {
809  case XLAL_EINVAL:
810  ABORT(stat,IIRFILTERH_EPAIR,IIRFILTERH_MSGEPAIR);
811  case XLAL_ENOMEM:
812  ABORT(stat,IIRFILTERH_EMEM,IIRFILTERH_MSGEMEM);
813  default:
814  ABORTXLAL(stat);
815  }
816  }
817 
818  RETURN(stat);
819 }
820 
821 
822 /**
823  * Deprecated.
824  * \deprecated Use XLALCreateREAL8IIRFilter() instead
825  */
828  COMPLEX16ZPGFilter *input )
829 {
830  INITSTATUS(stat);
831 
832  /* Make sure all the input structures have been initialized. */
833  ASSERT(input,stat,IIRFILTERH_ENUL,IIRFILTERH_MSGENUL);
834  ASSERT(input->zeros,stat,IIRFILTERH_ENUL,IIRFILTERH_MSGENUL);
835  ASSERT(input->zeros->data,stat,IIRFILTERH_ENUL,IIRFILTERH_MSGENUL);
836  ASSERT(input->poles,stat,IIRFILTERH_ENUL,IIRFILTERH_MSGENUL);
837  ASSERT(input->poles->data,stat,IIRFILTERH_ENUL,IIRFILTERH_MSGENUL);
838 
839  /* Make sure that the output handle exists, but points to a null
840  pointer. */
841  ASSERT(output,stat,IIRFILTERH_ENUL,IIRFILTERH_MSGENUL);
842  ASSERT(!*output,stat,IIRFILTERH_EOUT,IIRFILTERH_MSGEOUT);
843 
844  *output = XLALCreateREAL8IIRFilter( input );
845  if ( ! *output )
846  {
847  int code = xlalErrno & ~XLAL_EFUNC;
848  XLALClearErrno();
849  switch ( code )
850  {
851  case XLAL_EINVAL:
852  ABORT(stat,IIRFILTERH_EPAIR,IIRFILTERH_MSGEPAIR);
853  case XLAL_ENOMEM:
854  ABORT(stat,IIRFILTERH_EMEM,IIRFILTERH_MSGEMEM);
855  default:
856  ABORTXLAL(stat);
857  }
858  }
859 
860  RETURN(stat);
861 }
862 /** @} */
#define LALCalloc(m, n)
Definition: LALMalloc.h:94
#define ABORT(statusptr, code, mesg)
#define ASSERT(assertion, statusptr, code, mesg)
#define INITSTATUS(statusptr)
#define RETURN(statusptr)
#define ABORTXLAL(sp)
int XLALPrintWarning(const char *fmt,...)
Definition: XLALError.c:79
REAL4IIRFilter * XLALCreateREAL4IIRFilter(COMPLEX8ZPGFilter *input)
void LALCreateREAL4IIRFilter(LALStatus *stat, REAL4IIRFilter **output, COMPLEX8ZPGFilter *input)
Deprecated.
REAL8IIRFilter * XLALCreateREAL8IIRFilter(COMPLEX16ZPGFilter *input)
COMPLEX16IIRFilter * XLALCreateCOMPLEX16IIRFilter(COMPLEX16ZPGFilter *input)
void LALCreateREAL8IIRFilter(LALStatus *stat, REAL8IIRFilter **output, COMPLEX16ZPGFilter *input)
Deprecated.
void XLALDestroyREAL4IIRFilter(REAL4IIRFilter *filter)
void XLALDestroyCOMPLEX16IIRFilter(COMPLEX16IIRFilter *filter)
void XLALDestroyREAL8IIRFilter(REAL8IIRFilter *filter)
#define IIRFILTERH_ENUL
Unexpected null pointer in arguments.
Definition: IIRFilter.h:131
#define IIRFILTERH_EPAIR
Input has unpaired nonreal poles or zeros.
Definition: IIRFilter.h:134
#define IIRFILTERH_EMEM
Memory allocation error.
Definition: IIRFilter.h:133
#define IIRFILTERH_EOUT
Output handle points to a non-null pointer.
Definition: IIRFilter.h:132
#define LAL_REAL8_EPS
Difference between 1 and the next resolvable REAL8 2^-52.
Definition: LALConstants.h:61
#define LAL_REAL4_EPS
Difference between 1 and the next resolvable REAL4 2^-23.
Definition: LALConstants.h:57
double complex COMPLEX16
Double-precision floating-point complex number (16 bytes total)
double REAL8
Double precision real floating-point number (8 bytes).
float complex COMPLEX8
Single-precision floating-point complex number (8 bytes total)
int32_t INT4
Four-byte signed integer.
float REAL4
Single precision real floating-point number (4 bytes).
#define lalDebugLevel
Definition: LALDebugLevel.h:58
@ LALWARNING
enable warning messages
Definition: LALDebugLevel.h:47
COMPLEX16Vector * XLALCreateCOMPLEX16Vector(UINT4 length)
REAL4Vector * XLALCreateREAL4Vector(UINT4 length)
REAL8Vector * XLALCreateREAL8Vector(UINT4 length)
#define XLAL_ERROR_NULL(...)
Macro to invoke a failure from a XLAL routine returning a pointer.
Definition: XLALError.h:713
#define xlalErrno
Modifiable lvalue containing the XLAL error number.
Definition: XLALError.h:571
int XLALClearErrno(void)
Clears the XLAL error number, returns the old value.
Definition: XLALError.c:363
@ XLAL_ENOMEM
Memory allocation error.
Definition: XLALError.h:407
@ XLAL_EFAULT
Invalid pointer.
Definition: XLALError.h:408
@ XLAL_EFUNC
Internal function call failed bit: "or" this with existing error number.
Definition: XLALError.h:462
@ XLAL_EINVAL
Invalid argument.
Definition: XLALError.h:409
This structure stores the direct and recursive REAL8 filter coefficients, as well as the complex-valu...
Definition: IIRFilter.h:184
UINT4 length
Number of elements in array.
Definition: LALDatatypes.h:176
COMPLEX16 * data
Pointer to the data array.
Definition: LALDatatypes.h:177
See DATATYPE-ZPGFilter types for details.
Definition: LALDatatypes.h:930
COMPLEX16Vector * poles
Definition: LALDatatypes.h:934
COMPLEX16Vector * zeros
Definition: LALDatatypes.h:933
UINT4 length
Number of elements in array.
Definition: LALDatatypes.h:167
COMPLEX8 * data
Pointer to the data array.
Definition: LALDatatypes.h:168
See DATATYPE-ZPGFilter types for details.
Definition: LALDatatypes.h:921
COMPLEX8Vector * poles
Definition: LALDatatypes.h:925
COMPLEX8Vector * zeros
Definition: LALDatatypes.h:924
LAL status structure, see The LALStatus structure for more details.
Definition: LALDatatypes.h:947
This structure stores the direct and recursive REAL4 filter coefficients, as well as the history of t...
Definition: IIRFilter.h:152
This structure stores the direct and recursive REAL8 filter coefficients, as well as the history of t...
Definition: IIRFilter.h:168
void output(int gps_sec, int output_type)
Definition: tconvert.c:440