59 #ifndef FLOATING_POINT_EMULATION_HPP_INCLUDED
60 #define FLOATING_POINT_EMULATION_HPP_INCLUDED
65 #include <SDL_types.h>
67 #include <boost/utility/enable_if.hpp>
79 #ifdef FLOATING_POINT_EMULATION_ENABLE_RANGE_CHECK_THROW
80 #ifndef FLOATING_POINT_EMULATION_ENABLE_RANGE_CHECK
81 #error FLOATING_POINT_EMULATION_ENABLE_RANGE_CHECK_THROW requires \
82 FLOATING_POINT_EMULATION_ENABLE_RANGE_CHECK
85 #define FLOATING_POINT_EMULATION_RANGE_CHECK_THROW \
87 throw std::range_error(""); \
90 #define FLOATING_POINT_EMULATION_RANGE_CHECK_THROW \
95 #ifdef FLOATING_POINT_EMULATION_ENABLE_RANGE_CHECK
96 #ifdef FLOATING_POINT_EMULATION_USE_SCALED_INT
97 #error FLOATING_POINT_EMULATION_USE_SCALED_INT and \
98 FLOATING_POINT_EMULATION_ENABLE_RANGE_CHECK are mutually exclusive.
101 #define FLOATING_POINT_EMULATION_RANGE_CHECK \
102 FLOATING_POINT_EMULATION_RANGE_CHECK_OBJECT((*this))
104 #define FLOATING_POINT_EMULATION_RANGE_CHECK_OBJECT(object) \
106 if(object.value_ >= 2147483648.0) { \
107 std::cerr << "Positive overflow »" << object.value_ \
108 << "« as double »" << object.to_double() <<"« .\n"; \
109 FLOATING_POINT_EMULATION_RANGE_CHECK_THROW; \
111 if(object.value_ < -2147483648.0) { \
112 std::cerr << "Negative overflow »" << object.value_ \
113 << "« as double »" << object.to_double() <<"« .\n"; \
114 FLOATING_POINT_EMULATION_RANGE_CHECK_THROW; \
118 #define FLOATING_POINT_EMULATION_RANGE_CHECK \
121 #define FLOATING_POINT_EMULATION_RANGE_CHECK_OBJECT(object) \
126 #ifdef FLOATING_POINT_EMULATION_TRACER_ENABLE
128 #define FLOATING_POINT_EMULATION_TRACER_ENTRY(interval) TRACER_ENTRY(interval)
129 #define FLOATING_POINT_EMULATION_TRACER_COUNT(marker) TRACER_COUNT(marker)
131 #define FLOATING_POINT_EMULATION_TRACER_ENTRY(interval) \
135 #define FLOATING_POINT_EMULATION_TRACER_COUNT(marker) \
142 template<
class T,
unsigned S>
149 template<
class T,
unsigned S,
class E =
void>
227 template<
class T,
unsigned S>
235 template<
class T,
unsigned S>
242 template<
class R,
class T,
unsigned S>
250 template<
class T,
unsigned S>
287 sal(
double& lhs,
unsigned rhs)
299 sal(Sint32& lhs,
unsigned rhs)
315 sar(
double& lhs,
unsigned rhs)
327 sar(Sint32& lhs,
unsigned rhs)
332 template<
class T,
unsigned S>
437 Uint32 lhs_value = std::abs(lhs.
value_);
438 if(
LIKELY(lhs_value <= 0x007FFFFFu)) {
465 int dividend_high_bit = 0;
475 if(!(lhs_value & 0x78000000u)) {
478 dividend_high_bit += 4;
480 if(!(lhs_value & 0x60000000u)) {
483 dividend_high_bit += 2;
485 if(!(lhs_value & 0x40000000u)) {
487 dividend_high_bit += 1;
491 assert(dividend_high_bit >= 0);
492 assert(dividend_high_bit < 8);
497 int shifted = dividend_high_bit;
511 Uint32 rhs_value = std::abs(rhs.
value_);
517 int divisor_low_bit = 0;
519 if(!(rhs_value & 0xffu)) {
523 if(!(rhs_value & 0xfu)) {
525 divisor_low_bit += 4;
528 if(!(rhs_value & 0x3u)) {
530 divisor_low_bit += 2;
533 if(!(rhs_value & 0x1u)) {
535 divisor_low_bit += 1;
538 assert(divisor_low_bit >= 0);
539 assert(divisor_low_bit <= 8);
541 divisor_low_bit = std::min(8 - shifted, divisor_low_bit);
546 shifted += divisor_low_bit;
576 template<
class T,
unsigned S>
709 return tfloat(*this).negative();
885 return detail::store<int, T, S>(
value_);
891 return detail::store<double, T, S>(
value_);
942 template<
class T,
unsigned S>
946 return rhs.operator==(lhs);
949 template<
class T,
unsigned S>
953 return rhs.operator==(lhs);
956 template<
class T,
unsigned S>
960 return rhs.operator!=(lhs);
963 template<
class T,
unsigned S>
967 return rhs.operator!=(lhs);
990 value_ = (
static_cast<Sint64
>(value_) * rhs.
value_) >> 8;
994 template<
class T,
unsigned S>
998 return lhs.operator*=(rhs);
1001 template<
class T,
unsigned S>
1005 return lhs.operator*=(rhs);
1008 template<
class T,
unsigned S>
1012 return lhs.operator*=(rhs);
1015 template<
class T,
unsigned S>
1019 return rhs.operator*=(lhs);
1022 template<
class T,
unsigned S>
1026 return rhs.operator*=(lhs);
1031 template<
class T,
unsigned S>
1035 return lhs.operator/=(rhs);
1038 template<
class T,
unsigned S>
1042 return lhs.operator/=(rhs);
1045 template<
class T,
unsigned S>
1049 return lhs.operator/=(rhs);
1052 template<
class T,
unsigned S>
1059 template<
class T,
unsigned S>
1068 template<
class T,
unsigned S>
1072 return lhs.operator+=(rhs);
1075 template<
class T,
unsigned S>
1079 return lhs.operator+=(rhs);
1082 template<
class T,
unsigned S>
1086 return lhs.operator+=(rhs);
1089 template<
class T,
unsigned S>
1093 return rhs.operator+=(lhs);
1096 template<
class T,
unsigned S>
1100 return rhs.operator+=(lhs);
1105 template<
class T,
unsigned S>
1109 return lhs.operator-=(rhs);
1112 template<
class T,
unsigned S>
1116 return lhs.operator-=(rhs);
1119 template<
class T,
unsigned S>
1123 return lhs.operator-=(rhs);
1126 template<
class T,
unsigned S>
1133 template<
class T,
unsigned S>
1143 template<
class T,
unsigned S>
1152 #ifdef FLOATING_POINT_EMULATION_USE_SCALED_INT
1155 #ifdef FLOATING_POINT_EMULATION_ENABLE_RANGE_CHECK
T value_
The value of the emulation.
static int floor(double value)
bool operator==(const int rhs) const
tfloat & operator+=(const double rhs)
tfloat< T, S > operator+(tfloat< T, S > lhs, const tfloat< T, S > rhs)
tfloat & negative()
Changes the object to its negative value.
GLuint GLuint GLsizei GLenum type
bool operator==(const double rhs) const
static int floor(Sint32 value)
static T down(T &value)
Scales the internal value up.
bool operator!=(const int lhs, const tfloat< T, S > rhs)
static double up(double &value)
bool operator==(const tfloat rhs) const
tfloat & operator=(const double rhs)
tfloat(const double value)
tfloat & operator*=(const tfloat rhs)
Multiply.
tfloat & operator/=(const int rhs)
Divide.
#define FLOATING_POINT_EMULATION_RANGE_CHECK
tfloat & operator-=(const tfloat rhs)
tfloat & operator*=(const double rhs)
Multiply.
bool operator==(const int lhs, const tfloat< T, S > rhs)
int floor(tfloat< T, S > lhs)
#define FLOATING_POINT_EMULATION_RANGE_CHECK_OBJECT(object)
GLsizei const GLfloat * value
static tfloat< T, S > & idiv(tfloat< T, S > &lhs, tfloat< T, S > rhs)
tfloat & operator+=(const int rhs)
Contains code for tracing the code.
Templates and utility-routines for strings and numbers.
static T up(T &value)
Scales the value up.
bool operator<=(const tfloat rhs) const
tfloat & operator/=(const double rhs)
Divide.
tfloat & operator=(const int rhs)
tfloat< T, S > operator-(tfloat< T, S > lhs, const tfloat< T, S > rhs)
tfloat & operator=(const tfloat rhs)
tfloat< T, S > operator/(tfloat< T, S > lhs, const tfloat< T, S > rhs)
static Sint32 down(Sint32 &value)
Template class for the emulation.
tfloat & operator-=(const int rhs)
bool operator>=(const tfloat rhs) const
#define FLOATING_POINT_EMULATION_TRACER_ENTRY(interval)
bool operator!=(const double rhs) const
tfloat & operator*=(const int rhs)
Multiply.
floating_point_emulation::tfloat< double, 0 > tfloat
tfloat & operator-=(const double rhs)
tfloat< T, S > operator*(tfloat< T, S > lhs, const tfloat< T, S > rhs)
bool operator<(const tfloat rhs) const
#define FLOATING_POINT_EMULATION_TRACER_COUNT(marker)
bool operator!=(const int rhs) const
static Sint32 up(Sint32 &value)
bool operator!=(const tfloat rhs) const
static double down(double &value)
void sal(double &lhs, unsigned rhs)
Shift arithmetically left.
bool operator>(const tfloat rhs) const
tfloat & operator/=(const tfloat rhs)
Divide.
void sar(double &lhs, unsigned rhs)
Shift arithmetically right.
tfloat & operator+=(const tfloat rhs)