/*---------------------------------------------------------------------------* * IT++ * *---------------------------------------------------------------------------* * Copyright (c) 2004 by Johan Bergman. * * * * Permission to use, copy, modify, and distribute this software and its * * documentation under the terms of the GNU General Public License is hereby * * granted. No representations are made about the suitability of this * * software for any purpose. It is provided "as is" without expressed or * * implied warranty. See the GNU General Public License for more details. * *---------------------------------------------------------------------------*/ /*! \file \brief Complex fixed-point data type CFix \author Johan Bergman 1.13 2004/09/28 20:19:33 */ #include "base/cfix.h" #include "base/itassert.h" #include using std::cout; using std::endl; using std::complex; namespace itpp { CFix& CFix::operator=(const CFix &x) { shift = x.shift; re = apply_o_mode(x.re); im = apply_o_mode(x.im); return *this; } CFix& CFix::operator=(const Fix &x) { shift = x.shift; re = apply_o_mode(x.re); im = 0; return *this; } CFix& CFix::operator=(const complex &x) { shift = 0; re = apply_o_mode(fixrep(std::real(x))); im = apply_o_mode(fixrep(std::imag(x))); return *this; } CFix& CFix::operator=(const int x) { shift = 0; re = apply_o_mode(x); im = 0; return *this; } CFix& CFix::operator+=(const CFix &x) { shift = assert_shifts(*this, x); re = apply_o_mode(re + x.re); im = apply_o_mode(im + x.im); return *this; } CFix& CFix::operator+=(const Fix &x) { shift = assert_shifts(*this, x); re = apply_o_mode(re + x.re); return *this; } CFix& CFix::operator+=(const int x) { assert_shifts(*this, x); re = apply_o_mode(re + x); return *this; } CFix& CFix::operator-=(const CFix &x) { shift = assert_shifts(*this, x); re = apply_o_mode(re - x.re); im = apply_o_mode(im - x.im); return *this; } CFix& CFix::operator-=(const Fix &x) { shift = assert_shifts(*this, x); re = apply_o_mode(re - x.re); return *this; } CFix& CFix::operator-=(const int x) { assert_shifts(*this, x); re = apply_o_mode(re - x); return *this; } CFix& CFix::operator*=(const CFix &x) { shift += x.shift; fixrep tmp_re = apply_o_mode(re*x.re - im*x.im); im = apply_o_mode(re*x.im + im*x.re); re = tmp_re; return *this; } CFix& CFix::operator*=(const Fix &x) { shift += x.shift; re = apply_o_mode(re*x.re); im = apply_o_mode(im*x.re); return *this; } CFix& CFix::operator*=(const int x) { re = apply_o_mode(re*x); im = apply_o_mode(im*x); return *this; } CFix& CFix::operator/=(const CFix &x) { shift -= x.shift; fixrep denominator = x.re*x.re + x.im*x.im; fixrep tmp_re = apply_o_mode((re*x.re + im*x.im)/denominator); im = apply_o_mode((im*x.re - re*x.im)/denominator); re = tmp_re; return *this; } CFix& CFix::operator/=(const Fix &x) { shift -= x.shift; re = apply_o_mode(re/x.re); im = apply_o_mode(im/x.re); return *this; } CFix& CFix::operator/=(const int x) { re = apply_o_mode(re/x); im = apply_o_mode(im/x); return *this; } CFix CFix::operator-() const { return CFix(-re, -im, shift, 0, 0); } CFix& CFix::operator<<=(const int n) { it_assert1(n >= 0, "CFix::operator<<=: n cannot be negative!"); shift += n; re = apply_o_mode(re << n); im = apply_o_mode(im << n); return *this; } CFix& CFix::operator>>=(const int n) { shift -= n; re = rshift_and_apply_q_mode(re, n); im = rshift_and_apply_q_mode(im, n); return *this; } void CFix::set(double real, double imag, int n) { shift = n; re = scale_and_apply_modes(real); im = scale_and_apply_modes(imag); } void CFix::set(double real, double imag, int n, q_mode q) { shift = n; re = scale_and_apply_modes(real, q); im = scale_and_apply_modes(imag, q); } void CFix::set(const complex &x, int n) { shift = n; re = scale_and_apply_modes(std::real(x)); im = scale_and_apply_modes(std::imag(x)); } void CFix::set(const complex &x, int n, q_mode q) { shift = n; re = scale_and_apply_modes(std::real(x), q); im = scale_and_apply_modes(std::imag(x), q); } void CFix::lshift(int n) { it_assert1(n >= 0, "CFix::lshift: n cannot be negative!"); shift += n; re = apply_o_mode(re << n); im = apply_o_mode(im << n); } void CFix::rshift(int n) { shift -= n; re = rshift_and_apply_q_mode(re, n); im = rshift_and_apply_q_mode(im, n); } void CFix::rshift(int n, q_mode q) { shift -= n; re = rshift_and_apply_q_mode(re, n, q); im = rshift_and_apply_q_mode(im, n, q); } complex CFix::unfix() const { it_assert1(shift>=-63 && shift<=64, "CFix::unfix: Illegal shift!"); return complex(double(re)*DOUBLE_POW2[64 - shift], double(im)*DOUBLE_POW2[64 - shift]); } void CFix::print() const { Fix_Base::print(); cout << "re = " << re << endl; cout << "im = " << im << endl; } int assert_shifts(const CFix &x, const CFix &y) { int ret = 0; if (x.shift == y.shift) ret = x.shift; else if (x.re == 0 && x.im == 0) ret = y.shift; else if (y.re == 0 && y.im == 0) ret = x.shift; else it_error("assert_shifts: Different shifts not allowed!"); return ret; } int assert_shifts(const CFix &x, const Fix &y) { int ret = 0; if (x.shift == y.shift) ret = x.shift; else if (x.re == 0 && x.im == 0) ret = y.shift; else if (y.re == 0) ret = x.shift; else it_error("assert_shifts: Different shifts not allowed!"); return ret; } int assert_shifts(const CFix &x, int y) { if ((x.shift != 0) && !(x.re==0 && x.im==0) && (y != 0)) it_error("assert_shifts: Different shifts not allowed!"); return x.shift; } std::istream &operator>>(std::istream &is, CFix &x) { complex value; is >> value; if (!is.eof() && (is.peek() == '<')) { int shift; is.get(); // Swallow '<' sign if (is.peek() == '<') { is.get(); // Swallow '<' sign is >> shift; x.set(value, shift); } else { is >> shift; is.get(); // Swallow '>' sign x.set_re(fixrep(std::real(value))); x.set_im(fixrep(std::imag(value))); x.set_shift(shift); } } else { // Change data representation but keep shift x.set_re(fixrep(std::real(value))); x.set_im(fixrep(std::imag(value))); } return is; } std::ostream &operator<<(std::ostream &os, const CFix &x) { switch (x.get_output_mode()) { case OUTPUT_FIX: if (x.get_im() < 0) os << x.get_re() << x.get_im() << 'i'; else os << x.get_re() << '+' << x.get_im() << 'i'; break; case OUTPUT_FIX_SHIFT: if (x.get_im() < 0) os << x.get_re() << x.get_im() << 'i'; else os << x.get_re() << '+' << x.get_im() << 'i'; os << '<' << x.get_shift() << '>'; break; case OUTPUT_FLOAT: os << complex(x); break; case OUTPUT_FLOAT_SHIFT: os << complex(x) << "<<" << x.get_shift(); break; default: it_error("operator<<: Illegal output mode!"); } return os; } // Specialization of template definition in vec.cpp template<> bool cfixvec::set(const char *values) { istringstream buffer(values); int default_shift=0, pos=0, maxpos=10; if (datasize > 0) { // Assume that all elements have the same shift default_shift = data[0].get_shift(); } alloc(maxpos); while (buffer.peek()!=EOF) { switch (buffer.peek()) { case ':': it_error("set: expressions with ':' are not valid for cfixvec"); break; case ',': buffer.get(); break; default: pos++; if (pos > maxpos) { maxpos *= 2; set_size(maxpos, true); } data[pos-1].set_shift(default_shift); buffer >> data[pos-1]; // May override default_shift while (buffer.peek()==' ') { buffer.get(); } break; } } set_size(pos, true); return true; } // Specialization of template definition in mat.cpp template<> bool cfixmat::set(const char *values) { istringstream buffer(values); int default_shift=0, rows=0, maxrows=10, cols=0, nocols=0, maxcols=10; if (datasize > 0) { // Assume that all elements have the same shift default_shift = data[0].get_shift(); } alloc(maxrows, maxcols); while (buffer.peek()!=EOF) { rows++; if (rows > maxrows) { maxrows=maxrows*2; set_size(maxrows, maxcols, true); } cols=0; while ( (buffer.peek() != ';') && (buffer.peek() != EOF) ) { if (buffer.peek()==',') { buffer.get(); } else { cols++; if (cols > nocols) { nocols=cols; if (cols > maxcols) { maxcols=maxcols*2; set_size(maxrows, maxcols, true); } } this->operator()(rows-1,cols-1).set_shift(default_shift); buffer >> this->operator()(rows-1,cols-1); // May override default_shift while (buffer.peek()==' ') { buffer.get(); } } } if (!buffer.eof()) buffer.get(); } set_size(rows, nocols, true); return true; } } //namespace itpp