Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_ArithTraits.hpp
Go to the documentation of this file.
1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Kokkos: Manycore Performance-Portable Multidimensional Arrays
6 // Copyright (2012) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact H. Carter Edwards (hcedwar@sandia.gov)
39 //
40 // ************************************************************************
41 //@HEADER
42 */
43 
44 #ifndef KOKKOS_ARITHTRAITS_HPP
45 #define KOKKOS_ARITHTRAITS_HPP
46 
52 
53 #include <Kokkos_complex.hpp>
54 
55 #include <cfloat>
56 #include <climits>
57 #include <cmath>
58 #include <cstdlib> // strtof, strtod, strtold
59 #include <complex> // std::complex
60 #include <limits> // std::numeric_limits
61 #ifdef __CUDACC__
62 #include <math_constants.h>
63 #endif
64 //
65 // mfh 24 Dec 2013: Temporary measure for testing; will go away.
66 //
67 #ifndef KOKKOS_FORCEINLINE_FUNCTION
68 # ifdef __CUDA_ARCH__
69 # define KOKKOS_FORCEINLINE_FUNCTION inline __host__ __device__
70 # else
71 # define KOKKOS_FORCEINLINE_FUNCTION
72 # endif // __CUDA_ARCH__
73 #endif // KOKKOS_FORCEINLINE_FUNCTION
74 
75 namespace { // anonymous
76 
85 template<class IntType>
86 KOKKOS_FORCEINLINE_FUNCTION IntType
87 intPowImpl (const IntType x, const IntType y)
88 {
89  // Recursion (unrolled into while loop): pow(x, 2y) = (x^y)^2
90  IntType prod = x;
91  IntType y_cur = 1;
92  // If y == 1, then prod stays x.
93  while (y_cur < y) {
94  prod = prod * prod;
95  y_cur = y_cur << 1;
96  }
97  // abs(y - y_cur) < floor(log2(y)), so it won't hurt asymptotic run
98  // time to finish the remainder in a linear iteration.
99  if (y > y_cur) {
100  const IntType left = y - y_cur;
101  for (IntType k = 0; k < left; ++k) {
102  prod = prod * x;
103  }
104  }
105  else if (y < y_cur) {
106  // There's probably a better way to do this in order to avoid the
107  // (expensive) integer division, but I'm not motivated to think of
108  // it at the moment.
109  const IntType left = y_cur - y;
110  for (IntType k = 0; k < left; ++k) {
111  prod = prod / x;
112  }
113  }
114  return prod;
115 
116  // y = 8:
117  //
118  // x,1 -> x^2,2
119  // x^2,2 -> x^4,4
120  // x^4,4 -> x^8,8
121  //
122  // y = 9:
123  //
124  // x,1 -> x^2,2
125  // x^2,2 -> x^4,4
126  // x^4,4 -> x^8,8
127  //
128  // y - y_cur is what's left over. Just do it one at a time.
129  //
130  // y = 3:
131  // x,1 -> x^2,2
132  // x^2,2 -> x^4,4
133 }
134 
135 
136 
144 template<class IntType>
145 KOKKOS_FORCEINLINE_FUNCTION IntType
146 intPowSigned (const IntType x, const IntType y)
147 {
148  // It's not entirely clear what to return if x and y are both zero.
149  // In the case of floating-point numbers, 0^0 is NaN. Here, though,
150  // I think it's safe to return 0.
151  if (x == 0) {
152  return 0;
153  } else if (y == 0) {
154  return 1;
155  } else if (y < 0) {
156  if (x == 1) {
157  return 1;
158  }
159  else if (x == -1) {
160  return (y % 2 == 0) ? 1 : -1;
161  }
162  else {
163  return 0; // round the fraction to zero
164  }
165  } else {
166  return intPowImpl<IntType> (x, y);
167  }
168 }
169 
177 template<class IntType>
178 KOKKOS_FORCEINLINE_FUNCTION IntType
179 intPowUnsigned (const IntType x, const IntType y)
180 {
181  // It's not entirely clear what to return if x and y are both zero.
182  // In the case of floating-point numbers, 0^0 is NaN. Here, though,
183  // I think it's safe to return 0.
184  if (x == 0) {
185  return 0;
186  } else if (y == 0) {
187  return 1;
188  } else {
189  return intPowImpl<IntType> (x, y);
190  }
191 }
192 
193 // It might make sense to use special sqrt() approximations for
194 // integer arguments, like those presented on the following web site:
195 //
196 // http://www.azillionmonkeys.com/qed/sqroot.html#implementations
197 //
198 // Note that some of the implementations on the above page break ANSI
199 // C(++) aliasing rules (by assigning to the results of
200 // reinterpret_cast-ing between int and float). It's also just a
201 // performance optimization and not required for a reasonable
202 // implementation.
203 
204 } // namespace (anonymous)
205 
206 namespace Kokkos {
207 namespace Details {
208 
327 template<class T>
328 class ArithTraits {
329 public:
336  typedef T val_type;
343  typedef T mag_type;
344 
346  static const bool is_specialized = false;
348  static const bool is_signed = false;
350  static const bool is_integer = false;
355  static const bool is_exact = false;
357  static const bool is_complex = false;
358 
368  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const T& x);
369 
379  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const T& x);
380 
382  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const T& x);
383 
385  static KOKKOS_FORCEINLINE_FUNCTION T zero ();
386 
388  static KOKKOS_FORCEINLINE_FUNCTION T one ();
389 
394  static KOKKOS_FORCEINLINE_FUNCTION T min ();
395 
397  static KOKKOS_FORCEINLINE_FUNCTION T max ();
398 
402  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const T& x);
403 
407  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const T&);
408 
412  static KOKKOS_FORCEINLINE_FUNCTION T conj (const T&);
413 
415  static KOKKOS_FORCEINLINE_FUNCTION T pow (const T& x, const T& y);
416 
428  static KOKKOS_FORCEINLINE_FUNCTION T sqrt (const T& x);
429 
441  static KOKKOS_FORCEINLINE_FUNCTION T log (const T& x);
442 
454  static KOKKOS_FORCEINLINE_FUNCTION T log10 (const T& x);
455 
460  static KOKKOS_FORCEINLINE_FUNCTION T nan ();
461 
467  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon ();
468 
470 
481  typedef T magnitudeType;
482 
486  typedef T halfPrecision;
487 
491  typedef T doublePrecision;
492 
493  static const bool isComplex = false;
494  static const bool isOrdinal = false;
495  static const bool isComparable = false;
496 
503  static const bool hasMachineParameters = false;
504 
506  static KOKKOS_FORCEINLINE_FUNCTION mag_type eps ();
507 
509  static KOKKOS_FORCEINLINE_FUNCTION mag_type sfmin ();
510 
512  static KOKKOS_FORCEINLINE_FUNCTION int base ();
513 
515  static KOKKOS_FORCEINLINE_FUNCTION mag_type prec ();
516 
518  static KOKKOS_FORCEINLINE_FUNCTION int t ();
519 
521  static KOKKOS_FORCEINLINE_FUNCTION mag_type rnd ();
522 
524  static KOKKOS_FORCEINLINE_FUNCTION int emin ();
525 
527  static KOKKOS_FORCEINLINE_FUNCTION mag_type rmin ();
528 
530  static KOKKOS_FORCEINLINE_FUNCTION int emax ();
531 
533  static KOKKOS_FORCEINLINE_FUNCTION mag_type rmax ();
534 
536  static KOKKOS_FORCEINLINE_FUNCTION magnitudeType magnitude (const T& x);
537 
539  static KOKKOS_FORCEINLINE_FUNCTION T conjugate (const T& x);
540 
544  static KOKKOS_FORCEINLINE_FUNCTION bool isnaninf (const T& x);
545 
549  static std::string name ();
550 
552  static KOKKOS_FORCEINLINE_FUNCTION T squareroot (const T& x);
554 };
555 
556 
557 template<>
558 class ArithTraits<float> {
559 public:
560  typedef float val_type;
561  typedef val_type mag_type;
562 
563  static const bool is_specialized = true;
564  static const bool is_signed = true;
565  static const bool is_integer = false;
566  static const bool is_exact = false;
567  static const bool is_complex = false;
568 
569  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const float x) {
570 #ifdef __APPLE__
571  return std::isinf (x);
572 #else
573  return isinf (x);
574 #endif // __APPLE__
575  }
576  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const float x) {
577 #ifdef __APPLE__
578  return std::isnan (x);
579 #else
580  return isnan (x);
581 #endif // __APPLE__
582  }
583  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const float x) {
584  return ::fabs (x);
585  }
586  static KOKKOS_FORCEINLINE_FUNCTION float zero () {
587  return 0.0;
588  }
589  static KOKKOS_FORCEINLINE_FUNCTION float one () {
590  return 1.0;
591  }
592  static KOKKOS_FORCEINLINE_FUNCTION float min () {
593  return FLT_MIN;
594  }
595  static KOKKOS_FORCEINLINE_FUNCTION float max () {
596  return FLT_MAX;
597  }
598  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const float x) {
599  return x;
600  }
601  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const float) {
602  return 0.0;
603  }
604  static KOKKOS_FORCEINLINE_FUNCTION float conj (const float x) {
605  return x;
606  }
607  static KOKKOS_FORCEINLINE_FUNCTION float pow (const float x, const float y) {
608  return ::pow (x, y);
609  }
610  static KOKKOS_FORCEINLINE_FUNCTION float sqrt (const float x) {
611  return ::sqrt (x);
612  }
613  static KOKKOS_FORCEINLINE_FUNCTION float log (const float x) {
614  return ::log (x);
615  }
616  static KOKKOS_FORCEINLINE_FUNCTION float log10 (const float x) {
617  return ::log10 (x);
618  }
619  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon () {
620  return FLT_EPSILON;
621  }
622 
623  // Backwards compatibility with Teuchos::ScalarTraits.
624  typedef mag_type magnitudeType;
625  // C++ doesn't have a standard "half-float" type.
626  typedef float halfPrecision;
627  typedef double doublePrecision;
628 
629  static const bool isComplex = false;
630  static const bool isOrdinal = false;
631  static const bool isComparable = true;
632  static const bool hasMachineParameters = true;
633  static KOKKOS_FORCEINLINE_FUNCTION bool isnaninf (const float x) {
634  return isNan (x) || isInf (x);
635  }
636  static KOKKOS_FORCEINLINE_FUNCTION magnitudeType magnitude (const float x) {
637  return abs (x);
638  }
639  static KOKKOS_FORCEINLINE_FUNCTION float conjugate (const float x) {
640  return conj (x);
641  }
642  static std::string name () {
643  return "float";
644  }
645  static KOKKOS_FORCEINLINE_FUNCTION float squareroot (const float x) {
646  return sqrt (x);
647  }
648  static KOKKOS_FORCEINLINE_FUNCTION float nan () {
649 #ifdef __CUDA_ARCH__
650  return CUDART_NAN_F;
651  //return nan (); //this returns 0???
652 #else
653  // http://pubs.opengroup.org/onlinepubs/009696899/functions/nan.html
654  return strtof ("NAN()", (char**) NULL);
655 #endif // __CUDA_ARCH__
656  }
657  static KOKKOS_FORCEINLINE_FUNCTION mag_type eps () {
658  return epsilon ();
659  }
660  static KOKKOS_FORCEINLINE_FUNCTION mag_type sfmin () {
661  return FLT_MIN; // ???
662  }
663  static KOKKOS_FORCEINLINE_FUNCTION int base () {
664  return FLT_RADIX;
665  }
666  static KOKKOS_FORCEINLINE_FUNCTION mag_type prec () {
667  return eps () * static_cast<mag_type> (base ());
668  }
669  static KOKKOS_FORCEINLINE_FUNCTION int t () {
670  return FLT_MANT_DIG;
671  }
672  static KOKKOS_FORCEINLINE_FUNCTION mag_type rnd () {
673  return 1.0;
674  }
675  static KOKKOS_FORCEINLINE_FUNCTION int emin () {
676  return FLT_MIN_EXP;
677  }
678  static KOKKOS_FORCEINLINE_FUNCTION mag_type rmin () {
679  return FLT_MIN; // ??? // should be base^(emin-1)
680  }
681  static KOKKOS_FORCEINLINE_FUNCTION int emax () {
682  return FLT_MAX_EXP;
683  }
684  static KOKKOS_FORCEINLINE_FUNCTION mag_type rmax () {
685  return FLT_MAX; // ??? // should be (base^emax)*(1-eps)
686  }
687 };
688 
689 
690 // The C++ Standard Library (with C++03 at least) only allows
691 // std::complex<T> for T = float, double, or long double.
692 template<class RealFloatType>
693 class ArithTraits<std::complex<RealFloatType> > {
694 public:
695  typedef ::Kokkos::complex<RealFloatType> val_type;
696  typedef RealFloatType mag_type;
697 
698  static const bool is_specialized = true;
699  static const bool is_signed = true;
700  static const bool is_integer = false;
701  static const bool is_exact = false;
702  static const bool is_complex = true;
703 
704  static bool isInf (const std::complex<RealFloatType>& x) {
705 #if defined(__CUDACC__) || defined(_CRAYC)
706  return isinf (real (x)) || isinf (imag (x));
707 #else
708  return std::isinf (real (x)) || std::isinf (imag (x));
709 #endif // __CUDACC__
710  }
711  static bool isNan (const std::complex<RealFloatType>& x) {
712 #if defined(__CUDACC__) || defined(_CRAYC)
713  return isnan (real (x)) || isnan (imag (x));
714 #else
715  return std::isnan (real (x)) || std::isnan (imag (x));
716 #endif // __CUDACC__
717  }
718  static mag_type abs (const std::complex<RealFloatType>& x) {
719  return std::abs (x);
720  }
721  static std::complex<RealFloatType> zero () {
722  return std::complex<RealFloatType> (ArithTraits<mag_type>::zero (), ArithTraits<mag_type>::zero ());
723  }
724  static std::complex<RealFloatType> one () {
725  return std::complex<RealFloatType> (ArithTraits<mag_type>::one (), ArithTraits<mag_type>::zero ());
726  }
727  static std::complex<RealFloatType> min () {
728  return std::complex<RealFloatType> (ArithTraits<mag_type>::min (), ArithTraits<mag_type>::zero ());
729  }
730  static std::complex<RealFloatType> max () {
731  return std::complex<RealFloatType> (ArithTraits<mag_type>::max (), ArithTraits<mag_type>::zero ());
732  }
733  static mag_type real (const std::complex<RealFloatType>& x) {
734  return std::real (x);
735  }
736  static mag_type imag (const std::complex<RealFloatType>& x) {
737  return std::imag (x);
738  }
739  static std::complex<RealFloatType> conj (const std::complex<RealFloatType>& x) {
740  return std::conj (x);
741  }
742  static std::complex<RealFloatType>
743  pow (const std::complex<RealFloatType>& x, const std::complex<RealFloatType>& y) {
744  // Fix for some weird gcc 4.2.1 inaccuracy.
745  if (y == one ()) {
746  return x;
747  } else if (y == one () + one ()) {
748  return x * x;
749  } else {
750  return std::pow (x, y);
751  }
752  }
753  static std::complex<RealFloatType> sqrt (const std::complex<RealFloatType>& x) {
754  return std::sqrt (x);
755  }
756  static std::complex<RealFloatType> log (const std::complex<RealFloatType>& x) {
757  return std::log (x);
758  }
759  static std::complex<RealFloatType> log10 (const std::complex<RealFloatType>& x) {
760  return std::log10 (x);
761  }
762  static std::complex<RealFloatType> nan () {
763  const mag_type mag_nan = ArithTraits<mag_type>::nan ();
764  return std::complex<RealFloatType> (mag_nan, mag_nan);
765  }
766  static mag_type epsilon () {
768  }
769 
770  // Backwards compatibility with Teuchos::ScalarTraits.
771  typedef mag_type magnitudeType;
772  typedef std::complex<typename ArithTraits<mag_type>::halfPrecision> halfPrecision;
773  typedef std::complex<typename ArithTraits<mag_type>::doublePrecision> doublePrecision;
774 
775  static const bool isComplex = true;
776  static const bool isOrdinal = false;
777  static const bool isComparable = false;
778  static const bool hasMachineParameters = true;
779  static bool isnaninf (const std::complex<RealFloatType>& x) {
780  return isNan (x) || isInf (x);
781  }
782  static mag_type magnitude (const std::complex<RealFloatType>& x) {
783  return abs (x);
784  }
785  static std::complex<RealFloatType> conjugate (const std::complex<RealFloatType>& x) {
786  return conj (x);
787  }
788  static std::string name () {
789  return std::string ("std::complex<") + ArithTraits<mag_type>::name () + ">";
790  }
791  static std::complex<RealFloatType> squareroot (const std::complex<RealFloatType>& x) {
792  return sqrt (x);
793  }
794  static mag_type eps () {
795  return epsilon ();
796  }
797  static mag_type sfmin () {
799  }
800  static int base () {
801  return ArithTraits<mag_type>::base ();
802  }
803  static mag_type prec () {
804  return ArithTraits<mag_type>::prec ();
805  }
806  static int t () {
807  return ArithTraits<mag_type>::t ();
808  }
809  static mag_type rnd () {
810  return ArithTraits<mag_type>::one ();
811  }
812  static int emin () {
813  return ArithTraits<mag_type>::emin ();
814  }
815  static mag_type rmin () {
816  return ArithTraits<mag_type>::rmin ();
817  }
818  static int emax () {
819  return ArithTraits<mag_type>::emax ();
820  }
821  static mag_type rmax () {
822  return ArithTraits<mag_type>::rmax ();
823  }
824 };
825 
826 
827 template<>
828 class ArithTraits<double> {
829 public:
830  typedef double val_type;
831  typedef val_type mag_type;
832 
833  static const bool is_specialized = true;
834  static const bool is_signed = true;
835  static const bool is_integer = false;
836  static const bool is_exact = false;
837  static const bool is_complex = false;
838 
839  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const val_type x) {
840 #ifdef __APPLE__
841  return std::isinf (x);
842 #else
843  return isinf (x);
844 #endif // __APPLE__
845  }
846  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const val_type x) {
847 #ifdef __APPLE__
848  return std::isnan (x);
849 #else
850  return isnan (x);
851 #endif // __APPLE__
852  }
853  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const val_type x) {
854  return ::fabs (x);
855  }
856  static KOKKOS_FORCEINLINE_FUNCTION val_type zero () {
857  return 0.0;
858  }
859  static KOKKOS_FORCEINLINE_FUNCTION val_type one () {
860  return 1.0;
861  }
862  static KOKKOS_FORCEINLINE_FUNCTION val_type min () {
863  return DBL_MIN;
864  }
865  static KOKKOS_FORCEINLINE_FUNCTION val_type max () {
866  return DBL_MAX;
867  }
868  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const val_type x) {
869  return x;
870  }
871  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const val_type) {
872  return 0.0;
873  }
874  static KOKKOS_FORCEINLINE_FUNCTION val_type conj (const val_type x) {
875  return x;
876  }
877  static KOKKOS_FORCEINLINE_FUNCTION val_type pow (const val_type x, const val_type y) {
878  return ::pow (x, y);
879  }
880  static KOKKOS_FORCEINLINE_FUNCTION val_type sqrt (const val_type x) {
881  return ::sqrt (x);
882  }
883  static KOKKOS_FORCEINLINE_FUNCTION val_type log (const val_type x) {
884  return ::log (x);
885  }
886  static KOKKOS_FORCEINLINE_FUNCTION val_type log10 (const val_type x) {
887  return ::log10 (x);
888  }
889  static KOKKOS_FORCEINLINE_FUNCTION val_type nan () {
890 #ifdef __CUDA_ARCH__
891  return CUDART_NAN;
892  //return nan (); // this returns 0 ???
893 #else
894  // http://pubs.opengroup.org/onlinepubs/009696899/functions/nan.html
895  return strtod ("NAN", (char**) NULL);
896 #endif // __CUDA_ARCH__
897  }
898  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon () {
899  return DBL_EPSILON;
900  }
901 
902  // Backwards compatibility with Teuchos::ScalarTraits.
903  typedef mag_type magnitudeType;
904  typedef float halfPrecision;
905 #ifdef __CUDA_ARCH__
906  typedef double doublePrecision; // CUDA doesn't support long double, unfortunately
907 #else
908  typedef long double doublePrecision;
909 #endif // __CUDA_ARCH__
910  static const bool isComplex = false;
911  static const bool isOrdinal = false;
912  static const bool isComparable = true;
913  static const bool hasMachineParameters = true;
914  static bool isnaninf (const val_type& x) {
915  return isNan (x) || isInf (x);
916  }
917  static KOKKOS_FORCEINLINE_FUNCTION mag_type magnitude (const val_type x) {
918  return abs (x);
919  }
920  static KOKKOS_FORCEINLINE_FUNCTION val_type conjugate (const val_type x) {
921  return conj (x);
922  }
923  static std::string name () {
924  return "double";
925  }
926  static KOKKOS_FORCEINLINE_FUNCTION val_type squareroot (const val_type x) {
927  return sqrt (x);
928  }
929  static KOKKOS_FORCEINLINE_FUNCTION mag_type eps () {
930  return epsilon ();
931  }
932  static KOKKOS_FORCEINLINE_FUNCTION mag_type sfmin () {
933  return DBL_MIN; // ???
934  }
935  static KOKKOS_FORCEINLINE_FUNCTION int base () {
936  return FLT_RADIX; // same for float as for double
937  }
938  static KOKKOS_FORCEINLINE_FUNCTION mag_type prec () {
939  return eps () * static_cast<mag_type> (base ());
940  }
941  static KOKKOS_FORCEINLINE_FUNCTION int t () {
942  return DBL_MANT_DIG;
943  }
944  static KOKKOS_FORCEINLINE_FUNCTION mag_type rnd () {
945  return 1.0;
946  }
947  static KOKKOS_FORCEINLINE_FUNCTION int emin () {
948  return DBL_MIN_EXP;
949  }
950  static KOKKOS_FORCEINLINE_FUNCTION mag_type rmin () {
951  return DBL_MIN; // ??? // should be base^(emin-1)
952  }
953  static KOKKOS_FORCEINLINE_FUNCTION int emax () {
954  return DBL_MAX_EXP;
955  }
956  static KOKKOS_FORCEINLINE_FUNCTION mag_type rmax () {
957  return DBL_MAX; // ??? // should be (base^emax)*(1-eps)
958  }
959 };
960 
961 
962 // CUDA does not support long double in device functions, so none of
963 // the class methods in this specialization are marked as device
964 // functions.
965 template<>
966 class ArithTraits<long double> {
967 public:
968  typedef long double val_type;
969  typedef long double mag_type;
970 
971  static const bool is_specialized = true;
972  static const bool is_signed = true;
973  static const bool is_integer = false;
974  static const bool is_exact = false;
975  static const bool is_complex = false;
976 
977  static bool isInf (const val_type& x) {
978 #if defined(__CUDACC__) || defined(_CRAYC)
979  return isinf (x);
980 #else
981  return std::isinf (x);
982 #endif // __CUDACC__
983  }
984  static bool isNan (const val_type& x) {
985 #if defined(__CUDACC__) || defined(_CRAYC)
986  return isnan (x);
987 #else
988  return std::isnan (x);
989 #endif // __CUDACC__
990  }
991  static mag_type abs (const val_type& x) {
992  return ::fabs (x);
993  }
994  static val_type zero () {
995  return 0.0;
996  }
997  static val_type one () {
998  return 1.0;
999  }
1000  static val_type min () {
1001  return LDBL_MIN;
1002  }
1003  static val_type max () {
1004  return LDBL_MAX;
1005  }
1006  static mag_type real (const val_type& x) {
1007  return x;
1008  }
1009  static mag_type imag (const val_type&) {
1010  return zero ();
1011  }
1012  static val_type conj (const val_type& x) {
1013  return x;
1014  }
1015  static val_type pow (const val_type& x, const val_type& y) {
1016  return ::pow (x, y);
1017  }
1018  static val_type sqrt (const val_type& x) {
1019  return ::sqrt (x);
1020  }
1021  static val_type log (const val_type& x) {
1022  return ::log (x);
1023  }
1024  static val_type log10 (const val_type& x) {
1025  return ::log10 (x);
1026  }
1027  static val_type nan () {
1028  return strtold ("NAN()", (char**) NULL);
1029  }
1030  static mag_type epsilon () {
1031  return LDBL_EPSILON;
1032  }
1033 
1034  // Backwards compatibility with Teuchos::ScalarTraits.
1035  typedef mag_type magnitudeType;
1036  typedef double halfPrecision;
1037  // It might be appropriate to use QD's qd_real here.
1038  // For now, long double is the most you get.
1039  typedef val_type doublePrecision;
1040 
1041  static const bool isComplex = false;
1042  static const bool isOrdinal = false;
1043  static const bool isComparable = true;
1044  static const bool hasMachineParameters = true;
1045  static bool isnaninf (const val_type& x) {
1046  return isNan (x) || isInf (x);
1047  }
1048  static mag_type magnitude (const val_type& x) {
1049  return abs (x);
1050  }
1051  static val_type conjugate (const val_type& x) {
1052  return conj (x);
1053  }
1054  static std::string name () {
1055  return "long double";
1056  }
1057  static val_type squareroot (const val_type& x) {
1058  return sqrt (x);
1059  }
1060  static mag_type eps () {
1061  return epsilon ();
1062  }
1063  static mag_type sfmin () {
1064  return LDBL_MIN; // ???
1065  }
1066  static int base () {
1067  return FLT_RADIX; // same for float as for double or long double
1068  }
1069  static mag_type prec () {
1070  return eps () * static_cast<mag_type> (base ());
1071  }
1072  static int t () {
1073  return LDBL_MANT_DIG;
1074  }
1075  static mag_type rnd () {
1076  return one ();
1077  }
1078  static int emin () {
1079  return LDBL_MIN_EXP;
1080  }
1081  static mag_type rmin () {
1082  return LDBL_MIN;
1083  }
1084  static int emax () {
1085  return LDBL_MAX_EXP;
1086  }
1087  static mag_type rmax () {
1088  return LDBL_MAX;
1089  }
1090 };
1091 
1092 
1093 template<>
1094 class ArithTraits< ::Kokkos::complex<float> > {
1095 public:
1096  typedef ::Kokkos::complex<float> val_type;
1097  typedef float mag_type;
1098 
1099  static const bool is_specialized = true;
1100  static const bool is_signed = true;
1101  static const bool is_integer = false;
1102  static const bool is_exact = false;
1103  static const bool is_complex = true;
1104 
1105  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const val_type x) {
1106  return ArithTraits<mag_type>::isInf (x.real ()) ||
1107  ArithTraits<mag_type>::isInf (x.imag ());
1108  }
1109  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const val_type x) {
1110  return ArithTraits<mag_type>::isNan (x.real ()) ||
1111  ArithTraits<mag_type>::isNan (x.imag ());
1112  }
1113  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const val_type x) {
1114  return sqrt (::Kokkos::real (x) * ::Kokkos::real (x) +
1115  ::Kokkos::imag (x) * ::Kokkos::imag (x));
1116  }
1117  static KOKKOS_FORCEINLINE_FUNCTION val_type zero () {
1118  return val_type (ArithTraits<mag_type>::zero (), ArithTraits<mag_type>::zero ());
1119  }
1120  static KOKKOS_FORCEINLINE_FUNCTION val_type one () {
1121  return val_type (ArithTraits<mag_type>::one (), ArithTraits<mag_type>::zero ());
1122  }
1123  static KOKKOS_FORCEINLINE_FUNCTION val_type min () {
1124  return val_type (ArithTraits<mag_type>::min (), ArithTraits<mag_type>::min ()); // ???
1125  }
1126  static KOKKOS_FORCEINLINE_FUNCTION val_type max () {
1127  return val_type (ArithTraits<mag_type>::max (), ArithTraits<mag_type>::max ()); // ???
1128  }
1129  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const val_type x) {
1130  return x.real ();
1131  }
1132  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const val_type x) {
1133  return x.imag ();
1134  }
1135  static KOKKOS_FORCEINLINE_FUNCTION val_type conj (const val_type x) {
1136  return ::Kokkos::conj (x);
1137  }
1138  // static KOKKOS_FORCEINLINE_FUNCTION val_type pow (const val_type x, const val_type y) {
1139  // return ::pow (x, y);
1140  // }
1141  // static KOKKOS_FORCEINLINE_FUNCTION val_type sqrt (const val_type x) {
1142  // return ::sqrt (x);
1143  // }
1144  // static KOKKOS_FORCEINLINE_FUNCTION val_type log (const val_type x) {
1145  // return ::log (x);
1146  // }
1147  // static KOKKOS_FORCEINLINE_FUNCTION val_type log10 (const val_type x) {
1148  // return ::log10 (x);
1149  // }
1150  static KOKKOS_FORCEINLINE_FUNCTION val_type nan () {
1151  // ???
1152  return val_type (ArithTraits<mag_type>::nan (), ArithTraits<mag_type>::nan ());
1153  }
1154  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon () {
1155  return ArithTraits<mag_type>::epsilon (); // ???
1156  }
1157 
1158  // Backwards compatibility with Teuchos::ScalarTraits.
1159  typedef mag_type magnitudeType;
1160  typedef ::Kokkos::complex<ArithTraits<mag_type>::halfPrecision> halfPrecision;
1161  typedef ::Kokkos::complex<ArithTraits<mag_type>::doublePrecision> doublePrecision;
1162 
1163  static const bool isComplex = true;
1164  static const bool isOrdinal = false;
1165  static const bool isComparable = false;
1166  static const bool hasMachineParameters = ArithTraits<mag_type>::hasMachineParameters;
1167  static bool isnaninf (const val_type& x) {
1168  return isNan (x) || isInf (x);
1169  }
1170  static KOKKOS_FORCEINLINE_FUNCTION mag_type magnitude (const val_type x) {
1171  return abs (x);
1172  }
1173  static KOKKOS_FORCEINLINE_FUNCTION val_type conjugate (const val_type x) {
1174  return conj (x);
1175  }
1176  static std::string name () {
1177  return "Kokkos::complex<float>";
1178  }
1179  // static KOKKOS_FORCEINLINE_FUNCTION val_type squareroot (const val_type x) {
1180  // return sqrt (x);
1181  // }
1182  static KOKKOS_FORCEINLINE_FUNCTION mag_type eps () {
1183  return epsilon ();
1184  }
1185  static KOKKOS_FORCEINLINE_FUNCTION mag_type sfmin () {
1186  return ArithTraits<mag_type>::sfmin (); // ???
1187  }
1188  static KOKKOS_FORCEINLINE_FUNCTION int base () {
1189  return ArithTraits<mag_type>::base ();
1190  }
1191  static KOKKOS_FORCEINLINE_FUNCTION mag_type prec () {
1192  return ArithTraits<mag_type>::prec (); // ???
1193  }
1194  static KOKKOS_FORCEINLINE_FUNCTION int t () {
1195  return ArithTraits<mag_type>::t ();
1196  }
1197  static KOKKOS_FORCEINLINE_FUNCTION mag_type rnd () {
1198  return ArithTraits<mag_type>::rnd ();
1199  }
1200  static KOKKOS_FORCEINLINE_FUNCTION int emin () {
1201  return ArithTraits<mag_type>::emin ();
1202  }
1203  static KOKKOS_FORCEINLINE_FUNCTION mag_type rmin () {
1204  return ArithTraits<mag_type>::rmin ();
1205  }
1206  static KOKKOS_FORCEINLINE_FUNCTION int emax () {
1207  return ArithTraits<mag_type>::emax ();
1208  }
1209  static KOKKOS_FORCEINLINE_FUNCTION mag_type rmax () {
1210  return ArithTraits<mag_type>::rmax ();
1211  }
1212 };
1213 
1214 
1215 template<>
1216 class ArithTraits< ::Kokkos::complex<double> > {
1217 public:
1218  typedef ::Kokkos::complex<double> val_type;
1219  typedef double mag_type;
1220 
1221  static const bool is_specialized = true;
1222  static const bool is_signed = true;
1223  static const bool is_integer = false;
1224  static const bool is_exact = false;
1225  static const bool is_complex = true;
1226 
1227  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const val_type x) {
1228  return ArithTraits<mag_type>::isInf (x.real ()) ||
1229  ArithTraits<mag_type>::isInf (x.imag ());
1230  }
1231  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const val_type x) {
1232  return ArithTraits<mag_type>::isNan (x.real ()) ||
1233  ArithTraits<mag_type>::isNan (x.imag ());
1234  }
1235  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const val_type x) {
1236  return ::Kokkos::abs (x);
1237  }
1238  static KOKKOS_FORCEINLINE_FUNCTION val_type zero () {
1239  return val_type (ArithTraits<mag_type>::zero (), ArithTraits<mag_type>::zero ());
1240  }
1241  static KOKKOS_FORCEINLINE_FUNCTION val_type one () {
1242  return val_type (ArithTraits<mag_type>::one (), ArithTraits<mag_type>::zero ());
1243  }
1244  static KOKKOS_FORCEINLINE_FUNCTION val_type min () {
1245  return val_type (ArithTraits<mag_type>::min (), ArithTraits<mag_type>::min ()); // ???
1246  }
1247  static KOKKOS_FORCEINLINE_FUNCTION val_type max () {
1248  return val_type (ArithTraits<mag_type>::max (), ArithTraits<mag_type>::max ()); // ???
1249  }
1250  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const val_type x) {
1251  return x.real ();
1252  }
1253  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const val_type x) {
1254  return x.imag ();
1255  }
1256  static KOKKOS_FORCEINLINE_FUNCTION val_type conj (const val_type x) {
1257  return ::Kokkos::conj (x);
1258  }
1259  // static KOKKOS_FORCEINLINE_FUNCTION val_type pow (const val_type x, const val_type y) {
1260  // return ::pow (x, y);
1261  // }
1262  // static KOKKOS_FORCEINLINE_FUNCTION val_type sqrt (const val_type x) {
1263  // return ::sqrt (x);
1264  // }
1265  // static KOKKOS_FORCEINLINE_FUNCTION val_type log (const val_type x) {
1266  // return ::log (x);
1267  // }
1268  // static KOKKOS_FORCEINLINE_FUNCTION val_type log10 (const val_type x) {
1269  // return ::log10 (x);
1270  // }
1271  static KOKKOS_FORCEINLINE_FUNCTION val_type nan () {
1272  // ???
1273  return val_type (ArithTraits<mag_type>::nan (), ArithTraits<mag_type>::nan ());
1274  }
1275  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon () {
1276  return ArithTraits<mag_type>::epsilon (); // ???
1277  }
1278 
1279  // Backwards compatibility with Teuchos::ScalarTraits.
1280  typedef mag_type magnitudeType;
1281  typedef ::Kokkos::complex<ArithTraits<mag_type>::halfPrecision> halfPrecision;
1282  typedef ::Kokkos::complex<ArithTraits<mag_type>::doublePrecision> doublePrecision;
1283 
1284  static const bool isComplex = true;
1285  static const bool isOrdinal = false;
1286  static const bool isComparable = false;
1287  static const bool hasMachineParameters = ArithTraits<mag_type>::hasMachineParameters;
1288  static bool isnaninf (const val_type& x) {
1289  return isNan (x) || isInf (x);
1290  }
1291  static KOKKOS_FORCEINLINE_FUNCTION mag_type magnitude (const val_type x) {
1292  return abs (x);
1293  }
1294  static KOKKOS_FORCEINLINE_FUNCTION val_type conjugate (const val_type x) {
1295  return conj (x);
1296  }
1297  static std::string name () {
1298  return "Kokkos::complex<double>";
1299  }
1300  // static KOKKOS_FORCEINLINE_FUNCTION val_type squareroot (const val_type x) {
1301  // return sqrt (x);
1302  // }
1303  static KOKKOS_FORCEINLINE_FUNCTION mag_type eps () {
1304  return epsilon ();
1305  }
1306  static KOKKOS_FORCEINLINE_FUNCTION mag_type sfmin () {
1307  return ArithTraits<mag_type>::sfmin (); // ???
1308  }
1309  static KOKKOS_FORCEINLINE_FUNCTION int base () {
1310  return ArithTraits<mag_type>::base ();
1311  }
1312  static KOKKOS_FORCEINLINE_FUNCTION mag_type prec () {
1313  return ArithTraits<mag_type>::prec (); // ???
1314  }
1315  static KOKKOS_FORCEINLINE_FUNCTION int t () {
1316  return ArithTraits<mag_type>::t ();
1317  }
1318  static KOKKOS_FORCEINLINE_FUNCTION mag_type rnd () {
1319  return ArithTraits<mag_type>::rnd ();
1320  }
1321  static KOKKOS_FORCEINLINE_FUNCTION int emin () {
1322  return ArithTraits<mag_type>::emin ();
1323  }
1324  static KOKKOS_FORCEINLINE_FUNCTION mag_type rmin () {
1325  return ArithTraits<mag_type>::rmin ();
1326  }
1327  static KOKKOS_FORCEINLINE_FUNCTION int emax () {
1328  return ArithTraits<mag_type>::emax ();
1329  }
1330  static KOKKOS_FORCEINLINE_FUNCTION mag_type rmax () {
1331  return ArithTraits<mag_type>::rmax ();
1332  }
1333 };
1334 
1335 
1336 template<>
1337 class ArithTraits<char> {
1338 public:
1339  typedef char val_type;
1340  typedef val_type mag_type;
1341 
1342  static const bool is_specialized = true;
1343  // The C(++) standard does not require that char be signed. In
1344  // fact, signed char, unsigned char, and char are distinct types.
1345  // We can use std::numeric_limits here because it's a const bool,
1346  // not a class method.
1347  static const bool is_signed = std::numeric_limits<char>::is_signed;
1348  static const bool is_integer = true;
1349  static const bool is_exact = true;
1350  static const bool is_complex = false;
1351 
1352  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const val_type x) {
1353  return false;
1354  }
1355  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const val_type x) {
1356  return false;
1357  }
1358  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const val_type x) {
1359  // This may trigger a compiler warning if char is unsigned. On
1360  // all platforms I have encountered, char is signed, but the C(++)
1361  // standard does not require this.
1362  return x >= 0 ? x : -x;
1363  }
1364  static KOKKOS_FORCEINLINE_FUNCTION val_type zero () {
1365  return 0;
1366  }
1367  static KOKKOS_FORCEINLINE_FUNCTION val_type one () {
1368  return 1;
1369  }
1370  static KOKKOS_FORCEINLINE_FUNCTION val_type min () {
1371  return CHAR_MIN;
1372  }
1373  static KOKKOS_FORCEINLINE_FUNCTION val_type max () {
1374  return CHAR_MAX;
1375  }
1376  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const val_type x) {
1377  return x;
1378  }
1379  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const val_type x) {
1380  return 0;
1381  }
1382  static KOKKOS_FORCEINLINE_FUNCTION val_type conj (const val_type x) {
1383  return x;
1384  }
1385  static KOKKOS_FORCEINLINE_FUNCTION val_type
1386  pow (const val_type x, const val_type y) {
1387  if (is_signed) {
1388  return intPowSigned<val_type> (x, y);
1389  } else {
1390  return intPowUnsigned<val_type> (x, y);
1391  }
1392  }
1393  static KOKKOS_FORCEINLINE_FUNCTION val_type sqrt (const val_type x) {
1394  // C++11 defines std::sqrt for integer arguments. However, we
1395  // currently can't assume C++11.
1396  //
1397  // This cast will result in no loss of accuracy, though it might
1398  // be more expensive than it should, if we were clever about using
1399  // bit operations.
1400  //
1401  // We take the absolute value first to avoid negative arguments.
1402  // Negative real arguments to sqrt(float) return (float) NaN, but
1403  // built-in integer types do not have an equivalent to NaN.
1404  // Casting NaN to an integer type will thus result in some integer
1405  // value which appears valid, but is not. We cannot raise an
1406  // exception in device functions. Thus, we prefer to take the
1407  // absolute value of x first, to avoid issues. Another
1408  // possibility would be to test for a NaN output and convert it to
1409  // some reasonable value (like 0), though this might be more
1410  // expensive than the absolute value interpreted using the ternary
1411  // operator.
1412  return static_cast<val_type> ( ::sqrt (static_cast<float> (abs (x))));
1413  }
1414  static KOKKOS_FORCEINLINE_FUNCTION val_type log (const val_type x) {
1415  return static_cast<val_type> ( ::log (static_cast<float> (abs (x))));
1416  }
1417  static KOKKOS_FORCEINLINE_FUNCTION val_type log10 (const val_type x) {
1418  return static_cast<val_type> ( ::log10 (static_cast<float> (abs (x))));
1419  }
1420  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon () {
1421  return zero ();
1422  }
1423 
1424  // Backwards compatibility with Teuchos::ScalarTraits.
1425  typedef mag_type magnitudeType;
1426  typedef val_type halfPrecision;
1427  typedef val_type doublePrecision;
1428 
1429  static const bool isComplex = false;
1430  static const bool isOrdinal = true;
1431  static const bool isComparable = true;
1432  static const bool hasMachineParameters = false;
1433  static KOKKOS_FORCEINLINE_FUNCTION magnitudeType magnitude (const val_type x) {
1434  return abs (x);
1435  }
1436  static KOKKOS_FORCEINLINE_FUNCTION val_type conjugate (const val_type x) {
1437  return conj (x);
1438  }
1439  static KOKKOS_FORCEINLINE_FUNCTION bool isnaninf (const val_type) {
1440  return false;
1441  }
1442  static std::string name () {
1443  return "char";
1444  }
1445  static KOKKOS_FORCEINLINE_FUNCTION val_type squareroot (const val_type x) {
1446  return sqrt (x);
1447  }
1448 };
1449 
1450 
1451 template<>
1452 class ArithTraits<signed char> {
1453 public:
1454  typedef signed char val_type;
1455  typedef val_type mag_type;
1456 
1457  static const bool is_specialized = true;
1458  static const bool is_signed = true;
1459  static const bool is_integer = true;
1460  static const bool is_exact = true;
1461  static const bool is_complex = false;
1462 
1463  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const val_type x) {
1464  return false;
1465  }
1466  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const val_type x) {
1467  return false;
1468  }
1469  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const val_type x) {
1470  return x >= 0 ? x : -x;
1471  }
1472  static KOKKOS_FORCEINLINE_FUNCTION val_type zero () {
1473  return 0;
1474  }
1475  static KOKKOS_FORCEINLINE_FUNCTION val_type one () {
1476  return 1;
1477  }
1478  static KOKKOS_FORCEINLINE_FUNCTION val_type min () {
1479  return SCHAR_MIN;
1480  }
1481  static KOKKOS_FORCEINLINE_FUNCTION val_type max () {
1482  return SCHAR_MAX;
1483  }
1484  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const val_type x) {
1485  return x;
1486  }
1487  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const val_type x) {
1488  return 0;
1489  }
1490  static KOKKOS_FORCEINLINE_FUNCTION val_type conj (const val_type x) {
1491  return x;
1492  }
1493  static KOKKOS_FORCEINLINE_FUNCTION val_type
1494  pow (const val_type x, const val_type y) {
1495  return intPowSigned<val_type> (x, y);
1496  }
1497  static KOKKOS_FORCEINLINE_FUNCTION val_type sqrt (const val_type x) {
1498  return static_cast<val_type> ( ::sqrt (static_cast<float> (abs (x))));
1499  }
1500  static KOKKOS_FORCEINLINE_FUNCTION val_type log (const val_type x) {
1501  return static_cast<val_type> ( ::log (static_cast<float> (abs (x))));
1502  }
1503  static KOKKOS_FORCEINLINE_FUNCTION val_type log10 (const val_type x) {
1504  return static_cast<val_type> ( ::log10 (static_cast<float> (abs (x))));
1505  }
1506  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon () {
1507  return zero ();
1508  }
1509 
1510  // Backwards compatibility with Teuchos::ScalarTraits.
1511  typedef mag_type magnitudeType;
1512  typedef val_type halfPrecision;
1513  typedef val_type doublePrecision;
1514 
1515  static const bool isComplex = false;
1516  static const bool isOrdinal = true;
1517  static const bool isComparable = true;
1518  static const bool hasMachineParameters = false;
1519  static KOKKOS_FORCEINLINE_FUNCTION magnitudeType magnitude (const val_type x) {
1520  return abs (x);
1521  }
1522  static KOKKOS_FORCEINLINE_FUNCTION val_type conjugate (const val_type x) {
1523  return conj (x);
1524  }
1525  static KOKKOS_FORCEINLINE_FUNCTION bool isnaninf (const val_type) {
1526  return false;
1527  }
1528  static std::string name () {
1529  return "signed char";
1530  }
1531  static KOKKOS_FORCEINLINE_FUNCTION val_type squareroot (const val_type x) {
1532  return sqrt (x);
1533  }
1534 };
1535 
1536 
1537 template<>
1538 class ArithTraits<unsigned char> {
1539 public:
1540  typedef unsigned char val_type;
1541  typedef val_type mag_type;
1542 
1543  static const bool is_specialized = true;
1544  static const bool is_signed = false;
1545  static const bool is_integer = true;
1546  static const bool is_exact = true;
1547  static const bool is_complex = false;
1548 
1549  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const val_type x) {
1550  return false;
1551  }
1552  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const val_type x) {
1553  return false;
1554  }
1555  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const val_type x) {
1556  return x; // it's unsigned, so it's positive
1557  }
1558  static KOKKOS_FORCEINLINE_FUNCTION val_type zero () {
1559  return 0;
1560  }
1561  static KOKKOS_FORCEINLINE_FUNCTION val_type one () {
1562  return 1;
1563  }
1564  static KOKKOS_FORCEINLINE_FUNCTION val_type min () {
1565  return 0;
1566  }
1567  static KOKKOS_FORCEINLINE_FUNCTION val_type max () {
1568  return UCHAR_MAX;
1569  }
1570  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const val_type x) {
1571  return x;
1572  }
1573  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const val_type x) {
1574  return 0;
1575  }
1576  static KOKKOS_FORCEINLINE_FUNCTION val_type conj (const val_type x) {
1577  return x;
1578  }
1579  static KOKKOS_FORCEINLINE_FUNCTION val_type
1580  pow (const val_type x, const val_type y) {
1581  return intPowUnsigned<val_type> (x, y);
1582  }
1583  static KOKKOS_FORCEINLINE_FUNCTION val_type sqrt (const val_type x) {
1584  // This will result in no loss of accuracy, though it might be
1585  // more expensive than it should, if we were clever about using
1586  // bit operations.
1587  return static_cast<val_type> ( ::sqrt (static_cast<float> (x)));
1588  }
1589 
1590  static KOKKOS_FORCEINLINE_FUNCTION val_type log (const val_type x) {
1591  return static_cast<val_type> ( ::log (static_cast<float> (x)));
1592  }
1593  static KOKKOS_FORCEINLINE_FUNCTION val_type log10 (const val_type x) {
1594  return static_cast<val_type> ( ::log10 (static_cast<float> (x)));
1595  }
1596  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon () {
1597  return zero ();
1598  }
1599 
1600  // Backwards compatibility with Teuchos::ScalarTraits.
1601  typedef mag_type magnitudeType;
1602  typedef val_type halfPrecision;
1603  typedef val_type doublePrecision;
1604 
1605  static const bool isComplex = false;
1606  static const bool isOrdinal = true;
1607  static const bool isComparable = true;
1608  static const bool hasMachineParameters = false;
1609  static KOKKOS_FORCEINLINE_FUNCTION magnitudeType magnitude (const val_type x) {
1610  return abs (x);
1611  }
1612  static KOKKOS_FORCEINLINE_FUNCTION val_type conjugate (const val_type x) {
1613  return conj (x);
1614  }
1615  static KOKKOS_FORCEINLINE_FUNCTION bool isnaninf (const val_type) {
1616  return false;
1617  }
1618  static std::string name () {
1619  return "unsigned char";
1620  }
1621  static KOKKOS_FORCEINLINE_FUNCTION val_type squareroot (const val_type x) {
1622  return sqrt (x);
1623  }
1624 };
1625 
1626 
1627 template<>
1628 class ArithTraits<short> {
1629 public:
1630  typedef short val_type;
1631  typedef val_type mag_type;
1632 
1633  static const bool is_specialized = true;
1634  static const bool is_signed = true;
1635  static const bool is_integer = true;
1636  static const bool is_exact = true;
1637  static const bool is_complex = false;
1638 
1639  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const val_type x) {
1640  return false;
1641  }
1642  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const val_type x) {
1643  return false;
1644  }
1645  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const val_type x) {
1646  // std::abs appears to work with CUDA 5.5 at least, but I'll use
1647  // the ternary expression for maximum generality. Note that this
1648  // expression does not necessarily obey the rules for fabs() with
1649  // NaN input, so it should not be used for floating-point types.
1650  // It's perfectly fine for signed integer types, though.
1651  return x >= 0 ? x : -x;
1652  }
1653  static KOKKOS_FORCEINLINE_FUNCTION val_type zero () {
1654  return 0;
1655  }
1656  static KOKKOS_FORCEINLINE_FUNCTION val_type one () {
1657  return 1;
1658  }
1659  static KOKKOS_FORCEINLINE_FUNCTION val_type min () {
1660  // Macros like this work with CUDA, but
1661  // std::numeric_limits<val_type>::min() does not, because it is
1662  // not marked as a __device__ function.
1663  return SHRT_MIN;
1664  }
1665  static KOKKOS_FORCEINLINE_FUNCTION val_type max () {
1666  return SHRT_MAX;
1667  }
1668  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const val_type x) {
1669  return x;
1670  }
1671  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const val_type x) {
1672  return 0;
1673  }
1674  static KOKKOS_FORCEINLINE_FUNCTION val_type conj (const val_type x) {
1675  return x;
1676  }
1677  static KOKKOS_FORCEINLINE_FUNCTION val_type pow (const val_type x, const val_type y) {
1678  return intPowSigned<val_type> (x, y);
1679  }
1681  static KOKKOS_FORCEINLINE_FUNCTION val_type sqrt (const val_type x) {
1682  // This will result in no loss of accuracy, though it might be
1683  // more expensive than it should, if we were clever about using
1684  // bit operations.
1685  return static_cast<val_type> ( ::sqrt (static_cast<float> (abs (x))));
1686  }
1687  static KOKKOS_FORCEINLINE_FUNCTION val_type log (const val_type x) {
1688  return static_cast<val_type> ( ::log (static_cast<float> (abs (x))));
1689  }
1690  static KOKKOS_FORCEINLINE_FUNCTION val_type log10 (const val_type x) {
1691  return static_cast<val_type> ( ::log10 (static_cast<float> (abs (x))));
1692  }
1693  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon () {
1694  return zero ();
1695  }
1696 
1697  // Backwards compatibility with Teuchos::ScalarTraits.
1698  typedef mag_type magnitudeType;
1699  typedef val_type halfPrecision;
1700  typedef val_type doublePrecision;
1701 
1702  static const bool isComplex = false;
1703  static const bool isOrdinal = true;
1704  static const bool isComparable = true;
1705  static const bool hasMachineParameters = false;
1706  static KOKKOS_FORCEINLINE_FUNCTION magnitudeType magnitude (const val_type x) {
1707  return abs (x);
1708  }
1709  static KOKKOS_FORCEINLINE_FUNCTION val_type conjugate (const val_type x) {
1710  return conj (x);
1711  }
1712  static KOKKOS_FORCEINLINE_FUNCTION bool isnaninf (const val_type) {
1713  return false;
1714  }
1715  static std::string name () {
1716  return "short";
1717  }
1718  static KOKKOS_FORCEINLINE_FUNCTION val_type squareroot (const val_type x) {
1719  return sqrt (x);
1720  }
1721 };
1722 
1723 
1724 template<>
1725 class ArithTraits<unsigned short> {
1726 public:
1727  typedef unsigned short val_type;
1728  typedef val_type mag_type;
1729 
1730  static const bool is_specialized = true;
1731  static const bool is_signed = false;
1732  static const bool is_integer = true;
1733  static const bool is_exact = true;
1734  static const bool is_complex = false;
1735 
1736  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const val_type x) {
1737  return false;
1738  }
1739  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const val_type x) {
1740  return false;
1741  }
1742  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const val_type x) {
1743  return x; // it's unsigned, so it's positive
1744  }
1745  static KOKKOS_FORCEINLINE_FUNCTION val_type zero () {
1746  return 0;
1747  }
1748  static KOKKOS_FORCEINLINE_FUNCTION val_type one () {
1749  return 1;
1750  }
1751  static KOKKOS_FORCEINLINE_FUNCTION val_type min () {
1752  return 0;
1753  }
1754  static KOKKOS_FORCEINLINE_FUNCTION val_type max () {
1755  return USHRT_MAX;
1756  }
1757  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const val_type x) {
1758  return x;
1759  }
1760  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const val_type x) {
1761  return 0;
1762  }
1763  static KOKKOS_FORCEINLINE_FUNCTION val_type conj (const val_type x) {
1764  return x;
1765  }
1766  static KOKKOS_FORCEINLINE_FUNCTION val_type
1767  pow (const val_type x, const val_type y) {
1768  return intPowUnsigned<val_type> (x, y);
1769  }
1770  static KOKKOS_FORCEINLINE_FUNCTION val_type sqrt (const val_type x) {
1771  // This will result in no loss of accuracy, though it might be
1772  // more expensive than it should, if we were clever about using
1773  // bit operations.
1774  return static_cast<val_type> ( ::sqrt (static_cast<float> (x)));
1775  }
1776  static KOKKOS_FORCEINLINE_FUNCTION val_type log (const val_type x) {
1777  return static_cast<val_type> ( ::log (static_cast<float> (x)));
1778  }
1779  static KOKKOS_FORCEINLINE_FUNCTION val_type log10 (const val_type x) {
1780  return static_cast<val_type> ( ::log10 (static_cast<float> (x)));
1781  }
1782  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon () {
1783  return zero ();
1784  }
1785 
1786  // Backwards compatibility with Teuchos::ScalarTraits.
1787  typedef mag_type magnitudeType;
1788  typedef val_type halfPrecision;
1789  typedef val_type doublePrecision;
1790 
1791  static const bool isComplex = false;
1792  static const bool isOrdinal = true;
1793  static const bool isComparable = true;
1794  static const bool hasMachineParameters = false;
1795  static KOKKOS_FORCEINLINE_FUNCTION magnitudeType magnitude (const val_type x) {
1796  return abs (x);
1797  }
1798  static KOKKOS_FORCEINLINE_FUNCTION val_type conjugate (const val_type x) {
1799  return conj (x);
1800  }
1801  static KOKKOS_FORCEINLINE_FUNCTION bool isnaninf (const val_type) {
1802  return false;
1803  }
1804  static std::string name () {
1805  return "unsigned short";
1806  }
1807  static KOKKOS_FORCEINLINE_FUNCTION val_type squareroot (const val_type x) {
1808  return sqrt (x);
1809  }
1810 };
1811 
1812 
1813 template<>
1814 class ArithTraits<int> {
1815 public:
1816  typedef int val_type;
1817  typedef val_type mag_type;
1818 
1819  static const bool is_specialized = true;
1820  static const bool is_signed = true;
1821  static const bool is_integer = true;
1822  static const bool is_exact = true;
1823  static const bool is_complex = false;
1824 
1825  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const val_type x) {
1826  return false;
1827  }
1828  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const val_type x) {
1829  return false;
1830  }
1831  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const val_type x) {
1832  // std::abs appears to work with CUDA 5.5 at least, but I'll use
1833  // the ternary expression for maximum generality. Note that this
1834  // expression does not necessarily obey the rules for fabs() with
1835  // NaN input, so it should not be used for floating-point types.
1836  // It's perfectly fine for signed integer types, though.
1837  return x >= 0 ? x : -x;
1838  }
1839  static KOKKOS_FORCEINLINE_FUNCTION val_type zero () {
1840  return 0;
1841  }
1842  static KOKKOS_FORCEINLINE_FUNCTION val_type one () {
1843  return 1;
1844  }
1845  static KOKKOS_FORCEINLINE_FUNCTION val_type min () {
1846  // Macros like INT_MIN work with CUDA, but
1847  // std::numeric_limits<val_type>::min() does not, because it is
1848  // not marked as a __device__ function.
1849  return INT_MIN;
1850  }
1851  static KOKKOS_FORCEINLINE_FUNCTION val_type max () {
1852  return INT_MAX;
1853  }
1854  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const val_type x) {
1855  return x;
1856  }
1857  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const val_type x) {
1858  return 0;
1859  }
1860  static KOKKOS_FORCEINLINE_FUNCTION val_type conj (const val_type x) {
1861  return x;
1862  }
1863  static KOKKOS_FORCEINLINE_FUNCTION val_type
1864  pow (const val_type x, const val_type y) {
1865  return intPowSigned<val_type> (x, y);
1866  }
1867  static KOKKOS_FORCEINLINE_FUNCTION val_type sqrt (const val_type x) {
1868  // This will result in no loss of accuracy, though it might be
1869  // more expensive than it should, if we were clever about using
1870  // bit operations.
1871  return static_cast<val_type> ( ::sqrt (static_cast<double> (abs (x))));
1872  }
1873  static KOKKOS_FORCEINLINE_FUNCTION val_type log (const val_type x) {
1874  return static_cast<val_type> ( ::log (static_cast<double> (abs (x))));
1875  }
1876  static KOKKOS_FORCEINLINE_FUNCTION val_type log10 (const val_type x) {
1877  return static_cast<val_type> ( ::log10 (static_cast<double> (abs (x))));
1878  }
1879  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon () {
1880  return zero ();
1881  }
1882 
1883  // Backwards compatibility with Teuchos::ScalarTraits.
1884  typedef mag_type magnitudeType;
1885  typedef val_type halfPrecision;
1886  typedef val_type doublePrecision;
1887 
1888  static const bool isComplex = false;
1889  static const bool isOrdinal = true;
1890  static const bool isComparable = true;
1891  static const bool hasMachineParameters = false;
1892  static KOKKOS_FORCEINLINE_FUNCTION magnitudeType magnitude (const val_type x) {
1893  return abs (x);
1894  }
1895  static KOKKOS_FORCEINLINE_FUNCTION val_type conjugate (const val_type x) {
1896  return conj (x);
1897  }
1898  static KOKKOS_FORCEINLINE_FUNCTION bool isnaninf (const val_type) {
1899  return false;
1900  }
1901  static std::string name () {
1902  return "int";
1903  }
1904  static KOKKOS_FORCEINLINE_FUNCTION val_type squareroot (const val_type x) {
1905  return sqrt (x);
1906  }
1907 };
1908 
1909 
1910 template<>
1911 class ArithTraits<unsigned int> {
1912 public:
1913  typedef unsigned int val_type;
1914  typedef val_type mag_type;
1915 
1916  static const bool is_specialized = true;
1917  static const bool is_signed = false;
1918  static const bool is_integer = true;
1919  static const bool is_exact = true;
1920  static const bool is_complex = false;
1921 
1922  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const val_type x) {
1923  return false;
1924  }
1925  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const val_type x) {
1926  return false;
1927  }
1928  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const val_type x) {
1929  return x; // it's unsigned, so it's positive
1930  }
1931  static KOKKOS_FORCEINLINE_FUNCTION val_type zero () {
1932  return 0;
1933  }
1934  static KOKKOS_FORCEINLINE_FUNCTION val_type one () {
1935  return 1;
1936  }
1937  static KOKKOS_FORCEINLINE_FUNCTION val_type min () {
1938  return 0;
1939  }
1940  static KOKKOS_FORCEINLINE_FUNCTION val_type max () {
1941  return UINT_MAX;
1942  }
1943  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const val_type x) {
1944  return x;
1945  }
1946  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const val_type x) {
1947  return 0;
1948  }
1949  static KOKKOS_FORCEINLINE_FUNCTION val_type conj (const val_type x) {
1950  return x;
1951  }
1952  static KOKKOS_FORCEINLINE_FUNCTION val_type
1953  pow (const val_type x, const val_type y) {
1954  return intPowUnsigned<val_type> (x, y);
1955  }
1956  static KOKKOS_FORCEINLINE_FUNCTION val_type sqrt (const val_type x) {
1957  // This will result in no loss of accuracy, though it might be
1958  // more expensive than it should, if we were clever about using
1959  // bit operations.
1960  return static_cast<val_type> ( ::sqrt (static_cast<double> (x)));
1961  }
1962  static KOKKOS_FORCEINLINE_FUNCTION val_type log (const val_type x) {
1963  return static_cast<val_type> ( ::log (static_cast<double> (x)));
1964  }
1965  static KOKKOS_FORCEINLINE_FUNCTION val_type log10 (const val_type x) {
1966  return static_cast<val_type> ( ::log10 (static_cast<double> (x)));
1967  }
1968  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon () {
1969  return zero ();
1970  }
1971 
1972  // Backwards compatibility with Teuchos::ScalarTraits.
1973  typedef mag_type magnitudeType;
1974  typedef val_type halfPrecision;
1975  typedef val_type doublePrecision;
1976 
1977  static const bool isComplex = false;
1978  static const bool isOrdinal = true;
1979  static const bool isComparable = true;
1980  static const bool hasMachineParameters = false;
1981  static KOKKOS_FORCEINLINE_FUNCTION magnitudeType magnitude (const val_type x) {
1982  return abs (x);
1983  }
1984  static KOKKOS_FORCEINLINE_FUNCTION val_type conjugate (const val_type x) {
1985  return conj (x);
1986  }
1987  static KOKKOS_FORCEINLINE_FUNCTION bool isnaninf (const val_type) {
1988  return false;
1989  }
1990  static std::string name () {
1991  return "unsigned int";
1992  }
1993  static KOKKOS_FORCEINLINE_FUNCTION val_type squareroot (const val_type x) {
1994  return sqrt (x);
1995  }
1996 };
1997 
1998 
1999 template<>
2000 class ArithTraits<long> {
2001 public:
2002  typedef long val_type;
2003  typedef val_type mag_type;
2004 
2005  static const bool is_specialized = true;
2006  static const bool is_signed = true;
2007  static const bool is_integer = true;
2008  static const bool is_exact = true;
2009  static const bool is_complex = false;
2010 
2011  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const val_type x) {
2012  return false;
2013  }
2014  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const val_type x) {
2015  return false;
2016  }
2017  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const val_type x) {
2018  return x >= 0 ? x : -x;
2019  }
2020  static KOKKOS_FORCEINLINE_FUNCTION val_type zero () {
2021  return 0;
2022  }
2023  static KOKKOS_FORCEINLINE_FUNCTION val_type one () {
2024  return 1;
2025  }
2026  static KOKKOS_FORCEINLINE_FUNCTION val_type min () {
2027  return LONG_MIN;
2028  }
2029  static KOKKOS_FORCEINLINE_FUNCTION val_type max () {
2030  return LONG_MAX;
2031  }
2032  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const val_type x) {
2033  return x;
2034  }
2035  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const val_type x) {
2036  return 0;
2037  }
2038  static KOKKOS_FORCEINLINE_FUNCTION val_type conj (const val_type x) {
2039  return x;
2040  }
2041  static KOKKOS_FORCEINLINE_FUNCTION val_type
2042  pow (const val_type x, const val_type y) {
2043  return intPowSigned<val_type> (x, y);
2044  }
2045  static KOKKOS_FORCEINLINE_FUNCTION val_type sqrt (const val_type x) {
2046 #ifdef __CUDA_ARCH__
2047  return static_cast<val_type> ( ::sqrt (static_cast<double> (abs (x))));
2048 #else
2049  return static_cast<val_type> ( ::sqrt (static_cast<long double> (abs (x))));
2050 #endif // __CUDA_ARCH__
2051  }
2052  static KOKKOS_FORCEINLINE_FUNCTION val_type log (const val_type x) {
2053  return static_cast<val_type> ( ::log (static_cast<double> (abs (x))));
2054  }
2055  static KOKKOS_FORCEINLINE_FUNCTION val_type log10 (const val_type x) {
2056  return static_cast<val_type> ( ::log10 (static_cast<double> (abs (x))));
2057  }
2058  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon () {
2059  return zero ();
2060  }
2061 
2062  // Backwards compatibility with Teuchos::ScalarTraits.
2063  typedef mag_type magnitudeType;
2064  typedef val_type halfPrecision;
2065  typedef val_type doublePrecision;
2066 
2067  static const bool isComplex = false;
2068  static const bool isOrdinal = true;
2069  static const bool isComparable = true;
2070  static const bool hasMachineParameters = false;
2071  static KOKKOS_FORCEINLINE_FUNCTION magnitudeType magnitude (const val_type x) {
2072  return abs (x);
2073  }
2074  static KOKKOS_FORCEINLINE_FUNCTION val_type conjugate (const val_type x) {
2075  return conj (x);
2076  }
2077  static KOKKOS_FORCEINLINE_FUNCTION bool isnaninf (const val_type) {
2078  return false;
2079  }
2080  static std::string name () {
2081  return "long";
2082  }
2083  static KOKKOS_FORCEINLINE_FUNCTION val_type squareroot (const val_type x) {
2084  return sqrt (x);
2085  }
2086 };
2087 
2088 
2089 template<>
2090 class ArithTraits<unsigned long> {
2091 public:
2092  typedef unsigned long val_type;
2093  typedef val_type mag_type;
2094 
2095  static const bool is_specialized = true;
2096  static const bool is_signed = false;
2097  static const bool is_integer = true;
2098  static const bool is_exact = true;
2099  static const bool is_complex = false;
2100 
2101  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const val_type x) {
2102  return false;
2103  }
2104  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const val_type x) {
2105  return false;
2106  }
2107  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const val_type x) {
2108  return x;
2109  }
2110  static KOKKOS_FORCEINLINE_FUNCTION val_type zero () {
2111  return 0;
2112  }
2113  static KOKKOS_FORCEINLINE_FUNCTION val_type one () {
2114  return 1;
2115  }
2116  static KOKKOS_FORCEINLINE_FUNCTION val_type min () {
2117  return 0;
2118  }
2119  static KOKKOS_FORCEINLINE_FUNCTION val_type max () {
2120  return ULONG_MAX;
2121  }
2122  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const val_type x) {
2123  return x;
2124  }
2125  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const val_type x) {
2126  return 0;
2127  }
2128  static KOKKOS_FORCEINLINE_FUNCTION val_type conj (const val_type x) {
2129  return x;
2130  }
2131  static KOKKOS_FORCEINLINE_FUNCTION val_type pow (const val_type x, const val_type y) {
2132  return intPowUnsigned<val_type> (x, y);
2133  }
2134  static KOKKOS_FORCEINLINE_FUNCTION val_type sqrt (const val_type x) {
2135 #ifdef __CUDA_ARCH__
2136  return static_cast<val_type> ( ::sqrt (static_cast<double> (x)));
2137 #else
2138  return static_cast<val_type> ( ::sqrt (static_cast<long double> (x)));
2139 #endif // __CUDA_ARCH__
2140  }
2141  static KOKKOS_FORCEINLINE_FUNCTION val_type log (const val_type x) {
2142  return static_cast<long> ( ::log (static_cast<double> (x)));
2143  }
2144  static KOKKOS_FORCEINLINE_FUNCTION val_type log10 (const val_type x) {
2145  return static_cast<long> ( ::log10 (static_cast<double> (x)));
2146  }
2147  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon () {
2148  return zero ();
2149  }
2150 
2151  // Backwards compatibility with Teuchos::ScalarTraits.
2152  typedef mag_type magnitudeType;
2153  typedef val_type halfPrecision;
2154  typedef val_type doublePrecision;
2155 
2156  static const bool isComplex = false;
2157  static const bool isOrdinal = true;
2158  static const bool isComparable = true;
2159  static const bool hasMachineParameters = false;
2160  static KOKKOS_FORCEINLINE_FUNCTION magnitudeType magnitude (const val_type x) {
2161  return abs (x);
2162  }
2163  static KOKKOS_FORCEINLINE_FUNCTION val_type conjugate (const val_type x) {
2164  return conj (x);
2165  }
2166  static KOKKOS_FORCEINLINE_FUNCTION bool isnaninf (const val_type) {
2167  return false;
2168  }
2169  static std::string name () {
2170  return "unsigned long";
2171  }
2172  static KOKKOS_FORCEINLINE_FUNCTION val_type squareroot (const val_type x) {
2173  return sqrt (x);
2174  }
2175 };
2176 
2177 
2178 template<>
2179 class ArithTraits<long long> {
2180 public:
2181  typedef long long val_type;
2182  typedef val_type mag_type;
2183 
2184  static const bool is_specialized = true;
2185  static const bool is_signed = true;
2186  static const bool is_integer = true;
2187  static const bool is_exact = true;
2188  static const bool is_complex = false;
2189 
2190  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const val_type x) {
2191  return false;
2192  }
2193  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const val_type x) {
2194  return false;
2195  }
2196  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const val_type x) {
2197  return x >= 0 ? x : -x;
2198  }
2199  static KOKKOS_FORCEINLINE_FUNCTION val_type zero () {
2200  return 0;
2201  }
2202  static KOKKOS_FORCEINLINE_FUNCTION val_type one () {
2203  return 1;
2204  }
2205  static KOKKOS_FORCEINLINE_FUNCTION val_type min () {
2206  return LLONG_MIN;
2207  }
2208  static KOKKOS_FORCEINLINE_FUNCTION val_type max () {
2209  return LLONG_MAX;
2210  }
2211  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const val_type x) {
2212  return x;
2213  }
2214  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const val_type x) {
2215  return 0;
2216  }
2217  static KOKKOS_FORCEINLINE_FUNCTION val_type conj (const val_type x) {
2218  return x;
2219  }
2220  static KOKKOS_FORCEINLINE_FUNCTION val_type
2221  pow (const val_type x, const val_type y) {
2222  return intPowSigned<val_type> (x, y);
2223  }
2224  static KOKKOS_FORCEINLINE_FUNCTION val_type sqrt (const val_type x) {
2225 #ifdef __CUDA_ARCH__
2226  // Casting from a 64-bit integer type to double does result in a
2227  // loss of accuracy. However, it gives us a good first
2228  // approximation. For very large numbers, we may lose some
2229  // significand bits, but will always get within a factor of two
2230  // (assuming correct rounding) of the exact double-precision
2231  // number. We could then binary search between half the result
2232  // and twice the result (assuming the latter is <= INT64_MAX,
2233  // which it has to be, so we don't have to check) to ensure
2234  // correctness. It actually should suffice to check numbers
2235  // within 1 of the result.
2236  return static_cast<val_type> ( ::sqrt (static_cast<double> (abs (x))));
2237 #else
2238  // IEEE 754 promises that long double has at least 64 significand
2239  // bits, so we can use it to represent any signed or unsigned
2240  // 64-bit integer type exactly. However, CUDA does not implement
2241  // long double for device functions.
2242  return static_cast<val_type> ( ::sqrt (static_cast<long double> (abs (x))));
2243 #endif // __CUDA_ARCH__
2244  }
2245  static KOKKOS_FORCEINLINE_FUNCTION val_type log (const val_type x) {
2246  return static_cast<val_type> ( ::log (static_cast<double> (abs (x))));
2247  }
2248  static KOKKOS_FORCEINLINE_FUNCTION val_type log10 (const val_type x) {
2249  return static_cast<val_type> ( ::log10 (static_cast<double> (abs (x))));
2250  }
2251  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon () {
2252  return zero ();
2253  }
2254 
2255  // Backwards compatibility with Teuchos::ScalarTraits.
2256  typedef mag_type magnitudeType;
2257  typedef val_type halfPrecision;
2258  typedef val_type doublePrecision;
2259 
2260  static const bool isComplex = false;
2261  static const bool isOrdinal = true;
2262  static const bool isComparable = true;
2263  static const bool hasMachineParameters = false;
2264  static KOKKOS_FORCEINLINE_FUNCTION magnitudeType magnitude (const val_type x) {
2265  return abs (x);
2266  }
2267  static KOKKOS_FORCEINLINE_FUNCTION val_type conjugate (const val_type x) {
2268  return conj (x);
2269  }
2270  static KOKKOS_FORCEINLINE_FUNCTION bool isnaninf (const val_type) {
2271  return false;
2272  }
2273  static std::string name () {
2274  return "long long";
2275  }
2276  static KOKKOS_FORCEINLINE_FUNCTION val_type squareroot (const val_type x) {
2277  return sqrt (x);
2278  }
2279 };
2280 
2281 
2282 template<>
2283 class ArithTraits<unsigned long long> {
2284 public:
2285  typedef unsigned long long val_type;
2286  typedef val_type mag_type;
2287 
2288  static const bool is_specialized = true;
2289  static const bool is_signed = false;
2290  static const bool is_integer = true;
2291  static const bool is_exact = true;
2292  static const bool is_complex = false;
2293 
2294  static KOKKOS_FORCEINLINE_FUNCTION bool isInf (const val_type x) {
2295  return false;
2296  }
2297  static KOKKOS_FORCEINLINE_FUNCTION bool isNan (const val_type x) {
2298  return false;
2299  }
2300  static KOKKOS_FORCEINLINE_FUNCTION mag_type abs (const val_type x) {
2301  return x; // unsigned integers are always nonnegative
2302  }
2303  static KOKKOS_FORCEINLINE_FUNCTION val_type zero () {
2304  return 0;
2305  }
2306  static KOKKOS_FORCEINLINE_FUNCTION val_type one () {
2307  return 1;
2308  }
2309  static KOKKOS_FORCEINLINE_FUNCTION val_type min () {
2310  return 0;
2311  }
2312  static KOKKOS_FORCEINLINE_FUNCTION val_type max () {
2313  return ULLONG_MAX ;
2314  }
2315  static KOKKOS_FORCEINLINE_FUNCTION mag_type real (const val_type x) {
2316  return x;
2317  }
2318  static KOKKOS_FORCEINLINE_FUNCTION mag_type imag (const val_type x) {
2319  return 0;
2320  }
2321  static KOKKOS_FORCEINLINE_FUNCTION val_type conj (const val_type x) {
2322  return x;
2323  }
2324  static KOKKOS_FORCEINLINE_FUNCTION val_type
2325  pow (const val_type x, const val_type y) {
2326  return intPowUnsigned<val_type> (x, y);
2327  }
2328  static KOKKOS_FORCEINLINE_FUNCTION val_type sqrt (const val_type x) {
2329 #ifdef __CUDA_ARCH__
2330  return static_cast<val_type> ( ::sqrt (static_cast<double> (x)));
2331 #else
2332  return static_cast<val_type> ( ::sqrt (static_cast<long double> (x)));
2333 #endif // __CUDA_ARCH__
2334  }
2335  static KOKKOS_FORCEINLINE_FUNCTION val_type log (const val_type x) {
2336  return static_cast<val_type> ( ::log (static_cast<double> (x)));
2337  }
2338  static KOKKOS_FORCEINLINE_FUNCTION val_type log10 (const val_type x) {
2339  return static_cast<val_type> ( ::log10 (static_cast<double> (x)));
2340  }
2341  static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon () {
2342  return zero ();
2343  }
2344 
2345  // Backwards compatibility with Teuchos::ScalarTraits.
2346  typedef mag_type magnitudeType;
2347  typedef val_type halfPrecision;
2348  typedef val_type doublePrecision;
2349 
2350  static const bool isComplex = false;
2351  static const bool isOrdinal = true;
2352  static const bool isComparable = true;
2353  static const bool hasMachineParameters = false;
2354  static KOKKOS_FORCEINLINE_FUNCTION magnitudeType magnitude (const val_type x) {
2355  return abs (x);
2356  }
2357  static KOKKOS_FORCEINLINE_FUNCTION val_type conjugate (const val_type x) {
2358  return conj (x);
2359  }
2360  static KOKKOS_FORCEINLINE_FUNCTION bool isnaninf (const val_type) {
2361  return false;
2362  }
2363  static std::string name () {
2364  return "unsigned long long";
2365  }
2366  static KOKKOS_FORCEINLINE_FUNCTION val_type squareroot (const val_type x) {
2367  return sqrt (x);
2368  }
2369 };
2370 
2371 // dd_real and qd_real are floating-point types provided by the QD
2372 // library of David Bailey (LBNL):
2373 //
2374 // http://crd-legacy.lbl.gov/~dhbailey/mpdist/
2375 //
2376 // dd_real uses two doubles (128 bits), and qd_real uses four doubles
2377 // (256 bits).
2378 //
2379 // Kokkos does <i>not</i> currently support these types in device
2380 // functions. It should be possible to use Kokkos' support for
2381 // aggregate types to implement device function support for dd_real
2382 // and qd_real, but we have not done this yet (as of 07 Jan 2014).
2383 // Hence, the class methods of the ArithTraits specializations for
2384 // dd_real and qd_real are not marked as device functions.
2385 #ifdef HAVE_KOKKOS_QD
2386 template<>
2387 struct ScalarTraits<dd_real>
2388 {
2389  typedef dd_real val_type;
2390  typedef dd_real mag_type;
2391 
2392  static const bool is_specialized = true;
2393  static const bool is_signed = true;
2394  static const bool is_integer = false;
2395  static const bool is_exact = false;
2396  static const bool is_complex = false;
2397 
2398  static inline bool isInf (const val_type& x) {
2399  return isinf (x);
2400  }
2401  static inline bool isNan (const val_type& x) {
2402  return isnan (x);
2403  }
2404  static inline mag_type abs (const val_type& x) {
2405  return ::abs (x);
2406  }
2407  static inline val_type zero () {
2408  return val_type (0.0);
2409  }
2410  static inline val_type one () {
2411  return val_type (1.0);
2412  }
2413  static inline val_type min () {
2414  return std::numeric_limits<val_type>::min ();
2415  }
2416  static inline val_type max () {
2417  return std::numeric_limits<val_type>::max ();
2418  }
2419  static inline mag_type real (const val_type& x) {
2420  return x;
2421  }
2422  static inline mag_type imag (const val_type&) {
2423  return zero ();
2424  }
2425  static inline val_type conj (const val_type& x) {
2426  return x;
2427  }
2428  static inline val_type pow (const val_type& x, const val_type& y) {
2429  return ::pow(x,y);
2430  }
2431  static inline val_type sqrt (const val_type& x) {
2432  return ::sqrt (x);
2433  }
2434  static inline val_type log (const val_type& x) {
2435  // dd_real puts its transcendental functions in the global namespace.
2436  return ::log (x);
2437  }
2438  static inline val_type log10 (const val_type& x) {
2439  return ::log10 (x);
2440  }
2441  static inline val_type nan () {
2442  return val_type::_nan;
2443  }
2444  static val_type epsilon () {
2445  return std::numeric_limits<val_type>::epsilon ();
2446  }
2447 
2448  typedef dd_real magnitudeType;
2449  typedef double halfPrecision;
2450  typedef qd_real doublePrecision;
2451 
2452  static const bool isComplex = false;
2453  static const bool isOrdinal = false;
2454  static const bool isComparable = true;
2455  static const bool hasMachineParameters = true;
2456 
2457  static mag_type eps () {
2458  return epsilon ();
2459  }
2460  static mag_type sfmin () {
2461  return min ();
2462  }
2463  static int base () {
2464  return std::numeric_limits<val_type>::radix;
2465  }
2466  static mag_type prec () {
2467  return eps () * base ();
2468  }
2469  static int t () {
2470  return std::numeric_limits<val_type>::digits;
2471  }
2472  static mag_type rnd () {
2473  return std::numeric_limits<val_type>::round_style == std::round_to_nearest ?
2474  one () :
2475  zero ();
2476  }
2477  static int emin () {
2478  return std::numeric_limits<val_type>::min_exponent;
2479  }
2480  static mag_type rmin () {
2481  return std::numeric_limits<val_type>::min ();
2482  }
2483  static int emax () {
2484  return std::numeric_limits<val_type>::max_exponent;
2485  }
2486  static mag_type rmax () {
2487  return std::numeric_limits<val_type>::max ();
2488  }
2489  static mag_type magnitude (const val_type& x) {
2490  return ::abs (x);
2491  }
2492  static val_type conjugate (const val_type& x) {
2493  return conj (x);
2494  }
2495  static bool isnaninf (const val_type& x) {
2496  return isNan (x) || isInf (x);
2497  }
2498  static std::string name () { return "dd_real"; }
2499  static val_type squareroot (const val_type& x) {
2500  return ::sqrt (x);
2501  }
2502 };
2503 
2504 
2505 template<>
2506 struct ScalarTraits<qd_real>
2507 {
2508  typedef qd_real val_type;
2509  typedef qd_real mag_type;
2510 
2511  static const bool is_specialized = true;
2512  static const bool is_signed = true;
2513  static const bool is_integer = false;
2514  static const bool is_exact = false;
2515  static const bool is_complex = false;
2516 
2517  static inline bool isInf (const val_type& x) {
2518  return isinf (x);
2519  }
2520  static inline bool isNan (const val_type& x) {
2521  return isnan (x);
2522  }
2523  static inline mag_type abs (const val_type& x) {
2524  return ::abs (x);
2525  }
2526  static inline val_type zero () {
2527  return val_type (0.0);
2528  }
2529  static inline val_type one () {
2530  return val_type (1.0);
2531  }
2532  static inline val_type min () {
2533  return std::numeric_limits<val_type>::min ();
2534  }
2535  static inline val_type max () {
2536  return std::numeric_limits<val_type>::max ();
2537  }
2538  static inline mag_type real (const val_type& x) {
2539  return x;
2540  }
2541  static inline mag_type imag (const val_type&) {
2542  return zero ();
2543  }
2544  static inline val_type conj (const val_type& x) {
2545  return x;
2546  }
2547  static inline val_type pow (const val_type& x, const val_type& y) {
2548  return ::pow (x, y);
2549  }
2550  static inline val_type sqrt (const val_type& x) {
2551  return ::sqrt (x);
2552  }
2553  static inline val_type log (const val_type& x) {
2554  // val_type puts its transcendental functions in the global namespace.
2555  return ::log (x);
2556  }
2557  static inline val_type log10 (const val_type& x) {
2558  return ::log10 (x);
2559  }
2560  static inline val_type nan () {
2561  return val_type::_nan;
2562  }
2563  static inline val_type epsilon () {
2564  return std::numeric_limits<val_type>::epsilon ();
2565  }
2566 
2567  typedef qd_real magnitudeType;
2568  typedef dd_real halfPrecision;
2569  // The QD library does not have an "oct-double real" class. One
2570  // could use an arbitrary-precision library like MPFR or ARPREC,
2571  // with the precision set appropriately, to get an
2572  // extended-precision type for qd_real.
2573  typedef qd_real doublePrecision;
2574 
2575  static const bool isComplex = false;
2576  static const bool isOrdinal = false;
2577  static const bool isComparable = true;
2578  static const bool hasMachineParameters = true;
2579 
2580  static mag_type eps () {
2581  return epsilon ();
2582  }
2583  static mag_type sfmin () {
2584  return min ();
2585  }
2586  static int base () {
2587  return std::numeric_limits<val_type>::radix;
2588  }
2589  static mag_type prec () {
2590  return eps () * base ();
2591  }
2592  static int t () {
2593  return std::numeric_limits<val_type>::digits;
2594  }
2595  static mag_type rnd () {
2596  return std::numeric_limits<val_type>::round_style == std::round_to_nearest ?
2597  one () :
2598  zero ();
2599  }
2600  static int emin () {
2601  return std::numeric_limits<val_type>::min_exponent;
2602  }
2603  static mag_type rmin () {
2604  return std::numeric_limits<val_type>::min ();
2605  }
2606  static int emax () {
2607  return std::numeric_limits<val_type>::max_exponent;
2608  }
2609  static mag_type rmax () {
2610  return std::numeric_limits<val_type>::max ();
2611  }
2612  static mag_type magnitude (const val_type& x) {
2613  return ::abs (x);
2614  }
2615  static val_type conjugate (const val_type& x) {
2616  return conj (x);
2617  }
2618  static bool isnaninf (const val_type& x) {
2619  return isNan (x) || isInf (x);
2620  }
2621  static std::string name () { return "qd_real"; }
2622  static val_type squareroot (const val_type& x) {
2623  return ::sqrt (x);
2624  }
2625 };
2626 #endif // HAVE_KOKKOS_QD
2627 
2628 } // namespace Details
2629 } // namespace Kokkos
2630 
2631 #endif // KOKKOS_ARITHTRAITS_HPP
static const bool is_integer
Whether T is an integer type.
T val_type
A type that acts like T and works with Kokkos.
static KOKKOS_FORCEINLINE_FUNCTION mag_type epsilon()
Machine epsilon.
static KOKKOS_FORCEINLINE_FUNCTION T sqrt(const T &x)
The square root of x.
static KOKKOS_FORCEINLINE_FUNCTION T nan()
Return a silent NaN, if appropriate for T.
static KOKKOS_FORCEINLINE_FUNCTION mag_type abs(const T &x)
The absolute value (magnitude) of x.
static KOKKOS_FORCEINLINE_FUNCTION T conj(const T &)
The complex conjugate of x.
static KOKKOS_FORCEINLINE_FUNCTION mag_type rmax()
Overflow theshold: (base^emax)*(1-eps)
static KOKKOS_FORCEINLINE_FUNCTION T one()
The one value of T; the multiplicative identity.
static KOKKOS_FORCEINLINE_FUNCTION T squareroot(const T &x)
Same as sqrt(x); the square root of x.
Partial reimplementation of std::complex that works as the result of a Kokkos::parallel_reduce.
static KOKKOS_FORCEINLINE_FUNCTION mag_type real(const T &x)
The real part of x.
static KOKKOS_FORCEINLINE_FUNCTION mag_type rnd()
1.0 when rounding occurs in addition, else 0.0.
static KOKKOS_FORCEINLINE_FUNCTION int base()
Return the base of the scalar type T.
static KOKKOS_FORCEINLINE_FUNCTION int emax()
Returns the largest exponent before overflow.
static KOKKOS_FORCEINLINE_FUNCTION T pow(const T &x, const T &y)
x raised to the power y.
KOKKOS_INLINE_FUNCTION RealType abs(const complex< RealType > &x)
Absolute value (magnitude) of a complex number.
static const bool hasMachineParameters
True if this type T has floating-point parameters.
static KOKKOS_FORCEINLINE_FUNCTION T zero()
The zero value of T; the arithmetic identity.
static KOKKOS_FORCEINLINE_FUNCTION T max()
The maximum possible value of T.
static std::string name()
The string name of T.
static const bool is_complex
Whether T is a complex-valued type.
static KOKKOS_FORCEINLINE_FUNCTION int emin()
Returns the minimum exponent before (gradual) underflow.
static KOKKOS_FORCEINLINE_FUNCTION bool isnaninf(const T &x)
Whether x is (silent) NaN or Inf.
KOKKOS_INLINE_FUNCTION RealType real(const complex< RealType > &x)
Real part of a complex number.
T doublePrecision
The type with "twice the the precision" of T.
static const bool is_specialized
Whether ArithTraits has a specialization for T.
static KOKKOS_FORCEINLINE_FUNCTION int t()
Returns the number of (base) digits in the significand.
static KOKKOS_FORCEINLINE_FUNCTION bool isInf(const T &x)
Whether x is Inf.
static KOKKOS_FORCEINLINE_FUNCTION bool isNan(const T &x)
Whether x is NaN (not a number).
static KOKKOS_FORCEINLINE_FUNCTION T log(const T &x)
The natural (base e) logarithm of x.
static KOKKOS_FORCEINLINE_FUNCTION mag_type prec()
Return eps*base.
static KOKKOS_FORCEINLINE_FUNCTION mag_type sfmin()
Return safe minimum (sfmin), such that 1/sfmin does not overflow.
KOKKOS_INLINE_FUNCTION complex< RealType > conj(const complex< RealType > &x)
Conjugate of a complex number.
static const bool is_signed
Whether T is a signed type (has negative values).
static KOKKOS_FORCEINLINE_FUNCTION T conjugate(const T &x)
Same as conj(); return the complex conjugate of x.
T halfPrecision
The type with "half the precision" of T.
static KOKKOS_FORCEINLINE_FUNCTION mag_type rmin()
Returns the underflow threshold: base^(emin-1)
static const bool is_exact
Whether T "uses exact representations.".
static KOKKOS_FORCEINLINE_FUNCTION T min()
The minimum possible value of T.
static KOKKOS_FORCEINLINE_FUNCTION T log10(const T &x)
The base ten logarithm of the input.
T mag_type
The type of the magnitude (absolute value) of T.
static KOKKOS_FORCEINLINE_FUNCTION mag_type imag(const T &)
The imaginary part of x.
static KOKKOS_FORCEINLINE_FUNCTION magnitudeType magnitude(const T &x)
Same as abs(); return the magnitude of x.
Traits class for arithmetic on type T.
static KOKKOS_FORCEINLINE_FUNCTION mag_type eps()
Return relative machine precision.
T magnitudeType
Same as mag_type; the type of the absolute value (magnitude) of T.
KOKKOS_INLINE_FUNCTION RealType imag(const complex< RealType > &x)
Imaginary part of a complex number.