-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_float.h
156 lines (140 loc) · 3.54 KB
/
test_float.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright (c) 2010-2015 Sami Väisänen, Ensisoft
//
// http://www.ensisoft.com
//
// This software is copyrighted software. Unauthorized hacking, cracking, distribution
// and general assing around is prohibited.
// Redistribution and use in source and binary forms, with or without modification,
// without permission are prohibited.
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include <cstdint>
#include <cstdlib>
#include <cassert>
namespace real
{
class float32
{
public:
explicit
float32(double d) : m_f(d)
{}
explicit
float32(float f) : m_f(f)
{}
explicit
float32(uint32_t i) : m_i(i)
{}
int sign() const
{
// 1 for negative numbers, 0 for positive
return (m_i >> 31);
}
int exponent() const
{
return ((m_i >> 23) & 0xff);
}
int mantissa() const
{
return m_i & ((1 << 23) - 1);
}
float as_float() const
{
return m_f;
}
uint32_t as_uint() const
{
return m_i;
}
float32 operator++(int)
{
float32 ret(*this);
this->inc();
return ret;
}
float32& operator++()
{
this->inc();
return *this;
}
float32 operator--(int)
{
float32 ret(*this);
this->dec();
return ret;
}
float32& operator--()
{
this->dec();
return *this;
}
void inc()
{
++m_i;
}
void dec()
{
--m_i;
}
int ulps(const float32& other) const
{
return std::abs((long)m_i - (long)other.m_i);
}
bool is_zero() const
{
return !(m_i & 0x7FFFFFFF);
}
bool is_NaN() const
{
return exponent() == 255 && mantissa() != 0;
}
bool is_inf() const
{
return exponent() == 255 && mantissa() == 0;
}
private:
// little bit unsafe...
union {
float m_f;
uint32_t m_i;
};
};
inline
bool equals(float a, float b)
{
const float32 a32(a);
const float32 b32(b);
assert(!a32.is_NaN() && !a32.is_inf());
assert(!b32.is_NaN() && !b32.is_inf());
if (a32.sign() != b32.sign())
{
if (a32.is_zero() && b32.is_zero())
return true;
return false;
}
const int ulps = a32.ulps(b32);
return (ulps <= 1);
}
inline
bool operator==(const float32& f32, float f)
{
return equals(f32.as_float(), f);
}
inline
bool operator==(float f, const float32& f32)
{
return equals(f, f32.as_float());
}
#define F32(x) \
real::float32(x)
} // namespace