2010-02-08 17:23:39 +01:00
|
|
|
/* Copyright (c) 2010 Wildfire Games
|
2009-04-18 19:00:33 +02:00
|
|
|
*
|
2010-02-08 17:23:39 +01:00
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining
|
|
|
|
* a copy of this software and associated documentation files (the
|
|
|
|
* "Software"), to deal in the Software without restriction, including
|
|
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
|
|
* the following conditions:
|
|
|
|
*
|
|
|
|
* 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.
|
2009-04-18 19:00:33 +02:00
|
|
|
*/
|
|
|
|
|
2009-04-18 19:51:05 +02:00
|
|
|
/*
|
|
|
|
* various utility functions.
|
2006-04-12 01:59:08 +02:00
|
|
|
*/
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
2005-03-18 23:07:55 +01:00
|
|
|
|
|
|
|
low-level aka "lib"
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
this codebase was grown from modules shared between several projects,
|
|
|
|
i.e. my personal library; hence the name "lib". it has been expanded to
|
|
|
|
fit the needs of 0ad - in particular, resource loading.
|
|
|
|
|
|
|
|
owing to the dual-use situation, the 0ad coding conventions are not met;
|
|
|
|
also, major changes are ill-advised because they may break other projects.
|
|
|
|
|
|
|
|
|
|
|
|
design goals
|
|
|
|
------------
|
|
|
|
|
|
|
|
- fast and low-overhead, including startup time
|
|
|
|
- portable: must run on Win32, Mac OS X and Linux
|
|
|
|
- reusable across projects, i.e. no dependency on a
|
|
|
|
central 'manager' that ties modules together.
|
|
|
|
|
|
|
|
|
|
|
|
scope
|
|
|
|
-----
|
|
|
|
|
|
|
|
- POSIX definitions
|
|
|
|
- resource management
|
|
|
|
- debugging tools (including memory tracker)
|
|
|
|
- low-level helper functions, e.g. ADTs, endian conversion and timing
|
|
|
|
- platform-dependent system/feature detection
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
**/
|
2005-03-18 23:07:55 +01:00
|
|
|
|
2007-05-07 18:33:24 +02:00
|
|
|
#ifndef INCLUDED_LIB
|
|
|
|
#define INCLUDED_LIB
|
2004-03-03 00:56:51 +01:00
|
|
|
|
2011-04-30 15:22:46 +02:00
|
|
|
#include <cmath> // fabsf
|
2007-05-26 18:39:26 +02:00
|
|
|
#include <limits> // numeric_limits
|
|
|
|
#include <stdexcept> // out_of_range
|
2014-05-26 18:48:28 +02:00
|
|
|
#include <algorithm> // min, max
|
2005-06-28 06:12:50 +02:00
|
|
|
|
2010-07-25 19:10:57 +02:00
|
|
|
template<typename T>
|
|
|
|
T Clamp(T val, T min, T max)
|
|
|
|
{
|
2011-04-30 15:01:45 +02:00
|
|
|
ASSERT(min <= max);
|
2010-07-25 19:10:57 +02:00
|
|
|
return std::max(min, std::min(val, max));
|
|
|
|
}
|
|
|
|
|
2010-04-06 14:06:02 +02:00
|
|
|
template<typename T>
|
|
|
|
T DivideRoundUp(T dividend, T divisor)
|
|
|
|
{
|
2011-04-30 15:01:45 +02:00
|
|
|
ASSERT(divisor != 0);
|
2010-04-06 14:06:02 +02:00
|
|
|
return (dividend + divisor-1) / divisor;
|
|
|
|
}
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/**
|
|
|
|
* are the given floats nearly "equal"?
|
|
|
|
*
|
|
|
|
* @return whether the numbers are within "epsilon" of each other.
|
|
|
|
*
|
|
|
|
* notes:
|
|
|
|
* - the epsilon magic number varies with the magnitude of the inputs.
|
|
|
|
* we use a sane default, but don't use this routine for very
|
|
|
|
* large/small comparands.
|
|
|
|
* - floating-point numbers don't magically lose precision. addition,
|
|
|
|
* subtraction and multiplication results are precise up to the mantissa's
|
|
|
|
* least-significant bit. only division, sqrt, sin/cos and other
|
2011-04-30 15:22:46 +02:00
|
|
|
* transcendental operations introduce error.
|
2006-05-31 06:01:59 +02:00
|
|
|
**/
|
2007-01-01 22:25:47 +01:00
|
|
|
inline bool feq(double d1, double d2, double epsilon = 0.00001)
|
|
|
|
{
|
|
|
|
return fabs(d1 - d2) < epsilon;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool feqf(float f1, float f2, float epsilon = 0.001f)
|
2006-05-31 06:01:59 +02:00
|
|
|
{
|
|
|
|
return fabsf(f1 - f2) < epsilon;
|
|
|
|
}
|
2005-10-19 19:16:34 +02:00
|
|
|
|
2007-05-26 17:34:10 +02:00
|
|
|
inline bool IsSimilarMagnitude(double d1, double d2, const double relativeErrorTolerance = 0.05)
|
|
|
|
{
|
|
|
|
const double relativeError = fabs(d1/d2 - 1.0);
|
|
|
|
if(relativeError > relativeErrorTolerance)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2004-06-01 19:34:12 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// type conversion
|
2005-08-09 18:23:19 +02:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
// note: these avoid a common mistake in using >> (ANSI requires
|
|
|
|
// shift count be less than the bit width of the type).
|
2006-03-15 06:18:32 +01:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
extern u32 u64_hi(u64 x); /// return upper 32-bits
|
|
|
|
extern u32 u64_lo(u64 x); /// return lower 32-bits
|
|
|
|
extern u16 u32_hi(u32 x); /// return upper 16-bits
|
|
|
|
extern u16 u32_lo(u32 x); /// return lower 16-bits
|
2006-03-15 06:18:32 +01:00
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
extern u64 u64_from_u32(u32 hi, u32 lo); /// assemble u64 from u32
|
|
|
|
extern u32 u32_from_u16(u16 hi, u16 lo); /// assemble u32 from u16
|
2005-08-09 18:23:19 +02:00
|
|
|
|
2007-05-26 17:34:10 +02:00
|
|
|
// safe downcasters: cast from any integral type to u32 or u16;
|
|
|
|
// issues warning if larger than would fit in the target type.
|
|
|
|
//
|
|
|
|
// these are generally useful but included here (instead of e.g. lib.h) for
|
|
|
|
// several reasons:
|
|
|
|
// - including implementation in lib.h doesn't work because the definition
|
2011-04-30 15:01:45 +02:00
|
|
|
// of ENSURE in turn requires lib.h's STMT.
|
2007-05-26 17:34:10 +02:00
|
|
|
// - separate compilation of templates via export isn't supported by
|
|
|
|
// most compilers.
|
|
|
|
|
2011-03-11 17:29:27 +01:00
|
|
|
template<typename T> u8 u8_from_larger(T x)
|
2007-05-26 17:34:10 +02:00
|
|
|
{
|
2011-03-11 17:29:27 +01:00
|
|
|
const u8 max = std::numeric_limits<u8>::max();
|
2007-05-26 17:34:10 +02:00
|
|
|
if((u64)x > (u64)max)
|
2011-03-11 17:29:27 +01:00
|
|
|
throw std::out_of_range("u8_from_larger");
|
|
|
|
return (u8)(x & max);
|
2007-05-26 17:34:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T> u16 u16_from_larger(T x)
|
|
|
|
{
|
|
|
|
const u16 max = std::numeric_limits<u16>::max();
|
|
|
|
if((u64)x > (u64)max)
|
|
|
|
throw std::out_of_range("u16_from_larger");
|
|
|
|
return (u16)(x & max);
|
|
|
|
}
|
|
|
|
|
2011-03-11 17:29:27 +01:00
|
|
|
template<typename T> u32 u32_from_larger(T x)
|
|
|
|
{
|
|
|
|
const u32 max = std::numeric_limits<u32>::max();
|
|
|
|
if((u64)x > (u64)max)
|
|
|
|
throw std::out_of_range("u32_from_larger");
|
|
|
|
return (u32)(x & max);
|
|
|
|
}
|
|
|
|
|
2006-05-31 06:01:59 +02:00
|
|
|
/// convert double to u8; verifies number is in range.
|
2007-05-09 23:01:11 +02:00
|
|
|
extern u8 u8_from_double(double in);
|
2006-05-31 06:01:59 +02:00
|
|
|
/// convert double to u16; verifies number is in range.
|
2007-05-09 23:01:11 +02:00
|
|
|
extern u16 u16_from_double(double in);
|
2006-02-03 05:02:53 +01:00
|
|
|
|
2007-05-07 18:33:24 +02:00
|
|
|
#endif // #ifndef INCLUDED_LIB
|