mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-04-20 05:40:39 +02:00
clover: Import new utility library.
Tested-by: Tom Stellard <thomas.stellard@amd.com>
This commit is contained in:
parent
7baad4b996
commit
e93efa0d50
12 changed files with 2157 additions and 1 deletions
|
|
@ -610,7 +610,7 @@ WARN_LOGFILE =
|
|||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = api/ core/
|
||||
INPUT = api/ core/ util/
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
||||
|
|
|
|||
|
|
@ -1,4 +1,14 @@
|
|||
CPP_SOURCES := \
|
||||
util/adaptor.hpp \
|
||||
util/algebra.hpp \
|
||||
util/algorithm.hpp \
|
||||
util/compat.cpp \
|
||||
util/compat.hpp \
|
||||
util/functional.hpp \
|
||||
util/lazy.hpp \
|
||||
util/pointer.hpp \
|
||||
util/range.hpp \
|
||||
util/tuple.hpp \
|
||||
core/base.hpp \
|
||||
core/compat.hpp \
|
||||
core/compiler.hpp \
|
||||
|
|
|
|||
183
src/gallium/state_trackers/clover/util/adaptor.hpp
Normal file
183
src/gallium/state_trackers/clover/util/adaptor.hpp
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
//
|
||||
// Copyright 2013 Francisco Jerez
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#ifndef CLOVER_UTIL_ADAPTOR_HPP
|
||||
#define CLOVER_UTIL_ADAPTOR_HPP
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#include "util/tuple.hpp"
|
||||
#include "util/pointer.hpp"
|
||||
#include "util/functional.hpp"
|
||||
|
||||
namespace clover {
|
||||
namespace detail {
|
||||
///
|
||||
/// Implementation of the iterator concept that transforms the
|
||||
/// value of the source iterators \a Is on dereference by use of
|
||||
/// a functor \a F.
|
||||
///
|
||||
/// The exact category of the resulting iterator should be the
|
||||
/// least common denominator of the source iterator categories.
|
||||
///
|
||||
template<typename F, typename... Is>
|
||||
class iterator_adaptor {
|
||||
public:
|
||||
typedef std::forward_iterator_tag iterator_category;
|
||||
typedef typename std::result_of<
|
||||
F(typename std::iterator_traits<Is>::reference...)
|
||||
>::type reference;
|
||||
typedef typename std::remove_reference<reference>::type value_type;
|
||||
typedef pseudo_ptr<value_type> pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
iterator_adaptor() {
|
||||
}
|
||||
|
||||
iterator_adaptor(F f, std::tuple<Is...> &&its) :
|
||||
f(f), its(std::move(its)) {
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const {
|
||||
return tuple::apply(f, tuple::map(derefs(), its));
|
||||
}
|
||||
|
||||
iterator_adaptor &
|
||||
operator++() {
|
||||
tuple::map(preincs(), its);
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator_adaptor
|
||||
operator++(int) {
|
||||
auto jt = *this;
|
||||
++*this;
|
||||
return jt;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const iterator_adaptor &jt) const {
|
||||
return its == jt.its;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const iterator_adaptor &jt) const {
|
||||
return its != jt.its;
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const {
|
||||
return { **this };
|
||||
}
|
||||
|
||||
iterator_adaptor &
|
||||
operator--() {
|
||||
tuple::map(predecs(), its);
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator_adaptor
|
||||
operator--(int) {
|
||||
auto jt = *this;
|
||||
--*this;
|
||||
return jt;
|
||||
}
|
||||
|
||||
iterator_adaptor &
|
||||
operator+=(difference_type n) {
|
||||
tuple::map(advances_by(n), its);
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator_adaptor &
|
||||
operator-=(difference_type n) {
|
||||
tuple::map(advances_by(n), its);
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator_adaptor
|
||||
operator+(difference_type n) const {
|
||||
auto jt = *this;
|
||||
jt += n;
|
||||
return jt;
|
||||
}
|
||||
|
||||
iterator_adaptor
|
||||
operator-(difference_type n) const {
|
||||
auto jt = *this;
|
||||
jt -= n;
|
||||
return jt;
|
||||
}
|
||||
|
||||
difference_type
|
||||
operator-(const iterator_adaptor &jt) const {
|
||||
return std::get<0>(its) - std::get<0>(jt.its);
|
||||
}
|
||||
|
||||
reference
|
||||
operator[](difference_type n) const {
|
||||
return *(*this + n);
|
||||
}
|
||||
|
||||
bool
|
||||
operator<(iterator_adaptor &jt) const {
|
||||
return *this - jt < 0;
|
||||
}
|
||||
|
||||
bool
|
||||
operator>(iterator_adaptor &jt) const {
|
||||
return *this - jt > 0;
|
||||
}
|
||||
|
||||
bool
|
||||
operator>=(iterator_adaptor &jt) const {
|
||||
return !(*this < jt);
|
||||
}
|
||||
|
||||
bool
|
||||
operator<=(iterator_adaptor &jt) const {
|
||||
return !(*this > jt);
|
||||
}
|
||||
|
||||
protected:
|
||||
F f;
|
||||
std::tuple<Is...> its;
|
||||
};
|
||||
|
||||
template<typename F, typename... Is>
|
||||
iterator_adaptor<F, Is...>
|
||||
operator+(typename iterator_adaptor<F, Is...>::difference_type n,
|
||||
const iterator_adaptor<F, Is...> &jt) {
|
||||
return (jt + n);
|
||||
}
|
||||
|
||||
template<typename F, typename... Is>
|
||||
iterator_adaptor<F, Is...>
|
||||
operator-(typename iterator_adaptor<F, Is...>::difference_type n,
|
||||
const iterator_adaptor<F, Is...> &jt) {
|
||||
return (jt - n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
160
src/gallium/state_trackers/clover/util/algebra.hpp
Normal file
160
src/gallium/state_trackers/clover/util/algebra.hpp
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
//
|
||||
// Copyright 2013 Francisco Jerez
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#ifndef CLOVER_UTIL_ALGEBRA_HPP
|
||||
#define CLOVER_UTIL_ALGEBRA_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "util/range.hpp"
|
||||
#include "util/functional.hpp"
|
||||
|
||||
namespace clover {
|
||||
///
|
||||
/// Class that identifies vectors (in the linear-algebraic sense).
|
||||
///
|
||||
/// There should be a definition of this class for each type that
|
||||
/// makes sense as vector arithmetic operand.
|
||||
///
|
||||
template<typename V, typename = void>
|
||||
struct vector_traits;
|
||||
|
||||
///
|
||||
/// References of vectors are vectors.
|
||||
///
|
||||
template<typename T>
|
||||
struct vector_traits<T &, typename vector_traits<T>::enable> {
|
||||
typedef void enable;
|
||||
};
|
||||
|
||||
///
|
||||
/// Constant vectors are vectors.
|
||||
///
|
||||
template<typename T>
|
||||
struct vector_traits<const T, typename vector_traits<T>::enable> {
|
||||
typedef void enable;
|
||||
};
|
||||
|
||||
///
|
||||
/// Arrays of arithmetic types are vectors.
|
||||
///
|
||||
template<typename T, std::size_t N>
|
||||
struct vector_traits<std::array<T, N>,
|
||||
typename std::enable_if<
|
||||
std::is_arithmetic<T>::value>::type> {
|
||||
typedef void enable;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename... Ts>
|
||||
struct are_defined {
|
||||
typedef void enable;
|
||||
};
|
||||
}
|
||||
|
||||
///
|
||||
/// The result of mapping a vector is a vector.
|
||||
///
|
||||
template<typename F, typename... Vs>
|
||||
struct vector_traits<adaptor_range<F, Vs...>,
|
||||
typename detail::are_defined<
|
||||
typename vector_traits<Vs>::enable...>::enable> {
|
||||
typedef void enable;
|
||||
};
|
||||
|
||||
///
|
||||
/// Vector sum.
|
||||
///
|
||||
template<typename U, typename V,
|
||||
typename = typename vector_traits<U>::enable,
|
||||
typename = typename vector_traits<V>::enable>
|
||||
adaptor_range<plus, U, V>
|
||||
operator+(U &&u, V &&v) {
|
||||
return map(plus(), std::forward<U>(u), std::forward<V>(v));
|
||||
}
|
||||
|
||||
///
|
||||
/// Vector difference.
|
||||
///
|
||||
template<typename U, typename V,
|
||||
typename = typename vector_traits<U>::enable,
|
||||
typename = typename vector_traits<V>::enable>
|
||||
adaptor_range<minus, U, V>
|
||||
operator-(U &&u, V &&v) {
|
||||
return map(minus(), std::forward<U>(u), std::forward<V>(v));
|
||||
}
|
||||
|
||||
///
|
||||
/// Scalar multiplication.
|
||||
///
|
||||
template<typename U, typename T,
|
||||
typename = typename vector_traits<U>::enable>
|
||||
adaptor_range<multiplies_by_t<T>, U>
|
||||
operator*(U &&u, T &&a) {
|
||||
return map(multiplies_by<T>(std::forward<T>(a)), std::forward<U>(u));
|
||||
}
|
||||
|
||||
///
|
||||
/// Scalar multiplication.
|
||||
///
|
||||
template<typename U, typename T,
|
||||
typename = typename vector_traits<U>::enable>
|
||||
adaptor_range<multiplies_by_t<T>, U>
|
||||
operator*(T &&a, U &&u) {
|
||||
return map(multiplies_by<T>(std::forward<T>(a)), std::forward<U>(u));
|
||||
}
|
||||
|
||||
///
|
||||
/// Additive inverse.
|
||||
///
|
||||
template<typename U,
|
||||
typename = typename vector_traits<U>::enable>
|
||||
adaptor_range<negate, U>
|
||||
operator-(U &&u) {
|
||||
return map(negate(), std::forward<U>(u));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template<typename U, typename V>
|
||||
using dot_type = typename std::common_type<
|
||||
typename std::remove_reference<U>::type::value_type,
|
||||
typename std::remove_reference<V>::type::value_type
|
||||
>::type;
|
||||
}
|
||||
|
||||
///
|
||||
/// Dot product of two vectors.
|
||||
///
|
||||
/// It can also do matrix multiplication if \a u or \a v is a
|
||||
/// vector of vectors.
|
||||
///
|
||||
template<typename U, typename V,
|
||||
typename = typename vector_traits<U>::enable,
|
||||
typename = typename vector_traits<V>::enable>
|
||||
detail::dot_type<U, V>
|
||||
dot(U &&u, V &&v) {
|
||||
return fold(plus(), detail::dot_type<U, V>(),
|
||||
map(multiplies(), u, v));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
206
src/gallium/state_trackers/clover/util/algorithm.hpp
Normal file
206
src/gallium/state_trackers/clover/util/algorithm.hpp
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
//
|
||||
// Copyright 2013 Francisco Jerez
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#ifndef CLOVER_UTIL_ALGORITHM_HPP
|
||||
#define CLOVER_UTIL_ALGORITHM_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "util/range.hpp"
|
||||
#include "util/functional.hpp"
|
||||
|
||||
namespace clover {
|
||||
namespace detail {
|
||||
template<typename R>
|
||||
using preferred_reference_type = decltype(*std::declval<R>().begin());
|
||||
}
|
||||
|
||||
///
|
||||
/// Return the first element in a range.
|
||||
///
|
||||
template<typename R>
|
||||
detail::preferred_reference_type<R>
|
||||
head(R &&r) {
|
||||
assert(!r.empty());
|
||||
return r.front();
|
||||
}
|
||||
|
||||
///
|
||||
/// Return all elements in a range but the first.
|
||||
///
|
||||
template<typename R>
|
||||
slice_range<R>
|
||||
tail(R &&r) {
|
||||
assert(!r.empty());
|
||||
return { std::forward<R>(r), 1, r.size() };
|
||||
}
|
||||
|
||||
///
|
||||
/// Combine a variable number of ranges element-wise in a single
|
||||
/// range of tuples.
|
||||
///
|
||||
template<typename... Rs>
|
||||
adaptor_range<zips, Rs...>
|
||||
zip(Rs &&... rs) {
|
||||
return map(zips(), std::forward<Rs>(rs)...);
|
||||
}
|
||||
|
||||
///
|
||||
/// Evaluate the elements of a range.
|
||||
///
|
||||
/// Useful because most of the range algorithms evaluate their
|
||||
/// result lazily.
|
||||
///
|
||||
template<typename R>
|
||||
void
|
||||
eval(R &&r) {
|
||||
for (auto i = r.begin(), e = r.end(); i != e; ++i)
|
||||
*i;
|
||||
}
|
||||
|
||||
///
|
||||
/// Apply functor \a f element-wise on a variable number of ranges
|
||||
/// \a rs.
|
||||
///
|
||||
/// The functor \a f should take as many arguments as ranges are
|
||||
/// provided.
|
||||
///
|
||||
template<typename F, typename... Rs>
|
||||
void
|
||||
for_each(F &&f, Rs &&... rs) {
|
||||
eval(map(std::forward<F>(f), std::forward<Rs>(rs)...));
|
||||
}
|
||||
|
||||
///
|
||||
/// Copy all elements from range \a r into an output container
|
||||
/// starting from iterator \a i.
|
||||
///
|
||||
template<typename R, typename I>
|
||||
void
|
||||
copy(R &&r, I i) {
|
||||
for (detail::preferred_reference_type<R> x : r)
|
||||
*(i++) = x;
|
||||
}
|
||||
|
||||
///
|
||||
/// Reduce the elements of range \a r by applying functor \a f
|
||||
/// element by element.
|
||||
///
|
||||
/// \a f should take an accumulator value (which is initialized to
|
||||
/// \a a) and an element value as arguments, and return an updated
|
||||
/// accumulator value.
|
||||
///
|
||||
/// \returns The final value of the accumulator.
|
||||
///
|
||||
template<typename F, typename A, typename R>
|
||||
A
|
||||
fold(F &&f, A a, R &&r) {
|
||||
for (detail::preferred_reference_type<R> x : r)
|
||||
a = f(a, x);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
///
|
||||
/// Return how many elements of range \a r are equal to \a x.
|
||||
///
|
||||
template<typename T, typename R>
|
||||
typename std::remove_reference<R>::type::size_type
|
||||
count(T &&x, R &&r) {
|
||||
typename std::remove_reference<R>::type::size_type n = 0;
|
||||
|
||||
for (detail::preferred_reference_type<R> y : r) {
|
||||
if (x == y)
|
||||
n++;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
///
|
||||
/// Return the first element in range \a r for which predicate \a f
|
||||
/// evaluates to true.
|
||||
///
|
||||
template<typename F, typename R>
|
||||
detail::preferred_reference_type<R>
|
||||
find(F &&f, R &&r) {
|
||||
for (detail::preferred_reference_type<R> x : r) {
|
||||
if (f(x))
|
||||
return x;
|
||||
}
|
||||
|
||||
throw std::out_of_range("");
|
||||
}
|
||||
|
||||
///
|
||||
/// Return true if the element-wise application of predicate \a f
|
||||
/// on \a rs evaluates to true for all elements.
|
||||
///
|
||||
template<typename F, typename... Rs>
|
||||
bool
|
||||
all_of(F &&f, Rs &&... rs) {
|
||||
for (auto b : map(f, rs...)) {
|
||||
if (!b)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
/// Return true if the element-wise application of predicate \a f
|
||||
/// on \a rs evaluates to true for any element.
|
||||
///
|
||||
template<typename F, typename... Rs>
|
||||
bool
|
||||
any_of(F &&f, Rs &&... rs) {
|
||||
for (auto b : map(f, rs...)) {
|
||||
if (b)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
///
|
||||
/// Erase elements for which predicate \a f evaluates to true from
|
||||
/// container \a r.
|
||||
///
|
||||
template<typename F, typename R>
|
||||
void
|
||||
erase_if(F &&f, R &&r) {
|
||||
auto i = r.begin(), e = r.end();
|
||||
|
||||
for (auto j = r.begin(); j != e; ++j) {
|
||||
if (!f(*j)) {
|
||||
if (j != i)
|
||||
*i = std::move(*j);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
r.erase(i, e);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
38
src/gallium/state_trackers/clover/util/compat.cpp
Normal file
38
src/gallium/state_trackers/clover/util/compat.cpp
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// Copyright 2013 Francisco Jerez
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#include "util/compat.hpp"
|
||||
|
||||
using namespace clover::compat;
|
||||
|
||||
exception::~exception() {
|
||||
}
|
||||
|
||||
const char *
|
||||
exception::what() const {
|
||||
return "";
|
||||
}
|
||||
|
||||
const char *
|
||||
runtime_error::what() const {
|
||||
return _what.c_str();
|
||||
}
|
||||
328
src/gallium/state_trackers/clover/util/compat.hpp
Normal file
328
src/gallium/state_trackers/clover/util/compat.hpp
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
//
|
||||
// Copyright 2012 Francisco Jerez
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#ifndef CLOVER_UTIL_COMPAT_HPP
|
||||
#define CLOVER_UTIL_COMPAT_HPP
|
||||
|
||||
#include <new>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace clover {
|
||||
namespace compat {
|
||||
// XXX - For cases where we can't rely on STL... I.e. the
|
||||
// interface between code compiled as C++98 and C++11
|
||||
// source. Get rid of this as soon as everything can be
|
||||
// compiled as C++11.
|
||||
|
||||
template<typename T>
|
||||
class vector {
|
||||
protected:
|
||||
static T *
|
||||
alloc(int n, const T *q, int m) {
|
||||
T *p = reinterpret_cast<T *>(std::malloc(n * sizeof(T)));
|
||||
|
||||
for (int i = 0; i < m; ++i)
|
||||
new(&p[i]) T(q[i]);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
free(int n, T *p) {
|
||||
for (int i = 0; i < n; ++i)
|
||||
p[i].~T();
|
||||
|
||||
std::free(p);
|
||||
}
|
||||
|
||||
public:
|
||||
typedef T *iterator;
|
||||
typedef const T *const_iterator;
|
||||
typedef T value_type;
|
||||
typedef T &reference;
|
||||
typedef const T &const_reference;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
vector() : p(NULL), n(0) {
|
||||
}
|
||||
|
||||
vector(const vector &v) : p(alloc(v.n, v.p, v.n)), n(v.n) {
|
||||
}
|
||||
|
||||
vector(iterator p, size_type n) : p(alloc(n, p, n)), n(n) {
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
vector(const C &v) :
|
||||
p(alloc(v.size(), &*v.begin(), v.size())), n(v.size()) {
|
||||
}
|
||||
|
||||
~vector() {
|
||||
free(n, p);
|
||||
}
|
||||
|
||||
vector &
|
||||
operator=(const vector &v) {
|
||||
free(n, p);
|
||||
|
||||
p = alloc(v.n, v.p, v.n);
|
||||
n = v.n;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
reserve(size_type m) {
|
||||
if (n < m) {
|
||||
T *q = alloc(m, p, n);
|
||||
free(n, p);
|
||||
|
||||
p = q;
|
||||
n = m;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
resize(size_type m, T x = T()) {
|
||||
size_type n = size();
|
||||
|
||||
reserve(m);
|
||||
|
||||
for (size_type i = n; i < m; ++i)
|
||||
new(&p[i]) T(x);
|
||||
}
|
||||
|
||||
void
|
||||
push_back(const T &x) {
|
||||
size_type n = size();
|
||||
reserve(n + 1);
|
||||
new(&p[n]) T(x);
|
||||
}
|
||||
|
||||
size_type
|
||||
size() const {
|
||||
return n;
|
||||
}
|
||||
|
||||
iterator
|
||||
begin() {
|
||||
return p;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const {
|
||||
return p;
|
||||
}
|
||||
|
||||
iterator
|
||||
end() {
|
||||
return p + n;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const {
|
||||
return p + n;
|
||||
}
|
||||
|
||||
reference
|
||||
operator[](size_type i) {
|
||||
return p[i];
|
||||
}
|
||||
|
||||
const_reference
|
||||
operator[](size_type i) const {
|
||||
return p[i];
|
||||
}
|
||||
|
||||
private:
|
||||
iterator p;
|
||||
size_type n;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class vector_ref {
|
||||
public:
|
||||
typedef T *iterator;
|
||||
typedef const T *const_iterator;
|
||||
typedef T value_type;
|
||||
typedef T &reference;
|
||||
typedef const T &const_reference;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
vector_ref(iterator p, size_type n) : p(p), n(n) {
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
vector_ref(C &v) : p(&*v.begin()), n(v.size()) {
|
||||
}
|
||||
|
||||
size_type
|
||||
size() const {
|
||||
return n;
|
||||
}
|
||||
|
||||
iterator
|
||||
begin() {
|
||||
return p;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const {
|
||||
return p;
|
||||
}
|
||||
|
||||
iterator
|
||||
end() {
|
||||
return p + n;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const {
|
||||
return p + n;
|
||||
}
|
||||
|
||||
reference
|
||||
operator[](int i) {
|
||||
return p[i];
|
||||
}
|
||||
|
||||
const_reference
|
||||
operator[](int i) const {
|
||||
return p[i];
|
||||
}
|
||||
|
||||
private:
|
||||
iterator p;
|
||||
size_type n;
|
||||
};
|
||||
|
||||
class istream {
|
||||
public:
|
||||
typedef vector_ref<const unsigned char> buffer_t;
|
||||
|
||||
class error {
|
||||
public:
|
||||
virtual ~error() {}
|
||||
};
|
||||
|
||||
istream(const buffer_t &buf) : buf(buf), offset(0) {}
|
||||
|
||||
void
|
||||
read(char *p, size_t n) {
|
||||
if (offset + n > buf.size())
|
||||
throw error();
|
||||
|
||||
std::memcpy(p, buf.begin() + offset, n);
|
||||
offset += n;
|
||||
}
|
||||
|
||||
private:
|
||||
const buffer_t &buf;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
class ostream {
|
||||
public:
|
||||
typedef vector<unsigned char> buffer_t;
|
||||
|
||||
ostream(buffer_t &buf) : buf(buf), offset(buf.size()) {}
|
||||
|
||||
void
|
||||
write(const char *p, size_t n) {
|
||||
buf.resize(offset + n);
|
||||
std::memcpy(buf.begin() + offset, p, n);
|
||||
offset += n;
|
||||
}
|
||||
|
||||
private:
|
||||
buffer_t &buf;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
class string : public vector_ref<const char> {
|
||||
public:
|
||||
string(const char *p) : vector_ref(p, std::strlen(p)) {
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
string(const C &v) : vector_ref(v) {
|
||||
}
|
||||
|
||||
operator std::string() const {
|
||||
return std::string(begin(), end());
|
||||
}
|
||||
|
||||
const char *
|
||||
c_str() const {
|
||||
return begin();
|
||||
}
|
||||
|
||||
const char *
|
||||
find(const string &s) const {
|
||||
for (size_t i = 0; i + s.size() < size(); ++i) {
|
||||
if (!std::memcmp(begin() + i, s.begin(), s.size()))
|
||||
return begin() + i;
|
||||
}
|
||||
|
||||
return end();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool
|
||||
operator==(const vector_ref<T> &a, const vector_ref<T> &b) {
|
||||
if (a.size() != b.size())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < a.size(); ++i)
|
||||
if (a[i] != b[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class exception {
|
||||
public:
|
||||
exception() {}
|
||||
virtual ~exception();
|
||||
|
||||
virtual const char *what() const;
|
||||
};
|
||||
|
||||
class runtime_error : public exception {
|
||||
public:
|
||||
runtime_error(const string &what) : _what(what) {}
|
||||
|
||||
virtual const char *what() const;
|
||||
|
||||
protected:
|
||||
string _what;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
375
src/gallium/state_trackers/clover/util/functional.hpp
Normal file
375
src/gallium/state_trackers/clover/util/functional.hpp
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
//
|
||||
// Copyright 2013 Francisco Jerez
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#ifndef CLOVER_UTIL_FUNCTIONAL_HPP
|
||||
#define CLOVER_UTIL_FUNCTIONAL_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace clover {
|
||||
struct identity {
|
||||
template<typename T>
|
||||
typename std::remove_reference<T>::type
|
||||
operator()(T &&x) const {
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
struct plus {
|
||||
template<typename T, typename S>
|
||||
typename std::common_type<T, S>::type
|
||||
operator()(T x, S y) const {
|
||||
return x + y;
|
||||
}
|
||||
};
|
||||
|
||||
struct minus {
|
||||
template<typename T, typename S>
|
||||
typename std::common_type<T, S>::type
|
||||
operator()(T x, S y) const {
|
||||
return x - y;
|
||||
}
|
||||
};
|
||||
|
||||
struct negate {
|
||||
template<typename T>
|
||||
T
|
||||
operator()(T x) const {
|
||||
return -x;
|
||||
}
|
||||
};
|
||||
|
||||
struct multiplies {
|
||||
template<typename T, typename S>
|
||||
typename std::common_type<T, S>::type
|
||||
operator()(T x, S y) const {
|
||||
return x * y;
|
||||
}
|
||||
};
|
||||
|
||||
struct divides {
|
||||
template<typename T, typename S>
|
||||
typename std::common_type<T, S>::type
|
||||
operator()(T x, S y) const {
|
||||
return x / y;
|
||||
}
|
||||
};
|
||||
|
||||
struct modulus {
|
||||
template<typename T, typename S>
|
||||
typename std::common_type<T, S>::type
|
||||
operator()(T x, S y) const {
|
||||
return x % y;
|
||||
}
|
||||
};
|
||||
|
||||
struct minimum {
|
||||
template<typename T>
|
||||
T
|
||||
operator()(T x) const {
|
||||
return x;
|
||||
}
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
T
|
||||
operator()(T x, Ts... xs) const {
|
||||
T y = minimum()(xs...);
|
||||
return x < y ? x : y;
|
||||
}
|
||||
};
|
||||
|
||||
struct maximum {
|
||||
template<typename T>
|
||||
T
|
||||
operator()(T x) const {
|
||||
return x;
|
||||
}
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
T
|
||||
operator()(T x, Ts... xs) const {
|
||||
T y = maximum()(xs...);
|
||||
return x < y ? y : x;
|
||||
}
|
||||
};
|
||||
|
||||
struct preincs {
|
||||
template<typename T>
|
||||
T &
|
||||
operator()(T &x) const {
|
||||
return ++x;
|
||||
}
|
||||
};
|
||||
|
||||
struct predecs {
|
||||
template<typename T>
|
||||
T &
|
||||
operator()(T &x) const {
|
||||
return --x;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class multiplies_by_t {
|
||||
public:
|
||||
multiplies_by_t(T x) : x(x) {
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
typename std::common_type<T, S>::type
|
||||
operator()(S y) const {
|
||||
return x * y;
|
||||
}
|
||||
|
||||
private:
|
||||
T x;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
multiplies_by_t<T>
|
||||
multiplies_by(T x) {
|
||||
return { x };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class preincs_by_t {
|
||||
public:
|
||||
preincs_by_t(T n) : n(n) {
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
S &
|
||||
operator()(S &x) const {
|
||||
return x += n;
|
||||
}
|
||||
|
||||
private:
|
||||
T n;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
preincs_by_t<T>
|
||||
preincs_by(T n) {
|
||||
return { n };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class predecs_by_t {
|
||||
public:
|
||||
predecs_by_t(T n) : n(n) {
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
S &
|
||||
operator()(S &x) const {
|
||||
return x -= n;
|
||||
}
|
||||
|
||||
private:
|
||||
T n;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
predecs_by_t<T>
|
||||
predecs_by(T n) {
|
||||
return { n };
|
||||
}
|
||||
|
||||
struct greater {
|
||||
template<typename T, typename S>
|
||||
bool
|
||||
operator()(T x, S y) const {
|
||||
return x > y;
|
||||
}
|
||||
};
|
||||
|
||||
struct derefs {
|
||||
template<typename T>
|
||||
auto
|
||||
operator()(T &&x) const -> decltype(*x) {
|
||||
return *x;
|
||||
}
|
||||
};
|
||||
|
||||
struct addresses {
|
||||
template<typename T>
|
||||
T *
|
||||
operator()(T &x) const {
|
||||
return &x;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T *
|
||||
operator()(std::reference_wrapper<T> x) const {
|
||||
return &x.get();
|
||||
}
|
||||
};
|
||||
|
||||
struct begins {
|
||||
template<typename T>
|
||||
auto
|
||||
operator()(T &x) const -> decltype(x.begin()) {
|
||||
return x.begin();
|
||||
}
|
||||
};
|
||||
|
||||
struct ends {
|
||||
template<typename T>
|
||||
auto
|
||||
operator()(T &x) const -> decltype(x.end()) {
|
||||
return x.end();
|
||||
}
|
||||
};
|
||||
|
||||
struct sizes {
|
||||
template<typename T>
|
||||
auto
|
||||
operator()(T &x) const -> decltype(x.size()) {
|
||||
return x.size();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class advances_by_t {
|
||||
public:
|
||||
advances_by_t(T n) : n(n) {
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
S
|
||||
operator()(S &&it) const {
|
||||
std::advance(it, n);
|
||||
return it;
|
||||
}
|
||||
|
||||
private:
|
||||
T n;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
advances_by_t<T>
|
||||
advances_by(T n) {
|
||||
return { n };
|
||||
}
|
||||
|
||||
struct zips {
|
||||
template<typename... Ts>
|
||||
std::tuple<Ts...>
|
||||
operator()(Ts &&... xs) const {
|
||||
return std::tuple<Ts...>(std::forward<Ts>(xs)...);
|
||||
}
|
||||
};
|
||||
|
||||
struct is_zero {
|
||||
template<typename T>
|
||||
bool
|
||||
operator()(const T &x) const {
|
||||
return x == 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct keys {
|
||||
template<typename P>
|
||||
typename std::remove_reference<P>::type::first_type &
|
||||
operator()(P &&p) const {
|
||||
return p.first;
|
||||
}
|
||||
};
|
||||
|
||||
struct values {
|
||||
template<typename P>
|
||||
typename std::remove_reference<P>::type::second_type &
|
||||
operator()(P &&p) const {
|
||||
return p.second;
|
||||
}
|
||||
};
|
||||
|
||||
class name_equals {
|
||||
public:
|
||||
name_equals(const std::string &name) : name(name) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool
|
||||
operator()(const T &x) const {
|
||||
return std::string(x.name.begin(), x.name.end()) == name;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string &name;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class key_equals_t {
|
||||
public:
|
||||
key_equals_t(T &&x) : x(x) {
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
bool
|
||||
operator()(const std::pair<T, S> &p) const {
|
||||
return p.first == x;
|
||||
}
|
||||
|
||||
private:
|
||||
T x;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
key_equals_t<T>
|
||||
key_equals(T &&x) {
|
||||
return { std::forward<T>(x) };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class type_equals_t {
|
||||
public:
|
||||
type_equals_t(T type) : type(type) {
|
||||
}
|
||||
|
||||
template<typename S>
|
||||
bool
|
||||
operator()(const S &x) const {
|
||||
return x.type == type;
|
||||
}
|
||||
|
||||
private:
|
||||
T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
type_equals_t<T>
|
||||
type_equals(T x) {
|
||||
return { x };
|
||||
}
|
||||
|
||||
struct interval_overlaps {
|
||||
template<typename T>
|
||||
bool
|
||||
operator()(T x0, T x1, T y0, T y1) {
|
||||
return ((x0 <= y0 && y0 < x1) ||
|
||||
(y0 <= x0 && x0 < y1));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
161
src/gallium/state_trackers/clover/util/lazy.hpp
Normal file
161
src/gallium/state_trackers/clover/util/lazy.hpp
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
//
|
||||
// Copyright 2013 Francisco Jerez
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#ifndef CLOVER_UTIL_LAZY_HPP
|
||||
#define CLOVER_UTIL_LAZY_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
namespace clover {
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
class basic_lazy {
|
||||
public:
|
||||
virtual
|
||||
~basic_lazy() {
|
||||
}
|
||||
|
||||
virtual basic_lazy *
|
||||
clone() const = 0;
|
||||
|
||||
virtual
|
||||
operator T() const = 0;
|
||||
};
|
||||
|
||||
template<typename T, typename F>
|
||||
class deferred_lazy : public basic_lazy<T> {
|
||||
public:
|
||||
template<typename G>
|
||||
deferred_lazy(G &&f) : f(new F(std::forward<G>(f))) {
|
||||
}
|
||||
|
||||
virtual basic_lazy<T> *
|
||||
clone() const {
|
||||
return new deferred_lazy(*this);
|
||||
}
|
||||
|
||||
operator T() const {
|
||||
if (f) {
|
||||
x = (*f)();
|
||||
f = {};
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::shared_ptr<F> f;
|
||||
mutable T x;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class strict_lazy : public basic_lazy<T> {
|
||||
public:
|
||||
template<typename S>
|
||||
strict_lazy(S &&x) : x(std::forward<S>(x)) {
|
||||
}
|
||||
|
||||
virtual basic_lazy<T> *
|
||||
clone() const {
|
||||
return new strict_lazy(*this);
|
||||
}
|
||||
|
||||
operator T() const {
|
||||
return x;
|
||||
}
|
||||
|
||||
private:
|
||||
T x;
|
||||
};
|
||||
}
|
||||
|
||||
///
|
||||
/// Object that represents a value of type \a T that is calculated
|
||||
/// lazily as soon as it is required.
|
||||
///
|
||||
template<typename T>
|
||||
class lazy {
|
||||
public:
|
||||
class undefined_error : std::logic_error {
|
||||
public:
|
||||
undefined_error() : std::logic_error("") {
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
/// Initialize to some fixed value \a x which isn't calculated
|
||||
/// lazily.
|
||||
///
|
||||
lazy(T x) : obj(new detail::strict_lazy<T>(x)) {
|
||||
}
|
||||
|
||||
///
|
||||
/// Initialize by providing a functor \a f that will calculate
|
||||
/// the value on-demand.
|
||||
///
|
||||
template<typename F>
|
||||
lazy(F &&f) : obj(new detail::deferred_lazy<
|
||||
T, typename std::remove_reference<F>::type
|
||||
>(std::forward<F>(f))) {
|
||||
}
|
||||
|
||||
///
|
||||
/// Initialize to undefined.
|
||||
///
|
||||
lazy() : lazy([]() {
|
||||
throw undefined_error();
|
||||
return T();
|
||||
}) {
|
||||
}
|
||||
|
||||
lazy(const lazy &other) : obj(obj->clone()) {
|
||||
}
|
||||
|
||||
lazy(lazy &&other) : obj(NULL) {
|
||||
std::swap(obj, other.obj);
|
||||
}
|
||||
|
||||
~lazy() {
|
||||
delete obj;
|
||||
}
|
||||
|
||||
lazy &
|
||||
operator=(lazy other) {
|
||||
std::swap(obj, other.obj);
|
||||
return *this;
|
||||
}
|
||||
|
||||
///
|
||||
/// Evaluate the value.
|
||||
///
|
||||
operator T() const {
|
||||
return *obj;
|
||||
}
|
||||
|
||||
private:
|
||||
detail::basic_lazy<T> *obj;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
157
src/gallium/state_trackers/clover/util/pointer.hpp
Normal file
157
src/gallium/state_trackers/clover/util/pointer.hpp
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
//
|
||||
// Copyright 2013 Francisco Jerez
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#ifndef CLOVER_UTIL_POINTER_HPP
|
||||
#define CLOVER_UTIL_POINTER_HPP
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace clover {
|
||||
///
|
||||
/// Base class for objects that support reference counting.
|
||||
///
|
||||
class ref_counter {
|
||||
public:
|
||||
ref_counter() : _ref_count(1) {}
|
||||
|
||||
unsigned
|
||||
ref_count() {
|
||||
return _ref_count;
|
||||
}
|
||||
|
||||
void
|
||||
retain() {
|
||||
_ref_count++;
|
||||
}
|
||||
|
||||
bool
|
||||
release() {
|
||||
return (--_ref_count) == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<unsigned> _ref_count;
|
||||
};
|
||||
|
||||
///
|
||||
/// Intrusive smart pointer for objects that implement the
|
||||
/// clover::ref_counter interface.
|
||||
///
|
||||
template<typename T>
|
||||
class ref_ptr {
|
||||
public:
|
||||
ref_ptr(T *q = NULL) : p(NULL) {
|
||||
reset(q);
|
||||
}
|
||||
|
||||
ref_ptr(const ref_ptr<T> &ref) : p(NULL) {
|
||||
reset(ref.p);
|
||||
}
|
||||
|
||||
~ref_ptr() {
|
||||
reset(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
reset(T *q = NULL) {
|
||||
if (q)
|
||||
q->retain();
|
||||
if (p && p->release())
|
||||
delete p;
|
||||
p = q;
|
||||
}
|
||||
|
||||
ref_ptr &
|
||||
operator=(const ref_ptr &ref) {
|
||||
reset(ref.p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
T &
|
||||
operator*() const {
|
||||
return *p;
|
||||
}
|
||||
|
||||
T *
|
||||
operator->() const {
|
||||
return p;
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
T *p;
|
||||
};
|
||||
|
||||
///
|
||||
/// Transfer the caller's ownership of a reference-counted object
|
||||
/// to a clover::ref_ptr smart pointer.
|
||||
///
|
||||
template<typename T>
|
||||
inline ref_ptr<T>
|
||||
transfer(T *p) {
|
||||
ref_ptr<T> ref { p };
|
||||
p->release();
|
||||
return ref;
|
||||
}
|
||||
|
||||
///
|
||||
/// Class that implements the usual pointer interface but in fact
|
||||
/// contains the object it seems to be pointing to.
|
||||
///
|
||||
template<typename T>
|
||||
class pseudo_ptr {
|
||||
public:
|
||||
pseudo_ptr(T x) : x(x) {
|
||||
}
|
||||
|
||||
pseudo_ptr(const pseudo_ptr &p) : x(p.x) {
|
||||
}
|
||||
|
||||
pseudo_ptr &
|
||||
operator=(const pseudo_ptr &p) {
|
||||
x = p.x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T &
|
||||
operator*() {
|
||||
return x;
|
||||
}
|
||||
|
||||
T *
|
||||
operator->() {
|
||||
return &x;
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
T x;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
421
src/gallium/state_trackers/clover/util/range.hpp
Normal file
421
src/gallium/state_trackers/clover/util/range.hpp
Normal file
|
|
@ -0,0 +1,421 @@
|
|||
//
|
||||
// Copyright 2013 Francisco Jerez
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#ifndef CLOVER_UTIL_RANGE_HPP
|
||||
#define CLOVER_UTIL_RANGE_HPP
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include "util/adaptor.hpp"
|
||||
|
||||
namespace clover {
|
||||
///
|
||||
/// Class that identifies container types where the elements of a
|
||||
/// range can be stored by the type conversion operator.
|
||||
///
|
||||
/// \a T identifies the range element type.
|
||||
///
|
||||
template<typename T, typename V>
|
||||
struct range_store_traits;
|
||||
|
||||
template<typename T>
|
||||
struct range_store_traits<T, std::vector<T>> {
|
||||
typedef void enable;
|
||||
|
||||
template<typename R>
|
||||
static std::vector<T>
|
||||
create(const R &r) {
|
||||
return { r.begin(), r.end() };
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
struct range_store_traits<T, std::array<T, N>> {
|
||||
typedef void enable;
|
||||
|
||||
template<typename R>
|
||||
static std::array<T, N>
|
||||
create(const R &r) {
|
||||
std::array<T, N> v;
|
||||
assert(r.size() == v.size());
|
||||
copy(r, v.begin());
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
///
|
||||
/// Common functionality that is shared by other implementations
|
||||
/// of the container concept.
|
||||
///
|
||||
template<typename R, typename I, typename CI>
|
||||
class basic_range {
|
||||
public:
|
||||
typedef I iterator;
|
||||
typedef CI const_iterator;
|
||||
typedef typename std::iterator_traits<iterator>::value_type value_type;
|
||||
typedef typename std::iterator_traits<iterator>::reference
|
||||
reference;
|
||||
typedef typename std::iterator_traits<const_iterator>::reference
|
||||
const_reference;
|
||||
typedef typename std::iterator_traits<iterator>::difference_type
|
||||
difference_type;
|
||||
typedef std::size_t size_type;
|
||||
|
||||
bool
|
||||
operator==(const basic_range &r) const {
|
||||
return *static_cast<const R *>(this) == r;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(const basic_range &r) const {
|
||||
return !(*this == r);
|
||||
}
|
||||
|
||||
iterator
|
||||
begin() {
|
||||
return static_cast<R *>(this)->begin();
|
||||
}
|
||||
|
||||
iterator
|
||||
end() {
|
||||
return static_cast<R *>(this)->end();
|
||||
}
|
||||
|
||||
const_iterator
|
||||
begin() const {
|
||||
return static_cast<const R *>(this)->begin();
|
||||
}
|
||||
|
||||
const_iterator
|
||||
end() const {
|
||||
return static_cast<const R *>(this)->end();
|
||||
}
|
||||
|
||||
std::reverse_iterator<iterator>
|
||||
rbegin() {
|
||||
return { begin() };
|
||||
}
|
||||
|
||||
std::reverse_iterator<iterator>
|
||||
rend() {
|
||||
return { end() };
|
||||
}
|
||||
|
||||
reference
|
||||
front() {
|
||||
return *begin();
|
||||
}
|
||||
|
||||
reference
|
||||
back() {
|
||||
return *(end() - 1);
|
||||
}
|
||||
|
||||
bool
|
||||
empty() const {
|
||||
return begin() == end();
|
||||
}
|
||||
|
||||
reference
|
||||
at(size_type i) {
|
||||
if (i >= static_cast<const R *>(this)->size())
|
||||
throw std::out_of_range("");
|
||||
|
||||
return begin()[i];
|
||||
}
|
||||
|
||||
const_reference
|
||||
at(size_type i) const {
|
||||
if (i >= static_cast<const R *>(this)->size())
|
||||
throw std::out_of_range("");
|
||||
|
||||
return begin()[i];
|
||||
}
|
||||
|
||||
reference
|
||||
operator[](size_type i) {
|
||||
return begin()[i];
|
||||
}
|
||||
|
||||
const_reference
|
||||
operator[](size_type i) const {
|
||||
return begin()[i];
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
using store_traits = range_store_traits<
|
||||
typename std::remove_cv<value_type>::type, V
|
||||
>;
|
||||
|
||||
template<typename V,
|
||||
typename = typename store_traits<V>::enable>
|
||||
operator V() const {
|
||||
return store_traits<V>::create(*static_cast<const R *>(this));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
///
|
||||
/// Range that contains all elements delimited by an iterator pair
|
||||
/// (\a i, \a j). Use range() as convenience constructor.
|
||||
///
|
||||
template<typename I>
|
||||
class iterator_range : public detail::basic_range<iterator_range<I>, I, I> {
|
||||
public:
|
||||
typedef detail::basic_range<iterator_range<I>, I, I> super;
|
||||
|
||||
iterator_range() : i(), j() {
|
||||
}
|
||||
|
||||
iterator_range(I i, I j) : i(i), j(j) {
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const iterator_range &r) const {
|
||||
return i == r.i && j == r.j;
|
||||
}
|
||||
|
||||
I
|
||||
begin() const {
|
||||
return i;
|
||||
}
|
||||
|
||||
I
|
||||
end() const {
|
||||
return j;
|
||||
}
|
||||
|
||||
typename super::size_type
|
||||
size() const {
|
||||
return end() - begin();
|
||||
}
|
||||
|
||||
private:
|
||||
I i, j;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
using preferred_iterator_type = decltype(std::declval<T>().begin());
|
||||
|
||||
template<typename F, typename... Os>
|
||||
using adaptor_iterator = detail::iterator_adaptor<
|
||||
F, preferred_iterator_type<Os>...>;
|
||||
|
||||
template<typename F, typename... Os>
|
||||
using adaptor_const_iterator = detail::iterator_adaptor<
|
||||
F, preferred_iterator_type<const Os>...>;
|
||||
}
|
||||
|
||||
///
|
||||
/// Range that transforms the contents of a number of source ranges
|
||||
/// \a os element-wise by using the provided functor \a f. Use
|
||||
/// map() as convenience constructor.
|
||||
///
|
||||
template<typename F, typename... Os>
|
||||
class adaptor_range :
|
||||
public detail::basic_range<adaptor_range<F, Os...>,
|
||||
detail::adaptor_iterator<F, Os...>,
|
||||
detail::adaptor_const_iterator<F, Os...>> {
|
||||
public:
|
||||
typedef detail::basic_range<adaptor_range<F, Os...>,
|
||||
detail::adaptor_iterator<F, Os...>,
|
||||
detail::adaptor_const_iterator<F, Os...>
|
||||
> super;
|
||||
|
||||
template<typename G, typename... Rs>
|
||||
adaptor_range(G &&f, Rs &&... os) :
|
||||
f(std::forward<G>(f)), os(std::forward<Rs>(os)...) {
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const adaptor_range &r) const {
|
||||
return f == r.f && os == r.os;
|
||||
}
|
||||
|
||||
detail::adaptor_iterator<F, Os...>
|
||||
begin() {
|
||||
return { f, tuple::map(begins(), os) };
|
||||
}
|
||||
|
||||
detail::adaptor_iterator<F, Os...>
|
||||
end() {
|
||||
return { f, tuple::map(advances_by(size()),
|
||||
tuple::map(begins(), os)) };
|
||||
}
|
||||
|
||||
detail::adaptor_const_iterator<F, Os...>
|
||||
begin() const {
|
||||
return { f, tuple::map(begins(), os) };
|
||||
}
|
||||
|
||||
detail::adaptor_const_iterator<F, Os...>
|
||||
end() const {
|
||||
return { f, tuple::map(ends(), os) };
|
||||
}
|
||||
|
||||
typename super::size_type
|
||||
size() const {
|
||||
return tuple::apply(minimum(), tuple::map(sizes(), os));
|
||||
}
|
||||
|
||||
private:
|
||||
F f;
|
||||
std::tuple<Os...> os;
|
||||
};
|
||||
|
||||
///
|
||||
/// Range that contains all elements delimited by the index pair
|
||||
/// (\a i, \a j) in the source range \a r. Use slice() as
|
||||
/// convenience constructor.
|
||||
///
|
||||
template<typename O>
|
||||
class slice_range :
|
||||
public detail::basic_range<slice_range<O>,
|
||||
detail::preferred_iterator_type<O>,
|
||||
detail::preferred_iterator_type<const O>> {
|
||||
public:
|
||||
typedef detail::basic_range<slice_range<O>,
|
||||
detail::preferred_iterator_type<O>,
|
||||
detail::preferred_iterator_type<const O>
|
||||
> super;
|
||||
|
||||
template<typename R>
|
||||
slice_range(R &&r, typename super::size_type i,
|
||||
typename super::size_type j) :
|
||||
o(std::forward<R>(r)), i(i), j(j) {
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const slice_range &r) const {
|
||||
return o == r.o && i == r.i && j == r.j;
|
||||
}
|
||||
|
||||
typename super::iterator
|
||||
begin() {
|
||||
return std::next(o.begin(), i);
|
||||
}
|
||||
|
||||
typename super::iterator
|
||||
end() {
|
||||
return std::next(o.begin(), j);
|
||||
}
|
||||
|
||||
typename super::const_iterator
|
||||
begin() const {
|
||||
return std::next(o.begin(), i);
|
||||
}
|
||||
|
||||
typename super::const_iterator
|
||||
end() const {
|
||||
return std::next(o.begin(), j);
|
||||
}
|
||||
|
||||
typename super::size_type
|
||||
size() const {
|
||||
return j - i;
|
||||
}
|
||||
|
||||
private:
|
||||
O o;
|
||||
typename super::size_type i, j;
|
||||
};
|
||||
|
||||
///
|
||||
/// Create a range from an iterator pair (\a i, \a j).
|
||||
///
|
||||
/// \sa iterator_range.
|
||||
///
|
||||
template<typename T>
|
||||
iterator_range<T>
|
||||
range(T i, T j) {
|
||||
return { i, j };
|
||||
}
|
||||
|
||||
///
|
||||
/// Create a range of \a n elements starting from iterator \a i.
|
||||
///
|
||||
/// \sa iterator_range.
|
||||
///
|
||||
template<typename T>
|
||||
iterator_range<T>
|
||||
range(T i, typename std::iterator_traits<T>::difference_type n) {
|
||||
return { i, i + n };
|
||||
}
|
||||
|
||||
///
|
||||
/// Create a range by transforming the contents of a number of
|
||||
/// source ranges \a rs element-wise using a provided functor \a f.
|
||||
///
|
||||
/// \sa adaptor_range.
|
||||
///
|
||||
template<typename F, typename... Rs>
|
||||
adaptor_range<F, Rs...>
|
||||
map(F &&f, Rs &&... rs) {
|
||||
return { std::forward<F>(f), std::forward<Rs>(rs)... };
|
||||
}
|
||||
|
||||
///
|
||||
/// Create a range identical to another range \a r.
|
||||
///
|
||||
template<typename R>
|
||||
adaptor_range<identity, R>
|
||||
range(R &&r) {
|
||||
return { identity(), std::forward<R>(r) };
|
||||
}
|
||||
|
||||
///
|
||||
/// Create a range by taking the elements delimited by the index
|
||||
/// pair (\a i, \a j) in a source range \a r.
|
||||
///
|
||||
/// \sa slice_range.
|
||||
///
|
||||
template<typename R>
|
||||
slice_range<R>
|
||||
slice(R &&r, typename slice_range<R>::size_type i,
|
||||
typename slice_range<R>::size_type j) {
|
||||
return { std::forward<R>(r), i, j };
|
||||
}
|
||||
|
||||
///
|
||||
/// Range that behaves as a vector of references of type \a T.
|
||||
///
|
||||
/// Useful because STL containers cannot contain references to
|
||||
/// objects as elements.
|
||||
///
|
||||
template<typename T>
|
||||
class ref_vector : public adaptor_range<derefs, std::vector<T *>> {
|
||||
public:
|
||||
ref_vector(std::initializer_list<std::reference_wrapper<T>> il) :
|
||||
adaptor_range<derefs, std::vector<T *>>(derefs(), map(addresses(), il)) {
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
ref_vector(R &&r) : adaptor_range<derefs, std::vector<T *>>(
|
||||
derefs(), map(addresses(), std::forward<R>(r))) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
117
src/gallium/state_trackers/clover/util/tuple.hpp
Normal file
117
src/gallium/state_trackers/clover/util/tuple.hpp
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
//
|
||||
// Copyright 2013 Francisco Jerez
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
#ifndef CLOVER_UTIL_TUPLE_HPP
|
||||
#define CLOVER_UTIL_TUPLE_HPP
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace clover {
|
||||
namespace tuple {
|
||||
///
|
||||
/// Static sequence of integers.
|
||||
///
|
||||
template<int... Is>
|
||||
struct integral_sequence;
|
||||
|
||||
///
|
||||
/// Static sequence containing all integers from 0 to N-1.
|
||||
///
|
||||
template<int N, int... Is>
|
||||
struct enumerate {
|
||||
typedef typename enumerate<N-1, N-1, Is...>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template<int... Is>
|
||||
struct enumerate<0, Is...> {
|
||||
typedef integral_sequence<Is...> type;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename F, typename T,
|
||||
typename E = typename enumerate<std::tuple_size<
|
||||
typename std::remove_reference<T>::type>::value
|
||||
>::type>
|
||||
struct _apply;
|
||||
|
||||
template<typename F, typename T, int... Is>
|
||||
struct _apply<F, T, integral_sequence<Is...>> {
|
||||
typedef typename std::remove_reference<F>::type func_type;
|
||||
typedef decltype(
|
||||
std::declval<func_type>()(std::get<Is>(std::declval<T &&>())...)
|
||||
) value_type;
|
||||
|
||||
static value_type
|
||||
eval(F &&f, T &&t) {
|
||||
return f(std::get<Is>(std::forward<T>(t))...);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
///
|
||||
/// Evaluate function \a f with the elements of tuple \a t
|
||||
/// expanded as arguments.
|
||||
///
|
||||
template<typename F, typename T>
|
||||
typename detail::_apply<F, T>::value_type
|
||||
apply(F &&f, T &&t) {
|
||||
return detail::_apply<F, T>::eval(std::forward<F>(f),
|
||||
std::forward<T>(t));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template<typename F, typename T,
|
||||
typename E = typename enumerate<std::tuple_size<
|
||||
typename std::remove_reference<T>::type>::value
|
||||
>::type>
|
||||
struct _map;
|
||||
|
||||
template<typename F, typename T, int... Is>
|
||||
struct _map<F, T, integral_sequence<Is...>> {
|
||||
typedef typename std::remove_reference<F>::type func_type;
|
||||
typedef std::tuple<
|
||||
decltype(std::declval<func_type>()(
|
||||
std::get<Is>(std::declval<T &&>())))...
|
||||
> value_type;
|
||||
|
||||
static value_type
|
||||
eval(F &&f, T &&t) {
|
||||
return value_type(f(std::get<Is>(std::forward<T>(t)))...);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
///
|
||||
/// Evaluate function \a f on each element of the tuple \a t and
|
||||
/// return the resulting values as a new tuple.
|
||||
///
|
||||
template<typename F, typename T>
|
||||
typename detail::_map<F, T>::value_type
|
||||
map(F &&f, T &&t) {
|
||||
return detail::_map<F, T>::eval(std::forward<F>(f),
|
||||
std::forward<T>(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Reference in a new issue