FComplex.hpp 8.06 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 41 42 43 44
  FComplex() = default ;// complex({0.0,0.0}){}
  //{
//        complex[0] = 0;
//        complex[1] = 0;
//    }
45 46 47

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

    /** Copy constructor */
57
    FComplex(const FComplex<FReal>& other){
58 59
        complex[0] = other.complex[0];
        complex[1] = other.complex[1];
60
    }
61 62 63 64 65
    /** Move constructor */
    FComplex<FReal>(FComplex<FReal> &&c)
    {
      std::move(std::begin(c.complex), std::end(c.complex), complex);
    }
66
    /** Copy operator */
67
    FComplex<FReal>& operator=(const FComplex<FReal>& other){
68
        this->complex[0] = other.complex[0];
BRAMAS Berenger's avatar
BRAMAS Berenger committed
69
        this->complex[1] = other.complex[1];
70 71 72 73
        return *this;
    }

    /** Equality operator */
74
    bool operator==(const FComplex<FReal>& other){
75 76
        return FMath::LookEqual(this->complex[1],other.complex[1])
                       && FMath::LookEqual(this->complex[0],other.complex[0]);
77 78 79
    }

    /** Different equal */
80
    bool operator!=(const FComplex<FReal>& other){
81 82 83
        return !(*this == other);
    }

84

85 86 87 88
    /** Get imaginary */
    FReal imag() const{
        return this->complex[1];
    }
89

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

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

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

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

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

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

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

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

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

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

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

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

    /** Mul a complexe by another "c*=c2" */
189
    FComplex<FReal>& operator*=(const FComplex<FReal>& other){
190 191 192
        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]);
193 194
        return *this;
    }
195

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

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

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

    /** Mul other and another and add the result to current complexe */
216
    void addMul(const FComplex<FReal>& other, const FComplex<FReal>& another){
217 218 219
        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]);
    }
220

BRAMAS Berenger's avatar
BRAMAS Berenger committed
221
    /** Mul other and another and add the result to current complexe */
222
    void equalMul(const FComplex<FReal>& other, const FComplex<FReal>& another){
BRAMAS Berenger's avatar
BRAMAS Berenger committed
223 224 225 226
        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]);
    }

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

    /** To cast to FReal */
233
    static const FReal* ToFReal(const FComplex<FReal>*const array){
234 235
        return reinterpret_cast<const FReal*>(array);
    }
236
    /**
237
     * Operator stream FComplex<FReal> to std::ostream
238 239 240 241 242
     * 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
     */
243
    template <class StreamClass>
244
    friend StreamClass& operator<<(StreamClass& output, const FComplex<FReal>& inC){
245
        output << "(" <<  inC.real() << ", " << inC.imag() << ")";
246 247 248
        return output;  // for multiple << operators.
    }

249 250 251
};

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

#endif //FCOMPLEXE_HPP

262