Loading Documentation/Examples/Algorithms/CMakeLists.txt +1 −1 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ IF( BUILD_CUDA ) ADD_CUSTOM_COMMAND( COMMAND SortingExample3Cuda > ${TNL_DOCUMENTATION_OUTPUT_SNIPPETS_PATH}/SortingExample3.out OUTPUT SortingExample3.out ) ELSE() ADD_EXECUTABLE(ParallelForExample ParallelForExample.cpp) ADD_CUSTOM_COMMAND( COMMAND ParallelForExample > ${TNL_DOCUMENTATION_OUTPUT_SNIPPETS_PATH}/SortingExample.out OUTPUT SortingExample.out ) ADD_CUSTOM_COMMAND( COMMAND ParallelForExample > ${TNL_DOCUMENTATION_OUTPUT_SNIPPETS_PATH}/ParallelForExample.out OUTPUT ParallelForExample.out ) ADD_EXECUTABLE( SortingExample SortingExample.cpp) ADD_CUSTOM_COMMAND( COMMAND SortingExample > ${TNL_DOCUMENTATION_OUTPUT_SNIPPETS_PATH}/SortingExample.out OUTPUT SortingExample.out ) ADD_EXECUTABLE( SortingExample2 SortingExample2.cpp) Loading src/TNL/Algorithms/Sorting/BubbleSort.h 0 → 100644 +57 −0 Original line number Diff line number Diff line /*************************************************************************** BubbleSort.h - description ------------------- begin : Jul 26, 2021 copyright : (C) 2021 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ /* See Copyright Notice in tnl/Copyright */ // Implemented by: Tomas Oberhuber #pragma once #include <algorithm> namespace TNL { namespace Algorithms { namespace Sorting { struct BubbleSort { template< typename Device, typename Index, typename Compare, typename Swap > void static inplaceSort( const Index begin, const Index end, const Compare& compare, const Swap& swap ) { if( std::is_same< Device, Devices::Host >::value ) { Index left( begin ), right( end ); while( left < right ) { int lastChange; for( int j = left; j < right - 1; j++ ) if( ! compare( j, j+1 ) ) { swap( j, j+1 ); lastChange = j; } right = lastChange; for( int j = right - 1; j >= left; j-- ) if( ! compare( j, j+1 ) ) { swap( j, j+1 ); lastChange = j; } left = lastChange + 1; } } else TNL_ASSERT( false, std::cerr << "inplace bubble sort is implemented only for CPU" << std::endl ); } }; } // namespace Sorting } // namespace Algorithms } //namespace TNL src/TNL/Algorithms/Sorting/DefaultSorter.h +7 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <TNL/Devices/Host.h> #include <TNL/Devices/Cuda.h> #include <TNL/Algorithms/Sorting/BitonicSort.h> #include <TNL/Algorithms/Sorting/BubbleSort.h> #include <TNL/Algorithms/Sorting/Quicksort.h> #include <TNL/Algorithms/Sorting/STLSort.h> Loading @@ -43,6 +44,12 @@ struct DefaultSorter< Devices::Cuda > template< typename Device > struct DefaultInplaceSorter; template<> struct DefaultInplaceSorter< Devices::Host > { using SorterType = Algorithms::Sorting::BubbleSort; }; template<> struct DefaultInplaceSorter< Devices::Cuda > { Loading src/UnitTests/Algorithms/Sorting/BubbleSortTest.cpp 0 → 100644 +1 −0 Original line number Diff line number Diff line #include "BubbleSortTest.h" No newline at end of file src/UnitTests/Algorithms/Sorting/BubbleSortTest.h 0 → 100644 +93 −0 Original line number Diff line number Diff line #include <vector> #include <algorithm> #include <numeric> #include <random> #include <iostream> #include <TNL/Containers/Array.h> #include <TNL/Algorithms/MemoryOperations.h> #include <TNL/Algorithms/Sorting/BubbleSort.h> #include <TNL/Algorithms/Sort.h> #if defined HAVE_GTEST && defined HAVE_CUDA #include <gtest/gtest.h> using namespace TNL; using namespace TNL::Algorithms; using namespace TNL::Algorithms::Sorting; template<typename TYPE> void fetchAndSwapSorter( TNL::Containers::ArrayView< TYPE, TNL::Devices::Host > view) { auto Cmp = [=]__cuda_callable__(const int i, const int j ){return view[ i ] < view[ j ];}; auto Swap = [=] __cuda_callable__ (int i, int j) mutable {TNL::swap(view[i], view[j]);}; bubbleSort(0, view.getSize(), Cmp, Swap); } TEST(fetchAndSwap, oneBlockSort) { int size = 9; const int stride = 227; int i = 0; std::vector<int> orig(size); std::iota(orig.begin(), orig.end(), 0); do { if ((i++) % stride != 0) continue; TNL::Containers::Array<int, TNL::Devices::Host> arr(orig); auto view = arr.getView(); fetchAndSwapSorter(view); EXPECT_TRUE(Algorithms::isAscending(view)) << "result " << view << std::endl; } while (std::next_permutation(orig.begin(), orig.end())); } TEST(fetchAndSwap, typeDouble) { int size = 5; std::vector<double> orig(size); std::iota(orig.begin(), orig.end(), 0); do { TNL::Containers::Array<double, TNL::Devices::Host> arr(orig); auto view = arr.getView(); fetchAndSwapSorter(view); EXPECT_TRUE(Algorithms::isAscending(view)) << "result " << view << std::endl; } while (std::next_permutation(orig.begin(), orig.end())); } void fetchAndSwap_sortMiddle(TNL::Containers::ArrayView<int, TNL::Devices::Host> view, int from, int to) { //auto Fetch = [=]__cuda_callable__(int i){return view[i];}; auto Cmp = [=]__cuda_callable__(const int i, const int j ){ return view[ i ] < view[ j ]; }; auto Swap = [=] __cuda_callable__ (int i, int j) mutable { TNL::swap(view[i], view[j]); }; bubbleSort(from, to, Cmp, Swap); } TEST(fetchAndSwap, sortMiddle) { std::vector<int> orig{5, 9, 4, 54, 21, 6, 7, 9, 0, 9, 42, 4}; TNL::Containers::Array<int, TNL::Devices::Host> arr(orig); auto view = arr.getView(); size_t from = 3, to = 8; fetchAndSwap_sortMiddle(view, from, to); EXPECT_TRUE(Algorithms::isAscending(view.getView(3, 8))) << "result " << view << std::endl; for(size_t i = 0; i < orig.size(); i++) { if(i < from || i >= to) EXPECT_TRUE(view.getElement(i) == orig[i]); } } #endif #include "../../main.h" Loading
Documentation/Examples/Algorithms/CMakeLists.txt +1 −1 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ IF( BUILD_CUDA ) ADD_CUSTOM_COMMAND( COMMAND SortingExample3Cuda > ${TNL_DOCUMENTATION_OUTPUT_SNIPPETS_PATH}/SortingExample3.out OUTPUT SortingExample3.out ) ELSE() ADD_EXECUTABLE(ParallelForExample ParallelForExample.cpp) ADD_CUSTOM_COMMAND( COMMAND ParallelForExample > ${TNL_DOCUMENTATION_OUTPUT_SNIPPETS_PATH}/SortingExample.out OUTPUT SortingExample.out ) ADD_CUSTOM_COMMAND( COMMAND ParallelForExample > ${TNL_DOCUMENTATION_OUTPUT_SNIPPETS_PATH}/ParallelForExample.out OUTPUT ParallelForExample.out ) ADD_EXECUTABLE( SortingExample SortingExample.cpp) ADD_CUSTOM_COMMAND( COMMAND SortingExample > ${TNL_DOCUMENTATION_OUTPUT_SNIPPETS_PATH}/SortingExample.out OUTPUT SortingExample.out ) ADD_EXECUTABLE( SortingExample2 SortingExample2.cpp) Loading
src/TNL/Algorithms/Sorting/BubbleSort.h 0 → 100644 +57 −0 Original line number Diff line number Diff line /*************************************************************************** BubbleSort.h - description ------------------- begin : Jul 26, 2021 copyright : (C) 2021 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ /* See Copyright Notice in tnl/Copyright */ // Implemented by: Tomas Oberhuber #pragma once #include <algorithm> namespace TNL { namespace Algorithms { namespace Sorting { struct BubbleSort { template< typename Device, typename Index, typename Compare, typename Swap > void static inplaceSort( const Index begin, const Index end, const Compare& compare, const Swap& swap ) { if( std::is_same< Device, Devices::Host >::value ) { Index left( begin ), right( end ); while( left < right ) { int lastChange; for( int j = left; j < right - 1; j++ ) if( ! compare( j, j+1 ) ) { swap( j, j+1 ); lastChange = j; } right = lastChange; for( int j = right - 1; j >= left; j-- ) if( ! compare( j, j+1 ) ) { swap( j, j+1 ); lastChange = j; } left = lastChange + 1; } } else TNL_ASSERT( false, std::cerr << "inplace bubble sort is implemented only for CPU" << std::endl ); } }; } // namespace Sorting } // namespace Algorithms } //namespace TNL
src/TNL/Algorithms/Sorting/DefaultSorter.h +7 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <TNL/Devices/Host.h> #include <TNL/Devices/Cuda.h> #include <TNL/Algorithms/Sorting/BitonicSort.h> #include <TNL/Algorithms/Sorting/BubbleSort.h> #include <TNL/Algorithms/Sorting/Quicksort.h> #include <TNL/Algorithms/Sorting/STLSort.h> Loading @@ -43,6 +44,12 @@ struct DefaultSorter< Devices::Cuda > template< typename Device > struct DefaultInplaceSorter; template<> struct DefaultInplaceSorter< Devices::Host > { using SorterType = Algorithms::Sorting::BubbleSort; }; template<> struct DefaultInplaceSorter< Devices::Cuda > { Loading
src/UnitTests/Algorithms/Sorting/BubbleSortTest.cpp 0 → 100644 +1 −0 Original line number Diff line number Diff line #include "BubbleSortTest.h" No newline at end of file
src/UnitTests/Algorithms/Sorting/BubbleSortTest.h 0 → 100644 +93 −0 Original line number Diff line number Diff line #include <vector> #include <algorithm> #include <numeric> #include <random> #include <iostream> #include <TNL/Containers/Array.h> #include <TNL/Algorithms/MemoryOperations.h> #include <TNL/Algorithms/Sorting/BubbleSort.h> #include <TNL/Algorithms/Sort.h> #if defined HAVE_GTEST && defined HAVE_CUDA #include <gtest/gtest.h> using namespace TNL; using namespace TNL::Algorithms; using namespace TNL::Algorithms::Sorting; template<typename TYPE> void fetchAndSwapSorter( TNL::Containers::ArrayView< TYPE, TNL::Devices::Host > view) { auto Cmp = [=]__cuda_callable__(const int i, const int j ){return view[ i ] < view[ j ];}; auto Swap = [=] __cuda_callable__ (int i, int j) mutable {TNL::swap(view[i], view[j]);}; bubbleSort(0, view.getSize(), Cmp, Swap); } TEST(fetchAndSwap, oneBlockSort) { int size = 9; const int stride = 227; int i = 0; std::vector<int> orig(size); std::iota(orig.begin(), orig.end(), 0); do { if ((i++) % stride != 0) continue; TNL::Containers::Array<int, TNL::Devices::Host> arr(orig); auto view = arr.getView(); fetchAndSwapSorter(view); EXPECT_TRUE(Algorithms::isAscending(view)) << "result " << view << std::endl; } while (std::next_permutation(orig.begin(), orig.end())); } TEST(fetchAndSwap, typeDouble) { int size = 5; std::vector<double> orig(size); std::iota(orig.begin(), orig.end(), 0); do { TNL::Containers::Array<double, TNL::Devices::Host> arr(orig); auto view = arr.getView(); fetchAndSwapSorter(view); EXPECT_TRUE(Algorithms::isAscending(view)) << "result " << view << std::endl; } while (std::next_permutation(orig.begin(), orig.end())); } void fetchAndSwap_sortMiddle(TNL::Containers::ArrayView<int, TNL::Devices::Host> view, int from, int to) { //auto Fetch = [=]__cuda_callable__(int i){return view[i];}; auto Cmp = [=]__cuda_callable__(const int i, const int j ){ return view[ i ] < view[ j ]; }; auto Swap = [=] __cuda_callable__ (int i, int j) mutable { TNL::swap(view[i], view[j]); }; bubbleSort(from, to, Cmp, Swap); } TEST(fetchAndSwap, sortMiddle) { std::vector<int> orig{5, 9, 4, 54, 21, 6, 7, 9, 0, 9, 42, 4}; TNL::Containers::Array<int, TNL::Devices::Host> arr(orig); auto view = arr.getView(); size_t from = 3, to = 8; fetchAndSwap_sortMiddle(view, from, to); EXPECT_TRUE(Algorithms::isAscending(view.getView(3, 8))) << "result " << view << std::endl; for(size_t i = 0; i < orig.size(); i++) { if(i < from || i >= to) EXPECT_TRUE(view.getElement(i) == orig[i]); } } #endif #include "../../main.h"