FComplex.hpp 8.04 KB
Newer Older
1
// ===================================================================================
2 3 4 5 6 7 8 9 10 11 12 13
// olivier.coulaud@inria.fr, berenger.bramas@inria.fr
// This software is a computer program whose purpose is to compute the FMM.
//
// This software is governed by the CeCILL-C and LGPL licenses and
// abiding by the rules of distribution of free software.  
// 
// This program 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 General Public and CeCILL-C Licenses for more details.
// "http://www.cecill.info". 
// "http://www.gnu.org/licenses".
14
// ===================================================================================
15 16
#ifndef FCOMPLEXE_HPP
#define FCOMPLEXE_HPP
17

18
#include <array>
19 20 21 22
#include "FMath.hpp"

/**
* @author Berenger Bramas (berenger.bramas@inria.fr)
23
* @class FComplex<FReal>.hpp
24 25
*
* This class is a basic implementation of Complexe.
26 27 28 29 30
* Please read the license
*
* Propose basic complexe class.
* Do not modify the attributes of this class.
* It can be passed to blas fonction and has to be
31
* 2 x complex[0] size only.
32
*/
33
template <class FReal>
34
class FComplex {
35 36
  //std::array<FReal,2> complex;    //< Real & Imaginary
  FReal complex[2];    //< Real & Imaginary
37 38

public:
39
    /** Default Constructor (set complex[0]&imaginary to 0) */
40
    FComplex() {
41 42
        complex[0] = 0;
        complex[1] = 0;
43 44 45 46
    }

    /** Constructor with values
      * @param inImag the imaginary
47
      * @param inReal the complex[0]
48
      */
49
    explicit FComplex(const FReal inReal, const FReal inImag) {
50 51
        complex[0] = inReal;
        complex[1] = inImag;
52 53 54
    }

    /** Copy constructor */
55
    FComplex(const FComplex<FReal>& other){
56 57
        complex[0] = other.complex[0];
        complex[1] = other.complex[1];
58 59 60
    }

    /** Copy operator */
61
    FComplex<FReal>& operator=(const FComplex<FReal>& other){
62
        this->complex[0] = other.complex[0];
BRAMAS Berenger's avatar
BRAMAS Berenger committed
63
        this->complex[1] = other.complex[1];
64 65 66 67
        return *this;
    }

    /** Equality operator */
68
    bool operator==(const FComplex<FReal>& other){
69 70
        return FMath::LookEqual(this->complex[1],other.complex[1])
                       && FMath::LookEqual(this->complex[0],other.complex[0]);
71 72 73
    }

    /** Different equal */
74
    bool operator!=(const FComplex<FReal>& other){
75 76 77
        return !(*this == other);
    }

78 79 80 81
    /** Get imaginary */
    FReal imag() const{
        return this->complex[1];
    }
82 83
    /** Get imaginary */
    FReal getImag() const{
84
        return this->complex[1];
85 86
    }

87 88 89 90
    /** Get complex[0] */
    FReal real() const{
        return this->complex[0];
    }
91
    /** Get complex[0] */
92
    FReal getReal() const{
93
        return this->complex[0];
94 95 96 97
    }

    /** Set Imaginary */
    void setImag(const FReal inImag) {
98
        this->complex[1] = inImag;
99 100 101 102
    }

    /** Set Real */
    void setReal(const FReal inReal) {
103 104 105 106 107 108 109
        this->complex[0] = inReal;
    }

    /** Set Real and imaginary */
    void setRealImag(const FReal inReal, const FReal inImag) {
        this->complex[0] = inReal;
        this->complex[1] = inImag;
110 111
    }

BRAMAS Berenger's avatar
BRAMAS Berenger committed
112
    /** Return the conjugate */
113
    FComplex<FReal> conjugate() const{
114
        return FComplex(complex[0],-complex[1]);
BRAMAS Berenger's avatar
BRAMAS Berenger committed
115 116 117
    }

    /** Return the conjugate */
118
    FComplex<FReal> negate() const{
119
        return FComplex(-complex[0],-complex[1]);
BRAMAS Berenger's avatar
BRAMAS Berenger committed
120
    }
COULAUD Olivier's avatar
COULAUD Olivier committed
121 122 123 124 125 126 127 128 129 130 131 132
    /**
     *  return the square of the  modulus of the complex number
     */
    FReal norm2() const{
    		return complex[0]*complex[0]+complex[1]*complex[1] ;
    }
    /**
     *  return the modulus of the complex number
     */
    FReal norm() const{
    		return FMath::Sqrt(this->norm2() );
    }
133 134
    /**
     * Operator +=
135
     * in complex[0] with other complex[0], same for complex[1]
COULAUD Olivier's avatar
COULAUD Olivier committed
136
     * @param other the complex to use data
137
     */
138
    FComplex<FReal>& operator+=(const FComplex<FReal>& other){
139 140
        this->complex[0] += other.complex[0];
        this->complex[1] += other.complex[1];
141 142 143
        return *this;
    }   

144 145 146
    /** Inc complex[0] and imaginary by values
      * @param inIncReal to inc the complex[0]
      * @param inIncImag to inc the complex[1]
147 148
      */
    void inc(const FReal inIncReal, const FReal inIncImag){
149 150
        this->complex[0] += inIncReal;
        this->complex[1] += inIncImag;
151 152
    }

153 154
    /** Inc complex[0] by FReal
      * @param inIncReal to inc the complex[0]
155 156
      */
    void incReal(const FReal inIncReal){
157
        this->complex[0] += inIncReal;
158 159 160
    }

