Skip to content

C++20 concept implementations #116

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 17 additions & 24 deletions hydra/Random.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <hydra/detail/utility/Utility_Tuple.h>
#include <hydra/detail/ArgumentTraits.h>
#include <hydra/detail/PRNGTypedefs.h>
#include <hydra/detail/RandomConcepts.h>

#include <hydra/Range.h>

Expand Down Expand Up @@ -551,11 +552,9 @@ sample( Iterable&& output ,
* @param rng_jump sequence offset for the underlying pseudo-random number generator
*/
template< typename Engine = hydra::default_random_engine, hydra::detail::Backend BACKEND, typename Iterator, typename FUNCTOR >
typename std::enable_if< hydra::detail::has_rng_formula<FUNCTOR>::value && std::is_convertible<
decltype(std::declval<RngFormula<FUNCTOR>>().Generate( std::declval<Engine&>(), std::declval<FUNCTOR const&>())),
typename hydra::thrust::iterator_traits<Iterator>::value_type
>::value, void>::type
fill_random(hydra::detail::BackendPolicy<BACKEND> const& policy,
requires hydra::detail::HasRngFormula<FUNCTOR> &&
hydra::detail::IsRngFormulaConvertible<FUNCTOR, Engine, Iterator>
void fill_random(hydra::detail::BackendPolicy<BACKEND> const& policy,
Iterator begin, Iterator end, FUNCTOR const& functor, size_t seed=0x254a0afcf7da74a2, size_t rng_jump=0 );

/**
Expand All @@ -570,11 +569,9 @@ fill_random(hydra::detail::BackendPolicy<BACKEND> const& policy,
* @param rng_jump sequence offset for the underlying pseudo-random number generator
*/
template< typename Engine =hydra::default_random_engine, typename Iterator, typename FUNCTOR >
typename std::enable_if< hydra::detail::has_rng_formula<FUNCTOR>::value && std::is_convertible<
decltype(std::declval<RngFormula<FUNCTOR>>().Generate( std::declval<Engine&>(), std::declval<FUNCTOR const&>())),
typename hydra::thrust::iterator_traits<Iterator>::value_type
>::value, void>::type
fill_random(Iterator begin, Iterator end, FUNCTOR const& functor, size_t seed=0x254a0afcf7da74a2, size_t rng_jump=0 );
requires hydra::detail::HasRngFormula<FUNCTOR> &&
hydra::detail::IsRngFormulaConvertible<FUNCTOR, Engine, Iterator>
void fill_random(Iterator begin, Iterator end, FUNCTOR const& functor, size_t seed=0x254a0afcf7da74a2, size_t rng_jump=0 );

/**
* \ingroup random
Expand Down Expand Up @@ -620,8 +617,8 @@ fill_random(Iterable&& iterable, FUNCTOR const& functor, size_t seed=0x254a0afcf
* @param rng_jump sequence offset for the underlying pseudo-random number generator
*/
template< typename Engine = hydra::default_random_engine, hydra::detail::Backend BACKEND, typename Iterator, typename FUNCTOR >
typename std::enable_if< !hydra::detail::has_rng_formula<FUNCTOR>::value , void>::type
fill_random(hydra::detail::BackendPolicy<BACKEND> const& policy,
requires (!hydra::detail::HasRngFormula<FUNCTOR>)
void fill_random(hydra::detail::BackendPolicy<BACKEND> const& policy,
Iterator begin, Iterator end, FUNCTOR const& functor, size_t seed=0x254a0afcf7da74a2, size_t rng_jump=0 );

/**
Expand All @@ -636,8 +633,8 @@ fill_random(hydra::detail::BackendPolicy<BACKEND> const& policy,
* @param rng_jump sequence offset for the underlying pseudo-random number generator
*/
template< typename Engine = hydra::default_random_engine, typename Iterator, typename FUNCTOR >
typename std::enable_if< !hydra::detail::has_rng_formula<FUNCTOR>::value , void>::type
fill_random(Iterator begin, Iterator end, FUNCTOR const& functor, size_t seed=0x254a0afcf7da74a2, size_t rng_jump=0 );
requires (!hydra::detail::HasRngFormula<FUNCTOR>)
void fill_random(Iterator begin, Iterator end, FUNCTOR const& functor, size_t seed=0x254a0afcf7da74a2, size_t rng_jump=0 );

/**
* \ingroup random
Expand All @@ -652,11 +649,9 @@ fill_random(Iterator begin, Iterator end, FUNCTOR const& functor, size_t seed=0x
* @param rng_jump sequence offset for the underlying pseudo-random number generator
*/
template< typename Engine = hydra::default_random_engine, hydra::detail::Backend BACKEND, typename Iterator, typename FUNCTOR >
typename std::enable_if< !std::is_convertible<
decltype(std::declval<RngFormula<FUNCTOR>>().Generate( std::declval<Engine&>(), std::declval<FUNCTOR const&>())),
typename std::iterator_traits<Iterator>::value_type
>::value && hydra::detail::has_rng_formula<FUNCTOR>::value, void>::type
fill_random(hydra::detail::BackendPolicy<BACKEND> const& policy,
requires hydra::detail::HasRngFormula<FUNCTOR> &&
hydra::detail::NotConvertibleToIteratorValue<FUNCTOR, Engine, Iterator>
void fill_random(hydra::detail::BackendPolicy<BACKEND> const& policy,
Iterator begin, Iterator end, FUNCTOR const& funct, size_t seed=0x254a0afcf7da74a2, size_t rng_jump=0 );

/**
Expand All @@ -671,11 +666,9 @@ fill_random(hydra::detail::BackendPolicy<BACKEND> const& policy,
* @param rng_jump sequence offset for the underlying pseudo-random number generator
*/
template< typename Engine = hydra::default_random_engine, typename Iterator, typename FUNCTOR >
typename std::enable_if< !std::is_convertible<
decltype(std::declval<RngFormula<FUNCTOR>>().Generate( std::declval<Engine&>(), std::declval<FUNCTOR const&>())),
typename std::iterator_traits<Iterator>::value_type
>::value && hydra::detail::has_rng_formula<FUNCTOR>::value, void>::type
fill_random(Iterator begin, Iterator end, FUNCTOR const& functor, size_t seed=0x254a0afcf7da74a2, size_t rng_jump=0 );
requires hydra::detail::HasRngFormula<FUNCTOR> &&
hydra::detail::NotConvertibleToIteratorValue<FUNCTOR, Engine, Iterator>
void fill_random(Iterator begin, Iterator end, FUNCTOR const& functor, size_t seed=0x254a0afcf7da74a2, size_t rng_jump=0 );

/**
* \ingroup random
Expand Down
59 changes: 59 additions & 0 deletions hydra/detail/RandomConcepts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*----------------------------------------------------------------------------
*
* Copyright (C) 2016 - 2023 Antonio Augusto Alves Junior
*
* This file is part of Hydra Data Analysis Framework.
*
* Hydra is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Hydra is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Hydra. If not, see <http://www.gnu.org/licenses/>.
*
*---------------------------------------------------------------------------*/

/*
* RandomConcepts.h
*
* Created on: 14/03/2025
* Author: Davide Brundu
*/

#ifndef RANDOMCONCEPTS_H_
#define RANDOMCONCEPTS_H_

#include <concepts>
#include <type_traits>

namespace hydra {

namespace detail {

template <typename T>
concept HasRngFormula = has_rng_formula<T>::value;

template <typename FUNCTOR, typename Engine, typename Iterator>
concept IsRngFormulaConvertible = requires (Engine& engine, const FUNCTOR& functor) {
{ RngFormula<FUNCTOR>().Generate(engine, functor) } -> std::convertible_to<typename hydra::thrust::iterator_traits<Iterator>::value_type>;
};

template <typename FUNCTOR, typename Engine, typename Iterator>
concept NotConvertibleToIteratorValue =
!std::convertible_to<
decltype(RngFormula<FUNCTOR>().Generate(std::declval<Engine&>(), std::declval<const FUNCTOR&>())),
typename std::iterator_traits<Iterator>::value_type>;

} // namespace detail

} // namespace hydra



#endif /* RANDOMCONCEPTS_H_ */
51 changes: 21 additions & 30 deletions hydra/detail/RandomFill.inl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
#define RANDOMFILL_INL_



namespace hydra{

/**
Expand All @@ -47,12 +46,10 @@ namespace hydra{
* @param end ending of the range storing the generated values
* @param functor distribution to be sampled
*/
template< typename Engine, hydra::detail::Backend BACKEND, typename Iterator, typename FUNCTOR >
typename std::enable_if< hydra::detail::has_rng_formula<FUNCTOR>::value && std::is_convertible<
decltype(std::declval<RngFormula<FUNCTOR>>().Generate( std::declval<Engine&>(), std::declval<FUNCTOR const&>())),
typename hydra::thrust::iterator_traits<Iterator>::value_type
>::value, void>::type
fill_random(hydra::detail::BackendPolicy<BACKEND> const& policy,
template <typename Engine, hydra::detail::Backend BACKEND, typename Iterator, typename FUNCTOR>
requires hydra::detail::HasRngFormula<FUNCTOR> &&
hydra::detail::IsRngFormulaConvertible<FUNCTOR, Engine, Iterator>
void fill_random(hydra::detail::BackendPolicy<BACKEND> const& policy,
Iterator begin, Iterator end, FUNCTOR const& functor, size_t seed, size_t rng_jump)
{
using hydra::thrust::system::detail::generic::select_system;
Expand All @@ -63,7 +60,7 @@ namespace hydra{

typedef typename hydra::thrust::detail::remove_reference<
decltype(select_system( system, _policy ))>::type common_system_type;

hydra::thrust::tabulate( common_system_type(), begin, end, detail::Sampler<FUNCTOR,Engine>(functor, seed, rng_jump) );

}
Expand All @@ -75,11 +72,9 @@ namespace hydra{
* @param functor distribution to be sampled
*/
template< typename Engine, typename Iterator, typename FUNCTOR >
typename std::enable_if< hydra::detail::has_rng_formula<FUNCTOR>::value && std::is_convertible<
decltype(std::declval<RngFormula<FUNCTOR>>().Generate( std::declval<Engine&>(), std::declval<FUNCTOR const&>())),
typename hydra::thrust::iterator_traits<Iterator>::value_type
>::value, void>::type
fill_random(Iterator begin, Iterator end, FUNCTOR const& functor, size_t seed, size_t rng_jump)
requires hydra::detail::HasRngFormula<FUNCTOR> &&
hydra::detail::IsRngFormulaConvertible<FUNCTOR, Engine, Iterator>
void fill_random(Iterator begin, Iterator end, FUNCTOR const& functor, size_t seed, size_t rng_jump)
{
using hydra::thrust::system::detail::generic::select_system;
typedef typename hydra::thrust::iterator_system<Iterator>::type system_t;
Expand Down Expand Up @@ -123,8 +118,8 @@ namespace hydra{
* @brief Fall back function if RngFormula is not implemented for the requested functor
*/
template< typename Engine, hydra::detail::Backend BACKEND, typename Iterator, typename FUNCTOR >
typename std::enable_if< !hydra::detail::has_rng_formula<FUNCTOR>::value , void>::type
fill_random(hydra::detail::BackendPolicy<BACKEND> const& policy,
requires (!hydra::detail::HasRngFormula<FUNCTOR>)
void fill_random(hydra::detail::BackendPolicy<BACKEND> const& policy,
Iterator begin, Iterator end, FUNCTOR const& functor, size_t seed, size_t rng_jump)
{

Expand All @@ -134,13 +129,13 @@ namespace hydra{
" which will deploy different strategy \n.")

}

/**
* @brief Fall back function if RngFormula is not implemented for the requested functor
*/
template< typename Engine, typename Iterator, typename FUNCTOR >
typename std::enable_if< !hydra::detail::has_rng_formula<FUNCTOR>::value , void>::type
fill_random(Iterator begin, Iterator end, FUNCTOR const& functor, size_t seed, size_t rng_jump)
requires (!hydra::detail::HasRngFormula<FUNCTOR>)
void fill_random(Iterator begin, Iterator end, FUNCTOR const& functor, size_t seed, size_t rng_jump)
{

HYDRA_STATIC_ASSERT( int(std::is_class<Engine>::value) ==-1 ,
Expand All @@ -149,16 +144,14 @@ namespace hydra{
" which will deploy different strategy ")

}

/**
* @brief Fall back function if RngFormula::Generate() return value is not convertible to functor return value
*/
template< typename Engine, hydra::detail::Backend BACKEND, typename Iterator, typename FUNCTOR >
typename std::enable_if< !std::is_convertible<
decltype(std::declval<RngFormula<FUNCTOR>>().Generate( std::declval<Engine&>(), std::declval<FUNCTOR const&>())),
typename std::iterator_traits<Iterator>::value_type
>::value && hydra::detail::has_rng_formula<FUNCTOR>::value, void>::type
fill_random(hydra::detail::BackendPolicy<BACKEND> const& policy,
requires hydra::detail::HasRngFormula<FUNCTOR> &&
hydra::detail::NotConvertibleToIteratorValue<FUNCTOR, Engine, Iterator>
void fill_random(hydra::detail::BackendPolicy<BACKEND> const& policy,
Iterator begin, Iterator end, FUNCTOR const& funct, size_t seed, size_t rng_jump)
{
HYDRA_STATIC_ASSERT( int(std::is_class<Engine>::value) ==-1 ,
Expand All @@ -169,16 +162,14 @@ namespace hydra{
* @brief Fall back function if RngFormula::Generate() return value is not convertible to functor return value
*/
template< typename Engine, typename Iterator, typename FUNCTOR >
typename std::enable_if< !std::is_convertible<
decltype(std::declval<RngFormula<FUNCTOR>>().Generate( std::declval<Engine&>(), std::declval<FUNCTOR const&>())),
typename std::iterator_traits<Iterator>::value_type
>::value && hydra::detail::has_rng_formula<FUNCTOR>::value, void>::type
fill_random(Iterator begin, Iterator end, FUNCTOR const& funct, size_t seed, size_t rng_jump)
requires hydra::detail::HasRngFormula<FUNCTOR> &&
hydra::detail::NotConvertibleToIteratorValue<FUNCTOR, Engine, Iterator>
void fill_random(Iterator begin, Iterator end, FUNCTOR const& funct, size_t seed, size_t rng_jump)
{
HYDRA_STATIC_ASSERT( int(std::is_class<Engine>::value) ==-1 ,
" Generated objects can't be stored in this container. " )
}

/**
* @brief Fall back function if the argument is not an Iterable or if it is not convertible to the Functor return value
*/
Expand Down