Provide (experimental) clang-format file
[TortoiseGit.git] / ext / OGDF / ogdf / basic / Array.h
blob41793ad7ba87dfcdf8403028105a6fcdf9b7bed7
1 /*
2 * $Revision: 2615 $
4 * last checkin:
5 * $Author: gutwenger $
6 * $Date: 2012-07-16 14:23:36 +0200 (Mo, 16. Jul 2012) $
7 ***************************************************************/
9 /** \file
10 * \brief Declaration and implementation of Array class and
11 * Array algorithms
13 * \author Carsten Gutwenger
15 * \par License:
16 * This file is part of the Open Graph Drawing Framework (OGDF).
18 * \par
19 * Copyright (C)<br>
20 * See README.txt in the root directory of the OGDF installation for details.
22 * \par
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * Version 2 or 3 as published by the Free Software Foundation;
26 * see the file LICENSE.txt included in the packaging of this file
27 * for details.
29 * \par
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
35 * \par
36 * You should have received a copy of the GNU General Public
37 * License along with this program; if not, write to the Free
38 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
39 * Boston, MA 02110-1301, USA.
41 * \see http://www.gnu.org/copyleft/gpl.html
42 ***************************************************************/
45 #ifdef _MSC_VER
46 #pragma once
47 #endif
49 #ifndef OGDF_ARRAY_H
50 #define OGDF_ARRAY_H
53 #include <ogdf/basic/basic.h>
56 namespace ogdf {
58 //! Iteration over all indices \a i of an array \a A.
59 /**
60 * Note that the index variable \a i has to be defined prior to this macro
61 * (just as for \c #forall_edges, etc.).
62 * <h3>Example</h3>
64 * \code
65 * Array<double> A;
66 * ...
67 * int i;
68 * forall_arrayindices(i, A) {
69 * cout << A[i] << endl;
70 * }
71 * \endcode
73 * Note that this code is equivalent to the following tedious long version
75 * \code
76 * Array<double> A;
77 * ...
78 * int i;
79 * for(i = A.low(); i <= A.high(); ++i) {
80 * cout << A[i] << endl;
81 * }
82 * \endcode
84 #define forall_arrayindices(i, A) \
85 for(i = (A).low(); i<=(A).high(); ++i)
87 //! Iteration over all indices \a i of an array \a A, in reverse order.
88 /**
89 * Note that the index variable \a i has to be defined prior to this macro
90 * (just as for \c #forall_edges, etc.).
91 * See \c #forall_arrayindices for an example
93 #define forall_rev_arrayindices(i, A) \
94 for(i = (A).high(); i>=(A).low(); --i)
98 //! The parameterized class \a Array<E,INDEX> implements dynamic arrays of type \a E.
99 /**
100 * @tparam E denotes the element type.
101 * @tparam INDEX denotes the index type. The index type must be chosen such that it can
102 * express the whole index range of the array instance, as well as its size.
103 * The default index type is \c int, other possible types are \c short and
104 * <code>long long</code> (on 64-bit systems).
106 template<class E, class INDEX = int> class Array {
107 public:
108 //! Threshold used by \a quicksort() such that insertion sort is
109 //! called for instances smaller than \a maxSizeInsertionSort.
110 enum { maxSizeInsertionSort = 40 };
113 //! Creates an array with empty index set.
114 Array() { construct(0,-1); }
116 //! Creates an array with index set [0..\a s-1].
117 explicit Array(INDEX s) {
118 construct(0,s-1); initialize();
121 //! Creates an array with index set [\a a..\a b].
122 Array(INDEX a, INDEX b) {
123 construct(a,b); initialize();
126 //! Creates an array with index set [\a a..\a b] and initializes each element with \a x.
127 Array(INDEX a, INDEX b, const E &x) {
128 construct(a,b); initialize(x);
131 //! Creates an array that is a copy of \a A.
132 Array(const Array<E> &A) {
133 copy(A);
136 // destruction
137 ~Array() {
138 deconstruct();
141 //! Returns the minimal array index.
142 INDEX low() const { return m_low; }
144 //! Returns the maximal array index.
145 INDEX high() const { return m_high; }
147 //! Returns the size (number of elements) of the array.
148 INDEX size() const { return m_high - m_low + 1; }
150 //! Returns a pointer to the first element.
151 E *begin() { return m_pStart; }
153 //! Returns a pointer to the first element.
154 const E *begin() const { return m_pStart; }
156 //! Returns a pointer to one past the last element.
157 E *end() { return m_pStop; }
159 //! Returns a pointer to one past the last element.
160 const E *end() const { return m_pStop; }
162 //! Returns a pointer to the last element.
163 E *rbegin() { return m_pStop-1; }
165 //! Returns a pointer to the last element.
166 const E *rbegin() const { return m_pStop-1; }
168 //! Returns a pointer to one before the first element.
169 E *rend() { return m_pStart-1; }
171 //! Returns a pointer to one before the first element.
172 const E *rend() const { return m_pStart-1; }
174 //! Returns a reference to the element at position \a i.
175 const E &operator[](INDEX i) const {
176 OGDF_ASSERT(m_low <= i && i <= m_high)
177 return m_vpStart[i];
180 //! Returns a reference to the element at position \a i.
181 E &operator[](INDEX i) {
182 OGDF_ASSERT(m_low <= i && i <= m_high)
183 return m_vpStart[i];
186 //! Swaps the elements at position \a i and \a j.
187 void swap(INDEX i, INDEX j) {
188 OGDF_ASSERT(m_low <= i && i <= m_high)
189 OGDF_ASSERT(m_low <= j && j <= m_high)
191 std::swap(m_vpStart[i], m_vpStart[j]);
194 //! Reinitializes the array to an array with empty index set.
195 void init() {
196 //init(0,-1);
197 deconstruct();
198 construct(0,-1);
201 //! Reinitializes the array to an array with index set [0..\a s-1].
203 * Notice that the elements contained in the array get discarded!
205 void init(INDEX s) { init(0,s-1); }
207 //! Reinitializes the array to an array with index set [\a a..\a b].
209 * Notice that the elements contained in the array get discarded!
211 void init(INDEX a, INDEX b) {
212 deconstruct();
213 construct(a,b);
214 initialize();
217 //! Reinitializes the array to an array with index set [\a a..\a b] and sets all entries to \a x.
218 void init(INDEX a, INDEX b, const E &x) {
219 deconstruct();
220 construct(a,b);
221 initialize(x);
224 //! Assignment operator.
225 Array<E,INDEX> &operator=(const Array<E,INDEX> &array2) {
226 deconstruct();
227 copy(array2);
228 return *this;
231 //! Sets all elements to \a x.
232 void fill(const E &x) {
233 E *pDest = m_pStop;
234 while(pDest > m_pStart)
235 *--pDest = x;
238 //! Sets elements in the intervall [\a i..\a j] to \a x.
239 void fill(INDEX i, INDEX j, const E &x) {
240 OGDF_ASSERT(m_low <= i && i <= m_high)
241 OGDF_ASSERT(m_low <= j && j <= m_high)
243 E *pI = m_vpStart + i, *pJ = m_vpStart + j+1;
244 while(pJ > pI)
245 *--pJ = x;
248 //! Enlarges the array by \a add elements and sets new elements to \a x.
250 * Note: address of array entries in memory may change!
251 * @param add is the number of additional elements; \a add can be negative in order to shrink the array.
252 * @param x is the inital value of all new elements.
254 void grow(INDEX add, const E &x);
256 //! Enlarges the array by \a add elements.
258 * Note: address of array entries in memory may change!
259 * @param add is the number of additional elements; \a add can be negative in order to shrink the array.
261 void grow(INDEX add);
263 //! Randomly permutes the subarray with index set [\a l..\a r].
264 void permute (INDEX l, INDEX r);
266 //! Randomly permutes the array.
267 void permute() {
268 permute(low(), high());
271 //! Performs a binary search for element \a x.
273 * \pre The array must be sorted!
274 * \return the index of the found element, and low()-1 if not found.
276 inline int binarySearch (const E& x) const {
277 return binarySearch(x, StdComparer<E>());
280 //! Performs a binary search for element \a x with comparer \a comp.
282 * \pre The array must be sorted according to \a comp!
283 * \return the index of the found element, and low()-1 if not found.
285 template<class COMPARER>
286 int binarySearch(const E& e, const COMPARER &comp) const {
287 if(size() < 2) {
288 if(size() == 1 && comp.equal(e, m_vpStart[low()]))
289 return low();
290 return low()-1;
292 int l = low();
293 int r = high();
294 do {
295 int m = (r + l)/2;
296 if(comp.greater(e, m_vpStart[m]))
297 l = m+1;
298 else
299 r = m;
300 } while(r>l);
301 return comp.equal(e, m_vpStart[l]) ? l : low()-1;
304 //! Performs a linear search for element \a x.
306 * Warning: This method has linear running time!
307 * Note that the linear search runs from back to front.
308 * \return the index of the found element, and low()-1 if not found.
310 inline int linearSearch (const E& e) const {
311 int i;
312 for(i = size(); i-->0;)
313 if(e == m_pStart[i]) break;
314 return i+low(); }
316 //! Performs a linear search for element \a x with comparer \a comp.
318 * Warning: This method has linear running time!
319 * Note that the linear search runs from back to front.
320 * \return the index of the found element, and low()-1 if not found.
322 template<class COMPARER>
323 int linearSearch(const E& e, const COMPARER &comp) const {
324 int i;
325 for(i = size(); i-->0;)
326 if(comp.equal(e, m_pStart[i])) break;
327 return i+low();
330 //! Sorts array using Quicksort.
331 inline void quicksort() {
332 quicksort(StdComparer<E>());
335 //! Sorts subarray with index set [\a l..\a r] using Quicksort.
336 inline void quicksort(INDEX l, INDEX r) {
337 quicksort(l, r, StdComparer<E>());
340 //! Sorts array using Quicksort and a user-defined comparer \a comp.
342 * @param comp is a user-defined comparer; \a C must be a class providing a \a less(x,y) method.
344 template<class COMPARER>
345 inline void quicksort(const COMPARER &comp) {
346 if(low() < high())
347 quicksortInt(m_pStart,m_pStop-1,comp);
350 //! Sorts the subarray with index set [\a l..\a r] using Quicksort and a user-defined comparer \a comp.
352 * @param l is the left-most position in the range to be sorted.
353 * @param r is the right-most position in the range to be sorted.
354 * @param comp is a user-defined comparer; \a C must be a class providing a \a less(x,y) method.
356 template<class COMPARER>
357 void quicksort(INDEX l, INDEX r, const COMPARER &comp) {
358 OGDF_ASSERT(low() <= l && l <= high())
359 OGDF_ASSERT(low() <= r && r <= high())
360 if(l < r)
361 quicksortInt(m_vpStart+l,m_vpStart+r,comp);
364 template<class F, class I> friend class ArrayBuffer; // for efficient ArrayBuffer::compact-method
366 private:
367 E *m_vpStart; //!< The virtual start of the array (address of A[0]).
368 E *m_pStart; //!< The real start of the array (address of A[m_low]).
369 E *m_pStop; //!< Successor of last element (address of A[m_high+1]).
370 INDEX m_low; //!< The lowest index.
371 INDEX m_high; //!< The highest index.
373 //! Allocates new array with index set [\a a..\a b].
374 void construct(INDEX a, INDEX b);
376 //! Initializes elements with default constructor.
377 void initialize();
379 //! Initializes elements with \a x.
380 void initialize(const E &x);
382 //! Deallocates array.
383 void deconstruct();
385 //! Constructs a new array which is a copy of \a A.
386 void copy(const Array<E,INDEX> &A);
388 //! Internal Quicksort implementation with comparer template.
389 template<class COMPARER>
390 static void quicksortInt(E *pL, E *pR, const COMPARER &comp) {
391 size_t s = pR-pL;
393 // use insertion sort for small instances
394 if (s < maxSizeInsertionSort) {
395 for (E *pI = pL+1; pI <= pR; pI++) {
396 E v = *pI;
397 E *pJ = pI;
398 while (--pJ >= pL && comp.less(v,*pJ)) {
399 *(pJ+1) = *pJ;
401 *(pJ+1) = v;
403 return;
406 E *pI = pL, *pJ = pR;
407 E x = *(pL+(s>>1));
409 do {
410 while (comp.less(*pI,x)) pI++;
411 while (comp.less(x,*pJ)) pJ--;
412 if (pI <= pJ) std::swap(*pI++,*pJ--);
413 } while (pI <= pJ);
415 if (pL < pJ) quicksortInt(pL,pJ,comp);
416 if (pI < pR) quicksortInt(pI,pR,comp);
419 OGDF_NEW_DELETE
420 }; // class Array
425 // enlarges array by add elements and sets new elements to x
426 template<class E, class INDEX>
427 void Array<E,INDEX>::grow(INDEX add, const E &x)
429 INDEX sOld = size(), sNew = sOld + add;
431 // expand allocated memory block
432 if(m_pStart != 0) {
433 E *p = (E *)realloc(m_pStart, sNew*sizeof(E));
434 if(p == 0) OGDF_THROW(InsufficientMemoryException);
435 m_pStart = p;
436 } else {
437 m_pStart = (E *)malloc(sNew*sizeof(E));
438 if (m_pStart == 0) OGDF_THROW(InsufficientMemoryException);
441 m_vpStart = m_pStart-m_low;
442 m_pStop = m_pStart+sNew;
443 m_high += add;
445 // initialize new array entries
446 for (E *pDest = m_pStart+sOld; pDest < m_pStop; pDest++)
447 new (pDest) E(x);
450 // enlarges array by add elements (initialized with default constructor)
451 template<class E, class INDEX>
452 void Array<E,INDEX>::grow(INDEX add)
454 INDEX sOld = size(), sNew = sOld + add;
456 // expand allocated memory block
457 if(m_pStart != 0) {
458 E *p = (E *)realloc(m_pStart, sNew*sizeof(E));
459 if(p == 0) OGDF_THROW(InsufficientMemoryException);
460 m_pStart = p;
461 } else {
462 m_pStart = (E *)malloc(sNew*sizeof(E));
463 if (m_pStart == 0) OGDF_THROW(InsufficientMemoryException);
466 m_vpStart = m_pStart-m_low;
467 m_pStop = m_pStart+sNew;
468 m_high += add;
470 // initialize new array entries
471 for (E *pDest = m_pStart+sOld; pDest < m_pStop; pDest++)
472 new (pDest) E;
475 template<class E, class INDEX>
476 void Array<E,INDEX>::construct(INDEX a, INDEX b)
478 m_low = a; m_high = b;
479 INDEX s = b-a+1;
481 if (s < 1) {
482 m_pStart = m_vpStart = m_pStop = 0;
484 } else {
485 m_pStart = (E *)malloc(s*sizeof(E));
486 if (m_pStart == 0) OGDF_THROW(InsufficientMemoryException);
488 m_vpStart = m_pStart - a;
489 m_pStop = m_pStart + s;
494 template<class E, class INDEX>
495 void Array<E,INDEX>::initialize()
497 E *pDest = m_pStart;
498 try {
499 for (; pDest < m_pStop; pDest++)
500 new(pDest) E;
501 } catch (...) {
502 while(--pDest >= m_pStart)
503 pDest->~E();
504 free(m_pStart);
505 throw;
510 template<class E, class INDEX>
511 void Array<E,INDEX>::initialize(const E &x)
513 E *pDest = m_pStart;
514 try {
515 for (; pDest < m_pStop; pDest++)
516 new(pDest) E(x);
517 } catch (...) {
518 while(--pDest >= m_pStart)
519 pDest->~E();
520 free(m_pStart);
521 throw;
526 template<class E, class INDEX>
527 void Array<E,INDEX>::deconstruct()
529 if (doDestruction((E*)0)) {
530 for (E *pDest = m_pStart; pDest < m_pStop; pDest++)
531 pDest->~E();
533 free(m_pStart);
537 template<class E, class INDEX>
538 void Array<E,INDEX>::copy(const Array<E,INDEX> &array2)
540 construct(array2.m_low, array2.m_high);
542 if (m_pStart != 0) {
543 E *pSrc = array2.m_pStop;
544 E *pDest = m_pStop;
545 while(pDest > m_pStart)
546 //*--pDest = *--pSrc;
547 new (--pDest) E(*--pSrc);
552 // permutes array a from a[l] to a[r] randomly
553 template<class E, class INDEX>
554 void Array<E,INDEX>::permute (INDEX l, INDEX r)
556 OGDF_ASSERT(low() <= l && l <= high())
557 OGDF_ASSERT(low() <= r && r <= high())
559 E *pI = m_vpStart+l, *pStart = m_vpStart+l, *pStop = m_vpStart+r;
560 while(pI <= pStop)
561 std::swap(*pI++,*(pStart+randomNumber(0,r-l)));
565 // prints array a to output stream os using delimiter delim
566 template<class E, class INDEX>
567 void print(ostream &os, const Array<E,INDEX> &a, char delim = ' ')
569 for (int i = a.low(); i <= a.high(); i++) {
570 if (i > a.low()) os << delim;
571 os << a[i];
576 // output operator
577 template<class E, class INDEX>
578 ostream &operator<<(ostream &os, const ogdf::Array<E,INDEX> &a)
580 print(os,a);
581 return os;
584 } // end namespace ogdf
587 #endif