ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/include/util.h
Revision: 1.28
Committed: Mon Jan 15 01:25:41 2007 UTC (17 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.27: +31 -0 lines
Log Message:
- faster implementation for isqrt
- add fast idistance approximation

now find_dir_2 has moved to the top of the profiling output for
mlab/cwdccastleofmarquis3, followed by get_rangevector, hit_map
and ok_to_put_more.

File Contents

# User Rev Content
1 root 1.1 #ifndef UTIL_H__
2     #define UTIL_H__
3    
4 root 1.2 #if __GNUC__ >= 3
5     # define is_constant(c) __builtin_constant_p (c)
6     #else
7     # define is_constant(c) 0
8     #endif
9    
10 root 1.11 #include <cstddef>
11 root 1.28 #include <cmath>
12 root 1.25 #include <new>
13     #include <vector>
14 root 1.11
15     #include <glib.h>
16    
17 root 1.25 #include <shstr.h>
18     #include <traits.h>
19    
20 root 1.14 // use a gcc extension for auto declarations until ISO C++ sanctifies them
21     #define AUTODECL(var,expr) typeof(expr) var = (expr)
22    
23 root 1.26 // very ugly macro that basicaly declares and initialises a variable
24     // that is in scope for the next statement only
25     // works only for stuff that can be assigned 0 and converts to false
26     // (note: works great for pointers)
27     // most ugly macro I ever wrote
28     #define declvar(type, name, value) if (type name = 0) { } else if (((name) = (value)), 1)
29    
30 root 1.27 // in range including end
31     #define IN_RANGE_INC(val,beg,end) \
32     ((unsigned int)(val) - (unsigned int)(beg) <= (unsigned int)(end) - (unsigned int)(beg))
33    
34     // in range excluding end
35     #define IN_RANGE_EXC(val,beg,end) \
36     ((unsigned int)(val) - (unsigned int)(beg) < (unsigned int)(end) - (unsigned int)(beg))
37    
38 root 1.28 // this is much faster than crossfires original algorithm
39     // on modern cpus
40     inline int
41     isqrt (int n)
42     {
43     return (int)sqrtf ((float)n);
44     }
45    
46     // this is only twice as fast as naive sqrtf (dx*dy+dy*dy)
47     #if 0
48     // and has a max. error of 6 in the range -100..+100.
49     #else
50     // and has a max. error of 9 in the range -100..+100.
51     #endif
52     inline int
53     idistance (int dx, int dy)
54     {
55     unsigned int dx_ = abs (dx);
56     unsigned int dy_ = abs (dy);
57    
58     #if 0
59     return dx_ > dy_
60     ? (dx_ * 61685 + dy_ * 26870) >> 16
61     : (dy_ * 61685 + dx_ * 26870) >> 16;
62     #else
63     return dx + dy - min (dx, dy) * 5 / 8;
64     #endif
65     }
66    
67    
68 root 1.1 // makes dynamically allocated objects zero-initialised
69     struct zero_initialised
70     {
71 root 1.11 void *operator new (size_t s, void *p)
72     {
73     memset (p, 0, s);
74     return p;
75     }
76    
77     void *operator new (size_t s)
78     {
79     return g_slice_alloc0 (s);
80     }
81    
82     void *operator new[] (size_t s)
83     {
84     return g_slice_alloc0 (s);
85     }
86    
87     void operator delete (void *p, size_t s)
88     {
89     g_slice_free1 (s, p);
90     }
91    
92     void operator delete[] (void *p, size_t s)
93     {
94     g_slice_free1 (s, p);
95     }
96     };
97    
98 root 1.20 void *salloc_ (int n) throw (std::bad_alloc);
99     void *salloc_ (int n, void *src) throw (std::bad_alloc);
100    
101 root 1.12 // strictly the same as g_slice_alloc, but never returns 0
102 root 1.20 template<typename T>
103     inline T *salloc (int n = 1) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T)); }
104    
105 root 1.17 // also copies src into the new area, like "memdup"
106 root 1.18 // if src is 0, clears the memory
107     template<typename T>
108 root 1.20 inline T *salloc (int n, T *src) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T), (void *)src); }
109 root 1.18
110 root 1.21 // clears the memory
111     template<typename T>
112     inline T *salloc0(int n = 1) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T), 0); }
113    
114 root 1.12 // for symmetry
115 root 1.18 template<typename T>
116 root 1.20 inline void sfree (T *ptr, int n = 1) throw ()
117 root 1.12 {
118 root 1.20 g_slice_free1 (n * sizeof (T), (void *)ptr);
119 root 1.12 }
120 root 1.11
121     // a STL-compatible allocator that uses g_slice
122     // boy, this is verbose
123     template<typename Tp>
124     struct slice_allocator
125     {
126     typedef size_t size_type;
127     typedef ptrdiff_t difference_type;
128     typedef Tp *pointer;
129     typedef const Tp *const_pointer;
130     typedef Tp &reference;
131     typedef const Tp &const_reference;
132     typedef Tp value_type;
133    
134     template <class U>
135     struct rebind
136     {
137     typedef slice_allocator<U> other;
138     };
139    
140     slice_allocator () throw () { }
141     slice_allocator (const slice_allocator &o) throw () { }
142     template<typename Tp2>
143     slice_allocator (const slice_allocator<Tp2> &) throw () { }
144    
145     ~slice_allocator () { }
146    
147     pointer address (reference x) const { return &x; }
148     const_pointer address (const_reference x) const { return &x; }
149    
150     pointer allocate (size_type n, const_pointer = 0)
151     {
152 root 1.18 return salloc<Tp> (n);
153 root 1.11 }
154    
155     void deallocate (pointer p, size_type n)
156     {
157 root 1.19 sfree<Tp> (p, n);
158 root 1.11 }
159    
160     size_type max_size ()const throw ()
161     {
162     return size_t (-1) / sizeof (Tp);
163     }
164    
165     void construct (pointer p, const Tp &val)
166     {
167     ::new (p) Tp (val);
168     }
169    
170     void destroy (pointer p)
171     {
172     p->~Tp ();
173     }
174 root 1.1 };
175    
176 root 1.7 template<class T>
177     struct refptr
178     {
179     T *p;
180    
181     refptr () : p(0) { }
182     refptr (const refptr<T> &p) : p(p.p) { if (p) p->refcnt_inc (); }
183     refptr (T *p) : p(p) { if (p) p->refcnt_inc (); }
184     ~refptr () { if (p) p->refcnt_dec (); }
185    
186     const refptr<T> &operator =(T *o)
187     {
188     if (p) p->refcnt_dec ();
189     p = o;
190     if (p) p->refcnt_inc ();
191    
192     return *this;
193     }
194    
195     const refptr<T> &operator =(const refptr<T> o)
196     {
197     *this = o.p;
198     return *this;
199     }
200    
201     T &operator * () const { return *p; }
202     T *operator ->() const { return p; }
203    
204     operator T *() const { return p; }
205     };
206    
207 root 1.24 typedef refptr<maptile> maptile_ptr;
208 root 1.22 typedef refptr<object> object_ptr;
209     typedef refptr<archetype> arch_ptr;
210 root 1.24 typedef refptr<client> client_ptr;
211     typedef refptr<player> player_ptr;
212 root 1.22
213 root 1.4 struct str_hash
214     {
215     std::size_t operator ()(const char *s) const
216     {
217     unsigned long hash = 0;
218    
219     /* use the one-at-a-time hash function, which supposedly is
220     * better than the djb2-like one used by perl5.005, but
221     * certainly is better then the bug used here before.
222     * see http://burtleburtle.net/bob/hash/doobs.html
223     */
224     while (*s)
225     {
226     hash += *s++;
227     hash += hash << 10;
228     hash ^= hash >> 6;
229     }
230    
231     hash += hash << 3;
232     hash ^= hash >> 11;
233     hash += hash << 15;
234    
235     return hash;
236     }
237     };
238    
239     struct str_equal
240     {
241     bool operator ()(const char *a, const char *b) const
242     {
243     return !strcmp (a, b);
244     }
245     };
246    
247 root 1.26 template<class T>
248     struct unordered_vector : std::vector<T, slice_allocator<T> >
249 root 1.6 {
250 root 1.11 typedef typename unordered_vector::iterator iterator;
251 root 1.6
252     void erase (unsigned int pos)
253     {
254     if (pos < this->size () - 1)
255     (*this)[pos] = (*this)[this->size () - 1];
256    
257     this->pop_back ();
258     }
259    
260     void erase (iterator i)
261     {
262     erase ((unsigned int )(i - this->begin ()));
263     }
264     };
265    
266 root 1.26 template<class T, int T::* index>
267     struct object_vector : std::vector<T *, slice_allocator<T *> >
268     {
269     void insert (T *obj)
270     {
271     assert (!(obj->*index));
272     push_back (obj);
273     obj->*index = this->size ();
274     }
275    
276     void insert (T &obj)
277     {
278     insert (&obj);
279     }
280    
281     void erase (T *obj)
282     {
283     assert (obj->*index);
284     int pos = obj->*index;
285     obj->*index = 0;
286    
287     if (pos < this->size ())
288     {
289     (*this)[pos - 1] = (*this)[this->size () - 1];
290     (*this)[pos - 1]->*index = pos;
291     }
292    
293     this->pop_back ();
294     }
295    
296     void erase (T &obj)
297     {
298     errase (&obj);
299     }
300     };
301    
302 root 1.8 template<typename T, typename U> static inline T min (T a, U b) { return a < (T)b ? a : (T)b; }
303     template<typename T, typename U> static inline T max (T a, U b) { return a > (T)b ? a : (T)b; }
304     template<typename T, typename U, typename V> static inline T clamp (T v, U a, V b) { return v < (T)a ? a : v >(T)b ? b : v; }
305    
306     template<typename T, typename U> static inline void swap (T& a, U& b) { T t=a; a=(T)b; b=(U)t; }
307    
308 root 1.10 // basically does what strncpy should do, but appends "..." to strings exceeding length
309     void assign (char *dst, const char *src, int maxlen);
310    
311     // type-safe version of assign
312 root 1.9 template<int N>
313     inline void assign (char (&dst)[N], const char *src)
314     {
315 root 1.10 assign ((char *)&dst, src, N);
316 root 1.9 }
317    
318 root 1.17 typedef double tstamp;
319    
320     // return current time as timestampe
321     tstamp now ();
322    
323 root 1.25 int similar_direction (int a, int b);
324    
325 root 1.1 #endif
326