![]() |
RTXI 1.3
|
00001 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00002 // 00003 // File = bessfunc.cpp 00004 // 00005 // Bessel Filter Function 00006 // 00007 00008 #include <math.h> 00009 #include <stdlib.h> 00010 #include "bessfunc.h" 00011 #include "elipfunc.h" 00012 #include "laguerre.h" 00013 #include "complex.h" 00014 #include "cmpxpoly.h" 00015 #ifdef _DEBUG 00016 extern std::ofstream DebugFile; 00017 #endif 00018 00019 //====================================================== 00020 // constructor 00021 00022 BesselTransFunc::BesselTransFunc( int order, 00023 double passband_edge, 00024 int norm_for_delay) 00025 :FilterTransFunc(order) 00026 { 00027 int indx, indx_m1, indx_m2; 00028 int i, n, ii, work_order; 00029 double epsilon, epsilon2; 00030 int max_iter, laguerre_status; 00031 long q_poly[3][MAX_BESSEL_ORDER]; 00032 complex *denom_poly, *work_coeff; 00033 complex root, work1, work2; 00034 double renorm_val, smallest; 00035 CmplxPolynomial *work_poly; 00036 00037 //------------------------------------------------------- 00038 // these values are reciprocals of values in Table 5.10 00039 00040 double renorm_factor[9] = { 0.0, 0.0, 0.72675, 00041 0.57145, 0.46946, 0.41322, 00042 0.37038, 0.33898, 0.31546}; 00043 00044 Prototype_Pole_Locs = new complex[order+1]; 00045 Num_Prototype_Poles = order; 00046 Prototype_Zero_Locs = new complex[1]; 00047 Num_Prototype_Zeros = 0; 00048 00049 H_Sub_Zero = 1.0; 00050 denom_poly = new complex[MAX_BESSEL_ORDER]; 00051 work_coeff = new complex[MAX_BESSEL_ORDER]; 00052 00053 indx = 1; 00054 indx_m1 = 0; 00055 indx_m2 = 2; 00056 renorm_val = renorm_factor[order]; 00057 00058 //----------------------------------------- 00059 // initialize polynomials for n=0 and n=1 00060 00061 for( i=0; i<(3*MAX_BESSEL_ORDER) ; i++) 00062 q_poly[0][i] = 0; 00063 00064 q_poly[0][0] = 1; 00065 q_poly[1][0] = 1; 00066 q_poly[1][1] = 1; 00067 00068 //---------------------------------------------- 00069 // compute polynomial using recursion from n=2 00070 // up through n=order 00071 00072 for( n=2; n<=order; n++) 00073 { 00074 indx = (indx+1)%3; 00075 indx_m1 = (indx_m1+1)%3; 00076 indx_m2 = (indx_m2+1)%3; 00077 00078 for( i=0; i<n; i++) 00079 { 00080 q_poly[indx][i] = (2*n-1) * 00081 q_poly[indx_m1][i]; 00082 } 00083 for( i=2; i<=n; i++) 00084 { 00085 q_poly[indx][i] = q_poly[indx][i] + 00086 q_poly[indx_m2][i-2]; 00087 } 00088 } 00089 if(norm_for_delay) 00090 { 00091 for( i=0; i<=order; i++) 00092 { 00093 denom_poly[i] = complex( 00094 double(q_poly[indx][i]), 0.0); 00095 #ifdef _DEBUG 00096 DebugFile << "q_poly[" << i << "] = " 00097 << q_poly[indx][i] << std::endl; 00098 #endif 00099 } 00100 } 00101 else 00102 { 00103 for( i=0; i<=order; i++) 00104 denom_poly[i] = complex( 00105 (double(q_poly[indx][i]) * 00106 ipow(renorm_val, (order-i))), 0.0); 00107 } 00108 //--------------------------------------------------- 00109 // use Laguerre method to find roots of the 00110 // denominator polynomial -- these roots are the 00111 // poles of the filter 00112 00113 epsilon = 1.0e-6; 00114 epsilon2 = 1.0e-6; 00115 max_iter = 10; 00116 00117 for(i=0; i<=order; i++) work_coeff[i] = denom_poly[i]; 00118 00119 for(i=order; i>1; i--) 00120 { 00121 root = complex(0.0,0.0); 00122 work_order = i; 00123 work_poly = new CmplxPolynomial( work_coeff, work_order); 00124 laguerre_status = LaguerreMethod( work_poly, 00125 &root, 00126 epsilon, 00127 epsilon2, 00128 max_iter); 00129 delete work_poly; 00130 00131 #ifdef _DEBUG 00132 DebugFile << "laguerre_status = " 00133 << laguerre_status << std::endl; 00134 #endif 00135 00136 if(laguerre_status <0) 00137 { 00138 #ifdef _DEBUG 00139 DebugFile << "FATAL ERROR - \n" 00140 << "Laguerre method failed to converge.\n" 00141 << "Unable to find poles for desired Bessel filter." 00142 << std::endl; 00143 #endif 00144 exit(-1); 00145 } 00146 00147 #ifdef _DEBUG 00148 DebugFile << "root = " << root << std::endl; 00149 #endif 00150 00151 //-------------------------------------------- 00152 // if imaginary part of root is very small 00153 // relative to real part, set it to zero 00154 00155 if(fabs(imag(root)) < epsilon*fabs(real(root))) 00156 { 00157 root = complex(real(root), 0.0); 00158 } 00159 Prototype_Pole_Locs[order+1-i] = root; 00160 00161 //--------------------------------------------- 00162 // deflate working polynomial by removing 00163 // (s - r) factor where r is newly found root 00164 00165 work1 = work_coeff[i]; 00166 for(ii=i-1; ii>=0; ii--) 00167 { 00168 work2 = work_coeff[ii]; 00169 work_coeff[ii] = work1; 00170 work1 = work2 + root * work1; 00171 } 00172 } // end of loop over i 00173 #ifdef _DEBUG 00174 DebugFile << "work_coeff[1] = " << work_coeff[1] << std::endl; 00175 DebugFile << "work_coeff[0] = " << work_coeff[0] << std::endl; 00176 #endif 00177 00178 Prototype_Pole_Locs[order] = -work_coeff[0]; 00179 00180 #ifdef _DEBUG 00181 DebugFile << "pole[" << order << "] = " 00182 << Prototype_Pole_Locs[order] << std::endl; 00183 #endif 00184 //---------------------------------------------- 00185 // sort poles so that imaginary parts are in 00186 // ascending order. This order is critical for 00187 // sucessful operation of ImpulseResponse(). 00188 00189 for(i=1; i<order; i++) 00190 { 00191 smallest = imag(Prototype_Pole_Locs[i]); 00192 for( ii=i+1; ii<=order; ii++) 00193 { 00194 if(smallest <= imag(Prototype_Pole_Locs[ii])) continue; 00195 work1 = Prototype_Pole_Locs[ii]; 00196 Prototype_Pole_Locs[ii] = Prototype_Pole_Locs[i]; 00197 Prototype_Pole_Locs[i] = work1; 00198 smallest = imag(work1); 00199 } 00200 } 00201 00202 #ifdef _DEBUG 00203 for(i=1; i<=order; i++) 00204 { 00205 DebugFile << "pole[" << i << "] = " 00206 << Prototype_Pole_Locs[i] << std::endl; 00207 } 00208 #endif 00209 00210 return; 00211 }