btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / libs / agg / agg_array.h
blob8d56683840d442b5d92ad6d1f0fabea073258f0e
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 #ifndef AGG_ARRAY_INCLUDED
16 #define AGG_ARRAY_INCLUDED
18 #include <stddef.h>
19 #include <string.h>
20 #include "agg_basics.h"
22 namespace agg
25 //-------------------------------------------------------pod_array_adaptor
26 template<class T> class pod_array_adaptor
28 public:
29 typedef T value_type;
30 pod_array_adaptor(T* array, unsigned size) :
31 m_array(array), m_size(size) {}
33 unsigned size() const { return m_size; }
34 const T& operator [] (unsigned i) const { return m_array[i]; }
35 T& operator [] (unsigned i) { return m_array[i]; }
36 const T& at(unsigned i) const { return m_array[i]; }
37 T& at(unsigned i) { return m_array[i]; }
38 T value_at(unsigned i) const { return m_array[i]; }
40 private:
41 T* m_array;
42 unsigned m_size;
46 //---------------------------------------------------------pod_auto_array
47 template<class T, unsigned Size> class pod_auto_array
49 public:
50 typedef T value_type;
51 typedef pod_auto_array<T, Size> self_type;
53 pod_auto_array() {}
54 explicit pod_auto_array(const T* c)
56 memcpy(m_array, c, sizeof(T) * Size);
59 const self_type& operator = (const T* c)
61 memcpy(m_array, c, sizeof(T) * Size);
62 return *this;
65 static unsigned size() { return Size; }
66 const T& operator [] (unsigned i) const { return m_array[i]; }
67 T& operator [] (unsigned i) { return m_array[i]; }
68 const T& at(unsigned i) const { return m_array[i]; }
69 T& at(unsigned i) { return m_array[i]; }
70 T value_at(unsigned i) const { return m_array[i]; }
72 private:
73 T m_array[Size];
77 //--------------------------------------------------------pod_auto_vector
78 template<class T, unsigned Size> class pod_auto_vector
80 public:
81 typedef T value_type;
82 typedef pod_auto_vector<T, Size> self_type;
84 pod_auto_vector() : m_size(0) {}
86 void remove_all() { m_size = 0; }
87 void clear() { m_size = 0; }
88 void add(const T& v) { m_array[m_size++] = v; }
89 void push_back(const T& v) { m_array[m_size++] = v; }
90 void inc_size(unsigned size) { m_size += size; }
92 unsigned size() const { return m_size; }
93 const T& operator [] (unsigned i) const { return m_array[i]; }
94 T& operator [] (unsigned i) { return m_array[i]; }
95 const T& at(unsigned i) const { return m_array[i]; }
96 T& at(unsigned i) { return m_array[i]; }
97 T value_at(unsigned i) const { return m_array[i]; }
99 private:
100 T m_array[Size];
101 unsigned m_size;
105 //---------------------------------------------------------------pod_array
106 template<class T> class pod_array
108 public:
109 typedef T value_type;
110 typedef pod_array<T> self_type;
112 ~pod_array() { pod_allocator<T>::deallocate(m_array, m_size); }
113 pod_array() : m_array(0), m_size(0) {}
115 pod_array(unsigned size) :
116 m_array(pod_allocator<T>::allocate(size)),
117 m_size(size)
120 pod_array(const self_type& v) :
121 m_array(pod_allocator<T>::allocate(v.m_size)),
122 m_size(v.m_size)
124 memcpy(m_array, v.m_array, sizeof(T) * m_size);
127 void resize(unsigned size)
129 if(size != m_size)
131 pod_allocator<T>::deallocate(m_array, m_size);
132 m_array = pod_allocator<T>::allocate(m_size = size);
135 const self_type& operator = (const self_type& v)
137 resize(v.size());
138 memcpy(m_array, v.m_array, sizeof(T) * m_size);
139 return *this;
142 unsigned size() const { return m_size; }
143 const T& operator [] (unsigned i) const { return m_array[i]; }
144 T& operator [] (unsigned i) { return m_array[i]; }
145 const T& at(unsigned i) const { return m_array[i]; }
146 T& at(unsigned i) { return m_array[i]; }
147 T value_at(unsigned i) const { return m_array[i]; }
149 const T* data() const { return m_array; }
150 T* data() { return m_array; }
151 private:
152 T* m_array;
153 unsigned m_size;
158 //--------------------------------------------------------------pod_vector
159 // A simple class template to store Plain Old Data, a vector
160 // of a fixed size. The data is continous in memory
161 //------------------------------------------------------------------------
162 template<class T> class pod_vector
164 public:
165 typedef T value_type;
167 ~pod_vector() { pod_allocator<T>::deallocate(m_array, m_capacity); }
168 pod_vector() : m_size(0), m_capacity(0), m_array(0) {}
169 pod_vector(unsigned cap, unsigned extra_tail=0);
171 // Copying
172 pod_vector(const pod_vector<T>&);
173 const pod_vector<T>& operator = (const pod_vector<T>&);
175 // Set new capacity. All data is lost, size is set to zero.
176 void capacity(unsigned cap, unsigned extra_tail=0);
177 unsigned capacity() const { return m_capacity; }
179 // Allocate n elements. All data is lost,
180 // but elements can be accessed in range 0...size-1.
181 void allocate(unsigned size, unsigned extra_tail=0);
183 // Resize keeping the content.
184 void resize(unsigned new_size);
186 void zero()
188 memset(m_array, 0, sizeof(T) * m_size);
191 void add(const T& v) { m_array[m_size++] = v; }
192 void push_back(const T& v) { m_array[m_size++] = v; }
193 void insert_at(unsigned pos, const T& val);
194 void inc_size(unsigned size) { m_size += size; }
195 unsigned size() const { return m_size; }
196 unsigned byte_size() const { return m_size * sizeof(T); }
197 void serialize(int8u* ptr) const;
198 void deserialize(const int8u* data, unsigned byte_size);
199 const T& operator [] (unsigned i) const { return m_array[i]; }
200 T& operator [] (unsigned i) { return m_array[i]; }
201 const T& at(unsigned i) const { return m_array[i]; }
202 T& at(unsigned i) { return m_array[i]; }
203 T value_at(unsigned i) const { return m_array[i]; }
205 const T* data() const { return m_array; }
206 T* data() { return m_array; }
208 void remove_all() { m_size = 0; }
209 void clear() { m_size = 0; }
210 void cut_at(unsigned num) { if(num < m_size) m_size = num; }
212 private:
213 unsigned m_size;
214 unsigned m_capacity;
215 T* m_array;
218 //------------------------------------------------------------------------
219 template<class T>
220 void pod_vector<T>::capacity(unsigned cap, unsigned extra_tail)
222 m_size = 0;
223 if(cap > m_capacity)
225 pod_allocator<T>::deallocate(m_array, m_capacity);
226 m_capacity = cap + extra_tail;
227 m_array = m_capacity ? pod_allocator<T>::allocate(m_capacity) : 0;
231 //------------------------------------------------------------------------
232 template<class T>
233 void pod_vector<T>::allocate(unsigned size, unsigned extra_tail)
235 capacity(size, extra_tail);
236 m_size = size;
240 //------------------------------------------------------------------------
241 template<class T>
242 void pod_vector<T>::resize(unsigned new_size)
244 if(new_size > m_size)
246 if(new_size > m_capacity)
248 T* data = pod_allocator<T>::allocate(new_size);
249 memcpy(data, m_array, m_size * sizeof(T));
250 pod_allocator<T>::deallocate(m_array, m_capacity);
251 m_array = data;
254 else
256 m_size = new_size;
260 //------------------------------------------------------------------------
261 template<class T> pod_vector<T>::pod_vector(unsigned cap, unsigned extra_tail) :
262 m_size(0),
263 m_capacity(cap + extra_tail),
264 m_array(pod_allocator<T>::allocate(m_capacity)) {}
266 //------------------------------------------------------------------------
267 template<class T> pod_vector<T>::pod_vector(const pod_vector<T>& v) :
268 m_size(v.m_size),
269 m_capacity(v.m_capacity),
270 m_array(v.m_capacity ? pod_allocator<T>::allocate(v.m_capacity) : 0)
272 memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
275 //------------------------------------------------------------------------
276 template<class T> const pod_vector<T>&
277 pod_vector<T>::operator = (const pod_vector<T>&v)
279 allocate(v.m_size);
280 if(v.m_size) memcpy(m_array, v.m_array, sizeof(T) * v.m_size);
281 return *this;
284 //------------------------------------------------------------------------
285 template<class T> void pod_vector<T>::serialize(int8u* ptr) const
287 if(m_size) memcpy(ptr, m_array, m_size * sizeof(T));
290 //------------------------------------------------------------------------
291 template<class T>
292 void pod_vector<T>::deserialize(const int8u* data, unsigned byte_size)
294 byte_size /= sizeof(T);
295 allocate(byte_size);
296 if(byte_size) memcpy(m_array, data, byte_size * sizeof(T));
299 //------------------------------------------------------------------------
300 template<class T>
301 void pod_vector<T>::insert_at(unsigned pos, const T& val)
303 if(pos >= m_size)
305 m_array[m_size] = val;
307 else
309 memmove(m_array + pos + 1, m_array + pos, (m_size - pos) * sizeof(T));
310 m_array[pos] = val;
312 ++m_size;
315 //---------------------------------------------------------------pod_bvector
316 // A simple class template to store Plain Old Data, similar to std::deque
317 // It doesn't reallocate memory but instead, uses blocks of data of size
318 // of (1 << S), that is, power of two. The data is NOT contiguous in memory,
319 // so the only valid access method is operator [] or curr(), prev(), next()
321 // There reallocs occure only when the pool of pointers to blocks needs
322 // to be extended (it happens very rarely). You can control the value
323 // of increment to reallocate the pointer buffer. See the second constructor.
324 // By default, the incremeent value equals (1 << S), i.e., the block size.
325 //------------------------------------------------------------------------
326 template<class T, unsigned S=6> class pod_bvector
328 public:
329 enum block_scale_e
331 block_shift = S,
332 block_size = 1 << block_shift,
333 block_mask = block_size - 1
336 typedef T value_type;
338 ~pod_bvector();
339 pod_bvector();
340 pod_bvector(unsigned block_ptr_inc);
342 // Copying
343 pod_bvector(const pod_bvector<T, S>& v);
344 const pod_bvector<T, S>& operator = (const pod_bvector<T, S>& v);
346 void remove_all() { m_size = 0; }
347 void clear() { m_size = 0; }
348 void free_all() { free_tail(0); }
349 void free_tail(unsigned size);
350 void add(const T& val);
351 void push_back(const T& val) { add(val); }
352 void modify_last(const T& val);
353 void remove_last();
355 int allocate_continuous_block(unsigned num_elements);
357 void add_array(const T* ptr, unsigned num_elem)
359 while(num_elem--)
361 add(*ptr++);
365 template<class DataAccessor> void add_data(DataAccessor& data)
367 while(data.size())
369 add(*data);
370 ++data;
374 void cut_at(unsigned size)
376 if(size < m_size) m_size = size;
379 unsigned size() const { return m_size; }
381 const T& operator [] (unsigned i) const
383 return m_blocks[i >> block_shift][i & block_mask];
386 T& operator [] (unsigned i)
388 return m_blocks[i >> block_shift][i & block_mask];
391 const T& at(unsigned i) const
393 return m_blocks[i >> block_shift][i & block_mask];
396 T& at(unsigned i)
398 return m_blocks[i >> block_shift][i & block_mask];
401 T value_at(unsigned i) const
403 return m_blocks[i >> block_shift][i & block_mask];
406 const T& curr(unsigned idx) const
408 return (*this)[idx];
411 T& curr(unsigned idx)
413 return (*this)[idx];
416 const T& prev(unsigned idx) const
418 return (*this)[(idx + m_size - 1) % m_size];
421 T& prev(unsigned idx)
423 return (*this)[(idx + m_size - 1) % m_size];
426 const T& next(unsigned idx) const
428 return (*this)[(idx + 1) % m_size];
431 T& next(unsigned idx)
433 return (*this)[(idx + 1) % m_size];
436 const T& last() const
438 return (*this)[m_size - 1];
441 T& last()
443 return (*this)[m_size - 1];
446 unsigned byte_size() const;
447 void serialize(int8u* ptr) const;
448 void deserialize(const int8u* data, unsigned byte_size);
449 void deserialize(unsigned start, const T& empty_val,
450 const int8u* data, unsigned byte_size);
452 template<class ByteAccessor>
453 void deserialize(ByteAccessor data)
455 remove_all();
456 unsigned elem_size = data.size() / sizeof(T);
458 for(unsigned i = 0; i < elem_size; ++i)
460 int8u* ptr = (int8u*)data_ptr();
461 for(unsigned j = 0; j < sizeof(T); ++j)
463 *ptr++ = *data;
464 ++data;
466 ++m_size;
470 template<class ByteAccessor>
471 void deserialize(unsigned start, const T& empty_val, ByteAccessor data)
473 while(m_size < start)
475 add(empty_val);
478 unsigned elem_size = data.size() / sizeof(T);
479 for(unsigned i = 0; i < elem_size; ++i)
481 int8u* ptr;
482 if(start + i < m_size)
484 ptr = (int8u*)(&((*this)[start + i]));
486 else
488 ptr = (int8u*)data_ptr();
489 ++m_size;
491 for(unsigned j = 0; j < sizeof(T); ++j)
493 *ptr++ = *data;
494 ++data;
499 const T* block(unsigned nb) const { return m_blocks[nb]; }
501 private:
502 void allocate_block(unsigned nb);
503 T* data_ptr();
505 unsigned m_size;
506 unsigned m_num_blocks;
507 unsigned m_max_blocks;
508 T** m_blocks;
509 unsigned m_block_ptr_inc;
513 //------------------------------------------------------------------------
514 template<class T, unsigned S> pod_bvector<T, S>::~pod_bvector()
516 if(m_num_blocks)
518 T** blk = m_blocks + m_num_blocks - 1;
519 while(m_num_blocks--)
521 pod_allocator<T>::deallocate(*blk, block_size);
522 --blk;
525 pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
529 //------------------------------------------------------------------------
530 template<class T, unsigned S>
531 void pod_bvector<T, S>::free_tail(unsigned size)
533 if(size < m_size)
535 unsigned nb = (size + block_mask) >> block_shift;
536 while(m_num_blocks > nb)
538 pod_allocator<T>::deallocate(m_blocks[--m_num_blocks], block_size);
540 if(m_num_blocks == 0)
542 pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
543 m_blocks = 0;
544 m_max_blocks = 0;
546 m_size = size;
551 //------------------------------------------------------------------------
552 template<class T, unsigned S> pod_bvector<T, S>::pod_bvector() :
553 m_size(0),
554 m_num_blocks(0),
555 m_max_blocks(0),
556 m_blocks(0),
557 m_block_ptr_inc(block_size)
562 //------------------------------------------------------------------------
563 template<class T, unsigned S>
564 pod_bvector<T, S>::pod_bvector(unsigned block_ptr_inc) :
565 m_size(0),
566 m_num_blocks(0),
567 m_max_blocks(0),
568 m_blocks(0),
569 m_block_ptr_inc(block_ptr_inc)
574 //------------------------------------------------------------------------
575 template<class T, unsigned S>
576 pod_bvector<T, S>::pod_bvector(const pod_bvector<T, S>& v) :
577 m_size(v.m_size),
578 m_num_blocks(v.m_num_blocks),
579 m_max_blocks(v.m_max_blocks),
580 m_blocks(v.m_max_blocks ?
581 pod_allocator<T*>::allocate(v.m_max_blocks) :
583 m_block_ptr_inc(v.m_block_ptr_inc)
585 unsigned i;
586 for(i = 0; i < v.m_num_blocks; ++i)
588 m_blocks[i] = pod_allocator<T>::allocate(block_size);
589 memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
594 //------------------------------------------------------------------------
595 template<class T, unsigned S>
596 const pod_bvector<T, S>&
597 pod_bvector<T, S>::operator = (const pod_bvector<T, S>& v)
599 unsigned i;
600 for(i = m_num_blocks; i < v.m_num_blocks; ++i)
602 allocate_block(i);
604 for(i = 0; i < v.m_num_blocks; ++i)
606 memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T));
608 m_size = v.m_size;
609 return *this;
613 //------------------------------------------------------------------------
614 template<class T, unsigned S>
615 void pod_bvector<T, S>::allocate_block(unsigned nb)
617 if(nb >= m_max_blocks)
619 T** new_blocks = pod_allocator<T*>::allocate(m_max_blocks + m_block_ptr_inc);
621 if(m_blocks)
623 memcpy(new_blocks,
624 m_blocks,
625 m_num_blocks * sizeof(T*));
627 pod_allocator<T*>::deallocate(m_blocks, m_max_blocks);
629 m_blocks = new_blocks;
630 m_max_blocks += m_block_ptr_inc;
632 m_blocks[nb] = pod_allocator<T>::allocate(block_size);
633 m_num_blocks++;
638 //------------------------------------------------------------------------
639 template<class T, unsigned S>
640 inline T* pod_bvector<T, S>::data_ptr()
642 unsigned nb = m_size >> block_shift;
643 if(nb >= m_num_blocks)
645 allocate_block(nb);
647 return m_blocks[nb] + (m_size & block_mask);
652 //------------------------------------------------------------------------
653 template<class T, unsigned S>
654 inline void pod_bvector<T, S>::add(const T& val)
656 *data_ptr() = val;
657 ++m_size;
661 //------------------------------------------------------------------------
662 template<class T, unsigned S>
663 inline void pod_bvector<T, S>::remove_last()
665 if(m_size) --m_size;
669 //------------------------------------------------------------------------
670 template<class T, unsigned S>
671 void pod_bvector<T, S>::modify_last(const T& val)
673 remove_last();
674 add(val);
678 //------------------------------------------------------------------------
679 template<class T, unsigned S>
680 int pod_bvector<T, S>::allocate_continuous_block(unsigned num_elements)
682 if(num_elements < block_size)
684 data_ptr(); // Allocate initial block if necessary
685 unsigned rest = block_size - (m_size & block_mask);
686 unsigned index;
687 if(num_elements <= rest)
689 // The rest of the block is good, we can use it
690 //-----------------
691 index = m_size;
692 m_size += num_elements;
693 return index;
696 // New block
697 //---------------
698 m_size += rest;
699 data_ptr();
700 index = m_size;
701 m_size += num_elements;
702 return index;
704 return -1; // Impossible to allocate
708 //------------------------------------------------------------------------
709 template<class T, unsigned S>
710 unsigned pod_bvector<T, S>::byte_size() const
712 return m_size * sizeof(T);
716 //------------------------------------------------------------------------
717 template<class T, unsigned S>
718 void pod_bvector<T, S>::serialize(int8u* ptr) const
720 unsigned i;
721 for(i = 0; i < m_size; i++)
723 memcpy(ptr, &(*this)[i], sizeof(T));
724 ptr += sizeof(T);
728 //------------------------------------------------------------------------
729 template<class T, unsigned S>
730 void pod_bvector<T, S>::deserialize(const int8u* data, unsigned byte_size)
732 remove_all();
733 byte_size /= sizeof(T);
734 for(unsigned i = 0; i < byte_size; ++i)
736 T* ptr = data_ptr();
737 memcpy(ptr, data, sizeof(T));
738 ++m_size;
739 data += sizeof(T);
744 // Replace or add a number of elements starting from "start" position
745 //------------------------------------------------------------------------
746 template<class T, unsigned S>
747 void pod_bvector<T, S>::deserialize(unsigned start, const T& empty_val,
748 const int8u* data, unsigned byte_size)
750 while(m_size < start)
752 add(empty_val);
755 byte_size /= sizeof(T);
756 for(unsigned i = 0; i < byte_size; ++i)
758 if(start + i < m_size)
760 memcpy(&((*this)[start + i]), data, sizeof(T));
762 else
764 T* ptr = data_ptr();
765 memcpy(ptr, data, sizeof(T));
766 ++m_size;
768 data += sizeof(T);
773 //---------------------------------------------------------block_allocator
774 // Allocator for arbitrary POD data. Most usable in different cache
775 // systems for efficient memory allocations.
776 // Memory is allocated with blocks of fixed size ("block_size" in
777 // the constructor). If required size exceeds the block size the allocator
778 // creates a new block of the required size. However, the most efficient
779 // use is when the average reqired size is much less than the block size.
780 //------------------------------------------------------------------------
781 class block_allocator
783 struct block_type
785 int8u* data;
786 unsigned size;
789 public:
790 void remove_all()
792 if(m_num_blocks)
794 block_type* blk = m_blocks + m_num_blocks - 1;
795 while(m_num_blocks--)
797 pod_allocator<int8u>::deallocate(blk->data, blk->size);
798 --blk;
800 pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks);
802 m_num_blocks = 0;
803 m_max_blocks = 0;
804 m_blocks = 0;
805 m_buf_ptr = 0;
806 m_rest = 0;
809 ~block_allocator()
811 remove_all();
814 block_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) :
815 m_block_size(block_size),
816 m_block_ptr_inc(block_ptr_inc),
817 m_num_blocks(0),
818 m_max_blocks(0),
819 m_blocks(0),
820 m_buf_ptr(0),
821 m_rest(0)
826 int8u* allocate(unsigned size, unsigned alignment=1)
828 if(size == 0) return 0;
829 if(size <= m_rest)
831 int8u* ptr = m_buf_ptr;
832 if(alignment > 1)
834 unsigned align =
835 (alignment - unsigned((size_t)ptr) % alignment) % alignment;
837 size += align;
838 ptr += align;
839 if(size <= m_rest)
841 m_rest -= size;
842 m_buf_ptr += size;
843 return ptr;
845 allocate_block(size);
846 return allocate(size - align, alignment);
848 m_rest -= size;
849 m_buf_ptr += size;
850 return ptr;
852 allocate_block(size + alignment - 1);
853 return allocate(size, alignment);
857 private:
858 void allocate_block(unsigned size)
860 if(size < m_block_size) size = m_block_size;
861 if(m_num_blocks >= m_max_blocks)
863 block_type* new_blocks =
864 pod_allocator<block_type>::allocate(m_max_blocks + m_block_ptr_inc);
866 if(m_blocks)
868 memcpy(new_blocks,
869 m_blocks,
870 m_num_blocks * sizeof(block_type));
871 pod_allocator<block_type>::deallocate(m_blocks, m_max_blocks);
873 m_blocks = new_blocks;
874 m_max_blocks += m_block_ptr_inc;
877 m_blocks[m_num_blocks].size = size;
878 m_blocks[m_num_blocks].data =
879 m_buf_ptr =
880 pod_allocator<int8u>::allocate(size);
882 m_num_blocks++;
883 m_rest = size;
886 unsigned m_block_size;
887 unsigned m_block_ptr_inc;
888 unsigned m_num_blocks;
889 unsigned m_max_blocks;
890 block_type* m_blocks;
891 int8u* m_buf_ptr;
892 unsigned m_rest;
902 //------------------------------------------------------------------------
903 enum quick_sort_threshold_e
905 quick_sort_threshold = 9
909 //-----------------------------------------------------------swap_elements
910 template<class T> inline void swap_elements(T& a, T& b)
912 T temp = a;
913 a = b;
914 b = temp;
918 //--------------------------------------------------------------quick_sort
919 template<class Array, class Less>
920 void quick_sort(Array& arr, Less less)
922 if(arr.size() < 2) return;
924 typename Array::value_type* e1;
925 typename Array::value_type* e2;
927 int stack[80];
928 int* top = stack;
929 int limit = arr.size();
930 int base = 0;
932 for(;;)
934 int len = limit - base;
936 int i;
937 int j;
938 int pivot;
940 if(len > quick_sort_threshold)
942 // we use base + len/2 as the pivot
943 pivot = base + len / 2;
944 swap_elements(arr[base], arr[pivot]);
946 i = base + 1;
947 j = limit - 1;
949 // now ensure that *i <= *base <= *j
950 e1 = &(arr[j]);
951 e2 = &(arr[i]);
952 if(less(*e1, *e2)) swap_elements(*e1, *e2);
954 e1 = &(arr[base]);
955 e2 = &(arr[i]);
956 if(less(*e1, *e2)) swap_elements(*e1, *e2);
958 e1 = &(arr[j]);
959 e2 = &(arr[base]);
960 if(less(*e1, *e2)) swap_elements(*e1, *e2);
962 for(;;)
964 do i++; while( less(arr[i], arr[base]) );
965 do j--; while( less(arr[base], arr[j]) );
967 if( i > j )
969 break;
972 swap_elements(arr[i], arr[j]);
975 swap_elements(arr[base], arr[j]);
977 // now, push the largest sub-array
978 if(j - base > limit - i)
980 top[0] = base;
981 top[1] = j;
982 base = i;
984 else
986 top[0] = i;
987 top[1] = limit;
988 limit = j;
990 top += 2;
992 else
994 // the sub-array is small, perform insertion sort
995 j = base;
996 i = j + 1;
998 for(; i < limit; j = i, i++)
1000 for(; less(*(e1 = &(arr[j + 1])), *(e2 = &(arr[j]))); j--)
1002 swap_elements(*e1, *e2);
1003 if(j == base)
1005 break;
1009 if(top > stack)
1011 top -= 2;
1012 base = top[0];
1013 limit = top[1];
1015 else
1017 break;
1026 //------------------------------------------------------remove_duplicates
1027 // Remove duplicates from a sorted array. It doesn't cut the
1028 // tail of the array, it just returns the number of remaining elements.
1029 //-----------------------------------------------------------------------
1030 template<class Array, class Equal>
1031 unsigned remove_duplicates(Array& arr, Equal equal)
1033 if(arr.size() < 2) return arr.size();
1035 unsigned i, j;
1036 for(i = 1, j = 1; i < arr.size(); i++)
1038 typename Array::value_type& e = arr[i];
1039 if(!equal(e, arr[i - 1]))
1041 arr[j++] = e;
1044 return j;
1047 //--------------------------------------------------------invert_container
1048 template<class Array> void invert_container(Array& arr)
1050 int i = 0;
1051 int j = arr.size() - 1;
1052 while(i < j)
1054 swap_elements(arr[i++], arr[j--]);
1058 //------------------------------------------------------binary_search_pos
1059 template<class Array, class Value, class Less>
1060 unsigned binary_search_pos(const Array& arr, const Value& val, Less less)
1062 if(arr.size() == 0) return 0;
1064 unsigned beg = 0;
1065 unsigned end = arr.size() - 1;
1067 if(less(val, arr[0])) return 0;
1068 if(less(arr[end], val)) return end + 1;
1070 while(end - beg > 1)
1072 unsigned mid = (end + beg) >> 1;
1073 if(less(val, arr[mid])) end = mid;
1074 else beg = mid;
1077 //if(beg <= 0 && less(val, arr[0])) return 0;
1078 //if(end >= arr.size() - 1 && less(arr[end], val)) ++end;
1080 return end;
1083 //----------------------------------------------------------range_adaptor
1084 template<class Array> class range_adaptor
1086 public:
1087 typedef typename Array::value_type value_type;
1089 range_adaptor(Array& array, unsigned start, unsigned size) :
1090 m_array(array), m_start(start), m_size(size)
1093 unsigned size() const { return m_size; }
1094 const value_type& operator [] (unsigned i) const { return m_array[m_start + i]; }
1095 value_type& operator [] (unsigned i) { return m_array[m_start + i]; }
1096 const value_type& at(unsigned i) const { return m_array[m_start + i]; }
1097 value_type& at(unsigned i) { return m_array[m_start + i]; }
1098 value_type value_at(unsigned i) const { return m_array[m_start + i]; }
1100 private:
1101 Array& m_array;
1102 unsigned m_start;
1103 unsigned m_size;
1106 //---------------------------------------------------------------int_less
1107 inline bool int_less(int a, int b) { return a < b; }
1109 //------------------------------------------------------------int_greater
1110 inline bool int_greater(int a, int b) { return a > b; }
1112 //----------------------------------------------------------unsigned_less
1113 inline bool unsigned_less(unsigned a, unsigned b) { return a < b; }
1115 //-------------------------------------------------------unsigned_greater
1116 inline bool unsigned_greater(unsigned a, unsigned b) { return a > b; }
1119 #endif