    /** Inc imaginary by FReal
161
      * @param inIncImag to inc the complex[1]
162 163
      */
    void incImag(const FReal inIncImag){
164
        this->complex[1] += inIncImag;
165 166
    }

167 168
    /** Dec complex[0] by FReal
      * @param inDecReal to dec the complex[0]
169 170
      */
    void decReal(const FReal inIncReal){
171
        this->complex[0] -= inIncReal;
172 173 174
    }

    /** Dec imaginary by FReal
175
      * @param inDecImag to dec the complex[1]
176 177
      */
    void decImag(const FReal inIncImag){
178
        this->complex[1] -= inIncImag;
179 180
    }

181
    /** Mul complex[0] and imaginary by a FReal
182 183 184
      * @param inValue the coef to mul data
      */
    void mulRealAndImag(const FReal inValue){
185 186
        this->complex[1] *= inValue;
        this->complex[0] *= inValue;
187 188 189
    }

    /** Mul a complexe by another "c*=c2" */
190
    FComplex<FReal>& operator*=(const FComplex<FReal>& other){
191 192 193
        const FReal tempReal = this->complex[0];
        this->complex[0] = (tempReal * other.complex[0]) - (this->complex[1] * other.complex[1]);
        this->complex[1] = (tempReal * other.complex[1]) + (this->complex[1] * other.complex[0]);
194 195
        return *this;
    }
196

197
    /** Mul a complexe by another "c*=c2" */
198
    FComplex<FReal>& operator*=(const FReal& real){
199 200 201 202 203
        this->complex[0] *= real;
        this->complex[1] *= real;
        return *this;
    }

BRAMAS Berenger's avatar
BRAMAS Berenger committed
204
    /** Mul a complexe by another "c*=c2" */
205
    FComplex<FReal>& operator/=(const FReal& real){
BRAMAS Berenger's avatar
BRAMAS Berenger committed
206 207 208 209 210
        this->complex[0] /= real;
        this->complex[1] /= real;
        return *this;
    }

211 212
    /** Test if a complex is not a number */
    bool isNan() const {
213
        return FMath::IsNan(complex[1]) || FMath::IsNan(complex[0]);
214
    }
215 216

    /** Mul other and another and add the result to current complexe */
217
    void addMul(const FComplex<FReal>& other, const FComplex<FReal>& another){
218 219 220
        this->complex[0] += (other.complex[0] * another.complex[0]) - (other.complex[1] * another.complex[1]);
        this->complex[1] += (other.complex[0] * another.complex[1]) + (other.complex[1] * another.complex[0]);
    }
221

BRAMAS Berenger's avatar
BRAMAS Berenger committed
222
    /** Mul other and another and add the result to current complexe */
223
    void equalMul(const FComplex<FReal>& other, const FComplex<FReal>& another){
BRAMAS Berenger's avatar
BRAMAS Berenger committed
224 225 226 227
        this->complex[0] = (other.complex[0] * another.complex[0]) - (other.complex[1] * another.complex[1]);
        this->complex[1] = (other.complex[0] * another.complex[1]) + (other.complex[1] * another.complex[0]);
    }

228
    /** To cast to FReal */
229
    static FReal* ToFReal(FComplex<FReal>*const array){
230 231 232 233
        return reinterpret_cast<FReal*>(array);
    }

    /** To cast to FReal */
234
    static const FReal* ToFReal(const FComplex<FReal>*const array){
235 236
        return reinterpret_cast<const FReal*>(array);
    }
237
    /**
238
     * Operator stream FComplex<FReal> to std::ostream
239 240 241 242 243
     * This can be used to simpldata[1] write out a complex with format (Re,Im)
     * @param[in,out] output where to write the position
     * @param[in] inPosition the position to write out
     * @return the output for multiple << operators
     */
244
    template <class StreamClass>
245
    friend StreamClass& operator<<(StreamClass& output, const FComplex<FReal>& inC){
246 247 248 249
        output << "(" <<  inC.getReal() << ", " << inC.getImag() << ")";
        return output;  // for multiple << operators.
    }

250 251 252
};

/** Global operator Mul a complexe by another "c=c1*c2" */
253 254 255
template <class FReal>
inline FComplex<FReal> operator*=(const FComplex<FReal>& first, const FComplex<FReal>& second){
    return FComplex<FReal>(
256 257 258 259 260 261 262
            (first.getReal() * second.getImag()) + (first.getImag() * second.getReal()),
            (first.getReal() * second.getReal()) - (first.getImag() * second.getImag())
            );
}

#endif //FCOMPLEXE_HPP

263