1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.3
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
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.
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
20 #include "agg_basics.h"
27 //-------------------------------------------------------pod_array_adaptor
28 template<class T
> class pod_array_adaptor
32 pod_array_adaptor(T
* array
, unsigned _size
) :
33 m_array(array
), m_size(_size
) {}
35 unsigned size() const { return m_size
; }
36 const T
& operator [] (unsigned idx
) const { return m_array
[idx
]; }
37 T
& operator [] (unsigned idx
) { return m_array
[idx
]; }
45 //---------------------------------------------------------pod_auto_array
46 template<class T
, unsigned Size
> class pod_auto_array
50 typedef pod_auto_array
<T
, Size
> self_type
;
53 explicit pod_auto_array(const T
* c
)
55 memcpy(m_array
, c
, sizeof(T
) * Size
);
58 const self_type
& operator = (const T
* c
)
60 memcpy(m_array
, c
, sizeof(T
) * Size
);
64 static unsigned size() { return Size
; }
65 const T
& operator [] (unsigned i
) const { return m_array
[i
]; }
66 T
& operator [] (unsigned i
) { return m_array
[i
]; }
75 //---------------------------------------------------------------pod_array
76 // A simple class template to store Plain Old Data, a vector
77 // of a fixed size. The data is continous in memory
78 //------------------------------------------------------------------------
79 template<class T
> class pod_array
84 ~pod_array() { delete [] m_array
; }
85 pod_array() : m_size(0), m_capacity(0), m_array(0) {}
86 pod_array(unsigned cap
, unsigned extra_tail
=0);
89 pod_array(const pod_array
<T
>&);
90 const pod_array
<T
>& operator = (const pod_array
<T
>&);
92 unsigned capacity() const { return m_capacity
; }
93 void capacity(unsigned cap
, unsigned extra_tail
=0);
95 void resize(unsigned new_size
);
97 void add(const T
& v
) { m_array
[m_size
++] = v
; }
98 void inc_size(unsigned _size
) { m_size
+= _size
; }
99 unsigned size() const { return m_size
; }
100 unsigned byte_size() const { return m_size
* sizeof(T
); }
101 void serialize(int8u
* ptr
) const;
102 void deserialize(const int8u
* data
, unsigned byte_size
);
103 const T
& operator [] (unsigned idx
) const { return m_array
[idx
]; }
104 T
& operator [] (unsigned idx
) { return m_array
[idx
]; }
106 void remove_all() { m_size
= 0; }
107 void cut_at(unsigned num
) { if(num
< m_size
) m_size
= num
; }
115 //------------------------------------------------------------------------
117 void pod_array
<T
>::capacity(unsigned cap
, unsigned extra_tail
)
123 m_capacity
= cap
+ extra_tail
;
124 m_array
= m_capacity
? new T
[m_capacity
] : 0;
128 //------------------------------------------------------------------------
130 void pod_array
<T
>::resize(unsigned new_size
)
132 if(new_size
> m_size
)
134 if(new_size
> m_capacity
)
136 T
* data
= new T
[new_size
];
137 memcpy(data
, m_array
, m_size
* sizeof(T
));
148 //------------------------------------------------------------------------
149 template<class T
> pod_array
<T
>::pod_array(unsigned cap
, unsigned extra_tail
) :
150 m_size(cap
), m_capacity(cap
+ extra_tail
), m_array(new T
[m_capacity
]) {}
152 //------------------------------------------------------------------------
153 template<class T
> pod_array
<T
>::pod_array(const pod_array
<T
>& v
) :
155 m_capacity(v
.m_capacity
),
156 m_array(v
.m_capacity
? new T
[v
.m_capacity
] : 0)
158 memcpy(m_array
, v
.m_array
, sizeof(T
) * v
.m_size
);
161 //------------------------------------------------------------------------
162 template<class T
> const pod_array
<T
>&
163 pod_array
<T
>::operator = (const pod_array
<T
>&v
)
165 capacity(v
.m_capacity
);
166 if(v
.m_size
) memcpy(m_array
, v
.m_array
, sizeof(T
) * v
.m_size
);
170 //------------------------------------------------------------------------
171 template<class T
> void pod_array
<T
>::serialize(int8u
* ptr
) const
173 if(m_size
) memcpy(ptr
, m_array
, m_size
* sizeof(T
));
176 //------------------------------------------------------------------------
178 void pod_array
<T
>::deserialize(const int8u
* data
, unsigned _byte_size
)
180 _byte_size
/= sizeof(T
);
181 capacity(_byte_size
);
182 if(_byte_size
) memcpy(m_array
, data
, _byte_size
* sizeof(T
));
189 //---------------------------------------------------------------pod_deque
190 // A simple class template to store Plain Old Data, similar to std::deque
191 // It doesn't reallocate memory but instead, uses blocks of data of size
192 // of (1 << S), that is, power of two. The data is NOT contiguous in memory,
193 // so the only valid access method is operator [] or curr(), prev(), next()
195 // There reallocs occure only when the pool of pointers to blocks needs
196 // to be extended (it happens very rarely). You can control the value
197 // of increment to reallocate the pointer buffer. See the second constructor.
198 // By default, the incremeent value equals (1 << S), i.e., the block size.
199 //------------------------------------------------------------------------
200 template<class T
, unsigned S
=6> class pod_deque
206 block_size
= 1 << block_shift
,
207 block_mask
= block_size
- 1
210 typedef T value_type
;
214 pod_deque(unsigned block_ptr_inc
);
217 pod_deque(const pod_deque
<T
, S
>& v
);
218 const pod_deque
<T
, S
>& operator = (const pod_deque
<T
, S
>& v
);
220 void remove_all() { m_size
= 0; }
221 void free_all() { free_tail(0); }
222 void free_tail(unsigned size
);
223 void add(const T
& val
);
224 void modify_last(const T
& val
);
227 int allocate_continuous_block(unsigned num_elements
);
229 void add_array(const T
* ptr
, unsigned num_elem
)
237 template<class DataAccessor
> void add_data(DataAccessor
& data
)
246 void cut_at(unsigned _size
)
248 if(_size
< m_size
) m_size
= _size
;
251 unsigned size() const { return m_size
; }
253 const T
& operator [] (unsigned idx
) const
255 return m_blocks
[idx
>> block_shift
][idx
& block_mask
];
258 T
& operator [] (unsigned idx
)
260 return m_blocks
[idx
>> block_shift
][idx
& block_mask
];
263 const T
& curr(unsigned idx
) const
268 T
& curr(unsigned idx
)
273 const T
& prev(unsigned idx
) const
275 return (*this)[(idx
+ m_size
- 1) % m_size
];
278 T
& prev(unsigned idx
)
280 return (*this)[(idx
+ m_size
- 1) % m_size
];
283 const T
& next(unsigned idx
) const
285 return (*this)[(idx
+ 1) % m_size
];
288 T
& next(unsigned idx
)
290 return (*this)[(idx
+ 1) % m_size
];
293 const T
& last() const
295 return (*this)[m_size
- 1];
300 return (*this)[m_size
- 1];
303 unsigned byte_size() const;
304 void serialize(int8u
* ptr
) const;
305 void deserialize(const int8u
* data
, unsigned byte_size
);
306 void deserialize(unsigned start
, const T
& empty_val
,
307 const int8u
* data
, unsigned byte_size
);
309 template<class ByteAccessor
>
310 void deserialize(ByteAccessor data
)
313 unsigned elem_size
= data
.size() / sizeof(T
);
315 for(unsigned i
= 0; i
< elem_size
; ++i
)
317 int8u
* ptr
= (int8u
*)data_ptr();
318 for(unsigned j
= 0; j
< sizeof(T
); ++j
)
327 template<class ByteAccessor
>
328 void deserialize(unsigned start
, const T
& empty_val
, ByteAccessor data
)
330 while(m_size
< start
)
335 unsigned elem_size
= data
.size() / sizeof(T
);
336 for(unsigned i
= 0; i
< elem_size
; ++i
)
339 if(start
+ i
< m_size
)
341 ptr
= (int8u
*)(&((*this)[start
+ i
]));
345 ptr
= (int8u
*)data_ptr();
348 for(unsigned j
= 0; j
< sizeof(T
); ++j
)
356 const T
* block(unsigned nb
) const { return m_blocks
[nb
]; }
359 void allocate_block(unsigned nb
);
363 unsigned m_num_blocks
;
364 unsigned m_max_blocks
;
366 unsigned m_block_ptr_inc
;
370 //------------------------------------------------------------------------
371 template<class T
, unsigned S
> pod_deque
<T
, S
>::~pod_deque()
375 T
** blk
= m_blocks
+ m_num_blocks
- 1;
376 while(m_num_blocks
--)
386 //------------------------------------------------------------------------
387 template<class T
, unsigned S
>
388 void pod_deque
<T
, S
>::free_tail(unsigned _size
)
392 unsigned nb
= (_size
+ block_mask
) >> block_shift
;
393 while(m_num_blocks
> nb
)
395 delete [] m_blocks
[--m_num_blocks
];
402 //------------------------------------------------------------------------
403 template<class T
, unsigned S
> pod_deque
<T
, S
>::pod_deque() :
408 m_block_ptr_inc(block_size
)
413 //------------------------------------------------------------------------
414 template<class T
, unsigned S
>
415 pod_deque
<T
, S
>::pod_deque(unsigned block_ptr_inc
) :
420 m_block_ptr_inc(block_ptr_inc
)
425 //------------------------------------------------------------------------
426 template<class T
, unsigned S
>
427 pod_deque
<T
, S
>::pod_deque(const pod_deque
<T
, S
>& v
) :
429 m_num_blocks(v
.m_num_blocks
),
430 m_max_blocks(v
.m_max_blocks
),
431 m_blocks(v
.m_max_blocks
? new T
* [v
.m_max_blocks
] : 0),
432 m_block_ptr_inc(v
.m_block_ptr_inc
)
435 for(i
= 0; i
< v
.m_num_blocks
; ++i
)
437 m_blocks
[i
] = new T
[block_size
];
438 memcpy(m_blocks
[i
], v
.m_blocks
[i
], block_size
* sizeof(T
));
443 //------------------------------------------------------------------------
444 template<class T
, unsigned S
>
445 const pod_deque
<T
, S
>& pod_deque
<T
, S
>::operator = (const pod_deque
<T
, S
>& v
)
448 for(i
= m_num_blocks
; i
< v
.m_num_blocks
; ++i
)
452 for(i
= 0; i
< v
.m_num_blocks
; ++i
)
454 memcpy(m_blocks
[i
], v
.m_blocks
[i
], block_size
* sizeof(T
));
461 //------------------------------------------------------------------------
462 template<class T
, unsigned S
>
463 void pod_deque
<T
, S
>::allocate_block(unsigned nb
)
465 if(nb
>= m_max_blocks
)
467 T
** new_blocks
= new T
* [m_max_blocks
+ m_block_ptr_inc
];
473 m_num_blocks
* sizeof(T
*));
477 m_blocks
= new_blocks
;
478 m_max_blocks
+= m_block_ptr_inc
;
480 m_blocks
[nb
] = new T
[block_size
];
486 //------------------------------------------------------------------------
487 template<class T
, unsigned S
>
488 inline T
* pod_deque
<T
, S
>::data_ptr()
490 unsigned nb
= m_size
>> block_shift
;
491 if(nb
>= m_num_blocks
)
495 return m_blocks
[nb
] + (m_size
& block_mask
);
500 //------------------------------------------------------------------------
501 template<class T
, unsigned S
>
502 inline void pod_deque
<T
, S
>::add(const T
& val
)
509 //------------------------------------------------------------------------
510 template<class T
, unsigned S
>
511 inline void pod_deque
<T
, S
>::remove_last()
517 //------------------------------------------------------------------------
518 template<class T
, unsigned S
>
519 void pod_deque
<T
, S
>::modify_last(const T
& val
)
526 //------------------------------------------------------------------------
527 template<class T
, unsigned S
>
528 int pod_deque
<T
, S
>::allocate_continuous_block(unsigned num_elements
)
530 if(num_elements
< block_size
)
532 data_ptr(); // Allocate initial block if necessary
533 unsigned rest
= block_size
- (m_size
& block_mask
);
535 if(num_elements
<= rest
)
537 // The rest of the block is good, we can use it
540 m_size
+= num_elements
;
549 m_size
+= num_elements
;
552 return -1; // Impossible to allocate
556 //------------------------------------------------------------------------
557 template<class T
, unsigned S
>
558 unsigned pod_deque
<T
, S
>::byte_size() const
560 return m_size
* sizeof(T
);
564 //------------------------------------------------------------------------
565 template<class T
, unsigned S
>
566 void pod_deque
<T
, S
>::serialize(int8u
* ptr
) const
569 for(i
= 0; i
< m_size
; i
++)
571 memcpy(ptr
, &(*this)[i
], sizeof(T
));
576 //------------------------------------------------------------------------
577 template<class T
, unsigned S
>
578 void pod_deque
<T
, S
>::deserialize(const int8u
* data
, unsigned _byte_size
)
581 _byte_size
/= sizeof(T
);
582 for(unsigned i
= 0; i
< _byte_size
; ++i
)
585 memcpy(ptr
, data
, sizeof(T
));
592 // Replace or add a number of elements starting from "start" position
593 //------------------------------------------------------------------------
594 template<class T
, unsigned S
>
595 void pod_deque
<T
, S
>::deserialize(unsigned start
, const T
& empty_val
,
596 const int8u
* data
, unsigned _byte_size
)
598 while(m_size
< start
)
603 _byte_size
/= sizeof(T
);
604 for(unsigned i
= 0; i
< _byte_size
; ++i
)
606 if(start
+ i
< m_size
)
608 memcpy(&((*this)[start
+ i
]), data
, sizeof(T
));
613 memcpy(ptr
, data
, sizeof(T
));
621 //-----------------------------------------------------------pod_allocator
622 // Allocator for arbitrary POD data. Most usable in different cache
623 // systems for efficient memory allocations.
624 // Memory is allocated with blocks of fixed size ("block_size" in
625 // the constructor). If required size exceeds the block size the allocator
626 // creates a new block of the required size. However, the most efficient
627 // use is when the average reqired size is much less than the block size.
628 //------------------------------------------------------------------------
636 int8u
** blk
= m_blocks
+ m_num_blocks
- 1;
637 while(m_num_blocks
--)
656 pod_allocator(unsigned block_size
, unsigned block_ptr_inc
=256-8) :
657 m_block_size(block_size
),
658 m_block_ptr_inc(block_ptr_inc
),
668 int8u
* allocate(unsigned size
, unsigned alignment
=1)
670 if(size
== 0) return 0;
673 int8u
* ptr
= m_buf_ptr
;
676 unsigned align
= (alignment
- unsigned((size_t)ptr
) % alignment
) % alignment
;
685 allocate_block(size
);
686 return allocate(size
- align
, alignment
);
692 allocate_block(size
+ alignment
- 1);
693 return allocate(size
, alignment
);
698 void allocate_block(unsigned size
)
700 if(size
< m_block_size
) size
= m_block_size
;
701 if(m_num_blocks
>= m_max_blocks
)
703 int8u
** new_blocks
= new int8u
* [m_max_blocks
+ m_block_ptr_inc
];
709 m_num_blocks
* sizeof(int8u
*));
713 m_blocks
= new_blocks
;
714 m_max_blocks
+= m_block_ptr_inc
;
716 m_blocks
[m_num_blocks
] = m_buf_ptr
= new int8u
[size
];
721 unsigned m_block_size
;
722 unsigned m_block_ptr_inc
;
723 unsigned m_num_blocks
;
724 unsigned m_max_blocks
;
737 //------------------------------------------------------------------------
740 quick_sort_threshold
= 9
744 //-----------------------------------------------------------swap_elements
745 template<class T
> inline void swap_elements(T
& a
, T
& b
)
753 //--------------------------------------------------------------quick_sort
754 template<class Array
, class Less
>
755 void quick_sort(Array
& arr
, Less less
)
757 if(arr
.size() < 2) return;
759 typename
Array::value_type
* e1
;
760 typename
Array::value_type
* e2
;
764 int limit
= arr
.size();
769 int len
= limit
- base
;
775 if(len
> quick_sort_threshold
)
777 // we use base + len/2 as the pivot
778 pivot
= base
+ len
/ 2;
779 swap_elements(arr
[base
], arr
[pivot
]);
784 // now ensure that *i <= *base <= *j
787 if(less(*e1
, *e2
)) swap_elements(*e1
, *e2
);
791 if(less(*e1
, *e2
)) swap_elements(*e1
, *e2
);
795 if(less(*e1
, *e2
)) swap_elements(*e1
, *e2
);
799 do i
++; while( less(arr
[i
], arr
[base
]) );
800 do j
--; while( less(arr
[base
], arr
[j
]) );
807 swap_elements(arr
[i
], arr
[j
]);
810 swap_elements(arr
[base
], arr
[j
]);
812 // now, push the largest sub-array
813 if(j
- base
> limit
- i
)
829 // the sub-array is small, perform insertion sort
833 for(; i
< limit
; j
= i
, i
++)
835 for(; less(*(e1
= &(arr
[j
+ 1])), *(e2
= &(arr
[j
]))); j
--)
837 swap_elements(*e1
, *e2
);
861 //------------------------------------------------------remove_duplicates
862 // Remove duplicates from a sorted array. It doesn't cut the the
863 // tail of the array, it just returns the number of remaining elements.
864 //-----------------------------------------------------------------------
865 template<class Array
, class Equal
>
866 unsigned remove_duplicates(Array
& arr
, Equal equal
)
868 if(arr
.size() < 2) return arr
.size();
871 for(i
= 1, j
= 1; i
< arr
.size(); i
++)
873 typename
Array::value_type
& e
= arr
[i
];
874 if(!equal(e
, arr
[i
- 1]))