/*---------------------------------------------------------------------------*
 *                                   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.10
  
  2004/09/28 20:19:48
*/

#ifndef __cfix_h
#define __cfix_h

#include "base/fix_base.h"
#include "base/fix_factory.h"
#include "base/fix.h"

namespace itpp {

  // Forward declarations
  template<class Num_T> class Vec;
  template<class Num_T> class Mat;

  //! \addtogroup fixtypes
  //!@{

  /*!
    \brief Complex fixed-point data type.
  
    See the Detailed Description in the \ref fixtypes module.
  */
  class CFix : public Fix_Base {
    template<int, e_mode, o_mode, q_mode> friend class CFixed;
  public:
    //! Default constructor
    CFix(double r=0.0, double i=0.0, int s=0, int w=MAX_WORDLEN, e_mode e=TC, o_mode o=WRAP, q_mode q=TRN, Stat *ptr=0)
      : Fix_Base(s, w, e, o, q, ptr), re(scale_and_apply_modes(r)), im(scale_and_apply_modes(i)) {}
    //! Constructor
    CFix(std::complex<double> x, double dummy=0.0, int s=0, int w=MAX_WORDLEN, e_mode e=TC, o_mode o=WRAP, q_mode q=TRN, Stat *ptr=0)
      : Fix_Base(s, w, e, o, q, ptr), re(scale_and_apply_modes(std::real(x))), im(scale_and_apply_modes(std::imag(x))) {}
    //! Constructor
    explicit CFix(const Fix_Factory &f)
      : Fix_Base(0, f.wordlen, f.emode, f.omode, f.qmode, f.stat_ptr), re(0), im(0) {}
    //! Constructor for internal use. No restrictions are applied. The dummies help to avoid ambiguities
    CFix(fixrep r, fixrep i, int s, int dummy1, int dummy2)
      : Fix_Base(s), re(r), im(i) {}
    //! Constructor
    CFix(const Fix &r, const Fix &i=0.0, int w=MAX_WORDLEN, e_mode e=TC, o_mode o=WRAP, q_mode q=TRN, Stat *ptr=0)
      : Fix_Base(assert_shifts(r, i), w, e, o, q, ptr), re(r.re), im(i.re) {}
    //! Copy constructor
    CFix(const CFix &x, double dummy=0.0, int w=MAX_WORDLEN, e_mode e=TC, o_mode o=WRAP, q_mode q=TRN, Stat *ptr=0)
      : Fix_Base(x.shift, w, e, o, q, ptr), re(x.re), im(x.im) {}
    //! Destructor
    virtual ~CFix() {}

    //! Assignment from CFix
    CFix& operator=(const CFix &x);
    //! Assignment from Fix
    CFix& operator=(const Fix &x);
    //! Assignment from complex<double>. Fractional part is truncated
    CFix& operator=(const std::complex<double> &x);
    //! Assignment from int
    CFix& operator=(const int x);
    //! Addition of CFix
    CFix& operator+=(const CFix &x);
    //! Addition of Fix
    CFix& operator+=(const Fix &x);
    //! Addition of int
    CFix& operator+=(const int x);
    //! Subtraction of CFix
    CFix& operator-=(const CFix &x);
    //! Subtraction of Fix
    CFix& operator-=(const Fix &x);
    //! Subtraction of int
    CFix& operator-=(const int x);
    //! Multiplication with CFix. Temporary variables use the maximum word length (64 bits)
    CFix& operator*=(const CFix &x);
    //! Multiplication with Fix. Temporary variables use the maximum word length (64 bits)
    CFix& operator*=(const Fix &x);
    //! Multiplication with int. Temporary variables use the maximum word length (64 bits)
    CFix& operator*=(const int x);
    //! Division with CFix using quantization mode \c TRN. Temporary variables use the maximum word length (64 bits)
    CFix& operator/=(const CFix &x);
    //! Division with Fix using quantization mode \c TRN. Temporary variables use the maximum word length (64 bits)
    CFix& operator/=(const Fix &x);
    //! Division with int using quantization mode \c TRN. Temporary variables use the maximum word length (64 bits)
    CFix& operator/=(const int x);
    //! Unary negative of CFix
    CFix operator-() const;
    //! Left shift \c n bits
    CFix& operator<<=(const int n);
    //! Right shift \c n bits using quantization mode \c qmode (constructor argument)
    CFix& operator>>=(const int n);

    //! Set to <tt>(real + i*imag) * pow2(n)</tt> using quantization mode \c qmode (constructor argument)
    void set(double real, double imag, int n);
    //! Set to <tt>(real + i*imag) * pow2(n)</tt> using quantization mode \c q (function argument)
    void set(double real, double imag, int n, q_mode q);
    //! Set to <tt>x * pow2(n)</tt> using quantization mode \c qmode (constructor argument)
    void set(const complex<double> &x, int n);
    //! Set to <tt>x * pow2(n)</tt> using quantization mode \c q (function argument)
    void set(const complex<double> &x, int n, q_mode q);
    //! Set data representation for real part (mainly for internal use since it reveals the representation type)
    void set_re(fixrep x) {re = apply_o_mode(x);}
    //! Set data representation for imaginary part (mainly for internal use since it reveals the representation type)
    void set_im(fixrep x) {im = apply_o_mode(x);}

    //! Left shift \c n bits
    void lshift(int n);
    //! Right shift \c n bits using quantization mode \c qmode (constructor argument)
    void rshift(int n);
    //! Right shift \c n bits using quantization mode \c q (function argument)
    void rshift(int n, q_mode q);

    //! Print restrictions
    virtual void print() const;
    //! Get data representation for real part (mainly for internal use since it reveals the representation type)
    fixrep get_re() const {return re;}
    //! Get data representation for imaginary part (mainly for internal use since it reveals the representation type)
    fixrep get_im() const {return im;}
    //! Conversion to complex<double>
    std::complex<double> unfix() const;

#ifndef NO_IMPLICIT_FIX_CONVERSION
    //! Conversion to complex<double>
    operator std::complex<double>() const
    {
      it_assert1(shift>=-63 && shift<=64, "CFix::operator complex<double>: Illegal shift!");
      return complex<double>(double(re)*DOUBLE_POW2[64 - shift],
                             double(im)*DOUBLE_POW2[64 - shift]);
    }
#endif

    //! Check that x.shift==y.shift OR x==0 OR y==0 and return the shift (for the non-zero argument)
    friend int assert_shifts(const CFix &x, const CFix &y);
    //! Check that x.shift==y.shift OR x==0 OR y==0 and return the shift (for the non-zero argument)
    friend int assert_shifts(const CFix &x, const Fix &y);
    //! Check that x.shift==0 OR x==0 OR y==0 and return x.shift
    friend int assert_shifts(const CFix &x, int y);

  protected:
    //! Data representation
    fixrep re, im;
  };

  //! Input bit representation and, optionally, the shift
  std::istream &operator>>(std::istream &is, CFix &x);
  //! Output bit representation and, optionally, the shift
  std::ostream &operator<<(std::ostream &os, const CFix &x);

  //! Typedef for complex fixed-point vector type
  typedef Vec<CFix> cfixvec;
  //! Typedef for complex fixed-point matrix type
  typedef Mat<CFix> cfixmat;

  //!@}

} //namespace itpp

#endif // __cfix_h


syntax highlighted by Code2HTML, v. 0.9.1