aboutsummaryrefslogtreecommitdiffhomepage
path: root/unsupported/Eigen/Complex
blob: 04228c95a05c93a153cc34df6c6437e988ad06f5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#ifndef EIGEN_COMPLEX_H
#define EIGEN_COMPLEX_H

// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2009 Mark Borgerding mark a borgerding net
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

// Eigen::Complex reuses as much as possible from std::complex
// and allows easy conversion to and from, even at the pointer level.


#include <complex>

namespace Eigen {

template <typename _NativeData,typename _PunnedData>
struct castable_pointer
{
    castable_pointer(_NativeData * ptr) : _ptr(ptr) { }
    operator _NativeData * ()  {return _ptr;}
    operator _PunnedData * ()  {return reinterpret_cast<_PunnedData*>(_ptr);}
    operator const _NativeData * () const {return _ptr;}
    operator const _PunnedData * () const {return reinterpret_cast<_PunnedData*>(_ptr);}
    private: 
    _NativeData *  _ptr;
};

template <typename _NativeData,typename _PunnedData>
struct const_castable_pointer
{
    const_castable_pointer(_NativeData * ptr) : _ptr(ptr) { }
    operator const _NativeData * () const {return _ptr;}
    operator const _PunnedData * () const {return reinterpret_cast<_PunnedData*>(_ptr);}
    private: 
    _NativeData * _ptr;
};

template <typename T>
struct Complex
{
    typedef typename std::complex<T> StandardComplex;
    typedef T value_type;

    // constructors
    Complex() {}
    Complex(const T& re, const T& im = T()) : _re(re),_im(im) { }
    Complex(const Complex&other ): _re(other.real()) ,_im(other.imag()) {}

    template<class X> 
    Complex(const Complex<X>&other): _re(other.real()) ,_im(other.imag()) {}
    template<class X> 
    Complex(const std::complex<X>&other): _re(other.real()) ,_im(other.imag()) {}

    // allow binary access to the object as a std::complex
    typedef castable_pointer< Complex<T>, StandardComplex > pointer_type;
    typedef const_castable_pointer< Complex<T>, StandardComplex > const_pointer_type;

    inline
    pointer_type operator & () {return pointer_type(this);}

    inline
    const_pointer_type operator & () const {return const_pointer_type(this);}

    inline
    operator StandardComplex () const {return std_type();}
    inline
    operator StandardComplex & () {return std_type();}

    inline
    const StandardComplex & std_type() const {return *reinterpret_cast<const StandardComplex*>(this);}

    inline
    StandardComplex & std_type() {return *reinterpret_cast<StandardComplex*>(this);}


    // every sort of accessor and mutator that has ever been in fashion.
    // For a brief history, search for "std::complex over-encapsulated"
    // http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#387
    inline
    const T & real() const {return _re;}
    inline
    const T & imag() const {return _im;}
    inline
    T & real() {return _re;}
    inline
    T & imag() {return _im;}
    inline
    T & real(const T & x) {return _re=x;}
    inline
    T & imag(const T & x) {return _im=x;}
    inline
    void set_real(const T & x) {_re = x;}
    inline
    void set_imag(const T & x) {_im = x;}

    // *** complex member functions: ***
    inline
    Complex<T>& operator= (const T& val) { _re=val;_im=0;return *this;  }
    inline
    Complex<T>& operator+= (const T& val) {_re+=val;return *this;}
    inline
    Complex<T>& operator-= (const T& val) {_re-=val;return *this;}
    inline
    Complex<T>& operator*= (const T& val) {_re*=val;_im*=val;return *this;  }
    inline
    Complex<T>& operator/= (const T& val) {_re/=val;_im/=val;return *this;  }

    inline
    Complex& operator= (const Complex& rhs) {_re=rhs._re;_im=rhs._im;return *this;}
    inline
    Complex& operator= (const StandardComplex& rhs) {_re=rhs.real();_im=rhs.imag();return *this;}

    template<class X> Complex<T>& operator= (const Complex<X>& rhs) { _re=rhs._re;_im=rhs._im;return *this;}
    template<class X> Complex<T>& operator+= (const Complex<X>& rhs) { _re+=rhs._re;_im+=rhs._im;return *this;}
    template<class X> Complex<T>& operator-= (const Complex<X>& rhs) { _re-=rhs._re;_im-=rhs._im;return *this;}
    template<class X> Complex<T>& operator*= (const Complex<X>& rhs) { this->std_type() *= rhs.std_type(); return *this; }
    template<class X> Complex<T>& operator/= (const Complex<X>& rhs) { this->std_type() /= rhs.std_type(); return *this; }

