Line data Source code
1 : /* Copyright (C) 2019 Wildfire Games.
2 : *
3 : * Permission is hereby granted, free of charge, to any person obtaining
4 : * a copy of this software and associated documentation files (the
5 : * "Software"), to deal in the Software without restriction, including
6 : * without limitation the rights to use, copy, modify, merge, publish,
7 : * distribute, sublicense, and/or sell copies of the Software, and to
8 : * permit persons to whom the Software is furnished to do so, subject to
9 : * the following conditions:
10 : *
11 : * The above copyright notice and this permission notice shall be included
12 : * in all copies or substantial portions of the Software.
13 : *
14 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 : * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 : * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 : * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 : * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 : */
22 :
23 : /*
24 : * various utility functions.
25 : */
26 :
27 : /**
28 :
29 : low-level aka "lib"
30 : -------------------
31 :
32 : this codebase was grown from modules shared between several projects,
33 : i.e. my personal library; hence the name "lib". it has been expanded to
34 : fit the needs of 0ad - in particular, resource loading.
35 :
36 : owing to the dual-use situation, the 0ad coding conventions are not met;
37 : also, major changes are ill-advised because they may break other projects.
38 :
39 :
40 : design goals
41 : ------------
42 :
43 : - fast and low-overhead, including startup time
44 : - portable: must run on Win32, Mac OS X and Linux
45 : - reusable across projects, i.e. no dependency on a
46 : central 'manager' that ties modules together.
47 :
48 :
49 : scope
50 : -----
51 :
52 : - POSIX definitions
53 : - resource management
54 : - debugging tools (including memory tracker)
55 : - low-level helper functions, e.g. ADTs, endian conversion and timing
56 : - platform-dependent system/feature detection
57 :
58 : **/
59 :
60 : #ifndef INCLUDED_LIB
61 : #define INCLUDED_LIB
62 :
63 : #include <cmath> // fabsf
64 : #include <limits> // numeric_limits
65 : #include <stdexcept> // out_of_range
66 :
67 : template<typename T>
68 20 : T DivideRoundUp(T dividend, T divisor)
69 : {
70 20 : ASSERT(divisor != 0);
71 20 : return (dividend + divisor-1) / divisor;
72 : }
73 :
74 : /**
75 : * are the given floats nearly "equal"?
76 : *
77 : * @return whether the numbers are within "epsilon" of each other.
78 : *
79 : * notes:
80 : * - the epsilon magic number varies with the magnitude of the inputs.
81 : * we use a sane default, but don't use this routine for very
82 : * large/small comparands.
83 : * - floating-point numbers don't magically lose precision. addition,
84 : * subtraction and multiplication results are precise up to the mantissa's
85 : * least-significant bit. only division, sqrt, sin/cos and other
86 : * transcendental operations introduce error.
87 : **/
88 20 : inline bool feq(double d1, double d2, double epsilon = 0.00001)
89 : {
90 20 : return fabs(d1 - d2) < epsilon;
91 : }
92 :
93 : inline bool feqf(float f1, float f2, float epsilon = 0.001f)
94 : {
95 : return fabsf(f1 - f2) < epsilon;
96 : }
97 :
98 : inline bool IsSimilarMagnitude(double d1, double d2, const double relativeErrorTolerance = 0.05)
99 : {
100 : const double relativeError = fabs(d1/d2 - 1.0);
101 : if(relativeError > relativeErrorTolerance)
102 : return false;
103 : return true;
104 : }
105 :
106 :
107 : //-----------------------------------------------------------------------------
108 : // type conversion
109 :
110 : // note: these avoid a common mistake in using >> (ANSI requires
111 : // shift count be less than the bit width of the type).
112 :
113 : extern u32 u64_hi(u64 x); /// return upper 32-bits
114 : extern u32 u64_lo(u64 x); /// return lower 32-bits
115 : extern u16 u32_hi(u32 x); /// return upper 16-bits
116 : extern u16 u32_lo(u32 x); /// return lower 16-bits
117 :
118 : extern u64 u64_from_u32(u32 hi, u32 lo); /// assemble u64 from u32
119 : extern u32 u32_from_u16(u16 hi, u16 lo); /// assemble u32 from u16
120 :
121 : // safe downcasters: cast from any integral type to u32 or u16;
122 : // issues warning if larger than would fit in the target type.
123 : //
124 : // these are generally useful but included here (instead of e.g. lib.h) for
125 : // several reasons:
126 : // - including implementation in lib.h doesn't work because the definition
127 : // of ENSURE in turn requires lib.h's STMT.
128 : // - separate compilation of templates via export isn't supported by
129 : // most compilers.
130 :
131 : template<typename T> u8 u8_from_larger(T x)
132 : {
133 : const u8 max = std::numeric_limits<u8>::max();
134 : if((u64)x > (u64)max)
135 : throw std::out_of_range("u8_from_larger");
136 : return (u8)(x & max);
137 : }
138 :
139 0 : template<typename T> u16 u16_from_larger(T x)
140 : {
141 0 : const u16 max = std::numeric_limits<u16>::max();
142 0 : if((u64)x > (u64)max)
143 0 : throw std::out_of_range("u16_from_larger");
144 0 : return (u16)(x & max);
145 : }
146 :
147 0 : template<typename T> u32 u32_from_larger(T x)
148 : {
149 0 : const u32 max = std::numeric_limits<u32>::max();
150 0 : if((u64)x > (u64)max)
151 0 : throw std::out_of_range("u32_from_larger");
152 0 : return (u32)(x & max);
153 : }
154 :
155 : /// convert double to u8; verifies number is in range.
156 : extern u8 u8_from_double(double in);
157 : /// convert double to u16; verifies number is in range.
158 : extern u16 u16_from_double(double in);
159 :
160 : #endif // #ifndef INCLUDED_LIB
|