Commit de7beccf authored by Tomáš Oberhuber's avatar Tomáš Oberhuber
Browse files

Added bubble sort - to have CPU sorter with interface for lambda functions.

parent 4c564a62
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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)
+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

+7 −0
Original line number Diff line number Diff line
@@ -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>

@@ -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 >
{
+1 −0
Original line number Diff line number Diff line
#include "BubbleSortTest.h"
 No newline at end of file
+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