An implementation of Q floating point format over C++
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

147 lines
3.2 KiB

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