| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546 |
- /***************************************************************************
- * Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
- * Martin Renou *
- * Copyright (c) QuantStack *
- * *
- * Distributed under the terms of the BSD 3-Clause License. *
- * *
- * The full license is in the file LICENSE, distributed with this software. *
- ****************************************************************************/
- #ifndef XTL_XMASKED_VALUE_HPP
- #define XTL_XMASKED_VALUE_HPP
- #include "xmasked_value_meta.hpp"
- #include "xtype_traits.hpp"
- namespace xtl
- {
- template <class T>
- inline xmasked_value<T, bool> masked() noexcept
- {
- return xmasked_value<T, bool>(T(0), false);
- }
- /****************************
- * xmasked_value declaration *
- *****************************/
- template <class T, class B>
- class xmasked_value
- {
- public:
- using self_type = xmasked_value<T, B>;
- using value_type = T;
- using flag_type = B;
- template <class T1, class B1>
- constexpr xmasked_value(T1&& value, B1&& flag);
- template <class T1>
- constexpr xmasked_value(T1&& value);
- explicit constexpr xmasked_value();
- inline operator value_type() {
- return m_value;
- }
- std::add_lvalue_reference_t<T> value() & noexcept;
- std::add_lvalue_reference_t<std::add_const_t<T>> value() const & noexcept;
- std::conditional_t<std::is_reference<T>::value, apply_cv_t<T, std::decay_t<T>>&, std::decay_t<T>> value() && noexcept;
- std::conditional_t<std::is_reference<T>::value, const std::decay_t<T>&, std::decay_t<T>> value() const && noexcept;
- std::add_lvalue_reference_t<B> visible() & noexcept;
- std::add_lvalue_reference_t<std::add_const_t<B>> visible() const & noexcept;
- std::conditional_t<std::is_reference<B>::value, apply_cv_t<B, std::decay_t<B>>&, std::decay_t<B>> visible() && noexcept;
- std::conditional_t<std::is_reference<B>::value, const std::decay_t<B>&, std::decay_t<B>> visible() const && noexcept;
- template <class T1, class B1>
- bool equal(const xmasked_value<T1, B1>& rhs) const noexcept;
- template <class T1, XTL_DISALLOW(is_xmasked_value<T1>)>
- bool equal(const T1& rhs) const noexcept;
- template <class T1, class B1>
- void swap(xmasked_value<T1, B1>& other);
- #define DEFINE_ASSIGN_OPERATOR(OP) \
- template <class T1> \
- inline xmasked_value& operator OP(const T1& rhs) \
- { \
- if (m_visible) \
- { \
- m_value OP rhs; \
- } \
- return *this; \
- } \
- \
- template <class T1, class B1> \
- inline xmasked_value& operator OP(const xmasked_value<T1, B1>& rhs) \
- { \
- m_visible = m_visible && rhs.visible(); \
- if (m_visible) \
- { \
- m_value OP rhs.value(); \
- } \
- return *this; \
- }
- DEFINE_ASSIGN_OPERATOR(=);
- DEFINE_ASSIGN_OPERATOR(+=);
- DEFINE_ASSIGN_OPERATOR(-=);
- DEFINE_ASSIGN_OPERATOR(*=);
- DEFINE_ASSIGN_OPERATOR(/=);
- DEFINE_ASSIGN_OPERATOR(%=);
- DEFINE_ASSIGN_OPERATOR(&=);
- DEFINE_ASSIGN_OPERATOR(|=);
- DEFINE_ASSIGN_OPERATOR(^=);
- #undef DEFINE_ASSIGN_OPERATOR
- private:
- value_type m_value;
- flag_type m_visible;
- };
- /********************************
- * xmasked_value implementation *
- ********************************/
- template <class T, class B>
- template <class T1, class B1>
- inline constexpr xmasked_value<T, B>::xmasked_value(T1&& value, B1&& flag)
- : m_value(std::forward<T1>(value)), m_visible(std::forward<B1>(flag))
- {
- }
- template <class T, class B>
- template <class T1>
- inline constexpr xmasked_value<T, B>::xmasked_value(T1&& value)
- : m_value(std::forward<T1>(value)), m_visible(true)
- {
- }
- template <class T, class B>
- inline constexpr xmasked_value<T, B>::xmasked_value()
- : m_value(0), m_visible(true)
- {
- }
- template <class T>
- inline auto masked_value(T&& val)
- {
- return xmasked_value<T>(std::forward<T>(val));
- }
- template <class T, class B>
- inline auto masked_value(T&& val, B&& mask)
- {
- return xmasked_value<T, B>(std::forward<T>(val), std::forward<B>(mask));
- }
- template <class T, class B>
- inline auto xmasked_value<T, B>::value() & noexcept -> std::add_lvalue_reference_t<T>
- {
- return m_value;
- }
- template <class T, class B>
- inline auto xmasked_value<T, B>::value() const & noexcept -> std::add_lvalue_reference_t<std::add_const_t<T>>
- {
- return m_value;
- }
- template <class T, class B>
- inline auto xmasked_value<T, B>::value() && noexcept -> std::conditional_t<std::is_reference<T>::value, apply_cv_t<T, std::decay_t<T>>&, std::decay_t<T>>
- {
- return m_value;
- }
- template <class T, class B>
- inline auto xmasked_value<T, B>::value() const && noexcept -> std::conditional_t<std::is_reference<T>::value, const std::decay_t<T>&, std::decay_t<T>>
- {
- return m_value;
- }
- template <class T, class B>
- inline auto xmasked_value<T, B>::visible() & noexcept -> std::add_lvalue_reference_t<B>
- {
- return m_visible;
- }
- template <class T, class B>
- inline auto xmasked_value<T, B>::visible() const & noexcept -> std::add_lvalue_reference_t<std::add_const_t<B>>
- {
- return m_visible;
- }
- template <class T, class B>
- inline auto xmasked_value<T, B>::visible() && noexcept -> std::conditional_t<std::is_reference<B>::value, apply_cv_t<B, std::decay_t<B>>&, std::decay_t<B>>
- {
- return m_visible;
- }
- template <class T, class B>
- inline auto xmasked_value<T, B>::visible() const && noexcept -> std::conditional_t<std::is_reference<B>::value, const std::decay_t<B>&, std::decay_t<B>>
- {
- return m_visible;
- }
- template <class T, class B>
- template <class T1, class B1>
- inline bool xmasked_value<T, B>::equal(const xmasked_value<T1, B1>& rhs) const noexcept
- {
- return (!m_visible && !rhs.visible()) || (m_value == rhs.value() && (m_visible && rhs.visible()));
- }
- template <class T, class B>
- template <class T1, check_disallow<is_xmasked_value<T1>>>
- inline bool xmasked_value<T, B>::equal(const T1& rhs) const noexcept
- {
- return m_visible && m_value == rhs;
- }
- template <class T, class B>
- template <class T1, class B1>
- inline void xmasked_value<T, B>::swap(xmasked_value<T1, B1>& other)
- {
- using std::swap;
- swap(m_value, other.m_value);
- swap(m_visible, other.m_visible);
- }
- template <class T1, class B1, class T2, class B2>
- inline bool operator==(const xmasked_value<T1, B1>& lhs, const xmasked_value<T2, B2>& rhs) noexcept
- {
- return lhs.equal(rhs);
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(negation<is_xmasked_value<T1>>)>
- inline bool operator==(const T1& lhs, const xmasked_value<T2, B2>& rhs) noexcept
- {
- return rhs.equal(lhs);
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(negation<is_xmasked_value<T2>>)>
- inline bool operator==(const xmasked_value<T1, B1>& lhs, const T2& rhs) noexcept
- {
- return lhs.equal(rhs);
- }
- template <class T1, class B1, class T2, class B2>
- inline bool operator!=(const xmasked_value<T1, B1>& lhs, const xmasked_value<T2, B2>& rhs) noexcept
- {
- return !lhs.equal(rhs);
- }
- template <class T1, class T2, class B2, XTL_REQUIRES(negation<is_xmasked_value<T1>>)>
- inline bool operator!=(const T1& lhs, const xmasked_value<T2, B2>& rhs) noexcept
- {
- return !rhs.equal(lhs);
- }
- template <class T1, class B1, class T2, XTL_REQUIRES(negation<is_xmasked_value<T2>>)>
- inline bool operator!=(const xmasked_value<T1, B1>& lhs, const T2& rhs) noexcept
- {
- return !lhs.equal(rhs);
- }
- template <class T, class B>
- inline auto operator+(const xmasked_value<T, B>& e) noexcept
- -> xmasked_value<std::decay_t<T>, std::decay_t<B>>
- {
- return xmasked_value<std::decay_t<T>, std::decay_t<B>>(e.value(), e.visible());
- }
- template <class T, class B>
- inline auto operator-(const xmasked_value<T, B>& e) noexcept
- -> xmasked_value<std::decay_t<T>, std::decay_t<B>>
- {
- return xmasked_value<std::decay_t<T>, std::decay_t<B>>(-e.value(), e.visible());
- }
- template <class T, class B>
- inline auto operator~(const xmasked_value<T, B>& e) noexcept
- -> xmasked_value<std::decay_t<T>>
- {
- using value_type = std::decay_t<T>;
- return e.visible() ? masked_value(~e.value()) : masked<value_type>();
- }
- template <class T, class B>
- inline auto operator!(const xmasked_value<T, B>& e) noexcept -> xmasked_value<decltype(!e.value())>
- {
- using return_type = xmasked_value<decltype(!e.value())>;
- using value_type = typename return_type::value_type;
- return e.visible() ? return_type(!e.value()) : masked<value_type>();
- }
- template <class T, class B, class OC, class OT>
- inline std::basic_ostream<OC, OT>& operator<<(std::basic_ostream<OC, OT>& out, xmasked_value<T, B> v)
- {
- if (v.visible())
- {
- out << v.value();
- }
- else
- {
- out << "masked";
- }
- return out;
- }
- template <class T1, class B1, class T2, class B2>
- inline void swap(xmasked_value<T1, B1>& lhs, xmasked_value<T2, B2>& rhs)
- {
- lhs.swap(rhs);
- }
- #define DEFINE_OPERATOR(OP) \
- template <class T1, class B1, class T2, class B2> \
- inline auto operator OP(const xmasked_value<T1, B1>& e1, const xmasked_value<T2, B2>& e2) noexcept \
- -> xmasked_value<promote_type_t<std::decay_t<T1>, std::decay_t<T2>>> \
- { \
- using value_type = promote_type_t<std::decay_t<T1>, std::decay_t<T2>>; \
- return e1.visible() && e2.visible() ? masked_value(e1.value() OP e2.value()) : masked<value_type>(); \
- } \
- \
- template <class T1, class B1, class T2, XTL_REQUIRES(negation<is_xmasked_value<T2>>)> \
- inline auto operator OP(const xmasked_value<T1, B1>& e1, const T2& e2) noexcept \
- -> xmasked_value<promote_type_t<std::decay_t<T1>, std::decay_t<T2>>> \
- { \
- using value_type = promote_type_t<std::decay_t<T1>, std::decay_t<T2>>; \
- return e1.visible() ? masked_value(e1.value() OP e2) : masked<value_type>(); \
- } \
- \
- template <class T1, class T2, class B2, XTL_REQUIRES(negation<is_xmasked_value<T1>>)> \
- inline auto operator OP(const T1& e1, const xmasked_value<T2, B2>& e2) noexcept \
- -> xmasked_value<promote_type_t<std::decay_t<T1>, std::decay_t<T2>>> \
- { \
- using value_type = promote_type_t<std::decay_t<T1>, std::decay_t<T2>>; \
- return e2.visible() ? masked_value(e1 OP e2.value()) : masked<value_type>(); \
- }
- #define DEFINE_BOOL_OPERATOR(OP) \
- template <class T1, class B1, class T2, class B2> \
- inline auto operator OP(const xmasked_value<T1, B1>& e1, const xmasked_value<T2, B2>& e2) noexcept \
- -> xmasked_value<decltype(e1.value() OP e2.value())> \
- { \
- return e1.visible() && e2.visible() ? \
- masked_value(e1.value() OP e2.value()) : \
- masked<decltype(e1.value() OP e2.value())>(); \
- } \
- \
- template <class T1, class B1, class T2, XTL_REQUIRES(negation<is_xmasked_value<T2>>)> \
- inline auto operator OP(const xmasked_value<T1, B1>& e1, const T2& e2) noexcept \
- -> xmasked_value<decltype(e1.value() OP e2)> \
- { \
- return e1.visible() ? masked_value(e1.value() OP e2) : masked<decltype(e1.value() OP e2)>(); \
- } \
- \
- template <class T1, class T2, class B2, XTL_REQUIRES(negation<is_xmasked_value<T1>>)> \
- inline auto operator OP(const T1& e1, const xmasked_value<T2, B2>& e2) noexcept \
- -> xmasked_value<decltype(e1 OP e2.value())> \
- { \
- return e2.visible() ? masked_value(e1 OP e2.value()) : masked<decltype(e1 OP e2.value())>(); \
- }
- #define DEFINE_UNARY_OPERATOR(OP) \
- template <class T, class B> \
- inline xmasked_value<std::decay_t<T>> OP(const xmasked_value<T, B>& e) \
- { \
- using std::OP; \
- return e.visible() ? masked_value(OP(e.value())) : masked<std::decay_t<T>>(); \
- }
- #define DEFINE_UNARY_BOOL_OPERATOR(OP) \
- template <class T, class B> \
- inline auto OP(const xmasked_value<T, B>& e) \
- { \
- using std::OP; \
- return e.visible() ? masked_value(OP(e.value())) : masked<decltype(OP(e.value()))>(); \
- }
- #define DEFINE_BINARY_OPERATOR(OP) \
- template <class T1, class B1, class T2, class B2> \
- inline auto OP(const xmasked_value<T1, B1>& e1, const xmasked_value<T2, B2>& e2) \
- { \
- using std::OP; \
- return e1.visible() && e2.visible() ? \
- masked_value(OP(e1.value(), e2.value())) : \
- masked<decltype(OP(e1.value(), e2.value()))>(); \
- } \
- \
- template <class T1, class B1, class T2> \
- inline auto OP(const xmasked_value<T1, B1>& e1, const T2& e2) \
- { \
- using std::OP; \
- return e1.visible() ? masked_value(OP(e1.value(), e2)) : masked<decltype(OP(e1.value(), e2))>(); \
- } \
- \
- template <class T1, class T2, class B2> \
- inline auto OP(const T1& e1, const xmasked_value<T2, B2>& e2) \
- { \
- using std::OP; \
- return e2.visible() ? masked_value(OP(e1, e2.value())) : masked<decltype(OP(e1, e2.value()))>(); \
- }
- #define DEFINE_TERNARY_OPERATOR_MMM(OP) \
- template <class T1, class B1, class T2, class B2, class T3, class B3> \
- inline auto OP(const xmasked_value<T1, B1>& e1, const xmasked_value<T2, B2>& e2, const xmasked_value<T3, B3>& e3) \
- { \
- using std::OP; \
- return (e1.visible() && e2.visible() && e3.visible()) ? \
- masked_value(OP(e1.value(), e2.value(), e3.value())) : \
- masked<decltype(OP(e1.value(), e2.value(), e3.value()))>(); \
- }
- #define DEFINE_TERNARY_OPERATOR_MMT(OP) \
- template <class T1, class B1, class T2, class B2, class T3> \
- inline auto OP(const xmasked_value<T1, B1>& e1, const xmasked_value<T2, B2>& e2, const T3& e3) \
- { \
- using std::OP; \
- return (e1.visible() && e2.visible()) ? \
- masked_value(OP(e1.value(), e2.value(), e3)) : \
- masked<decltype(OP(e1.value(), e2.value(), e3))>(); \
- }
- #define DEFINE_TERNARY_OPERATOR_MTM(OP) \
- template <class T1, class B1, class T2, class T3, class B3> \
- inline auto OP(const xmasked_value<T1, B1>& e1, const T2& e2, const xmasked_value<T3, B3>& e3) \
- { \
- using std::OP; \
- return (e1.visible() && e3.visible()) ? \
- masked_value(OP(e1.value(), e2, e3.value())) : \
- masked<decltype(OP(e1.value(), e2, e3.value()))>(); \
- }
- #define DEFINE_TERNARY_OPERATOR_TMM(OP) \
- template <class T1, class T2, class B2, class T3, class B3> \
- inline auto OP(const T1& e1, const xmasked_value<T2, B2>& e2, const xmasked_value<T3, B3>& e3) \
- { \
- using std::OP; \
- return (e2.visible() && e3.visible()) ? \
- masked_value(OP(e1, e2.value(), e3.value())) : \
- masked<decltype(OP(e1, e2.value(), e3.value()))>(); \
- }
- #define DEFINE_TERNARY_OPERATOR_TTM(OP) \
- template <class T1, class T2, class T3, class B3> \
- inline auto OP(const T1& e1, const T2& e2, const xmasked_value<T3, B3>& e3) \
- { \
- using std::OP; \
- return e3.visible() ? \
- masked_value(OP(e1, e2, e3.value())) : \
- masked<decltype(OP(e1, e2, e3.value()))>(); \
- }
- #define DEFINE_TERNARY_OPERATOR_TMT(OP) \
- template <class T1, class T2, class B2, class T3> \
- inline auto OP(const T1& e1, const xmasked_value<T2, B2>& e2, const T3& e3) \
- { \
- using std::OP; \
- return e2.visible() ? \
- masked_value(OP(e1, e2.value(), e3)) : \
- masked<decltype(OP(e1, e2.value(), e3))>(); \
- }
- #define DEFINE_TERNARY_OPERATOR_MTT(OP) \
- template <class T1, class B1, class T2, class T3> \
- inline auto OP(const xmasked_value<T1, B1>& e1, const T2& e2, const T3& e3) \
- { \
- using std::OP; \
- return e1.visible() ? \
- masked_value(OP(e1.value(), e2, e3)) : \
- masked<decltype(OP(e1.value(), e2, e3))>(); \
- }
- #define DEFINE_TERNARY_OPERATOR(OP) \
- DEFINE_TERNARY_OPERATOR_MMM(OP) \
- \
- DEFINE_TERNARY_OPERATOR_MMT(OP) \
- DEFINE_TERNARY_OPERATOR_MTM(OP) \
- DEFINE_TERNARY_OPERATOR_TMM(OP) \
- DEFINE_TERNARY_OPERATOR_TTM(OP) \
- DEFINE_TERNARY_OPERATOR_TMT(OP) \
- DEFINE_TERNARY_OPERATOR_MTT(OP)
- DEFINE_OPERATOR(+);
- DEFINE_OPERATOR(-);
- DEFINE_OPERATOR(*);
- DEFINE_OPERATOR(/);
- DEFINE_OPERATOR(%);
- DEFINE_BOOL_OPERATOR(||);
- DEFINE_BOOL_OPERATOR(&&);
- DEFINE_OPERATOR(&);
- DEFINE_OPERATOR(|);
- DEFINE_OPERATOR(^);
- DEFINE_BOOL_OPERATOR(<);
- DEFINE_BOOL_OPERATOR(<=);
- DEFINE_BOOL_OPERATOR(>);
- DEFINE_BOOL_OPERATOR(>=);
- DEFINE_UNARY_OPERATOR(abs)
- DEFINE_UNARY_OPERATOR(fabs)
- DEFINE_UNARY_OPERATOR(exp)
- DEFINE_UNARY_OPERATOR(exp2)
- DEFINE_UNARY_OPERATOR(expm1)
- DEFINE_UNARY_OPERATOR(log)
- DEFINE_UNARY_OPERATOR(log10)
- DEFINE_UNARY_OPERATOR(log2)
- DEFINE_UNARY_OPERATOR(log1p)
- DEFINE_UNARY_OPERATOR(sqrt)
- DEFINE_UNARY_OPERATOR(cbrt)
- DEFINE_UNARY_OPERATOR(sin)
- DEFINE_UNARY_OPERATOR(cos)
- DEFINE_UNARY_OPERATOR(tan)
- DEFINE_UNARY_OPERATOR(acos)
- DEFINE_UNARY_OPERATOR(asin)
- DEFINE_UNARY_OPERATOR(atan)
- DEFINE_UNARY_OPERATOR(sinh)
- DEFINE_UNARY_OPERATOR(cosh)
- DEFINE_UNARY_OPERATOR(tanh)
- DEFINE_UNARY_OPERATOR(acosh)
- DEFINE_UNARY_OPERATOR(asinh)
- DEFINE_UNARY_OPERATOR(atanh)
- DEFINE_UNARY_OPERATOR(erf)
- DEFINE_UNARY_OPERATOR(erfc)
- DEFINE_UNARY_OPERATOR(tgamma)
- DEFINE_UNARY_OPERATOR(lgamma)
- DEFINE_UNARY_OPERATOR(ceil)
- DEFINE_UNARY_OPERATOR(floor)
- DEFINE_UNARY_OPERATOR(trunc)
- DEFINE_UNARY_OPERATOR(round)
- DEFINE_UNARY_OPERATOR(nearbyint)
- DEFINE_UNARY_OPERATOR(rint)
- DEFINE_UNARY_BOOL_OPERATOR(isfinite)
- DEFINE_UNARY_BOOL_OPERATOR(isinf)
- DEFINE_UNARY_BOOL_OPERATOR(isnan)
- DEFINE_BINARY_OPERATOR(fmod)
- DEFINE_BINARY_OPERATOR(remainder)
- DEFINE_BINARY_OPERATOR(fmax)
- DEFINE_BINARY_OPERATOR(fmin)
- DEFINE_BINARY_OPERATOR(fdim)
- DEFINE_BINARY_OPERATOR(pow)
- DEFINE_BINARY_OPERATOR(hypot)
- DEFINE_BINARY_OPERATOR(atan2)
- DEFINE_TERNARY_OPERATOR(fma)
- #undef DEFINE_TERNARY_OPERATOR
- #undef DEFINE_TERNARY_OPERATOR_MMM
- #undef DEFINE_TERNARY_OPERATOR_MMT
- #undef DEFINE_TERNARY_OPERATOR_MTM
- #undef DEFINE_TERNARY_OPERATOR_TMM
- #undef DEFINE_TERNARY_OPERATOR_TTM
- #undef DEFINE_TERNARY_OPERATOR_TMT
- #undef DEFINE_TERNARY_OPERATOR_MTT
- #undef DEFINE_BINARY_OPERATOR
- #undef DEFINE_UNARY_OPERATOR
- #undef DEFINE_UNARY_BOOL_OPERATOR
- #undef DEFINE_OPERATOR
- #undef DEFINE_BOOL_OPERATOR
- }
- #endif
|