Program Listing for File fix_index.hpp
↰ Return to documentation for file (/tmp/ws/src/proxsuite/include/proxsuite/linalg/veg/internal/fix_index.hpp
)
#ifndef VEG_META_INT_FIX_HPP_7S9Y48TFS
#define VEG_META_INT_FIX_HPP_7S9Y48TFS
#include "proxsuite/linalg/veg/type_traits/tags.hpp"
#include "proxsuite/linalg/veg/internal/std.hpp"
#include "proxsuite/linalg/veg/internal/dbg.hpp"
#include "proxsuite/linalg/veg/internal/prologue.hpp"
namespace proxsuite {
namespace linalg {
namespace veg {
struct Dyn;
template<isize N>
struct Fix;
namespace _detail {
template<typename L, typename R>
struct binary_traits
{
using Add = void;
using Sub = void;
using Mul = void;
using Div = void;
using Mod = void;
using CmpEq = void;
using CmpNEq = void;
using CmpLT = void;
using CmpLE = void;
using CmpGT = void;
using CmpGE = void;
};
namespace idx {
namespace adl {
template<typename T>
struct IdxBase
{};
} // namespace adl
} // namespace idx
namespace _meta {
template<typename T>
struct is_fix : false_type
{};
template<isize N>
struct is_fix<Fix<N>> : true_type
{};
} // namespace _meta
} // namespace _detail
namespace concepts {
VEG_DEF_CONCEPT(typename T,
index,
VEG_CONCEPT(same<T, Dyn>) || _detail::_meta::is_fix<T>::value);
} // namespace concepts
enum struct Ternary : unsigned char
{
no,
maybe,
yes,
};
constexpr auto no = Ternary::no;
constexpr auto maybe = Ternary::maybe;
constexpr auto yes = Ternary::yes;
using no_c = meta::constant<Ternary, Ternary::no>;
using maybe_c = meta::constant<Ternary, Ternary::maybe>;
using yes_c = meta::constant<Ternary, Ternary::yes>;
template<Ternary T>
struct Boolean;
template<Ternary T>
struct Boolean
{
constexpr Boolean() VEG_NOEXCEPT = default;
using type = meta::constant<Ternary, T>;
VEG_INLINE constexpr Boolean(Boolean<maybe> /*b*/,
Unsafe /*tag*/) VEG_NOEXCEPT;
VEG_INLINE constexpr Boolean // NOLINT(hicpp-explicit-conversions)
(Boolean<maybe> b) VEG_NOEXCEPT;
VEG_NODISCARD VEG_INLINE constexpr friend auto operator!(Boolean /*arg*/)
VEG_NOEXCEPT->Boolean<T == yes ? no : yes>
{
return {};
}
VEG_NODISCARD VEG_INLINE explicit constexpr operator bool() const VEG_NOEXCEPT
{
return T == yes;
}
};
template<isize N>
struct Fix : _detail::idx::adl::IdxBase<Fix<N>>
{
constexpr Fix() VEG_NOEXCEPT = default;
VEG_INLINE constexpr Fix(Dyn /*arg*/, Unsafe /*tag*/) VEG_NOEXCEPT;
VEG_INLINE constexpr Fix // NOLINT(hicpp-explicit-conversions)
(Dyn arg) VEG_NOEXCEPT;
VEG_TEMPLATE((isize M),
requires((M != N)),
constexpr Fix,
(/*arg*/, Fix<M>)) = delete;
VEG_NODISCARD VEG_INLINE explicit constexpr operator isize() const
VEG_NOEXCEPT
{
return N;
}
VEG_NODISCARD VEG_INLINE constexpr auto operator+() const VEG_NOEXCEPT->Fix
{
return {};
}
VEG_NODISCARD VEG_INLINE constexpr auto operator-() const
VEG_NOEXCEPT->Fix<-N>
{
return {};
}
#define VEG_OP(Op, Name, TypeName) \
VEG_TEMPLATE((typename R), \
requires(VEG_CONCEPT(index<R>)), \
VEG_NODISCARD VEG_INLINE constexpr auto \
operator Op, \
(b, R)) \
const VEG_NOEXCEPT->typename _detail::binary_traits<Fix, R>::TypeName \
{ \
return _detail::binary_traits<Fix, R>::Name##_fn(*this, b); \
} \
VEG_NOM_SEMICOLON
VEG_OP(+, add, Add);
VEG_OP(-, sub, Sub);
VEG_OP(*, mul, Mul);
#undef VEG_OP
VEG_TEMPLATE(
(typename R),
requires(VEG_CONCEPT(index<R>) &&
VEG_CONCEPT(index<typename _detail::binary_traits<Fix, R>::Div>)),
VEG_NODISCARD VEG_INLINE constexpr auto
operator/,
(b, R))
const VEG_NOEXCEPT->typename _detail::binary_traits<Fix, R>::Div
{
return _detail::binary_traits<Fix, R>::div_fn(*this, b);
}
VEG_TEMPLATE(
(typename R),
requires(VEG_CONCEPT(index<R>) &&
VEG_CONCEPT(index<typename _detail::binary_traits<Fix, R>::Mod>)),
VEG_NODISCARD VEG_INLINE constexpr auto
operator%,
(b, R))
const VEG_NOEXCEPT->typename _detail::binary_traits<Fix, R>::Mod
{
return _detail::binary_traits<Fix, R>::mod_fn(*this, b);
}
#define VEG_CMP(Name, TypeName, Op) \
VEG_TEMPLATE((typename R), \
requires(VEG_CONCEPT(index<R>)), \
VEG_NODISCARD VEG_INLINE constexpr auto \
operator Op, /* NOLINT */ \
(b, R)) \
const VEG_NOEXCEPT->typename _detail::binary_traits<Fix, R>::TypeName \
{ \
return _detail::binary_traits<Fix, R>::cmp_##Name##_fn(*this, b); \
} \
VEG_NOM_SEMICOLON
VEG_CMP(eq, CmpEq, ==);
VEG_CMP(neq, CmpNEq, !=);
VEG_CMP(lt, CmpLT, <);
VEG_CMP(le, CmpLE, <=);
VEG_CMP(gt, CmpGT, >);
VEG_CMP(ge, CmpGE, >=);
#undef VEG_CMP
#undef VEG_CMP
};
namespace _detail {
struct Error
{
constexpr auto operator()(u64 const* fail = nullptr) const VEG_NOEXCEPT->u64
{
return *fail;
}
};
using parser = auto (*)(char, Error) -> u64;
constexpr auto
parse_digit_2(char c, Error e) VEG_NOEXCEPT->u64
{
return (c == '0') ? 0 : (c == '1' ? 1 : e());
}
constexpr auto
parse_digit_8(char c, Error e) VEG_NOEXCEPT->u64
{
return (c >= '0' && c <= '7') ? u64(c - '0') : e();
}
constexpr auto
parse_digit_10(char c, Error e) VEG_NOEXCEPT->u64
{
return (c >= '0' && c <= '9') ? u64(c - '0') : e();
}
constexpr auto
parse_digit_16(char c, Error e) VEG_NOEXCEPT->u64
{
return (c >= '0' && c <= '9') //
? u64(c - '0')
: (c >= 'a' && c <= 'f') //
? u64(c - 'a')
: (c >= 'A' && c <= 'F') //
? u64(c - 'A')
: e();
}
constexpr auto
parse_digit(u64 radix) VEG_NOEXCEPT->parser
{
return radix == 2
? parse_digit_2
: (radix == 8
? parse_digit_8
: (radix == 10 ? parse_digit_10
: (radix == 16 ? parse_digit_16 : nullptr)));
}
constexpr auto
parse_num(char const* str, u64 len, u64 radix, Error e) VEG_NOEXCEPT->u64
{
return (len == 0) ? 0
: radix * parse_num(str, len - 1, radix, e) +
(parse_digit(radix)(str[len - 1], e));
}
constexpr auto
parse_int(char const* str, u64 len, Error e) VEG_NOEXCEPT->u64
{
return (len == 0) //
? e()
: ((str[0] == '0') //
? ((len == 1) //
? 0
: (str[1] == 'b' || str[1] == 'B') //
? parse_num(str + 2, len - 2, 2, e)
: (str[1] == 'x' || str[1] == 'X') //
? parse_num(str + 2, len - 2, 16, e)
: parse_num(str + 1, len - 1, 8, e))
: parse_num(str, len, 10, e));
}
template<char... Chars>
struct char_seq
{
static constexpr char value[] = { Chars... };
};
template<isize N, isize M>
struct binary_traits<Fix<N>, Fix<M>>
{
#define VEG_OP(Name, TypeName, Op) \
using TypeName /* NOLINT(bugprone-macro-parentheses) */ = \
Fix<isize(usize(isize{ N }) Op usize(isize{ M }))>; \
VEG_NODISCARD VEG_INLINE static constexpr auto Name##_fn(Fix<N>, Fix<M>) \
VEG_NOEXCEPT->TypeName \
{ \
return {}; \
} \
static_assert(true, "")
#define VEG_CMP(Name, TypeName, Op) \
using TypeName /* NOLINT(bugprone-macro-parentheses) */ = \
Boolean<(N Op M) ? yes : no>; \
VEG_NODISCARD VEG_INLINE static constexpr auto Name##_fn(Fix<N>, Fix<M>) \
VEG_NOEXCEPT->TypeName \
{ \
return {}; \
} \
static_assert(true, "")
VEG_OP(add, Add, +);
VEG_OP(sub, Sub, -);
VEG_OP(mul, Mul, *);
VEG_CMP(cmp_eq, CmpEq, ==);
VEG_CMP(cmp_neq, CmpNEq, !=);
VEG_CMP(cmp_lt, CmpLT, <);
VEG_CMP(cmp_le, CmpLE, <=);
VEG_CMP(cmp_gt, CmpGT, >);
VEG_CMP(cmp_ge, CmpGE, >=);
using Div = meta::if_t<M == 0, void, Fix<N / (M != 0 ? M : 1)>>;
using Mod = meta::if_t<M == 0, void, Fix<N % (M != 0 ? M : 1)>>;
VEG_NODISCARD VEG_INLINE static constexpr auto div_fn(Fix<N> /*a*/,
Fix<M> /*b*/)
VEG_NOEXCEPT->Div
{
return Div();
}
VEG_NODISCARD VEG_INLINE static constexpr auto mod_fn(Fix<N> /*a*/,
Fix<M> /*b*/)
VEG_NOEXCEPT->Mod
{
return Mod();
}
#undef VEG_OP
#undef VEG_CMP
};
namespace idx {
namespace adl {
} // namespace adl
} // namespace idx
} // namespace _detail
inline namespace literals {
template<char... Chars>
VEG_INLINE constexpr auto operator"" _c() VEG_NOEXCEPT
{
return Fix<_detail::parse_int(
_detail::char_seq<Chars...>::value, sizeof...(Chars), _detail::Error{})>{};
}
} // namespace literals
} // namespace veg
} // namespace linalg
} // namespace proxsuite
#include "proxsuite/linalg/veg/internal/epilogue.hpp"
#endif /* end of include guard VEG_META_INT_FIX_HPP_7S9Y48TFS */