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