    private:
    T _re;
    T _im;
};

//template <typename T> T ei_to_std( const T & x) {return x;}

template <typename T>
std::complex<T> ei_to_std( const Complex<T> & x) {return x.std_type();}

// 26.2.6 operators
template<class T> Complex<T> operator+(const Complex<T>& rhs) {return rhs;}
template<class T> Complex<T> operator-(const Complex<T>& rhs) {return -ei_to_std(rhs);}

template<class T> Complex<T> operator+(const Complex<T>& lhs, const Complex<T>& rhs) { return ei_to_std(lhs) + ei_to_std(rhs);}
template<class T> Complex<T> operator-(const Complex<T>& lhs, const Complex<T>& rhs) { return ei_to_std(lhs) - ei_to_std(rhs);}
template<class T> Complex<T> operator*(const Complex<T>& lhs, const Complex<T>& rhs) { return ei_to_std(lhs) * ei_to_std(rhs);}
template<class T> Complex<T> operator/(const Complex<T>& lhs, const Complex<T>& rhs) { return ei_to_std(lhs) / ei_to_std(rhs);}
template<class T> bool operator==(const Complex<T>& lhs, const Complex<T>& rhs) { return ei_to_std(lhs) == ei_to_std(rhs);}
template<class T> bool operator!=(const Complex<T>& lhs, const Complex<T>& rhs) { return ei_to_std(lhs) != ei_to_std(rhs);}

template<class T> Complex<T> operator+(const Complex<T>& lhs, const T& rhs) {return ei_to_std(lhs) + ei_to_std(rhs); }
template<class T> Complex<T> operator-(const Complex<T>& lhs, const T& rhs) {return ei_to_std(lhs) - ei_to_std(rhs); }
template<class T> Complex<T> operator*(const Complex<T>& lhs, const T& rhs) {return ei_to_std(lhs) * ei_to_std(rhs); }
template<class T> Complex<T> operator/(const Complex<T>& lhs, const T& rhs) {return ei_to_std(lhs) / ei_to_std(rhs); }
template<class T> bool operator==(const Complex<T>& lhs, const T& rhs) {return ei_to_std(lhs) == ei_to_std(rhs); }
template<class T> bool operator!=(const Complex<T>& lhs, const T& rhs) {return ei_to_std(lhs) != ei_to_std(rhs); }

template<class T> Complex<T> operator+(const T& lhs, const Complex<T>& rhs) {return ei_to_std(lhs) + ei_to_std(rhs); }
template<class T> Complex<T> operator-(const T& lhs, const Complex<T>& rhs) {return ei_to_std(lhs) - ei_to_std(rhs); }
template<class T> Complex<T> operator*(const T& lhs, const Complex<T>& rhs) {return ei_to_std(lhs) * ei_to_std(rhs); }
template<class T> Complex<T> operator/(const T& lhs, const Complex<T>& rhs) {return ei_to_std(lhs) / ei_to_std(rhs); }
template<class T> bool operator==(const T& lhs, const Complex<T>& rhs) {return ei_to_std(lhs) == ei_to_std(rhs); }
template<class T> bool operator!=(const T& lhs, const Complex<T>& rhs) {return ei_to_std(lhs) != ei_to_std(rhs); }

template<class T, class charT, class traits>
std::basic_istream<charT,traits>&
  operator>> (std::basic_istream<charT,traits>& istr, Complex<T>& rhs)
{
    return istr >> rhs.std_type();
}

template<class T, class charT, class traits>
std::basic_ostream<charT,traits>&
operator<< (std::basic_ostream<charT,traits>& ostr, const Complex<T>& rhs)
{
    return ostr << rhs.std_type();
}

 // 26.2.7 values:
 template<class T> T real(const Complex<T>&x) {return real(ei_to_std(x));}
 template<class T> T abs(const Complex<T>&x) {return abs(ei_to_std(x));}
 template<class T> T arg(const Complex<T>&x) {return arg(ei_to_std(x));}
 template<class T> T norm(const Complex<T>&x) {return norm(ei_to_std(x));}

 template<class T> Complex<T> conj(const Complex<T>&x) { return conj(ei_to_std(x));}
 template<class T> Complex<T> polar(const T& x, const T&y) {return polar(ei_to_std(x),ei_to_std(y));} 
 // 26.2.8 transcendentals:
 template<class T> Complex<T> cos (const  Complex<T>&x){return cos(ei_to_std(x));}
 template<class T> Complex<T> cosh (const  Complex<T>&x){return cosh(ei_to_std(x));}
 template<class T> Complex<T> exp (const  Complex<T>&x){return exp(ei_to_std(x));}
 template<class T> Complex<T> log (const  Complex<T>&x){return log(ei_to_std(x));}
 template<class T> Complex<T> log10 (const  Complex<T>&x){return log10(ei_to_std(x));}

 template<class T> Complex<T> pow(const Complex<T>&x, int p) {return pow(ei_to_std(x),p);}
 template<class T> Complex<T> pow(const Complex<T>&x, const T&p) {return pow(ei_to_std(x),ei_to_std(p));}
 template<class T> Complex<T> pow(const Complex<T>&x, const Complex<T>&p) {return pow(ei_to_std(x),ei_to_std(p));}
 template<class T> Complex<T> pow(const T&x, const Complex<T>&p) {return pow(ei_to_std(x),ei_to_std(p));}

 template<class T> Complex<T> sin (const  Complex<T>&x){return sin(ei_to_std(x));}
 template<class T> Complex<T> sinh (const  Complex<T>&x){return sinh(ei_to_std(x));}
 template<class T> Complex<T> sqrt (const  Complex<T>&x){return sqrt(ei_to_std(x));}
 template<class T> Complex<T> tan (const  Complex<T>&x){return tan(ei_to_std(x));}
 template<class T> Complex<T> tanh (const  Complex<T>&x){return tanh(ei_to_std(x));}

  template<typename _Real> struct NumTraits<Complex<_Real> >
  {
    typedef _Real Real;
    typedef Complex<_Real> FloatingPoint;
    enum {
      IsComplex = 1,
      HasFloatingPoint = NumTraits<Real>::HasFloatingPoint,
      ReadCost = 2,
      AddCost = 2 * NumTraits<Real>::AddCost,
      MulCost = 4 * NumTraits<Real>::MulCost + 2 * NumTraits<Real>::AddCost
    };
  };
}
#endif
/* vim: set filetype=cpp et sw=2 ts=2 ai: */