Reviewed-on: https://git.madvoxel.net/OpenVulkano/OpenVulkano/pulls/159 Reviewed-by: Georg Hagen <georg.hagen@madvoxel.com>
164 lines
4.4 KiB
C++
164 lines
4.4 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <cinttypes>
|
|
#include <type_traits>
|
|
|
|
namespace OpenVulkano
|
|
{
|
|
class int24 final
|
|
{
|
|
uint8_t m_internal[3];
|
|
public:
|
|
constexpr int24() : m_internal{ 0, 0, 0 }
|
|
{}
|
|
|
|
constexpr int24(const int val)
|
|
: m_internal{(uint8_t)(val & 0xff), (uint8_t)((val >> 8) & 0xff), (uint8_t)((val >> 16) & 0xff)}
|
|
{}
|
|
|
|
constexpr int24(const int24& val) : m_internal{ val.m_internal[0], val.m_internal[1], val.m_internal[2] }
|
|
{}
|
|
|
|
operator int() const
|
|
{
|
|
if (m_internal[2] & 0x80)
|
|
{ // Negative numbers
|
|
return (0xff << 24) | (m_internal[2] << 16) | (m_internal[1] << 8) | (m_internal[0] << 0);
|
|
}
|
|
else
|
|
{
|
|
return (m_internal[2] << 16) | (m_internal[1] << 8) | (m_internal[0] << 0);
|
|
}
|
|
}
|
|
|
|
operator float() const
|
|
{
|
|
return (float)this->operator int();
|
|
}
|
|
|
|
int24& operator =(const int24& input)
|
|
{
|
|
m_internal[0] = input.m_internal[0];
|
|
m_internal[1] = input.m_internal[1];
|
|
m_internal[2] = input.m_internal[2];
|
|
return *this;
|
|
}
|
|
|
|
int24& operator =(const int input)
|
|
{
|
|
m_internal[0] = ((unsigned char*)&input)[0];
|
|
m_internal[1] = ((unsigned char*)&input)[1];
|
|
m_internal[2] = ((unsigned char*)&input)[2];
|
|
return *this;
|
|
}
|
|
|
|
#define INT24_OPERATORS(op) \
|
|
template<typename T, std::enable_if_t<std::is_convertible_v<T, int>, bool> = true> \
|
|
int24 operator op(const T& val) const { return int24( (int)*this op static_cast<int>(val) ); } \
|
|
template<typename T, std::enable_if_t<std::is_convertible_v<T, int>, bool> = true> \
|
|
int24& operator op##=(const T& val ) { *this = *this op static_cast<int>(val); return *this; }
|
|
|
|
INT24_OPERATORS(+)
|
|
INT24_OPERATORS(-)
|
|
INT24_OPERATORS(*)
|
|
INT24_OPERATORS(/)
|
|
#undef INT24_OPERATORS
|
|
|
|
int24 operator >>(const int val) const
|
|
{
|
|
return int24( (int)*this >> val );
|
|
}
|
|
|
|
int24 operator <<(const int val) const
|
|
{
|
|
return int24( (int)*this << val );
|
|
}
|
|
|
|
int24& operator >>=(const int val )
|
|
{
|
|
*this = *this >> val;
|
|
return *this;
|
|
}
|
|
|
|
int24& operator <<=(const int val )
|
|
{
|
|
*this = *this << val;
|
|
return *this;
|
|
}
|
|
|
|
operator bool() const
|
|
{
|
|
return (int)*this != 0;
|
|
}
|
|
|
|
bool operator !() const
|
|
{
|
|
return !((int)*this);
|
|
}
|
|
|
|
int24 operator -()
|
|
{
|
|
return int24( -(int)*this );
|
|
}
|
|
|
|
template<typename T, std::enable_if_t<std::is_convertible_v<T, int>, bool> = true>
|
|
[[nodiscard]] bool operator==(const T& val) const
|
|
{
|
|
return static_cast<int>(*this) == static_cast<int>(val);
|
|
}
|
|
|
|
template<typename T, std::enable_if_t<std::is_convertible_v<T, int>, bool> = true>
|
|
[[nodiscard]] constexpr auto operator<=>(const T& other) const
|
|
{
|
|
return operator int() <=> static_cast<int>(other);
|
|
}
|
|
};
|
|
}
|
|
|
|
namespace std
|
|
{
|
|
template <>
|
|
class numeric_limits<OpenVulkano::int24>
|
|
{
|
|
public:
|
|
static const bool is_specialized = true;
|
|
static constexpr OpenVulkano::int24 min() { return OpenVulkano::int24(0x800000); }
|
|
static constexpr OpenVulkano::int24 max() { return OpenVulkano::int24(0x7FFFFF); }
|
|
static const int radix = 2;
|
|
static const int digits = 23;
|
|
static const int digits10 = 6;
|
|
static const bool is_signed = true;
|
|
static const bool is_integer = true;
|
|
static const bool is_exact = true;
|
|
static const bool traps = false;
|
|
static const bool is_modulo = false;
|
|
static const bool is_bounded = true;
|
|
|
|
static constexpr OpenVulkano::int24 epsilon() { return OpenVulkano::int24(1); }
|
|
static constexpr OpenVulkano::int24 round_error() { return OpenVulkano::int24(0); }
|
|
static const int min_exponent10 = 0;
|
|
static const int max_exponent10 = 0;
|
|
static const int min_exponent = 0;
|
|
static const int max_exponent = 0;
|
|
|
|
static const bool has_infinity = false;
|
|
static const bool has_quiet_NaN = false;
|
|
static const bool has_signaling_NaN = false;
|
|
static const bool is_iec559 = false;
|
|
static const bool has_denorm = false;
|
|
static const bool tinyness_before = false;
|
|
static const float_round_style round_style = round_toward_zero;
|
|
|
|
// Not meaningful for int24...
|
|
static constexpr OpenVulkano::int24 denorm_min() { return OpenVulkano::int24(0); }
|
|
static constexpr OpenVulkano::int24 infinity() { return OpenVulkano::int24(0); }
|
|
static constexpr OpenVulkano::int24 quiet_NaN() { return OpenVulkano::int24(0); }
|
|
static constexpr OpenVulkano::int24 signaling_NaN() { return OpenVulkano::int24(0); }
|
|
};
|
|
} |