QUDA  0.9.0
complex_quda.h
Go to the documentation of this file.
1 /*
2  * Copyright 2008-2009 NVIDIA Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
21 #pragma once
22 
23 #include <math.h>
24 #include <cmath>
25 #include <complex>
26 #include <sstream>
27 #include <cuComplex.h>
28 
29 // We need this to make sure code inside quda:: that calls sqrt() using real numbers
30 // doesn't try to call the complex sqrt, but the standard sqrt
31 namespace quda
32 {
33  template <typename ValueType>
34  __host__ __device__
35  inline ValueType cos(ValueType x){
36  return std::cos(x);
37  }
38  template <typename ValueType>
39  __host__ __device__
40  inline ValueType sin(ValueType x){
41  return std::sin(x);
42  }
43  template <typename ValueType>
44  __host__ __device__
45  inline ValueType tan(ValueType x){
46  return std::tan(x);
47  }
48  template <typename ValueType>
49  __host__ __device__
50  inline ValueType acos(ValueType x){
51  return std::acos(x);
52  }
53  template <typename ValueType>
54  __host__ __device__
55  inline ValueType asin(ValueType x){
56  return std::asin(x);
57  }
58  template <typename ValueType>
59  __host__ __device__
60  inline ValueType atan(ValueType x){
61  return std::atan(x);
62  }
63  template <typename ValueType>
64  __host__ __device__
65  inline ValueType atan2(ValueType x,ValueType y){
66  return std::atan2(x,y);
67  }
68  template <typename ValueType>
69  __host__ __device__
70  inline ValueType cosh(ValueType x){
71  return std::cosh(x);
72  }
73  template <typename ValueType>
74  __host__ __device__
75  inline ValueType sinh(ValueType x){
76  return std::sinh(x);
77  }
78  template <typename ValueType>
79  __host__ __device__
80  inline ValueType tanh(ValueType x){
81  return std::tanh(x);
82  }
83  template <typename ValueType>
84  __host__ __device__
85  inline ValueType exp(ValueType x){
86  return std::exp(x);
87  }
88  template <typename ValueType>
89  __host__ __device__
90  inline ValueType log(ValueType x){
91  return std::log(x);
92  }
93  template <typename ValueType>
94  __host__ __device__
95  inline ValueType log10(ValueType x){
96  return std::log10(x);
97  }
98  template <typename ValueType, typename ExponentType>
99  __host__ __device__
100  inline ValueType pow(ValueType x, ExponentType e){
101  return std::pow(x,e);
102  }
103  template <typename ValueType>
104  __host__ __device__
105  inline ValueType sqrt(ValueType x){
106  return std::sqrt(x);
107  }
108  template <typename ValueType>
109  __host__ __device__
110  inline ValueType abs(ValueType x){
111  return std::abs(x);
112  }
113  template <typename ValueType>
114  __host__ __device__
115  inline ValueType conj(ValueType x){
116  return x;
117  }
118 
119  template <typename ValueType> struct complex;
120  template <> struct complex<float>;
121  template <> struct complex<double>;
122 
123 
125  template<typename ValueType>
126  __host__ __device__
127  ValueType abs(const complex<ValueType>& z);
129  template<typename ValueType>
130  __host__ __device__
131  ValueType arg(const complex<ValueType>& z);
133  template<typename ValueType>
134  __host__ __device__
135  ValueType norm(const complex<ValueType>& z);
136 
138  template<typename ValueType>
139  __host__ __device__
140  complex<ValueType> conj(const complex<ValueType>& z);
142 
143  template<typename ValueType>
144  __host__ __device__
145  complex<ValueType> polar(const ValueType& m, const ValueType& theta = 0);
146 
147  // Arithmetic operators:
148  // Multiplication
149  template <typename ValueType>
150  __host__ __device__
151  inline complex<ValueType> operator*(const complex<ValueType>& lhs, const complex<ValueType>& rhs);
152  template <typename ValueType>
153  __host__ __device__
154  inline complex<ValueType> operator*(const complex<ValueType>& lhs, const ValueType & rhs);
155  template <typename ValueType>
156  __host__ __device__
157  inline complex<ValueType> operator*(const ValueType& lhs, const complex<ValueType>& rhs);
158  // Division
159  template <typename ValueType>
160  __host__ __device__
161  inline complex<ValueType> operator/(const complex<ValueType>& lhs, const complex<ValueType>& rhs);
162  template <>
163  __host__ __device__
164  inline complex<float> operator/(const complex<float>& lhs, const complex<float>& rhs);
165  template <>
166  __host__ __device__
167  inline complex<double> operator/(const complex<double>& lhs, const complex<double>& rhs);
168 
169  // Addition
170  template <typename ValueType>
171  __host__ __device__
172  inline complex<ValueType> operator+(const complex<ValueType>& lhs, const complex<ValueType>& rhs);
173  template <typename ValueType>
174  __host__ __device__
175  inline complex<ValueType> operator+(const complex<ValueType>& lhs, const ValueType & rhs);
176  template <typename ValueType>
177  __host__ __device__
178  inline complex<ValueType> operator+(const ValueType& lhs, const complex<ValueType>& rhs);
179  // Subtraction
180  template <typename ValueType>
181  __host__ __device__
182  inline complex<ValueType> operator-(const complex<ValueType>& lhs, const complex<ValueType>& rhs);
183  template <typename ValueType>
184  __host__ __device__
185  inline complex<ValueType> operator-(const complex<ValueType>& lhs, const ValueType & rhs);
186  template <typename ValueType>
187  __host__ __device__
188  inline complex<ValueType> operator-(const ValueType& lhs, const complex<ValueType>& rhs);
189 
190  // Unary plus and minus
191  template <typename ValueType>
192  __host__ __device__
193  inline complex<ValueType> operator+(const complex<ValueType>& rhs);
194  template <typename ValueType>
195  __host__ __device__
196  inline complex<ValueType> operator-(const complex<ValueType>& rhs);
197 
198  // Transcendentals:
199  // Returns the complex cosine of z.
200  template <typename ValueType>
201  __host__ __device__
202  complex<ValueType> cos(const complex<ValueType>& z);
203  // Returns the complex hyperbolic cosine of z.
204  template <typename ValueType>
205  __host__ __device__
206  complex<ValueType> cosh(const complex<ValueType>& z);
207  // Returns the complex base e exponential of z.
208  template <typename ValueType>
209  __host__ __device__
210  complex<ValueType> exp(const complex<ValueType>& z);
211  // Returns the complex natural logarithm of z.
212  template <typename ValueType>
213  __host__ __device__
214  complex<ValueType> log(const complex<ValueType>& z);
215  // Returns the complex base 10 logarithm of z.
216  template <typename ValueType>
217  __host__ __device__
218  complex<ValueType> log10(const complex<ValueType>& z);
219  // Returns z to the n'th power.
220  template <typename ValueType>
221  __host__ __device__
222  complex<ValueType> pow(const complex<ValueType>& z, const int& n);
223  // Returns z to the x'th power.
224  template <typename ValueType>
225  __host__ __device__
226  complex<ValueType> pow(const complex<ValueType>&z, const ValueType&x);
227  // Returns z to the z2'th power.
228  template <typename ValueType>
229  __host__ __device__
230  complex<ValueType> pow(const complex<ValueType>&z, const complex<ValueType>&z2);
231  // Returns x to the z'th power.
232  template <typename ValueType>
233  __host__ __device__
234  complex<ValueType> pow(const ValueType& x, const complex<ValueType>& z);
235  // Returns the complex sine of z.
236  template <typename ValueType>
237  __host__ __device__
238  complex<ValueType> sin(const complex<ValueType>&z);
239  // Returns the complex hyperbolic sine of z.
240  template <typename ValueType>
241  __host__ __device__
242  complex<ValueType> sinh(const complex<ValueType>&z);
243  // Returns the complex square root of z.
244  template <typename ValueType>
245  __host__ __device__
246  complex<ValueType> sqrt(const complex<ValueType>&z);
247  // Returns the complex tangent of z.
248  template <typename ValueType>
249  __host__ __device__
250  complex<ValueType> tan(const complex<ValueType>&z);
251  // Returns the complex hyperbolic tangent of z.
252  template <typename ValueType>
253  __host__ __device__
254  complex<ValueType> tanh(const complex<ValueType>&z);
255 
256 
257  // Inverse Trigonometric:
258  // Returns the complex arc cosine of z.
259  template <typename ValueType>
260  __host__ __device__
261  complex<ValueType> acos(const complex<ValueType>& z);
262  // Returns the complex arc sine of z.
263  template <typename ValueType>
264  __host__ __device__
265  complex<ValueType> asin(const complex<ValueType>& z);
266  // Returns the complex arc tangent of z.
267  template <typename ValueType>
268  __host__ __device__
269  complex<ValueType> atan(const complex<ValueType>& z);
270  // Returns the complex hyperbolic arc cosine of z.
271  template <typename ValueType>
272  __host__ __device__
273  complex<ValueType> acosh(const complex<ValueType>& z);
274  // Returns the complex hyperbolic arc sine of z.
275  template <typename ValueType>
276  __host__ __device__
277  complex<ValueType> asinh(const complex<ValueType>& z);
278  // Returns the complex hyperbolic arc tangent of z.
279  template <typename ValueType>
280  __host__ __device__
281  complex<ValueType> atanh(const complex<ValueType>& z);
282 
283 
284 
285  // Stream operators:
286  template<typename ValueType,class charT, class traits>
287  std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const complex<ValueType>& z);
288  template<typename ValueType, typename charT, class traits>
289  std::basic_istream<charT, traits>&
290  operator>>(std::basic_istream<charT, traits>& is, complex<ValueType>& z);
291 
292 
293  // Stream operators
294  template<typename ValueType,class charT, class traits>
295  std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const complex<ValueType>& z)
296  {
297  os << '(' << z.real() << ',' << z.imag() << ')';
298  return os;
299  };
300 
301  template<typename ValueType, typename charT, class traits>
302  std::basic_istream<charT, traits>&
303  operator>>(std::basic_istream<charT, traits>& is, complex<ValueType>& z)
304  {
305  ValueType re, im;
306 
307  charT ch;
308  is >> ch;
309 
310  if(ch == '(')
311  {
312  is >> re >> ch;
313  if (ch == ',')
314  {
315  is >> im >> ch;
316  if (ch == ')')
317  {
318  z = complex<ValueType>(re, im);
319  }
320  else
321  {
322  is.setstate(std::ios_base::failbit);
323  }
324  }
325  else if (ch == ')')
326  {
327  z = re;
328  }
329  else
330  {
331  is.setstate(std::ios_base::failbit);
332  }
333  }
334  else
335  {
336  is.putback(ch);
337  is >> re;
338  z = re;
339  }
340  return is;
341  }
342 
343 template <typename T>
344  struct norm_type {
345  typedef T type;
346  };
347  template <typename T>
348  struct norm_type< complex<T> > {
349  typedef T type;
350  };
351 
352 template <typename ValueType>
353 struct complex
354 {
355 public:
356  typedef ValueType value_type;
357 
358  // Constructors
359  __host__ __device__
360  inline complex<ValueType>(const ValueType & re = ValueType(), const ValueType& im = ValueType())
361  {
362  real(re);
363  imag(im);
364  }
365 
366  template <class X>
367  __host__ __device__
368  inline complex<ValueType>(const complex<X> & z)
369  {
370  real(z.real());
371  imag(z.imag());
372  }
373 
374  template <class X>
375  __host__ __device__
376  inline complex<ValueType>(const std::complex<X> & z)
377  {
378  real(z.real());
379  imag(z.imag());
380  }
381 
382  template <typename T>
383  __host__ __device__
384  inline complex<ValueType>& operator=(const complex<T> z)
385  {
386  real(z.real());
387  imag(z.imag());
388  return *this;
389  }
390 
391  __host__ __device__
392  inline complex<ValueType>& operator+=(const complex<ValueType> z)
393  {
394  real(real()+z.real());
395  imag(imag()+z.imag());
396  return *this;
397  }
398 
399  __host__ __device__
400  inline complex<ValueType>& operator-=(const complex<ValueType> z)
401  {
402  real(real()-z.real());
403  imag(imag()-z.imag());
404  return *this;
405  }
406 
407  __host__ __device__
408  inline complex<ValueType>& operator*=(const complex<ValueType> z)
409  {
410  *this = *this * z;
411  return *this;
412  }
413 
414  __host__ __device__
415  inline complex<ValueType>& operator/=(const complex<ValueType> z)
416  {
417  *this = *this / z;
418  return *this;
419  }
420 
421  __host__ __device__
422  inline complex<ValueType>& operator*=(const ValueType z)
423  {
424  this->x *= z;
425  this->y *= z;
426  return *this;
427  }
428 
429  __host__ __device__ inline ValueType real() const volatile;
430  __host__ __device__ inline ValueType imag() const volatile;
431  __host__ __device__ inline ValueType real() const;
432  __host__ __device__ inline ValueType imag() const;
433  __host__ __device__ inline void real(ValueType) volatile;
434  __host__ __device__ inline void imag(ValueType) volatile;
435  __host__ __device__ inline void real(ValueType);
436  __host__ __device__ inline void imag(ValueType);
437 };
438 
439 // TODO make cuFloatComplex and cuDoubleComplex protected
440 // TODO see if returning references is a perf hazard
441 
442 template<>
443 struct complex <float> : public cuFloatComplex
444 {
445 public:
446  typedef float value_type;
447  __host__ __device__
448  inline complex<float>(){};
449  __host__ __device__
450  inline complex<float>(const float & re, const float& im = float())
451  {
452  real(re);
453  imag(im);
454  }
455 
456  // For some reason having the following constructor
457  // explicitly makes things faster with at least g++
458  __host__ __device__
460  : cuFloatComplex(z){}
461 
462  __host__ __device__
463  complex<float>(cuFloatComplex z)
464  : cuFloatComplex(z){}
465 
466  template <class X>
467  inline complex<float>(const std::complex<X> & z)
468  {
469  real(z.real());
470  imag(z.imag());
471  }
472 
473  // Member operators
474  template <typename T>
475  __host__ __device__
476  inline volatile complex<float>& operator=(const complex<T> z) volatile
477  {
478  real(z.real());
479  imag(z.imag());
480  return *this;
481  }
482 
483  template <typename T>
484  __host__ __device__
485  inline complex<float>& operator=(const complex<T> z)
486  {
487  real(z.real());
488  imag(z.imag());
489  return *this;
490  }
491 
492  __host__ __device__
494  {
495  real(real()+z.real());
496  imag(imag()+z.imag());
497  return *this;
498  }
499 
500  __host__ __device__
502  {
503  real(real()-z.real());
504  imag(imag()-z.imag());
505  return *this;
506  }
507 
508  __host__ __device__
510  {
511  *this = *this * z;
512  return *this;
513  }
514 
515  __host__ __device__
517  {
518  *this = *this / z;
519  return *this;
520  }
521 
522  __host__ __device__
523  inline complex<float>& operator*=(const float z)
524  {
525  this->x *= z;
526  this->y *= z;
527  return *this;
528  }
529 
530  // Let the compiler synthesize the copy and assignment operators.
531  __host__ __device__ inline complex<float>(const volatile complex<float> & z)
532  {
533  real(z.real());
534  imag(z.imag());
535  }
536 
537  __host__ __device__ inline float real() const volatile{ return x; }
538  __host__ __device__ inline float imag() const volatile{ return y; }
539  __host__ __device__ inline float real() const{ return x; }
540  __host__ __device__ inline float imag() const{ return y; }
541  __host__ __device__ inline void real(float re)volatile{ x = re; }
542  __host__ __device__ inline void imag(float im)volatile{ y = im; }
543  __host__ __device__ inline void real(float re){ x = re; }
544  __host__ __device__ inline void imag(float im){ y = im; }
545 
546  // cast operators
547  inline operator std::complex<float>() const { return std::complex<float>(real(),imag()); }
548  template <typename T>
549  inline __host__ __device__ operator complex<T>() const { return complex<T>(static_cast<T>(real()),static_cast<T>(imag())); }
550  // inline operator float() const { return real(); }
551 };
552 
553 template<>
554 struct complex <double> : public cuDoubleComplex
555 {
556 public:
557  typedef double value_type;
558  __host__ __device__
559  inline complex<double>(){};
560  __host__ __device__
561  inline complex<double>(const double & re, const double& im = double())
562  {
563  real(re);
564  imag(im);
565  }
566 
567  // For some reason having the following constructor
568  // explicitly makes things faster with at least g++
569  __host__ __device__
571  : cuDoubleComplex(z) {}
572 
573  __host__ __device__
574  inline complex<double>(cuDoubleComplex z)
575  : cuDoubleComplex(z) {}
576 
577  template <class X>
578  inline complex<double>(const std::complex<X> & z)
579  {
580  real(z.real());
581  imag(z.imag());
582  }
583 
584  // Member operators
585  template <typename T>
586  __host__ __device__
587  inline volatile complex<double>& operator=(const complex<T> z) volatile
588  {
589  real(z.real());
590  imag(z.imag());
591  return *this;
592  }
593 
594  template <typename T>
595  __host__ __device__
596  inline complex<double>& operator=(const complex<T> z)
597  {
598  real(z.real());
599  imag(z.imag());
600  return *this;
601  }
602 
603  __host__ __device__
605  {
606  real(real()+z.real());
607  imag(imag()+z.imag());
608  return *this;
609  }
610 
611  __host__ __device__
613  {
614  real(real()+z.real());
615  imag(imag()+z.imag());
616  return *this;
617  }
618 
619  __host__ __device__
621  {
622  real(real()-z.real());
623  imag(imag()-z.imag());
624  return *this;
625  }
626 
627  __host__ __device__
629  {
630  *this = *this * z;
631  return *this;
632  }
633 
634  __host__ __device__
636  {
637  *this = *this / z;
638  return *this;
639  }
640 
641  __host__ __device__
642  inline complex<double>& operator*=(const double z)
643  {
644  this->x *= z;
645  this->y *= z;
646  return *this;
647  }
648 
649  __host__ __device__ inline complex<double>(const volatile complex<double> & z)
650  {
651  real(z.real());
652  imag(z.imag());
653  }
654 
655  // Let the compiler synthesize the copy and assignment operators.
656  __host__ __device__ inline double real() const volatile { return x; }
657  __host__ __device__ inline double imag() const volatile { return y; }
658  __host__ __device__ inline double real() const { return x; }
659  __host__ __device__ inline double imag() const { return y; }
660  __host__ __device__ inline void real(double re)volatile{ x = re; }
661  __host__ __device__ inline void imag(double im)volatile{ y = im; }
662  __host__ __device__ inline void real(double re){ x = re; }
663  __host__ __device__ inline void imag(double im){ y = im; }
664 
665  // cast operators
666  inline operator std::complex<double>() const { return std::complex<double>(real(),imag()); }
667 
668  template <typename T>
669  inline __host__ __device__ operator complex<T>() const { return complex<T>(static_cast<T>(real()),static_cast<T>(imag())); }
670  // inline operator double() { return real(); }
671 };
672 
673  // Binary arithmetic operations
674  // At the moment I'm implementing the basic functions, and the
675  // corresponding cuComplex calls are commented.
676 
677  template<typename ValueType>
678  __host__ __device__
679  inline complex<ValueType> operator+(const complex<ValueType>& lhs,
680 const complex<ValueType>& rhs){
681  return complex<ValueType>(lhs.real()+rhs.real(),lhs.imag()+rhs.imag());
682  // return cuCaddf(lhs,rhs);
683  }
684 
685  template<typename ValueType>
686  __host__ __device__
687  inline complex<ValueType> operator+(const volatile complex<ValueType>& lhs,
688 const volatile complex<ValueType>& rhs){
689  return complex<ValueType>(lhs.real()+rhs.real(),lhs.imag()+rhs.imag());
690  // return cuCaddf(lhs,rhs);
691  }
692 
693  template <typename ValueType>
694  __host__ __device__
695  inline complex<ValueType> operator+(const complex<ValueType>& lhs, const ValueType & rhs){
696  return complex<ValueType>(lhs.real()+rhs,lhs.imag());
697  // return cuCaddf(lhs,complex<ValueType>(rhs));
698  }
699  template <typename ValueType>
700  __host__ __device__
701  inline complex<ValueType> operator+(const ValueType& lhs, const complex<ValueType>& rhs){
702  return complex<ValueType>(rhs.real()+lhs,rhs.imag());
703  // return cuCaddf(complex<float>(lhs),rhs);
704  }
705 
706  template <typename ValueType>
707  __host__ __device__
708  inline complex<ValueType> operator-(const complex<ValueType>& lhs, const complex<ValueType>& rhs){
709  return complex<ValueType>(lhs.real()-rhs.real(),lhs.imag()-rhs.imag());
710  // return cuCsubf(lhs,rhs);
711  }
712  template <typename ValueType>
713  __host__ __device__
714  inline complex<ValueType> operator-(const complex<ValueType>& lhs, const ValueType & rhs){
715  return complex<ValueType>(lhs.real()-rhs,lhs.imag());
716  // return cuCsubf(lhs,complex<float>(rhs));
717  }
718  template <typename ValueType>
719  __host__ __device__
720  inline complex<ValueType> operator-(const ValueType& lhs, const complex<ValueType>& rhs){
721  return complex<ValueType>(lhs-rhs.real(),-rhs.imag());
722  // return cuCsubf(complex<float>(lhs),rhs);
723  }
724 
725  template <typename ValueType>
726  __host__ __device__
727  inline complex<ValueType> operator*(const complex<ValueType>& lhs,
728 const complex<ValueType>& rhs){
729  return complex<ValueType>(lhs.real()*rhs.real()-lhs.imag()*rhs.imag(),
730 lhs.real()*rhs.imag()+lhs.imag()*rhs.real());
731  // return cuCmulf(lhs,rhs);
732  }
733 
734  template <typename ValueType>
735  __host__ __device__
736  inline complex<ValueType> operator*(const complex<ValueType>& lhs, const ValueType & rhs){
737  return complex<ValueType>(lhs.real()*rhs,lhs.imag()*rhs);
738  // return cuCmulf(lhs,complex<float>(rhs));
739  }
740 
741  template <typename ValueType>
742  __host__ __device__
743  inline complex<ValueType> operator*(const ValueType& lhs, const complex<ValueType>& rhs){
744  return complex<ValueType>(rhs.real()*lhs,rhs.imag()*lhs);
745  // return cuCmulf(complex<float>(lhs),rhs);
746  }
747 
748 
749  template <typename ValueType>
750  __host__ __device__
751  inline complex<ValueType> operator/(const complex<ValueType>& lhs, const complex<ValueType>& rhs){
752  const ValueType cross_norm = lhs.real() * rhs.real() + lhs.imag() * rhs.imag();
753  const ValueType rhs_norm = norm(rhs);
754  return complex<ValueType>(cross_norm/rhs_norm,
755 (lhs.imag() * rhs.real() - lhs.real() * rhs.imag()) / rhs_norm);
756  }
757 
758  template <>
759  __host__ __device__
760  inline complex<float> operator/(const complex<float>& lhs, const complex<float>& rhs){
761  return cuCdivf(lhs,rhs);
762  }
763 
764  template <>
765  __host__ __device__
767  return cuCdiv(lhs,rhs);
768  }
769 
770  template <typename ValueType>
771  __host__ __device__
772  inline complex<ValueType> operator/(const complex<ValueType>& lhs, const ValueType & rhs){
773  return complex<ValueType>(lhs.real()/rhs,lhs.imag()/rhs);
774  // return cuCdivf(lhs,complex<float>(rhs));
775  }
776 
777  template <typename ValueType>
778  __host__ __device__
779  inline complex<ValueType> operator/(const ValueType& lhs, const complex<ValueType>& rhs){
780  const ValueType cross_norm = lhs * rhs.real();
781  const ValueType rhs_norm = norm(rhs);
782  return complex<ValueType>(cross_norm/rhs_norm,(-lhs.real() * rhs.imag()) / rhs_norm);
783  }
784 
785  template <>
786  __host__ __device__
787  inline complex<float> operator/(const float& lhs, const complex<float>& rhs){
788  return cuCdivf(complex<float>(lhs),rhs);
789  }
790  template <>
791  __host__ __device__
792  inline complex<double> operator/(const double& lhs, const complex<double>& rhs){
793  return cuCdiv(complex<double>(lhs),rhs);
794  }
795 
796 
797  // Unary arithmetic operations
798  template <typename ValueType>
799  __host__ __device__
800  inline complex<ValueType> operator+(const complex<ValueType>& rhs){
801  return rhs;
802  }
803  template <typename ValueType>
804  __host__ __device__
805  inline complex<ValueType> operator-(const complex<ValueType>& rhs){
806  return rhs*-ValueType(1);
807  }
808 
809  // Equality operators
810  template <typename ValueType>
811  __host__ __device__
812  inline bool operator==(const complex<ValueType>& lhs, const complex<ValueType>& rhs){
813  if(lhs.real() == rhs.real() && lhs.imag() == rhs.imag()){
814  return true;
815  }
816  return false;
817  }
818 
819  template <typename ValueType>
820  __host__ __device__
821  inline bool operator==(const ValueType & lhs, const complex<ValueType>& rhs){
822  if(lhs == rhs.real() && rhs.imag() == 0){
823  return true;
824  }
825  return false;
826  }
827  template <typename ValueType>
828  __host__ __device__
829  inline bool operator==(const complex<ValueType> & lhs, const ValueType& rhs){
830  if(lhs.real() == rhs && lhs.imag() == 0){
831  return true;
832  }
833  return false;
834  }
835 
836 
837  template <typename ValueType>
838  __host__ __device__
839  inline bool operator!=(const complex<ValueType>& lhs, const complex<ValueType>& rhs){
840  return !(lhs == rhs);
841  }
842 
843  template <typename ValueType>
844  __host__ __device__
845  inline bool operator!=(const ValueType & lhs, const complex<ValueType>& rhs){
846  return !(lhs == rhs);
847  }
848 
849  template <typename ValueType>
850  __host__ __device__
851  inline bool operator!=(const complex<ValueType> & lhs, const ValueType& rhs){
852  return !(lhs == rhs);
853  }
854 
855 
856  template <typename ValueType>
857  __host__ __device__
858  inline complex<ValueType> conj(const complex<ValueType>& z){
859  return complex<ValueType>(z.real(),-z.imag());
860  }
861 
862  template <typename ValueType>
863  __host__ __device__
864  inline ValueType abs(const complex<ValueType>& z){
865  return ::hypot(z.real(),z.imag());
866  }
867  template <>
868  __host__ __device__
869  inline float abs(const complex<float>& z){
870  return ::hypotf(z.real(),z.imag());
871  }
872  template<>
873  __host__ __device__
874  inline double abs(const complex<double>& z){
875  return ::hypot(z.real(),z.imag());
876  }
877 
878  template <typename ValueType>
879  __host__ __device__
880  inline ValueType arg(const complex<ValueType>& z){
881  return atan2(z.imag(),z.real());
882  }
883  template<>
884  __host__ __device__
885  inline float arg(const complex<float>& z){
886  return atan2f(z.imag(),z.real());
887  }
888  template<>
889  __host__ __device__
890  inline double arg(const complex<double>& z){
891  return atan2(z.imag(),z.real());
892  }
893 
894  template <typename ValueType>
895  __host__ __device__
896  inline ValueType norm(const complex<ValueType>& z){
897  return z.real()*z.real() + z.imag()*z.imag();
898  }
899 
900  template <typename ValueType>
901  __host__ __device__
902  inline complex<ValueType> polar(const ValueType & m, const ValueType & theta){
903  return complex<ValueType>(m * ::cos(theta),m * ::sin(theta));
904  }
905 
906  template <>
907  __host__ __device__
908  inline complex<float> polar(const float & magnitude, const float & angle){
909  return complex<float>(magnitude * ::cosf(angle),magnitude * ::sinf(angle));
910  }
911 
912  template <>
913  __host__ __device__
914  inline complex<double> polar(const double & magnitude, const double & angle){
915  return complex<double>(magnitude * ::cos(angle),magnitude * ::sin(angle));
916  }
917 
918  // Transcendental functions implementation
919  template <typename ValueType>
920  __host__ __device__
921  inline complex<ValueType> cos(const complex<ValueType>& z){
922  const ValueType re = z.real();
923  const ValueType im = z.imag();
924  return complex<ValueType>(::cos(re) * ::cosh(im), -::sin(re) * ::sinh(im));
925  }
926 
927  template <>
928  __host__ __device__
930  const float re = z.real();
931  const float im = z.imag();
932  return complex<float>(cosf(re) * coshf(im), -sinf(re) * sinhf(im));
933  }
934 
935  template <typename ValueType>
936  __host__ __device__
937  inline complex<ValueType> cosh(const complex<ValueType>& z){
938  const ValueType re = z.real();
939  const ValueType im = z.imag();
940  return complex<ValueType>(::cosh(re) * ::cos(im), ::sinh(re) * ::sin(im));
941  }
942 
943  template <>
944  __host__ __device__
946  const float re = z.real();
947  const float im = z.imag();
948  return complex<float>(::coshf(re) * ::cosf(im), ::sinhf(re) * ::sinf(im));
949  }
950 
951 
952  template <typename ValueType>
953  __host__ __device__
954  inline complex<ValueType> exp(const complex<ValueType>& z){
955  return polar(::exp(z.real()),z.imag());
956  }
957 
958  template <>
959  __host__ __device__
961  return polar(::expf(z.real()),z.imag());
962  }
963 
964  template <typename ValueType>
965  __host__ __device__
966  inline complex<ValueType> log(const complex<ValueType>& z){
967  return complex<ValueType>(::log(abs(z)),arg(z));
968  }
969 
970  template <>
971  __host__ __device__
973  return complex<float>(::logf(abs(z)),arg(z));
974  }
975 
976 
977  template <typename ValueType>
978  __host__ __device__
979  inline complex<ValueType> log10(const complex<ValueType>& z){
980  // Using the explicit literal prevents compile time warnings in
981  // devices that don't support doubles
982  return log(z)/ValueType(2.30258509299404568402);
983  // return log(z)/ValueType(::log(10.0));
984  }
985 
986  template <typename ValueType>
987  __host__ __device__
988  inline complex<ValueType> pow(const complex<ValueType>& z, const ValueType & exponent){
989  return exp(log(z)*exponent);
990  }
991 
992  template <typename ValueType>
993  __host__ __device__
994  inline complex<ValueType> pow(const complex<ValueType>& z, const complex<ValueType> & exponent){
995  return exp(log(z)*exponent);
996  }
997 
998  template <typename ValueType>
999  __host__ __device__
1000  inline complex<ValueType> pow(const ValueType & x, const complex<ValueType> & exponent){
1001  return exp(::log(x)*exponent);
1002  }
1003 
1004  template <>
1005  __host__ __device__
1006  inline complex<float> pow(const float & x, const complex<float> & exponent){
1007  return exp(::logf(x)*exponent);
1008  }
1009 
1010  template <typename ValueType>
1011  __host__ __device__
1012  inline complex<ValueType> pow(const complex<ValueType>& z,const int & exponent){
1013  return exp(log(z)*ValueType(exponent));
1014  }
1015 
1016  template <typename ValueType>
1017  __host__ __device__
1018  inline complex<ValueType> sin(const complex<ValueType>& z){
1019  const ValueType re = z.real();
1020  const ValueType im = z.imag();
1021  return complex<ValueType>(::sin(re) * ::cosh(im), ::cos(re) * ::sinh(im));
1022  }
1023 
1024  template <>
1025  __host__ __device__
1027  const float re = z.real();
1028  const float im = z.imag();
1029  return complex<float>(::sinf(re) * ::coshf(im), ::cosf(re) * ::sinhf(im));
1030  }
1031 
1032  template <typename ValueType>
1033  __host__ __device__
1034  inline complex<ValueType> sinh(const complex<ValueType>& z){
1035  const ValueType re = z.real();
1036  const ValueType im = z.imag();
1037  return complex<ValueType>(::sinh(re) * ::cos(im), ::cosh(re) * ::sin(im));
1038  }
1039 
1040  template <>
1041  __host__ __device__
1043  const float re = z.real();
1044  const float im = z.imag();
1045  return complex<float>(::sinhf(re) * ::cosf(im), ::coshf(re) * ::sinf(im));
1046  }
1047 
1048  template <typename ValueType>
1049  __host__ __device__
1050  inline complex<ValueType> sqrt(const complex<ValueType>& z){
1051  return polar(::sqrt(abs(z)),arg(z)/ValueType(2));
1052  }
1053 
1054  template <typename ValueType>
1055  __host__ __device__
1057  return polar(::sqrtf(abs(z)),arg(z)/float(2));
1058  }
1059 
1060  template <typename ValueType>
1061  __host__ __device__
1062  inline complex<ValueType> tan(const complex<ValueType>& z){
1063  return sin(z)/cos(z);
1064  }
1065 
1066  template <typename ValueType>
1067  __host__ __device__
1068  inline complex<ValueType> tanh(const complex<ValueType>& z){
1069  // This implementation seems better than the simple sin/cos
1070  return (exp(ValueType(2)*z)-ValueType(1))/(exp(ValueType(2)*z)+ValueType(1));
1071  // return sinh(z)/cosh(z);
1072  }
1073 
1074  // Inverse trigonometric functions implementation
1075 
1076  template <typename ValueType>
1077  __host__ __device__
1078  inline complex<ValueType> acos(const complex<ValueType>& z){
1079  const complex<ValueType> ret = asin(z);
1080  return complex<ValueType>(ValueType(M_PI/2.0) - ret.real(),-ret.imag());
1081  }
1082 
1083  template <typename ValueType>
1084  __host__ __device__
1085  inline complex<ValueType> asin(const complex<ValueType>& z){
1086  const complex<ValueType> i(0,1);
1087  return -i*asinh(i*z);
1088  }
1089 
1090  template <typename ValueType>
1091  __host__ __device__
1092  inline complex<ValueType> atan(const complex<ValueType>& z){
1093  const complex<ValueType> i(0,1);
1094  return -i*atanh(i*z);
1095  }
1096 
1097  template <typename ValueType>
1098  __host__ __device__
1099  inline complex<ValueType> acosh(const complex<ValueType>& z){
1100  quda::complex<ValueType> ret((z.real() - z.imag()) * (z.real() + z.imag()) - ValueType(1.0),
1101  ValueType(2.0) * z.real() * z.imag());
1102  ret = sqrt(ret);
1103  if (z.real() < ValueType(0.0)){
1104  ret = -ret;
1105  }
1106  ret += z;
1107  ret = log(ret);
1108  if (ret.real() < ValueType(0.0)){
1109  ret = -ret;
1110  }
1111  return ret;
1112 
1113  /*
1114  quda::complex<ValueType> ret = log(sqrt(z*z-ValueType(1))+z);
1115  if(ret.real() < 0){
1116  ret.real(-ret.real());
1117  }
1118  return ret;
1119  */
1120  }
1121 
1122  template <typename ValueType>
1123  __host__ __device__
1124  inline complex<ValueType> asinh(const complex<ValueType>& z){
1125  return log(sqrt(z*z+ValueType(1))+z);
1126  }
1127 
1128  template <typename ValueType>
1129  __host__ __device__
1130  inline complex<ValueType> atanh(const complex<ValueType>& z){
1131  ValueType imag2 = z.imag() * z.imag();
1132  ValueType n = ValueType(1.0) + z.real();
1133  n = imag2 + n * n;
1134 
1135  ValueType d = ValueType(1.0) - z.real();
1136  d = imag2 + d * d;
1137  complex<ValueType> ret(ValueType(0.25) * (::log(n) - ::log(d)),0);
1138 
1139  d = ValueType(1.0) - z.real() * z.real() - imag2;
1140 
1141  ret.imag(ValueType(0.5) * ::atan2(ValueType(2.0) * z.imag(), d));
1142  return ret;
1143  //return (log(ValueType(1)+z)-log(ValueType(1)-z))/ValueType(2);
1144  }
1145 
1146  template <typename ValueType>
1147  __host__ __device__
1149  float imag2 = z.imag() * z.imag();
1150  float n = float(1.0) + z.real();
1151  n = imag2 + n * n;
1152 
1153  float d = float(1.0) - z.real();
1154  d = imag2 + d * d;
1155  complex<float> ret(float(0.25) * (::logf(n) - ::logf(d)),0);
1156 
1157  d = float(1.0) - z.real() * z.real() - imag2;
1158 
1159  ret.imag(float(0.5) * ::atan2f(float(2.0) * z.imag(), d));
1160  return ret;
1161  //return (log(ValueType(1)+z)-log(ValueType(1)-z))/ValueType(2);
1162 
1163  }
1164 
1165 } // end namespace quda
__host__ __device__ complex< float > sinh(const complex< float > &z)
__host__ __device__ ValueType tanh(ValueType x)
Definition: complex_quda.h:80
float cosf(float)
__host__ __device__ ValueType sinh(ValueType x)
Definition: complex_quda.h:75
__host__ __device__ complex< float > & operator-=(const complex< float > z)
Definition: complex_quda.h:501
__host__ __device__ complex< double > & operator=(const complex< T > z)
Definition: complex_quda.h:596
ValueType value_type
Definition: complex_quda.h:356
__host__ __device__ ValueType norm(const complex< ValueType > &z)
Returns the magnitude of z squared.
Definition: complex_quda.h:896
__host__ __device__ complex< double > & operator+=(const complex< float > z)
Definition: complex_quda.h:612
__host__ __device__ ValueType atan(ValueType x)
Definition: complex_quda.h:60
__host__ __device__ complex< double > & operator-=(const complex< double > z)
Definition: complex_quda.h:620
__host__ __device__ ValueType exp(ValueType x)
Definition: complex_quda.h:85
__host__ __device__ complex< float > & operator*=(const complex< float > z)
Definition: complex_quda.h:509
__host__ __device__ ValueType cosh(ValueType x)
Definition: complex_quda.h:70
__host__ __device__ void real(double re) volatile
Definition: complex_quda.h:660
__host__ __device__ ValueType sqrt(ValueType x)
Definition: complex_quda.h:105
__host__ __device__ complex< float > cosh(const complex< float > &z)
Definition: complex_quda.h:945
__host__ __device__ void real(float re)
Definition: complex_quda.h:543
float coshf(float)
__host__ __device__ ValueType imag() const volatile
__host__ __device__ complex< ValueType > tanh(const complex< ValueType > &z)
__host__ __device__ void imag(float im)
Definition: complex_quda.h:544
std::basic_istream< charT, traits > & operator>>(std::basic_istream< charT, traits > &is, complex< ValueType > &z)
Definition: complex_quda.h:303
__host__ __device__ double imag() const
Definition: complex_quda.h:659
__host__ __device__ ValueType tan(ValueType x)
Definition: complex_quda.h:45
__host__ __device__ void imag(double im) volatile
Definition: complex_quda.h:661
__host__ __device__ complex< ValueType > & operator+=(const complex< ValueType > z)
Definition: complex_quda.h:392
__host__ __device__ void real(float re) volatile
Definition: complex_quda.h:541
__host__ __device__ complex< float > & operator=(const complex< T > z)
Definition: complex_quda.h:485
__host__ __device__ complex< ValueType > tan(const complex< ValueType > &z)
__host__ __device__ complex< ValueType > & operator-=(const complex< ValueType > z)
Definition: complex_quda.h:400
__host__ __device__ complex< ValueType > & operator*=(const complex< ValueType > z)
Definition: complex_quda.h:408
__host__ __device__ complex< ValueType > asin(const complex< ValueType > &z)
__host__ __device__ void imag(float im) volatile
Definition: complex_quda.h:542
__host__ __device__ ValueType sin(ValueType x)
Definition: complex_quda.h:40
__host__ __device__ complex< ValueType > acos(const complex< ValueType > &z)
float atan2f(float, float)
__host__ __device__ complex< float > sin(const complex< float > &z)
__host__ __device__ void real(double re)
Definition: complex_quda.h:662
__host__ __device__ ValueType atan2(ValueType x, ValueType y)
Definition: complex_quda.h:65
__device__ __host__ ColorSpinor< Float, Nc, Ns > operator-(const ColorSpinor< Float, Nc, Ns > &x, const ColorSpinor< Float, Nc, Ns > &y)
ColorSpinor subtraction operator.
Definition: color_spinor.h:907
__host__ __device__ complex< float > cos(const complex< float > &z)
Definition: complex_quda.h:929
__host__ __device__ ValueType pow(ValueType x, ExponentType e)
Definition: complex_quda.h:100
__host__ __device__ void imag(double im)
Definition: complex_quda.h:663
__host__ __device__ float imag() const volatile
Definition: complex_quda.h:538
__host__ __device__ ValueType real() const volatile
__host__ __device__ complex< float > & operator/=(const complex< float > z)
Definition: complex_quda.h:516
__host__ __device__ float real() const
Definition: complex_quda.h:539
__host__ __device__ complex< float > exp(const complex< float > &z)
Definition: complex_quda.h:960
float sinhf(float)
__host__ __device__ complex< float > log(const complex< float > &z)
Definition: complex_quda.h:972
__host__ __device__ complex< double > & operator/=(const complex< double > z)
Definition: complex_quda.h:635
__host__ __device__ complex< ValueType > log10(const complex< ValueType > &z)
Definition: complex_quda.h:979
__host__ __device__ complex< ValueType > & operator/=(const complex< ValueType > z)
Definition: complex_quda.h:415
__host__ __device__ complex< ValueType > asinh(const complex< ValueType > &z)
__host__ __device__ complex< ValueType > & operator*=(const ValueType z)
Definition: complex_quda.h:422
__host__ __device__ complex< ValueType > & operator=(const complex< T > z)
Definition: complex_quda.h:384
__host__ __device__ ValueType log(ValueType x)
Definition: complex_quda.h:90
__host__ __device__ double imag() const volatile
Definition: complex_quda.h:657
__host__ __device__ complex< float > & operator*=(const float z)
Definition: complex_quda.h:523
__host__ __device__ complex< ValueType > operator/(const complex< ValueType > &lhs, const complex< ValueType > &rhs)
Definition: complex_quda.h:751
__host__ __device__ volatile complex< float > & operator=(const complex< T > z) volatile
Definition: complex_quda.h:476
float logf(float)
__host__ __device__ ValueType log10(ValueType x)
Definition: complex_quda.h:95
double hypot(double, double)
__host__ __device__ double abs(const complex< double > &z)
Definition: complex_quda.h:874
__device__ __host__ ColorSpinor< Float, Nc, Ns > operator+(const ColorSpinor< Float, Nc, Ns > &x, const ColorSpinor< Float, Nc, Ns > &y)
ColorSpinor addition operator.
Definition: color_spinor.h:885
float sinf(float)
__host__ __device__ complex< double > & operator*=(const double z)
Definition: complex_quda.h:642
float expf(float)
__host__ __device__ complex< ValueType > atan(const complex< ValueType > &z)
__host__ __device__ ValueType arg(const complex< ValueType > &z)
Returns the phase angle of z.
Definition: complex_quda.h:880
__host__ __device__ complex< float > sqrt(const complex< float > &z)
__host__ __device__ double real() const
Definition: complex_quda.h:658
__host__ __device__ ValueType cos(ValueType x)
Definition: complex_quda.h:35
__host__ __device__ complex< ValueType > polar(const ValueType &m, const ValueType &theta=0)
Returns the complex with magnitude m and angle theta in radians.
Definition: complex_quda.h:902
__host__ __device__ ValueType abs(ValueType x)
Definition: complex_quda.h:110
__device__ __host__ ColorSpinor< Float, Nc, Ns > operator*(const S &a, const ColorSpinor< Float, Nc, Ns > &x)
Compute the scalar-vector product y = a * x.
Definition: color_spinor.h:929
__host__ __device__ ValueType acos(ValueType x)
Definition: complex_quda.h:50
__host__ __device__ complex< float > pow(const float &x, const complex< float > &exponent)
__host__ __device__ ValueType conj(ValueType x)
Definition: complex_quda.h:115
float sqrtf(float)
__host__ __device__ complex< double > & operator*=(const complex< double > z)
Definition: complex_quda.h:628
static __inline__ size_t size_t d
float hypotf(float, float)
__host__ __device__ bool operator!=(const complex< ValueType > &lhs, const complex< ValueType > &rhs)
Definition: complex_quda.h:839
__host__ __device__ complex< ValueType > atanh(const complex< ValueType > &z)
__host__ __device__ float imag() const
Definition: complex_quda.h:540
__host__ __device__ complex< float > & operator+=(const complex< float > z)
Definition: complex_quda.h:493
__host__ __device__ volatile complex< double > & operator=(const complex< T > z) volatile
Definition: complex_quda.h:587
__host__ __device__ double real() const volatile
Definition: complex_quda.h:656
__host__ __device__ float real() const volatile
Definition: complex_quda.h:537
__host__ __device__ complex< ValueType > acosh(const complex< ValueType > &z)
__host__ __device__ bool operator==(const complex< ValueType > &lhs, const complex< ValueType > &rhs)
Definition: complex_quda.h:812
__host__ __device__ ValueType asin(ValueType x)
Definition: complex_quda.h:55
__host__ __device__ complex< double > & operator+=(const complex< double > z)
Definition: complex_quda.h:604