--- deliantra/server/include/util.h 2007/01/19 22:47:57 1.35 +++ deliantra/server/include/util.h 2007/05/11 08:00:00 1.44 @@ -1,6 +1,8 @@ #ifndef UTIL_H__ #define UTIL_H__ +//#define PREFER_MALLOC + #if __GNUC__ >= 3 # define is_constant(c) __builtin_constant_p (c) #else @@ -18,7 +20,7 @@ #include // use a gcc extension for auto declarations until ISO C++ sanctifies them -#define AUTODECL(var,expr) typeof(expr) var = (expr) +#define auto(var,expr) typeof(expr) var = (expr) // very ugly macro that basicaly declares and initialises a variable // that is in scope for the next statement only @@ -45,6 +47,58 @@ template static inline void swap (T& a, U& b) { T t=a; a=(T)b; b=(U)t; } +template +static inline T +lerp (T val, T min_in, T max_in, T min_out, T max_out) +{ + return (val - min_in) * (max_out - min_out) / (max_in - min_in) + min_out; +} + +// lots of stuff taken from FXT + +/* Rotate right. This is used in various places for checksumming */ +//TODO: that sucks, use a better checksum algo +static inline uint32_t +rotate_right (uint32_t c, uint32_t count = 1) +{ + return (c << (32 - count)) | (c >> count); +} + +static inline uint32_t +rotate_left (uint32_t c, uint32_t count = 1) +{ + return (c >> (32 - count)) | (c << count); +} + +// Return abs(a-b) +// Both a and b must not have the most significant bit set +static inline uint32_t +upos_abs_diff (uint32_t a, uint32_t b) +{ + long d1 = b - a; + long d2 = (d1 & (d1 >> 31)) << 1; + + return d1 - d2; // == (b - d) - (a + d); +} + +// Both a and b must not have the most significant bit set +static inline uint32_t +upos_min (uint32_t a, uint32_t b) +{ + int32_t d = b - a; + d &= d >> 31; + return a + d; +} + +// Both a and b must not have the most significant bit set +static inline uint32_t +upos_max (uint32_t a, uint32_t b) +{ + int32_t d = b - a; + d &= d >> 31; + return b - d; +} + // this is much faster than crossfires original algorithm // on modern cpus inline int @@ -135,7 +189,11 @@ template inline void sfree (T *ptr, int n = 1) throw () { +#ifdef PREFER_MALLOC + free (ptr); +#else g_slice_free1 (n * sizeof (T), (void *)ptr); +#endif } // a STL-compatible allocator that uses g_slice @@ -213,18 +271,18 @@ uint32_t next (); // uniform distribution - uint32_t operator ()(uint32_t r_max) + uint32_t operator ()(uint32_t num) { - return is_constant (r_max) - ? this->next () % r_max - : get_range (r_max); + return is_constant (num) + ? (next () * (uint64_t)num) >> 32U + : get_range (num); } // return a number within (min .. max) int operator () (int r_min, int r_max) { - return is_constant (r_min) && is_constant (r_max) - ? r_min + (*this) (max (r_max - r_min + 1, 1)) + return is_constant (r_min) && is_constant (r_max) && r_min <= r_max + ? r_min + operator ()(r_max - r_min + 1) : get_range (r_min, r_max); } @@ -350,7 +408,7 @@ void erase (T *obj) { assert (obj->*index); - int pos = obj->*index; + unsigned int pos = obj->*index; obj->*index = 0; if (pos < this->size ()) @@ -385,5 +443,8 @@ int similar_direction (int a, int b); +// like printf, but returns a std::string +const std::string format (const char *format, ...); + #endif