10 #ifndef INCLUDE_MOLASSEMBLER_TEMPLE_CONSTEXPR_CONTAINERS_H
11 #define INCLUDE_MOLASSEMBLER_TEMPLE_CONSTEXPR_CONTAINERS_H
19 namespace Molassembler {
24 template<
class Function,
typename ...Args>
33 template<
typename,
size_t>
class ArrayType,
38 > constexpr
auto mapImpl(
39 const ArrayType<T, size>& array,
40 UnaryFunction&&
function,
41 std::index_sequence<Inds...>
47 function(array.at(Inds))...
58 template<
typename,
size_t>
class ArrayType,
63 const ArrayType<T, size>& array,
64 UnaryFunction&&
function
66 return Detail::mapImpl(
68 std::forward<UnaryFunction>(
function),
69 std::make_index_sequence<size>{}
84 template<
typename,
size_t>
class ArrayType,
89 const ArrayType<T, size>& array,
91 BinaryFunction&& reduction
93 for(
const auto&
element : array) {
94 init = reduction(init,
element);
108 template<
typename,
size_t>
class ArrayType,
111 > constexpr T
sum(
const ArrayType<T, size>& array) {
114 for(
unsigned i = 0; i < size; ++i) {
125 template<
typename,
size_t>
class ArrayType,
129 > constexpr ArrayType<T, size> iotaHelper(
130 std::index_sequence<Inds...>
132 return ArrayType<T, size> {
static_cast<T
>(Inds)... };
139 template<
typename,
size_t>
class ArrayType,
143 std::is_arithmetic<T>::value,
146 return Detail::iotaHelper<ArrayType, T, size>(
147 std::make_index_sequence<size>()
154 template<
typename,
size_t>
class ArrayType,
159 > constexpr
ArrayType<T, (end - begin)> rangeHelper(
160 std::index_sequence<Inds...>
171 template<
typename,
size_t>
class ArrayType,
176 return Detail::rangeHelper<ArrayType, T, begin, end>(
177 std::make_index_sequence<(end - begin)>()
185 template<
typename,
size_t>
class ArrayType,
192 constexpr ArrayType<T, N1+N2> arrayConcatenateImpl(
193 const ArrayType<T, N1>& a,
194 const ArrayType<T, N2>& b,
195 std::index_sequence<AIndices...> ,
196 std::index_sequence<BIndices...>
208 template<
typename,
size_t>
class ArrayType,
214 const ArrayType<T, N1>& a,
215 const ArrayType<T, N2>& b
217 return Detail::arrayConcatenateImpl(
220 std::make_index_sequence<N1>{},
221 std::make_index_sequence<N2>{}
228 template<
typename,
size_t>
class ArrayType,
230 size_t concatenatedSize
231 > constexpr ArrayType<T, concatenatedSize> concatenateHelper(
232 const ArrayType<T, concatenatedSize>& concatenated
238 template<
typename,
size_t>
class ArrayType,
240 size_t concatenatedSize,
243 > constexpr
auto concatenateHelper(
244 const ArrayType<T, concatenatedSize>& concatenated,
245 const ArrayType<T, curSize>& array,
246 const ArrayType<T, Ns>& ... arrays
248 return concatenateHelper(
261 template<
typename,
size_t>
class ArrayType,
266 const ArrayType<T, N>& startingArray,
267 const ArrayType<T, Ns>& ... remainingArrays
269 return Detail::concatenateHelper(startingArray, remainingArrays...);
277 template<
typename,
size_t>
class ArrayType,
281 const ArrayType<T, size>& a,
282 const ArrayType<T, size>& b
284 for(
unsigned i = 0; i < size; ++i) {
285 if(a.at(i) != b.at(i)) {
301 template<
typename,
size_t>
class ArrayType,
305 > constexpr std::enable_if_t<
309 const ArrayType<T, sizeA>& a,
310 const ArrayType<T, sizeB>& b
312 for(
unsigned i = 0; i < sizeA; ++i) {
313 if(!(a.at(i) < b.at(i))) {
327 template<
typename,
size_t>
class ArrayType,
331 > constexpr std::enable_if_t<
335 const ArrayType<T, sizeA>& ,
336 const ArrayType<T, sizeB>&
347 template<
typename,
size_t>
class ArrayType,
351 > constexpr std::enable_if_t<
355 const ArrayType<T, sizeA>& ,
356 const ArrayType<T, sizeB>&
399 class LessThanPredicate,
401 > constexpr Iter lowerBound(
405 LessThanPredicate predicate
407 using DiffType = decltype(last - bound);
409 std::is_signed<DiffType>::value,
410 "Difference between iterators must be a signed type!"
414 DiffType count = last - bound, step = 0;
421 if(predicate(*it, item)) {
443 class LessThanPredicate = std::less<>
444 > constexpr
typename Container::const_iterator binarySearch(
445 const Container& container,
447 LessThanPredicate predicate = LessThanPredicate()
449 auto bound = lowerBound<T, LessThanPredicate>(
465 if(predicate(item, *bound)) {
466 return container.end();
477 template<
typename,
size_t>
class ArrayType,
480 > constexpr
void inPlaceSwap(
481 ArrayType<T, size>& data,
485 T intermediate = std::move(data.at(b));
486 data.at(b) = std::move(data.at(a));
487 data.at(a) = std::move(intermediate);
495 template<
typename,
size_t>
class ArrayType,
498 > constexpr
void inPlaceReverse(
499 ArrayType<T, size>& data,
500 const unsigned indexFrom,
501 const unsigned indexTo
503 size_t a = indexFrom, b = indexTo;
504 while(a != b && a != --b) {
505 inPlaceSwap(data, a++, b);
518 template<
typename,
size_t>
class ArrayType,
521 > constexpr std::enable_if_t<
524 > inPlaceNextPermutation(
525 ArrayType<T, size>& data,
534 throw "Call parameters to inPlaceNextPermutation make no sense!";
537 size_t i = last - 1, j = 0, k = 0;
544 && data.at(--i) < data.at(j)
551 data.at(i) < data.at(--k)
557 inPlaceSwap(data, i, k);
558 inPlaceReverse(data, j, last);
563 inPlaceReverse(data, first, last);
571 template<
typename,
size_t>
class ArrayType,
574 > constexpr std::enable_if_t<
577 > inPlaceNextPermutation(ArrayType<T, size>& data) {
578 return inPlaceNextPermutation(data, 0, size);
590 template<
typename,
size_t>
class ArrayType,
593 > constexpr std::enable_if_t<
596 > inPlacePreviousPermutation(
597 ArrayType<T, size>& data,
606 throw "Call parameters to inPlaceNextPermutation make no sense!";
609 size_t i = last - 1, j = 0, k = 0;
616 && data.at(j) < data.at(--i)
623 data.at(--k) < data.at(i)
629 inPlaceSwap(data, i, k);
630 inPlaceReverse(data, j, last);
635 inPlaceReverse(data, first, last);
643 template<
typename,
size_t>
class ArrayType,
646 > constexpr std::enable_if_t<
649 > inPlacePreviousPermutation(ArrayType<T, size>& data) {
650 return inPlacePreviousPermutation(data, 0, size);
658 template<
typename,
size_t>
class ArrayType,
666 for(
size_t p = size - 2; p != std::numeric_limits<size_t>::max(); --p) {
667 size_t largerSuccessors = 0;
669 for(
size_t q = p + 1; q <
size; ++q) {
670 if(container.at(p) > container.at(q)) {
675 index += (largerSuccessors * factor);
684 template<
class ContainerType>
685 struct getValueTypeImpl {
686 using type =
typename std::remove_const<
687 typename std::remove_reference<
690 std::declval<ContainerType>()
699 template<
class ContainerType>
700 using getValueType =
typename Detail::getValueTypeImpl<ContainerType>::type;
715 class LessThanComparator = std::less<
716 getValueType<ContainerType>
718 > constexpr
bool isPartiallyOrdered(
719 const ContainerType& container,
720 LessThanComparator comparator = LessThanComparator {}
722 auto leftIter = container.begin();
723 if(leftIter == container.end()) {
727 auto rightIter = leftIter + 1;
729 while(rightIter != container.end()) {
731 if(comparator(*rightIter, *leftIter)) {
755 class LessThanComparator = std::less<
756 getValueType<ContainerType>
758 > constexpr
bool isTotallyOrdered(
759 const ContainerType& container,
760 LessThanComparator comparator = LessThanComparator {}
762 auto leftIter = container.begin();
763 if(leftIter == container.end()) {
767 auto rightIter = leftIter + 1;
770 while(rightIter != container.end()) {
772 if(!comparator(*leftIter, *rightIter)) {
PURITY_STRONG constexpr std::enable_if_t< std::is_arithmetic< T >::value, ArrayType< T, size >> iota()
Iota for any array type.
Definition: Containers.h:145
double element(const PositionCollection &normalizedPositions, const Elements::Rotation &rotation)
Returns the CSM for a Rotation symmetry element along the rotation axis without optimizing the coordi...
Temple::Array< T, size > ArrayType
Definition: Properties.h:143
Defines a set of useful preprocessor macros.
constexpr Get< 0 > first
Calls std::get<0> on any argument it is invoked with.
Definition: Functor.h:123
constexpr T reduce(const ArrayType< T, size > &array, T init, BinaryFunction &&reduction)
Reduce an array-like container with a binary function.
Definition: Containers.h:88
unsigned size(const Shape shape)
Fetch the number of vertices of a shape.
std::result_of_t< Function(Args...)> functionReturnType
Figure out the return type of calling a function.
Definition: Containers.h:25
constexpr bool arraysEqual(const ArrayType< T, size > &a, const ArrayType< T, size > &b)
Array-like container lexicographic equality comparaotr.
Definition: Containers.h:280
constexpr auto map(const ArrayType< T, size > &array, UnaryFunction &&function)
Maps all elements of any array-like container with a unary function.
Definition: Containers.h:62
constexpr T sum(const ArrayType< T, size > &array)
Sum up all elements of an array-like class.
Definition: Containers.h:111
constexpr ArrayType< T,(end-begin)> range()
Range for any array type.
Definition: Containers.h:175
constexpr ArrayType< T, N1+N2 > arrayConcatenate(const ArrayType< T, N1 > &a, const ArrayType< T, N2 > &b)
Concatenation of two instances of an array-like class.
Definition: Containers.h:213
std::size_t permutationIndex(const Container &container)
Calculate the index of permutation of elements in a container.
Definition: Permutations.h:25
constexpr std::enable_if_t< sizeA==sizeB, bool > arraysLess(const ArrayType< T, sizeA > &a, const ArrayType< T, sizeB > &b)
Lexicographical comparison for two instances of an array-like class.
Definition: Containers.h:308
#define PURITY_STRONG
Definition: Preprocessor.h:65