Skip to content
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

Add a multidimensional wrapper around c-array #21

Merged
merged 14 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from 12 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
184 changes: 184 additions & 0 deletions src/common/CArray.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/**
* @file CArray.hpp
* @brief This file contains the implementation of the CArray class.
*/

#pragma once


#include "common/ShivaMacros.hpp"

#include "CArrayHelper.hpp"

#include <utility>



namespace shiva
{



/**
* @struct CArray
* @brief This struct provides a compile-time dimesion multidimensional array.
* @tparam T This is the type of the data stored in the array.
* @tparam DIMS These are the dimensions of the array.
*/
template< typename T, typename DATA_BUFFER, int ... DIMS >
struct CArray
{
/// The type of the an element in the array.
using element_type = T;

/// The type of the data stored in the array.
using value_type = std::remove_cv_t< T >;

/// The type of the indices used to access the array.
using index_type = int;

/// The number of dimensions in the array.
static inline constexpr int rank() { return sizeof ... ( DIMS ); }

/// The dimensions of the array.
template< int INDEX >
static inline constexpr int extent() { return CArrayHelper::get< INDEX, DIMS ... >(); }

/// The size of the data in array...i.e. the product of the dimensions.
static inline constexpr int size() { return ( DIMS * ... ); }

/**
* @brief Constructor for wrapping a pointer to data
* @tparam U Type to used to check if the data is a pointer for SFINAE.
* @tparam ENABLE SFINAE parameter.
* @param buffer data that the view will point to.
*/
template< typename U = DATA_BUFFER,
std::enable_if_t< std::is_pointer_v< U >, int > ENABLE = 0 >
constexpr explicit CArray( T const (&buffer)[ CArrayHelper::size< DIMS... >() ] ):
m_data( buffer )
{}

/**
* @copydoc CArray
*/
template< typename U = DATA_BUFFER,
std::enable_if_t< std::is_pointer_v< U >, int > = 0 >
constexpr explicit CArray( std::remove_const_t< T >(&buffer)[ CArrayHelper::size< DIMS... >() ] ):
m_data( buffer )
{}

/**
* @brief Constructor for list initialization.
* @tparam ...U the type of the arguments.
* @param ...args the data to initialize the array with.
*/
template< typename ... U >
constexpr CArray( U ... args ): m_data{ args ... }
{}

/**
* @brief accessor for m_data
* @return reference to m_data
*/
DATA_BUFFER & data() { return m_data; }

/**
* @brief const accessor for m_data
* @return reference to const m_data
*/
DATA_BUFFER const & data() const { return m_data; }

/**
* @brief Templated operator() to access the data in the array.
* @tparam ...INDICES The indices that specify the data to access.
* @return A reference to the data at the specified indices.
*/
template< int... INDICES >
SHIVA_CONSTEXPR_HOSTDEVICE_FORCEINLINE
T& operator()( )
{
static_assert( sizeof...(INDICES) == sizeof...(DIMS), "Incorrect number of indices" );
return m_data[ CArrayHelper::linearIndexHelper< DIMS... >::template eval< INDICES... >() ];
}

/**
* @brief const operator() to access the data in the array.
* @tparam ...INDICES The indices that specify the data to access.
* @return A reference to the data at the specified indices.
*/
template< int... INDICES >
SHIVA_CONSTEXPR_HOSTDEVICE_FORCEINLINE
std::add_const_t< T >& operator()( ) const
{
static_assert( sizeof...(INDICES) == sizeof...(DIMS), "Incorrect number of indices" );
return m_data[ CArrayHelper::linearIndexHelper< DIMS... >::template eval< INDICES... >() ];
}

/**
* @brief parentheses operator accessor to data in the array.
* @tparam ...INDICES The type of the indices that specify the data to access.
* @param ...indices The pack of indices that specify the data to access.
* @return A reference to the data at the specified indices.
*/
template< typename ... INDICES >
SHIVA_CONSTEXPR_HOSTDEVICE_FORCEINLINE
T& operator()( INDICES... indices )
{
static_assert( sizeof...(INDICES) == sizeof...(DIMS), "Incorrect number of indices" );
return m_data[ CArrayHelper::linearIndexHelper< DIMS... >::eval( indices ... ) ];
}

/**
* @brief const parentheses operator accessor to data in the array.
* @tparam ...INDICES The type of the indices that specify the data to access.
* @param ...indices The pack of indices that specify the data to access.
* @return A reference to the data at the specified indices.
*/
template< typename ... INDICES >
SHIVA_CONSTEXPR_HOSTDEVICE_FORCEINLINE
std::add_const_t< T >& operator()( INDICES... indices ) const
{
static_assert( sizeof...(INDICES) == sizeof...(DIMS), "Incorrect number of indices" );
return m_data[ CArrayHelper::linearIndexHelper< DIMS... >::eval( indices ... ) ];
}

private:
/// The data in the array.
DATA_BUFFER m_data;
};

/**
* @brief Alias for a scalar.
* @tparam T Type held in the scalar
*/
template< typename T >
using Scalar = CArray< T, T[1], 1 >;

/**
* @brief Alias for a N-d array.
* @tparam T Type held in the array.
* @tparam DIMS The dimensions of the array.
*/
template< typename T, int ... DIMS >
using CArrayNd = CArray< T, T[CArrayHelper::size< DIMS ... >()], DIMS ... >;


/**
* @brief Alias for a scalar view.
* @tparam T Type held in the scalar
*/
template< typename T >
using ScalarView = CArray< T, T, 1 >;

/**
* @brief Alias for a N-d array view.
* @tparam T Type held in the array.
* @tparam DIMS The dimensions of the array.
*/
template< typename T, int ... DIMS >
using CArrayViewNd = CArray< T, T * const, DIMS ... >;



} // namespace shiva
184 changes: 184 additions & 0 deletions src/common/CArrayHelper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/**
* @file CArrayHelper.hpp
* @brief This file contains the helper functions for the MultiDimensionalArray and MultiDimensionalSpan.
*/

