source: Revenant/marslib/include/mars_util.h@ 7ef8ec4

port/mars-tycoon
Last change on this file since 7ef8ec4 was 80a6a52, checked in by Jonathan Neufeld <support@…>, 3 years ago

Get to a compile state for terrain procedural generation

  • Property mode set to 100755
File size: 15.5 KB
Line 
1#pragma once
2
3#include <exception>
4#include <limits>
5#include <assert.h>
6#include <string.h>
7
8#include "mars_calc.h"
9#include "mars_linalg.h"
10#include "mars_ptr.h"
11
12#define STRINGIFY(a) #a
13
14#define PARALLEL_FOR(i)
15#ifdef __pragma
16 __pragma(omp parallel for private(i))
17#elif defined(_Pragma)
18 _Pragma(STRINGIFY( omp parallel for private(i) ))
19#endif
20
21#define PARALLEL_FOR2(i,j)
22#ifdef __pragma
23 __pragma(omp parallel for private(i,j))
24#elif defined(_Pragma)
25 _Pragma(STRINGIFY( omp parallel for private(i,j) ))
26#endif
27
28namespace mars
29{
30 template< typename T >
31 struct BaseNumerics
32 {
33 static inline T zero () { return static_cast< T > (0); }
34 static inline T max () { return std::numeric_limits< T >::max(); }
35 };
36
37 template< typename T >
38 struct IntegralNumerics : public BaseNumerics< T >
39 {
40 static inline T step() { return static_cast< T > (1); }
41 static inline T min () { return std::numeric_limits< T >::min(); }
42 };
43
44 template< typename T >
45 struct RationalNumerics : public BaseNumerics< T >
46 {
47 static inline T step () { return std::numeric_limits< T >::epsilon(); }
48 static inline T min () { return std::numeric_limits< T >::lowest(); }
49 };
50
51 template< typename T >
52 struct Numerics;
53
54 template <>
55 struct Numerics< float > : public RationalNumerics< float >
56 {
57 typedef double UP;
58 typedef float POS;
59 };
60 template <>
61 struct Numerics< double > : public RationalNumerics< double >
62 {
63 typedef long double UP;
64 typedef double POS;
65 };
66 template <>
67 struct Numerics< long double > : public RationalNumerics< long double >
68 {
69 typedef long double UP;
70 typedef long double POS;
71 };
72
73 template <>
74 struct Numerics< signed char > : public IntegralNumerics< signed char >
75 {
76 typedef signed short UP;
77 typedef unsigned char POS;
78 };
79 template <>
80 struct Numerics< unsigned char > : public IntegralNumerics< unsigned char >
81 {
82 typedef unsigned short UP;
83 typedef unsigned char POS;
84 };
85
86 template <>
87 struct Numerics< signed short > : public IntegralNumerics< signed short >
88 {
89 typedef signed int UP;
90 typedef unsigned short POS;
91 };
92 template <>
93 struct Numerics< unsigned short > : public IntegralNumerics< unsigned short >
94 {
95 typedef unsigned int UP;
96 typedef unsigned short POS;
97 };
98
99 template <>
100 struct Numerics< signed int > : public IntegralNumerics< signed int >
101 {
102 typedef signed long long UP;
103 typedef unsigned int POS;
104 };
105 template <>
106 struct Numerics< unsigned int > : public IntegralNumerics< unsigned int >
107 {
108 typedef unsigned long long UP;
109 typedef unsigned int POS;
110 };
111
112 template <>
113 struct Numerics< signed long > : public IntegralNumerics< signed long >
114 {
115 typedef signed long long UP;
116 typedef unsigned long POS;
117 };
118 template <>
119 struct Numerics< unsigned long > : public IntegralNumerics< unsigned long >
120 {
121 typedef unsigned long long UP;
122 typedef unsigned long POS;
123 };
124
125 template <>
126 struct Numerics< signed long long > : public IntegralNumerics< signed long long >
127 {
128 typedef signed long long UP;
129 typedef unsigned long long POS;
130 };
131 template <>
132 struct Numerics< unsigned long long > : public IntegralNumerics< unsigned long long >
133 {
134 typedef unsigned long long UP;
135 typedef unsigned long long POS;
136 };
137
138 class RingBufferBoundsEx : public std::exception
139 {
140 public:
141 const unsigned int index, count;
142
143 RingBufferBoundsEx (const unsigned int i, const unsigned int count)
144 : index (i), count(count) {}
145 };
146
147 template <typename T>
148 class RingBuffer
149 {
150 private:
151 T * _v;
152 unsigned int _i;
153
154 inline unsigned int index (const unsigned int i) const
155 {
156#ifdef _DEBUG
157 if (i >= count)
158 throw RingBufferBoundsEx (i, count);
159#endif
160 return (_i + count - i) % count;
161 }
162
163 public:
164 const unsigned int count;
165
166 inline RingBuffer (const unsigned short nSize)
167 : _v(new T[nSize]), _i(0), count(nSize)
168 {
169 memset(_v, 0, sizeof(_v[0]) * count);
170 }
171
172 inline RingBuffer (const RingBuffer <T> & copy)
173 : _v(new T[copy.count]), count(copy.count)
174 {
175 memcpy (_v, copy._v, count * sizeof(_v[0]));
176 }
177
178 inline T & operator [] (unsigned int i) { return _v[index(i)]; }
179 inline const T & operator [] (unsigned int i) const { return _v[index(i)]; }
180 inline T & last () { return _v[_i]; }
181 inline const T & last () const { return _v[_i]; }
182 inline void operator ++ () { _i = (_i + 1) % count; }
183
184 inline void add (const T & val)
185 {
186 _v[_i = (_i + 1) % count] = val;
187 }
188 void clear ()
189 {
190 for (unsigned int i = 0; i < count; ++i)
191 _v[i] = T();
192 }
193
194 inline ~RingBuffer () { delete _v; }
195 };
196
197 template <typename T, typename ST = Numerics< T > >
198 class Range
199 {
200 public:
201 typedef T Precision;
202
203 T minimum, maximum;
204
205 Range()
206 : minimum(ST::zero()), maximum(ST::zero()) {}
207 Range (const T minimum, const T maximum)
208 : minimum(minimum), maximum(maximum)
209 { assert (minimum <= maximum); }
210
211 inline virtual void update ()
212 { assert(minimum <= maximum); }
213
214 inline bool contains (const T val) const
215 { return val >= minimum && val <= maximum; }
216
217 inline T clamp (const T value) const
218 { return std::min(maximum, std::max(minimum, value)); }
219
220 inline Range & operator |= (const Range & other)
221 {
222 minimum = std::min(minimum, other.minimum);
223 maximum = std::max(maximum, other.maximum);
224 return *this;
225 }
226 };
227
228 template <typename T >
229 class RangeX : public Range< T >
230 {
231 public:
232 typedef T Precision;
233 typedef typename Numerics< typename Numerics< T >::POS >::UP Delta;
234 typedef typename Numerics< T >::UP SuperPrecision;
235
236 T step;
237 Delta delta;
238
239 RangeX()
240 : Range<T>(), step(Numerics< T >::step()), delta(static_cast< Delta > (Numerics< Delta >::zero())) {}
241 RangeX (const T minimum, const T maximum)
242 : Range<T>(minimum, maximum), delta(static_cast< SuperPrecision > (maximum) - minimum + Numerics< T >::step()), step(Numerics< T >::step())
243 { assert (delta > Numerics< Delta >::zero()); }
244 RangeX (const T minimum, const T maximum, const T step)
245 : Range<T>(minimum, maximum), delta(static_cast< SuperPrecision > (maximum) - minimum + Numerics< T >::step()), step(step)
246 { assert (delta > Numerics< Delta >::zero() && step > Numerics< T >::zero()); }
247 RangeX (const Range<T> & rng)
248 : Range<T>(rng), delta(static_cast< SuperPrecision > (rng.maximum) - rng.minimum + Numerics< T >::step()), step(Numerics< T >::step())
249 { assert (delta > Numerics< Delta >::zero() && step > Numerics< T >::zero()); }
250 RangeX (const RangeX<T> & copy)
251 : Range<T>(copy), delta(copy.delta), step(copy.step) {}
252
253 inline virtual void update ()
254 {
255 Range<T>::update();
256 assert (step > Numerics< T >::zero());
257 delta = static_cast< SuperPrecision > (this->maximum) - this->minimum + Numerics< T >::step();
258 }
259
260 inline T next() const
261 {
262 assert (this->minimum <= this->maximum && step > Numerics< T >::zero());
263 return next1<T> (identity<T>());
264 }
265
266 inline T median () const
267 {
268 assert (this->minimum <= this->maximum && step > Numerics< T >::zero());
269 return static_cast <T> (this->minimum + delta / 2);
270 }
271 inline Range<T> operator / (const T n) const
272 {
273 assert (this->minimum <= this->maximum && step > Numerics< T >::zero());
274 const T min2 = this->minimum / n;
275 return Range<T> (min2, min2 + delta / n);
276 }
277
278 RangeX & operator = (const Range< T > & rval)
279 {
280 this->minimum = rval.minimum;
281 this->maximum = rval.maximum;
282 update();
283 return *this;
284 }
285
286 private:
287 template <typename J>
288 inline J nextf () const { return static_cast< J > (static_cast <J> (rand()) / static_cast <J> (RAND_MAX) * delta) + this->minimum; }
289
290 template <typename J> inline J next1 (identity<J>) const { return static_cast <J> (fmod(rand(), delta)) + this->minimum; }
291 inline double next1 (identity<double>) const { return nextf<double>(); }
292 inline float next1 (identity<float>) const { return nextf<float>(); }
293 };
294
295 template <typename T>
296 class BBox
297 {
298 private:
299 inline void assertions () const
300 {
301 // Must not be empty for operations
302 assert(!empty());
303
304 // Must be a signed type
305 assert(static_cast <T> (0) - 1 < 0);
306
307 // Assert bounds
308 assert(left <= right && top <= bottom);
309 }
310
311 public:
312 T left, top, right, bottom;
313
314 inline BBox ()
315 : left(1), top(1), right(0), bottom(0) {}
316
317 template <typename J>
318 inline BBox (const BBox< J > & copy)
319 :
320 left(static_cast< T > (copy.left)),
321 top(static_cast< T > (copy.top)),
322 right(static_cast< T > (copy.right)),
323 bottom(static_cast< T > (copy.bottom))
324 {}
325
326 inline BBox (const T left, const T top, const T right, const T bottom)
327 : left(left), top(top), right(right), bottom(bottom)
328 { assertions(); }
329
330 inline BBox (const vector2D< T > & vMin, const vector2D< T > &vMax)
331 : left(vMin.x), top(vMin.y), right(vMax.x), bottom(vMax.y)
332 { assertions(); }
333
334 inline T getWidth() const { return right - left + 1; }
335 inline T getHeight() const { return bottom - top + 1; }
336
337 inline bool empty () const { return getWidth() == 0 && getHeight() == 0; }
338
339 inline bool inside (const vector2D< T > & v, const T pad = 0) const
340 { return inside(v.x, v.y, pad); }
341 inline bool inside (const T x, const T y, const T pad = 0) const
342 {
343 assertions();
344 return
345 x >= left + pad && x <= right - pad &&
346 y >= top + pad && y <= bottom - pad;
347 }
348 inline bool intersects (const BBox< T > & other) const
349 {
350 assertions();
351 return
352 right >= other.left &&
353 bottom >= other.top &&
354 left <= other.right &&
355 top <= other.bottom;
356 }
357 inline void add (const vector2D< T > & p)
358 {
359 assertions();
360 if (p.x < left)
361 left = p.x;
362 if (p.x > right)
363 right = p.x;
364 if (p.y < top)
365 top = p.y;
366 if (p.y > bottom)
367 bottom = p.y;
368 }
369 inline void add (const BBox< T > & bbox)
370 {
371 assertions();
372 if (bbox.left < left)
373 left = bbox.left;
374 if (bbox.right > right)
375 right = bbox.right;
376 if (bbox.top < top)
377 top = bbox.top;
378 if (bbox.bottom > bottom)
379 bottom = bbox.bottom;
380 }
381 inline vector2D< T > getMinimum () const { return vector2D< T > (left, top); }
382 inline vector2D< T > getMaximum () const { return vector2D< T > (right, bottom); }
383 inline bool operator () (const T x, const T y) const { return inside(x, y); }
384 inline const Range< T > horizontal(const T step = 1) const { return mars::Range< T > (left, right, step); }
385 inline const Range< T > vertical(const T step = 1) const { return mars::Range< T > (top, bottom, step); }
386
387 template< typename F >
388 inline BBox< F > operator << (const unsigned short n) const
389 {
390 return BBox< F > (
391 static_cast< F > (left) << n,
392 static_cast< F > (top) << n,
393 static_cast< F > (right) << n,
394 static_cast< F > (bottom) << n
395 );
396 }
397 template< typename F >
398 inline BBox< F > operator >> (const unsigned short n) const
399 {
400 return BBox< F > (
401 static_cast< F > (left >> n),
402 static_cast< F > (top >> n),
403 static_cast< F > (right >> n),
404 static_cast< F > (bottom >> n)
405 );
406 }
407
408 template< typename F >
409 inline operator BBox< F > () const
410 {
411 assertions();
412 return BBox< F > (
413 static_cast< F > (left),
414 static_cast< F > (top),
415 static_cast< F > (right),
416 static_cast< F > (bottom)
417 );
418 }
419
420 template< typename F >
421 inline vector2D< F > clamp (const vector2D< F > & v) const
422 {
423 assertions();
424 return
425 vector2D< F > (
426 std::min(static_cast< F > (right), std::max(static_cast< F > (left), v.x)),
427 std::min(static_cast< F > (top), std::max(static_cast< F > (bottom), v.y))
428 );
429 }
430 template< typename F >
431 inline vector3D< F > clampXY (const vector3D< F > & v) const
432 {
433 assertions();
434 return
435 vector3D< F > (
436 std::min(static_cast< F > (right), std::max(static_cast< F > (left), v.x)),
437 std::min(static_cast< F > (bottom), std::max(static_cast< F > (top), v.y)),
438 v.z
439 );
440 }
441
442 inline bool operator == (const BBox< T > & other) const
443 {
444 return
445 left == other.left &&
446 top == other.top &&
447 right == other.right &&
448 bottom == other.bottom;
449 }
450
451 template <typename J>
452 inline const BBox & operator = (const BBox< J > & bbox)
453 {
454 left = static_cast <T> (bbox.left);
455 right = static_cast <T> (bbox.right);
456 top = static_cast <T> (bbox.top);
457 bottom = static_cast <T> (bbox.bottom);
458
459 return *this;
460 }
461
462 inline BBox operator - (const vector2D< T > & v) const
463 {
464 assertions();
465 return BBox (
466 left - v.x,
467 top - v.y,
468 right - v.x,
469 bottom - v.y
470 );
471 }
472 inline BBox operator + (const vector2D< T > & v) const
473 {
474 assertions();
475 return BBox (
476 left + v.x,
477 top + v.y,
478 right + v.x,
479 bottom + v.y
480 );
481 }
482
483 inline BBox & operator -= (const vector2D< T > & v)
484 {
485 assertions();
486 left -= v.x;
487 top -= v.y;
488 right -= v.x;
489 bottom -= v.y;
490 return *this;
491 }
492 inline BBox & operator += (const vector2D< T > & v)
493 {
494 assertions();
495 left += v.x;
496 top += v.y;
497 right += v.x;
498 bottom += v.y;
499 return *this;
500 }
501 };
502
503 template <typename T>
504 class Magnitudinal
505 {
506 private:
507 T _val, _sq;
508
509 public:
510 enum ValueType
511 {
512 Normal,
513 Squared
514 };
515
516 Magnitudinal ()
517 : _val(0), _sq(0) {}
518
519 Magnitudinal (const Magnitudinal & copy)
520 : _val(copy._val), _sq(copy._sq) {}
521
522 Magnitudinal (const T val, const ValueType envt = Normal)
523 : _val(envt == Normal ? val : sqrt(val)), _sq(envt == Squared ? val : mars::SQ(val)) {}
524
525 static Magnitudinal hypotenuseOf (const T x, const T y)
526 { return Magnitudinal(mars::SQ(x) + mars::SQ(y), Squared); }
527
528 Magnitudinal & operator = (const Magnitudinal & rval)
529 {
530 _sq = rval._sq;
531 _val = rval._val;
532 return *this;
533 }
534
535 Magnitudinal & operator += (const Magnitudinal & rval)
536 {
537 _sq += rval._sq;
538 _val += rval._val;
539 }
540
541 inline operator const T () const { return _val; }
542 inline operator T & () { return _val; }
543 inline T SQ() const { return _sq; }
544
545 inline T compareTo (const float x, const float y) const
546 { return (mars::SQ(x) + mars::SQ(y)) - _sq; }
547 };
548
549 class BitSet
550 {
551 private:
552 static const unsigned char UINTBITS = sizeof(unsigned int) * 8;
553
554 unsigned int * _bits;
555
556 inline void init () { memset(_bits, 0, size / sizeof(unsigned int)); }
557
558 public:
559 class Bit
560 {
561 private:
562 unsigned int
563 * _pointer,
564 _mask;
565
566 public:
567 inline Bit (const unsigned char bit, unsigned int * pointer)
568 : _mask(1 << bit), _pointer(pointer) {}
569
570 inline bool operator = (const bool b)
571 {
572 *_pointer = (*_pointer & ~_mask) | ((b ? ~0 : 0) & _mask);
573 return b;
574 }
575 inline operator bool () const { return (*_pointer & _mask) != 0; }
576 };
577
578 const unsigned int size;
579
580 inline BitSet (const BitSet & copy)
581 : _bits(new unsigned int[copy.size / UINTBITS]), size(copy.size)
582 { memcpy (_bits, copy._bits, size / 8); }
583 inline BitSet ()
584 : _bits(NULL), size(0) { init(); }
585 inline BitSet (const unsigned int nSize)
586 : _bits(new unsigned int[nSize / UINTBITS]), size(nSize) { init (); }
587
588 inline const Bit operator [] (const unsigned int i) const
589 { return Bit(i % UINTBITS, &_bits[i / UINTBITS]); }
590
591 inline void set(const bool bFlag, const Range< unsigned int > & range)
592 {
593 assert(bFlag == 1 || bFlag == 0);
594
595 const int
596 n0 = static_cast< int > (range.minimum / UINTBITS),
597 n1 = static_cast< int > (range.maximum / UINTBITS);
598
599 const unsigned int
600 b0 = range.minimum % UINTBITS,
601 b1 = range.maximum % UINTBITS;
602 const unsigned int
603 nBoolMask = (bFlag ? ~0 : 0);
604
605 if (n1 - 1 >= n0 + 1)
606 memset(&_bits[n0], nBoolMask, n1 - n0 + 1);
607
608 if (n1 > n0)
609 {
610 _bits[n0 - 1] = (_bits[n0 - 1] & ((1 << (UINTBITS - b0)) - 1)) | (nBoolMask & ~((1 << (UINTBITS - b0)) - 1));
611 _bits[n1 + 1] = (_bits[n1 + 1] & ~((1 << b1) - 1)) | (nBoolMask & (1 << b1) - 1);
612 } else
613 {
614 const unsigned int nMask =
615 ~0 & ~((1 << (UINTBITS - b0)) - 1) & ((1 << b1) - 1);
616
617 _bits[range.minimum / UINTBITS] = (_bits[range.minimum / UINTBITS] & ~nMask) | (nBoolMask & nMask);
618 }
619 }
620
621 inline ~BitSet()
622 { delete [] _bits; }
623 };
624}
Note: See TracBrowser for help on using the repository browser.