Last active
August 29, 2015 14:17
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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