LoginSignup
2
2

More than 5 years have passed since last update.

Cranberries Interval Library Ver. 3.0.0 Release Note

Posted at

Cranberries Interval Library Ver. 3.0.0 Release Note

New Features

New functions

Summary

Add 10 functions.
See bellow.

New functions list

rad
rad is radian of interval. " (upper_bound - lower_bound) / 2 ".
middle
middle is middle point of interval. Same as mid. "(lower_bound + upper_bound)/2".
mig
mig returns minimum absolute value of interval.
mag
mag returns maximum absolute value of interval.
norm
Same as mag.
in
in(T x, interval <T> I) returns true if I includes x. Others return false.
subset
subset(interval<T> I, interval<T> J) returns true if J includes I. Others return false.
proper_subset
proper_subset(interval<T> I, interval\ J) returns true if I is proper subset of J. Others return false.
overlap
overlap(interval<T> I, interval<T> J) returns true if I ∩ J ≠ ∅. Others return false.
intersect
intersect(interval<T> I, interval<T> J) returns I ∩ J. Never use if I ∩ J = ∅.

Definition

    template < typename T >
    constexpr T interval<T>::rad() const
    {
        return pimpl->upper() - pimpl->lower() / static_cast<T>(2.0L);
    }

    template < typename T >
    constexpr T interval<T>::norm() const
    {
        using std::abs;
        auto&& l = abs(pimpl->lower());
        auto&& r = abs(pimpl->upper());
        return l < r ? r : l;
    }

    template < typename T >
    constexpr T interval<T>::mag() const
    {
        using std::abs;
        auto&& l = abs(pimpl->lower());
        auto&& r = abs(pimpl->upper());
        return l < r ? r : l;
    }

    template < typename T >
    constexpr T interval<T>::mig() const
    {
        using std::abs;
        auto&& l = abs(pimpl->lower());
        auto&& r = abs(pimpl->upper());
        return l < r ? l : r;
    }

    template < typename T >
    constexpr bool in(T&& x, interval<T> const& y)
    {
        return y.lower() < x && x < y.upper() ? true : false;
    }

    template < typename T >
    constexpr bool subset(interval<T> const& x, interval<T> const& y)
    {
        return y.lower() <= x.lower() && x.lower() <= y.upper() ? true : false;
    }

    template < typename T >
    constexpr bool proper_subset(interval<T> const& x, interval<T> const& y)
    {
        return y.lower() < x.lower() && x.lower() < y.upper() ? true : false;
    }

    template < typename T >
    constexpr bool overlap(interval<T> const& x, interval<T> const& y)
    {
        return x.lower() < y.upper() || y.lower() < x.upper() ? true : false;
    }

    template < typename T >
    constexpr interval<T> intersect(interval<T> const& x, interval<T> const& y)
    {
        if (x.lower() < y.lower() && y.upper() < x.upper()) {
            return interval<T>(y);
        }
        else if (y.lower() < x.lower() && x.upper() < y.upper()) {
            return interval<T>(x);
        }
        else if (x.lower() < y.upper()) {
            interval<T>{ x.lower(), y.upper() };
        }
        else if (y.lower() < x.upper()) {
            interval<T>{ y.lower(), x.upper() };
        }
        else {
            CRANBERRIES_THROW_INVALID_ARGUMENT_ERROR(x and y do not overlap each other)
        }
    }

Constants


Summary

Add constants and interval_constants as constexpr functions.
It includes Math Constants and Physics Constants.
Physics constants are defined The International System of Units.
Physics constants considered standard uncertainty.
It allows to compute with standard uncertainty using interval arithmetic.

Constants List

Math Constants

max

define as max<T>() .
constants::max<T>() returns std::numeric_limits<T>::max().
constants::max<interval<T>>() returns interval<T>{ constants::max<T>(), constants::max<T>() }


zero

define as zero<T>() .
constants::zero<T>() returns static_cast<T>(0.0L).
constants::max<interval<T>>() returns interval<T>{ constants::zero<T>(), constants::zero<T>() }


one

define as one<T>() .
constants::one<T>() returns static_cast<T>(1.0L).
constants::one<interval<T>>() returns interval<T>{ constants::one<T>(), constants::one<T>() }


\pi 

The ratio of the circumference of a circle to its diameter.

define as pi<T>() .
constants::pi<T>() returns static_cast<T>(3.141592653589793238462643383279L).
constants::pi<interval<T>>() returns interval<T>{ constants::pi<T>(), constants::pi<T>() }


e

Base of natural logarithm.

define as e<T>() .
constants::e<T>() returns static_cast<T>(2.718281828459045235360287471352L).
constants::e<interval<T>>() returns interval<T>{ constants::<T>(), constants::<T>() }


ln2(log_e 2)

define as ln2<T>() .
constants::ln2<T>() returns static_cast<T>(0.693147180559945309417232121458L).
constants::<interval<T>>() returns interval<T>{ constants::e<T>(), constants::e<T>() }


ln10(log_e 10)

define as ln10<T>() .
constants::ln10<T>() returns static_cast<T>(2.302585092994045684017991454684L).
constants::ln10<interval<T>>() returns interval<T>{ constants::ln10<T>(), constants::ln10<T>() }


