00001 00030 #include <itpp/fixed/cfix.h> 00031 #include <itpp/base/itassert.h> 00032 #include <cstdio> 00033 #include <iostream> 00034 00035 00036 namespace itpp 00037 { 00038 00039 CFix& CFix::operator=(const CFix &x) 00040 { 00041 shift = x.shift; 00042 re = apply_o_mode(x.re); 00043 im = apply_o_mode(x.im); 00044 return *this; 00045 } 00046 00047 CFix& CFix::operator=(const Fix &x) 00048 { 00049 shift = x.shift; 00050 re = apply_o_mode(x.re); 00051 im = 0; 00052 return *this; 00053 } 00054 00055 CFix& CFix::operator=(const std::complex<double> &x) 00056 { 00057 shift = 0; 00058 re = apply_o_mode(fixrep(std::real(x))); 00059 im = apply_o_mode(fixrep(std::imag(x))); 00060 return *this; 00061 } 00062 00063 CFix& CFix::operator=(const int x) 00064 { 00065 shift = 0; 00066 re = apply_o_mode(x); 00067 im = 0; 00068 return *this; 00069 } 00070 00071 CFix& CFix::operator+=(const CFix &x) 00072 { 00073 shift = assert_shifts(*this, x); 00074 re = apply_o_mode(re + x.re); 00075 im = apply_o_mode(im + x.im); 00076 return *this; 00077 } 00078 00079 CFix& CFix::operator+=(const Fix &x) 00080 { 00081 shift = assert_shifts(*this, x); 00082 re = apply_o_mode(re + x.re); 00083 return *this; 00084 } 00085 00086 CFix& CFix::operator+=(const int x) 00087 { 00088 assert_shifts(*this, x); 00089 re = apply_o_mode(re + x); 00090 return *this; 00091 } 00092 00093 CFix& CFix::operator-=(const CFix &x) 00094 { 00095 shift = assert_shifts(*this, x); 00096 re = apply_o_mode(re - x.re); 00097 im = apply_o_mode(im - x.im); 00098 return *this; 00099 } 00100 00101 CFix& CFix::operator-=(const Fix &x) 00102 { 00103 shift = assert_shifts(*this, x); 00104 re = apply_o_mode(re - x.re); 00105 return *this; 00106 } 00107 00108 CFix& CFix::operator-=(const int x) 00109 { 00110 assert_shifts(*this, x); 00111 re = apply_o_mode(re - x); 00112 return *this; 00113 } 00114 00115 CFix& CFix::operator*=(const CFix &x) 00116 { 00117 shift += x.shift; 00118 fixrep tmp_re = apply_o_mode(re * x.re - im * x.im); 00119 im = apply_o_mode(re * x.im + im * x.re); 00120 re = tmp_re; 00121 return *this; 00122 } 00123 00124 CFix& CFix::operator*=(const Fix &x) 00125 { 00126 shift += x.shift; 00127 re = apply_o_mode(re * x.re); 00128 im = apply_o_mode(im * x.re); 00129 return *this; 00130 } 00131 00132 CFix& CFix::operator*=(const int x) 00133 { 00134 re = apply_o_mode(re * x); 00135 im = apply_o_mode(im * x); 00136 return *this; 00137 } 00138 00139 CFix& CFix::operator/=(const CFix &x) 00140 { 00141 shift -= x.shift; 00142 fixrep denominator = x.re * x.re + x.im * x.im; 00143 fixrep tmp_re = apply_o_mode((re * x.re + im * x.im) / denominator); 00144 im = apply_o_mode((im * x.re - re * x.im) / denominator); 00145 re = tmp_re; 00146 return *this; 00147 } 00148 00149 CFix& CFix::operator/=(const Fix &x) 00150 { 00151 shift -= x.shift; 00152 re = apply_o_mode(re / x.re); 00153 im = apply_o_mode(im / x.re); 00154 return *this; 00155 } 00156 00157 CFix& CFix::operator/=(const int x) 00158 { 00159 re = apply_o_mode(re / x); 00160 im = apply_o_mode(im / x); 00161 return *this; 00162 } 00163 00164 CFix CFix::operator-() const 00165 { 00166 return CFix(-re, -im, shift, 0, 0); 00167 } 00168 00169 CFix& CFix::operator<<=(const int n) 00170 { 00171 it_assert_debug(n >= 0, "CFix::operator<<=: n cannot be negative!"); 00172 shift += n; 00173 re = apply_o_mode(re << n); 00174 im = apply_o_mode(im << n); 00175 return *this; 00176 } 00177 00178 CFix& CFix::operator>>=(const int n) 00179 { 00180 shift -= n; 00181 re = rshift_and_apply_q_mode(re, n); 00182 im = rshift_and_apply_q_mode(im, n); 00183 return *this; 00184 } 00185 00186 void CFix::set(double real, double imag, int n) 00187 { 00188 shift = n; 00189 re = scale_and_apply_modes(real); 00190 im = scale_and_apply_modes(imag); 00191 } 00192 00193 void CFix::set(double real, double imag, int n, q_mode q) 00194 { 00195 shift = n; 00196 re = scale_and_apply_modes(real, q); 00197 im = scale_and_apply_modes(imag, q); 00198 } 00199 00200 void CFix::set(const std::complex<double> &x, int n) 00201 { 00202 shift = n; 00203 re = scale_and_apply_modes(std::real(x)); 00204 im = scale_and_apply_modes(std::imag(x)); 00205 } 00206 00207 void CFix::set(const std::complex<double> &x, int n, q_mode q) 00208 { 00209 shift = n; 00210 re = scale_and_apply_modes(std::real(x), q); 00211 im = scale_and_apply_modes(std::imag(x), q); 00212 } 00213 00214 void CFix::lshift(int n) 00215 { 00216 it_assert_debug(n >= 0, "CFix::lshift: n cannot be negative!"); 00217 shift += n; 00218 re = apply_o_mode(re << n); 00219 im = apply_o_mode(im << n); 00220 } 00221 00222 void CFix::rshift(int n) 00223 { 00224 shift -= n; 00225 re = rshift_and_apply_q_mode(re, n); 00226 im = rshift_and_apply_q_mode(im, n); 00227 } 00228 00229 void CFix::rshift(int n, q_mode q) 00230 { 00231 shift -= n; 00232 re = rshift_and_apply_q_mode(re, n, q); 00233 im = rshift_and_apply_q_mode(im, n, q); 00234 } 00235 00236 std::complex<double> CFix::unfix() const 00237 { 00238 it_assert_debug(shift >= -63 && shift <= 64, "CFix::unfix: Illegal shift!"); 00239 return std::complex<double>(double(re)*DOUBLE_POW2[64 - shift], 00240 double(im)*DOUBLE_POW2[64 - shift]); 00241 } 00242 00243 void CFix::print() const 00244 { 00245 Fix_Base::print(); 00246 std::cout << "re = " << re << std::endl; 00247 std::cout << "im = " << im << std::endl; 00248 } 00249 00250 int assert_shifts(const CFix &x, const CFix &y) 00251 { 00252 int ret = 0; 00253 00254 if (x.shift == y.shift) 00255 ret = x.shift; 00256 else if (x.re == 0 && x.im == 0) 00257 ret = y.shift; 00258 else if (y.re == 0 && y.im == 0) 00259 ret = x.shift; 00260 else 00261 it_error("assert_shifts: Different shifts not allowed!"); 00262 00263 return ret; 00264 } 00265 00266 int assert_shifts(const CFix &x, const Fix &y) 00267 { 00268 int ret = 0; 00269 00270 if (x.shift == y.shift) 00271 ret = x.shift; 00272 else if (x.re == 0 && x.im == 0) 00273 ret = y.shift; 00274 else if (y.re == 0) 00275 ret = x.shift; 00276 else 00277 it_error("assert_shifts: Different shifts not allowed!"); 00278 00279 return ret; 00280 } 00281 00282 int assert_shifts(const CFix &x, int y) 00283 { 00284 it_error_if((x.shift != 0) && !(x.re == 0 && x.im == 0) 00285 && (y != 0), "assert_shifts: Different shifts not allowed!"); 00286 return x.shift; 00287 } 00288 00289 std::istream &operator>>(std::istream &is, CFix &x) 00290 { 00291 std::complex<double> value; 00292 is >> value; 00293 if (!is.eof() && (is.peek() == '<')) { 00294 int shift; 00295 is.get(); // Swallow '<' sign 00296 if (is.peek() == '<') { 00297 is.get(); // Swallow '<' sign 00298 is >> shift; 00299 x.set(value, shift); 00300 } 00301 else { 00302 is >> shift; 00303 is.get(); // Swallow '>' sign 00304 x.set_re(fixrep(std::real(value))); 00305 x.set_im(fixrep(std::imag(value))); 00306 x.set_shift(shift); 00307 } 00308 } 00309 else { 00310 // Change data representation but keep shift 00311 x.set_re(fixrep(std::real(value))); 00312 x.set_im(fixrep(std::imag(value))); 00313 } 00314 return is; 00315 } 00316 00317 std::ostream &operator<<(std::ostream &os, const CFix &x) 00318 { 00319 switch (x.get_output_mode()) { 00320 case OUTPUT_FIX: 00321 if (x.get_im() < 0) 00322 os << x.get_re() << x.get_im() << 'i'; 00323 else 00324 os << x.get_re() << '+' << x.get_im() << 'i'; 00325 break; 00326 case OUTPUT_FIX_SHIFT: 00327 if (x.get_im() < 0) 00328 os << x.get_re() << x.get_im() << 'i'; 00329 else 00330 os << x.get_re() << '+' << x.get_im() << 'i'; 00331 os << '<' << x.get_shift() << '>'; 00332 break; 00333 case OUTPUT_FLOAT: 00334 os << std::complex<double>(x); 00335 break; 00336 case OUTPUT_FLOAT_SHIFT: 00337 os << std::complex<double>(x) << "<<" << x.get_shift(); 00338 break; 00339 default: 00340 it_error("operator<<: Illegal output mode!"); 00341 } 00342 return os; 00343 } 00344 00345 // Specialization of template definition in vec.cpp 00346 template<> 00347 void cfixvec::set(const char *values) 00348 { 00349 std::istringstream buffer(values); 00350 int default_shift = 0, pos = 0, maxpos = 10; 00351 if (datasize > 0) { 00352 // Assume that all elements have the same shift 00353 default_shift = data[0].get_shift(); 00354 } 00355 alloc(maxpos); 00356 while (buffer.peek() != EOF) { 00357 switch (buffer.peek()) { 00358 case ':': 00359 it_error("set: expressions with ':' are not valid for cfixvec"); 00360 break; 00361 case ',': 00362 buffer.get(); 00363 break; 00364 default: 00365 pos++; 00366 if (pos > maxpos) { 00367 maxpos *= 2; 00368 set_size(maxpos, true); 00369 } 00370 data[pos-1].set_shift(default_shift); 00371 buffer >> data[pos-1]; // May override default_shift 00372 while (buffer.peek() == ' ') { buffer.get(); } 00373 break; 00374 } 00375 } 00376 set_size(pos, true); 00377 } 00378 00379 // Specialization of template definition in mat.cpp 00380 template<> 00381 void cfixmat::set(const char *values) 00382 { 00383 std::istringstream buffer(values); 00384 int default_shift = 0, rows = 0, maxrows = 10, cols = 0, nocols = 0, maxcols = 10; 00385 if (datasize > 0) { 00386 // Assume that all elements have the same shift 00387 default_shift = data[0].get_shift(); 00388 } 00389 alloc(maxrows, maxcols); 00390 while (buffer.peek() != EOF) { 00391 rows++; 00392 if (rows > maxrows) { 00393 maxrows = maxrows * 2; 00394 set_size(maxrows, maxcols, true); 00395 } 00396 cols = 0; 00397 while ((buffer.peek() != ';') && (buffer.peek() != EOF)) { 00398 if (buffer.peek() == ',') { 00399 buffer.get(); 00400 } 00401 else { 00402 cols++; 00403 if (cols > nocols) { 00404 nocols = cols; 00405 if (cols > maxcols) { 00406 maxcols = maxcols * 2; 00407 set_size(maxrows, maxcols, true); 00408 } 00409 } 00410 this->operator()(rows-1, cols - 1).set_shift(default_shift); 00411 buffer >> this->operator()(rows-1, cols - 1); // May override default_shift 00412 while (buffer.peek() == ' ') { buffer.get(); } 00413 } 00414 } 00415 if (!buffer.eof()) 00416 buffer.get(); 00417 } 00418 set_size(rows, nocols, true); 00419 } 00420 00421 } // namespace itpp
Generated on Fri May 1 11:09:18 2009 for IT++ by Doxygen 1.5.8