Created
January 14, 2021 14:50
-
-
Save Rseding91/074c36c2d70296c4892ea88d65e3432f to your computer and use it in GitHub Desktop.
FixedPointNumber
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <TypeTraitsExtensions.hpp> | |
#include <Util/FixedPointNumberTemplateForwards.hpp> | |
#include <cstdlib> // keep me | |
#include <limits> // keep me | |
#include <stdint.h> | |
class Deserialiser; | |
class Serialiser; | |
template<class T, uint32_t PrecisionBits> | |
class FixedPointNumberTemplate | |
{ | |
public: | |
using ValueType = T; | |
static constexpr uint32_t FractionalBits = PrecisionBits; | |
static constexpr T ValuesPerOne = T(1) << PrecisionBits; | |
constexpr FixedPointNumberTemplate() : value(0) {} | |
constexpr FixedPointNumberTemplate(int32_t number) : value(T(T(number) << PrecisionBits)) {} | |
constexpr FixedPointNumberTemplate(uint32_t number) : value(T(T(number) << PrecisionBits)) {} | |
constexpr FixedPointNumberTemplate(int64_t number) : value(T(T(number) << PrecisionBits)) {} | |
constexpr FixedPointNumberTemplate(uint64_t number) : value(T(T(number) << PrecisionBits)) {} | |
constexpr FixedPointNumberTemplate(double number) : value(T(number * ValuesPerOne)) {} | |
constexpr FixedPointNumberTemplate(int32_t, T value) : value(value) {} | |
explicit FixedPointNumberTemplate(Deserialiser& input); | |
template <class K, uint32_t OtherPrecisionBits> | |
constexpr FixedPointNumberTemplate(const FixedPointNumberTemplate<K, OtherPrecisionBits>& other) | |
{ | |
if constexpr (PrecisionBits < OtherPrecisionBits) | |
this->value = T(other.value >> (OtherPrecisionBits - PrecisionBits)); | |
else | |
this->value = T(other.value << (PrecisionBits - OtherPrecisionBits)); | |
} | |
static FixedPointNumberTemplate powerOfTwo(int32_t exponent) { return FixedPointNumberTemplate(0, T(1) << (PrecisionBits + exponent)); } | |
INLINE_CPP void save(Serialiser& output) const; | |
constexpr double getDouble() const { constexpr double ValuePerIncrement = 1.0 / ValuesPerOne; return double(this->value) * ValuePerIncrement; } | |
constexpr float getFloat() const { constexpr float ValuePerIncrement = 1.0f / ValuesPerOne; return float(this->value) * ValuePerIncrement; } | |
static constexpr FixedPointNumberTemplate max() { return FixedPointNumberTemplate(0, std::numeric_limits<T>::max()); } | |
static constexpr FixedPointNumberTemplate min() { return FixedPointNumberTemplate(0, std::numeric_limits<T>::min()); } | |
constexpr void cutBits(uint32_t bits) { this->value >>= bits; this->value <<= bits; } | |
constexpr FixedPointNumberTemplate next() const { FixedPointNumberTemplate result(*this); ++result.value; return result; } | |
constexpr FixedPointNumberTemplate previous() const { FixedPointNumberTemplate result(*this); --result.value; return result; } | |
constexpr FixedPointNumberTemplate abs() const | |
{ | |
FixedPointNumberTemplate result(*this); | |
if constexpr (std::numeric_limits<T>::min() < 0) | |
result.value = T(result.value < 0 ? -result.value : result.value); | |
return result; | |
} | |
constexpr FixedPointNumberTemplate& operator+=(double addition) { return this->value += T(addition * ValuesPerOne), *this; } | |
constexpr FixedPointNumberTemplate& operator+=(const FixedPointNumberTemplate& addition) { return this->value += addition.value, *this; } | |
constexpr FixedPointNumberTemplate& operator-=(double minus) { return this->value -= T(minus * ValuesPerOne), *this; } | |
constexpr FixedPointNumberTemplate& operator-=(const FixedPointNumberTemplate& minus) { return this->value -= minus.value, *this; } | |
constexpr FixedPointNumberTemplate& operator*=(const double& multiplier) { return this->value = T(this->value * multiplier), *this; } | |
constexpr FixedPointNumberTemplate& operator/=(const double& divisor) { return this->value = T(this->value / divisor), *this; } | |
constexpr FixedPointNumberTemplate& operator++() { return this->value += T(1) << PrecisionBits, *this; } | |
constexpr bool operator<(const FixedPointNumberTemplate& cmp) const { return this->value < cmp.value; } | |
constexpr bool operator<=(const FixedPointNumberTemplate& cmp) const { return this->value <= cmp.value; } | |
constexpr bool operator>(const FixedPointNumberTemplate& cmp) const { return this->value > cmp.value; } | |
constexpr bool operator>=(const FixedPointNumberTemplate& cmp) const { return this->value >= cmp.value; } | |
constexpr bool operator==(const FixedPointNumberTemplate& cmp) const { return this->value == cmp.value; } | |
constexpr bool operator!=(const FixedPointNumberTemplate& cmp) const { return this->value != cmp.value; } | |
constexpr FixedPointNumberTemplate operator-() const | |
{ | |
FixedPointNumberTemplate result(*this); | |
if constexpr (std::numeric_limits<T>::min() < 0) | |
result.value = -result.value; | |
return result; | |
} | |
constexpr T floor() const { return this->value >> PrecisionBits; } | |
constexpr FixedPointNumberTemplate cutPrecision(int32_t remainingPrecision) { return FixedPointNumberTemplate(0, T(this->value & ~((1 << (PrecisionBits - remainingPrecision)) - 1))); } | |
constexpr FixedPointNumberTemplate floorAsFixedPoint() const { FixedPointNumberTemplate result(*this); result.value >>= PrecisionBits; result.value <<= PrecisionBits; return result; } | |
constexpr T ceil() const { return (this->value + (ValuesPerOne - 1)) >> PrecisionBits; } constexpr FixedPointNumberTemplate ceilAsFixedPoint() const { FixedPointNumberTemplate result(*this); result.value += (ValuesPerOne - 1); result.value >>= PrecisionBits; result.value <<= PrecisionBits; return result; } | |
constexpr T round() const { return (this->value >= 0) ? (*this + FixedPointNumberTemplate(0.5)).floor() : (*this - FixedPointNumberTemplate(0.5)).ceil(); } | |
constexpr FixedPointNumberTemplate roundAsFixedPoint() const { return (this->value >= 0) ? (*this + FixedPointNumberTemplate(0.5)).floorAsFixedPoint() : (*this - FixedPointNumberTemplate(0.5)).ceilAsFixedPoint(); } | |
constexpr FixedPointNumberTemplate operator+(const FixedPointNumberTemplate& other) const { return FixedPointNumberTemplate(0, this->value + other.value); } | |
constexpr FixedPointNumberTemplate operator-(const FixedPointNumberTemplate& other) const { return FixedPointNumberTemplate(0, this->value - other.value); } | |
constexpr FixedPointNumberTemplate operator*(double multiplier) const { return FixedPointNumberTemplate(0, T(this->value * multiplier)); } | |
constexpr FixedPointNumberTemplate operator/(double divisor) const { return FixedPointNumberTemplate(0, T(this->value / divisor)); } | |
constexpr FixedPointNumberTemplate operator<<(uint32_t shift) const { return FixedPointNumberTemplate(0, this->value << shift); } | |
constexpr FixedPointNumberTemplate operator>>(uint32_t shift) const { return FixedPointNumberTemplate(0, this->value >> shift); } | |
constexpr FixedPointNumberTemplate fround(double divisor) const { FixedPointNumberTemplate result(*this); result /= divisor; result = result.roundAsFixedPoint(); result *= divisor; return result; } | |
T value; | |
}; | |
using FixedPointNumber = FixedPointNumberTemplate<>; | |
static_assert(uses_memcpy<FixedPointNumber>); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Map/MapSerialiser.hpp> | |
#include <Util/Deserialiser.hpp> | |
template<class T, uint32_t PrecisionBits> | |
FixedPointNumberTemplate<T, PrecisionBits>::FixedPointNumberTemplate(Deserialiser& input) | |
: value(input.load<T>()) | |
{} | |
template<class T, uint32_t PrecisionBits> | |
INLINE_CPP void FixedPointNumberTemplate<T, PrecisionBits>::save(Serialiser& output) const | |
{ | |
output << this->value; | |
} | |
template class FixedPointNumberTemplate<uint8_t, 3>; | |
template class FixedPointNumberTemplate<int8_t, 4>; | |
template class FixedPointNumberTemplate<int16_t, 10>; | |
template class FixedPointNumberTemplate<int16_t, 8>; | |
template class FixedPointNumberTemplate<uint16_t, 8>; | |
template class FixedPointNumberTemplate<int32_t, 8>; | |
template class FixedPointNumberTemplate<int32_t, 24>; | |
template class FixedPointNumberTemplate<int64_t, 8>; | |
template class FixedPointNumberTemplate<int64_t, 32>; | |
template class FixedPointNumberTemplate<uint32_t, 8>; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment