44 #ifndef TPETRA_DETAILS_FIXEDHASHTABLE_DEF_HPP
45 #define TPETRA_DETAILS_FIXEDHASHTABLE_DEF_HPP
47 #include "Tpetra_Details_FixedHashTable_decl.hpp"
49 #ifdef TPETRA_USE_MURMUR_HASH
50 # include "Kokkos_Functional.hpp"
51 #endif // TPETRA_USE_MURMUR_HASH
52 #include "Kokkos_ArithTraits.hpp"
53 #include "Teuchos_TypeNameTraits.hpp"
54 #include <type_traits>
77 template<
class ExecSpace>
78 bool worthBuildingFixedHashTableInParallel () {
79 return ExecSpace::concurrency() > 1;
90 template<
class KeyType,
93 class OutputExecSpace,
94 const bool mustDeepCopy =
95 ! std::is_same<
typename InputExecSpace::memory_space,
96 typename OutputExecSpace::memory_space>::value>
97 struct DeepCopyIfNeeded {
103 template<
class KeyType,
105 class InputExecSpace,
106 class OutputExecSpace>
107 struct DeepCopyIfNeeded<KeyType, ArrayLayout, InputExecSpace, OutputExecSpace, true>
109 typedef Kokkos::View<
const KeyType*, ArrayLayout,
110 InputExecSpace, Kokkos::MemoryUnmanaged> input_view_type;
116 typedef Kokkos::View<const KeyType*, ArrayLayout, OutputExecSpace> output_view_type;
118 static output_view_type copy (
const input_view_type& src) {
119 typedef typename output_view_type::non_const_type NC;
121 NC dst (Kokkos::ViewAllocateWithoutInitializing (src.tracker ().label ()),
124 return output_view_type (dst);
129 template<
class KeyType,
131 class InputExecSpace,
132 class OutputExecSpace>
133 struct DeepCopyIfNeeded<KeyType, ArrayLayout, InputExecSpace, OutputExecSpace, false> {
134 typedef Kokkos::View<
const KeyType*, ArrayLayout,
135 InputExecSpace, Kokkos::MemoryUnmanaged> input_view_type;
136 typedef Kokkos::View<
const KeyType*, ArrayLayout, OutputExecSpace,
137 Kokkos::MemoryUnmanaged> output_view_type;
139 static output_view_type copy (
const input_view_type& src) {
140 return output_view_type (src);
162 template<
class CountsViewType,
164 class SizeType =
typename KeysViewType::size_type>
167 typedef CountsViewType counts_view_type;
168 typedef KeysViewType keys_view_type;
169 typedef typename CountsViewType::execution_space execution_space;
170 typedef typename CountsViewType::memory_space memory_space;
171 typedef SizeType size_type;
172 typedef typename keys_view_type::non_const_value_type key_type;
188 const keys_view_type& keys,
189 const size_type size) :
199 KOKKOS_INLINE_FUNCTION
void
205 Kokkos::atomic_increment (&counts_[hashVal]);
210 counts_view_type counts_;
212 keys_view_type keys_;
227 template<
class KeyType>
229 KOKKOS_INLINE_FUNCTION
231 minKey_ (::Kokkos::Details::ArithTraits<KeyType>::max ()),
244 maxKey_ (::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
245 ::Kokkos::Details::ArithTraits<KeyType>::min () :
246 -::Kokkos::Details::ArithTraits<KeyType>::max ()),
249 static_assert (std::is_arithmetic<KeyType>::value,
"FillPairsResult: "
250 "KeyType must be some kind of number type.");
253 KOKKOS_INLINE_FUNCTION
255 const KeyType& initMaxKey) :
260 static_assert (std::is_arithmetic<KeyType>::value,
"FillPairsResult: "
261 "KeyType must be some kind of number type.");
298 template<
class PairsViewType,
300 class CountsViewType,
301 class SizeType =
typename KeysViewType::size_type>
304 typedef typename CountsViewType::non_const_type counts_view_type;
305 typedef typename counts_view_type::const_type offsets_view_type;
307 typedef PairsViewType pairs_view_type;
308 typedef typename KeysViewType::const_type keys_view_type;
309 typedef typename offsets_view_type::execution_space execution_space;
310 typedef typename offsets_view_type::memory_space memory_space;
311 typedef SizeType size_type;
313 typedef typename keys_view_type::non_const_value_type key_type;
314 typedef typename pairs_view_type::non_const_value_type pair_type;
338 const counts_view_type& counts,
339 const offsets_view_type& ptr,
340 const keys_view_type& keys,
341 const typename pair_type::second_type startingValue) :
346 size_ (counts.extent (0)),
347 startingValue_ (startingValue),
348 initMinKey_ (::Kokkos::
Details::ArithTraits<key_type>::max ()),
349 initMaxKey_ (::Kokkos::
Details::ArithTraits<key_type>::is_integer ?
350 ::Kokkos::
Details::ArithTraits<key_type>::min () :
351 -::Kokkos::
Details::ArithTraits<key_type>::max ())
373 const counts_view_type& counts,
374 const offsets_view_type& ptr,
375 const keys_view_type& keys,
376 const typename pair_type::second_type startingValue,
377 const key_type initMinKey,
378 const key_type initMaxKey) :
383 size_ (counts.extent (0)),
384 startingValue_ (startingValue),
385 initMinKey_ (initMinKey),
386 initMaxKey_ (initMaxKey)
397 KOKKOS_INLINE_FUNCTION
void
398 join (
volatile value_type& dst,
399 const volatile value_type& src)
const
401 if (src.maxKey_ > dst.maxKey_) {
402 dst.maxKey_ = src.maxKey_;
404 if (src.minKey_ < dst.minKey_) {
405 dst.minKey_ = src.minKey_;
407 dst.success_ = dst.success_ && src.success_;
414 KOKKOS_INLINE_FUNCTION
void
418 typedef typename offsets_view_type::non_const_value_type offset_type;
419 typedef typename pair_type::second_type val_type;
420 typedef typename std::remove_reference< decltype( counts_[0] ) >::type atomic_incr_type;
422 const key_type key = keys_[i];
429 const val_type theVal = startingValue_ + static_cast<val_type> (i);
433 const offset_type count = Kokkos::atomic_fetch_add (&counts_[hashVal], atomic_incr_type(-1));
438 const offset_type curPos = ptr_[hashVal+1] - count;
440 pairs_[curPos].first = key;
441 pairs_[curPos].second = theVal;
446 pairs_view_type pairs_;
447 counts_view_type counts_;
448 offsets_view_type ptr_;
449 keys_view_type keys_;
451 typename pair_type::second_type startingValue_;
453 key_type initMinKey_;
455 key_type initMaxKey_;
481 template<
class OffsetsViewType,
483 class SizeType =
typename OffsetsViewType::size_type>
486 typedef typename OffsetsViewType::const_type offsets_view_type;
487 typedef typename PairsViewType::const_type pairs_view_type;
488 typedef typename offsets_view_type::execution_space execution_space;
489 typedef typename offsets_view_type::memory_space memory_space;
490 typedef SizeType size_type;
493 typedef int value_type;
500 const offsets_view_type& ptr) :
503 size_ (ptr_.extent (0) == 0 ?
509 KOKKOS_INLINE_FUNCTION
void init (value_type& dst)
const
515 KOKKOS_INLINE_FUNCTION
void
516 join (
volatile value_type& dst,
517 const volatile value_type& src)
const
519 dst = dst + src > 0?1:0;
523 KOKKOS_INLINE_FUNCTION
void
526 typedef typename offsets_view_type::non_const_value_type offset_type;
527 typedef typename pairs_view_type::non_const_value_type pair_type;
528 typedef typename pair_type::first_type key_type;
534 const offset_type beg = ptr_[i];
535 const offset_type end = ptr_[i+1];
536 bool foundDuplicateKey =
false;
541 for (offset_type j = beg + 1; j < end; ++j) {
542 const key_type curKey = pairs_[j].first;
543 for (offset_type k = beg; k < j; ++k) {
544 if (pairs_[k].first == curKey) {
545 foundDuplicateKey =
true;
550 dst = (dst>0) || foundDuplicateKey?1:0;
555 pairs_view_type pairs_;
556 offsets_view_type ptr_;
566 template<
class KeyType,
class ValueType,
class DeviceType>
576 return keys_.extent (0) == val_.extent (0);
579 template<
class KeyType,
class ValueType,
class DeviceType>
588 template<
class KeyType,
class ValueType,
class DeviceType>
591 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
592 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
593 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
594 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
595 minVal_ (::Kokkos::
Details::ArithTraits<ValueType>::max ()),
596 maxVal_ (::Kokkos::
Details::ArithTraits<ValueType>::is_integer ?
597 ::Kokkos::
Details::ArithTraits<ValueType>::min () :
598 -::Kokkos::
Details::ArithTraits<ValueType>::max ()),
599 firstContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
600 lastContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
601 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
602 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
603 contiguousValues_ (true),
604 checkedForDuplicateKeys_ (true),
605 hasDuplicateKeys_ (false)
607 #ifdef HAVE_TPETRA_DEBUG
609 #endif // HAVE_TPETRA_DEBUG
612 template<
class KeyType,
class ValueType,
class DeviceType>
616 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
617 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
618 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
619 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
621 maxVal_ (keys.size () == 0 ?
622 static_cast<ValueType> (0) :
623 static_cast<ValueType> (keys.size () - 1)),
624 firstContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
625 lastContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
626 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
627 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
628 contiguousValues_ (true),
629 checkedForDuplicateKeys_ (false),
630 hasDuplicateKeys_ (false)
632 const ValueType startingValue = static_cast<ValueType> (0);
633 const KeyType initMinKey = this->minKey_;
634 const KeyType initMaxKey = this->maxKey_;
635 this->init (keys, startingValue, initMinKey, initMaxKey,
636 initMinKey, initMinKey,
false);
638 #ifdef HAVE_TPETRA_DEBUG
640 #endif // HAVE_TPETRA_DEBUG
643 template<
class KeyType,
class ValueType,
class DeviceType>
646 const bool keepKeys) :
647 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
648 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
649 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
650 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
652 maxVal_ (keys.size () == 0 ?
653 static_cast<ValueType> (0) :
654 static_cast<ValueType> (keys.size () - 1)),
655 firstContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
656 lastContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
657 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
658 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
659 contiguousValues_ (true),
660 checkedForDuplicateKeys_ (false),
661 hasDuplicateKeys_ (false)
663 typedef typename keys_type::non_const_type nonconst_keys_type;
668 const ValueType startingValue = static_cast<ValueType> (0);
669 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
671 using Kokkos::ViewAllocateWithoutInitializing;
672 nonconst_keys_type keys_d (ViewAllocateWithoutInitializing (
"FixedHashTable::keys"),
675 const KeyType initMinKey = this->minKey_;
676 const KeyType initMaxKey = this->maxKey_;
677 this->init (keys_d, startingValue, initMinKey, initMaxKey,
678 initMinKey, initMinKey,
false);
681 #ifdef HAVE_TPETRA_DEBUG
682 typedef typename keys_type::size_type size_type;
683 TEUCHOS_TEST_FOR_EXCEPTION
684 (keys_.extent (0) != static_cast<size_type> (keys.size ()),
685 std::logic_error,
"Tpetra::Details::FixedHashTable constructor: "
686 "keepKeys is true, but on return, keys_.extent(0) = " <<
687 keys_.extent (0) <<
" != keys.size() = " << keys.size () <<
688 ". Please report this bug to the Tpetra developers.");
689 #endif // HAVE_TPETRA_DEBUG
692 #ifdef HAVE_TPETRA_DEBUG
694 #endif // HAVE_TPETRA_DEBUG
697 template<
class KeyType,
class ValueType,
class DeviceType>
700 const ValueType startingValue,
701 const bool keepKeys) :
702 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
703 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
704 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
705 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
706 minVal_ (startingValue),
707 maxVal_ (keys.size () == 0 ?
709 static_cast<ValueType> (startingValue + keys.size () - 1)),
710 firstContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
711 lastContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
712 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
713 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
714 contiguousValues_ (true),
715 checkedForDuplicateKeys_ (false),
716 hasDuplicateKeys_ (false)
718 typedef typename keys_type::non_const_type nonconst_keys_type;
723 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
725 using Kokkos::ViewAllocateWithoutInitializing;
726 nonconst_keys_type keys_d (ViewAllocateWithoutInitializing (
"FixedHashTable::keys"),
730 const KeyType initMinKey = ::Kokkos::Details::ArithTraits<KeyType>::max ();
743 const KeyType initMaxKey = ::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
744 ::Kokkos::Details::ArithTraits<KeyType>::min () :
745 -::Kokkos::Details::ArithTraits<KeyType>::max ();
746 this->init (keys_d, startingValue, initMinKey, initMaxKey,
747 initMinKey, initMinKey,
false);
750 #ifdef HAVE_TPETRA_DEBUG
751 typedef typename keys_type::size_type size_type;
752 TEUCHOS_TEST_FOR_EXCEPTION
753 (keys_.extent (0) != static_cast<size_type> (keys.size ()),
754 std::logic_error,
"Tpetra::Details::FixedHashTable constructor: "
755 "keepKeys is true, but on return, keys_.extent(0) = " <<
756 keys_.extent (0) <<
" != keys.size() = " << keys.size () <<
757 ". Please report this bug to the Tpetra developers.");
758 #endif // HAVE_TPETRA_DEBUG
761 #ifdef HAVE_TPETRA_DEBUG
763 #endif // HAVE_TPETRA_DEBUG
766 template<
class KeyType,
class ValueType,
class DeviceType>
769 const KeyType firstContigKey,
770 const KeyType lastContigKey,
771 const ValueType startingValue,
772 const bool keepKeys) :
773 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
774 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
775 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
776 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
777 minVal_ (startingValue),
778 maxVal_ (keys.size () == 0 ?
780 static_cast<ValueType> (startingValue + keys.size () - 1)),
781 firstContigKey_ (firstContigKey),
782 lastContigKey_ (lastContigKey),
783 contiguousValues_ (true),
784 checkedForDuplicateKeys_ (false),
785 hasDuplicateKeys_ (false)
787 const KeyType initMinKey = ::Kokkos::Details::ArithTraits<KeyType>::max ();
800 const KeyType initMaxKey = ::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
801 ::Kokkos::Details::ArithTraits<KeyType>::min () :
802 -::Kokkos::Details::ArithTraits<KeyType>::max ();
803 this->init (keys, startingValue, initMinKey, initMaxKey,
804 firstContigKey, lastContigKey,
true);
807 #ifdef HAVE_TPETRA_DEBUG
808 typedef typename keys_type::size_type size_type;
809 TEUCHOS_TEST_FOR_EXCEPTION
810 (keys_.extent (0) != static_cast<size_type> (keys.size ()),
811 std::logic_error,
"Tpetra::Details::FixedHashTable constructor: "
812 "keepKeys is true, but on return, keys_.extent(0) = " <<
813 keys_.extent (0) <<
" != keys.size() = " << keys.size () <<
814 ". Please report this bug to the Tpetra developers.");
815 #endif // HAVE_TPETRA_DEBUG
818 #ifdef HAVE_TPETRA_DEBUG
820 #endif // HAVE_TPETRA_DEBUG
823 template<
class KeyType,
class ValueType,
class DeviceType>
826 const KeyType firstContigKey,
827 const KeyType lastContigKey,
828 const ValueType startingValue,
829 const bool keepKeys) :
830 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
831 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
832 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
833 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
834 minVal_ (startingValue),
835 maxVal_ (keys.size () == 0 ?
837 static_cast<ValueType> (startingValue + keys.size () - 1)),
838 firstContigKey_ (firstContigKey),
839 lastContigKey_ (lastContigKey),
840 contiguousValues_ (true),
841 checkedForDuplicateKeys_ (false),
842 hasDuplicateKeys_ (false)
844 typedef typename keys_type::non_const_type nonconst_keys_type;
849 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
851 using Kokkos::ViewAllocateWithoutInitializing;
852 nonconst_keys_type keys_d (ViewAllocateWithoutInitializing (
"FixedHashTable::keys"),
856 const KeyType initMinKey = ::Kokkos::Details::ArithTraits<KeyType>::max ();
869 const KeyType initMaxKey = ::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
870 ::Kokkos::Details::ArithTraits<KeyType>::min () :
871 -::Kokkos::Details::ArithTraits<KeyType>::max ();
872 this->init (keys_d, startingValue, initMinKey, initMaxKey,
873 firstContigKey, lastContigKey,
true);
876 #ifdef HAVE_TPETRA_DEBUG
877 typedef typename keys_type::size_type size_type;
878 TEUCHOS_TEST_FOR_EXCEPTION
879 (keys_.extent (0) != static_cast<size_type> (keys.size ()),
880 std::logic_error,
"Tpetra::Details::FixedHashTable constructor: "
881 "keepKeys is true, but on return, keys_.extent(0) = " <<
882 keys_.extent (0) <<
" != keys.size() = " << keys.size () <<
883 ". Please report this bug to the Tpetra developers.");
884 #endif // HAVE_TPETRA_DEBUG
887 #ifdef HAVE_TPETRA_DEBUG
889 #endif // HAVE_TPETRA_DEBUG
892 template<
class KeyType,
class ValueType,
class DeviceType>
895 const ValueType startingValue) :
897 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
898 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
899 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
900 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
901 minVal_ (startingValue),
902 maxVal_ (keys.size () == 0 ?
904 static_cast<ValueType> (startingValue + keys.size () - 1)),
905 firstContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
906 lastContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
907 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
908 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
909 contiguousValues_ (true),
910 checkedForDuplicateKeys_ (false),
911 hasDuplicateKeys_ (false)
913 const KeyType initMinKey = ::Kokkos::Details::ArithTraits<KeyType>::max ();
926 const KeyType initMaxKey = ::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
927 ::Kokkos::Details::ArithTraits<KeyType>::min () :
928 -::Kokkos::Details::ArithTraits<KeyType>::max ();
929 this->init (keys, startingValue, initMinKey, initMaxKey,
930 initMinKey, initMinKey,
false);
932 #ifdef HAVE_TPETRA_DEBUG
934 #endif // HAVE_TPETRA_DEBUG
937 template<
class KeyType,
class ValueType,
class DeviceType>
940 const Teuchos::ArrayView<const ValueType>& vals) :
941 minKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
942 maxKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
943 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
944 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
945 minVal_ (::Kokkos::
Details::ArithTraits<ValueType>::max ()),
946 maxVal_ (::Kokkos::
Details::ArithTraits<ValueType>::is_integer ?
947 ::Kokkos::
Details::ArithTraits<ValueType>::min () :
948 -::Kokkos::
Details::ArithTraits<ValueType>::max ()),
949 firstContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::max ()),
950 lastContigKey_ (::Kokkos::
Details::ArithTraits<KeyType>::is_integer ?
951 ::Kokkos::
Details::ArithTraits<KeyType>::min () :
952 -::Kokkos::
Details::ArithTraits<KeyType>::max ()),
953 contiguousValues_ (false),
954 checkedForDuplicateKeys_ (false),
955 hasDuplicateKeys_ (false)
960 host_input_keys_type keys_k (keys.size () == 0 ? NULL : keys.getRawPtr (),
962 host_input_vals_type vals_k (vals.size () == 0 ? NULL : vals.getRawPtr (),
964 const KeyType initMinKey = ::Kokkos::Details::ArithTraits<KeyType>::max ();
977 const KeyType initMaxKey = ::Kokkos::Details::ArithTraits<KeyType>::is_integer ?
978 ::Kokkos::Details::ArithTraits<KeyType>::min () :
979 -::Kokkos::Details::ArithTraits<KeyType>::max ();
980 this->init (keys_k, vals_k, initMinKey, initMaxKey);
982 #ifdef HAVE_TPETRA_DEBUG
984 #endif // HAVE_TPETRA_DEBUG
987 template<
class KeyType,
class ValueType,
class DeviceType>
990 init (
const keys_type& keys,
991 ValueType startingValue,
994 KeyType firstContigKey,
995 KeyType lastContigKey,
996 const bool computeInitContigKeys)
998 using Kokkos::subview;
999 using Kokkos::ViewAllocateWithoutInitializing;
1000 using Teuchos::TypeNameTraits;
1001 typedef typename std::decay<decltype (keys.extent (0)) >::type size_type;
1002 const char prefix[] =
"Tpetra::Details::FixedHashTable: ";
1004 const offset_type numKeys = static_cast<offset_type> (keys.extent (0));
1006 const offset_type theMaxVal = ::Kokkos::Details::ArithTraits<offset_type>::max ();
1007 const size_type maxValST = static_cast<size_type> (theMaxVal);
1008 TEUCHOS_TEST_FOR_EXCEPTION
1009 (keys.extent (0) > maxValST, std::invalid_argument, prefix <<
"The "
1010 "number of keys " << keys.extent (0) <<
" does not fit in "
1011 "offset_type = " << TypeNameTraits<offset_type>::name () <<
", whose "
1012 "max value is " << theMaxVal <<
". This means that it is not possible to "
1013 "use this constructor.");
1015 TEUCHOS_TEST_FOR_EXCEPTION
1016 (static_cast<unsigned long long> (numKeys) >
1017 static_cast<unsigned long long> (::Kokkos::Details::ArithTraits<ValueType>::max ()),
1018 std::invalid_argument,
"Tpetra::Details::FixedHashTable: The number of "
1019 "keys " << numKeys <<
" is greater than the maximum representable "
1020 "ValueType value " << ::Kokkos::Details::ArithTraits<ValueType>::max () <<
". "
1021 "This means that it is not possible to use this constructor.");
1022 TEUCHOS_TEST_FOR_EXCEPTION
1023 (numKeys > static_cast<offset_type> (INT_MAX), std::logic_error, prefix <<
1024 "This class currently only works when the number of keys is <= INT_MAX = "
1025 << INT_MAX <<
". If this is a problem for you, please talk to the Tpetra "
1028 const bool buildInParallel =
1029 FHT::worthBuildingFixedHashTableInParallel<execution_space> ();
1039 if (computeInitContigKeys) {
1058 firstContigKey_ = keys[0];
1062 lastContigKey_ = firstContigKey_ + 1;
1068 for (offset_type k = 1; k < numKeys; ++k) {
1069 if (lastContigKey_ != keys[k]) {
1078 firstContigKey_ = firstContigKey;
1079 lastContigKey_ = lastContigKey;
1082 offset_type startIndex;
1084 initMinKey = std::min (initMinKey, firstContigKey_);
1085 initMaxKey = std::max (initMaxKey, lastContigKey_);
1086 startIndex = static_cast<offset_type> (lastContigKey_ - firstContigKey_);
1091 const offset_type theNumKeys = numKeys - startIndex;
1092 const offset_type size = hash_type::getRecommendedSize (theNumKeys);
1093 #ifdef HAVE_TPETRA_DEBUG
1094 TEUCHOS_TEST_FOR_EXCEPTION(
1095 size == 0 && numKeys != 0, std::logic_error,
1096 "Tpetra::Details::FixedHashTable constructor: "
1097 "getRecommendedSize(" << numKeys <<
") returned zero, "
1098 "even though the number of keys " << numKeys <<
" is nonzero. "
1099 "Please report this bug to the Tpetra developers.");
1100 #endif // HAVE_TPETRA_DEBUG
1102 subview (keys, std::pair<offset_type, offset_type> (startIndex, numKeys));
1109 typedef typename ptr_type::non_const_type counts_type;
1110 counts_type counts (
"FixedHashTable::counts", size);
1121 if (buildInParallel) {
1122 FHT::CountBuckets<counts_type, keys_type> functor (counts, theKeys, size);
1124 typedef typename counts_type::execution_space execution_space;
1125 typedef Kokkos::RangePolicy<execution_space, offset_type> range_type;
1126 Kokkos::parallel_for (range_type (0, theNumKeys), functor);
1133 auto countsHost = Kokkos::create_mirror_view (counts);
1137 for (offset_type k = 0; k < theNumKeys; ++k) {
1138 typedef typename hash_type::result_type hash_value_type;
1139 const hash_value_type hashVal = hash_type::hashFunc (theKeys[k], size);
1140 ++countsHost[hashVal];
1147 execution_space::fence ();
1150 typename ptr_type::non_const_type ptr (
"FixedHashTable::ptr", size+1);
1164 if (buildInParallel) {
1170 typename decltype (ptr)::HostMirror ptrHost = Kokkos::create_mirror_view (ptr);
1173 for (offset_type i = 0; i < size; ++i) {
1175 ptrHost[i+1] = ptrHost[i] + counts[i];
1182 execution_space::fence ();
1186 using Kokkos::ViewAllocateWithoutInitializing;
1187 typedef typename val_type::non_const_type nonconst_val_type;
1188 nonconst_val_type val (ViewAllocateWithoutInitializing (
"FixedHashTable::pairs"),
1192 typedef FHT::FillPairs<
typename val_type::non_const_type, keys_type,
1193 typename ptr_type::non_const_type> functor_type;
1194 typename functor_type::value_type result (initMinKey, initMaxKey);
1196 const ValueType newStartingValue = startingValue + static_cast<ValueType> (startIndex);
1197 if (buildInParallel) {
1198 functor_type functor (val, counts, ptr, theKeys, newStartingValue,
1199 initMinKey, initMaxKey);
1200 typedef Kokkos::RangePolicy<execution_space, offset_type> range_type;
1201 Kokkos::parallel_reduce (range_type (0, theNumKeys), functor, result);
1204 for (offset_type k = 0; k < theNumKeys; ++k) {
1205 typedef typename hash_type::result_type hash_value_type;
1206 const KeyType key = theKeys[k];
1207 if (key > result.maxKey_) {
1208 result.maxKey_ = key;
1210 if (key < result.minKey_) {
1211 result.minKey_ = key;
1213 const ValueType theVal = newStartingValue + static_cast<ValueType> (k);
1214 const hash_value_type hashVal = hash_type::hashFunc (key, size);
1220 const offset_type count = counts[hashVal];
1223 result.success_ =
false;
1228 const offset_type curPos = ptr[hashVal+1] - count;
1231 val[curPos].first = key;
1232 val[curPos].second = theVal;
1249 minKey_ = result.minKey_;
1250 maxKey_ = result.maxKey_;
1255 template<
class KeyType,
class ValueType,
class DeviceType>
1257 FixedHashTable<KeyType, ValueType, DeviceType>::
1258 init (
const host_input_keys_type& keys,
1259 const host_input_vals_type& vals,
1263 const offset_type numKeys = static_cast<offset_type> (keys.extent (0));
1264 TEUCHOS_TEST_FOR_EXCEPTION
1265 (static_cast<unsigned long long> (numKeys) > static_cast<unsigned long long> (::Kokkos::Details::ArithTraits<ValueType>::max ()),
1266 std::invalid_argument,
"Tpetra::Details::FixedHashTable: The number of "
1267 "keys " << numKeys <<
" is greater than the maximum representable "
1268 "ValueType value " << ::Kokkos::Details::ArithTraits<ValueType>::max () <<
".");
1269 TEUCHOS_TEST_FOR_EXCEPTION
1270 (numKeys > static_cast<offset_type> (INT_MAX), std::logic_error,
"Tpetra::"
1271 "Details::FixedHashTable: This class currently only works when the number "
1272 "of keys is <= INT_MAX = " << INT_MAX <<
". If this is a problem for you"
1273 ", please talk to the Tpetra developers.");
1280 const offset_type size = hash_type::getRecommendedSize (numKeys);
1281 #ifdef HAVE_TPETRA_DEBUG
1282 TEUCHOS_TEST_FOR_EXCEPTION(
1283 size == 0 && numKeys != 0, std::logic_error,
1284 "Tpetra::Details::FixedHashTable constructor: "
1285 "getRecommendedSize(" << numKeys <<
") returned zero, "
1286 "even though the number of keys " << numKeys <<
" is nonzero. "
1287 "Please report this bug to the Tpetra developers.");
1288 #endif // HAVE_TPETRA_DEBUG
1298 typename ptr_type::non_const_type ptr (
"FixedHashTable::ptr", size + 1);
1302 using Kokkos::ViewAllocateWithoutInitializing;
1303 typedef typename val_type::non_const_type nonconst_val_type;
1304 nonconst_val_type val (ViewAllocateWithoutInitializing (
"FixedHashTable::pairs"),
1308 for (offset_type k = 0; k < numKeys; ++k) {
1309 const typename hash_type::result_type hashVal =
1310 hash_type::hashFunc (keys[k], size);
1322 for (offset_type i = 0; i < size; ++i) {
1328 typename ptr_type::non_const_type curRowStart (
"FixedHashTable::curRowStart", size);
1331 FHT::FillPairsResult<KeyType> result (initMinKey, initMaxKey);
1332 for (offset_type k = 0; k < numKeys; ++k) {
1333 typedef typename hash_type::result_type hash_value_type;
1334 const KeyType key = keys[k];
1335 if (key > result.maxKey_) {
1336 result.maxKey_ = key;
1338 if (key < result.minKey_) {
1339 result.minKey_ = key;
1341 const ValueType theVal = vals[k];
1342 if (theVal > maxVal_) {
1345 if (theVal < minVal_) {
1348 const hash_value_type hashVal = hash_type::hashFunc (key, size);
1350 const offset_type offset = curRowStart[hashVal];
1351 const offset_type curPos = ptr[hashVal] + offset;
1352 if (curPos >= ptr[hashVal+1]) {
1353 result.success_ =
false;
1356 val[curPos].first = key;
1357 val[curPos].second = theVal;
1358 ++curRowStart[hashVal];
1362 TEUCHOS_TEST_FOR_EXCEPTION
1363 (! result.success_, std::logic_error,
"Tpetra::Details::FixedHashTable::"
1364 "init: Filling the hash table failed! Please report this bug to the "
1365 "Tpetra developers.");
1370 minKey_ = result.minKey_;
1371 maxKey_ = result.maxKey_;
1375 template <
class KeyType,
class ValueType,
class DeviceType>
1377 FixedHashTable<KeyType, ValueType, DeviceType>::
1380 if (! checkedForDuplicateKeys_) {
1381 hasDuplicateKeys_ = checkForDuplicateKeys ();
1382 checkedForDuplicateKeys_ =
true;
1384 return hasDuplicateKeys_;
1387 template <
class KeyType,
class ValueType,
class DeviceType>
1392 const offset_type size = this->getSize ();
1396 if (size == 0 || this->numPairs () == 0) {
1400 typedef FHT::CheckForDuplicateKeys<ptr_type, val_type> functor_type;
1401 functor_type functor (val_, ptr_);
1403 typedef Kokkos::RangePolicy<execution_space, offset_type> range_type;
1404 Kokkos::parallel_reduce (range_type (0, size), functor, hasDupKeys);
1405 return hasDupKeys > 0;
1409 template <
class KeyType,
class ValueType,
class DeviceType>
1411 FixedHashTable<KeyType, ValueType, DeviceType>::
1412 description ()
const
1414 std::ostringstream oss;
1415 oss <<
"FixedHashTable<"
1416 << Teuchos::TypeNameTraits<KeyType>::name () <<
","
1417 << Teuchos::TypeNameTraits<ValueType>::name () <<
">: "
1418 <<
"{ numKeys: " << val_.extent (0)
1419 <<
", tableSize: " << this->getSize () <<
" }";
1423 template <
class KeyType,
class ValueType,
class DeviceType>
1427 const Teuchos::EVerbosityLevel verbLevel)
const
1431 using Teuchos::OSTab;
1432 using Teuchos::rcpFromRef;
1433 using Teuchos::TypeNameTraits;
1434 using Teuchos::VERB_DEFAULT;
1435 using Teuchos::VERB_NONE;
1436 using Teuchos::VERB_LOW;
1437 using Teuchos::VERB_EXTREME;
1442 Teuchos::EVerbosityLevel vl = verbLevel;
1443 if (vl == VERB_DEFAULT) vl = VERB_LOW;
1445 if (vl == VERB_NONE) {
1448 else if (vl == VERB_LOW) {
1449 out << this->description() << endl;
1452 out <<
"FixedHashTable:" << endl;
1454 OSTab tab1 (rcpFromRef (out));
1460 out <<
"Template parameters:" << endl;
1462 OSTab tab2 (rcpFromRef (out));
1463 out <<
"KeyType: " << TypeNameTraits<KeyType>::name () << endl
1464 <<
"ValueType: " << TypeNameTraits<ValueType>::name () << endl;
1467 const offset_type tableSize = this->getSize ();
1468 const offset_type numKeys = val_.extent (0);
1470 out <<
"Table parameters:" << endl;
1472 OSTab tab2 (rcpFromRef (out));
1473 out <<
"numKeys: " << numKeys << endl
1474 <<
"tableSize: " << tableSize << endl;
1477 if (vl >= VERB_EXTREME) {
1478 out <<
"Contents: ";
1479 if (tableSize == 0 || numKeys == 0) {
1480 out <<
"[]" << endl;
1482 out <<
"[ " << endl;
1484 OSTab tab2 (rcpFromRef (out));
1485 for (offset_type i = 0; i < tableSize; ++i) {
1486 OSTab tab3 (rcpFromRef (out));
1488 for (offset_type k = ptr_[i]; k < ptr_[i+1]; ++k) {
1489 out <<
"(" << val_[k].first <<
"," << val_[k].second <<
")";
1490 if (k + 1 < ptr_[i+1]) {
1516 #define TPETRA_DETAILS_FIXEDHASHTABLE_INSTANT_DEFAULTNODE(LO,GO) \
1517 template class FixedHashTable< GO , LO >;
1528 #define TPETRA_DETAILS_FIXEDHASHTABLE_INSTANT(LO, GO, DEVICE) \
1529 template class FixedHashTable< GO , LO , DEVICE >;
1531 #endif // TPETRA_DETAILS_FIXEDHASHTABLE_DEF_HPP