\phi

Golden ratio.

define as golden<T>() .
constants::golden<T>() returns static_cast<T>(1.61803398874989484820458683436563811L).
constants::golden<interval<T>>() returns interval<T>{ constants::golden<T>(), constants::golden<T>() }


Physics Constants


c_0 = 299792458  [m \cdot s^{-1}]

Velocity of light in vacuum.

define as c_0<T>() .
constants::c_0<T>() returns static_cast<T>(299792458L).
constants::c_0<interval<T>>() returns interval<T>{ constants::c_0<T>(), constants::c_0<T>() }


\mu_0 = 12.566 370 614...×10^{−7} [N \cdot A^{−2}]

Permeability in vacuum.

define as mu_0<T>() .
constants::mu_0<T>() returns static_cast<T>(4.0L*pi<T>()*1E-7L).
constants::mu_0<interval<T>>() returns interval<T>{ constants::mu_0<T>(), constants::mu_0<T>() }


\epsilon_0 = 8.854 187 817...×10^{−12} [F \cdot m^{−1}]

Permittivity of vacuum.

define as epsilon_0<T>() .
constants::epsilon_0<T>() returns static_cast<T>(8.854187817L).
constants::epsilon_0<interval<T>>() returns interval<T>{ constants::epsilon_0<T>(), constants::epsilon_0<T>() }


Z_0 = \mu_0 \cdot c_0 = 376.730 313 461... [Ω]

Impedance of free space.

define as z_0<T>() .
constants::z_0<T>() returns static_cast<T>(376.730313461L).
constants::x_0<interval<T>>() returns interval<T>{ constants::z_0<T>(), constants::z_0<T>() }


G = 6.67408(31)×10^{−11} [ N \cdot m^{2} \cdot kg^{−2}  ]

Gravitational constant.

define as g<T>() .
constants::g<T>() returns static_cast<T>(6.67408E-11L).
constants::g<interval<T>>() returns interval<T>{ static_cast<T>(6.67377E-11L), static_cast<T>(6.67439E-11L) }


h = 6.626070040(81)×10^{−34} [ J \cdot s ]

Planck constant.

define as planck<T>() .
constants::planck<T>() returns static_cast<T>(6.626070040E-34L).
constants::planck<interval<T>>() returns interval<T>{ static_cast<T>(6.626069959E-34L), static_cast<T>(6.626070121E-34L) }


\hbar = 6.626070040(81)×10^{−34} [ J \cdot s ]   

Dirac constants.

define as dirac<T>() .
constants::dirac<T>() returns static_cast<T>(1.054571800E-34L).
constants::dirac<interval<T>>() returns interval<T>{ static_cast<T>(1.054571753E-34L), static_cast<T>(1.054571847E-34L) }


e = 1.6021766208(98)×10^{−19} [ C ]  

Elementary charge.

define as <T>() .
constants::<T>() returns static_cast<T>(1.6021766208E-19L).
constants::<interval<T>>() returns interval<T>{ static_cast<T>(1.6021766110E-19L), static_cast<T>(1.6021766306E-19L) }


\phi_0 = \frac{h}{2e} = 2.067833831(13)×10^{−15} [ Wb ]

Flux quantum.

define as phi_0<T>() .
constants::phi_0<T>() returns static_cast<T>(2.067833831E-15L).
constants::phi_0<interval<T>>() returns interval<T>{ static_cast<T>(2.067833818E-15L), static_cast<T>(2.067833844E-15L) }


G_0 = \frac{2e^{2}}{h} = 7.7480917310(18)×10^{−5} [ S ]

Conductance quantum.

define as g_0<T>() .
constants::g_0<T>() returns static_cast<T>(7.7480917310E-5L).
constants::g_0<interval<T>>() returns interval<T>{ static_cast<T>(7.7480917292E-5L), static_cast<T>(7.7480917328E-5L) }


R_0 = \frac{h}{2e^{2}} = 12906.4037278(29) [ Ω ]

Resistance quantum.

define as r_0<T>() .
constants::r_0<T>() returns static_cast<T>(12906.4037278L).
constants::r_0<interval<T>>() returns interval<T>{ static_cast<T>(12906.4037249L), static_cast<T>(12906.4037307L) }


How to Use


namespace c = Cranberries::constants ;

// Normal double arithmetic
auto a = 3.0 * c::g<double>() ;

// Considering standard uncertainty
auto b = 3.0 * c::g<interval<double>>() ;

