pocketpy/3rd/numpy/include/xtl/xmasked_value.hpp
Anurag Bhat 86b4fc623c
Merge numpy to pocketpy (#303)
* Merge numpy to pocketpy

* Add CI

* Fix CI
2024-09-02 16:22:41 +08:00

547 lines
27 KiB
C++

/***************************************************************************
* 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