|
|
- #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
-
- }
|