| @ -0,0 +1,156 @@ | |||
| #pragma once | |||
| #include <type_traits> | |||
| #include <iostream> | |||
| #pragma GCC diagnostic push | |||
| #pragma GCC diagnostic ignored "-Wnarrowing" | |||
| namespace ninefloat{ | |||
| struct private_t{}; | |||
| private_t priv; | |||
| template<class integer_type, int fractionals> | |||
| class Q{ | |||
| integer_type backend; | |||
| static constexpr int degen=fractionals; | |||
| constexpr Q (const integer_type value, private_t) | |||
| : backend{value} | |||
| {} | |||
| public: | |||
| constexpr Q(const Q<integer_type,fractionals>& value) | |||
| : backend{value.backend} | |||
| {} | |||
| template<class srcT> | |||
| constexpr Q (const srcT value) | |||
| : backend{(integer_type)(value*(1<<degen))} | |||
| {} | |||
| constexpr Q () | |||
| : backend{0} | |||
| {} | |||
| constexpr bool is_negative() | |||
| { | |||
| return backend&(1<<(sizeof(backend)-1)); | |||
| } | |||
| constexpr integer_type data() | |||
| { | |||
| return backend; | |||
| } | |||
| constexpr bool is_positive() | |||
| { | |||
| return !is_negative(); | |||
| } | |||
| constexpr Q<integer_type, fractionals>& operator+=(const Q& oth) | |||
| { | |||
| backend+=oth.backend; | |||
| return *this; | |||
| } | |||
| constexpr Q<integer_type, fractionals>& operator-=(const Q& oth) | |||
| { | |||
| backend-=oth.backend; | |||
| return *this; | |||
| } | |||
| constexpr Q<integer_type, fractionals>& operator/=(const Q& oth) | |||
| { | |||
| backend*=1<<Q<integer_type, fractionals>::degen; | |||
| backend/=oth.backend; | |||
| return *this; | |||
| } | |||
| constexpr Q<integer_type, fractionals>& operator*=(const Q& oth) | |||
| { | |||
| if constexpr(Q<integer_type, fractionals>::degen%2==0) | |||
| { | |||
| backend=(backend>>(Q<integer_type, fractionals>::degen/2))*(oth.backend>>(Q<integer_type, fractionals>::degen/2)); | |||
| }else{ | |||
| backend=(backend>>(Q<integer_type, fractionals>::degen>>1))*(oth.backend>>((Q<integer_type, fractionals>::degen>>1)+1)); | |||
| } | |||
| return *this; | |||
| } | |||
| constexpr Q<integer_type, fractionals> operator+(const Q& oth) | |||
| { | |||
| return Q{backend+oth.backend, priv}; | |||
| } | |||
| constexpr Q<integer_type, fractionals> operator-(const Q& oth) | |||
| { | |||
| return Q{backend-oth.backend, priv}; | |||
| } | |||
| constexpr Q<integer_type, fractionals> operator/(const Q& oth) | |||
| { | |||
| return Q{(1<<Q<integer_type, fractionals>::degen)*backend/oth.backend, priv}; | |||
| } | |||
| constexpr Q<integer_type, fractionals> operator*(const Q& oth) | |||
| { | |||
| if constexpr(Q<integer_type, fractionals>::degen%2==0) | |||
| { | |||
| return Q{(backend>>(Q<integer_type, fractionals>::degen/2))*(oth.backend>>(Q<integer_type, fractionals>::degen/2)),priv}; | |||
| }else{ | |||
| return Q{(backend>>(Q<integer_type, fractionals>::degen>>1))*(oth.backend>>((Q<integer_type, fractionals>::degen>>1)+1)),priv}; | |||
| } | |||
| } | |||
| constexpr bool operator==(const Q& oth) | |||
| { | |||
| return backend == oth.backend; | |||
| } | |||
| constexpr bool operator!=(const Q& oth) | |||
| { | |||
| return backend != oth.backend; | |||
| } | |||
| constexpr bool operator>=(const Q& oth) | |||
| { | |||
| return backend >= oth.backend; | |||
| } | |||
| constexpr bool operator<=(const Q& oth) | |||
| { | |||
| return backend <= oth.backend; | |||
| } | |||
| constexpr bool operator>(const Q& oth) | |||
| { | |||
| return backend > oth.backend; | |||
| } | |||
| constexpr bool operator<(const Q& oth) | |||
| { | |||
| return backend < oth.backend; | |||
| } | |||
| constexpr operator float() | |||
| { | |||
| float n=backend; | |||
| n/=(1<<Q<integer_type, fractionals>::degen); | |||
| return n; | |||
| } | |||
| constexpr operator double() | |||
| { | |||
| double n=backend; | |||
| n/=(1<<Q<integer_type, fractionals>::degen); | |||
| return n; | |||
| } | |||
| }; | |||
| #pragma GCC diagnostic pop | |||
| } | |||