/*---------------------------------------------------------------------------*
* 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 <iostream>
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<double> &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<double> &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<double> &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<double> CFix::unfix() const
{
it_assert1(shift>=-63 && shift<=64, "CFix::unfix: Illegal shift!");
return complex<double>(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<double> 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<double>(x);
break;
case OUTPUT_FLOAT_SHIFT:
os << complex<double>(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
syntax highlighted by Code2HTML, v. 0.9.1