Skip to content

Instantly share code, notes, and snippets.

@christophercrouzet
Last active August 29, 2015 14:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save christophercrouzet/216920f78d62c24fb5ac to your computer and use it in GitHub Desktop.
Save christophercrouzet/216920f78d62c24fb5ac to your computer and use it in GitHub Desktop.
Compute the strides of a n-dimensional array either at compile or run time.
#ifndef STRIDES_H
#define STRIDES_H
#include <cstddef>
#include <m3ta/concatenateintegersequences>
#include <m3ta/integersequence>
#include <m3ta/reverseintegersequence>
enum class StorageOrder {
firstMajor, // generalization of row-major order.
lastMajor // generalization of column-major order.
};
namespace _strides
{
template<
typename T,
StorageOrder T_storageOrder,
std::size_t T_previous,
typename T_Sequence
>
struct Helper;
template<
typename T,
StorageOrder T_storageOrder,
std::size_t T_previous,
std::size_t T_first,
std::size_t ... T_others
>
struct Helper<
T,
T_storageOrder,
T_previous,
m3ta::IntegerSequence<T, T_first, T_others ...>
>
{
using type = m3ta::ConcatenateIntegerSequencesT<
m3ta::IntegerSequence<T, T_first * T_previous>,
typename Helper<
T,
T_storageOrder,
T_first * T_previous,
m3ta::IntegerSequence<T, T_others ...>
>::type
>;
};
template<
typename T,
StorageOrder T_storageOrder,
std::size_t T_previous,
std::size_t T_unique
>
struct Helper<
T,
T_storageOrder,
T_previous,
m3ta::IntegerSequence<T, T_unique>
>
{
using type = m3ta::IntegerSequence<T>;
};
} // namespace _strides.
//- Compile time version.
template<typename T, StorageOrder T_storageOrder, std::size_t ... T_dimensions>
struct CompileTimeStrides;
template<typename T, std::size_t T_first, std::size_t ... T_others>
struct CompileTimeStrides<T, StorageOrder::firstMajor, T_first, T_others ...>
{
using type = m3ta::ConcatenateIntegerSequencesT<
m3ta::ReverseIntegerSequenceT<
typename _strides::Helper<
T,
StorageOrder::firstMajor,
1,
m3ta::ReverseIndexPackT<T_first, T_others ...>
>::type
>,
m3ta::IntegerSequence<T, 1>
>;
};
template<typename T, std::size_t T_first, std::size_t ... T_others>
struct CompileTimeStrides<T, StorageOrder::lastMajor, T_first, T_others ...>
{
using type = m3ta::ConcatenateIntegerSequencesT<
m3ta::IntegerSequence<T, 1>,
typename _strides::Helper<
T,
StorageOrder::lastMajor,
1,
m3ta::IntegerSequence<T, T_first, T_others ...>
>::type
>;
};
template<typename T, StorageOrder T_storageOrder>
struct CompileTimeStrides<T, T_storageOrder>
{
using type = m3ta::IntegerSequence<T>;
};
//- Run-time version.
template<StorageOrder T_storageOrder>
struct RunTimeStrides;
template<>
struct RunTimeStrides<StorageOrder::firstMajor>
{
template<typename T_Shape>
static T_Shape compute(const T_Shape &shape)
{
T_Shape strides;
std::size_t i = shape.size() - 1;
strides[i] = 1;
while (i-- > 0) {
strides[i] = strides[i + 1] * shape[i + 1];
}
return strides;
}
};
template<>
struct RunTimeStrides<StorageOrder::lastMajor>
{
template<typename T_Shape>
static T_Shape compute(const T_Shape &shape)
{
T_Shape strides;
std::size_t i = 0;
strides[i] = 1;
while (i++ < shape.size() - 1) {
strides[i] = strides[i - 1] * shape[i - 1];
}
return strides;
}
};
#endif // STRIDES_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment