1
#ifndef RDESTL_ALGORITHM_H
2
#define RDESTL_ALGORITHM_H
4
#include "int_to_type.h"
6
#include "type_traits.h"
12
//-----------------------------------------------------------------------------
13
template<typename T> RDE_FORCEINLINE
14
void copy_construct(T* mem, const T& orig)
17
internal::copy_construct(mem, orig, int_to_type<has_trivial_copy<T>::value>());
20
//-----------------------------------------------------------------------------
21
template<typename T> RDE_FORCEINLINE
22
void construct(T* mem)
24
internal::construct(mem, int_to_type<has_trivial_constructor<T>::value>());
27
//-----------------------------------------------------------------------------
28
template<typename T> RDE_FORCEINLINE
31
internal::destruct(mem, int_to_type<has_trivial_destructor<T>::value>());
34
//-----------------------------------------------------------------------------
36
void copy_n(const T* first, size_t n, T* result)
38
internal::copy_n(first, n, result, int_to_type<has_trivial_copy<T>::value>());
41
//-----------------------------------------------------------------------------
43
void copy(const T* first, const T* last, T* result)
45
internal::copy(first, last, result, int_to_type<has_trivial_copy<T>::value>());
48
//-----------------------------------------------------------------------------
50
void copy_construct_n(T* first, size_t n, T* result)
52
internal::copy_construct_n(first, n, result, int_to_type<has_trivial_copy<T>::value>());
55
//-----------------------------------------------------------------------------
57
void move_n(const T* from, size_t n, T* result)
59
RDE_ASSERT(from != result || n == 0);
61
if (result + n >= from && result < from + n)
63
internal::move_n(from, n, result, int_to_type<has_trivial_copy<T>::value>());
67
internal::copy_n(from, n, result, int_to_type<has_trivial_copy<T>::value>());
71
//-----------------------------------------------------------------------------
73
inline void move(const T* first, const T* last, T* result)
75
RDE_ASSERT(first != result || first == last);
76
const size_t n = reinterpret_cast<uintptr_t>(last) - reinterpret_cast<uintptr_t>(first);
77
const unsigned char* resultEnd = reinterpret_cast<const unsigned char*>(result) + n;
78
if (resultEnd >= reinterpret_cast<const unsigned char*>(first) && result < last)
80
internal::move(first, last, result, int_to_type<has_trivial_copy<T>::value>());
84
internal::copy(first, last, result, int_to_type<has_trivial_copy<T>::value>());
88
//-----------------------------------------------------------------------------
90
void construct_n(T* first, size_t n)
92
internal::construct_n(first, n, int_to_type<has_trivial_constructor<T>::value>());
95
//-----------------------------------------------------------------------------
97
void destruct_n(T* first, size_t n)
99
internal::destruct_n(first, n, int_to_type<has_trivial_destructor<T>::value>());
102
//-----------------------------------------------------------------------------
103
template<typename T> RDE_FORCEINLINE
104
void fill_n(T* first, size_t n, const T& val)
106
//for (size_t i = 0; i < n; ++i)
108
// Loop unrolling with Duff's Device.
113
while (first != last)
115
*first = val; ++first;
116
case 7: *first = val; ++first;
117
case 6: *first = val; ++first;
118
case 5: *first = val; ++first;
119
case 4: *first = val; ++first;
120
case 3: *first = val; ++first;
121
case 2: *first = val; ++first;
122
case 1: *first = val; ++first;
127
//-----------------------------------------------------------------------------
128
template<typename TIter, typename TDist> inline
129
void distance(TIter first, TIter last, TDist& dist)
131
internal::distance(first, last, dist, typename iterator_traits<TIter>::iterator_category());
134
//-----------------------------------------------------------------------------
135
template<typename TIter, typename TDist> inline
136
void advance(TIter& iter, TDist off)
138
internal::advance(iter, off, typename iterator_traits<TIter>::iterator_category());
141
//-----------------------------------------------------------------------------
142
template<class TIter, typename T, class TPred> inline
143
TIter lower_bound(TIter first, TIter last, const T& val, const TPred& pred)
145
internal::test_ordering(first, last, pred);
147
distance(first, last, dist);
150
const int halfDist = dist >> 1;
152
advance(mid, halfDist);
153
if (internal::debug_pred(pred, *mid, val))
154
first = ++mid, dist -= halfDist + 1;
161
//-----------------------------------------------------------------------------
162
template<class TIter, typename T, class TPred> inline
163
TIter upper_bound(TIter first, TIter last, const T& val, const TPred& pred)
165
internal::test_ordering(first, last, pred);
167
distance(first, last, dist);
170
const int halfDist = dist >> 1;
172
advance(mid, halfDist);
173
if (!internal::debug_pred(pred, val, *mid))
174
first = ++mid, dist -= halfDist + 1;
181
//-----------------------------------------------------------------------------
182
template<class TIter, typename T>
183
TIter find(TIter first, TIter last, const T& val)
185
while (first != last)
194
//-----------------------------------------------------------------------------
195
template<class TIter, typename T, class TPred>
196
TIter find_if(TIter first, TIter last, const T& val, const TPred& pred)
198
while (first != last)
200
if (pred(*first, val))
207
//-----------------------------------------------------------------------------
208
template<class TIter, typename T>
209
void accumulate(TIter first, TIter last, T& result)
211
while (first != last)
218
//-----------------------------------------------------------------------------
222
return t >= T(0) ? t : -t;
224
// No branches, Hacker's Delight way.
225
RDE_FORCEINLINE int abs(int x)
227
const int y = x >> 31;
230
RDE_FORCEINLINE short abs(short x)
232
const short y = x >> 15;
236
//-----------------------------------------------------------------------------
237
template<typename T> inline
238
T max(const T& x, const T& y)
240
return x > y ? x : y;
243
//-----------------------------------------------------------------------------
244
template<typename T> inline
245
T min(const T& x, const T& y)
247
return x < y ? x : y;
249
// @TODO: determine if it REALLY is quicker than version with branches.
250
/*RDE_FORCEINLINE float min(float x, float y)
265
//-----------------------------------------------------------------------------
266
template<typename TAssignable>
267
void swap(TAssignable& a, TAssignable& b)
276
//-----------------------------------------------------------------------------
277
#endif // #ifndef RDESTL_ALGORITHM_H