Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_complex.hpp
1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Kokkos: Manycore Performance-Portable Multidimensional Arrays
6 // Copyright (2012) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact H. Carter Edwards (hcedwar@sandia.gov)
39 //
40 // ************************************************************************
41 //@HEADER
42 */
43 #ifndef KOKKOS_COMPLEX_HPP
44 #define KOKKOS_COMPLEX_HPP
45 
46 #include <Kokkos_Atomic.hpp>
47 #include <complex>
48 #include <iostream>
49 
50 namespace Kokkos {
51 
59 template<class RealType>
60 class complex {
61 private:
62  RealType re_, im_;
63 
64 public:
66  typedef RealType value_type;
67 
69  KOKKOS_INLINE_FUNCTION complex () :
70  re_ (0.0), im_ (0.0)
71  {}
72 
74  KOKKOS_INLINE_FUNCTION complex (const complex<RealType>& src) :
75  re_ (src.re_), im_ (src.im_)
76  {}
77 
83  template<class InputRealType>
84  complex (const std::complex<InputRealType>& src) :
85  re_ (std::real (src)), im_ (std::imag (src))
86  {}
87 
93  operator std::complex<RealType> () const {
94  return std::complex<RealType> (re_, im_);
95  }
96 
99  template<class InputRealType>
100  KOKKOS_INLINE_FUNCTION complex (const InputRealType& val) :
101  re_ (val), im_ (0.0)
102  {}
103 
105  template<class RealType1, class RealType2>
106  KOKKOS_INLINE_FUNCTION complex (const RealType1& re, const RealType2& im) :
107  re_ (re), im_ (im)
108  {}
109 
111  template<class InputRealType>
112  KOKKOS_INLINE_FUNCTION
114  re_ = src.re_;
115  im_ = src.im_;
116  return *this;
117  }
118 
120  template<class InputRealType>
121  KOKKOS_INLINE_FUNCTION
123  re_ = src.re_;
124  im_ = src.im_;
125  return *this;
126  }
127 
129  template<class InputRealType>
130  KOKKOS_INLINE_FUNCTION
131  complex<RealType>& operator= (const InputRealType& val) {
132  re_ = val;
133  im_ = static_cast<RealType> (0.0);
134  return *this;
135  }
136 
142  template<class InputRealType>
143  complex<RealType>& operator= (const std::complex<InputRealType>& src) {
144  re_ = std::real (src);
145  im_ = std::imag (src);
146  return *this;
147  }
148 
150  KOKKOS_INLINE_FUNCTION RealType imag () const {
151  return im_;
152  }
153 
155  KOKKOS_INLINE_FUNCTION RealType real () const {
156  return re_;
157  }
158 
160  KOKKOS_INLINE_FUNCTION RealType imag () const volatile {
161  return im_;
162  }
163 
165  KOKKOS_INLINE_FUNCTION RealType real () const volatile {
166  return re_;
167  }
168 
169  KOKKOS_INLINE_FUNCTION
170  complex<RealType>& operator += (const complex<RealType>& src) {
171  re_ += src.re_;
172  im_ += src.im_;
173  return *this;
174  }
175 
176  KOKKOS_INLINE_FUNCTION
177  void operator += (const volatile complex<RealType>& src) volatile {
178  re_ += src.re_;
179  im_ += src.im_;
180  }
181 
182  KOKKOS_INLINE_FUNCTION
183  complex<RealType>& operator += (const RealType& src) {
184  re_ += src;
185  return *this;
186  }
187 
188  KOKKOS_INLINE_FUNCTION
189  void operator += (const volatile RealType& src) volatile {
190  re_ += src;
191  }
192 
193  KOKKOS_INLINE_FUNCTION void atomic_add (const complex<RealType>& x) volatile {
194  // We can do the atomic update of a complex number componentwise,
195  // since the components don't interact in an add operation. This
196  // does NOT work for dd_real!
197  ::Kokkos::atomic_add (&re_, x.real ());
198  ::Kokkos::atomic_add (&im_, x.imag ());
199  }
200 
201  KOKKOS_INLINE_FUNCTION
202  complex<RealType>& operator -= (const complex<RealType>& src) {
203  re_ -= src.re_;
204  im_ -= src.im_;
205  return *this;
206  }
207 
208  KOKKOS_INLINE_FUNCTION
209  complex<RealType>& operator -= (const RealType& src) {
210  re_ -= src;
211  return *this;
212  }
213 
214  KOKKOS_INLINE_FUNCTION
215  complex<RealType>& operator *= (const complex<RealType>& src) {
216  const RealType realPart = re_ * src.re_ - im_ * src.im_;
217  const RealType imagPart = re_ * src.im_ + im_ * src.re_;
218  re_ = realPart;
219  im_ = imagPart;
220  return *this;
221  }
222 
223  KOKKOS_INLINE_FUNCTION
224  void operator *= (const volatile complex<RealType>& src) volatile {
225  const RealType realPart = re_ * src.re_ - im_ * src.im_;
226  const RealType imagPart = re_ * src.im_ + im_ * src.re_;
227  re_ = realPart;
228  im_ = imagPart;
229  }
230 
231  KOKKOS_INLINE_FUNCTION
232  complex<RealType>& operator *= (const RealType& src) {
233  re_ *= src;
234  im_ *= src;
235  return *this;
236  }
237 
238  KOKKOS_INLINE_FUNCTION
239  void operator *= (const volatile RealType& src) volatile {
240  re_ *= src;
241  im_ *= src;
242  }
243 
244  KOKKOS_INLINE_FUNCTION
245  complex<RealType>& operator /= (const complex<RealType>& y) {
246  // Scale (by the "1-norm" of y) to avoid unwarranted overflow.
247  // If the real part is +/-Inf and the imaginary part is -/+Inf,
248  // this won't change the result.
249  const RealType s = ::fabs (real (y)) + ::fabs (imag (y));
250 
251  // If s is 0, then y is zero, so x/y == real(x)/0 + i*imag(x)/0.
252  // In that case, the relation x/y == (x/s) / (y/s) doesn't hold,
253  // because y/s is NaN.
254  if (s == 0.0) {
255  this->re_ /= s;
256  this->im_ /= s;
257  }
258  else {
259  const complex<RealType> x_scaled (this->re_ / s, this->im_ / s);
260  const complex<RealType> y_conj_scaled (y.re_ / s, -(y.im_) / s);
261  const RealType y_scaled_abs = y_conj_scaled.re_ * y_conj_scaled.re_ +
262  y_conj_scaled.im_ * y_conj_scaled.im_; // abs(y) == abs(conj(y))
263  *this = x_scaled * y_conj_scaled;
264  *this /= y_scaled_abs;
265  }
266  return *this;
267  }
268 
269  KOKKOS_INLINE_FUNCTION
270  complex<RealType>& operator /= (const RealType& src) {
271  re_ /= src;
272  im_ /= src;
273  return *this;
274  }
275 };
276 
278 template<class RealType>
279 KOKKOS_INLINE_FUNCTION
280 complex<RealType>
282  return complex<RealType> (x.real () + y.real (), x.imag () + y.imag ());
283 }
284 
286 template<class RealType>
287 KOKKOS_INLINE_FUNCTION
288 complex<RealType>
290  return x;
291 }
292 
294 template<class RealType>
295 KOKKOS_INLINE_FUNCTION
296 complex<RealType>
298  return complex<RealType> (x.real () - y.real (), x.imag () - y.imag ());
299 }
300 
302 template<class RealType>
303 KOKKOS_INLINE_FUNCTION
304 complex<RealType>
306  return complex<RealType> (-x.real (), -x.imag ());
307 }
308 
310 template<class RealType>
311 KOKKOS_INLINE_FUNCTION
312 complex<RealType>
314  return complex<RealType> (x.real () * y.real () - x.imag () * y.imag (),
315  x.real () * y.imag () + x.imag () * y.real ());
316 }
317 
319 template<class RealType>
320 KOKKOS_INLINE_FUNCTION
321 RealType imag (const complex<RealType>& x) {
322  return x.imag ();
323 }
324 
326 template<class RealType>
327 KOKKOS_INLINE_FUNCTION
328 RealType real (const complex<RealType>& x) {
329  return x.real ();
330 }
331 
333 template<class RealType>
334 KOKKOS_INLINE_FUNCTION
335 RealType abs (const complex<RealType>& x) {
336  // FIXME (mfh 31 Oct 2014) Scale to avoid unwarranted overflow.
337  return ::sqrt (real (x) * real (x) + imag (x) * imag (x));
338 }
339 
341 template<class RealType>
342 KOKKOS_INLINE_FUNCTION
344  return complex<RealType> (real (x), -imag (x));
345 }
346 
347 
349 template<class RealType1, class RealType2>
350 KOKKOS_INLINE_FUNCTION
351 complex<RealType1>
352 operator / (const complex<RealType1>& x, const RealType2& y) {
353  return complex<RealType1> (real (x) / y, imag (x) / y);
354 }
355 
357 template<class RealType>
358 KOKKOS_INLINE_FUNCTION
359 complex<RealType>
361  // Scale (by the "1-norm" of y) to avoid unwarranted overflow.
362  // If the real part is +/-Inf and the imaginary part is -/+Inf,
363  // this won't change the result.
364  const RealType s = ::fabs (real (y)) + ::fabs (imag (y));
365 
366  // If s is 0, then y is zero, so x/y == real(x)/0 + i*imag(x)/0.
367  // In that case, the relation x/y == (x/s) / (y/s) doesn't hold,
368  // because y/s is NaN.
369  if (s == 0.0) {
370  return complex<RealType> (real (x) / s, imag (x) / s);
371  }
372  else {
373  const complex<RealType> x_scaled (real (x) / s, imag (x) / s);
374  const complex<RealType> y_conj_scaled (real (y) / s, -imag (y) / s);
375  const RealType y_scaled_abs = real (y_conj_scaled) * real (y_conj_scaled) +
376  imag (y_conj_scaled) * imag (y_conj_scaled); // abs(y) == abs(conj(y))
377  complex<RealType> result = x_scaled * y_conj_scaled;
378  result /= y_scaled_abs;
379  return result;
380  }
381 }
382 
384 template<class RealType>
385 KOKKOS_INLINE_FUNCTION
387  return real (x) == real (y) && imag (x) == imag (y);
388 }
389 
391 template<class RealType1, class RealType2>
392 KOKKOS_INLINE_FUNCTION
393 bool operator == (const complex<RealType1>& x, const RealType2& y) {
394  return real (x) == y && imag (x) == static_cast<RealType1> (0.0);
395 }
396 
398 template<class RealType>
399 KOKKOS_INLINE_FUNCTION
400 bool operator == (const RealType& x, const complex<RealType>& y) {
401  return y == x;
402 }
403 
405 template<class RealType>
406 KOKKOS_INLINE_FUNCTION
408  return real (x) != real (y) || imag (x) != imag (y);
409 }
410 
412 template<class RealType1, class RealType2>
413 KOKKOS_INLINE_FUNCTION
414 bool operator != (const complex<RealType1>& x, const RealType2& y) {
415  return real (x) != y || imag (x) != static_cast<RealType1> (0.0);
416 }
417 
419 template<class RealType>
420 KOKKOS_INLINE_FUNCTION
421 bool operator != (const RealType& x, const complex<RealType>& y) {
422  return y != x;
423 }
424 
425 template<class RealType>
426 std::ostream& operator << (std::ostream& os, const complex<RealType>& x) {
427  const std::complex<RealType> x_std (Kokkos::real (x), Kokkos::imag (x));
428  os << x_std;
429  return os;
430 }
431 
432 template<class RealType>
433 std::ostream& operator >> (std::ostream& os, complex<RealType>& x) {
434  std::complex<RealType> x_std;
435  os >> x_std;
436  x = x_std; // only assigns on success of above
437  return os;
438 }
439 
440 KOKKOS_INLINE_FUNCTION void
441 atomic_add (volatile ::Kokkos::complex<double>* const dest,
442  const ::Kokkos::complex<double> src)
443 {
444  dest->atomic_add (src);
445 }
446 
447 } // namespace Kokkos
448 
449 #endif // KOKKOS_COMPLEX_HPP
KOKKOS_INLINE_FUNCTION RealType real() const
The real part of this complex number.
KOKKOS_INLINE_FUNCTION complex(const RealType1 &re, const RealType2 &im)
Constructor that takes the real and imaginary parts.
KOKKOS_INLINE_FUNCTION complex< RealType > operator*(const complex< RealType > &x, const complex< RealType > &y)
Binary * operator for complex.
Partial reimplementation of std::complex that works as the result of a Kokkos::parallel_reduce.
KOKKOS_INLINE_FUNCTION complex(const InputRealType &val)
Constructor that takes just the real part, and sets the imaginary part to zero.
KOKKOS_INLINE_FUNCTION complex(const complex< RealType > &src)
Copy constructor.
KOKKOS_INLINE_FUNCTION complex()
Default constructor (initializes both real and imaginary parts to zero).
KOKKOS_INLINE_FUNCTION RealType abs(const complex< RealType > &x)
Absolute value (magnitude) of a complex number.
complex(const std::complex< InputRealType > &src)
Conversion constructor from std::complex.
KOKKOS_INLINE_FUNCTION complex< RealType > & operator=(const complex< InputRealType > &src)
Assignment operator.
KOKKOS_FORCEINLINE_FUNCTION bool operator==(const pair< T1, T2 > &lhs, const pair< T1, T2 > &rhs)
Equality operator for Kokkos::pair.
KOKKOS_INLINE_FUNCTION complex< RealType > operator+(const complex< RealType > &x, const complex< RealType > &y)
Binary + operator for complex.
KOKKOS_FORCEINLINE_FUNCTION bool operator!=(const pair< T1, T2 > &lhs, const pair< T1, T2 > &rhs)
Inequality operator for Kokkos::pair.
KOKKOS_INLINE_FUNCTION complex< RealType > operator-(const complex< RealType > &x, const complex< RealType > &y)
Binary - operator for complex.
RealType value_type
The type of the real or imaginary parts of this complex number.
KOKKOS_INLINE_FUNCTION RealType real(const complex< RealType > &x)
Real part of a complex number.
KOKKOS_INLINE_FUNCTION complex< RealType > conj(const complex< RealType > &x)
Conjugate of a complex number.
KOKKOS_INLINE_FUNCTION RealType real() const volatile
The real part of this complex number (volatile overload).
Atomic functions.
KOKKOS_INLINE_FUNCTION RealType imag() const
The imaginary part of this complex number.
KOKKOS_INLINE_FUNCTION RealType imag() const volatile
The imaginary part of this complex number (volatile overload).
KOKKOS_INLINE_FUNCTION complex< RealType1 > operator/(const complex< RealType1 > &x, const RealType2 &y)
Binary operator / for complex and real numbers.
KOKKOS_INLINE_FUNCTION RealType imag(const complex< RealType > &x)
Imaginary part of a complex number.