QUDA  v0.7.0
A library for QCD on GPUs
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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__
142  template<typename ValueType>
143  __host__ __device__
144  complex<ValueType> polar(const ValueType& m, const ValueType& theta = 0);
145 
146  // Arithmetic operators:
147  // Multiplication
148  template <typename ValueType>
149  __host__ __device__
150  inline complex<ValueType> operator*(const complex<ValueType>& lhs, const complex<ValueType>& rhs);
151  template <typename ValueType>
152  __host__ __device__
153  inline complex<ValueType> operator*(const complex<ValueType>& lhs, const ValueType & rhs);
154  template <typename ValueType>
155  __host__ __device__
156  inline complex<ValueType> operator*(const ValueType& lhs, const complex<ValueType>& rhs);
157  // Division
158  template <typename ValueType>
159  __host__ __device__
160  inline complex<ValueType> operator/(const complex<ValueType>& lhs, const complex<ValueType>& rhs);
161  template <>
162  __host__ __device__
163  inline complex<float> operator/(const complex<float>& lhs, const complex<float>& rhs);
164  template <>
165  __host__ __device__
166  inline complex<double> operator/(const complex<double>& lhs, const complex<double>& rhs);
167 
168  // Addition
169  template <typename ValueType>
170  __host__ __device__
171  inline complex<ValueType> operator+(const complex<ValueType>& lhs, const complex<ValueType>& rhs);
172  template <typename ValueType>
173  __host__ __device__
174  inline complex<ValueType> operator+(const complex<ValueType>& lhs, const ValueType & rhs);
175  template <typename ValueType>
176  __host__ __device__
177  inline complex<ValueType> operator+(const ValueType& lhs, const complex<ValueType>& rhs);
178  // Subtraction
179  template <typename ValueType>
180  __host__ __device__
181  inline complex<ValueType> operator-(const complex<ValueType>& lhs, const complex<ValueType>& rhs);
182  template <typename ValueType>
183  __host__ __device__
184  inline complex<ValueType> operator-(const complex<ValueType>& lhs, const ValueType & rhs);
185  template <typename ValueType>
186  __host__ __device__
187  inline complex<ValueType> operator-(const ValueType& lhs, const complex<ValueType>& rhs);
188 
189  // Unary plus and minus
190  template <typename ValueType>
191  __host__ __device__
193  template <typename ValueType>
194  __host__ __device__
196 
197  // Transcendentals:
198  // Returns the complex cosine of z.
199  template <typename ValueType>
200  __host__ __device__
202  // Returns the complex hyperbolic cosine of z.
203  template <typename ValueType>
204  __host__ __device__
206  // Returns the complex base e exponential of z.
207  template <typename ValueType>
208  __host__ __device__
210  // Returns the complex natural logarithm of z.
211  template <typename ValueType>
212  __host__ __device__
214  // Returns the complex base 10 logarithm of z.
215  template <typename ValueType>
216  __host__ __device__
218  // Returns z to the n'th power.
219  template <typename ValueType>
220  __host__ __device__
221  complex<ValueType> pow(const complex<ValueType>& z, const int& n);
222  // Returns z to the x'th power.
223  template <typename ValueType>
224  __host__ __device__
225  complex<ValueType> pow(const complex<ValueType>&z, const ValueType&x);
226  // Returns z to the z2'th power.
227  template <typename ValueType>
228  __host__ __device__
230 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__
239  // Returns the complex hyperbolic sine of z.
240  template <typename ValueType>
241  __host__ __device__
243  // Returns the complex square root of z.
244  template <typename ValueType>
245  __host__ __device__
247  // Returns the complex tangent of z.
248  template <typename ValueType>
249  __host__ __device__
251  // Returns the complex hyperbolic tangent of z.
252  template <typename ValueType>
253  __host__ __device__
255 
256 
257  // Inverse Trigonometric:
258  // Returns the complex arc cosine of z.
259  template <typename ValueType>
260  __host__ __device__
262  // Returns the complex arc sine of z.
263  template <typename ValueType>
264  __host__ __device__
266  // Returns the complex arc tangent of z.
267  template <typename ValueType>
268  __host__ __device__
270  // Returns the complex hyperbolic arc cosine of z.
271  template <typename ValueType>
272  __host__ __device__
274  // Returns the complex hyperbolic arc sine of z.
275  template <typename ValueType>
276  __host__ __device__
278  // Returns the complex hyperbolic arc tangent of z.
279  template <typename ValueType>
280  __host__ __device__
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__
385  {
386  real(z.real());
387  imag(z.imag());
388  return *this;
389  }
390 
391  __host__ __device__
393  {
394  real(real()+z.real());
395  imag(imag()+z.imag());
396  return *this;
397  }
398 
399  __host__ __device__
401  {
402  real(real()-z.real());
403  imag(imag()-z.imag());
404  return *this;
405  }
406 
407  __host__ __device__
409  {
410  *this = *this * z;
411  return *this;
412  }
413 
414  __host__ __device__
416  {
417  *this = *this / z;
418  return *this;
419  }
420 
421  __host__ __device__ inline ValueType real() const volatile;
422  __host__ __device__ inline ValueType imag() const volatile;
423  __host__ __device__ inline ValueType real() const;
424  __host__ __device__ inline ValueType imag() const;
425  __host__ __device__ inline void real(ValueType) volatile;
426  __host__ __device__ inline void imag(ValueType) volatile;
427  __host__ __device__ inline void real(ValueType);
428  __host__ __device__ inline void imag(ValueType);
429 };
430 
431 // TODO make cuFloatComplex and cuDoubleComplex protected
432 // TODO see if returning references is a perf hazard
433 
434 template<>
435 struct complex <float> : public cuFloatComplex
436 {
437 public:
438  typedef float value_type;
439  __host__ __device__
440  inline complex<float>(){};
441  __host__ __device__
442  inline complex<float>(const float & re, const float& im = float())
443  {
444  real(re);
445  imag(im);
446  }
447 
448  // For some reason having the following constructor
449  // explicitly makes things faster with at least g++
450  __host__ __device__
452  : cuFloatComplex(z){}
453 
454  __host__ __device__
455  complex<float>(cuFloatComplex z)
456  : cuFloatComplex(z){}
457 
458  template <class X>
459  inline complex<float>(const std::complex<X> & z)
460  {
461  real(z.real());
462  imag(z.imag());
463  }
464 
465  // Member operators
466  template <typename T>
467  __host__ __device__
468  inline volatile complex<float>& operator=(const complex<T> z) volatile
469  {
470  real(z.real());
471  imag(z.imag());
472  return *this;
473  }
474 
475  template <typename T>
476  __host__ __device__
478  {
479  real(z.real());
480  imag(z.imag());
481  return *this;
482  }
483 
484  __host__ __device__
486  {
487  real(real()+z.real());
488  imag(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  *this = *this * z;
504  return *this;
505  }
506 
507  __host__ __device__
509  {
510  *this = *this / z;
511  return *this;
512  }
513 
514  // Let the compiler synthesize the copy and assignment operators.
515  __host__ __device__ inline complex<float>(const volatile complex<float> & z)
516  {
517  real(z.real());
518  imag(z.imag());
519  }
520 
521  __host__ __device__ inline float real() const volatile{ return x; }
522  __host__ __device__ inline float imag() const volatile{ return y; }
523  __host__ __device__ inline float real() const{ return x; }
524  __host__ __device__ inline float imag() const{ return y; }
525  __host__ __device__ inline void real(float re)volatile{ x = re; }
526  __host__ __device__ inline void imag(float im)volatile{ y = im; }
527  __host__ __device__ inline void real(float re){ x = re; }
528  __host__ __device__ inline void imag(float im){ y = im; }
529 
530  // cast operators
531  inline operator std::complex<float>() const { return std::complex<float>(real(),imag()); }
532  // inline operator float() const { return real(); }
533 };
534 
535 template<>
536 struct complex <double> : public cuDoubleComplex
537 {
538 public:
539  typedef double value_type;
540  __host__ __device__
541  inline complex<double>(){};
542  __host__ __device__
543  inline complex<double>(const double & re, const double& im = double())
544  {
545  real(re);
546  imag(im);
547  }
548 
549  // For some reason having the following constructor
550  // explicitly makes things faster with at least g++
551  __host__ __device__
553  : cuDoubleComplex(z) {}
554 
555  __host__ __device__
556  inline complex<double>(cuDoubleComplex z)
557  : cuDoubleComplex(z) {}
558 
559  template <class X>
560  inline complex<double>(const std::complex<X> & z)
561  {
562  real(z.real());
563  imag(z.imag());
564  }
565 
566  // Member operators
567  template <typename T>
568  __host__ __device__
569  inline volatile complex<double>& operator=(const complex<T> z) volatile
570  {
571  real(z.real());
572  imag(z.imag());
573  return *this;
574  }
575 
576  template <typename T>
577  __host__ __device__
579  {
580  real(z.real());
581  imag(z.imag());
582  return *this;
583  }
584 
585  __host__ __device__
587  {
588  real(real()+z.real());
589  imag(imag()+z.imag());
590  return *this;
591  }
592 
593  __host__ __device__
595  {
596  real(real()-z.real());
597  imag(imag()-z.imag());
598  return *this;
599  }
600 
601  __host__ __device__
603  {
604  *this = *this * z;
605  return *this;
606  }
607 
608  __host__ __device__
610  {
611  *this = *this / z;
612  return *this;
613  }
614 
615  __host__ __device__ inline complex<double>(const volatile complex<double> & z)
616  {
617  real(z.real());
618  imag(z.imag());
619  }
620 
621  // Let the compiler synthesize the copy and assignment operators.
622  __host__ __device__ inline double real() const volatile { return x; }
623  __host__ __device__ inline double imag() const volatile { return y; }
624  __host__ __device__ inline double real() const { return x; }
625  __host__ __device__ inline double imag() const { return y; }
626  __host__ __device__ inline void real(double re)volatile{ x = re; }
627  __host__ __device__ inline void imag(double im)volatile{ y = im; }
628  __host__ __device__ inline void real(double re){ x = re; }
629  __host__ __device__ inline void imag(double im){ y = im; }
630 
631  // cast operators
632  inline operator std::complex<double>() const { return std::complex<double>(real(),imag()); }
633  // inline operator double() { return real(); }
634 };
635 
636 
637 
638  // Binary arithmetic operations
639  // At the moment I'm implementing the basic functions, and the
640  // corresponding cuComplex calls are commented.
641 
642  template<typename ValueType>
643  __host__ __device__
645 const complex<ValueType>& rhs){
646  return complex<ValueType>(lhs.real()+rhs.real(),lhs.imag()+rhs.imag());
647  // return cuCaddf(lhs,rhs);
648  }
649 
650  template<typename ValueType>
651  __host__ __device__
652  inline complex<ValueType> operator+(const volatile complex<ValueType>& lhs,
653 const volatile complex<ValueType>& rhs){
654  return complex<ValueType>(lhs.real()+rhs.real(),lhs.imag()+rhs.imag());
655  // return cuCaddf(lhs,rhs);
656  }
657 
658  template <typename ValueType>
659  __host__ __device__
660  inline complex<ValueType> operator+(const complex<ValueType>& lhs, const ValueType & rhs){
661  return complex<ValueType>(lhs.real()+rhs,lhs.imag());
662  // return cuCaddf(lhs,complex<ValueType>(rhs));
663  }
664  template <typename ValueType>
665  __host__ __device__
666  inline complex<ValueType> operator+(const ValueType& lhs, const complex<ValueType>& rhs){
667  return complex<ValueType>(rhs.real()+lhs,rhs.imag());
668  // return cuCaddf(complex<float>(lhs),rhs);
669  }
670 
671  template <typename ValueType>
672  __host__ __device__
674  return complex<ValueType>(lhs.real()-rhs.real(),lhs.imag()-rhs.imag());
675  // return cuCsubf(lhs,rhs);
676  }
677  template <typename ValueType>
678  __host__ __device__
679  inline complex<ValueType> operator-(const complex<ValueType>& lhs, const ValueType & rhs){
680  return complex<ValueType>(lhs.real()-rhs,lhs.imag());
681  // return cuCsubf(lhs,complex<float>(rhs));
682  }
683  template <typename ValueType>
684  __host__ __device__
685  inline complex<ValueType> operator-(const ValueType& lhs, const complex<ValueType>& rhs){
686  return complex<ValueType>(lhs-rhs.real(),-rhs.imag());
687  // return cuCsubf(complex<float>(lhs),rhs);
688  }
689 
690  template <typename ValueType>
691  __host__ __device__
693 const complex<ValueType>& rhs){
694  return complex<ValueType>(lhs.real()*rhs.real()-lhs.imag()*rhs.imag(),
695 lhs.real()*rhs.imag()+lhs.imag()*rhs.real());
696  // return cuCmulf(lhs,rhs);
697  }
698 
699  template <typename ValueType>
700  __host__ __device__
701  inline complex<ValueType> operator*(const complex<ValueType>& lhs, const ValueType & rhs){
702  return complex<ValueType>(lhs.real()*rhs,lhs.imag()*rhs);
703  // return cuCmulf(lhs,complex<float>(rhs));
704  }
705 
706  template <typename ValueType>
707  __host__ __device__
708  inline complex<ValueType> operator*(const ValueType& lhs, const complex<ValueType>& rhs){
709  return complex<ValueType>(rhs.real()*lhs,rhs.imag()*lhs);
710  // return cuCmulf(complex<float>(lhs),rhs);
711  }
712 
713 
714  template <typename ValueType>
715  __host__ __device__
717  const ValueType cross_norm = lhs.real() * rhs.real() + lhs.imag() * rhs.imag();
718  const ValueType rhs_norm = norm(rhs);
719  return complex<ValueType>(cross_norm/rhs_norm,
720 (lhs.imag() * rhs.real() - lhs.real() * rhs.imag()) / rhs_norm);
721  }
722 
723  template <>
724  __host__ __device__
725  inline complex<float> operator/(const complex<float>& lhs, const complex<float>& rhs){
726  return cuCdivf(lhs,rhs);
727  }
728 
729  template <>
730  __host__ __device__
732  return cuCdiv(lhs,rhs);
733  }
734 
735  template <typename ValueType>
736  __host__ __device__
737  inline complex<ValueType> operator/(const complex<ValueType>& lhs, const ValueType & rhs){
738  return complex<ValueType>(lhs.real()/rhs,lhs.imag()/rhs);
739  // return cuCdivf(lhs,complex<float>(rhs));
740  }
741 
742  template <typename ValueType>
743  __host__ __device__
744  inline complex<ValueType> operator/(const ValueType& lhs, const complex<ValueType>& rhs){
745  const ValueType cross_norm = lhs * rhs.real();
746  const ValueType rhs_norm = norm(rhs);
747  return complex<ValueType>(cross_norm/rhs_norm,(-lhs.real() * rhs.imag()) / rhs_norm);
748  }
749 
750  template <>
751  __host__ __device__
752  inline complex<float> operator/(const float& lhs, const complex<float>& rhs){
753  return cuCdivf(complex<float>(lhs),rhs);
754  }
755  template <>
756  __host__ __device__
757  inline complex<double> operator/(const double& lhs, const complex<double>& rhs){
758  return cuCdiv(complex<double>(lhs),rhs);
759  }
760 
761 
762  // Unary arithmetic operations
763  template <typename ValueType>
764  __host__ __device__
766  return rhs;
767  }
768  template <typename ValueType>
769  __host__ __device__
771  return rhs*-ValueType(1);
772  }
773 
774  // Equality operators
775  template <typename ValueType>
776  __host__ __device__
777  inline bool operator==(const complex<ValueType>& lhs, const complex<ValueType>& rhs){
778  if(lhs.real() == rhs.real() && lhs.imag() == rhs.imag()){
779  return true;
780  }
781  return false;
782  }
783  template <typename ValueType>
784  __host__ __device__
785  inline bool operator==(const ValueType & lhs, const complex<ValueType>& rhs){
786  if(lhs == rhs.real() && rhs.imag() == 0){
787  return true;
788  }
789  return false;
790  }
791  template <typename ValueType>
792  __host__ __device__
793  inline bool operator==(const complex<ValueType> & lhs, const ValueType& rhs){
794  if(lhs.real() == rhs && lhs.imag() == 0){
795  return true;
796  }
797  return false;
798  }
799 
800  template <typename ValueType>
801  __host__ __device__
802  inline bool operator!=(const complex<ValueType>& lhs, const complex<ValueType>& rhs){
803  return !(lhs == rhs);
804  }
805 
806  template <typename ValueType>
807  __host__ __device__
808  inline bool operator!=(const ValueType & lhs, const complex<ValueType>& rhs){
809  return !(lhs == rhs);
810  }
811 
812  template <typename ValueType>
813  __host__ __device__
814  inline bool operator!=(const complex<ValueType> & lhs, const ValueType& rhs){
815  return !(lhs == rhs);
816  }
817 
818 
819  template <typename ValueType>
820  __host__ __device__
822  return complex<ValueType>(z.real(),-z.imag());
823  }
824 
825  template <typename ValueType>
826  __host__ __device__
827  inline ValueType abs(const complex<ValueType>& z){
828  return ::hypot(z.real(),z.imag());
829  }
830  template <>
831  __host__ __device__
832  inline float abs(const complex<float>& z){
833  return ::hypotf(z.real(),z.imag());
834  }
835  template<>
836  __host__ __device__
837  inline double abs(const complex<double>& z){
838  return ::hypot(z.real(),z.imag());
839  }
840 
841  template <typename ValueType>
842  __host__ __device__
843  inline ValueType arg(const complex<ValueType>& z){
844  return atan2(z.imag(),z.real());
845  }
846  template<>
847  __host__ __device__
848  inline float arg(const complex<float>& z){
849  return atan2f(z.imag(),z.real());
850  }
851  template<>
852  __host__ __device__
853  inline double arg(const complex<double>& z){
854  return atan2(z.imag(),z.real());
855  }
856 
857  template <typename ValueType>
858  __host__ __device__
859  inline ValueType norm(const complex<ValueType>& z){
860  return z.real()*z.real() + z.imag()*z.imag();
861  }
862 
863  template <typename ValueType>
864  __host__ __device__
865  inline complex<ValueType> polar(const ValueType & m, const ValueType & theta){
866  return complex<ValueType>(m * ::cos(theta),m * ::sin(theta));
867  }
868 
869  template <>
870  __host__ __device__
871  inline complex<float> polar(const float & magnitude, const float & angle){
872  return complex<float>(magnitude * ::cosf(angle),magnitude * ::sinf(angle));
873  }
874 
875  template <>
876  __host__ __device__
877  inline complex<double> polar(const double & magnitude, const double & angle){
878  return complex<double>(magnitude * ::cos(angle),magnitude * ::sin(angle));
879  }
880 
881  // Transcendental functions implementation
882  template <typename ValueType>
883  __host__ __device__
885  const ValueType re = z.real();
886  const ValueType im = z.imag();
887  return complex<ValueType>(::cos(re) * ::cosh(im), -::sin(re) * ::sinh(im));
888  }
889 
890  template <>
891  __host__ __device__
893  const float re = z.real();
894  const float im = z.imag();
895  return complex<float>(cosf(re) * coshf(im), -sinf(re) * sinhf(im));
896  }
897 
898  template <typename ValueType>
899  __host__ __device__
901  const ValueType re = z.real();
902  const ValueType im = z.imag();
903  return complex<ValueType>(::cosh(re) * ::cos(im), ::sinh(re) * ::sin(im));
904  }
905 
906  template <>
907  __host__ __device__
909  const float re = z.real();
910  const float im = z.imag();
911  return complex<float>(::coshf(re) * ::cosf(im), ::sinhf(re) * ::sinf(im));
912  }
913 
914 
915  template <typename ValueType>
916  __host__ __device__
918  return polar(::exp(z.real()),z.imag());
919  }
920 
921  template <>
922  __host__ __device__
924  return polar(::expf(z.real()),z.imag());
925  }
926 
927  template <typename ValueType>
928  __host__ __device__
930  return complex<ValueType>(::log(abs(z)),arg(z));
931  }
932 
933  template <>
934  __host__ __device__
936  return complex<float>(::logf(abs(z)),arg(z));
937  }
938 
939 
940  template <typename ValueType>
941  __host__ __device__
943  // Using the explicit literal prevents compile time warnings in
944  // devices that don't support doubles
945  return log(z)/ValueType(2.30258509299404568402);
946  // return log(z)/ValueType(::log(10.0));
947  }
948 
949  template <typename ValueType>
950  __host__ __device__
951  inline complex<ValueType> pow(const complex<ValueType>& z, const ValueType & exponent){
952  return exp(log(z)*exponent);
953  }
954 
955  template <typename ValueType>
956  __host__ __device__
957  inline complex<ValueType> pow(const complex<ValueType>& z, const complex<ValueType> & exponent){
958  return exp(log(z)*exponent);
959  }
960 
961  template <typename ValueType>
962  __host__ __device__
963  inline complex<ValueType> pow(const ValueType & x, const complex<ValueType> & exponent){
964  return exp(::log(x)*exponent);
965  }
966 
967  template <>
968  __host__ __device__
969  inline complex<float> pow(const float & x, const complex<float> & exponent){
970  return exp(::logf(x)*exponent);
971  }
972 
973  template <typename ValueType>
974  __host__ __device__
975  inline complex<ValueType> pow(const complex<ValueType>& z,const int & exponent){
976  return exp(log(z)*ValueType(exponent));
977  }
978 
979  template <typename ValueType>
980  __host__ __device__
982  const ValueType re = z.real();
983  const ValueType im = z.imag();
984  return complex<ValueType>(::sin(re) * ::cosh(im), ::cos(re) * ::sinh(im));
985  }
986 
987  template <>
988  __host__ __device__
990  const float re = z.real();
991  const float im = z.imag();
992  return complex<float>(::sinf(re) * ::coshf(im), ::cosf(re) * ::sinhf(im));
993  }
994 
995  template <typename ValueType>
996  __host__ __device__
998  const ValueType re = z.real();
999  const ValueType im = z.imag();
1000  return complex<ValueType>(::sinh(re) * ::cos(im), ::cosh(re) * ::sin(im));
1001  }
1002 
1003  template <>
1004  __host__ __device__
1006  const float re = z.real();
1007  const float im = z.imag();
1008  return complex<float>(::sinhf(re) * ::cosf(im), ::coshf(re) * ::sinf(im));
1009  }
1010 
1011  template <typename ValueType>
1012  __host__ __device__
1014  return polar(::sqrt(abs(z)),arg(z)/ValueType(2));
1015  }
1016 
1017  template <typename ValueType>
1018  __host__ __device__
1020  return polar(::sqrtf(abs(z)),arg(z)/float(2));
1021  }
1022 
1023  template <typename ValueType>
1024  __host__ __device__
1026  return sin(z)/cos(z);
1027  }
1028 
1029  template <typename ValueType>
1030  __host__ __device__
1032  // This implementation seems better than the simple sin/cos
1033  return (exp(ValueType(2)*z)-ValueType(1))/(exp(ValueType(2)*z)+ValueType(1));
1034  // return sinh(z)/cosh(z);
1035  }
1036 
1037  // Inverse trigonometric functions implementation
1038 
1039  template <typename ValueType>
1040  __host__ __device__
1042  const complex<ValueType> ret = asin(z);
1043  return complex<ValueType>(ValueType(M_PI/2.0) - ret.real(),-ret.imag());
1044  }
1045 
1046  template <typename ValueType>
1047  __host__ __device__
1049  const complex<ValueType> i(0,1);
1050  return -i*asinh(i*z);
1051  }
1052 
1053  template <typename ValueType>
1054  __host__ __device__
1056  const complex<ValueType> i(0,1);
1057  return -i*atanh(i*z);
1058  }
1059 
1060  template <typename ValueType>
1061  __host__ __device__
1063  quda::complex<ValueType> ret((z.real() - z.imag()) * (z.real() + z.imag()) - ValueType(1.0),
1064 ValueType(2.0) * z.real() * z.imag());
1065  ret = sqrt(ret);
1066  if (z.real() < ValueType(0.0)){
1067  ret = -ret;
1068  }
1069  ret += z;
1070  ret = log(ret);
1071  if (ret.real() < ValueType(0.0)){
1072  ret = -ret;
1073  }
1074  return ret;
1075 
1076  /*
1077 quda::complex<ValueType> ret = log(sqrt(z*z-ValueType(1))+z);
1078 if(ret.real() < 0){
1079 ret.real(-ret.real());
1080 }
1081 return ret;
1082 */
1083  }
1084 
1085  template <typename ValueType>
1086  __host__ __device__
1088  return log(sqrt(z*z+ValueType(1))+z);
1089  }
1090 
1091  template <typename ValueType>
1092  __host__ __device__
1094  ValueType imag2 = z.imag() * z.imag();
1095  ValueType n = ValueType(1.0) + z.real();
1096  n = imag2 + n * n;
1097 
1098  ValueType d = ValueType(1.0) - z.real();
1099  d = imag2 + d * d;
1100  complex<ValueType> ret(ValueType(0.25) * (::log(n) - ::log(d)),0);
1101 
1102  d = ValueType(1.0) - z.real() * z.real() - imag2;
1103 
1104  ret.imag(ValueType(0.5) * ::atan2(ValueType(2.0) * z.imag(), d));
1105  return ret;
1106  //return (log(ValueType(1)+z)-log(ValueType(1)-z))/ValueType(2);
1107  }
1108 
1109  template <typename ValueType>
1110  __host__ __device__
1112  float imag2 = z.imag() * z.imag();
1113  float n = float(1.0) + z.real();
1114  n = imag2 + n * n;
1115 
1116  float d = float(1.0) - z.real();
1117  d = imag2 + d * d;
1118  complex<float> ret(float(0.25) * (::logf(n) - ::logf(d)),0);
1119 
1120  d = float(1.0) - z.real() * z.real() - imag2;
1121 
1122  ret.imag(float(0.5) * ::atan2f(float(2.0) * z.imag(), d));
1123  return ret;
1124  //return (log(ValueType(1)+z)-log(ValueType(1)-z))/ValueType(2);
1125 
1126  }
1127 
1128 } // end namespace quda
__host__ __device__ complex< float > sinh(const complex< float > &z)
__host__ __device__ ValueType tanh(ValueType x)
Definition: complex_quda.h:80
__host__ __device__ ValueType sinh(ValueType x)
Definition: complex_quda.h:75
__host__ __device__ complex< float > & operator-=(const complex< float > z)
Definition: complex_quda.h:493
__host__ __device__ complex< double > & operator=(const complex< T > z)
Definition: complex_quda.h:578
int y[4]
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:859
__host__ __device__ ValueType atan(ValueType x)
Definition: complex_quda.h:60
__host__ __device__ complex< double > & operator-=(const complex< double > z)
Definition: complex_quda.h:594
__host__ __device__ ValueType exp(ValueType x)
Definition: complex_quda.h:85
__host__ __device__ complex< float > & operator*=(const complex< float > z)
Definition: complex_quda.h:501
__host__ __device__ ValueType cosh(ValueType x)
Definition: complex_quda.h:70
__host__ __device__ void real(double re) volatile
Definition: complex_quda.h:626
__host__ __device__ ValueType sqrt(ValueType x)
Definition: complex_quda.h:105
__host__ __device__ complex< float > cosh(const complex< float > &z)
Definition: complex_quda.h:908
__host__ __device__ void real(float re)
Definition: complex_quda.h:527
__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:528
__host__ __device__ float real() const
Definition: complex_quda.h:523
std::basic_istream< charT, traits > & operator>>(std::basic_istream< charT, traits > &is, complex< ValueType > &z)
Definition: complex_quda.h:303
__host__ __device__ ValueType tan(ValueType x)
Definition: complex_quda.h:45
__host__ __device__ double imag() const
Definition: complex_quda.h:625
__host__ __device__ void imag(double im) volatile
Definition: complex_quda.h:627
__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:525
__host__ __device__ complex< float > & operator=(const complex< T > z)
Definition: complex_quda.h:477
__host__ __device__ complex< ValueType > tan(const complex< ValueType > &z)
__host__ __device__ float imag() const
Definition: complex_quda.h:524
__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:526
__host__ __device__ ValueType sin(ValueType x)
Definition: complex_quda.h:40
__host__ __device__ complex< ValueType > acos(const complex< ValueType > &z)
__host__ __device__ complex< float > sin(const complex< float > &z)
Definition: complex_quda.h:989
__host__ __device__ complex< ValueType > operator-(const complex< ValueType > &lhs, const complex< ValueType > &rhs)
Definition: complex_quda.h:673
__host__ __device__ void real(double re)
Definition: complex_quda.h:628
__host__ __device__ ValueType atan2(ValueType x, ValueType y)
Definition: complex_quda.h:65
__host__ __device__ complex< float > cos(const complex< float > &z)
Definition: complex_quda.h:892
__host__ __device__ ValueType pow(ValueType x, ExponentType e)
Definition: complex_quda.h:100
__host__ __device__ void imag(double im)
Definition: complex_quda.h:629
__host__ __device__ float imag() const volatile
Definition: complex_quda.h:522
__host__ __device__ ValueType real() const volatile
__host__ __device__ complex< float > & operator/=(const complex< float > z)
Definition: complex_quda.h:508
__host__ __device__ complex< float > exp(const complex< float > &z)
Definition: complex_quda.h:923
__host__ __device__ complex< float > log(const complex< float > &z)
Definition: complex_quda.h:935
__host__ __device__ complex< double > & operator/=(const complex< double > z)
Definition: complex_quda.h:609
int x[4]
__host__ __device__ complex< ValueType > log10(const complex< ValueType > &z)
Definition: complex_quda.h:942
__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 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:623
__host__ __device__ complex< ValueType > operator/(const complex< ValueType > &lhs, const complex< ValueType > &rhs)
Definition: complex_quda.h:716
__host__ __device__ volatile complex< float > & operator=(const complex< T > z) volatile
Definition: complex_quda.h:468
__host__ __device__ ValueType log10(ValueType x)
Definition: complex_quda.h:95
__host__ __device__ complex< ValueType > operator*(const complex< ValueType > &lhs, const complex< ValueType > &rhs)
Definition: complex_quda.h:692
__host__ __device__ double abs(const complex< double > &z)
Definition: complex_quda.h:837
int z2
Definition: llfat_core.h:816
float im
Definition: qio_util.h:19
__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:843
__host__ __device__ complex< float > sqrt(const complex< float > &z)
__host__ __device__ double real() const
Definition: complex_quda.h:624
__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:865
__host__ __device__ ValueType abs(ValueType x)
Definition: complex_quda.h:110
__host__ __device__ ValueType acos(ValueType x)
Definition: complex_quda.h:50
__host__ __device__ complex< float > pow(const float &x, const complex< float > &exponent)
Definition: complex_quda.h:969
__host__ __device__ ValueType conj(ValueType x)
Definition: complex_quda.h:115
__host__ __device__ complex< ValueType > operator+(const complex< ValueType > &lhs, const complex< ValueType > &rhs)
Definition: complex_quda.h:644
__host__ __device__ complex< double > & operator*=(const complex< double > z)
Definition: complex_quda.h:602
__host__ __device__ bool operator!=(const complex< ValueType > &lhs, const complex< ValueType > &rhs)
Definition: complex_quda.h:802
__host__ __device__ complex< ValueType > atanh(const complex< ValueType > &z)
__host__ __device__ complex< float > & operator+=(const complex< float > z)
Definition: complex_quda.h:485
__host__ __device__ volatile complex< double > & operator=(const complex< T > z) volatile
Definition: complex_quda.h:569
__host__ __device__ double real() const volatile
Definition: complex_quda.h:622
__host__ __device__ float real() const volatile
Definition: complex_quda.h:521
__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:777
float re
Definition: qio_util.h:18
__host__ __device__ ValueType asin(ValueType x)
Definition: complex_quda.h:55
__host__ __device__ complex< double > & operator+=(const complex< double > z)
Definition: complex_quda.h:586