pfor/src/pfor/index/property/monotonic.h

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