135 lines
3.0 KiB
C++
135 lines
3.0 KiB
C++
#ifndef PFOR_PFOR_INDEX_PROPERTY_MONOTONIC_H
|
|
#define PFOR_PFOR_INDEX_PROPERTY_MONOTONIC_H
|
|
|
|
#include "../../mp/pack.h"
|
|
#include "../index.h"
|
|
#include "traits.h"
|
|
|
|
#include "injective.h"
|
|
|
|
namespace pfor {
|
|
namespace index {
|
|
|
|
namespace prop {
|
|
|
|
struct Monotonic;
|
|
struct Inc;
|
|
struct Dec;
|
|
struct Strict;
|
|
|
|
using StrictInc = Pack<Monotonic, Strict, Inc>;
|
|
using StrictDec = Pack<Monotonic, Strict, Dec>;
|
|
|
|
}
|
|
|
|
template<typename L, typename R>
|
|
struct ComputeProperty<prop::Monotonic, op::Minus, L, R> {
|
|
using type = Pack<prop::Monotonic>;
|
|
};
|
|
|
|
template<typename L, typename R>
|
|
struct ComputeProperty<prop::Inc, op::Minus, L, R> {
|
|
using type = Pack<prop::Dec>;
|
|
};
|
|
|
|
template<typename L, typename R>
|
|
struct ComputeProperty<prop::Dec, op::Minus, L, R> {
|
|
using type = Pack<prop::Inc>;
|
|
};
|
|
|
|
template<typename L, typename R>
|
|
struct ComputeProperty<prop::Strict, op::Minus, L, R> {
|
|
using type = Pack<prop::Strict>;
|
|
};
|
|
|
|
template<typename L, typename R>
|
|
struct ComputeProperty<prop::Inc, op::Addition, L, R> {
|
|
using type = If<containsProperties<L, prop::StrictInc> and containsProperties<R, prop::StrictInc>,
|
|
prop::StrictInc,
|
|
Pack<>
|
|
>;
|
|
};
|
|
|
|
template<typename L, typename R>
|
|
struct ComputeProperty<prop::Dec, op::Addition, L, R> {
|
|
using type = If<containsProperties<L, prop::StrictDec> and containsProperties<R, prop::StrictDec>,
|
|
prop::StrictDec,
|
|
Pack<>
|
|
>;
|
|
};
|
|
|
|
template<typename L, typename R>
|
|
struct ComputeProperty<prop::Inc, op::Subtraction, L, R> {
|
|
using type = If<containsProperties<L, prop::StrictInc> and containsProperties<R, prop::StrictDec>,
|
|
prop::StrictInc,
|
|
Pack<>
|
|
>;
|
|
};
|
|
|
|
template<typename L, typename R>
|
|
struct ComputeProperty<prop::Dec, op::Subtraction, L, R> {
|
|
using type = If<containsProperties<L, prop::StrictDec> and containsProperties<R, prop::StrictInc>,
|
|
prop::StrictDec,
|
|
Pack<>
|
|
>;
|
|
};
|
|
|
|
template<typename S>
|
|
struct InferProperty<prop::Monotonic, S> {
|
|
using type = If<containsProperties<S, Pack<prop::Strict>>,
|
|
Pack<prop::Injective>,
|
|
Pack<>
|
|
>;
|
|
};
|
|
|
|
/**
|
|
* @brief tags an index expression as strictly increasing
|
|
*/
|
|
template<typename Expr, typename P>
|
|
auto strictinc(IndexImpl<Expr, P>) {
|
|
return IndexImpl<Expr, AddProperties<P, prop::StrictInc>>{};
|
|
}
|
|
|
|
/**
|
|
* @brief tests if an index has strict inc property
|
|
*
|
|
* @param Index an index
|
|
*
|
|
* @return true if Index is strictly increasing
|
|
*/
|
|
template<typename Index>
|
|
struct IsStrictInc {
|
|
static constexpr bool value = hasProperties<Index, prop::StrictInc>;
|
|
};
|
|
|
|
template<typename Index>
|
|
constexpr bool isStrictInc = IsStrictInc<Index>::value;
|
|
|
|
/**
|
|
* @brief tags an index expression as strictly decreasing
|
|
*/
|
|
template<typename Expr, typename P>
|
|
auto strictdec(IndexImpl<Expr, P>) {
|
|
return IndexImpl<Expr, AddProperties<P, prop::StrictDec>>{};
|
|
}
|
|
|
|
/**
|
|
* @brief tests if an index has strict dec property
|
|
*
|
|
* @param Index an index
|
|
*
|
|
* @return true if Index is strictly decreasing
|
|
*/
|
|
template<typename Index>
|
|
struct IsStrictDec {
|
|
static constexpr bool value = hasProperties<Index, prop::StrictDec>;
|
|
};
|
|
|
|
template<typename Index>
|
|
constexpr bool isStrictDec = IsStrictDec<Index>::value;
|
|
|
|
}
|
|
}
|
|
|
|
#endif
|