Definition


    namespace constants {

        template < typename T >
        constexpr auto pi() -> decltype(static_cast<T>(3.141592653589793238462643383279L)) 
        { 
            return static_cast<T>(3.141592653589793238462643383279L);
        }

        template < typename T >
        constexpr auto e() -> decltype(static_cast<T>(2.718281828459045235360287471352L))
        { 
            return static_cast<T>(2.718281828459045235360287471352L); 
        }

        template < typename T >
        constexpr auto ln2() -> decltype(static_cast<T>(0.693147180559945309417232121458L))
        {
            return static_cast<T>(0.693147180559945309417232121458L);
        }

        template < typename T >
        constexpr auto ln10() -> decltype(static_cast<T>(2.302585092994045684017991454684L))
        {
            return static_cast<T>(2.302585092994045684017991454684L);
        }

        template < typename T >
        constexpr auto golden() -> decltype(static_cast<T>(1.61803398874989484820458683436563811L))
        {
            return static_cast<T>(1.61803398874989484820458683436563811L);
        }

        template < typename T >
        constexpr auto c_0() -> decltype(static_cast<T>(299792458L))
        {
            return static_cast<T>(299792458L);
        }

        template < typename T >
        constexpr auto mu_0() -> decltype(static_cast<T>(4.0L*pi<T>()*1E-7L))
        {
            return static_cast<T>(4.0L*pi<T>()*1E-7L);
        }

        template < typename T >
        constexpr auto epsilon_0() -> decltype(static_cast<T>(8.854187817L))
        {
            return static_cast<T>(8.854187817L);
        }

        template < typename T >
        constexpr auto z_0() -> decltype(static_cast<T>(376.730313461L))
        {
            return static_cast<T>(376.730313461L);
        }

        template < typename T >
        constexpr auto g() -> decltype(static_cast<T>(6.67408E-11L))
        {
            return static_cast<T>(6.67408E-11L);
        }

        template < typename T >
        constexpr auto planck() -> decltype(static_cast<T>(6.626070040E-34L))
        {
            return static_cast<T>(6.626070040E-34L);
        }

        template < typename T >
        constexpr auto dirac() -> decltype(static_cast<T>(1.054571800E-34L))
        {
            return static_cast<T>(1.054571800E-34L);
        }

        template < typename T >
        constexpr auto electron() -> decltype(static_cast<T>(1.6021766208E-19L))
        {
            return static_cast<T>(1.6021766208E-19L);
        }

        template < typename T >
        constexpr auto phi_0() -> decltype(static_cast<T>(2.067833831E-15L))
        {
            return static_cast<T>(2.067833831E-15L);
        }

        template < typename T >
        constexpr auto g_0() -> decltype(static_cast<T>(7.7480917310E-5L))
        {
            return static_cast<T>(7.7480917310E-5L);
        }

        template < typename T >
        constexpr auto r_0() -> decltype(static_cast<T>(12906.4037278L))
        {
            return static_cast<T>(12906.4037278L);
        }

        template < typename T >
        constexpr auto max() -> decltype(std::numeric_limits<T>::max())
        {
            return std::numeric_limits<T>::max();
        }

        template < typename T >
        constexpr auto zero() -> decltype(static_cast<T>(0.0L))
        {
            return static_cast<T>(0.0L);
        }

        template < typename T >
        constexpr auto one() -> decltype(static_cast<T>(1.0L))
        {
            return static_cast<T>(1.0L);
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T pi()
        {
            return interval<U>{ constants::pi<U>(), constants::pi<U>() };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T e()
        {
            return interval<U>{ constants::e<U>(), constants::e<U>() };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T ln2()
        {
            return interval<U>{ constants::ln2<U>(), constants::ln2<U>() };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T ln10()
        {
            return interval<U>{ constants::ln10<U>(), constants::ln10<U>() };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T golden()
        {
            return interval<U>{ constants::golden<U>(), constants::golden<U>() };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T c_0()
        {
            return interval<U>{ constants::c_0<U>(), constants::c_0<U>() };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T mu_0()
        {
            return interval<U>{ constants::mu_0<U>(), constants::mu_0<U>() };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T epsilon_0()
        {
            return interval<U>{ constants::epsilon_0<U>(), constants::epsilon_0<U>() };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T z_0()
        {
            return interval<U>{ constants::z_0<U>(), constants::z_0<U>() };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T g()
        {
            return interval<U>{ static_cast<U>(6.67377E-11L), static_cast<U>(6.67439E-11L) };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T planck()
        {
            return interval<U>{ static_cast<U>(6.626069959E-34L), static_cast<U>(6.626070121E-34L) };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T dirac()
        {
            return interval<U>{ static_cast<U>(1.054571753E-34L), static_cast<U>(1.054571847E-34L) };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T electron()
        {
            return interval<U>{ static_cast<U>(1.6021766110E-19L), static_cast<U>(1.6021766306E-19L) };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T phi_0()
        {
            return interval<U>{ static_cast<U>(2.067833818E-15L), static_cast<U>(2.067833844E-15L) };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T g_0()
        {
            return interval<U>{ static_cast<U>(7.7480917292E-5L), static_cast<U>(7.7480917328E-5L) };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T r_0()
        {
            return interval<U>{ static_cast<U>(12906.4037249L), static_cast<U>(12906.4037307L) };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T max()
        {
            return interval<U>{ constants::max<U>(), constants::max<U>() };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T zero()
        {
            return interval<U>{ constants::zero<U>(), constants::zero<U>() };
        }

        template < typename T, typename U = typename T::value_type >
        constexpr T one()
        {
            return interval<U>{ constants::one<U>(), constants::one<U>() };
        }


    }

Expression Template

Summary

It is feature for lazy evaluation.
Construct Expression and hold structure.
It allows to calculate before or not.

How to Use

interval a{1,2},b{2,3},c{3,4},d{4,5};
{
    // Introducing Expression Template
    using namespace Expression;

    interval<> hoge{};

    // Construction Expression
    // Use auto
    auto expr = sub_(add_(max_(sin_(a), b), multi_(a, max_(a, b, c, sin_(a)))), min_(pow_(c, 2), div_(erf_(d), a)));

    hoge = expr ; // Able to assign to interval

    // Also available compound assign operator
    hoge += expr ;
    hoge -= expr ;
    hoge *= expr ;
    hoge /= expr ;

    // Or can call member func eval() to get result of Expression.
    cout << expr.eval() << endl;
    cout << hoge << endl;
}

Definition

    template< typename T >
    class is_expr
    {
    private:
        template< typename U >
        static auto check(U v) -> decltype(v.is_expr(), std::true_type());
        static auto check(...) -> decltype(std::false_type());
    public:
        typedef decltype(check(std::declval<T>())) type;
        static bool const value = type::value;
    };

    template< typename T >
    class is_interval
    {
    private:
        template< typename U >
        static auto check(U v) -> decltype(v.is_interval(), std::true_type());
        static auto check(...) -> decltype(std::false_type());
    public:
        typedef decltype(check(std::declval<T>())) type;
        static bool const value = type::value;
    };

    template < typename T >
    struct Val
    {
        T value;
    public:
        void is_expr() {};
        typedef T type;
        Val()
            :value(T()) {}
        Val(T&& v)
            : value(std::forward<T>(v)) {}

        T operator[](int)
        {
            return value;
        }
    };

    template < typename T >
    Val<T> val(T&& x)
    {
        return Val<T>(std::forward<T>(x));
    }

    template <typename T, int F = std::is_class<T>::value >
    struct Expr
    {
        typedef Val<T> Ref;
    };

    template <typename T>
    struct Expr<T, true>
    {
        typedef T Ref;
    };



    struct Add;
    struct Sub;
    struct Multi;
    struct Div;
    struct Max;
    struct Min;
    struct Pow;


    template < typename T1, typename T2, typename Op, int F = is_expr<T1>::value + (is_expr<T2>::value << 1) >
    struct promotion;

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Add, 0>
    {
        typedef decltype(std::declval<T1>() + std::declval<T2>()) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Add, 1>
    {
        typedef decltype(std::declval<typename T1::type>() + std::declval<T2>()) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Add, 2>
    {
        typedef decltype(std::declval<T1>() + std::declval<typename T2::type>()) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Add, 3>
    {
        typedef decltype(std::declval<typename T1::type>() + std::declval<typename T2::type>()) type;
    };


    template < typename T1, typename T2 >
    struct promotion<T1, T2, Sub, 0>
    {
        typedef decltype(std::declval<T1>() - std::declval<T2>()) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Sub, 1>
    {
        typedef decltype(std::declval<typename T1::type>() - std::declval<T2>()) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Sub, 2>
    {
        typedef decltype(std::declval<T1>() - std::declval<typename T2::type>()) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Sub, 3>
    {
        typedef decltype(std::declval<typename T1::type>() - std::declval<typename T2::type>()) type;
    };
    template < typename T1, typename T2 >
    struct promotion<T1, T2, Multi, 0>
    {
        typedef decltype(std::declval<T1>() * std::declval<T2>()) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Multi, 1>
    {
        typedef decltype(std::declval<typename T1::type>() * std::declval<T2>()) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Multi, 2>
    {
        typedef decltype(std::declval<T1>() * std::declval<typename T2::type>()) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Multi, 3>
    {
        typedef decltype(std::declval<typename T1::type>() * std::declval<typename T2::type>()) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Div, 0>
    {
        typedef decltype(std::declval<T1>() / std::declval<T2>()) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Div, 1>
    {
        typedef decltype(std::declval<typename T1::type>() / std::declval<T2>()) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Div, 2>
    {
        typedef decltype(std::declval<T1>() / std::declval<typename T2::type>()) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Div, 3>
    {
        typedef decltype(std::declval<typename T1::type>() / std::declval<typename T2::type>()) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Max, 0>
    {
        typedef decltype(max(std::declval<T1>(), std::declval<T2>())) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Max, 1>
    {
        typedef decltype(max(std::declval<typename T1::type>(), std::declval<T2>())) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Max, 2>
    {
        typedef decltype(max(std::declval<T1>(), std::declval<typename T2::type>())) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Max, 3>
    {
        typedef decltype(max(std::declval<typename T1::type>(), std::declval<typename T2::type>())) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Min, 0>
    {
        typedef decltype(min(std::declval<T1>(), std::declval<T2>())) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Min, 1>
    {
        typedef decltype(min(std::declval<typename T1::type>(), std::declval<T2>())) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Min, 2>
    {
        typedef decltype(min(std::declval<T1>(), std::declval<typename T2::type>())) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Min, 3>
    {
        typedef decltype(min(std::declval<typename T1::type>(), std::declval<typename T2::type>())) type;
    };
    template < typename T1, typename T2 >
    struct promotion<T1, T2, Pow, 0>
    {
        typedef decltype(pow(std::declval<T1>(), std::declval<T2>())) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Pow, 1>
    {
        typedef decltype(pow(std::declval<typename T1::type>(), std::declval<T2>())) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Pow, 2>
    {
        typedef decltype(pow(std::declval<T1>(), std::declval<typename T2::type>())) type;
    };

    template < typename T1, typename T2 >
    struct promotion<T1, T2, Pow, 3>
    {
        typedef decltype(pow(std::declval<typename T1::type>(), std::declval<typename T2::type>())) type;
    };

    template < typename T1, typename T2, typename Op >
    using promotion_t = typename promotion<T1, T2, Op>::type;
#ifdef _MSC_VER
    template < typename T1, typename T2, typename T3
        , int F = is_expr<T1>::value + (is_expr<T2>::value << 1) + (is_expr<T3>::value << 2) >
    struct fma_promotion
    {
        typedef decltype(std::fma(std::decay_t<T1>(), std::decay_t<T2>(), std::decay_t<T3>())) type;
    };

    template < typename T1, typename T2, typename T3 >
    struct fma_promotion<T1, T2, T3, 1>
    {
        typedef decltype(std::fma(typename std::decay_t<T1>::type(), std::decay_t<T2>(), std::decay_t<T3>())) type;
    };

    template < typename T1, typename T2, typename T3 >
    struct fma_promotion<T1, T2, T3, 2>
    {
        typedef decltype(std::fma(std::decay_t<T1>(), std::decay_t<typename T2::type>(), std::decay_t<T3>())) type;
    };

    template < typename T1, typename T2, typename T3 >
    struct fma_promotion<T1, T2, T3, 3>
    {
        typedef decltype(std::fma(std::decay_t<typename T1::type>(), std::decay_t<typename T2::type>(), std::decay_t<T3>())) type;
    };

    template < typename T1, typename T2, typename T3 >
    struct fma_promotion<T1, T2, T3, 4>
    {
        typedef decltype(std::fma(std::decay_t<T1>(), std::decay_t<T2>(), std::decay_t<typename T3::type>())) type;
    };

    template < typename T1, typename T2, typename T3 >
    struct fma_promotion<T1, T2, T3, 5>
    {
        typedef decltype(std::fma(std::decay_t<typename T1::type>(), std::decay_t<T2>(), std::decay_t<typename T3::type>())) type;
    };

    template < typename T1, typename T2, typename T3 >
    struct fma_promotion<T1, T2, T3, 6>
    {
        typedef decltype(std::fma(std::decay_t<T1>(), std::decay_t<typename T2::type>(), std::decay_t<typename T3::type>())) type;
    };

    template < typename T1, typename T2, typename T3 >
    struct fma_promotion<T1, T2, T3, 7>
    {
        typedef decltype(std::fma(std::decay_t<typename T1::type>(), std::decay_t<typename T2::type>(), std::decay_t<typename T3::type>())) type;
    };
#else
    template < typename T1, typename T2, typename T3
        , int F = is_expr<T1>::value + (is_expr<T2>::value << 1) + (is_expr<T3>::value << 2) >
    struct fma_promotion
    {
        typedef decltype(fma(std::decay_t<T1>(), std::decay_t<T2>(), std::decay_t<T3>())) type;
    };

    template < typename T1, typename T2, typename T3 >
    struct fma_promotion<T1, T2, T3, 1>
    {
        typedef decltype(fma(typename std::decay_t<T1>::type(), std::decay_t<T2>(), std::decay_t<T3>())) type;
    };

    template < typename T1, typename T2, typename T3 >
    struct fma_promotion<T1, T2, T3, 2>
    {
        typedef decltype(fma(std::decay_t<T1>(), std::decay_t<typename T2::type>(), std::decay_t<T3>())) type;
    };

    template < typename T1, typename T2, typename T3 >
    struct fma_promotion<T1, T2, T3, 3>
    {
        typedef decltype(fma(std::decay_t<typename T1::type>(), std::decay_t<typename T2::type>(), std::decay_t<T3>())) type;
    };

    template < typename T1, typename T2, typename T3 >
    struct fma_promotion<T1, T2, T3, 4>
    {
        typedef decltype(fma(std::decay_t<T1>(), std::decay_t<T2>(), std::decay_t<typename T3::type>())) type;
    };

    template < typename T1, typename T2, typename T3 >
    struct fma_promotion<T1, T2, T3, 5>
    {
        typedef decltype(fma(std::decay_t<typename T1::type>(), std::decay_t<T2>(), std::decay_t<typename T3::type>())) type;
    };

    template < typename T1, typename T2, typename T3 >
    struct fma_promotion<T1, T2, T3, 6>
    {
        typedef decltype(fma(std::decay_t<T1>(), std::decay_t<typename T2::type>(), std::decay_t<typename T3::type>())) type;
    };

    template < typename T1, typename T2, typename T3 >
    struct fma_promotion<T1, T2, T3, 7>
    {
        typedef decltype(fma(std::decay_t<typename T1::type>(), std::decay_t<typename T2::type>(), std::decay_t<typename T3::type>())) type;
    };
#endif
    template < typename T1, typename T2, typename T3 >
    using fma_promotion_t = typename fma_promotion<T1, T2, T3>::type;

    template < class A, class Func >
    class Expr1
    {
        std::decay_t<typename Expr<A>::Ref> arg;
    public:
        void is_expr() {};
        typedef decltype(Func::Apply(arg[0])) type;
        Expr1(A&& a)
            :arg(std::forward<A>(a)) {}
        auto operator[](const long long)->decltype(Func::Apply(arg[0])) const
        {
            return Func::Apply(arg[0]);
        }
        auto eval()->decltype(Func::Apply(arg[0])) const
        {
            return Func::Apply(arg[0]);
        }
    };

    template <class L, class Op, class R>
    class Expr2 {
        std::decay_t<typename Expr<L>::Ref> l_;
        std::decay_t<typename Expr<R>::Ref> r_;
    public:
        void is_expr() {};
        typedef promotion_t<L, R, Op> type;
        Expr2(L&& l, R&& r)
            : l_(std::forward<L>(l)), r_(std::forward<R>(r)) {}

        auto operator[](const long long)->decltype(Op::Apply(l_[0], r_[0])) const
        {
            return Op::Apply(l_[0], r_[0]);
        }
        auto eval()->decltype(Op::Apply(l_[0], r_[0])) const
        {
            return Op::Apply(l_[0], r_[0]);
        }
    };

    template <class T1, class T2, class T3, class Func>
    class Expr3 {
        std::decay_t<typename Expr<T1>::Ref> v1_;
        std::decay_t<typename Expr<T2>::Ref> v2_;
        std::decay_t<typename Expr<T3>::Ref> v3_;
    public:
        void is_expr() {};
        typedef fma_promotion_t<T1, T2, T3> type;
        Expr3(T1&& v1, T2&& v2, T3&& v3)
            : v1_(std::forward<T1>(v1)), v2_(std::forward<T2>(v2)), v3_(std::forward<T3>(v3)) {}

        auto operator[](const long long)->decltype(Func::Apply(v1_[0], v2_[0], v3_[0])) const
        {
            return Func::Apply(v1_[0], v2_[0], v3_[0]);
        }
        auto eval()->decltype(Func::Apply(v1_[0], v2_[0], v3_[0])) const
        {
            return Func::Apply(v1_[0], v2_[0], v3_[0]);
        }
    };


    struct Add {
        template <typename L, typename R>
        using promotion_t = promotion_add_t<L, R>;

        template < typename T, typename U >
        static auto Apply(interval<T> const& l, interval<U> const& r)
        {
            return add(l, r);
        }
        template < typename T, typename U >
        static auto Apply(interval<T> const& l, U const& r)
        {
            return add(l, r);
        }
        template < typename T, typename U >
        static auto Apply(U&& l, interval<T> const& r)
        {
            return add(std::forward<U>(l), r);
        }
    };
    struct Sub {
        template <typename L, typename R>
        using promotion_t = promotion_sub_t<L, R>;

        template < typename T, typename U >
        static interval<promotion_t<T, U>> Apply(interval<T> const& l, interval<U> const& r)
        {
            return sub(l, r);
        }
        template < typename T, typename U >
        static interval<promotion_t<T, U>> Apply(interval<T> const& l, U const& r)
        {
            return sub(l, r);
        }
        template < typename T, typename U >
        static interval<promotion_t<T, U>> Apply(U const& l, interval<T> const& r)
        {
            return sub(l, r);
        }
    };
    struct Multi {
        template <typename L, typename R>
        using promotion_t = promotion_multi_t<L, R>;

        template < typename T, typename U >
        static interval<promotion_t<T, U>> Apply(interval<T> const& l, interval<U> const& r)
        {
            return multi(l, r);
        }
        template < typename T, typename U >
        static auto Apply(interval<T> const& l, U const& r)
        {
            return multi(l, r);
        }
        template < typename T, typename U >
        static interval<promotion_t<T, U>> Apply(U const& l, interval<T> const& r)
        {
            return multi(l, r);
        }
    };

    struct Div {
        template <typename L, typename R>
        using promotion_t = promotion_div_t<L, R>;

        template < typename T, typename U >
        static interval<promotion_t<T, U>> Apply(interval<T> const& l, interval<U> const& r)
        {
            return div(l, r);
        }
        template < typename T, typename U >
        static interval<promotion_t<T, U>> Apply(interval<T> const& l, U const& r)
        {
            return div(l, r);
        }
        template < typename T, typename U >
        static interval<promotion_t<T, U>> Apply(U const& l, interval<T> const& r)
        {
            return div(l, r);
        }
    };

    struct Sin
    {
        template < typename T >
        static interval<T> Apply(interval<T> const& x)
        {
            return sin(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::sin(x))
        {
            return std::sin(x);
        }

    };
    struct Cos
    {
        template < typename T >
        static interval<T> Apply(interval<T> const& x)
        {
            return cos(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::cos(x))
        {
            return std::cos(x);
        }
    };
    struct Tan
    {
        template < typename T >
        static interval<T> Apply(interval<T> const& x)
        {
            return tan(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::tan(x))
        {
            return std::tan(x);
        }
    };

    struct Asin
    {
        template < typename T >
        static interval<T> Apply(interval<T> const& x)
        {
            return asin(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::asin(x))
        {
            return std::asin(x);
        }
    };

    struct Acos
    {
        template < typename T >
        static interval<T> Apply(interval<T> const& x)
        {
            return acos(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::acos(x))
        {
            return std::acos(x);
        }
    };

    struct Atan
    {
        template < typename T >
        static interval<T> Apply(interval<T> const& x)
        {
            return atan(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::atan(x))
        {
            return std::atan(x);
        }
    };

    struct Sinh
    {
        template < typename T >
        static interval<T> Apply(interval<T> const& x)
        {
            return sinh(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::sinh(x))
        {
            return std::sinh(x);
        }
    };

    struct Cosh
    {
        template < typename T >
        static interval<T> Apply(interval<T> const& x)
        {
            return cosh(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::cosh(x))
        {
            return std::cosh(x);
        }
    };

    struct Tanh
    {
        template < typename T >
        static interval<T> Apply(interval<T> const& x)
        {
            return tanh(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::tanh(x))
        {
            return std::tanh(x);
        }
    };

    struct Asinh
    {
        template < typename T >
        static interval<T> Apply(interval<T> const& x)
        {
            return asinh(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::asinh(x))
        {
            return std::asinh(x);
        }
    };

    struct Acosh
    {
        template < typename T >
        static interval<T> Apply(interval<T> const& x)
        {
            return acosh(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::acosh(x))
        {
            return std::acosh(x);
        }
    };

    struct Atanh
    {
        template < typename T >
        static interval<T> Apply(interval<T> const& x)
        {
            return atanh(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::atanh(x))
        {
            return std::atanh(x);
        }
    };

    struct Sqrt
    {
        template < typename T >
        static interval<T> Apply(interval<T> const& x)
        {
            return sqrt(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::sqrt(x))
        {
            return std::sqrt(x);
        }
    };

    struct Cbrt
    {
        template < typename T >
        static interval<T> Apply(interval<T> const& x)
        {
            return cbrt(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::cbrt(x))
        {
            return std::cbrt(x);
        }
    };

    struct Pow
    {
        template < typename T >
        static interval<T> Apply(interval<T> x, int const& n)
        {
            return pow(x, n);
        }
        template < typename T >
        static auto Apply(T const& x, int const& n)->decltype(std::pow(x, n))
        {
            return std::pow(x, n);
        }
    };

    struct Exp
    {
        template < typename T >
        static interval<T> Apply(interval<T> x)
        {
            return exp(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::exp(x))
        {
            return std::exp(x);
        }
    };

    struct Exp2
    {
        template < typename T >
        static interval<T> Apply(interval<T> x)
        {
            return exp2(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::exp2(x))
        {
            return std::exp2(x);
        }
    };

    struct Expm1
    {
        template < typename T >
        static interval<T> Apply(interval<T> x)
        {
            return expm1(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::expm1(x))
        {
            return std::expm1(x);
        }
    };

    struct Abs
    {
        template < typename T >
        static interval<T> Apply(interval<T> x)
        {
            return abs(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::abs(x))
        {
            return std::abs(x);
        }
    };

    struct Log
    {
        template < typename T >
        static interval<T> Apply(interval<T> x)
        {
            return log(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::log(x))
        {
            return std::log(x);
        }
    };

    struct Log10
    {
        template < typename T >
        static interval<T> Apply(interval<T> x)
        {
            return log10(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::log10(x))
        {
            return std::log10(x);
        }
    };

    struct Log2
    {
        template < typename T >
        static interval<T> Apply(interval<T> x)
        {
            return log2(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::log2(x))
        {
            return std::log2(x);
        }
    };

    struct Log1p
    {
        template < typename T >
        static interval<T> Apply(interval<T> x)
        {
            return log1p(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::log1p(x))
        {
            return std::log1p(x);
        }
    };

    struct Erf
    {
        template < typename T >
        static interval<T> Apply(interval<T> x)
        {
            return erf(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::erf(x))
        {
            return std::erf(x);
        }
    };

    struct Erfc
    {
        template < typename T >
        static interval<T> Apply(interval<T> x)
        {
            return erfc(x);
        }
        template < typename T >
        static auto Apply(T const& x)->decltype(std::erfc(x))
        {
            return std::erfc(x);
        }
    };
    struct Fma
    {
        template < typename T1, typename T2, typename T3 >
        static auto Apply(T1&& v1, T2&& v2, T3&& v3)->decltype(fma(v1, v2, v3))
        {
            return fma(std::forward<T1>(v1), std::forward<T2>(v2), std::forward<T3>(v3));
        }
    };

    struct Max
    {
        template < typename L, typename R >
        static auto Apply(L&& v1, R&& v2)
        {
            return max(std::forward<L>(v1), std::forward<R>(v2));
        }
    };


    struct Min
    {
        template < typename L, typename R >
        static auto Apply(L&& v1, R&& v2)
        {
            return min(std::forward<L>(v1), std::forward<R>(v2));
        }
    };

    namespace Expression {
        template <class L, class R>
        inline constexpr Expr2<L, Add, R> add_(L&& lhs, R&& rhs)
        {
            return Expr2<L, Add, R>(std::forward<L>(lhs), std::forward<R>(rhs));
        }
        template <class L, class R>
        inline constexpr Expr2<L, Sub, R> sub_(L&& lhs, R&& rhs)
        {
            return Expr2<L, Sub, R>(std::forward<L>(lhs), std::forward<R>(rhs));
        }

        template <class L, class R>
        inline constexpr Expr2<L, Multi, R> multi_(L&& lhs, R&& rhs)
        {
            return Expr2<L, Multi, R>(std::forward<L>(lhs), std::forward<R>(rhs));
        }

        template <class L, class R>
        inline constexpr Expr2<L, Div, R> div_(L&& lhs, R&& rhs)
        {
            return Expr2<L, Div, R>(std::forward<L>(lhs), std::forward<R>(rhs));
        }

        template< class A >
        inline constexpr Expr1<A, Sin> sin_(A&& a)
        {
            return Expr1<A, Sin>(std::forward<A>(a));
        }
        template< class A >
        inline constexpr Expr1<A, Cos> cos_(A&& a)
        {
            return Expr1<A, Cos>(std::forward<A>(a));
        }
        template< class A >
        inline constexpr Expr1<A, Tan> tan_(A&& a)
        {
            return Expr1<A, Tan>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Asin> asin_(A&& a)
        {
            return Expr1<A, Asin>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Acos> acos_(A&& a)
        {
            return Expr1<A, Acos>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Atan> atan_(A&& a)
        {
            return Expr1<A, Atan>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Sinh> sinh_(A&& a)
        {
            return Expr1<A, Sinh>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Cosh> cosh_(A&& a)
        {
            return Expr1<A, Cosh>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Tanh> tanh_(A&& a)
        {
            return Expr1<A, Tanh>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Asinh> asinh_(A&& a)
        {
            return Expr1<A, Asinh>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Acosh> acosh_(A&& a)
        {
            return Expr1<A, Acosh>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Atanh> atanh_(A&& a)
        {
            return Expr1<A, Atanh>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Exp> exp_(A&& a)
        {
            return Expr1<A, Exp>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Exp2> exp2_(A&& a)
        {
            return Expr1<A, Exp2>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Expm1> expm1_(A&& a)
        {
            return Expr1<A, Expm1>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Log> log_(A&& a)
        {
            return Expr1<A, Log>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Log10> log10_(A&& a)
        {
            return Expr1<A, Log10>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Log2> log2_(A&& a)
        {
            return Expr1<A, Log2>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Log1p> log1p_(A&& a)
        {
            return Expr1<A, Log1p>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Abs> abs_(A&& a)
        {
            return Expr1<A, Abs>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Erf> erf_(A&& a)
        {
            return Expr1<A, Erf>(std::forward<A>(a));
        }

        template < class A >
        inline constexpr Expr1<A, Erfc> erfc_(A&& a)
        {
            return Expr1<A, Erfc>(std::forward<A>(a));
        }

        template< class L, class R >
        inline constexpr Expr2<L, Pow, R> pow_(L&& a, R&& n)
        {
            return Expr2<L, Pow, R>(std::forward<L>(a), std::forward<R>(n));
        }

        template< class T1, class T2, class T3 >
        inline constexpr auto fma_(T1&& v1, T2&& v2, T3&& v3)
        {
            return Expr3<T1, T2, T3, Fma>(std::forward<T1>(v1), std::forward<T2>(v2), std::forward<T3>(v3));
        }

        template < typename L, typename R >
        inline constexpr auto max_(L&& v1, R&& v2)
        {
            return Expr2<L, Max, R>(std::forward<L>(v1), std::forward<R>(v2));
        }

        template < typename L, typename R >
        inline constexpr auto min_(L&& v1, R&& v2)
        {
            return Expr2<L, Min, R>(std::forward<L>(v1), std::forward<R>(v2));
        }

        template < typename T, typename ... Args >
        inline constexpr auto max_(T&& head, Args&&... args)
        {
            return max_(std::forward<T>(head), max_(std::forward<Args>(args)...));
        }

        template < typename T, typename ... Args >
        inline constexpr auto min_(T&& head, Args&&... args)
        {
            return min_(std::forward<T>(head), min_(std::forward<Args>(args)...));
        }

    }


Fixed Features

Fixed #2

Changed rounding control for math func to use fesetround instead of nextforward.
Four arithmetic operator and sqrt are perfectly work.
But other math functions work are undefined IEEE754.
Now writing polynomial approximation.

Fixed #5

Add resetters receiving value as const lvalue reference.

Fixed exception.hpp

Add exception check if-block MACRO.
Rename exception class.

Improvement exception check

Introducing exception check MACRO, exception having more information.
Exception has information; file, line, function name and reason why occurred it.

Fixed logical operator and four arithmetic operator

Fixed the problem that ADL failure occurred with policy if and only if arguments are const lvalue.

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2