#pragma once


#include "common/ShivaMacros.hpp"
#include <utility>



namespace shiva
{

/**
* @namespace shiva::CArrayHelper
* @brief The CArrayHelper namespace contains some stride calculations and
* linearIndex calculations for the MultiDimensionalBase class.
*/
namespace CArrayHelper
{


/**
* @brief This recursive function helps to calculates the strides for
* dimensions passed in as a template parameter pack.
* @tparam DIM This is the first dimension peeled off the parameter pack.
* @tparam DIMS These are the remaining dimensions of the pack.
* @return This returns the stride of the largest dimension in the pack.
*/
template< int DIM, int ... DIMS >
SHIVA_STATIC_CONSTEXPR_HOSTDEVICE_FORCEINLINE int
strideHelper()
{
if constexpr ( sizeof ... ( DIMS ) == 0 )
{
return DIM;
}
else
{
return DIM * strideHelper< DIMS ... >();
}
}

/**
* @brief This function calculates the stride of the largest dimension in the
* pack.
* @tparam DIM This is the first dimension peeled off the parameter pack.
* @tparam DIMS These are the remaining dimensions of the pack.
* @return This returns the stride of the largest dimension in the pack.
*/
template< int DIM, int ... DIMS >
SHIVA_STATIC_CONSTEXPR_HOSTDEVICE_FORCEINLINE int
stride()
{
return strideHelper< DIMS ..., 1 >();
}

/**
* @struct linearIndexHelper
* @brief struct to facilitate the calculation of a linear index from a pack
* of dimensions by peeling the dimensions pack one at a time.
* @tparam DIM This is the first dimension peeled off the parameter pack.
* @tparam DIMS These are the remaining dimensions of the pack.
*/
template< int DIM, int ... DIMS >
struct linearIndexHelper
{
/**
* @brief This recursive function calculates the linear index from a pack
* of indices by peeling off the indices one at a time, and multiplying
* by the stride at that "level" of the product sum.
* @tparam INDEX This is the first index peeled off the parameter pack.
* @tparam INDICES These are the remaining indices of the pack.
* @return This returns the linear index.
*/
template< int INDEX, int ... INDICES >
SHIVA_STATIC_CONSTEXPR_HOSTDEVICE_FORCEINLINE int
level()
{
constexpr int thisStride = strideHelper< DIMS ..., 1 >();
if constexpr ( sizeof ... ( DIMS ) == 0 )
{
return INDEX * thisStride;
}
else
{
return INDEX * thisStride + linearIndexHelper< DIMS ... >::template level< INDICES ... >();
}
}

/**
* @copydoc level()
*/
template< typename INDEX_TYPE, typename ... INDICES_TYPE >
SHIVA_STATIC_CONSTEXPR_HOSTDEVICE_FORCEINLINE int
level( INDEX_TYPE const index, INDICES_TYPE const ... indices )
{
constexpr int thisStride = strideHelper< DIMS ..., 1 >();
if constexpr ( sizeof ... ( DIMS ) == 0 )
{
return index * thisStride;
}
else
{
return index * thisStride + linearIndexHelper< DIMS ... >::template level( std::forward< INDICES_TYPE const >( indices )... );
}
}

/**
* @brief This function calculates the linear index from a pack of indices.
* @tparam INDICES The indices to calculate the linear index from.
* @return This returns the linear index.
*/
template< int ... INDICES >
SHIVA_STATIC_CONSTEXPR_HOSTDEVICE_FORCEINLINE int
eval()
{
return level< INDICES ... >();
}

/**
* @brief This function calculates the linear index from a pack of indices.
* @tparam INDEX_TYPE The type of the index.
* @param indices The indices to calculate the linear index from.
* @return This returns the linear index.
*/
template< typename ... INDEX_TYPE >
SHIVA_STATIC_CONSTEXPR_HOSTDEVICE_FORCEINLINE int
eval( INDEX_TYPE ... indices )
{
return level( std::forward< INDEX_TYPE >( indices )... );
}
};


/**
* @brief function to get a specific value from a pack of indices.
* @tparam COUNT The index of the pack to return.
* @tparam INDEX The first index peeled off the pack.
* @tparam INDICES The remaining indices in the pack.
* @return The value of the INDICES pack at COUNT.
*/
template< int COUNT, int INDEX, int ... INDICES >
SHIVA_STATIC_CONSTEXPR_HOSTDEVICE_FORCEINLINE int
get()
{
if constexpr ( COUNT == 0 )
{
return INDEX;
}
else
{
return get< COUNT - 1, INDICES ... >();
}
}

/**
* @brief function to get the product size of a pack of indices.
* @tparam INDICES The indices to get the aggregate length of.
*/
template< int ... DIMS >
SHIVA_STATIC_CONSTEXPR_HOSTDEVICE_FORCEINLINE int
size()
{
return ( DIMS * ... );
}

/**
* @brief function to peel a value from a parameter pack.
* @tparam T The type of the first value in the pack.
* @tparam Ts The types of the remaining values in the pack.
*/
template< typename T, typename ... Ts >
struct Peeler
{
/// The type of the first value in the pack.
using type = T;
};

} // namespace CArrayHelper
} // namespace shiva
2 changes: 2 additions & 0 deletions src/common/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@

set( common_headers
CArray.hpp
CArrayHelper.hpp
IndexTypes.hpp
LinearIndex.hpp
MathUtilities.hpp
Expand Down
Loading
Loading