#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}
|
|
{{std::cout<<value<< " : "<<backend<<std::endl;}}
|
|
|
|
public:
|
|
template<class srcT>
|
|
constexpr Q (const srcT value)
|
|
: backend{(integer_type)(value*(1<<degen))}
|
|
{std::cout<<value<< " : "<<backend<<std::endl;}
|
|
|
|
|
|
bool constexpr is_negative()
|
|
{
|
|
return backend&(1<<(sizeof(backend)-1));
|
|
}
|
|
|
|
|
|
integer_type constexpr data()
|
|
{
|
|
return backend;
|
|
}
|
|
|
|
bool constexpr is_positive()
|
|
{
|
|
return !is_negative();
|
|
}
|
|
|
|
Q constexpr operator+=(const Q& oth)
|
|
{
|
|
backend+=oth.backend;
|
|
return this;
|
|
}
|
|
|
|
Q constexpr operator-=(const Q& oth)
|
|
{
|
|
backend-=oth.backend;
|
|
return this;
|
|
}
|
|
|
|
Q constexpr operator/=(const Q& oth)
|
|
{
|
|
backend*=1<<Q<integer_type, fractionals>::degen;
|
|
backend/=oth.backend;
|
|
return this;
|
|
}
|
|
|
|
Q constexpr 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;
|
|
}
|
|
|
|
Q constexpr operator+(const Q& oth)
|
|
{
|
|
return Q{backend+oth.backend, priv};
|
|
}
|
|
|
|
Q constexpr operator-(const Q& oth)
|
|
{
|
|
return Q{backend-oth.backend, priv};
|
|
}
|
|
|
|
Q constexpr operator/(const Q& oth)
|
|
{
|
|
return Q{(1<<Q<integer_type, fractionals>::degen)*backend/oth.backend, priv};
|
|
}
|
|
|
|
Q constexpr 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};
|
|
}
|
|
}
|
|
|
|
bool constexpr operator==(const Q& oth)
|
|
{
|
|
return backend == oth.backend;
|
|
}
|
|
|
|
bool constexpr operator!=(const Q& oth)
|
|
{
|
|
return backend != oth.backend;
|
|
}
|
|
|
|
bool constexpr operator>=(const Q& oth)
|
|
{
|
|
return backend >= oth.backend;
|
|
}
|
|
|
|
bool constexpr operator<=(const Q& oth)
|
|
{
|
|
return backend <= oth.backend;
|
|
}
|
|
|
|
bool constexpr operator>(const Q& oth)
|
|
{
|
|
return backend > oth.backend;
|
|
}
|
|
|
|
bool constexpr 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
|
|
|
|
}
|