CUB
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups
util_type.cuh
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright (c) 2011, Duane Merrill. All rights reserved.
3  * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the NVIDIA CORPORATION nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  ******************************************************************************/
28 
34 #pragma once
35 
36 #include <iostream>
37 #include <limits>
38 
39 #include "util_macro.cuh"
40 #include "util_arch.cuh"
41 #include "util_namespace.cuh"
42 
44 CUB_NS_PREFIX
45 
47 namespace cub {
48 
49 
57 /******************************************************************************
58  * Type equality
59  ******************************************************************************/
60 
64 template <bool IF, typename ThenType, typename ElseType>
65 struct If
66 {
68  typedef ThenType Type; // true
69 };
70 
71 #ifndef DOXYGEN_SHOULD_SKIP_THIS // Do not document
72 
73 template <typename ThenType, typename ElseType>
74 struct If<false, ThenType, ElseType>
75 {
76  typedef ElseType Type; // false
77 };
78 
79 #endif // DOXYGEN_SHOULD_SKIP_THIS
80 
81 
82 
83 /******************************************************************************
84  * Conditional types
85  ******************************************************************************/
86 
90 template <typename A, typename B>
91 struct Equals
92 {
93  enum {
94  VALUE = 0,
95  NEGATE = 1
96  };
97 };
98 
99 #ifndef DOXYGEN_SHOULD_SKIP_THIS // Do not document
100 
101 template <typename A>
102 struct Equals <A, A>
103 {
104  enum {
105  VALUE = 1,
106  NEGATE = 0
107  };
108 };
109 
110 #endif // DOXYGEN_SHOULD_SKIP_THIS
111 
112 
113 /******************************************************************************
114  * Marker types
115  ******************************************************************************/
116 
120 struct NullType
121 {
122 #ifndef DOXYGEN_SHOULD_SKIP_THIS // Do not document
123 
124  template <typename T>
125  __host__ __device__ __forceinline__ NullType& operator =(const T& b) { return *this; }
126 
127  __host__ __device__ __forceinline__ bool operator ==(const NullType& b) { return true; }
128 
129  __host__ __device__ __forceinline__ bool operator !=(const NullType& b) { return false; }
130 
131 #endif // DOXYGEN_SHOULD_SKIP_THIS
132 };
133 
134 
138 template <int A>
139 struct Int2Type
140 {
141  enum {VALUE = A};
142 };
143 
144 
145 #ifndef DOXYGEN_SHOULD_SKIP_THIS // Do not document
146 
147 
148 /******************************************************************************
149  * Size and alignment
150  ******************************************************************************/
151 
153 template <typename T>
154 struct AlignBytes
155 {
156  struct Pad
157  {
158  T val;
159  char byte;
160  };
161 
162  enum
163  {
165  ALIGN_BYTES = sizeof(Pad) - sizeof(T)
166  };
167 };
168 
169 // Specializations where host C++ compilers (e.g., Windows) may disagree with device C++ compilers (EDG)
170 
171 template <> struct AlignBytes<short4> { enum { ALIGN_BYTES = 8 }; };
172 template <> struct AlignBytes<ushort4> { enum { ALIGN_BYTES = 8 }; };
173 template <> struct AlignBytes<int2> { enum { ALIGN_BYTES = 8 }; };
174 template <> struct AlignBytes<uint2> { enum { ALIGN_BYTES = 8 }; };
175 #ifdef _WIN32
176  template <> struct AlignBytes<long2> { enum { ALIGN_BYTES = 8 }; };
177  template <> struct AlignBytes<ulong2> { enum { ALIGN_BYTES = 8 }; };
178 #endif
179 template <> struct AlignBytes<long long> { enum { ALIGN_BYTES = 8 }; };
180 template <> struct AlignBytes<unsigned long long> { enum { ALIGN_BYTES = 8 }; };
181 template <> struct AlignBytes<float2> { enum { ALIGN_BYTES = 8 }; };
182 template <> struct AlignBytes<double> { enum { ALIGN_BYTES = 8 }; };
183 
184 template <> struct AlignBytes<int4> { enum { ALIGN_BYTES = 16 }; };
185 template <> struct AlignBytes<uint4> { enum { ALIGN_BYTES = 16 }; };
186 template <> struct AlignBytes<float4> { enum { ALIGN_BYTES = 16 }; };
187 #ifndef _WIN32
188  template <> struct AlignBytes<long2> { enum { ALIGN_BYTES = 16 }; };
189  template <> struct AlignBytes<ulong2> { enum { ALIGN_BYTES = 16 }; };
190 #endif
191 template <> struct AlignBytes<long4> { enum { ALIGN_BYTES = 16 }; };
192 template <> struct AlignBytes<ulong4> { enum { ALIGN_BYTES = 16 }; };
193 template <> struct AlignBytes<longlong2> { enum { ALIGN_BYTES = 16 }; };
194 template <> struct AlignBytes<ulonglong2> { enum { ALIGN_BYTES = 16 }; };
195 template <> struct AlignBytes<double2> { enum { ALIGN_BYTES = 16 }; };
196 template <> struct AlignBytes<longlong4> { enum { ALIGN_BYTES = 16 }; };
197 template <> struct AlignBytes<ulonglong4> { enum { ALIGN_BYTES = 16 }; };
198 template <> struct AlignBytes<double4> { enum { ALIGN_BYTES = 16 }; };
199 
200 
202 template <typename T>
203 struct UnitWord
204 {
205  enum {
206  ALIGN_BYTES = AlignBytes<T>::ALIGN_BYTES
207  };
208 
209  template <typename Unit>
210  struct IsMultiple
211  {
212  enum {
213  UNIT_ALIGN_BYTES = AlignBytes<Unit>::ALIGN_BYTES,
214  IS_MULTIPLE = (sizeof(T) % sizeof(Unit) == 0) && (ALIGN_BYTES % UNIT_ALIGN_BYTES == 0)
215  };
216  };
217 
219  typedef typename If<IsMultiple<int>::IS_MULTIPLE,
220  unsigned int,
221  typename If<IsMultiple<short>::IS_MULTIPLE,
222  unsigned short,
223  unsigned char>::Type>::Type ShuffleWord;
224 
226  typedef typename If<IsMultiple<long long>::IS_MULTIPLE,
227  unsigned long long,
228  ShuffleWord>::Type VolatileWord;
229 
231  typedef typename If<IsMultiple<longlong2>::IS_MULTIPLE,
232  ulonglong2,
233  VolatileWord>::Type DeviceWord;
234 
236  typedef typename If<IsMultiple<int4>::IS_MULTIPLE,
237  uint4,
238  typename If<IsMultiple<int2>::IS_MULTIPLE,
239  uint2,
240  ShuffleWord>::Type>::Type TextureWord;
241 };
242 
243 
244 // float2 specialization workaround (for SM10-SM13)
245 template <>
246 struct UnitWord <float2>
247 {
248  typedef int ShuffleWord;
249 #if (CUB_PTX_ARCH > 0) && (CUB_PTX_ARCH <= 130)
250  typedef float VolatileWord;
251  typedef uint2 DeviceWord;
252 #else
253  typedef unsigned long long VolatileWord;
254  typedef unsigned long long DeviceWord;
255 #endif
256  typedef float2 TextureWord;
257 };
258 
259 // float4 specialization workaround (for SM10-SM13)
260 template <>
261 struct UnitWord <float4>
262 {
263  typedef int ShuffleWord;
264 #if (CUB_PTX_ARCH > 0) && (CUB_PTX_ARCH <= 130)
265  typedef float VolatileWord;
266  typedef uint4 DeviceWord;
267 #else
268  typedef unsigned long long VolatileWord;
269  typedef ulonglong2 DeviceWord;
270 #endif
271  typedef float4 TextureWord;
272 };
273 
274 
275 // char2 specialization workaround (for SM10-SM13)
276 template <>
277 struct UnitWord <char2>
278 {
279  typedef unsigned short ShuffleWord;
280 #if (CUB_PTX_ARCH > 0) && (CUB_PTX_ARCH <= 130)
281  typedef unsigned short VolatileWord;
282  typedef short DeviceWord;
283 #else
284  typedef unsigned short VolatileWord;
285  typedef unsigned short DeviceWord;
286 #endif
287  typedef unsigned short TextureWord;
288 };
289 
290 #endif // DOXYGEN_SHOULD_SKIP_THIS
291 
292 
293 
294 /******************************************************************************
295  * Vector type inference utilities.
296  ******************************************************************************/
297 
301 template <typename T, int vec_elements> struct CubVector;
302 
303 #ifndef DOXYGEN_SHOULD_SKIP_THIS // Do not document
304 
305 enum
306 {
308  MAX_VEC_ELEMENTS = 4,
309 };
310 
311 
315 template <typename T>
316 struct CubVector<T, 1>
317 {
318  T x;
319 
320  typedef T BaseType;
321  typedef CubVector<T, 1> Type;
322 };
323 
327 template <typename T>
328 struct CubVector<T, 2>
329 {
330  T x;
331  T y;
332 
333  typedef T BaseType;
334  typedef CubVector<T, 2> Type;
335 };
336 
340 template <typename T>
341 struct CubVector<T, 3>
342 {
343  T x;
344  T y;
345  T z;
346 
347  typedef T BaseType;
348  typedef CubVector<T, 3> Type;
349 };
350 
354 template <typename T>
355 struct CubVector<T, 4>
356 {
357  T x;
358  T y;
359  T z;
360  T w;
361 
362  typedef T BaseType;
363  typedef CubVector<T, 4> Type;
364 };
365 
366 
370 #define CUB_DEFINE_VECTOR_TYPE(base_type,short_type) \
371  \
372  template<> struct CubVector<base_type, 1> : short_type##1 \
373  { \
374  typedef base_type BaseType; \
375  typedef short_type##1 Type; \
376  __host__ __device__ __forceinline__ CubVector operator+(const CubVector &other) const { \
377  CubVector retval; \
378  retval.x = x + other.x; \
379  return retval; \
380  } \
381  __host__ __device__ __forceinline__ CubVector operator-(const CubVector &other) const { \
382  CubVector retval; \
383  retval.x = x - other.x; \
384  return retval; \
385  } \
386  }; \
387  \
388  template<> struct CubVector<base_type, 2> : short_type##2 \
389  { \
390  typedef base_type BaseType; \
391  typedef short_type##2 Type; \
392  __host__ __device__ __forceinline__ CubVector operator+(const CubVector &other) const { \
393  CubVector retval; \
394  retval.x = x + other.x; \
395  retval.y = y + other.y; \
396  return retval; \
397  } \
398  __host__ __device__ __forceinline__ CubVector operator-(const CubVector &other) const { \
399  CubVector retval; \
400  retval.x = x - other.x; \
401  retval.y = y - other.y; \
402  return retval; \
403  } \
404  }; \
405  \
406  template<> struct CubVector<base_type, 3> : short_type##3 \
407  { \
408  typedef base_type BaseType; \
409  typedef short_type##3 Type; \
410  __host__ __device__ __forceinline__ CubVector operator+(const CubVector &other) const { \
411  CubVector retval; \
412  retval.x = x + other.x; \
413  retval.y = y + other.y; \
414  retval.z = z + other.z; \
415  return retval; \
416  } \
417  __host__ __device__ __forceinline__ CubVector operator-(const CubVector &other) const { \
418  CubVector retval; \
419  retval.x = x - other.x; \
420  retval.y = y - other.y; \
421  retval.z = z - other.z; \
422  return retval; \
423  } \
424  }; \
425  \
426  template<> struct CubVector<base_type, 4> : short_type##4 \
427  { \
428  typedef base_type BaseType; \
429  typedef short_type##4 Type; \
430  __host__ __device__ __forceinline__ CubVector operator+(const CubVector &other) const { \
431  CubVector retval; \
432  retval.x = x + other.x; \
433  retval.y = y + other.y; \
434  retval.z = z + other.z; \
435  retval.w = w + other.w; \
436  return retval; \
437  } \
438  __host__ __device__ __forceinline__ CubVector operator-(const CubVector &other) const { \
439  CubVector retval; \
440  retval.x = x - other.x; \
441  retval.y = y - other.y; \
442  retval.z = z - other.z; \
443  retval.w = w - other.w; \
444  return retval; \
445  } \
446  };
447 
448 
449 
450 // Expand CUDA vector types for built-in primitives
451 CUB_DEFINE_VECTOR_TYPE(char, char)
452 CUB_DEFINE_VECTOR_TYPE(signed char, char)
453 CUB_DEFINE_VECTOR_TYPE(short, short)
454 CUB_DEFINE_VECTOR_TYPE(int, int)
455 CUB_DEFINE_VECTOR_TYPE(long, long)
456 CUB_DEFINE_VECTOR_TYPE(long long, longlong)
457 CUB_DEFINE_VECTOR_TYPE(unsigned char, uchar)
458 CUB_DEFINE_VECTOR_TYPE(unsigned short, ushort)
459 CUB_DEFINE_VECTOR_TYPE(unsigned int, uint)
460 CUB_DEFINE_VECTOR_TYPE(unsigned long, ulong)
461 CUB_DEFINE_VECTOR_TYPE(unsigned long long, ulonglong)
462 CUB_DEFINE_VECTOR_TYPE(float, float)
463 CUB_DEFINE_VECTOR_TYPE(double, double)
464 CUB_DEFINE_VECTOR_TYPE(bool, uchar)
465 
466 // Undefine macros
467 #undef CUB_DEFINE_VECTOR_TYPE
468 
469 #endif // DOXYGEN_SHOULD_SKIP_THIS
470 
471 
472 
473 /******************************************************************************
474  * Wrapper types
475  ******************************************************************************/
476 
480 template <typename T>
482 {
484  typedef typename UnitWord<T>::DeviceWord DeviceWord;
485 
486  enum
487  {
488  WORDS = sizeof(T) / sizeof(DeviceWord)
489  };
490 
493 
495  __host__ __device__ __forceinline__ T& Alias()
496  {
497  return reinterpret_cast<T&>(*this);
498  }
499 };
500 
501 
505 template <typename _T, typename _Offset>
507 {
508  typedef _T T;
509  typedef _Offset Offset;
510 
511 #if (CUB_PTX_ARCH == 0)
512  union
513  {
515  typename UnitWord<T>::DeviceWord align0;
516  };
517 #else
518  Offset offset;
519 #endif
520 
522 
524  __host__ __device__ __forceinline__ bool operator !=(const ItemOffsetPair &b)
525  {
526  return (value != b.value) || (offset != b.offset);
527  }
528 };
529 
530 
534 template <typename _Key, typename _Value>
536 {
537  typedef _Key Key;
538  typedef _Value Value;
539 
542 
544  __host__ __device__ __forceinline__ bool operator !=(const KeyValuePair &b)
545  {
546  return (value != b.value) || (key != b.key);
547  }
548 
549 };
550 
551 #ifndef DOXYGEN_SHOULD_SKIP_THIS // Do not document
552 
553 
557 template <typename T>
558 __host__ __device__ __forceinline__ T ZeroInitialize()
559 {
560 #if (CUB_PTX_ARCH > 0) && (CUB_PTX_ARCH <= 130)
561 
562  typedef typename UnitWord<T>::ShuffleWord ShuffleWord;
563  const int MULTIPLE = sizeof(T) / sizeof(ShuffleWord);
564  ShuffleWord words[MULTIPLE];
565  #pragma unroll
566  for (int i = 0; i < MULTIPLE; ++i)
567  words[i] = 0;
568  return *reinterpret_cast<T*>(words);
569 
570 #else
571 
572  return T();
573 
574 #endif
575 }
576 
577 
581 template <typename T, int COUNT>
582 struct ArrayWrapper
583 {
585  T array[COUNT];
586 };
587 
588 #endif // DOXYGEN_SHOULD_SKIP_THIS
589 
598 template <typename T>
600 {
602  T *d_buffers[2];
603 
605  int selector;
606 
608  __host__ __device__ __forceinline__ DoubleBuffer()
609  {
610  selector = 0;
611  d_buffers[0] = NULL;
612  d_buffers[1] = NULL;
613  }
614 
616  __host__ __device__ __forceinline__ DoubleBuffer(
617  T *d_current,
618  T *d_alternate)
619  {
620  selector = 0;
621  d_buffers[0] = d_current;
622  d_buffers[1] = d_alternate;
623  }
624 
626  __host__ __device__ __forceinline__ T* Current() { return d_buffers[selector]; }
627 };
628 
629 
630 
631 /******************************************************************************
632  * Static math
633  ******************************************************************************/
634 
642 template <int N, int CURRENT_VAL = N, int COUNT = 0>
643 struct Log2
644 {
646  enum { VALUE = Log2<N, (CURRENT_VAL >> 1), COUNT + 1>::VALUE }; // Inductive case
647 };
648 
649 #ifndef DOXYGEN_SHOULD_SKIP_THIS // Do not document
650 template <int N, int COUNT>
651 struct Log2<N, 0, COUNT>
652 {
653  enum {VALUE = (1 << (COUNT - 1) < N) ? // Base case
654  COUNT :
655  COUNT - 1 };
656 };
657 #endif // DOXYGEN_SHOULD_SKIP_THIS
658 
659 
663 template <int N>
665 {
666  enum { VALUE = ((N & (N - 1)) == 0) };
667 };
668 
669 
670 #ifndef DOXYGEN_SHOULD_SKIP_THIS // Do not document
671 
672 
673 /******************************************************************************
674  * Pointer vs. iterator detection
675  ******************************************************************************/
676 
680 template <typename Tp>
681 struct IsPointer
682 {
683  enum { VALUE = 0 };
684 };
685 
686 #ifndef DOXYGEN_SHOULD_SKIP_THIS // Do not document
687 
688 template <typename Tp>
689 struct IsPointer<Tp*>
690 {
691  enum { VALUE = 1 };
692 };
693 
694 #endif // DOXYGEN_SHOULD_SKIP_THIS
695 
696 
697 
698 /******************************************************************************
699  * Qualifier detection
700  ******************************************************************************/
701 
705 template <typename Tp>
706 struct IsVolatile
707 {
708  enum { VALUE = 0 };
709 };
710 
711 #ifndef DOXYGEN_SHOULD_SKIP_THIS // Do not document
712 
713 template <typename Tp>
714 struct IsVolatile<Tp volatile>
715 {
716  enum { VALUE = 1 };
717 };
718 
719 #endif // DOXYGEN_SHOULD_SKIP_THIS
720 
721 
722 /******************************************************************************
723  * Qualifier removal
724  ******************************************************************************/
725 
732 template <typename Tp, typename Up = Tp>
733 struct RemoveQualifiers
734 {
736  typedef Up Type;
737 };
738 
739 #ifndef DOXYGEN_SHOULD_SKIP_THIS // Do not document
740 
741 template <typename Tp, typename Up>
742 struct RemoveQualifiers<Tp, volatile Up>
743 {
744  typedef Up Type;
745 };
746 
747 template <typename Tp, typename Up>
748 struct RemoveQualifiers<Tp, const Up>
749 {
750  typedef Up Type;
751 };
752 
753 template <typename Tp, typename Up>
754 struct RemoveQualifiers<Tp, const volatile Up>
755 {
756  typedef Up Type;
757 };
758 
759 #endif // DOXYGEN_SHOULD_SKIP_THIS
760 
761 
762 
763 /******************************************************************************
764  * Typedef-detection
765  ******************************************************************************/
766 
767 
771 #define CUB_DEFINE_DETECT_NESTED_TYPE(detector_name, nested_type_name) \
772  template <typename T> \
773  struct detector_name \
774  { \
775  template <typename C> \
776  static char& test(typename C::nested_type_name*); \
777  template <typename> \
778  static int& test(...); \
779  enum \
780  { \
781  VALUE = sizeof(test<T>(0)) < sizeof(int) \
782  }; \
783  };
784 
785 
786 
787 /******************************************************************************
788  * Simple enable-if (similar to Boost)
789  ******************************************************************************/
790 
794 template <bool Condition, class T = void>
795 struct EnableIf
796 {
798  typedef T Type;
799 };
800 
801 #ifndef DOXYGEN_SHOULD_SKIP_THIS // Do not document
802 
803 template <class T>
804 struct EnableIf<false, T> {};
805 
806 #endif // DOXYGEN_SHOULD_SKIP_THIS
807 
808 
809 /******************************************************************************
810  * Typedef-detection
811  ******************************************************************************/
812 
816 template <typename T, typename BinaryOp>
817 struct BinaryOpHasIdxParam
818 {
819 private:
820  template <typename BinaryOpT, bool (BinaryOpT::*)(const T &a, const T &b, unsigned int idx) const> struct SFINAE1 {};
821  template <typename BinaryOpT, bool (BinaryOpT::*)(const T &a, const T &b, unsigned int idx)> struct SFINAE2 {};
822  template <typename BinaryOpT, bool (BinaryOpT::*)(T a, T b, unsigned int idx) const> struct SFINAE3 {};
823  template <typename BinaryOpT, bool (BinaryOpT::*)(T a, T b, unsigned int idx)> struct SFINAE4 {};
824 
825  template <typename BinaryOpT, bool (BinaryOpT::*)(const T &a, const T &b, int idx) const> struct SFINAE5 {};
826  template <typename BinaryOpT, bool (BinaryOpT::*)(const T &a, const T &b, int idx)> struct SFINAE6 {};
827  template <typename BinaryOpT, bool (BinaryOpT::*)(T a, T b, int idx) const> struct SFINAE7 {};
828  template <typename BinaryOpT, bool (BinaryOpT::*)(T a, T b, int idx)> struct SFINAE8 {};
829 
830  template <typename BinaryOpT> static char Test(SFINAE1<BinaryOpT, &BinaryOpT::operator()> *);
831  template <typename BinaryOpT> static char Test(SFINAE2<BinaryOpT, &BinaryOpT::operator()> *);
832  template <typename BinaryOpT> static char Test(SFINAE3<BinaryOpT, &BinaryOpT::operator()> *);
833  template <typename BinaryOpT> static char Test(SFINAE4<BinaryOpT, &BinaryOpT::operator()> *);
834 
835  template <typename BinaryOpT> static char Test(SFINAE5<BinaryOpT, &BinaryOpT::operator()> *);
836  template <typename BinaryOpT> static char Test(SFINAE6<BinaryOpT, &BinaryOpT::operator()> *);
837  template <typename BinaryOpT> static char Test(SFINAE7<BinaryOpT, &BinaryOpT::operator()> *);
838  template <typename BinaryOpT> static char Test(SFINAE8<BinaryOpT, &BinaryOpT::operator()> *);
839 
840  template <typename BinaryOpT> static int Test(...);
841 
842 public:
843 
845  static const bool HAS_PARAM = sizeof(Test<BinaryOp>(NULL)) == sizeof(char);
846 };
847 
848 #endif // DOXYGEN_SHOULD_SKIP_THIS
849 
850 /******************************************************************************
851  * Simple type traits utilities.
852  *
853  * For example:
854  * Traits<int>::CATEGORY // SIGNED_INTEGER
855  * Traits<NullType>::NULL_TYPE // true
856  * Traits<uint4>::CATEGORY // NOT_A_NUMBER
857  * Traits<uint4>::PRIMITIVE; // false
858  *
859  ******************************************************************************/
860 
865 {
866  NOT_A_NUMBER,
867  SIGNED_INTEGER,
868  UNSIGNED_INTEGER,
869  FLOATING_POINT
870 };
871 
872 
876 template <Category _CATEGORY, bool _PRIMITIVE, bool _NULL_TYPE, typename _UnsignedBits>
878 {
880  static const Category CATEGORY = _CATEGORY;
881  enum
882  {
883  PRIMITIVE = _PRIMITIVE,
884  NULL_TYPE = _NULL_TYPE,
885  };
886 };
887 
888 #ifndef DOXYGEN_SHOULD_SKIP_THIS // Do not document
889 
893 template <typename _UnsignedBits>
894 struct BaseTraits<UNSIGNED_INTEGER, true, false, _UnsignedBits>
895 {
896  typedef _UnsignedBits UnsignedBits;
897 
898  static const Category CATEGORY = UNSIGNED_INTEGER;
899  static const UnsignedBits MIN_KEY = UnsignedBits(0);
900  static const UnsignedBits MAX_KEY = UnsignedBits(-1);
901 
902  enum
903  {
904  PRIMITIVE = true,
905  NULL_TYPE = false,
906  };
907 
908 
909  static __device__ __forceinline__ UnsignedBits TwiddleIn(UnsignedBits key)
910  {
911  return key;
912  }
913 
914  static __device__ __forceinline__ UnsignedBits TwiddleOut(UnsignedBits key)
915  {
916  return key;
917  }
918 };
919 
920 
924 template <typename _UnsignedBits>
925 struct BaseTraits<SIGNED_INTEGER, true, false, _UnsignedBits>
926 {
927  typedef _UnsignedBits UnsignedBits;
928 
929  static const Category CATEGORY = SIGNED_INTEGER;
930  static const UnsignedBits HIGH_BIT = UnsignedBits(1) << ((sizeof(UnsignedBits) * 8) - 1);
931  static const UnsignedBits MIN_KEY = HIGH_BIT;
932  static const UnsignedBits MAX_KEY = UnsignedBits(-1) ^ HIGH_BIT;
933 
934  enum
935  {
936  PRIMITIVE = true,
937  NULL_TYPE = false,
938  };
939 
940  static __device__ __forceinline__ UnsignedBits TwiddleIn(UnsignedBits key)
941  {
942  return key ^ HIGH_BIT;
943  };
944 
945  static __device__ __forceinline__ UnsignedBits TwiddleOut(UnsignedBits key)
946  {
947  return key ^ HIGH_BIT;
948  };
949 
950 };
951 
952 
956 template <typename _UnsignedBits>
957 struct BaseTraits<FLOATING_POINT, true, false, _UnsignedBits>
958 {
959  typedef _UnsignedBits UnsignedBits;
960 
961  static const Category CATEGORY = FLOATING_POINT;
962  static const UnsignedBits HIGH_BIT = UnsignedBits(1) << ((sizeof(UnsignedBits) * 8) - 1);
963  static const UnsignedBits MIN_KEY = UnsignedBits(-1);
964  static const UnsignedBits MAX_KEY = UnsignedBits(-1) ^ HIGH_BIT;
965 
966  static __device__ __forceinline__ UnsignedBits TwiddleIn(UnsignedBits key)
967  {
968  UnsignedBits mask = (key & HIGH_BIT) ? UnsignedBits(-1) : HIGH_BIT;
969  return key ^ mask;
970  };
971 
972  static __device__ __forceinline__ UnsignedBits TwiddleOut(UnsignedBits key)
973  {
974  UnsignedBits mask = (key & HIGH_BIT) ? HIGH_BIT : UnsignedBits(-1);
975  return key ^ mask;
976  };
977 
978  enum
979  {
980  PRIMITIVE = true,
981  NULL_TYPE = false,
982  };
983 };
984 
985 #endif // DOXYGEN_SHOULD_SKIP_THIS
986 
987 
991 template <typename T> struct NumericTraits : BaseTraits<NOT_A_NUMBER, false, false, T> {};
992 
993 #ifndef DOXYGEN_SHOULD_SKIP_THIS // Do not document
994 
995 template <> struct NumericTraits<NullType> : BaseTraits<NOT_A_NUMBER, false, true, NullType> {};
996 
997 template <> struct NumericTraits<char> : BaseTraits<(std::numeric_limits<char>::is_signed) ? SIGNED_INTEGER : UNSIGNED_INTEGER, true, false, unsigned char> {};
998 template <> struct NumericTraits<signed char> : BaseTraits<SIGNED_INTEGER, true, false, unsigned char> {};
999 template <> struct NumericTraits<short> : BaseTraits<SIGNED_INTEGER, true, false, unsigned short> {};
1000 template <> struct NumericTraits<int> : BaseTraits<SIGNED_INTEGER, true, false, unsigned int> {};
1001 template <> struct NumericTraits<long> : BaseTraits<SIGNED_INTEGER, true, false, unsigned long> {};
1002 template <> struct NumericTraits<long long> : BaseTraits<SIGNED_INTEGER, true, false, unsigned long long> {};
1003 
1004 template <> struct NumericTraits<unsigned char> : BaseTraits<UNSIGNED_INTEGER, true, false, unsigned char> {};
1005 template <> struct NumericTraits<unsigned short> : BaseTraits<UNSIGNED_INTEGER, true, false, unsigned short> {};
1006 template <> struct NumericTraits<unsigned int> : BaseTraits<UNSIGNED_INTEGER, true, false, unsigned int> {};
1007 template <> struct NumericTraits<unsigned long> : BaseTraits<UNSIGNED_INTEGER, true, false, unsigned long> {};
1008 template <> struct NumericTraits<unsigned long long> : BaseTraits<UNSIGNED_INTEGER, true, false, unsigned long long> {};
1009 
1010 template <> struct NumericTraits<float> : BaseTraits<FLOATING_POINT, true, false, unsigned int> {};
1011 template <> struct NumericTraits<double> : BaseTraits<FLOATING_POINT, true, false, unsigned long long> {};
1012 
1013 #endif // DOXYGEN_SHOULD_SKIP_THIS
1014 
1015 
1019 template <typename T>
1020 struct Traits : NumericTraits<typename RemoveQualifiers<T>::Type> {};
1021 
1022 
1023  // end group UtilModule
1025 
1026 } // CUB namespace
1027 CUB_NS_POSTFIX // Optional outer namespace(s)