1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <fbl/type_support.h>
8 #include <stdlib.h>
9 
10 namespace fbl {
11 
12 template<class T>
min(const T & a,const T & b)13 constexpr const T& min(const T& a, const T& b) {
14     return (b < a) ? b : a;
15 }
16 
17 template<class T>
max(const T & a,const T & b)18 constexpr const T& max(const T& a, const T& b) {
19     return (a < b) ? b : a;
20 }
21 
22 template<class T>
clamp(const T & v,const T & lo,const T & hi)23 constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
24     return (v < lo) ? lo : (hi < v) ? hi : v;
25 }
26 
27 // is_pow2
28 //
29 // Test to see if an unsigned integer type is an exact power of two or
30 // not.  Note, this needs to use a helper struct because we are not
31 // allowed to partially specialize functions (because C++).
32 namespace internal {
33 template <typename T, typename Enable = void> struct IsPow2Helper;
34 
35 template <typename T>
36 struct IsPow2Helper<T, typename enable_if<is_unsigned_integer<T>::value>::type> {
37     static constexpr bool is_pow2(T val) {
38         return (val != 0) && (((val - 1u) & val) == 0);
39     }
40 };
41 }
42 
43 // is_pow2<T>(T val)
44 //
45 // Tests to see if val (which may be any unsigned integer type) is a power of 2
46 // or not.  0 is not considered to be a power of 2.
47 //
48 template <typename T>
49 constexpr bool is_pow2(T val) {
50     return internal::IsPow2Helper<T>::is_pow2(val);
51 }
52 
53 // round_up rounds up val until it is divisible by multiple.
54 // Zero is divisible by all multiples.
55 template<class T, class U,
56          class L = typename conditional<sizeof(T) >= sizeof(U), T, U>::type,
57          class = typename enable_if<is_unsigned_integer<T>::value>::type,
58          class = typename enable_if<is_unsigned_integer<U>::value>::type>
59 constexpr const L round_up(const T& val_, const U& multiple_) {
60     const L val = static_cast<L>(val_);
61     const L multiple = static_cast<L>(multiple_);
62     return val == 0 ? 0 :
63             is_pow2<L>(multiple) ? (val + (multiple - 1)) & ~(multiple - 1) :
64                 ((val + (multiple - 1)) / multiple) * multiple;
65 }
66 
67 // round_down rounds down val until it is divisible by multiple.
68 // Zero is divisible by all multiples.
69 template<class T, class U,
70          class L = typename conditional<sizeof(T) >= sizeof(U), T, U>::type,
71          class = typename enable_if<is_unsigned_integer<T>::value>::type,
72          class = typename enable_if<is_unsigned_integer<U>::value>::type>
73 constexpr const L round_down(const T& val_, const U& multiple_) {
74     const L val = static_cast<L>(val_);
75     const L multiple = static_cast<L>(multiple_);
76     return val == 0 ? 0 :
77             is_pow2<L>(multiple) ? val & ~(multiple - 1) :
78                 (val / multiple) * multiple;
79 }
80 
81 // Returns an iterator to the maximum element in the range [|first|, |last|).
82 //
83 // |first| and |last| must be forward iterators.
84 //
85 // Similar to: <http://en.cppreference.com/w/cpp/algorithm/max_element>
86 template<class FwIterator>
87 FwIterator max_element(FwIterator first, FwIterator last) {
88     FwIterator max = first;
89     while (first < last) {
90         if (*first > *max) {
91             max = first;
92         }
93         first++;
94     }
95     return max;
96 }
97 
98 // Returns an iterator to the maximum element in the range [|first|, |last|).
99 // using |comp| to compare elements instead of operator>
100 //
101 // |first| and |last| must be forward iterators.
102 //
103 // Similar to: <http://en.cppreference.com/w/cpp/algorithm/max_element>
104 template<class FwIterator, class Compare>
105 FwIterator max_element(FwIterator first, FwIterator last, Compare comp) {
106     FwIterator max = first;
107     while (first < last) {
108         if (comp(*first, *max)) {
109             max = first;
110         }
111         first++;
112     }
113     return max;
114 }
115 
116 // Returns an iterator to the minimum element in the range [|first|, |last|).
117 //
118 // |first| and |last| must be forward iterators.
119 //
120 // Similar to: <http://en.cppreference.com/w/cpp/algorithm/min_element>
121 template<class FwIterator>
122 FwIterator min_element(FwIterator first, FwIterator last) {
123     FwIterator min = first;
124     while (first < last) {
125         if (*first < *min) {
126             min = first;
127         }
128         first++;
129     }
130     return min;
131 }
132 
133 // Returns an iterator to the minimum element in the range [|first|, |last|)
134 // using |comp| to compare elements instead of operator<
135 //
136 // |first| and |last| must be forward iterators.
137 //
138 // Similar to: <http://en.cppreference.com/w/cpp/algorithm/min_element>
139 template<class FwIterator, class Compare>
140 FwIterator min_element(FwIterator first, FwIterator last, Compare comp) {
141     FwIterator min = first;
142     while (first < last) {
143         if (comp(*first, *min)) {
144             min = first;
145         }
146         first++;
147     }
148     return min;
149 }
150 
151 // Returns a pointer to the first element that is not less than |value|, or
152 // |last| if no such element is found.
153 //
154 // Similar to <http://en.cppreference.com/w/cpp/algorithm/lower_bound>
155 template<class T, class U>
156 const T* lower_bound(const T* first, const T* last, const U& value) {
157     while (first < last) {
158         const T* probe = first + (last - first) / 2;
159         if (*probe < value) {
160             first = probe + 1;
161         } else {
162             last = probe;
163         }
164     }
165     return last;
166 }
167 
168 // Returns a pointer to the first element that is not less than |value|, or
169 // |last| if no such element is found.
170 //
171 // |comp| is used to compare the elements rather than operator<.
172 //
173 // Similar to <http://en.cppreference.com/w/cpp/algorithm/lower_bound>
174 template<class T, class U, class Compare>
175 const T* lower_bound(const T* first, const T* last, const U& value, Compare comp) {
176     while (first < last) {
177         const T* probe = first + (last - first) / 2;
178         if (comp(*probe, value)) {
179             first = probe + 1;
180         } else {
181             last = probe;
182         }
183     }
184     return last;
185 }
186 
187 template <typename T, size_t N>
188 constexpr size_t count_of(T const(&)[N]) {
189     return N;
190 }
191 
192 // 2017-12-10: On ARM/release/GCC, a div(mod)-based implementation runs at 2x
193 // the speed of subtract-based ones, with no O(n) scaling as input values grow.
194 // For x86-64/release/GCC, sub-based methods are initially 20-40% faster (depending
195 // on int type) but scale linearly; they are comparable for values 100000-200000.
196 //
197 // gcd (greatest common divisor) returns the largest non-negative integer that cleanly
198 // divides both inputs. Inputs are unsigned integers. gcd(x,0)=x; gcd(x,1)=1
199 template <typename T, class = typename enable_if<is_unsigned_integer<T>::value>::type>
200 T gcd(T first, T second) {
201     // If function need not support uint8 or uint16, static_casts can be removed
202     while (second != 0) {
203         first = static_cast<T>(first % second);
204         if (first == 0) {
205             return second;
206         }
207         second = static_cast<T>(second % first);
208     }
209 
210     return first;
211 }
212 
213 // lcm (least common multiple) returns the smallest non-negative integer that is
214 // cleanly divided by both inputs.
215 // Inputs are unsigned integers. lcm(x,0)=0; lcm(x,1)=x
216 template <typename T, class = typename enable_if<is_unsigned_integer<T>::value>::type>
217 T lcm(T first, T second) {
218     if (first == 0 && second == 0) {
219         return 0;
220     }
221 
222     // If function need not support uint8 or uint16, static_cast can be removed
223     return static_cast<T>((first / gcd(first, second)) * second);
224 }
225 
226 // Accumulates the elements in the range [|first|, |last|) with |initial_value|.
227 // Returns the accumulated value.
228 //
229 // |first| and |last| must be InputIterators.
230 //
231 // Similar to <http://en.cppreference.com/w/cpp/algorithm/accumulate>.
232 template <class InputIterator, class T>
233 T accumulate(InputIterator first, InputIterator last, T initial_value) {
234     while(first < last) {
235         initial_value += *first;
236         first++;
237     }
238     return initial_value;
239 }
240 
241 // Accumulates the elements in the range [|first|, |last|) with |initial_value|
242 // using |op| instead of operator+.  Returns the accumulated value.
243 //
244 // |first| and |last| must be InputIterators.
245 //
246 // Similar to <http://en.cppreference.com/w/cpp/algorithm/accumulate>.
247 template <class InputIterator, class T, class BinaryOp>
248 T accumulate(InputIterator first, InputIterator last, T initial_value, BinaryOp op) {
249     while(first < last) {
250         initial_value = op(initial_value, *first);
251         first++;
252     }
253     return initial_value;
254 }
255 
256 }  // namespace fbl
257