4 * Hewlett-Packard Company
6 * Permission to use, copy, modify, distribute and sell this software
7 * and its documentation for any purpose is hereby granted without fee,
8 * provided that the above copyright notice appear in all copies and
9 * that both that copyright notice and this permission notice appear
10 * in supporting documentation. Hewlett-Packard Company makes no
11 * representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
15 * Copyright (c) 1996-1998
16 * Silicon Graphics Computer Systems, Inc.
18 * Permission to use, copy, modify, distribute and sell this software
19 * and its documentation for any purpose is hereby granted without fee,
20 * provided that the above copyright notice appear in all copies and
21 * that both that copyright notice and this permission notice appear
22 * in supporting documentation. Silicon Graphics makes no
23 * representations about the suitability of this software for any
24 * purpose. It is provided "as is" without express or implied warranty.
27 /* NOTE: This is an internal header file, included by other STL headers.
28 * You should not attempt to use it directly.
32 #ifndef __SGI_STL_INTERNAL_ALGOBASE_H
33 #define __SGI_STL_INTERNAL_ALGOBASE_H
35 #ifndef __STL_CONFIG_H
36 #include <stl_config.h>
38 #ifndef __SGI_STL_INTERNAL_RELOPS
39 #include <stl_relops.h>
41 #ifndef __SGI_STL_INTERNAL_PAIR_H
44 #ifndef __TYPE_TRAITS_H_
45 #include <type_traits.h>
55 #ifndef __SGI_STL_INTERNAL_ITERATOR_H
56 #include <stl_iterator.h>
63 template <class _ForwardIter1
, class _ForwardIter2
, class _Tp
>
64 inline void __iter_swap(_ForwardIter1 __a
, _ForwardIter2 __b
, _Tp
*) {
70 template <class _ForwardIter1
, class _ForwardIter2
>
71 inline void iter_swap(_ForwardIter1 __a
, _ForwardIter2 __b
) {
72 __iter_swap(__a
, __b
, __VALUE_TYPE(__a
));
76 inline void swap(_Tp
& __a
, _Tp
& __b
) {
82 //--------------------------------------------------
91 inline const _Tp
& min(const _Tp
& __a
, const _Tp
& __b
) {
92 return __b
< __a
? __b
: __a
;
96 inline const _Tp
& max(const _Tp
& __a
, const _Tp
& __b
) {
97 return __a
< __b
? __b
: __a
;
100 #endif /* __BORLANDC__ */
102 template <class _Tp
, class _Compare
>
103 inline const _Tp
& min(const _Tp
& __a
, const _Tp
& __b
, _Compare __comp
) {
104 return __comp(__b
, __a
) ? __b
: __a
;
107 template <class _Tp
, class _Compare
>
108 inline const _Tp
& max(const _Tp
& __a
, const _Tp
& __b
, _Compare __comp
) {
109 return __comp(__a
, __b
) ? __b
: __a
;
112 //--------------------------------------------------
115 // All of these auxiliary functions serve two purposes. (1) Replace
116 // calls to copy with memmove whenever possible. (Memmove, not memcpy,
117 // because the input and output ranges are permitted to overlap.)
118 // (2) If we're using random access iterators, then write the loop as
119 // a for loop with an explicit count. The auxiliary class __copy_dispatch
120 // is a workaround for compilers that don't support partial ordering of
121 // function templates.
123 template <class _InputIter
, class _OutputIter
, class _Distance
>
124 inline _OutputIter
__copy(_InputIter __first
, _InputIter __last
,
125 _OutputIter __result
,
126 input_iterator_tag
, _Distance
*)
128 for ( ; __first
!= __last
; ++__result
, ++__first
)
129 *__result
= *__first
;
133 template <class _RandomAccessIter
, class _OutputIter
, class _Distance
>
135 __copy(_RandomAccessIter __first
, _RandomAccessIter __last
,
136 _OutputIter __result
, random_access_iterator_tag
, _Distance
*)
138 for (_Distance __n
= __last
- __first
; __n
> 0; --__n
) {
139 *__result
= *__first
;
148 __copy_trivial(const _Tp
* __first
, const _Tp
* __last
, _Tp
* __result
) {
149 memmove(__result
, __first
, sizeof(_Tp
) * (__last
- __first
));
150 return __result
+ (__last
- __first
);
153 #ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
155 template <class _InputIter
, class _OutputIter
, class _BoolType
>
156 struct __copy_dispatch
{
157 static _OutputIter
copy(_InputIter __first
, _InputIter __last
,
158 _OutputIter __result
) {
159 typedef typename iterator_traits
<_InputIter
>::iterator_category _Category
;
160 typedef typename iterator_traits
<_InputIter
>::difference_type _Distance
;
161 return __copy(__first
, __last
, __result
, _Category(), (_Distance
*) 0);
166 struct __copy_dispatch
<_Tp
*, _Tp
*, __true_type
>
168 static _Tp
* copy(const _Tp
* __first
, const _Tp
* __last
, _Tp
* __result
) {
169 return __copy_trivial(__first
, __last
, __result
);
174 struct __copy_dispatch
<const _Tp
*, _Tp
*, __true_type
>
176 static _Tp
* copy(const _Tp
* __first
, const _Tp
* __last
, _Tp
* __result
) {
177 return __copy_trivial(__first
, __last
, __result
);
181 template <class _InputIter
, class _OutputIter
>
182 inline _OutputIter
copy(_InputIter __first
, _InputIter __last
,
183 _OutputIter __result
) {
184 typedef typename iterator_traits
<_InputIter
>::value_type _Tp
;
185 typedef typename __type_traits
<_Tp
>::has_trivial_assignment_operator
187 return __copy_dispatch
<_InputIter
, _OutputIter
, _Trivial
>
188 ::copy(__first
, __last
, __result
);
191 #else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
193 template <class _InputIter
, class _OutputIter
>
194 inline _OutputIter
copy(_InputIter __first
, _InputIter __last
,
195 _OutputIter __result
)
197 return __copy(__first
, __last
, __result
,
198 __ITERATOR_CATEGORY(__first
),
199 __DISTANCE_TYPE(__first
));
202 inline char* copy(const char* __first
, const char* __last
, char* __result
) {
203 memmove(__result
, __first
, __last
- __first
);
204 return __result
+ (__last
- __first
);
207 inline wchar_t* copy(const wchar_t* __first
, const wchar_t* __last
,
209 memmove(__result
, __first
, sizeof(wchar_t) * (__last
- __first
));
210 return __result
+ (__last
- __first
);
213 #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
215 //--------------------------------------------------
218 template <class _BidirectionalIter1
, class _BidirectionalIter2
,
220 inline _BidirectionalIter2
__copy_backward(_BidirectionalIter1 __first
,
221 _BidirectionalIter1 __last
,
222 _BidirectionalIter2 __result
,
223 bidirectional_iterator_tag
,
226 while (__first
!= __last
)
227 *--__result
= *--__last
;
231 template <class _RandomAccessIter
, class _BidirectionalIter
, class _Distance
>
232 inline _BidirectionalIter
__copy_backward(_RandomAccessIter __first
,
233 _RandomAccessIter __last
,
234 _BidirectionalIter __result
,
235 random_access_iterator_tag
,
238 for (_Distance __n
= __last
- __first
; __n
> 0; --__n
)
239 *--__result
= *--__last
;
243 #ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
245 // This dispatch class is a workaround for compilers that do not
246 // have partial ordering of function templates. All we're doing is
247 // creating a specialization so that we can turn a call to copy_backward
248 // into a memmove whenever possible.
250 template <class _BidirectionalIter1
, class _BidirectionalIter2
,
252 struct __copy_backward_dispatch
254 typedef typename iterator_traits
<_BidirectionalIter1
>::iterator_category
256 typedef typename iterator_traits
<_BidirectionalIter1
>::difference_type
259 static _BidirectionalIter2
copy(_BidirectionalIter1 __first
,
260 _BidirectionalIter1 __last
,
261 _BidirectionalIter2 __result
) {
262 return __copy_backward(__first
, __last
, __result
, _Cat(), (_Distance
*) 0);
267 struct __copy_backward_dispatch
<_Tp
*, _Tp
*, __true_type
>
269 static _Tp
* copy(const _Tp
* __first
, const _Tp
* __last
, _Tp
* __result
) {
270 const ptrdiff_t _Num
= __last
- __first
;
271 memmove(__result
- _Num
, __first
, sizeof(_Tp
) * _Num
);
272 return __result
- _Num
;
277 struct __copy_backward_dispatch
<const _Tp
*, _Tp
*, __true_type
>
279 static _Tp
* copy(const _Tp
* __first
, const _Tp
* __last
, _Tp
* __result
) {
280 return __copy_backward_dispatch
<_Tp
*, _Tp
*, __true_type
>
281 ::copy(__first
, __last
, __result
);
285 template <class _BI1
, class _BI2
>
286 inline _BI2
copy_backward(_BI1 __first
, _BI1 __last
, _BI2 __result
) {
287 typedef typename __type_traits
<typename iterator_traits
<_BI2
>::value_type
>
288 ::has_trivial_assignment_operator
290 return __copy_backward_dispatch
<_BI1
, _BI2
, _Trivial
>
291 ::copy(__first
, __last
, __result
);
294 #else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
296 template <class _BI1
, class _BI2
>
297 inline _BI2
copy_backward(_BI1 __first
, _BI1 __last
, _BI2 __result
) {
298 return __copy_backward(__first
, __last
, __result
,
299 __ITERATOR_CATEGORY(__first
),
300 __DISTANCE_TYPE(__first
));
303 #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
305 //--------------------------------------------------
306 // copy_n (not part of the C++ standard)
308 template <class _InputIter
, class _Size
, class _OutputIter
>
309 pair
<_InputIter
, _OutputIter
> __copy_n(_InputIter __first
, _Size __count
,
310 _OutputIter __result
,
311 input_iterator_tag
) {
312 for ( ; __count
> 0; --__count
) {
313 *__result
= *__first
;
317 return pair
<_InputIter
, _OutputIter
>(__first
, __result
);
320 template <class _RAIter
, class _Size
, class _OutputIter
>
321 inline pair
<_RAIter
, _OutputIter
>
322 __copy_n(_RAIter __first
, _Size __count
,
323 _OutputIter __result
,
324 random_access_iterator_tag
) {
325 _RAIter __last
= __first
+ __count
;
326 return pair
<_RAIter
, _OutputIter
>(__last
, copy(__first
, __last
, __result
));
329 template <class _InputIter
, class _Size
, class _OutputIter
>
330 inline pair
<_InputIter
, _OutputIter
>
331 __copy_n(_InputIter __first
, _Size __count
, _OutputIter __result
) {
332 return __copy_n(__first
, __count
, __result
,
333 __ITERATOR_CATEGORY(__first
));
336 template <class _InputIter
, class _Size
, class _OutputIter
>
337 inline pair
<_InputIter
, _OutputIter
>
338 copy_n(_InputIter __first
, _Size __count
, _OutputIter __result
) {
339 return __copy_n(__first
, __count
, __result
);
342 //--------------------------------------------------
346 template <class _ForwardIter
, class _Tp
>
347 void fill(_ForwardIter __first
, _ForwardIter __last
, const _Tp
& __value
) {
348 for ( ; __first
!= __last
; ++__first
)
352 template <class _OutputIter
, class _Size
, class _Tp
>
353 _OutputIter
fill_n(_OutputIter __first
, _Size __n
, const _Tp
& __value
) {
354 for ( ; __n
> 0; --__n
, ++__first
)
359 //--------------------------------------------------
360 // equal and mismatch
362 template <class _InputIter1
, class _InputIter2
>
363 pair
<_InputIter1
, _InputIter2
> mismatch(_InputIter1 __first1
,
365 _InputIter2 __first2
) {
366 while (__first1
!= __last1
&& *__first1
== *__first2
) {
370 return pair
<_InputIter1
, _InputIter2
>(__first1
, __first2
);
373 template <class _InputIter1
, class _InputIter2
, class _BinaryPredicate
>
374 pair
<_InputIter1
, _InputIter2
> mismatch(_InputIter1 __first1
,
376 _InputIter2 __first2
,
377 _BinaryPredicate __binary_pred
) {
378 while (__first1
!= __last1
&& __binary_pred(*__first1
, *__first2
)) {
382 return pair
<_InputIter1
, _InputIter2
>(__first1
, __first2
);
385 template <class _InputIter1
, class _InputIter2
>
386 inline bool equal(_InputIter1 __first1
, _InputIter1 __last1
,
387 _InputIter2 __first2
) {
388 for ( ; __first1
!= __last1
; ++__first1
, ++__first2
)
389 if (*__first1
!= *__first2
)
394 template <class _InputIter1
, class _InputIter2
, class _BinaryPredicate
>
395 inline bool equal(_InputIter1 __first1
, _InputIter1 __last1
,
396 _InputIter2 __first2
, _BinaryPredicate __binary_pred
) {
397 for ( ; __first1
!= __last1
; ++__first1
, ++__first2
)
398 if (!__binary_pred(*__first1
, *__first2
))
403 //--------------------------------------------------
404 // lexicographical_compare and lexicographical_compare_3way.
405 // (the latter is not part of the C++ standard.)
407 template <class _InputIter1
, class _InputIter2
>
408 bool lexicographical_compare(_InputIter1 __first1
, _InputIter1 __last1
,
409 _InputIter2 __first2
, _InputIter2 __last2
) {
410 for ( ; __first1
!= __last1
&& __first2
!= __last2
411 ; ++__first1
, ++__first2
) {
412 if (*__first1
< *__first2
)
414 if (*__first2
< *__first1
)
417 return __first1
== __last1
&& __first2
!= __last2
;
420 template <class _InputIter1
, class _InputIter2
, class _Compare
>
421 bool lexicographical_compare(_InputIter1 __first1
, _InputIter1 __last1
,
422 _InputIter2 __first2
, _InputIter2 __last2
,
424 for ( ; __first1
!= __last1
&& __first2
!= __last2
425 ; ++__first1
, ++__first2
) {
426 if (__comp(*__first1
, *__first2
))
428 if (__comp(*__first2
, *__first1
))
431 return __first1
== __last1
&& __first2
!= __last2
;
435 lexicographical_compare(const unsigned char* __first1
,
436 const unsigned char* __last1
,
437 const unsigned char* __first2
,
438 const unsigned char* __last2
)
440 const size_t __len1
= __last1
- __first1
;
441 const size_t __len2
= __last2
- __first2
;
442 const int __result
= memcmp(__first1
, __first2
, min(__len1
, __len2
));
443 return __result
!= 0 ? __result
< 0 : __len1
< __len2
;
446 inline bool lexicographical_compare(const char* __first1
, const char* __last1
,
447 const char* __first2
, const char* __last2
)
449 #if CHAR_MAX == SCHAR_MAX
450 return lexicographical_compare((const signed char*) __first1
,
451 (const signed char*) __last1
,
452 (const signed char*) __first2
,
453 (const signed char*) __last2
);
454 #else /* CHAR_MAX == SCHAR_MAX */
455 return lexicographical_compare((const unsigned char*) __first1
,
456 (const unsigned char*) __last1
,
457 (const unsigned char*) __first2
,
458 (const unsigned char*) __last2
);
459 #endif /* CHAR_MAX == SCHAR_MAX */
462 template <class _InputIter1
, class _InputIter2
>
463 int __lexicographical_compare_3way(_InputIter1 __first1
, _InputIter1 __last1
,
464 _InputIter2 __first2
, _InputIter2 __last2
)
466 while (__first1
!= __last1
&& __first2
!= __last2
) {
467 if (*__first1
< *__first2
)
469 if (*__first2
< *__first1
)
474 if (__first2
== __last2
) {
475 return !(__first1
== __last1
);
483 __lexicographical_compare_3way(const unsigned char* __first1
,
484 const unsigned char* __last1
,
485 const unsigned char* __first2
,
486 const unsigned char* __last2
)
488 const ptrdiff_t __len1
= __last1
- __first1
;
489 const ptrdiff_t __len2
= __last2
- __first2
;
490 const int __result
= memcmp(__first1
, __first2
, min(__len1
, __len2
));
491 return __result
!= 0 ? __result
492 : (__len1
== __len2
? 0 : (__len1
< __len2
? -1 : 1));
496 __lexicographical_compare_3way(const char* __first1
, const char* __last1
,
497 const char* __first2
, const char* __last2
)
499 #if CHAR_MAX == SCHAR_MAX
500 return __lexicographical_compare_3way(
501 (const signed char*) __first1
,
502 (const signed char*) __last1
,
503 (const signed char*) __first2
,
504 (const signed char*) __last2
);
506 return __lexicographical_compare_3way((const unsigned char*) __first1
,
507 (const unsigned char*) __last1
,
508 (const unsigned char*) __first2
,
509 (const unsigned char*) __last2
);
513 template <class _InputIter1
, class _InputIter2
>
514 int lexicographical_compare_3way(_InputIter1 __first1
, _InputIter1 __last1
,
515 _InputIter2 __first2
, _InputIter2 __last2
)
517 return __lexicographical_compare_3way(__first1
, __last1
, __first2
, __last2
);
522 #endif /* __SGI_STL_INTERNAL_ALGOBASE_H */