|
|
@ -1,147 +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} |
|
|
|
{{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
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
|
|
} |