Kokkos Core Kernels Package  Version of the Day
Kokkos_Complex.hpp
1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Kokkos v. 2.0
6 // Copyright (2014) 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 <Kokkos_NumericTraits.hpp>
48 #include <complex>
49 #include <iostream>
50 
51 namespace Kokkos {
52 
60 template<class RealType>
61 class complex {
62 private:
63  RealType re_, im_;
64 
65 public:
67  typedef RealType value_type;
68 
70  KOKKOS_INLINE_FUNCTION complex () :
71  re_ (0.0), im_ (0.0)
72  {}
73 
75  KOKKOS_INLINE_FUNCTION complex (const complex<RealType>& src) :
76  re_ (src.re_), im_ (src.im_)
77  {}
78 
80  KOKKOS_INLINE_FUNCTION complex (const volatile complex<RealType>& src) :
81  re_ (src.re_), im_ (src.im_)
82  {}
83 
89  template<class InputRealType>
90  complex (const std::complex<InputRealType>& src) :
91  re_ (std::real (src)), im_ (std::imag (src))
92  {}
93 
99  operator std::complex<RealType> () const {
100  return std::complex<RealType> (re_, im_);
101  }
102 
105  template<class InputRealType>
106  KOKKOS_INLINE_FUNCTION complex (const InputRealType& val) :
107  re_ (val), im_ (0.0)
108  {}
109 
111  template<class RealType1, class RealType2>
112  KOKKOS_INLINE_FUNCTION complex (const RealType1& re, const RealType2& im) :
113  re_ (re), im_ (im)
114  {}
115 
117  template<class InputRealType>
118  KOKKOS_INLINE_FUNCTION
120  re_ = src.re_;
121  im_ = src.im_;
122  return *this;
123  }
124 
134  template<class InputRealType>
135  KOKKOS_INLINE_FUNCTION
136  void operator= (const complex<InputRealType>& src) volatile {
137  re_ = src.re_;
138  im_ = src.im_;
139  // We deliberately do not return anything here. See explanation
140  // in public documentation above.
141  }
142 
144  template<class InputRealType>
145  KOKKOS_INLINE_FUNCTION
146  volatile complex<RealType>& operator= (const volatile complex<InputRealType>& src) volatile {
147  re_ = src.re_;
148  im_ = src.im_;
149  return *this;
150  }
151 
153  template<class InputRealType>
154  KOKKOS_INLINE_FUNCTION
156  re_ = src.re_;
157  im_ = src.im_;
158  return *this;
159  }
160 
162  template<class InputRealType>
163  KOKKOS_INLINE_FUNCTION
164  complex<RealType>& operator= (const InputRealType& val) {
165  re_ = val;
166  im_ = static_cast<RealType> (0.0);
167  return *this;
168  }
169 
171  template<class InputRealType>
172  KOKKOS_INLINE_FUNCTION
173  void operator= (const InputRealType& val) volatile {
174  re_ = val;
175  im_ = static_cast<RealType> (0.0);
176  }
177 
183  template<class InputRealType>
184  complex<RealType>& operator= (const std::complex<InputRealType>& src) {
185  re_ = std::real (src);
186  im_ = std::imag (src);
187  return *this;
188  }
189 
191  KOKKOS_INLINE_FUNCTION RealType& imag () {
192  return im_;
193  }
194 
196  KOKKOS_INLINE_FUNCTION RealType& real () {
197  return re_;
198  }
199 
201  KOKKOS_INLINE_FUNCTION const RealType imag () const {
202  return im_;
203  }
204 
206  KOKKOS_INLINE_FUNCTION const RealType real () const {
207  return re_;
208  }
209 
211  KOKKOS_INLINE_FUNCTION volatile RealType& imag () volatile {
212  return im_;
213  }
214 
216  KOKKOS_INLINE_FUNCTION volatile RealType& real () volatile {
217  return re_;
218  }
219 
221  KOKKOS_INLINE_FUNCTION const RealType imag () const volatile {
222  return im_;
223  }
224 
226  KOKKOS_INLINE_FUNCTION const RealType real () const volatile {
227  return re_;
228  }
229 
230  KOKKOS_INLINE_FUNCTION
231  complex<RealType>& operator += (const complex<RealType>& src) {
232  re_ += src.re_;
233  im_ += src.im_;
234  return *this;
235  }
236 
237  KOKKOS_INLINE_FUNCTION
238  void operator += (const volatile complex<RealType>& src) volatile {
239  re_ += src.re_;
240  im_ += src.im_;
241  }
242 
243  KOKKOS_INLINE_FUNCTION
244  complex<RealType>& operator += (const RealType& src) {
245  re_ += src;
246  return *this;
247  }
248 
249  KOKKOS_INLINE_FUNCTION
250  void operator += (const volatile RealType& src) volatile {
251  re_ += src;
252  }
253 
254  KOKKOS_INLINE_FUNCTION
255  complex<RealType>& operator -= (const complex<RealType>& src) {
256  re_ -= src.re_;
257  im_ -= src.im_;
258  return *this;
259  }
260 
261  KOKKOS_INLINE_FUNCTION
262  complex<RealType>& operator -= (const RealType& src) {
263  re_ -= src;
264  return *this;
265  }
266 
267  KOKKOS_INLINE_FUNCTION
268  complex<RealType>& operator *= (const complex<RealType>& src) {
269  const RealType realPart = re_ * src.re_ - im_ * src.im_;
270  const RealType imagPart = re_ * src.im_ + im_ * src.re_;
271  re_ = realPart;
272  im_ = imagPart;
273  return *this;
274  }
275 
276  KOKKOS_INLINE_FUNCTION
277  void operator *= (const volatile complex<RealType>& src) volatile {
278  const RealType realPart = re_ * src.re_ - im_ * src.im_;
279  const RealType imagPart = re_ * src.im_ + im_ * src.re_;
280  re_ = realPart;
281  im_ = imagPart;
282  }
283 
284  KOKKOS_INLINE_FUNCTION
285  complex<RealType>& operator *= (const RealType& src) {
286  re_ *= src;
287  im_ *= src;
288  return *this;
289  }
290 
291  KOKKOS_INLINE_FUNCTION
292  void operator *= (const volatile RealType& src) volatile {
293  re_ *= src;
294  im_ *= src;
295  }
296 
297  KOKKOS_INLINE_FUNCTION
298  complex<RealType>& operator /= (const complex<RealType>& y) {
299  // Scale (by the "1-norm" of y) to avoid unwarranted overflow.
300  // If the real part is +/-Inf and the imaginary part is -/+Inf,
301  // this won't change the result.
302  const RealType s = ::fabs (y.real ()) + ::fabs (y.imag ());
303 
304  // If s is 0, then y is zero, so x/y == real(x)/0 + i*imag(x)/0.
305  // In that case, the relation x/y == (x/s) / (y/s) doesn't hold,
306  // because y/s is NaN.
307  if (s == 0.0) {
308  this->re_ /= s;
309  this->im_ /= s;
310  }
311  else {
312  const complex<RealType> x_scaled (this->re_ / s, this->im_ / s);
313  const complex<RealType> y_conj_scaled (y.re_ / s, -(y.im_) / s);
314  const RealType y_scaled_abs = y_conj_scaled.re_ * y_conj_scaled.re_ +
315  y_conj_scaled.im_ * y_conj_scaled.im_; // abs(y) == abs(conj(y))
316  *this = x_scaled * y_conj_scaled;
317  *this /= y_scaled_abs;
318  }
319  return *this;
320  }
321 
322  KOKKOS_INLINE_FUNCTION
323  complex<RealType>& operator /= (const RealType& src) {
324  re_ /= src;
325  im_ /= src;
326  return *this;
327  }
328 
329  KOKKOS_INLINE_FUNCTION
330  bool operator == (const complex<RealType>& src) {
331  return (re_ == src.re_) && (im_ == src.im_);
332  }
333 
334  KOKKOS_INLINE_FUNCTION
335  bool operator == (const RealType src) {
336  return (re_ == src) && (im_ == RealType(0));
337  }
338 
339  KOKKOS_INLINE_FUNCTION
340  bool operator != (const complex<RealType>& src) {
341  return (re_ != src.re_) || (im_ != src.im_);
342  }
343 
344  KOKKOS_INLINE_FUNCTION
345  bool operator != (const RealType src) {
346  return (re_ != src) || (im_ != RealType(0));
347  }
348 
349 };
350 
352 template<class RealType>
353 KOKKOS_INLINE_FUNCTION
356  return complex<RealType> (x.real () + y.real (), x.imag () + y.imag ());
357 }
358 
360 template<class RealType>
361 KOKKOS_INLINE_FUNCTION
363 operator + (const complex<RealType>& x, const RealType& y) {
364  return complex<RealType> (x.real () + y , x.imag ());
365 }
366 
368 template<class RealType>
369 KOKKOS_INLINE_FUNCTION
371 operator + (const RealType& x, const complex<RealType>& y) {
372  return complex<RealType> (x + y.real (), y.imag ());
373 }
374 
376 template<class RealType>
377 KOKKOS_INLINE_FUNCTION
380  return x;
381 }
382 
384 template<class RealType>
385 KOKKOS_INLINE_FUNCTION
388  return complex<RealType> (x.real () - y.real (), x.imag () - y.imag ());
389 }
390 
392 template<class RealType>
393 KOKKOS_INLINE_FUNCTION
395 operator - (const complex<RealType>& x, const RealType& y) {
396  return complex<RealType> (x.real () - y , x.imag ());
397 }
398 
400 template<class RealType>
401 KOKKOS_INLINE_FUNCTION
403 operator - (const RealType& x, const complex<RealType>& y) {
404  return complex<RealType> (x - y.real (), - y.imag ());
405 }
406 
408 template<class RealType>
409 KOKKOS_INLINE_FUNCTION
412  return complex<RealType> (-x.real (), -x.imag ());
413 }
414 
416 template<class RealType>
417 KOKKOS_INLINE_FUNCTION
420  return complex<RealType> (x.real () * y.real () - x.imag () * y.imag (),
421  x.real () * y.imag () + x.imag () * y.real ());
422 }
423 
434 template<class RealType>
436 operator * (const std::complex<RealType>& x, const complex<RealType>& y) {
437  return complex<RealType> (x.real () * y.real () - x.imag () * y.imag (),
438  x.real () * y.imag () + x.imag () * y.real ());
439 }
440 
445 template<class RealType>
446 KOKKOS_INLINE_FUNCTION
448 operator * (const RealType& x, const complex<RealType>& y) {
449  return complex<RealType> (x * y.real (), x * y.imag ());
450 }
451 
456 template<class RealType>
457 KOKKOS_INLINE_FUNCTION
459 operator * (const complex<RealType>& y, const RealType& x) {
460  return complex<RealType> (x * y.real (), x * y.imag ());
461 }
462 
464 template<class RealType>
465 KOKKOS_INLINE_FUNCTION
466 RealType imag (const complex<RealType>& x) {
467  return x.imag ();
468 }
469 
471 template<class RealType>
472 KOKKOS_INLINE_FUNCTION
473 RealType real (const complex<RealType>& x) {
474  return x.real ();
475 }
476 
478 template<class RealType>
479 KOKKOS_INLINE_FUNCTION
480 RealType abs (const complex<RealType>& x) {
481  // FIXME (mfh 31 Oct 2014) Scale to avoid unwarranted overflow.
482  return std::sqrt (real (x) * real (x) + imag (x) * imag (x));
483 }
484 
486 template<class RealType>
487 KOKKOS_INLINE_FUNCTION
488 Kokkos::complex<RealType> pow (const complex<RealType>& x, const RealType& e) {
489  RealType r = abs(x);
490  RealType phi = std::atan(x.imag()/x.real());
491  return std::pow(r,e) * Kokkos::complex<RealType>(std::cos(phi*e),std::sin(phi*e));
492 }
493 
495 template<class RealType>
496 KOKKOS_INLINE_FUNCTION
498  RealType r = abs(x);
499  RealType phi = std::atan(x.imag()/x.real());
500  return std::sqrt(r) * Kokkos::complex<RealType>(std::cos(phi*0.5),std::sin(phi*0.5));
501 }
502 
504 template<class RealType>
505 KOKKOS_INLINE_FUNCTION
507  return complex<RealType> (real (x), -imag (x));
508 }
509 
511 template<class RealType>
512 KOKKOS_INLINE_FUNCTION
514  return std::exp(x.real()) * complex<RealType> (std::cos (x.imag()), std::sin(x.imag()));
515 }
516 
518 template<class RealType>
519 KOKKOS_INLINE_FUNCTION
521  return std::exp(x.real()) * complex<RealType> (std::cos (x.imag()), std::sin(x.imag()));
522 }
523 
525 template<class RealType1, class RealType2>
526 KOKKOS_INLINE_FUNCTION
528 operator / (const complex<RealType1>& x, const RealType2& y) {
529  return complex<RealType1> (real (x) / y, imag (x) / y);
530 }
531 
533 template<class RealType>
534 KOKKOS_INLINE_FUNCTION
537  // Scale (by the "1-norm" of y) to avoid unwarranted overflow.
538  // If the real part is +/-Inf and the imaginary part is -/+Inf,
539  // this won't change the result.
540  const RealType s = ::fabs (real (y)) + ::fabs (imag (y));
541 
542  // If s is 0, then y is zero, so x/y == real(x)/0 + i*imag(x)/0.
543  // In that case, the relation x/y == (x/s) / (y/s) doesn't hold,
544  // because y/s is NaN.
545  if (s == 0.0) {
546  return complex<RealType> (real (x) / s, imag (x) / s);
547  }
548  else {
549  const complex<RealType> x_scaled (real (x) / s, imag (x) / s);
550  const complex<RealType> y_conj_scaled (real (y) / s, -imag (y) / s);
551  const RealType y_scaled_abs = real (y_conj_scaled) * real (y_conj_scaled) +
552  imag (y_conj_scaled) * imag (y_conj_scaled); // abs(y) == abs(conj(y))
553  complex<RealType> result = x_scaled * y_conj_scaled;
554  result /= y_scaled_abs;
555  return result;
556  }
557 }
558 
560 template<class RealType1, class RealType2>
561 KOKKOS_INLINE_FUNCTION
563 operator / (const RealType1& x, const complex<RealType2>& y) {
564  return complex<RealType1> (x)/y;
565 }
566 
568 template<class RealType>
569 KOKKOS_INLINE_FUNCTION
570 bool operator == (const complex<RealType>& x, const complex<RealType>& y) {
571  return real (x) == real (y) && imag (x) == imag (y);
572 }
573 
580 template<class RealType>
581 bool operator == (const std::complex<RealType>& x, const complex<RealType>& y) {
582  return std::real (x) == real (y) && std::imag (x) == imag (y);
583 }
584 
586 template<class RealType1, class RealType2>
587 KOKKOS_INLINE_FUNCTION
588 bool operator == (const complex<RealType1>& x, const RealType2& y) {
589  return real (x) == y && imag (x) == static_cast<RealType1> (0.0);
590 }
591 
593 template<class RealType>
594 KOKKOS_INLINE_FUNCTION
595 bool operator == (const RealType& x, const complex<RealType>& y) {
596  return y == x;
597 }
598 
600 template<class RealType>
601 KOKKOS_INLINE_FUNCTION
602 bool operator != (const complex<RealType>& x, const complex<RealType>& y) {
603  return real (x) != real (y) || imag (x) != imag (y);
604 }
605 
607 template<class RealType>
608 KOKKOS_INLINE_FUNCTION
609 bool operator != (const std::complex<RealType>& x, const complex<RealType>& y) {
610  return std::real (x) != real (y) || std::imag (x) != imag (y);
611 }
612 
614 template<class RealType1, class RealType2>
615 KOKKOS_INLINE_FUNCTION
616 bool operator != (const complex<RealType1>& x, const RealType2& y) {
617  return real (x) != y || imag (x) != static_cast<RealType1> (0.0);
618 }
619 
621 template<class RealType>
622 KOKKOS_INLINE_FUNCTION
623 bool operator != (const RealType& x, const complex<RealType>& y) {
624  return y != x;
625 }
626 
627 template<class RealType>
628 std::ostream& operator << (std::ostream& os, const complex<RealType>& x) {
629  const std::complex<RealType> x_std (Kokkos::real (x), Kokkos::imag (x));
630  os << x_std;
631  return os;
632 }
633 
634 template<class RealType>
635 std::ostream& operator >> (std::ostream& os, complex<RealType>& x) {
636  std::complex<RealType> x_std;
637  os >> x_std;
638  x = x_std; // only assigns on success of above
639  return os;
640 }
641 
642 
643 template<class T>
644 struct reduction_identity<Kokkos::complex<T> > {
645  typedef reduction_identity<T> t_red_ident;
646  KOKKOS_FORCEINLINE_FUNCTION constexpr static Kokkos::complex<T> sum()
647  {return Kokkos::complex<T>(t_red_ident::sum(),t_red_ident::sum());}
648  KOKKOS_FORCEINLINE_FUNCTION constexpr static Kokkos::complex<T> prod()
649  {return Kokkos::complex<T>(t_red_ident::prod(),t_red_ident::sum());}
650 };
651 
652 } // namespace Kokkos
653 
654 #endif // KOKKOS_COMPLEX_HPP
KOKKOS_INLINE_FUNCTION const RealType imag() const
The imaginary part of this complex number.
KOKKOS_INLINE_FUNCTION const RealType real() const
The real part of this complex number.
KOKKOS_INLINE_FUNCTION RealType & imag()
The imaginary 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 Kokkos::complex< RealType > pow(const complex< RealType > &x, const RealType &e)
Power of a complex number.
KOKKOS_INLINE_FUNCTION complex(const volatile complex< RealType > &src)
Copy constructor from volatile.
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.
KOKKOS_INLINE_FUNCTION RealType & real()
The real part of this complex number.
complex(const std::complex< InputRealType > &src)
Conversion constructor from std::complex.
KOKKOS_INLINE_FUNCTION volatile RealType & imag() volatile
The imaginary part of this complex number (volatile overload).
KOKKOS_INLINE_FUNCTION complex< RealType > & operator=(const complex< InputRealType > &src)
Assignment operator.
KOKKOS_INLINE_FUNCTION complex< RealType > operator+(const complex< RealType > &x, const complex< RealType > &y)
Binary + operator for complex complex.
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 volatile RealType & real() volatile
The real part of this complex number (volatile overload).
KOKKOS_INLINE_FUNCTION const RealType imag() const volatile
The imaginary part of this complex number (volatile overload).
KOKKOS_INLINE_FUNCTION Kokkos::complex< RealType > sqrt(const complex< RealType > &x)
Square root of a complex number.
KOKKOS_INLINE_FUNCTION const RealType real() const volatile
The real part of this complex number (volatile overload).
KOKKOS_INLINE_FUNCTION complex< RealType > conj(const complex< RealType > &x)
Conjugate of a complex number.
Atomic functions.
KOKKOS_INLINE_FUNCTION complex< RealType > exp(const complex< RealType > &x)
Exponential of a complex number.
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.