add min, max, min_element, max_element in algorithm.h; rename VectorRange to PointerRange and move to range.h (useful as generic, e.g. with InitializerList)

master
Daniel Kolesa 2015-04-19 00:02:38 +01:00
parent c36a653824
commit 58063fe392
3 changed files with 135 additions and 64 deletions

View File

@ -118,6 +118,80 @@ namespace octa {
void sort(R range) {
sort(range, Less<typename RangeTraits<R>::value>());
}
template<typename T>
inline const T &min(const T &a, const T &b) {
return (a < b) ? a : b;
}
template<typename T, typename C>
inline const T &min(const T &a, const T &b, C compare) {
return compare(a, b) ? a : b;
}
template<typename T>
inline const T &max(const T &a, const T &b) {
return (a < b) ? b : a;
}
template<typename T, typename C>
inline const T &max(const T &a, const T &b, C compare) {
return compare(a, b) ? b : a;
}
template<typename R>
inline R min_element(R range) {
R r = range;
for (; !range.empty(); range.pop_first())
if (min(r.first(), range.first()) == range.first())
r = range;
return r;
}
template<typename R, typename C>
inline R min_element(R range, C compare) {
R r = range;
for (; !range.empty(); range.pop_first())
if (min(r.first(), range.first(), compare) == range.first())
r = range;
return r;
}
template<typename R>
inline R max_element(R range) {
R r = range;
for (; !range.empty(); range.pop_first())
if (max(r.first(), range.first()) == range.first())
r = range;
return r;
}
template<typename R, typename C>
inline R max_element(R range, C compare) {
R r = range;
for (; !range.empty(); range.pop_first())
if (max(r.first(), range.first(), compare) == range.first())
r = range;
return r;
}
template<typename T>
inline T min(InitializerList<T> il) {
return min_element(PointerRange<const T>(il.get(),
il.get() + il.length())).first();
}
template<typename T, typename C>
inline T min(InitializerList<T> il, C compare) {
return min_element(PointerRange<const T>(il.get(),
il.get() + il.length(), compare)).first();
}
template<typename T>
inline T max(InitializerList<T> il) {
return max_element(PointerRange<const T>(il.get(),
il.get() + il.length())).first();
}
template<typename T, typename C>
inline T max(InitializerList<T> il, C compare) {
return max_element(PointerRange<const T>(il.get(),
il.get() + il.length(), compare)).first();
}
}
#endif

View File

@ -232,6 +232,53 @@ namespace octa {
NumberRange<T> range(T v) {
return NumberRange<T>(v);
}
template<typename T>
struct PointerRange: InputRangeBase<PointerRange<T>, RandomAccessRange, T> {
PointerRange(): p_beg(nullptr), p_end(nullptr) {}
PointerRange(const PointerRange &v): p_beg(v.p_beg), p_end(v.p_end) {}
PointerRange(T *beg, T *end): p_beg(beg), p_end(end) {}
bool operator==(const PointerRange &v) const {
return p_beg == v.p_beg && p_end == v.p_end;
}
bool operator!=(const PointerRange &v) const {
return p_beg != v.p_beg || p_end != v.p_end;
}
/* satisfy InputRange / ForwardRange */
bool empty() const { return p_beg == nullptr; }
void pop_first() {
if (p_beg == nullptr) return;
if (++p_beg == p_end) p_beg = p_end = nullptr;
}
T &first() { return *p_beg; }
const T &first() const { return *p_beg; }
/* satisfy BidirectionalRange */
void pop_last() {
if (p_end-- == p_beg) { p_end = nullptr; return; }
if (p_end == p_beg) p_beg = p_end = nullptr;
}
T &last() { return *(p_end - 1); }
const T &last() const { return *(p_end - 1); }
/* satisfy RandomAccessRange */
size_t length() const { return p_end - p_beg; }
PointerRange slice(size_t start, size_t end) {
return PointerRange(p_beg + start, p_beg + end);
}
T &operator[](size_t i) { return p_beg[i]; }
const T &operator[](size_t i) const { return p_beg[i]; }
private:
T *p_beg, *p_end;
};
}
#endif

View File

@ -13,59 +13,9 @@
#include "octa/traits.h"
#include "octa/utility.h"
#include "octa/range.h"
#include "octa/algorithm.h"
namespace octa {
/* Implementation of vector ranges
*
* See the range specification as documented on OctaForge wiki.
*/
template<typename T>
struct VectorRange: InputRangeBase<VectorRange<T>, RandomAccessRange, T> {
VectorRange(): p_beg(nullptr), p_end(nullptr) {}
VectorRange(const VectorRange &v): p_beg(v.p_beg), p_end(v.p_end) {}
VectorRange(T *beg, T *end): p_beg(beg), p_end(end) {}
bool operator==(const VectorRange &v) const {
return p_beg == v.p_beg && p_end == v.p_end;
}
bool operator!=(const VectorRange &v) const {
return p_beg != v.p_beg || p_end != v.p_end;
}
/* satisfy InputRange / ForwardRange */
bool empty() const { return p_beg == nullptr; }
void pop_first() {
if (p_beg == nullptr) return;
if (++p_beg == p_end) p_beg = p_end = nullptr;
}
T &first() { return *p_beg; }
const T &first() const { return *p_beg; }
/* satisfy BidirectionalRange */
void pop_last() {
if (p_end-- == p_beg) { p_end = nullptr; return; }
if (p_end == p_beg) p_beg = p_end = nullptr;
}
T &last() { return *(p_end - 1); }
const T &last() const { return *(p_end - 1); }
/* satisfy RandomAccessRange */
size_t length() const { return p_end - p_beg; }
VectorRange slice(size_t start, size_t end) {
return VectorRange(p_beg + start, p_beg + end);
}
T &operator[](size_t i) { return p_beg[i]; }
const T &operator[](size_t i) const { return p_beg[i]; }
private:
T *p_beg, *p_end;
};
template<typename T>
class Vector {
T *p_buf;
@ -83,15 +33,15 @@ namespace octa {
enum { MIN_SIZE = 8 };
struct type {
typedef T value;
typedef T &reference;
typedef const T &const_reference;
typedef T *pointer;
typedef const T *const_pointer;
typedef size_t size;
typedef ptrdiff_t difference;
typedef VectorRange< T> range;
typedef VectorRange<const T> const_range;
typedef T value;
typedef T &reference;
typedef const T &const_reference;
typedef T *pointer;
typedef const T *const_pointer;
typedef size_t size;
typedef ptrdiff_t difference;
typedef PointerRange< T> range;
typedef PointerRange<const T> const_range;
};
Vector(): p_buf(nullptr), p_len(0), p_cap(0) {}
@ -197,7 +147,7 @@ namespace octa {
}
size_t oc = p_cap;
if (!oc) {
p_cap = (n > MIN_SIZE) ? n : size_t(MIN_SIZE);
p_cap = max(n, size_t(MIN_SIZE));
} else {
while (p_cap < n) p_cap *= 2;
}
@ -314,15 +264,15 @@ namespace octa {
}
T *insert(size_t idx, InitializerList<T> il) {
return insert_range(idx, VectorRange<const T>(il.get(),
return insert_range(idx, PointerRange<const T>(il.get(),
il.get() + il.length()));
}
typename type::range each() {
return VectorRange<T>(p_buf, p_buf + p_len);
return PointerRange<T>(p_buf, p_buf + p_len);
}
typename type::const_range each() const {
return VectorRange<const T>(p_buf, p_buf + p_len);
return PointerRange<const T>(p_buf, p_buf + p_len);
}
};
}