Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
lib.h
Go to the documentation of this file.
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
29low-level aka "lib"
30-------------------
31
32this codebase was grown from modules shared between several projects,
33i.e. my personal library; hence the name "lib". it has been expanded to
34fit the needs of 0ad - in particular, resource loading.
35
36owing to the dual-use situation, the 0ad coding conventions are not met;
37also, major changes are ill-advised because they may break other projects.
38
39
40design 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
49scope
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
67template<typename T>
68T DivideRoundUp(T dividend, T divisor)
69{
70 ASSERT(divisor != 0);
71 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 **/
88inline bool feq(double d1, double d2, double epsilon = 0.00001)
89{
90 return fabs(d1 - d2) < epsilon;
91}
92
93inline bool feqf(float f1, float f2, float epsilon = 0.001f)
94{
95 return fabsf(f1 - f2) < epsilon;
96}
97
98inline 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
113extern u32 u64_hi(u64 x); /// return upper 32-bits
114extern u32 u64_lo(u64 x); /// return lower 32-bits
115extern u16 u32_hi(u32 x); /// return upper 16-bits
116extern u16 u32_lo(u32 x); /// return lower 16-bits
117
118extern u64 u64_from_u32(u32 hi, u32 lo); /// assemble u64 from u32
119extern 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
131template<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
139template<typename T> u16 u16_from_larger(T x)
140{
141 const u16 max = std::numeric_limits<u16>::max();
142 if((u64)x > (u64)max)
143 throw std::out_of_range("u16_from_larger");
144 return (u16)(x & max);
145}
146
147template<typename T> u32 u32_from_larger(T x)
148{
149 const u32 max = std::numeric_limits<u32>::max();
150 if((u64)x > (u64)max)
151 throw std::out_of_range("u32_from_larger");
152 return (u32)(x & max);
153}
154
155/// convert double to u8; verifies number is in range.
156extern u8 u8_from_double(double in);
157/// convert double to u16; verifies number is in range.
158extern u16 u16_from_double(double in);
159
160#endif // #ifndef INCLUDED_LIB
#define ASSERT(expr)
same as ENSURE in debug mode, does nothing in release mode.
Definition: debug.h:305
bool feq(double d1, double d2, double epsilon=0.00001)
are the given floats nearly "equal"?
Definition: lib.h:88
bool feqf(float f1, float f2, float epsilon=0.001f)
Definition: lib.h:93
u16 u16_from_larger(T x)
Definition: lib.h:139
u8 u8_from_double(double in)
convert double to u8; verifies number is in range.
Definition: lib.cpp:83
u8 u8_from_larger(T x)
assemble u32 from u16
Definition: lib.h:131
u32 u64_lo(u64 x)
return upper 32-bits
Definition: lib.cpp:49
u32 u32_from_u16(u16 hi, u16 lo)
assemble u64 from u32
Definition: lib.cpp:73
T DivideRoundUp(T dividend, T divisor)
Definition: lib.h:68
u16 u32_lo(u32 x)
return upper 16-bits
Definition: lib.cpp:59
u64 u64_from_u32(u32 hi, u32 lo)
return lower 16-bits
Definition: lib.cpp:65
u32 u64_hi(u64 x)
Definition: lib.cpp:44
bool IsSimilarMagnitude(double d1, double d2, const double relativeErrorTolerance=0.05)
Definition: lib.h:98
u32 u32_from_larger(T x)
Definition: lib.h:147
u16 u16_from_double(double in)
convert double to u16; verifies number is in range.
Definition: lib.cpp:97
u16 u32_hi(u32 x)
return lower 32-bits
Definition: lib.cpp:54
#define T(string_literal)
Definition: secure_crt.cpp:77
uint64_t u64
Definition: types.h:40
uint8_t u8
Definition: types.h:37
uint16_t u16
Definition: types.h:38
uint32_t u32
Definition: types.h:39