GteUIntegerFP32.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
10 #include <LowLevel/GteLogger.h>
12 #include <array>
13 #include <fstream>
14 
15 // Class UIntegerFP32 is designed to support fixed precision arithmetic
16 // using BSNumber and BSRational. It is not a general-purpose class for
17 // arithmetic of unsigned integers. The template parameter N is the
18 // number of 32-bit words required to store the precision for the desired
19 // computations (maximum number of bits is 32*N).
20 
21 // Uncomment this to trap when an attempt is made to create storage with
22 // more than N uint32_t items.
23 //
24 //#define GTE_ASSERT_ON_UINTEGERFP32_OUT_OF_RANGE
25 
26 // Uncomment this to collect statistics on how large the UIntegerFP32 storage
27 // becomes when using it for the UIntegerType of BSNumber. After a sequence
28 // of BSNumber operations, look at UIntegerFP32::msMaxSize in the debugger
29 // watch window. If the number is not too large, you might be safe in
30 // replacing the template parameter N by a smaller number. See class
31 // BSPrecision for code that allows you to compute maximum N.
32 //
33 // NOTE: Because UIntegerFP32::msMaxSize is a static member of a template
34 // class, if you expose this define, you must also declare in your code
35 // 'std::atomic<int32_t> gte::UIntegerFP32<N>::msMaxSize;'
36 //#define GTE_COLLECT_UINTEGERFP32_STATISTICS
37 
38 #if defined(GTE_COLLECT_UINTEGERFP32_STATISTICS)
40 #endif
41 
42 namespace gte
43 {
44 
45 template <int N>
46 class UIntegerFP32 : public UIntegerALU32<UIntegerFP32<N>>
47 {
48 public:
49  // Construction.
50  UIntegerFP32();
51  UIntegerFP32(UIntegerFP32 const& number);
52  UIntegerFP32(uint32_t number);
53  UIntegerFP32(uint64_t number);
54  UIntegerFP32(int numBits);
55 
56  // Assignment. Only mSize elements are copied.
57  UIntegerFP32& operator=(UIntegerFP32 const& number);
58 
59  // Support for std::move. The interface is required by BSNumber, but the
60  // std::move of std::array is a copy (no pointer stealing). Moreover,
61  // a std::array object in this class typically uses smaller than N
62  // elements, the actual size stored in mSize, so we do not want to move
63  // everything. Therefore, the move operator only copies the bits BUT
64  // BUT 'number' is modified as if you have stolen the data (mNumBits and
65  // mSize set to zero).
66  UIntegerFP32(UIntegerFP32&& number);
68 
69  // Member access.
70  void SetNumBits(uint32_t numBits);
71  inline int32_t GetNumBits() const;
72  inline std::array<uint32_t, N> const& GetBits() const;
73  inline std::array<uint32_t, N>& GetBits();
74  inline void SetBack(uint32_t value);
75  inline uint32_t GetBack() const;
76  inline int32_t GetSize() const;
77 
78  // Disk input/output. The fstream objects should be created using
79  // std::ios::binary. The return value is 'true' iff the operation
80  // was successful.
81  bool Write(std::ofstream& output) const;
82  bool Read(std::ifstream& input);
83 
84 private:
85  int32_t mNumBits, mSize;
86  std::array<uint32_t, N> mBits;
87 
88  friend class UnitTestBSNumber;
89 
90 #if defined(GTE_COLLECT_UINTEGERFP32_STATISTICS)
91  static std::atomic<int32_t> msMaxSize;
92 public:
93  static void SetMaxSizeToZero() { msMaxSize = 0; }
94  static int32_t GetMaxSize() { return msMaxSize; }
95 #endif
96 };
97 
98 
99 template <int N>
101  :
102  mNumBits(0),
103  mSize(0)
104 {
105  static_assert(N >= 1, "Invalid size N.");
106 }
107 
108 template <int N>
110 {
111  static_assert(N >= 1, "Invalid size N.");
112 
113  *this = number;
114 }
115 
116 template <int N>
118 {
119  static_assert(N >= 1, "Invalid size N.");
120 
121  if (number > 0)
122  {
123  int32_t first = GetLeadingBit(number);
124  int32_t last = GetTrailingBit(number);
125  mNumBits = first - last + 1;
126  mSize = 1;
127  mBits[0] = (number >> last);
128  }
129  else
130  {
131  mNumBits = 0;
132  mSize = 0;
133  }
134 
135 #if defined(GTE_COLLECT_UINTEGERFP32_STATISTICS)
136  AtomicMax(msMaxSize, mSize);
137 #endif
138 }
139 
140 template <int N>
142 {
143  static_assert(N >= 2, "N not large enough to store 64-bit integers.");
144 
145  if (number > 0)
146  {
147  int32_t first = GetLeadingBit(number);
148  int32_t last = GetTrailingBit(number);
149  number >>= last;
150  mNumBits = first - last + 1;
151  mSize = 1 + (mNumBits - 1) / 32;
152  mBits[0] = GTE_GET_LO_U64(number);
153  if (mSize > 1)
154  {
155  mBits[1] = GTE_GET_HI_U64(number);
156  }
157  }
158  else
159  {
160  mNumBits = 0;
161  mSize = 0;
162  }
163 
164 #if defined(GTE_COLLECT_UINTEGERFP32_STATISTICS)
165  AtomicMax(msMaxSize, mSize);
166 #endif
167 }
168 
169 template <int N>
171  :
172  mNumBits(numBits),
173  mSize(1 + (numBits - 1) / 32)
174 {
175  static_assert(N >= 1, "Invalid size N.");
176 
177 #if defined(GTE_ASSERT_ON_UINTEGERFP32_OUT_OF_RANGE)
178  LogAssert(mSize <= N, "N not large enough to store number of bits.");
179 #endif
180 
181 #if defined(GTE_COLLECT_UINTEGERFP32_STATISTICS)
182  AtomicMax(msMaxSize, mSize);
183 #endif
184 }
185 
186 template <int N>
188 {
189  static_assert(N >= 1, "Invalid size N.");
190 
191  mNumBits = number.mNumBits;
192  mSize = number.mSize;
193  std::copy(number.mBits.begin(), number.mBits.begin() + mSize,
194  mBits.begin());
195  return *this;
196 }
197 
198 template <int N>
200 {
201  *this = std::move(number);
202 }
203 
204 template <int N>
206 {
207  mNumBits = number.mNumBits;
208  mSize = number.mSize;
209  std::copy(number.mBits.begin(), number.mBits.begin() + mSize,
210  mBits.begin());
211  number.mNumBits = 0;
212  number.mSize = 0;
213  return *this;
214 }
215 
216 template <int N>
217 void UIntegerFP32<N>::SetNumBits(uint32_t numBits)
218 {
219  mNumBits = numBits;
220  mSize = 1 + (numBits - 1) / 32;
221 
222 #if defined(GTE_ASSERT_ON_UINTEGERFP32_OUT_OF_RANGE)
223  LogAssert(mSize <= N, "N not large enough to store number of bits.");
224 #endif
225 
226 #if defined(GTE_COLLECT_UINTEGERFP32_STATISTICS)
227  AtomicMax(msMaxSize, mSize);
228 #endif
229 }
230 
231 template <int N> inline
233 {
234  return mNumBits;
235 }
236 
237 template <int N> inline
238 std::array<uint32_t, N> const& UIntegerFP32<N>::GetBits() const
239 {
240  return mBits;
241 }
242 
243 template <int N> inline
244 std::array<uint32_t, N>& UIntegerFP32<N>::GetBits()
245 {
246  return mBits;
247 }
248 
249 template <int N> inline
251 {
252  mBits[mSize - 1] = value;
253 }
254 
255 template <int N> inline
256 uint32_t UIntegerFP32<N>::GetBack() const
257 {
258  return mBits[mSize - 1];
259 }
260 
261 template <int N> inline
263 {
264  return mSize;
265 }
266 
267 template <int N>
268 bool UIntegerFP32<N>::Write(std::ofstream& output) const
269 {
270  if (output.write((char const*)&mNumBits, sizeof(mNumBits)).bad())
271  {
272  return false;
273  }
274 
275  if (output.write((char const*)&mSize, sizeof(mSize)).bad())
276  {
277  return false;
278  }
279 
280  return output.write((char const*)&mBits[0],
281  mSize*sizeof(mBits[0])).good();
282 }
283 
284 template <int N>
285 bool UIntegerFP32<N>::Read(std::ifstream& input)
286 {
287  if (input.read((char*)&mNumBits, sizeof(mNumBits)).bad())
288  {
289  return false;
290  }
291 
292  if (input.read((char*)&mSize, sizeof(mSize)).bad())
293  {
294  return false;
295  }
296 
297  return input.read((char*)&mBits[0], mSize*sizeof(mBits[0])).good();
298 }
299 
300 
301 }
int32_t GetNumBits() const
bool Read(std::ifstream &input)
GTE_IMPEXP int32_t GetTrailingBit(uint32_t value)
#define LogAssert(condition, message)
Definition: GteLogger.h:86
UIntegerFP32 & operator=(UIntegerFP32 const &number)
GTE_IMPEXP int32_t GetLeadingBit(uint32_t value)
Definition: GteBitHacks.cpp:61
std::array< uint32_t, N > mBits
bool Write(std::ofstream &output) const
GLsizei const GLfloat * value
Definition: glcorearb.h:819
int32_t GetSize() const
std::array< uint32_t, N > const & GetBits() const
friend class UnitTestBSNumber
#define GTE_GET_HI_U64(v)
Definition: GteBitHacks.h:19
#define GTE_GET_LO_U64(v)
Definition: GteBitHacks.h:18
GLint first
Definition: glcorearb.h:400
GLenum GLenum GLenum input
Definition: glext.h:9913
void SetBack(uint32_t value)
uint32_t GetBack() const
void SetNumBits(uint32_t numBits)
T AtomicMax(std::atomic< T > &v0, T const &v1)


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:01