build: migrate from ipp files to pure hpp files
ipp files weren't a great way of keeping things clean, and IDEs have a little trouble dealing with the split configuration. this simplifies debugging a great deal.
This commit is contained in:
parent
3b3f9cd3d3
commit
0e3fa05f05
@ -75,7 +75,6 @@ list (
|
|||||||
APPEND UTIL_FILES
|
APPEND UTIL_FILES
|
||||||
posix/dir.cpp
|
posix/dir.cpp
|
||||||
posix/dir.hpp
|
posix/dir.hpp
|
||||||
posix/dir.ipp
|
|
||||||
posix/except.cpp
|
posix/except.cpp
|
||||||
posix/except.hpp
|
posix/except.hpp
|
||||||
posix/fd.cpp
|
posix/fd.cpp
|
||||||
@ -97,7 +96,6 @@ if (NOT WINDOWS)
|
|||||||
debug_posix.cpp
|
debug_posix.cpp
|
||||||
io_posix.cpp
|
io_posix.cpp
|
||||||
io_posix.hpp
|
io_posix.hpp
|
||||||
io_posix.ipp
|
|
||||||
library_posix.hpp
|
library_posix.hpp
|
||||||
library_posix.cpp
|
library_posix.cpp
|
||||||
posix/fwd.hpp
|
posix/fwd.hpp
|
||||||
@ -116,7 +114,6 @@ if (WINDOWS)
|
|||||||
exe_win32.cpp
|
exe_win32.cpp
|
||||||
io_win32.cpp
|
io_win32.cpp
|
||||||
io_win32.hpp
|
io_win32.hpp
|
||||||
io_win32.ipp
|
|
||||||
library_win32.hpp
|
library_win32.hpp
|
||||||
library_win32.cpp
|
library_win32.cpp
|
||||||
time_win32.cpp
|
time_win32.cpp
|
||||||
@ -138,14 +135,11 @@ list (
|
|||||||
adapter.cpp
|
adapter.cpp
|
||||||
algo/sort.cpp
|
algo/sort.cpp
|
||||||
algo/sort.hpp
|
algo/sort.hpp
|
||||||
algo/sort.ipp
|
|
||||||
alloc/fwd.hpp
|
alloc/fwd.hpp
|
||||||
alloc/allocator.cpp
|
alloc/allocator.cpp
|
||||||
alloc/allocator.hpp
|
alloc/allocator.hpp
|
||||||
alloc/allocator.ipp
|
|
||||||
alloc/arena.cpp
|
alloc/arena.cpp
|
||||||
alloc/arena.hpp
|
alloc/arena.hpp
|
||||||
alloc/arena.ipp
|
|
||||||
alloc/raw/affix.cpp
|
alloc/raw/affix.cpp
|
||||||
alloc/raw/affix.hpp
|
alloc/raw/affix.hpp
|
||||||
alloc/raw/aligned.hpp
|
alloc/raw/aligned.hpp
|
||||||
@ -173,10 +167,8 @@ list (
|
|||||||
cast.hpp
|
cast.hpp
|
||||||
cmdopt.cpp
|
cmdopt.cpp
|
||||||
cmdopt.hpp
|
cmdopt.hpp
|
||||||
cmdopt.ipp
|
|
||||||
colour.cpp
|
colour.cpp
|
||||||
colour.hpp
|
colour.hpp
|
||||||
colour.ipp
|
|
||||||
coord/fwd.hpp
|
coord/fwd.hpp
|
||||||
coord/base.hpp
|
coord/base.hpp
|
||||||
coord.hpp
|
coord.hpp
|
||||||
@ -187,7 +179,6 @@ list (
|
|||||||
coord/traits.hpp
|
coord/traits.hpp
|
||||||
debug.cpp
|
debug.cpp
|
||||||
debug.hpp
|
debug.hpp
|
||||||
debug.ipp
|
|
||||||
encode/base.cpp
|
encode/base.cpp
|
||||||
encode/base.hpp
|
encode/base.hpp
|
||||||
endian.cpp
|
endian.cpp
|
||||||
@ -195,7 +186,6 @@ list (
|
|||||||
exe.hpp
|
exe.hpp
|
||||||
extent.cpp
|
extent.cpp
|
||||||
extent.hpp
|
extent.hpp
|
||||||
extent.ipp
|
|
||||||
fixed.cpp
|
fixed.cpp
|
||||||
fixed.hpp
|
fixed.hpp
|
||||||
float.cpp
|
float.cpp
|
||||||
@ -211,7 +201,6 @@ list (
|
|||||||
geom/cylinder.hpp
|
geom/cylinder.hpp
|
||||||
geom/ellipse.cpp
|
geom/ellipse.cpp
|
||||||
geom/ellipse.hpp
|
geom/ellipse.hpp
|
||||||
geom/ellipse.ipp
|
|
||||||
geom/iostream.cpp
|
geom/iostream.cpp
|
||||||
geom/iostream.hpp
|
geom/iostream.hpp
|
||||||
geom/ops.hpp
|
geom/ops.hpp
|
||||||
@ -258,7 +247,6 @@ list (
|
|||||||
introspection.hpp
|
introspection.hpp
|
||||||
io.cpp
|
io.cpp
|
||||||
io.hpp
|
io.hpp
|
||||||
io.ipp
|
|
||||||
iterator.hpp
|
iterator.hpp
|
||||||
job/queue.cpp
|
job/queue.cpp
|
||||||
job/queue.hpp
|
job/queue.hpp
|
||||||
@ -286,7 +274,6 @@ list (
|
|||||||
library.hpp
|
library.hpp
|
||||||
log.cpp
|
log.cpp
|
||||||
log.hpp
|
log.hpp
|
||||||
log.ipp
|
|
||||||
maths.cpp
|
maths.cpp
|
||||||
maths.hpp
|
maths.hpp
|
||||||
matrix.cpp
|
matrix.cpp
|
||||||
@ -304,18 +291,14 @@ list (
|
|||||||
platform.hpp
|
platform.hpp
|
||||||
point.cpp
|
point.cpp
|
||||||
point.hpp
|
point.hpp
|
||||||
point.ipp
|
|
||||||
pointer.hpp
|
pointer.hpp
|
||||||
polynomial.cpp
|
polynomial.cpp
|
||||||
polynomial.hpp
|
polynomial.hpp
|
||||||
polynomial.ipp
|
|
||||||
pool.cpp
|
pool.cpp
|
||||||
pool.hpp
|
pool.hpp
|
||||||
pool.ipp
|
|
||||||
preprocessor.hpp
|
preprocessor.hpp
|
||||||
quaternion.cpp
|
quaternion.cpp
|
||||||
quaternion.hpp
|
quaternion.hpp
|
||||||
quaternion.ipp
|
|
||||||
raii.hpp
|
raii.hpp
|
||||||
rand/lcg.cpp
|
rand/lcg.cpp
|
||||||
rand/lcg.hpp
|
rand/lcg.hpp
|
||||||
@ -327,20 +310,16 @@ list (
|
|||||||
random.hpp
|
random.hpp
|
||||||
range.cpp
|
range.cpp
|
||||||
range.hpp
|
range.hpp
|
||||||
range.ipp
|
|
||||||
rational.cpp
|
rational.cpp
|
||||||
rational.hpp
|
rational.hpp
|
||||||
rational.ipp
|
|
||||||
region.cpp
|
region.cpp
|
||||||
region.hpp
|
region.hpp
|
||||||
region.ipp
|
|
||||||
roots/bisection.hpp
|
roots/bisection.hpp
|
||||||
sarray.cpp
|
sarray.cpp
|
||||||
sarray.hpp
|
sarray.hpp
|
||||||
si.cpp
|
si.cpp
|
||||||
signal.cpp
|
signal.cpp
|
||||||
signal.hpp
|
signal.hpp
|
||||||
signal.ipp
|
|
||||||
si.hpp
|
si.hpp
|
||||||
stats.cpp
|
stats.cpp
|
||||||
stats.hpp
|
stats.hpp
|
||||||
@ -378,7 +357,6 @@ list (
|
|||||||
variadic.hpp
|
variadic.hpp
|
||||||
vector.cpp
|
vector.cpp
|
||||||
vector.hpp
|
vector.hpp
|
||||||
vector.ipp
|
|
||||||
version.cpp
|
version.cpp
|
||||||
version.hpp
|
version.hpp
|
||||||
view.cpp
|
view.cpp
|
||||||
|
116
algo/sort.hpp
116
algo/sort.hpp
@ -18,7 +18,39 @@
|
|||||||
#ifndef CRUFT_UTIL_ALGO_SORT_HPP
|
#ifndef CRUFT_UTIL_ALGO_SORT_HPP
|
||||||
#define CRUFT_UTIL_ALGO_SORT_HPP
|
#define CRUFT_UTIL_ALGO_SORT_HPP
|
||||||
|
|
||||||
|
#include "../debug.hpp"
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <numeric>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
namespace cruft::util::sort {
|
namespace cruft::util::sort {
|
||||||
|
namespace detail {
|
||||||
|
template <typename IndexA, typename IndexB, typename RandomIt>
|
||||||
|
void
|
||||||
|
index_swap (IndexA a, IndexB b, RandomIt value)
|
||||||
|
{
|
||||||
|
static_assert(
|
||||||
|
std::is_base_of<
|
||||||
|
std::random_access_iterator_tag,
|
||||||
|
typename std::iterator_traits<RandomIt>::iterator_category
|
||||||
|
>::value
|
||||||
|
);
|
||||||
|
|
||||||
|
std::swap (value[a], value[b]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename IndexA, typename IndexB, typename RandomIt, typename ...Tail>
|
||||||
|
void
|
||||||
|
index_swap (IndexA a, IndexB b, RandomIt value, Tail ...tail)
|
||||||
|
{
|
||||||
|
index_swap (a, b, value);
|
||||||
|
index_swap (a, b, tail...);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// rearrange the values in the arrays specified by the iterators value and
|
// rearrange the values in the arrays specified by the iterators value and
|
||||||
// ...tail by moving values to the positions described by the mapping of
|
// ...tail by moving values to the positions described by the mapping of
|
||||||
@ -31,7 +63,38 @@ namespace cruft::util::sort {
|
|||||||
// the operation.
|
// the operation.
|
||||||
template <typename IndexIt, typename ValueIt, typename ...OtherIt>
|
template <typename IndexIt, typename ValueIt, typename ...OtherIt>
|
||||||
void
|
void
|
||||||
reorder (IndexIt idx_first, IndexIt idx_last, ValueIt value, OtherIt ...tail);
|
reorder (IndexIt idx_first, IndexIt idx_last, ValueIt value, OtherIt ...tail)
|
||||||
|
{
|
||||||
|
static_assert (
|
||||||
|
std::is_base_of<
|
||||||
|
std::random_access_iterator_tag,
|
||||||
|
typename std::iterator_traits<IndexIt>::iterator_category
|
||||||
|
>::value
|
||||||
|
);
|
||||||
|
|
||||||
|
static_assert (
|
||||||
|
std::is_base_of<
|
||||||
|
std::random_access_iterator_tag,
|
||||||
|
typename std::iterator_traits<ValueIt>::iterator_category
|
||||||
|
>::value
|
||||||
|
);
|
||||||
|
|
||||||
|
// Bail early on zero size arrays, partly so we can simplify some
|
||||||
|
// debugging checks
|
||||||
|
auto size = std::distance (idx_first, idx_last);
|
||||||
|
if (!size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CHECK_LT (*std::max_element (idx_first, idx_last), size);
|
||||||
|
|
||||||
|
for (decltype(size) i = 0; i < size - 1; ++i) {
|
||||||
|
while (i != (decltype(size))idx_first[i]) {
|
||||||
|
auto j = idx_first[i];
|
||||||
|
|
||||||
|
detail::index_swap (i, j, value, tail..., idx_first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// sort an array specified by the iterators key_first:key_last using a
|
// sort an array specified by the iterators key_first:key_last using a
|
||||||
@ -41,9 +104,54 @@ namespace cruft::util::sort {
|
|||||||
// sorting is performed in-place and will invariably allocate memory.
|
// sorting is performed in-place and will invariably allocate memory.
|
||||||
template <typename RandomIt, class Comparator, class ...Args>
|
template <typename RandomIt, class Comparator, class ...Args>
|
||||||
void
|
void
|
||||||
soa (RandomIt key_first, RandomIt key_last, Comparator comp, Args ...values);
|
soa (RandomIt key_first, RandomIt key_last, Comparator comp, Args ...values)
|
||||||
|
{
|
||||||
|
static_assert (
|
||||||
|
std::is_base_of<
|
||||||
|
std::random_access_iterator_tag,
|
||||||
|
typename std::iterator_traits<RandomIt>::iterator_category
|
||||||
|
>::value
|
||||||
|
);
|
||||||
|
|
||||||
|
// bail early on guaranteed sorted or degenerate cases. we can make some
|
||||||
|
// assumptions about minimum array sizes and non-wrapping indices later on
|
||||||
|
// this way.
|
||||||
|
if (std::distance (key_first, key_last) <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// generate a list of indices into the key array and sort them so we have,
|
||||||
|
// in effect, a sorted list of pointers.
|
||||||
|
auto size = std::distance (key_first, key_last);
|
||||||
|
std::vector<decltype(size)> indices (size);
|
||||||
|
std::iota (std::begin (indices), std::end (indices), 0);
|
||||||
|
|
||||||
|
std::sort (std::begin (indices),
|
||||||
|
std::end (indices),
|
||||||
|
[&] (const auto &cruft_util_sort_soa_a, const auto &cruft_util_sort_soa_b)
|
||||||
|
{
|
||||||
|
// GCC: we use the ridiculous parameter names to avoid a name aliasing
|
||||||
|
// bug/warning under gcc 6.3.0; if the client passes a comparator
|
||||||
|
// lambda that uses the same parameter names then a warning will be
|
||||||
|
// generated. given 'a' and 'b' aren't unlikely names we try to avoid
|
||||||
|
// them here.
|
||||||
|
return comp (
|
||||||
|
key_first[cruft_util_sort_soa_a],
|
||||||
|
key_first[cruft_util_sort_soa_b]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// convert from a sorted list of pointers to a mapping of pointers to
|
||||||
|
// desired final offsets. this is done so we can palm it off to the
|
||||||
|
// reorder function.
|
||||||
|
// TODO: avoid the need for this inverse array.
|
||||||
|
decltype (indices) dest (indices.size ());
|
||||||
|
for (decltype(size) i = 0; i < (decltype(size))dest.size (); ++i) {
|
||||||
|
dest[indices[i]] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reorder all the arrays using the mapping we have discovered.
|
||||||
|
reorder (std::begin (dest), std::end (dest), key_first, values...);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "sort.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
155
algo/sort.ipp
155
algo/sort.ipp
@ -1,155 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright:
|
|
||||||
* 2017, Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef CRUFT_UTIL_ALGO_SORT_IPP
|
|
||||||
#error
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CRUFT_UTIL_ALGO_SORT_IPP
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <array>
|
|
||||||
#include <iterator>
|
|
||||||
#include <numeric>
|
|
||||||
#include <vector>
|
|
||||||
#include <iterator>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
#include "../debug.hpp"
|
|
||||||
#include "../tuple.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
namespace cruft::util::sort::detail {
|
|
||||||
template <typename IndexA, typename IndexB, typename RandomIt>
|
|
||||||
void
|
|
||||||
index_swap (IndexA a, IndexB b, RandomIt value)
|
|
||||||
{
|
|
||||||
static_assert(
|
|
||||||
std::is_base_of<
|
|
||||||
std::random_access_iterator_tag,
|
|
||||||
typename std::iterator_traits<RandomIt>::iterator_category
|
|
||||||
>::value
|
|
||||||
);
|
|
||||||
|
|
||||||
std::swap (value[a], value[b]);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename IndexA, typename IndexB, typename RandomIt, typename ...Tail>
|
|
||||||
void
|
|
||||||
index_swap (IndexA a, IndexB b, RandomIt value, Tail ...tail)
|
|
||||||
{
|
|
||||||
index_swap (a, b, value);
|
|
||||||
index_swap (a, b, tail...);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename IndexIt, typename ValueIt, typename ...OtherIt>
|
|
||||||
void
|
|
||||||
cruft::util::sort::reorder (IndexIt idx_first,
|
|
||||||
IndexIt idx_last,
|
|
||||||
ValueIt value,
|
|
||||||
OtherIt ...tail)
|
|
||||||
{
|
|
||||||
static_assert (
|
|
||||||
std::is_base_of<
|
|
||||||
std::random_access_iterator_tag,
|
|
||||||
typename std::iterator_traits<IndexIt>::iterator_category
|
|
||||||
>::value
|
|
||||||
);
|
|
||||||
|
|
||||||
static_assert (
|
|
||||||
std::is_base_of<
|
|
||||||
std::random_access_iterator_tag,
|
|
||||||
typename std::iterator_traits<ValueIt>::iterator_category
|
|
||||||
>::value
|
|
||||||
);
|
|
||||||
|
|
||||||
// Bail early on zero size arrays, partly so we can simplify some
|
|
||||||
// debugging checks
|
|
||||||
auto size = std::distance (idx_first, idx_last);
|
|
||||||
if (!size)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CHECK_LT (*std::max_element (idx_first, idx_last), size);
|
|
||||||
|
|
||||||
for (decltype(size) i = 0; i < size - 1; ++i) {
|
|
||||||
while (i != (decltype(size))idx_first[i]) {
|
|
||||||
auto j = idx_first[i];
|
|
||||||
|
|
||||||
detail::index_swap (i, j, value, tail..., idx_first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename RandomIt, class Comparator, class ...Args>
|
|
||||||
void
|
|
||||||
cruft::util::sort::soa (RandomIt key_first,
|
|
||||||
RandomIt key_last,
|
|
||||||
Comparator comp,
|
|
||||||
Args ...values)
|
|
||||||
{
|
|
||||||
static_assert (
|
|
||||||
std::is_base_of<
|
|
||||||
std::random_access_iterator_tag,
|
|
||||||
typename std::iterator_traits<RandomIt>::iterator_category
|
|
||||||
>::value
|
|
||||||
);
|
|
||||||
|
|
||||||
// bail early on guaranteed sorted or degenerate cases. we can make some
|
|
||||||
// assumptions about minimum array sizes and non-wrapping indices later on
|
|
||||||
// this way.
|
|
||||||
if (std::distance (key_first, key_last) <= 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// generate a list of indices into the key array and sort them so we have,
|
|
||||||
// in effect, a sorted list of pointers.
|
|
||||||
auto size = std::distance (key_first, key_last);
|
|
||||||
std::vector<decltype(size)> indices (size);
|
|
||||||
std::iota (std::begin (indices), std::end (indices), 0);
|
|
||||||
|
|
||||||
std::sort (std::begin (indices),
|
|
||||||
std::end (indices),
|
|
||||||
[&] (const auto &cruft_util_sort_soa_a, const auto &cruft_util_sort_soa_b)
|
|
||||||
{
|
|
||||||
// GCC: we use the ridiculous parameter names to avoid a name aliasing
|
|
||||||
// bug/warning under gcc 6.3.0; if the client passes a comparator
|
|
||||||
// lambda that uses the same parameter names then a warning will be
|
|
||||||
// generated. given 'a' and 'b' aren't unlikely names we try to avoid
|
|
||||||
// them here.
|
|
||||||
return comp (
|
|
||||||
key_first[cruft_util_sort_soa_a],
|
|
||||||
key_first[cruft_util_sort_soa_b]
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// convert from a sorted list of pointers to a mapping of pointers to
|
|
||||||
// desired final offsets. this is done so we can palm it off to the
|
|
||||||
// reorder function.
|
|
||||||
// TODO: avoid the need for this inverse array.
|
|
||||||
decltype (indices) dest (indices.size ());
|
|
||||||
for (decltype(size) i = 0; i < (decltype(size))dest.size (); ++i) {
|
|
||||||
dest[indices[i]] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
// reorder all the arrays using the mapping we have discovered.
|
|
||||||
reorder (std::begin (dest), std::end (dest), key_first, values...);
|
|
||||||
};
|
|
@ -18,26 +18,38 @@
|
|||||||
#define __UTIL_ALLOC_ALLOCATOR_HPP
|
#define __UTIL_ALLOC_ALLOCATOR_HPP
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
// C++11 allocator concept conformant allocator adaptor, going from our
|
// C++11 allocator concept conformant allocator adaptor, going from our
|
||||||
// allocator interface to that of the STL and friends.
|
// allocator interface to that of the STL and friends.
|
||||||
namespace util::alloc {
|
namespace util::alloc {
|
||||||
template <class B, class T>
|
template <class BackingT, class ValueT>
|
||||||
class allocator {
|
class allocator {
|
||||||
public:
|
public:
|
||||||
typedef T value_type;
|
typedef ValueT value_type;
|
||||||
|
|
||||||
template <typename ...Args>
|
template <typename ...Args>
|
||||||
explicit allocator (Args&& ...args);
|
explicit allocator (Args&& ...args):
|
||||||
|
m_backing (std::forward (args)...)
|
||||||
|
{ ; }
|
||||||
|
|
||||||
|
|
||||||
|
ValueT* allocate (size_t count)
|
||||||
|
{
|
||||||
|
return m_backing.template allocate<ValueT> (count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
deallocate (ValueT *t, size_t count)
|
||||||
|
{
|
||||||
|
return m_backing.template deallocate (t, count);
|
||||||
|
}
|
||||||
|
|
||||||
T* allocate (size_t count);
|
|
||||||
void deallocate (T*, size_t count);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
B &m_backing;
|
BackingT &m_backing;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "allocator.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __UTIL_ALLOC_ALLOCATOR_IPP
|
|
||||||
#error
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define __UTIL_ALLOC_ALLOCATOR_IPP
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <class B, class T>
|
|
||||||
template <typename ...Args>
|
|
||||||
util::alloc::allocator<B,T>::allocator (Args&& ...args):
|
|
||||||
m_backing (std::forward (args)...)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <class B, class T>
|
|
||||||
T*
|
|
||||||
util::alloc::allocator<B,T>::allocate (std::size_t count)
|
|
||||||
{
|
|
||||||
return m_backing.template allocate<T> (count);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <class B, class T>
|
|
||||||
void
|
|
||||||
util::alloc::allocator<B,T>::deallocate (T *t, std::size_t count)
|
|
||||||
{
|
|
||||||
return m_backing.template deallocate (t, count);
|
|
||||||
}
|
|
@ -28,17 +28,38 @@ namespace util::alloc {
|
|||||||
template <class T>
|
template <class T>
|
||||||
class arena {
|
class arena {
|
||||||
public:
|
public:
|
||||||
explicit arena (T &store);
|
explicit arena (T &store):
|
||||||
|
m_store (store)
|
||||||
|
{ ; }
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
template <typename U, typename ...Args>
|
template <typename U, typename ...Args>
|
||||||
U*
|
U*
|
||||||
acquire (Args&&...);
|
acquire (Args&&... args)
|
||||||
|
{
|
||||||
|
U *data = reinterpret_cast<U*> (
|
||||||
|
m_store.allocate (sizeof (U), alignof (U))
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
new (data) U (std::forward<Args> (args)...);
|
||||||
|
} catch (...) {
|
||||||
|
m_store.deallocate (data, sizeof (U));
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
template <typename U>
|
template <typename U>
|
||||||
void
|
void
|
||||||
release (U*);
|
release (U *u)
|
||||||
|
{
|
||||||
|
u->~U ();
|
||||||
|
m_store.deallocate (reinterpret_cast<void*> (u), sizeof (U));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
template <typename U>
|
template <typename U>
|
||||||
@ -68,6 +89,4 @@ namespace util::alloc {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "arena.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __UTIL_ALLOC_ARENA_IPP
|
|
||||||
#error
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define __UTIL_ALLOC_ARENA_IPP
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <class T>
|
|
||||||
util::alloc::arena<T>::arena (T &store):
|
|
||||||
m_store (store)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <class T>
|
|
||||||
template <typename U, typename ...Args>
|
|
||||||
U*
|
|
||||||
util::alloc::arena<T>::acquire (Args&& ...args)
|
|
||||||
{
|
|
||||||
U *data = reinterpret_cast<U*> (
|
|
||||||
m_store.allocate (sizeof (U), alignof (U))
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
new (data) U (std::forward<Args> (args)...);
|
|
||||||
} catch (...) {
|
|
||||||
m_store.deallocate (data, sizeof (U));
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <class T>
|
|
||||||
template <typename U>
|
|
||||||
void
|
|
||||||
util::alloc::arena<T>::release (U *u)
|
|
||||||
{
|
|
||||||
u->~U ();
|
|
||||||
m_store.deallocate (reinterpret_cast<void*> (u), sizeof (U));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
243
cmdopt.hpp
243
cmdopt.hpp
@ -15,19 +15,72 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __UTIL_CMDLINE_HPP
|
#ifndef CRUFT_UTIL_CMDLINE_HPP
|
||||||
#define __UTIL_CMDLINE_HPP
|
#define CRUFT_UTIL_CMDLINE_HPP
|
||||||
|
|
||||||
|
#include "introspection.hpp"
|
||||||
|
#include "iterator.hpp"
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <exception>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
namespace util::cmdopt {
|
namespace util::cmdopt {
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
class error : public std::exception { };
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
class invalid_key : public error {
|
||||||
|
public:
|
||||||
|
explicit invalid_key (std::string _key);
|
||||||
|
const char* what (void) const noexcept override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string m_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
class invalid_value : public error {
|
||||||
|
public:
|
||||||
|
explicit invalid_value (std::string _value);
|
||||||
|
const char* what (void) const noexcept override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string m_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
class invalid_null : public error {
|
||||||
|
public:
|
||||||
|
const char* what (void) const noexcept override;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
class invalid_required : public error {
|
||||||
|
public:
|
||||||
|
const char* what (void) const noexcept override;
|
||||||
|
};
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
class unhandled_argument : public error {
|
||||||
|
public:
|
||||||
|
explicit unhandled_argument (int index);
|
||||||
|
const char* what (void) const noexcept override;
|
||||||
|
|
||||||
|
int index (void) const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int m_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
namespace option {
|
namespace option {
|
||||||
class base {
|
class base {
|
||||||
public:
|
public:
|
||||||
@ -84,25 +137,125 @@ namespace util::cmdopt {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template <typename T>
|
||||||
|
std::enable_if_t<!std::is_enum<T>::value, const std::string&>
|
||||||
|
value_example (void)
|
||||||
|
{
|
||||||
|
static const std::string EXAMPLE =
|
||||||
|
std::string {"<"} +
|
||||||
|
std::string {to_string<T> ()} +
|
||||||
|
std::string {">"};
|
||||||
|
|
||||||
|
return EXAMPLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::enable_if_t<std::is_enum<T>::value, const std::string&>
|
||||||
|
value_example (void)
|
||||||
|
{
|
||||||
|
static const std::string EXAMPLE = [] (void) {
|
||||||
|
std::ostringstream os;
|
||||||
|
std::copy (std::cbegin (enum_traits<T>::names),
|
||||||
|
std::cend (enum_traits<T>::names),
|
||||||
|
infix_iterator<const char*> (os, "|"));
|
||||||
|
return os.str ();
|
||||||
|
} ();
|
||||||
|
return EXAMPLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class value : public base {
|
class value : public base {
|
||||||
public:
|
public:
|
||||||
explicit value (T&);
|
explicit value (T &_data): m_data (_data) { }
|
||||||
explicit value (T&&) = delete;
|
explicit value (T&&) = delete;
|
||||||
|
|
||||||
using base::execute;
|
using base::execute;
|
||||||
void execute (const char *restrict) override;
|
|
||||||
|
|
||||||
const std::string& example (void) const override;
|
void execute (const char *restrict str) override
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
std::istringstream is (str);
|
||||||
|
is.exceptions (
|
||||||
|
std::istringstream::failbit
|
||||||
|
| std::istringstream::badbit
|
||||||
|
);
|
||||||
|
|
||||||
const T& data (void) const&;
|
is >> m_data;
|
||||||
T& data (void) &;
|
} catch (...) {
|
||||||
T& data (T) &;
|
throw invalid_value (__func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
seen (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& example (void) const override
|
||||||
|
{
|
||||||
|
return detail::value_example<T> ();
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& data (void) const&
|
||||||
|
{
|
||||||
|
return m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
T& data (void) &
|
||||||
|
{
|
||||||
|
return m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
T& data (T _data) &
|
||||||
|
{
|
||||||
|
return m_data = _data;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T& m_data;
|
T& m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline void
|
||||||
|
value<bool>::execute (const char *restrict str)
|
||||||
|
{
|
||||||
|
static const std::string TRUE_STRING[] = {
|
||||||
|
"true",
|
||||||
|
"yes",
|
||||||
|
"y",
|
||||||
|
"1"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (std::any_of (std::begin (TRUE_STRING),
|
||||||
|
std::end (TRUE_STRING),
|
||||||
|
[str] (auto i) { return i == str; }))
|
||||||
|
{
|
||||||
|
m_data = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const std::string FALSE_STRING[] = {
|
||||||
|
"false",
|
||||||
|
"no",
|
||||||
|
"n",
|
||||||
|
"0"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (std::any_of (std::begin (FALSE_STRING),
|
||||||
|
std::end (FALSE_STRING),
|
||||||
|
[str] (auto i) { return i == str; }))
|
||||||
|
{
|
||||||
|
m_data = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base::execute (str);
|
||||||
|
seen (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T = unsigned>
|
template <typename T = unsigned>
|
||||||
class count : public value<T> {
|
class count : public value<T> {
|
||||||
@ -132,11 +285,29 @@ namespace util::cmdopt {
|
|||||||
T& add (char shortname,
|
T& add (char shortname,
|
||||||
std::string longname,
|
std::string longname,
|
||||||
std::string description,
|
std::string description,
|
||||||
Args&&...);
|
Args&&... args)
|
||||||
|
{
|
||||||
|
auto handler = std::make_unique<T> (std::forward<Args> (args)...);
|
||||||
|
T& ref = *handler;
|
||||||
|
|
||||||
|
m_short.emplace_back (shortname, ref);
|
||||||
|
m_long .emplace_back (std::move (longname), ref);
|
||||||
|
|
||||||
|
m_options.emplace_back (std::move (description), std::move (handler));
|
||||||
|
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, typename ...Args>
|
template <typename T, typename ...Args>
|
||||||
T&
|
T&
|
||||||
append (std::string description, Args&&...);
|
append (std::string description, Args&&...args)
|
||||||
|
{
|
||||||
|
auto handler = std::make_unique<T> (std::forward<Args> (args)...);
|
||||||
|
auto &ref = *handler;
|
||||||
|
m_positional.push_back (ref);
|
||||||
|
m_options.emplace_back (std::move (description), std::move (handler));
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
int scan (int argc, const char *const *argv);
|
int scan (int argc, const char *const *argv);
|
||||||
|
|
||||||
@ -160,56 +331,6 @@ namespace util::cmdopt {
|
|||||||
>
|
>
|
||||||
> m_options;
|
> m_options;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
class error : public std::exception { };
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
class invalid_key : public error {
|
|
||||||
public:
|
|
||||||
explicit invalid_key (std::string _key);
|
|
||||||
const char* what (void) const noexcept override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::string m_key;
|
|
||||||
};
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
class invalid_value : public error {
|
|
||||||
public:
|
|
||||||
explicit invalid_value (std::string _value);
|
|
||||||
const char* what (void) const noexcept override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const std::string m_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
class invalid_null : public error {
|
|
||||||
public:
|
|
||||||
const char* what (void) const noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
class invalid_required : public error {
|
|
||||||
public:
|
|
||||||
const char* what (void) const noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
class unhandled_argument : public error {
|
|
||||||
public:
|
|
||||||
explicit unhandled_argument (int index);
|
|
||||||
const char* what (void) const noexcept override;
|
|
||||||
|
|
||||||
int index (void) const noexcept;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const int m_index;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "cmdopt.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
198
cmdopt.ipp
198
cmdopt.ipp
@ -1,198 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2013-2016 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __UTIL_CMDLINE_IPP
|
|
||||||
#error
|
|
||||||
#endif
|
|
||||||
#define __UTIL_CMDLINE_IPP
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iterator>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include "introspection.hpp"
|
|
||||||
#include "iterator.hpp"
|
|
||||||
|
|
||||||
namespace util::cmdopt {
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T>
|
|
||||||
option::value<T>::value (T &_data):
|
|
||||||
m_data (_data)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
inline void
|
|
||||||
option::value<T>::execute (const char *restrict str)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
std::istringstream is (str);
|
|
||||||
is.exceptions (
|
|
||||||
std::istringstream::failbit
|
|
||||||
| std::istringstream::badbit
|
|
||||||
);
|
|
||||||
|
|
||||||
is >> m_data;
|
|
||||||
} catch (...) {
|
|
||||||
throw invalid_value (__func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
seen (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
namespace option {
|
|
||||||
template <>
|
|
||||||
inline void
|
|
||||||
value<bool>::execute (const char *restrict str)
|
|
||||||
{
|
|
||||||
static const std::string TRUE_STRING[] = {
|
|
||||||
"true",
|
|
||||||
"yes",
|
|
||||||
"y",
|
|
||||||
"1"
|
|
||||||
};
|
|
||||||
|
|
||||||
if (std::any_of (std::begin (TRUE_STRING),
|
|
||||||
std::end (TRUE_STRING),
|
|
||||||
[str] (auto i) { return i == str; }))
|
|
||||||
{
|
|
||||||
m_data = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const std::string FALSE_STRING[] = {
|
|
||||||
"false",
|
|
||||||
"no",
|
|
||||||
"n",
|
|
||||||
"0"
|
|
||||||
};
|
|
||||||
|
|
||||||
if (std::any_of (std::begin (FALSE_STRING),
|
|
||||||
std::end (FALSE_STRING),
|
|
||||||
[str] (auto i) { return i == str; }))
|
|
||||||
{
|
|
||||||
m_data = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
base::execute (str);
|
|
||||||
seen (true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
namespace detail {
|
|
||||||
template <typename T>
|
|
||||||
std::enable_if_t<!std::is_enum<T>::value, const std::string&>
|
|
||||||
value_example (void)
|
|
||||||
{
|
|
||||||
static const std::string EXAMPLE =
|
|
||||||
std::string {"<"} +
|
|
||||||
std::string {to_string<T> ()} +
|
|
||||||
std::string {">"};
|
|
||||||
|
|
||||||
return EXAMPLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
std::enable_if_t<std::is_enum<T>::value, const std::string&>
|
|
||||||
value_example (void)
|
|
||||||
{
|
|
||||||
static const std::string EXAMPLE = [] (void) {
|
|
||||||
std::ostringstream os;
|
|
||||||
std::copy (std::cbegin (enum_traits<T>::names),
|
|
||||||
std::cend (enum_traits<T>::names),
|
|
||||||
infix_iterator<const char*> (os, "|"));
|
|
||||||
return os.str ();
|
|
||||||
} ();
|
|
||||||
return EXAMPLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
const std::string&
|
|
||||||
option::value<T>::example (void) const
|
|
||||||
{
|
|
||||||
return detail::value_example<T> ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
const T&
|
|
||||||
option::value<T>::data (void) const&
|
|
||||||
{
|
|
||||||
return m_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
T&
|
|
||||||
option::value<T>::data (void) &
|
|
||||||
{
|
|
||||||
return m_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
T&
|
|
||||||
option::value<T>::data (T _data) &
|
|
||||||
{
|
|
||||||
return m_data = _data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T, typename ...Args>
|
|
||||||
T&
|
|
||||||
parser::add (char shortname,
|
|
||||||
std::string longname,
|
|
||||||
std::string description,
|
|
||||||
Args&&... args)
|
|
||||||
{
|
|
||||||
auto handler = std::make_unique<T> (std::forward<Args> (args)...);
|
|
||||||
T& ref = *handler;
|
|
||||||
|
|
||||||
m_short.emplace_back (shortname, ref);
|
|
||||||
m_long .emplace_back (std::move (longname), ref);
|
|
||||||
|
|
||||||
m_options.emplace_back (std::move (description), std::move (handler));
|
|
||||||
|
|
||||||
return ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T, typename ...Args>
|
|
||||||
T&
|
|
||||||
parser::append (std::string description,
|
|
||||||
Args &&...args)
|
|
||||||
{
|
|
||||||
auto handler = std::make_unique<T> (std::forward<Args> (args)...);
|
|
||||||
auto &ref = *handler;
|
|
||||||
m_positional.push_back (ref);
|
|
||||||
m_options.emplace_back (std::move (description), std::move (handler));
|
|
||||||
return ref;
|
|
||||||
}
|
|
||||||
}
|
|
@ -115,6 +115,4 @@ namespace util {
|
|||||||
constexpr auto is_colour_v = is_colour<T>::value;
|
constexpr auto is_colour_v = is_colour<T>::value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "colour.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
21
colour.ipp
21
colour.ipp
@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2010-2015 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __UTIL_COLOUR_IPP
|
|
||||||
#error
|
|
||||||
#endif
|
|
||||||
#define __UTIL_COLOUR_IPP
|
|
||||||
|
|
97
debug.hpp
97
debug.hpp
@ -371,25 +371,101 @@ namespace util::debug {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void breakpoint (void);
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
constexpr void panic [[noreturn]] (const char*);
|
#include "log.hpp"
|
||||||
|
#include "backtrace.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace util::debug::detail {
|
||||||
|
void panic [[noreturn]] (const char *msg);
|
||||||
|
|
||||||
|
template <typename ...Args, size_t N>
|
||||||
|
void panic [[noreturn]] (const char (&fmt)[N], const Args& ...args)
|
||||||
|
{
|
||||||
|
LOG_EMERGENCY (fmt, args...);
|
||||||
|
LOG_EMERGENCY ("%!", ::debug::backtrace ());
|
||||||
|
breakpoint ();
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void not_implemented [[noreturn]] (const char *msg);
|
||||||
|
void unreachable [[noreturn]] (const char *msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
constexpr void
|
||||||
|
panic [[noreturn]] (const char *msg)
|
||||||
|
{
|
||||||
|
! msg
|
||||||
|
? panic (msg)
|
||||||
|
: util::debug::detail::panic (msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename ...Args, size_t N>
|
template <typename ...Args, size_t N>
|
||||||
constexpr
|
constexpr void
|
||||||
void panic [[noreturn]] (const char (&fmt)[N], const Args&...);
|
panic [[noreturn]] (const char (&fmt)[N], const Args&... args)
|
||||||
|
{
|
||||||
|
util::debug::detail::panic (fmt, args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
constexpr void not_implemented [[noreturn]] (void);
|
// not_implemented/unreachable/panic must be callable from constexpr contexts.
|
||||||
constexpr void not_implemented [[noreturn]] (const char *msg);
|
// but they rely on functions that aren't constexpr to perform the controlled
|
||||||
|
// abort.
|
||||||
|
//
|
||||||
|
// we can work around this in the same way assert does by using a conditional
|
||||||
|
// that hides an extern function that actually does the work. as we can't
|
||||||
|
// utilise external state this has to be the message variable which will
|
||||||
|
// assume isn't ever null.
|
||||||
|
//
|
||||||
|
// to avoid warnings about a return from a noreturn function we recurse into
|
||||||
|
// ourself in the alternate case. this branch shouldn't ever be taken, but if
|
||||||
|
// it is we were planning on crashing anyway...
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
constexpr void
|
||||||
|
not_implemented [[noreturn]] (const char *msg)
|
||||||
|
{
|
||||||
|
! msg
|
||||||
|
? not_implemented (msg)
|
||||||
|
: util::debug::detail::not_implemented (msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
constexpr void
|
||||||
|
not_implemented [[noreturn]] (void)
|
||||||
|
{
|
||||||
|
not_implemented ("operation not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
constexpr void unimplemented [[noreturn]] (void) { not_implemented (); }
|
constexpr void unimplemented [[noreturn]] (void) { not_implemented (); }
|
||||||
|
|
||||||
|
|
||||||
constexpr void unimplemented [[noreturn]] (const char *msg) { not_implemented (msg); }
|
constexpr void unimplemented [[noreturn]] (const char *msg) { not_implemented (msg); }
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
constexpr void unreachable [[noreturn]] (void);
|
constexpr void
|
||||||
constexpr void unreachable [[noreturn]] (const char*);
|
unreachable [[noreturn]] (const char *msg)
|
||||||
|
{
|
||||||
|
! msg
|
||||||
|
? unreachable (msg)
|
||||||
|
: util::debug::detail::unreachable (msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
constexpr void
|
||||||
|
unreachable [[noreturn]] (void)
|
||||||
|
{
|
||||||
|
unreachable ("unreachable code executed");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -410,8 +486,6 @@ void warn (const char *);
|
|||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
void breakpoint (void);
|
|
||||||
|
|
||||||
void await_debugger (void);
|
void await_debugger (void);
|
||||||
void prepare_debugger (void);
|
void prepare_debugger (void);
|
||||||
|
|
||||||
@ -514,11 +588,6 @@ namespace util::debug {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "debug.ipp"
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// XXX: maths needs to be included so that CHECK_EQ/NEQ can call almost_equal,
|
// XXX: maths needs to be included so that CHECK_EQ/NEQ can call almost_equal,
|
||||||
// but maths.hpp might be using CHECK_ macros so we must include maths.hpp
|
// but maths.hpp might be using CHECK_ macros so we must include maths.hpp
|
||||||
|
108
debug.ipp
108
debug.ipp
@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2015-2018, Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __UTIL_DEBUG_IPP
|
|
||||||
#error
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define __UTIL_DEBUG_IPP
|
|
||||||
|
|
||||||
#include "backtrace.hpp"
|
|
||||||
#include "format.hpp"
|
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
namespace util::debug::detail {
|
|
||||||
void panic [[noreturn]] (const char *msg);
|
|
||||||
|
|
||||||
template <typename ...Args, size_t N>
|
|
||||||
void panic [[noreturn]] (const char (&fmt)[N], const Args& ...args)
|
|
||||||
{
|
|
||||||
std::cerr << ::util::format::printf (fmt, args...) << ::debug::backtrace () << std::endl;
|
|
||||||
breakpoint ();
|
|
||||||
abort ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void not_implemented [[noreturn]] (const char *msg);
|
|
||||||
void unreachable [[noreturn]] (const char *msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// not_implemented/unreachable/panic must be callable from constexpr contexts.
|
|
||||||
// but they rely on functions that aren't constexpr to perform the controlled
|
|
||||||
// abort.
|
|
||||||
//
|
|
||||||
// we can work around this in the same way assert does by using a conditional
|
|
||||||
// that hides an extern function that actually does the work. as we can't
|
|
||||||
// utilise external state this has to be the message variable which will
|
|
||||||
// assume isn't ever null.
|
|
||||||
//
|
|
||||||
// to avoid warnings about a return from a noreturn function we recurse into
|
|
||||||
// ourself in the alternate case. this branch shouldn't ever be taken, but if
|
|
||||||
// it is we were planning on crashing anyway...
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
constexpr void not_implemented [[noreturn]] (void)
|
|
||||||
{
|
|
||||||
not_implemented ("operation not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
constexpr void not_implemented [[noreturn]] (const char *msg)
|
|
||||||
{
|
|
||||||
! msg
|
|
||||||
? not_implemented (msg)
|
|
||||||
: util::debug::detail::not_implemented (msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
constexpr void unreachable [[noreturn]] (void)
|
|
||||||
{
|
|
||||||
unreachable ("unreachable code executed");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
constexpr void unreachable [[noreturn]] (const char *msg)
|
|
||||||
{
|
|
||||||
! msg
|
|
||||||
? unreachable (msg)
|
|
||||||
: util::debug::detail::unreachable (msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
constexpr void panic [[noreturn]] (const char *msg)
|
|
||||||
{
|
|
||||||
! msg
|
|
||||||
? panic (msg)
|
|
||||||
: util::debug::detail::panic (msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename ...Args, size_t N>
|
|
||||||
constexpr
|
|
||||||
void
|
|
||||||
panic [[noreturn]] (const char (&fmt)[N], const Args& ...args)
|
|
||||||
{
|
|
||||||
util::debug::detail::panic (fmt, args...);
|
|
||||||
}
|
|
50
extent.hpp
50
extent.hpp
@ -14,8 +14,8 @@
|
|||||||
* Copyright 2010-2017 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2010-2017 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_EXTENT_HPP
|
#ifndef CRUFT_UTIL_EXTENT_HPP
|
||||||
#define __UTIL_EXTENT_HPP
|
#define CRUFT_UTIL_EXTENT_HPP
|
||||||
|
|
||||||
#include "coord/fwd.hpp"
|
#include "coord/fwd.hpp"
|
||||||
#include "coord/base.hpp"
|
#include "coord/base.hpp"
|
||||||
@ -36,12 +36,34 @@ namespace util {
|
|||||||
extent () = default;
|
extent () = default;
|
||||||
explicit extent (::util::vector<S,T>);
|
explicit extent (::util::vector<S,T>);
|
||||||
|
|
||||||
constexpr T area (void) const;
|
constexpr T
|
||||||
constexpr T diameter (void) const;
|
area (void) const
|
||||||
|
{
|
||||||
|
return std::accumulate (std::begin (this->data),
|
||||||
|
std::end (this->data),
|
||||||
|
T {1},
|
||||||
|
std::multiplies<T> ());
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr T
|
||||||
|
diameter (void) const
|
||||||
|
{
|
||||||
|
return static_cast<T> (
|
||||||
|
std::sqrt (
|
||||||
|
std::accumulate (std::begin (this->data),
|
||||||
|
std::end (this->data),
|
||||||
|
T {0},
|
||||||
|
[] (auto a, auto b) { return a + b * b; })
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename U = float>
|
template <typename U = float>
|
||||||
constexpr
|
constexpr
|
||||||
U aspect (void) const;
|
U aspect (void) const
|
||||||
|
{
|
||||||
|
return static_cast<U> (this->w) / this->h;
|
||||||
|
}
|
||||||
|
|
||||||
/// tests whether a point would lie within:
|
/// tests whether a point would lie within:
|
||||||
/// region { origin, *this }, inclusive of borders.
|
/// region { origin, *this }, inclusive of borders.
|
||||||
@ -70,8 +92,20 @@ namespace util {
|
|||||||
|
|
||||||
bool empty (void) const;
|
bool empty (void) const;
|
||||||
|
|
||||||
static constexpr ::util::extent<S,T> max (void);
|
static constexpr
|
||||||
static constexpr ::util::extent<S,T> min (void);
|
::util::extent<S,T> max (void)
|
||||||
|
{
|
||||||
|
return extent<S,T> {
|
||||||
|
std::numeric_limits<T>::max ()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static constexpr
|
||||||
|
::util::extent<S,T> min (void)
|
||||||
|
{
|
||||||
|
return extent<S,T> { 0 };
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
@ -147,6 +181,4 @@ namespace util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#include "extent.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
88
extent.ipp
88
extent.ipp
@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2015-2017 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __UTIL_EXTENT_IPP
|
|
||||||
#error
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define __UTIL_EXTENT_IPP
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t S, typename T>
|
|
||||||
constexpr
|
|
||||||
T
|
|
||||||
util::extent<S,T>::diameter (void) const
|
|
||||||
{
|
|
||||||
return static_cast<T> (
|
|
||||||
std::sqrt (
|
|
||||||
std::accumulate (std::begin (this->data),
|
|
||||||
std::end (this->data),
|
|
||||||
T {0},
|
|
||||||
[] (auto a, auto b) { return a + b * b; })
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t S, typename T>
|
|
||||||
constexpr
|
|
||||||
T
|
|
||||||
util::extent<S,T>::area (void) const
|
|
||||||
{
|
|
||||||
return std::accumulate (std::begin (this->data),
|
|
||||||
std::end (this->data),
|
|
||||||
T {1},
|
|
||||||
std::multiplies<T> ());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t S, typename T>
|
|
||||||
template <typename U>
|
|
||||||
constexpr
|
|
||||||
U
|
|
||||||
util::extent<S,T>::aspect (void) const
|
|
||||||
{
|
|
||||||
return static_cast<U> (this->w) / this->h;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t S, typename T>
|
|
||||||
constexpr
|
|
||||||
util::extent<S,T>
|
|
||||||
util::extent<S,T>::max (void)
|
|
||||||
{
|
|
||||||
return extent<S,T> {
|
|
||||||
std::numeric_limits<T>::max ()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <size_t S, typename T>
|
|
||||||
constexpr
|
|
||||||
util::extent<S,T>
|
|
||||||
util::extent<S,T>::min (void)
|
|
||||||
{
|
|
||||||
return extent<S,T> { 0 };
|
|
||||||
}
|
|
@ -24,13 +24,37 @@
|
|||||||
|
|
||||||
namespace util::geom {
|
namespace util::geom {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename ValueT>
|
||||||
struct ellipse {
|
struct ellipse {
|
||||||
util::point<S,T> origin;
|
util::point<S,ValueT> origin;
|
||||||
util::vector<S,T> radius;
|
util::vector<S,ValueT> radius;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "ellipse.ipp"
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
#include "sample.hpp"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
namespace util::geom {
|
||||||
|
template <typename T, template <size_t,typename> class K, typename G>
|
||||||
|
struct sampler<2,T,K,G>
|
||||||
|
{
|
||||||
|
static util::point<2,T> fn (K<2,T> k, G &g)
|
||||||
|
{
|
||||||
|
std::uniform_real_distribution<T> dist;
|
||||||
|
|
||||||
|
float phi = dist (g) * 2 * PI<T>;
|
||||||
|
float rho = std::sqrt (dist (g));
|
||||||
|
|
||||||
|
return util::point<2,T> {
|
||||||
|
std::cos (phi),
|
||||||
|
std::sin (phi)
|
||||||
|
} * rho * k.radius + k.origin.template as<util::vector> ();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(__UTIL_GEOM_ELLIPSE_IPP)
|
|
||||||
#error
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define __UTIL_GEOM_ELLIPSE_IPP
|
|
||||||
|
|
||||||
#include "sample.hpp"
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <random>
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
namespace util::geom {
|
|
||||||
template <typename T, template <size_t,typename> class K, typename G>
|
|
||||||
struct sampler<2,T,K,G>
|
|
||||||
{
|
|
||||||
static util::point<2,T> fn (K<2,T> k, G &g)
|
|
||||||
{
|
|
||||||
std::uniform_real_distribution<T> dist;
|
|
||||||
|
|
||||||
float phi = dist (g) * 2 * PI<T>;
|
|
||||||
float rho = std::sqrt (dist (g));
|
|
||||||
|
|
||||||
return util::point<2,T> {
|
|
||||||
std::cos (phi),
|
|
||||||
std::sin (phi)
|
|
||||||
} * rho * k.radius + k.origin.template as<util::vector> ();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
28
io.hpp
28
io.hpp
@ -94,23 +94,27 @@ namespace util {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <typename T>
|
// a wrapper type that implicitly indents a single value when passed to an
|
||||||
|
// ostream operator.
|
||||||
|
template <typename ValueT>
|
||||||
struct indented {
|
struct indented {
|
||||||
explicit indented (const T &_data);
|
explicit indented (const ValueT &_data):
|
||||||
const T &data;
|
data (_data)
|
||||||
|
{ ; }
|
||||||
|
|
||||||
|
const ValueT &data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename ValueT>
|
||||||
indented<T>
|
|
||||||
make_indented (const T &_data);
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
std::ostream&
|
std::ostream&
|
||||||
operator<< (std::ostream &os, const util::indented<T> &v);
|
operator<< (std::ostream &os, const util::indented<ValueT> &value)
|
||||||
|
{
|
||||||
|
util::indenter scoped_indent (os);
|
||||||
|
return os << value.data;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
@ -148,6 +152,4 @@ namespace util {
|
|||||||
#include "io_posix.hpp"
|
#include "io_posix.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "io.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
49
io.ipp
49
io.ipp
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright:
|
|
||||||
* 2014-2015, Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __UTIL_IO_IPP
|
|
||||||
#error "multiple inclusions"
|
|
||||||
#else
|
|
||||||
#define __UTIL__IO_IPP
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace util {
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
indented<T>::indented (const T &_data):
|
|
||||||
data (_data)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
indented<T>
|
|
||||||
make_indented (const T &_data) {
|
|
||||||
return indented<T> (_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
std::ostream&
|
|
||||||
operator<< (std::ostream &os, const util::indented<T> &&v) {
|
|
||||||
util::indenter raii (os);
|
|
||||||
os << v.data;
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
}
|
|
@ -81,6 +81,4 @@ namespace util {
|
|||||||
typedef detail::posix::mapped_file mapped_file;
|
typedef detail::posix::mapped_file mapped_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "io_posix.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
23
io_posix.ipp
23
io_posix.ipp
@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __UTIL_IO_POSIX_IPP
|
|
||||||
#error
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define __UTIL_IO_POSIX_IPP
|
|
||||||
|
|
||||||
#include "pointer.hpp"
|
|
18
io_win32.hpp
18
io_win32.hpp
@ -84,11 +84,23 @@ namespace util {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
util::view<std::add_const_t<T>*>
|
util::view<std::add_const_t<T>*>
|
||||||
as_view () const &;
|
as_view () const &
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
reinterpret_cast<const T*> (cbegin ()),
|
||||||
|
reinterpret_cast<const T*> (align (cend (), alignof (T)))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
util::view<T*>
|
util::view<T*>
|
||||||
as_view () &;
|
as_view () &
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
reinterpret_cast<T *> (begin ()),
|
||||||
|
reinterpret_cast<T *> (align (end (), alignof(T)))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
::util::win32::handle m_file;
|
::util::win32::handle m_file;
|
||||||
@ -102,6 +114,4 @@ namespace util {
|
|||||||
typedef detail::win32::mapped_file mapped_file;
|
typedef detail::win32::mapped_file mapped_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "io_win32.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
48
io_win32.ipp
48
io_win32.ipp
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __UTIL_IO_WIN32_IPP
|
|
||||||
#error
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define __UTIL_IO_WIN32_IPP
|
|
||||||
|
|
||||||
#include "pointer.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T>
|
|
||||||
util::view<std::add_const_t<T>*>
|
|
||||||
util::detail::win32::mapped_file::as_view (void) const&
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
reinterpret_cast<const T*> (cbegin ()),
|
|
||||||
reinterpret_cast<const T*> (align (cend (), alignof (T)))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
util::view<T*>
|
|
||||||
util::detail::win32::mapped_file::as_view (void) &
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
reinterpret_cast<T *> (begin ()),
|
|
||||||
reinterpret_cast<T *> (align (end (), alignof(T)))
|
|
||||||
};
|
|
||||||
}
|
|
15
log.ipp
15
log.ipp
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2012-2016 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
89
point.hpp
89
point.hpp
@ -14,12 +14,14 @@
|
|||||||
* Copyright 2011-2016 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2011-2016 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_POINT_HPP
|
#ifndef CRUFT_UTIL_POINT_HPP
|
||||||
#define __UTIL_POINT_HPP
|
#define CRUFT_UTIL_POINT_HPP
|
||||||
|
|
||||||
#include "vector.hpp"
|
#include "vector.hpp"
|
||||||
#include "coord.hpp"
|
#include "coord.hpp"
|
||||||
|
#include "maths.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
@ -35,7 +37,29 @@ namespace util {
|
|||||||
vector<S,T> to (point) const;
|
vector<S,T> to (point) const;
|
||||||
vector<S,T> from (point) const;
|
vector<S,T> from (point) const;
|
||||||
|
|
||||||
template <size_t D> point<D,T> homog (void) const;
|
/// expand point to use homogenous coordinates of a higher dimension.
|
||||||
|
/// ie, fill with (0,..,0,1)
|
||||||
|
template <size_t D>
|
||||||
|
point<D,T>
|
||||||
|
homog (void) const
|
||||||
|
{
|
||||||
|
static_assert (D > S, "homog will not overwrite data");
|
||||||
|
|
||||||
|
point<D,T> out;
|
||||||
|
|
||||||
|
// Copy the existing data
|
||||||
|
auto c = std::copy (this->begin (),
|
||||||
|
this->end (),
|
||||||
|
out.begin ());
|
||||||
|
|
||||||
|
// Fill until the second last element with zeros
|
||||||
|
auto f = std::fill_n (c, D - S - 1, T{0});
|
||||||
|
|
||||||
|
// Last element should be one
|
||||||
|
*f = T{1};
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
static constexpr
|
static constexpr
|
||||||
@ -54,7 +78,10 @@ namespace util {
|
|||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
static constexpr
|
static constexpr
|
||||||
point<S,T> origin (void);
|
point<S,T> origin (void)
|
||||||
|
{
|
||||||
|
return point<S,T> {0};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
@ -66,33 +93,75 @@ namespace util {
|
|||||||
|
|
||||||
/// computes the exact euclidean distance between two points.
|
/// computes the exact euclidean distance between two points.
|
||||||
template <size_t S, typename T, typename U>
|
template <size_t S, typename T, typename U>
|
||||||
typename std::common_type<T,U>::type distance (point<S,T>, point<S,U>);
|
typename std::common_type<T,U>::type
|
||||||
|
distance (point<S,T> a, point<S,U> b)
|
||||||
|
{
|
||||||
|
using type_t = typename std::common_type<T,U>::type;
|
||||||
|
static_assert (std::is_floating_point<type_t>::value,
|
||||||
|
"sqrt likely requires fractional types");
|
||||||
|
|
||||||
|
return std::sqrt (distance2 (a, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// computes the squared euclidean distance between two points.
|
/// computes the squared euclidean distance between two points.
|
||||||
///
|
///
|
||||||
/// useful if you just need to compare distances because it avoids a sqrt
|
/// useful if you just need to compare distances because it avoids a sqrt
|
||||||
/// operation.
|
/// operation.
|
||||||
template <size_t S, typename T, typename U>
|
template <size_t S, typename T, typename U>
|
||||||
constexpr typename std::common_type<T,U>::type distance2 (point<S,T>, point<S,U>);
|
constexpr typename std::common_type<T,U>::type
|
||||||
|
distance2 (point<S,T> a, point<S,U> b)
|
||||||
|
{
|
||||||
|
return sum (pow2 (a - b));
|
||||||
|
}
|
||||||
|
|
||||||
/// computes the octile distance between two points. that is, the shortest
|
/// computes the octile distance between two points. that is, the shortest
|
||||||
/// distance between `a' and `b' where travel is only allowed beween the 8
|
/// distance between `a' and `b' where travel is only allowed beween the 8
|
||||||
/// grid neighbours and cost for diagonals is proportionally larger than
|
/// grid neighbours and cost for diagonals is proportionally larger than
|
||||||
/// cardinal movement. see also: chebyshev.
|
/// cardinal movement. see also: chebyshev.
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
typename std::common_type<T,U>::type octile (point<2,T>, point<2,U>);
|
typename std::common_type<T,U>::type
|
||||||
|
octile (point<2,T> a, point<2,U> b)
|
||||||
|
{
|
||||||
|
using type_t = typename std::common_type<T,U>::type;
|
||||||
|
static_assert (!std::is_integral<type_t>::value,
|
||||||
|
"octile requires more than integer precision");
|
||||||
|
|
||||||
|
const type_t D1 = 1;
|
||||||
|
const type_t D2 = std::sqrt (type_t {2});
|
||||||
|
|
||||||
|
auto diff = util::abs (a - b);
|
||||||
|
|
||||||
|
// distance for axis-aligned walks
|
||||||
|
auto axis = D1 * (diff.x + diff.y);
|
||||||
|
|
||||||
|
// the savings from diagonal walks
|
||||||
|
auto diag = (D2 - 2 * D1) * util::min (diff);
|
||||||
|
|
||||||
|
return axis + diag;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// computes the manhattan distance between two points. that is, the
|
/// computes the manhattan distance between two points. that is, the
|
||||||
/// distance where travel is only allowed along cardinal directions.
|
/// distance where travel is only allowed along cardinal directions.
|
||||||
template <size_t S, typename T, typename U>
|
template <size_t S, typename T, typename U>
|
||||||
constexpr typename std::common_type<T,U>::type manhattan (point<S,T>, point<S,U>);
|
constexpr typename std::common_type<T,U>::type
|
||||||
|
manhattan (point<S,T> a, point<S,U> b)
|
||||||
|
{
|
||||||
|
return sum (abs (a - b));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// computes the cheyvshev distance between two points. that is, the
|
/// computes the cheyvshev distance between two points. that is, the
|
||||||
/// shortest distance between `a' and `b' where travel is only allowed
|
/// shortest distance between `a' and `b' where travel is only allowed
|
||||||
/// between the 8 grid neighbours and cost for diagonals is the same as
|
/// between the 8 grid neighbours and cost for diagonals is the same as
|
||||||
/// cardinal movement. see also: octile.
|
/// cardinal movement. see also: octile.
|
||||||
template <size_t S, typename T, typename U>
|
template <size_t S, typename T, typename U>
|
||||||
constexpr typename std::common_type<T,U>::type chebyshev (point<S,T>, point<S,U>);
|
constexpr typename std::common_type<T,U>::type
|
||||||
|
chebyshev (point<S,T> a, point<S,U> b)
|
||||||
|
{
|
||||||
|
return util::max (abs (a - b));
|
||||||
|
}
|
||||||
|
|
||||||
// Convenience typedefs
|
// Convenience typedefs
|
||||||
template <typename T> using point1 = point<1,T>;
|
template <typename T> using point1 = point<1,T>;
|
||||||
@ -122,6 +191,4 @@ namespace util {
|
|||||||
typedef point4<int> point4i;
|
typedef point4<int> point4i;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "point.ipp"
|
|
||||||
|
|
||||||
#endif // __UTIL_POINT_HPP
|
#endif // __UTIL_POINT_HPP
|
||||||
|
120
point.ipp
120
point.ipp
@ -1,120 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2014-2015 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "maths.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// expand point to use homogenous coordinates of a higher dimension.
|
|
||||||
/// ie, fill with (0,..,0,1)
|
|
||||||
template <size_t S, typename T>
|
|
||||||
template <size_t D>
|
|
||||||
util::point<D,T>
|
|
||||||
util::point<S,T>::homog (void) const
|
|
||||||
{
|
|
||||||
static_assert (D > S, "homog will not overwrite data");
|
|
||||||
|
|
||||||
point<D,T> out;
|
|
||||||
|
|
||||||
// Copy the existing data
|
|
||||||
auto c = std::copy (this->begin (),
|
|
||||||
this->end (),
|
|
||||||
out.begin ());
|
|
||||||
|
|
||||||
// Fill until the second last element with zeros
|
|
||||||
auto f = std::fill_n (c, D - S - 1, T{0});
|
|
||||||
|
|
||||||
// Last element should be one
|
|
||||||
*f = T{1};
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t S, typename T>
|
|
||||||
constexpr
|
|
||||||
util::point<S,T>
|
|
||||||
util::point<S,T>::origin (void)
|
|
||||||
{
|
|
||||||
return point<S,T> {0};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t S, typename T, typename U>
|
|
||||||
typename std::common_type<T,U>::type
|
|
||||||
util::distance (point<S,T> a, point<S,U> b)
|
|
||||||
{
|
|
||||||
using type_t = typename std::common_type<T,U>::type;
|
|
||||||
static_assert (std::is_floating_point<type_t>::value,
|
|
||||||
"sqrt likely requires fractional types");
|
|
||||||
|
|
||||||
return std::sqrt (distance2 (a, b));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t S, typename T, typename U>
|
|
||||||
constexpr typename std::common_type<T,U>::type
|
|
||||||
util::distance2 (point<S,T> a, point<S,U> b)
|
|
||||||
{
|
|
||||||
return sum (pow2 (a - b));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T, typename U>
|
|
||||||
typename std::common_type<T,U>::type
|
|
||||||
util::octile (point2<T> a, point2<U> b)
|
|
||||||
{
|
|
||||||
using type_t = typename std::common_type<T,U>::type;
|
|
||||||
static_assert (!std::is_integral<type_t>::value,
|
|
||||||
"octile requires more than integer precision");
|
|
||||||
|
|
||||||
const type_t D1 = 1;
|
|
||||||
const type_t D2 = std::sqrt (type_t {2});
|
|
||||||
|
|
||||||
auto diff = util::abs (a - b);
|
|
||||||
|
|
||||||
// distance for axis-aligned walks
|
|
||||||
auto axis = D1 * (diff.x + diff.y);
|
|
||||||
|
|
||||||
// the savings from diagonal walks
|
|
||||||
auto diag = (D2 - 2 * D1) * util::min (diff);
|
|
||||||
|
|
||||||
return axis + diag;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t S, typename T, typename U>
|
|
||||||
constexpr typename std::common_type<T,U>::type
|
|
||||||
util::manhattan (point<S,T> a, point<S,U> b)
|
|
||||||
{
|
|
||||||
return sum (abs (a - b));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t S, typename T, typename U>
|
|
||||||
constexpr typename std::common_type<T,U>::type
|
|
||||||
util::chebyshev(point<S,T> a, point<S,U> b)
|
|
||||||
{
|
|
||||||
return util::max (abs (a - b));
|
|
||||||
}
|
|
@ -14,8 +14,8 @@
|
|||||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_POLYNOMIAL_HPP
|
#ifndef CRUFT_UTIL_POLYNOMIAL_HPP
|
||||||
#define __UTIL_POLYNOMIAL_HPP
|
#define CRUFT_UTIL_POLYNOMIAL_HPP
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@ -30,9 +30,18 @@ namespace util::polynomial {
|
|||||||
|
|
||||||
template <size_t S, typename T, typename U>
|
template <size_t S, typename T, typename U>
|
||||||
T
|
T
|
||||||
eval (std::array<T,S>, U x);
|
eval (std::array<T,S> coeffs, U x)
|
||||||
|
{
|
||||||
|
U x_ = 1.f;
|
||||||
|
T sum {0.f};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < S; ++i) {
|
||||||
|
sum += coeffs[S-i-1] * x_;
|
||||||
|
x_ *= x;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "polynomial.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __UTIL_POLYNOMIAL_IPP
|
|
||||||
#error "twice included ipp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define __UTIL_POLYNOMIAL_IPP
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t S, typename T, typename U>
|
|
||||||
T
|
|
||||||
util::polynomial::eval (const std::array<T,S> coeffs, const U x)
|
|
||||||
{
|
|
||||||
U x_ = 1.f;
|
|
||||||
T sum {0.f};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < S; ++i) {
|
|
||||||
sum += coeffs[S-i-1] * x_;
|
|
||||||
x_ *= x;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sum;
|
|
||||||
}
|
|
89
pool.hpp
89
pool.hpp
@ -14,12 +14,14 @@
|
|||||||
* Copyright 2011-2016 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2011-2016 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_POOL_HPP
|
#ifndef CRUFT_UTIL_POOL_HPP
|
||||||
#define __UTIL_POOL_HPP
|
#define CRUFT_UTIL_POOL_HPP
|
||||||
|
|
||||||
#include "nocopy.hpp"
|
#include "nocopy.hpp"
|
||||||
|
#include "debug.hpp"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
/// a simple pre-allocated pool for storage of PODs.
|
/// a simple pre-allocated pool for storage of PODs.
|
||||||
@ -42,19 +44,85 @@ namespace util {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit
|
explicit
|
||||||
pool (unsigned int _capacity);
|
pool (unsigned int _capacity):
|
||||||
|
m_capacity (_capacity),
|
||||||
|
m_size (0u)
|
||||||
|
{
|
||||||
|
static_assert (sizeof (T) >= sizeof (uintptr_t),
|
||||||
|
"pool<T>'s chained block system requires that T be at least pointer sized");
|
||||||
|
|
||||||
~pool ();
|
// allocate the memory and note the base address for deletion in destructor
|
||||||
|
m_next = m_head = new node[m_capacity]; // static_cast<node *> (operator new (sizeof (T) * m_capacity));
|
||||||
|
|
||||||
|
// initialise the linked list of nodes
|
||||||
|
for (unsigned int i = 0; i < m_capacity - 1; ++i)
|
||||||
|
m_next[i]._node = m_next + i + 1;
|
||||||
|
m_next[m_capacity - 1]._node = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
~pool ()
|
||||||
|
{
|
||||||
|
// don't check if everything's been returned as pools are often used
|
||||||
|
// for PODs which don't need to be destructed via calling release.
|
||||||
|
delete [] m_head;
|
||||||
|
}
|
||||||
|
|
||||||
// Data management
|
// Data management
|
||||||
template <typename ...Args>
|
template <typename ...Args>
|
||||||
T* acquire (Args&... args);
|
T* acquire (Args&... args)
|
||||||
|
{
|
||||||
|
// double check we have enough capacity left
|
||||||
|
if (!m_next)
|
||||||
|
throw std::bad_alloc ();
|
||||||
|
CHECK_LT (m_size, m_capacity);
|
||||||
|
|
||||||
void release (T *data);
|
// save what will become the next node shortly. it could be overwritten
|
||||||
|
// in the constructor we're about to call.
|
||||||
|
node *newnext = m_next->_node;
|
||||||
|
T *data = reinterpret_cast<T*> (m_next);
|
||||||
|
|
||||||
size_t capacity (void) const;
|
// try to construct the returnable object.
|
||||||
size_t size (void) const;
|
try {
|
||||||
bool empty (void) const;
|
new (data) T (args...);
|
||||||
|
} catch (...) {
|
||||||
|
// the constructor may have overwritten the node linkages before
|
||||||
|
// throwing. fix this up before forwarding the exception.
|
||||||
|
m_next->_node = newnext;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the object is valid. save the new linked list head and bump the
|
||||||
|
// stats for availability.
|
||||||
|
m_next = newnext;
|
||||||
|
m_size++;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release (T *data)
|
||||||
|
{
|
||||||
|
CHECK_NEZ (m_size);
|
||||||
|
|
||||||
|
data->~T();
|
||||||
|
node *newnode = reinterpret_cast<node *> (data);
|
||||||
|
|
||||||
|
newnode->_node = m_next;
|
||||||
|
m_next = newnode;
|
||||||
|
m_size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t capacity (void) const
|
||||||
|
{
|
||||||
|
return m_capacity;
|
||||||
|
}
|
||||||
|
size_t size (void) const
|
||||||
|
{
|
||||||
|
return m_size;
|
||||||
|
}
|
||||||
|
bool empty (void) const
|
||||||
|
{
|
||||||
|
return m_size == m_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
// Indexing
|
// Indexing
|
||||||
size_t index (const T*) const;
|
size_t index (const T*) const;
|
||||||
@ -64,6 +132,5 @@ namespace util {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "pool.ipp"
|
|
||||||
|
|
||||||
#endif // __UTIL_POOL_HPP
|
#endif
|
||||||
|
138
pool.ipp
138
pool.ipp
@ -1,138 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2011-2016 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __UTIL_POOL_IPP
|
|
||||||
#error
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define __UTIL_POOL_IPP
|
|
||||||
|
|
||||||
#include "debug.hpp"
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <new>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
|
||||||
namespace util {
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
pool<T>::pool (unsigned int _capacity):
|
|
||||||
m_capacity (_capacity),
|
|
||||||
m_size (0u)
|
|
||||||
{
|
|
||||||
static_assert (sizeof (T) >= sizeof (uintptr_t),
|
|
||||||
"pool<T>'s chained block system requires that T be at least pointer sized");
|
|
||||||
|
|
||||||
// allocate the memory and note the base address for deletion in destructor
|
|
||||||
m_next = m_head = new node[m_capacity]; // static_cast<node *> (operator new (sizeof (T) * m_capacity));
|
|
||||||
|
|
||||||
// initialise the linked list of nodes
|
|
||||||
for (unsigned int i = 0; i < m_capacity - 1; ++i)
|
|
||||||
m_next[i]._node = m_next + i + 1;
|
|
||||||
m_next[m_capacity - 1]._node = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
pool<T>::~pool ()
|
|
||||||
{
|
|
||||||
// don't check if everything's been returned as pools are often used
|
|
||||||
// for PODs which don't need to be destructed via calling release.
|
|
||||||
delete [] m_head;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
size_t
|
|
||||||
pool<T>::capacity (void) const
|
|
||||||
{
|
|
||||||
return m_capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
size_t
|
|
||||||
pool<T>::size (void) const
|
|
||||||
{
|
|
||||||
return m_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
bool
|
|
||||||
pool<T>::empty (void) const
|
|
||||||
{
|
|
||||||
return m_size == m_capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
template <typename ...Args>
|
|
||||||
T*
|
|
||||||
pool<T>::acquire (Args&... args)
|
|
||||||
{
|
|
||||||
// double check we have enough capacity left
|
|
||||||
if (!m_next)
|
|
||||||
throw std::bad_alloc ();
|
|
||||||
CHECK_LT (m_size, m_capacity);
|
|
||||||
|
|
||||||
// save what will become the next node shortly. it could be overwritten
|
|
||||||
// in the constructor we're about to call.
|
|
||||||
node *newnext = m_next->_node;
|
|
||||||
T *data = reinterpret_cast<T*> (m_next);
|
|
||||||
|
|
||||||
// try to construct the returnable object.
|
|
||||||
try {
|
|
||||||
new (data) T (args...);
|
|
||||||
} catch (...) {
|
|
||||||
// the constructor may have overwritten the node linkages before
|
|
||||||
// throwing. fix this up before forwarding the exception.
|
|
||||||
m_next->_node = newnext;
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the object is valid. save the new linked list head and bump the
|
|
||||||
// stats for availability.
|
|
||||||
m_next = newnext;
|
|
||||||
m_size++;
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
void
|
|
||||||
pool<T>::release (T *data)
|
|
||||||
{
|
|
||||||
CHECK_NEZ (m_size);
|
|
||||||
|
|
||||||
data->~T();
|
|
||||||
node *newnode = reinterpret_cast<node *> (data);
|
|
||||||
|
|
||||||
newnode->_node = m_next;
|
|
||||||
m_next = newnode;
|
|
||||||
m_size--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -17,11 +17,15 @@
|
|||||||
#ifndef __UTIL_POSIX_DIR_HPP
|
#ifndef __UTIL_POSIX_DIR_HPP
|
||||||
#define __UTIL_POSIX_DIR_HPP
|
#define __UTIL_POSIX_DIR_HPP
|
||||||
|
|
||||||
|
#include "except.hpp"
|
||||||
|
|
||||||
|
#include <cerrno>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <experimental/filesystem>
|
#include <experimental/filesystem>
|
||||||
|
|
||||||
|
|
||||||
namespace util::posix {
|
namespace util::posix {
|
||||||
struct dir {
|
struct dir {
|
||||||
public:
|
public:
|
||||||
@ -30,13 +34,18 @@ namespace util::posix {
|
|||||||
|
|
||||||
operator DIR* (void);
|
operator DIR* (void);
|
||||||
|
|
||||||
template <typename ...Args>
|
// run a callback for each entry in the provided directory
|
||||||
|
template <typename FunctionT, typename ...Args>
|
||||||
void
|
void
|
||||||
scan (std::function<void(const std::experimental::filesystem::path&, Args&...)>, Args&...);
|
scan (FunctionT &&func, Args&&...args)
|
||||||
|
{
|
||||||
|
rewind ();
|
||||||
|
|
||||||
template <typename ...Args>
|
for (dirent *cursor; errno = 0, cursor = readdir (m_handle); )
|
||||||
void
|
func (cursor->d_name, args...);
|
||||||
scan (void (*) (const std::experimental::filesystem::path&, Args&...), Args&...);
|
|
||||||
|
error::try_code ();
|
||||||
|
}
|
||||||
|
|
||||||
//entry begin (void) { rewind (); return { readdir (m_handle), m_handle }; }
|
//entry begin (void) { rewind (); return { readdir (m_handle), m_handle }; }
|
||||||
//entry end (void) { return { nullptr, m_handle }; }
|
//entry end (void) { return { nullptr, m_handle }; }
|
||||||
@ -48,6 +57,4 @@ namespace util::posix {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "dir.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2015-2016 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "except.hpp"
|
|
||||||
|
|
||||||
#include <cerrno>
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename ...Args>
|
|
||||||
void
|
|
||||||
util::posix::dir::scan(std::function<void(const std::experimental::filesystem::path&, Args&...)> cb, Args &...args)
|
|
||||||
{
|
|
||||||
rewind ();
|
|
||||||
|
|
||||||
for (dirent *cursor; errno = 0, cursor = readdir (m_handle); )
|
|
||||||
cb (cursor->d_name, args...);
|
|
||||||
|
|
||||||
error::try_code ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename ...Args>
|
|
||||||
void
|
|
||||||
util::posix::dir::scan (void (*cb) (const std::experimental::filesystem::path&, Args&...), Args &...args)
|
|
||||||
{
|
|
||||||
rewind ();
|
|
||||||
|
|
||||||
for (dirent *cursor; errno = 0, cursor = readdir (m_handle); )
|
|
||||||
cb (cursor->d_name, args...);
|
|
||||||
|
|
||||||
error::try_code ();
|
|
||||||
}
|
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "coord/traits.hpp"
|
#include "coord/traits.hpp"
|
||||||
|
|
||||||
|
#include "maths.hpp"
|
||||||
#include "vector.hpp"
|
#include "vector.hpp"
|
||||||
#include "matrix.hpp"
|
#include "matrix.hpp"
|
||||||
|
|
||||||
@ -48,10 +49,15 @@ namespace util {
|
|||||||
|
|
||||||
matrix4<T> as_matrix (void) const;
|
matrix4<T> as_matrix (void) const;
|
||||||
|
|
||||||
static constexpr quaternion<T> identity (void);
|
static constexpr
|
||||||
|
quaternion<T> identity (void)
|
||||||
|
{
|
||||||
|
return { 1, 0, 0, 0 };
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct arity<quaternion<T>,void>
|
struct arity<quaternion<T>,void>
|
||||||
:std::integral_constant<std::size_t, 4>
|
:std::integral_constant<std::size_t, 4>
|
||||||
@ -68,22 +74,43 @@ namespace util {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr
|
constexpr
|
||||||
T
|
T
|
||||||
norm2 (quaternion<T>);
|
norm2 (quaternion<T> q)
|
||||||
|
{
|
||||||
|
return q.w * q.w +
|
||||||
|
q.x * q.x +
|
||||||
|
q.y * q.y +
|
||||||
|
q.z * q.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr
|
constexpr
|
||||||
T
|
T
|
||||||
norm (quaternion<T>);
|
norm (quaternion<T> q)
|
||||||
|
{
|
||||||
|
return std::sqrt (norm2 (q));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr
|
constexpr
|
||||||
bool
|
bool
|
||||||
is_normalised (quaternion<T>);
|
is_normalised (quaternion<T> q)
|
||||||
|
{
|
||||||
|
return almost_equal (T{1}, norm2 (q));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr
|
constexpr
|
||||||
quaternion<T>
|
quaternion<T>
|
||||||
normalised (quaternion<T>);
|
normalised (quaternion<T> q)
|
||||||
|
{
|
||||||
|
return q / norm (q);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
@ -97,32 +124,46 @@ namespace util {
|
|||||||
quaternion<T>
|
quaternion<T>
|
||||||
operator* (quaternion<T>, quaternion<T>);
|
operator* (quaternion<T>, quaternion<T>);
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
quaternion<T>&
|
quaternion<T>&
|
||||||
operator*= (quaternion<T>&, quaternion<T>);
|
operator*= (quaternion<T>&, quaternion<T>);
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
quaternion<T>
|
quaternion<T>
|
||||||
operator/ (quaternion<T>, quaternion<T>);
|
operator/ (quaternion<T>, quaternion<T>);
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr
|
constexpr
|
||||||
quaternion<T>
|
quaternion<T>
|
||||||
operator/ (quaternion<T>, T);
|
operator/ (quaternion<T> q, T t)
|
||||||
|
{
|
||||||
|
return { q.w / t, q.x / t, q.y / t, q.z / t };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr
|
constexpr
|
||||||
bool operator== (quaternion<T>, quaternion<T>);
|
bool operator== (quaternion<T> a, quaternion<T> b)
|
||||||
|
{
|
||||||
|
return exactly_equal (a.w, b.w) &&
|
||||||
|
exactly_equal (a.x, b.x) &&
|
||||||
|
exactly_equal (a.y, b.y) &&
|
||||||
|
exactly_equal (a.z, b.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool almost_equal (quaternion<T>, quaternion<T>);
|
bool almost_equal (quaternion<T>, quaternion<T>);
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
typedef quaternion<float> quaternionf;
|
typedef quaternion<float> quaternionf;
|
||||||
typedef quaternion<double> quaterniond;
|
typedef quaternion<double> quaterniond;
|
||||||
@ -134,6 +175,4 @@ namespace util {
|
|||||||
operator<< (std::ostream&, quaternion<T>);
|
operator<< (std::ostream&, quaternion<T>);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "quaternion.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,99 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2011-2016 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(CRUFT_UTIL_QUATERNION_IPP)
|
|
||||||
#error
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CRUFT_UTIL_QUATERNION_IPP
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
|
||||||
util::quaternion<T>
|
|
||||||
util::quaternion<T>::identity (void)
|
|
||||||
{
|
|
||||||
return { 1, 0, 0, 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
|
||||||
T
|
|
||||||
util::norm2 (quaternion<T> q)
|
|
||||||
{
|
|
||||||
return q.w * q.w +
|
|
||||||
q.x * q.x +
|
|
||||||
q.y * q.y +
|
|
||||||
q.z * q.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
|
||||||
T
|
|
||||||
util::norm (quaternion<T> q)
|
|
||||||
{
|
|
||||||
return std::sqrt (norm2 (q));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
|
||||||
bool
|
|
||||||
util::is_normalised (quaternion<T> q)
|
|
||||||
{
|
|
||||||
return almost_equal (T{1}, norm2 (q));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
|
||||||
util::quaternion<T>
|
|
||||||
util::normalised (quaternion<T> q)
|
|
||||||
{
|
|
||||||
return q / norm (q);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
|
||||||
util::quaternion<T>
|
|
||||||
util::operator/ (quaternion<T> q, T t)
|
|
||||||
{
|
|
||||||
return { q.w / t, q.x / t, q.y / t, q.z / t };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
|
||||||
bool
|
|
||||||
util::operator== (quaternion<T> a, quaternion<T> b)
|
|
||||||
{
|
|
||||||
return exactly_equal (a.w, b.w) &&
|
|
||||||
exactly_equal (a.x, b.x) &&
|
|
||||||
exactly_equal (a.y, b.y) &&
|
|
||||||
exactly_equal (a.z, b.z);
|
|
||||||
}
|
|
42
range.hpp
42
range.hpp
@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <limits>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
/**
|
/**
|
||||||
@ -55,7 +57,15 @@ namespace util {
|
|||||||
/// bounds, it is the caller's responsibility to clamp the result if
|
/// bounds, it is the caller's responsibility to clamp the result if
|
||||||
/// needed.
|
/// needed.
|
||||||
template <typename U>
|
template <typename U>
|
||||||
U normalise (T val) const;
|
U
|
||||||
|
normalise (T val) const
|
||||||
|
{
|
||||||
|
static_assert (std::is_floating_point<U>::value,
|
||||||
|
"normalise isn't implemented for integer types");
|
||||||
|
|
||||||
|
return static_cast<U> (val - lo) /
|
||||||
|
static_cast<U> ( hi - lo);
|
||||||
|
}
|
||||||
|
|
||||||
range& operator*= (T);
|
range& operator*= (T);
|
||||||
range operator* (T) const;
|
range operator* (T) const;
|
||||||
@ -78,10 +88,32 @@ namespace util {
|
|||||||
{ return !(*this == rhs); }
|
{ return !(*this == rhs); }
|
||||||
|
|
||||||
/// A range which is guaranteed to contain all elements type T
|
/// A range which is guaranteed to contain all elements type T
|
||||||
static constexpr range<T> unlimited (void);
|
static constexpr range<T> unlimited (void)
|
||||||
static constexpr range<T> max (void);
|
{
|
||||||
|
return {
|
||||||
|
std::numeric_limits<T>::has_infinity ? -std::numeric_limits<T>::infinity () :
|
||||||
|
std::numeric_limits<T>::lowest (),
|
||||||
|
std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity () :
|
||||||
|
std::numeric_limits<T>::max ()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr range<T> max (void)
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
std::numeric_limits<T>::lowest (),
|
||||||
|
std::numeric_limits<T>::max ()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// A range which only contains elements between 0 and 1 inclusive
|
/// A range which only contains elements between 0 and 1 inclusive
|
||||||
static constexpr range<T> unit (void);
|
static constexpr range<T> unit (void)
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
T {0}, T {1}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void sanity (void) const;
|
void sanity (void) const;
|
||||||
};
|
};
|
||||||
@ -101,6 +133,4 @@ namespace util {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "range.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
78
range.ipp
78
range.ipp
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2010-2015 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __UTIL_RANGE_IPP
|
|
||||||
#error
|
|
||||||
#else
|
|
||||||
#define __UTIL_RANGE_IPP
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
template <typename U>
|
|
||||||
U
|
|
||||||
util::range<T>::normalise (T val) const
|
|
||||||
{
|
|
||||||
static_assert (std::is_floating_point<U>::value,
|
|
||||||
"normalise isn't implemented for integer types");
|
|
||||||
|
|
||||||
return static_cast<U> (val - lo) /
|
|
||||||
static_cast<U> ( hi - lo);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
|
||||||
util::range<T>
|
|
||||||
util::range<T>::unlimited (void)
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
std::numeric_limits<T>::has_infinity ? -std::numeric_limits<T>::infinity () :
|
|
||||||
std::numeric_limits<T>::lowest (),
|
|
||||||
std::numeric_limits<T>::has_infinity ? std::numeric_limits<T>::infinity () :
|
|
||||||
std::numeric_limits<T>::max ()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
|
||||||
util::range<T>
|
|
||||||
util::range<T>::max (void)
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
std::numeric_limits<T>::lowest (),
|
|
||||||
std::numeric_limits<T>::max ()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
|
||||||
util::range<T>
|
|
||||||
util::range<T>::unit (void)
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
T {0}, T {1}
|
|
||||||
};
|
|
||||||
}
|
|
17
rational.hpp
17
rational.hpp
@ -51,15 +51,24 @@ namespace util {
|
|||||||
T d;
|
T d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
rational<typename std::common_type<T,U>::type>
|
rational<typename std::common_type<T,U>::type>
|
||||||
operator/ (U, rational<T>);
|
operator/ (U lhs, rational<T> rhs)
|
||||||
|
{
|
||||||
|
return rhs.inverse () * lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
rational<typename std::common_type<T,U>::type>
|
rational<typename std::common_type<T,U>::type>
|
||||||
operator* (U, rational<T>);
|
operator* (U lhs, rational<T> rhs)
|
||||||
}
|
{
|
||||||
|
return rhs * lhs;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#include "rational.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
38
rational.ipp
38
rational.ipp
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __UTIL_RATIONAL_IPP
|
|
||||||
#error
|
|
||||||
#endif
|
|
||||||
#define __UTIL_RATIONAL_IPP
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T, typename U>
|
|
||||||
util::rational<typename std::common_type<T,U>::type>
|
|
||||||
util::operator/ (U lhs, rational<T> rhs)
|
|
||||||
{
|
|
||||||
return rhs.inverse () * lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T, typename U>
|
|
||||||
util::rational<typename std::common_type<T,U>::type>
|
|
||||||
util::operator* (U lhs, rational<T> rhs)
|
|
||||||
{
|
|
||||||
return rhs * lhs;
|
|
||||||
}
|
|
28
region.hpp
28
region.hpp
@ -51,7 +51,14 @@ namespace util {
|
|||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
template <typename U>
|
template <typename U>
|
||||||
constexpr region<S,U> cast (void) const;
|
constexpr region<S,U>
|
||||||
|
cast (void) const
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
p.template cast<U> (),
|
||||||
|
e.template cast<U> ()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
T area (void) const;
|
T area (void) const;
|
||||||
@ -114,8 +121,21 @@ namespace util {
|
|||||||
{ return !(*this == rhs); }
|
{ return !(*this == rhs); }
|
||||||
|
|
||||||
// Utility constants
|
// Utility constants
|
||||||
static constexpr region<S,T> max (void);
|
static constexpr region<S,T> max (void)
|
||||||
static constexpr region<S,T> unit (void);
|
{
|
||||||
|
return {
|
||||||
|
util::point <S,T> {std::numeric_limits<T>::lowest () / 2},
|
||||||
|
util::extent<S,T> {std::numeric_limits<T>::max ()}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr region<S,T> unit (void)
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
point_t::origin (),
|
||||||
|
extent_t {1}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr region<S,T> zero (void)
|
static constexpr region<S,T> zero (void)
|
||||||
{ return { point_t {0}, extent_t {0} }; }
|
{ return { point_t {0}, extent_t {0} }; }
|
||||||
@ -231,6 +251,4 @@ namespace util {
|
|||||||
std::ostream& operator<< (std::ostream&, const util::region<S,T>&);
|
std::ostream& operator<< (std::ostream&, const util::region<S,T>&);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "region.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
59
region.ipp
59
region.ipp
@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2010-2015 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __UTIL_REGION_IPP
|
|
||||||
#error
|
|
||||||
#endif
|
|
||||||
#define __UTIL_REGION_IPP
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t S, typename T>
|
|
||||||
template <typename U>
|
|
||||||
constexpr util::region<S,U>
|
|
||||||
util::region<S,T>::cast (void) const
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
p.template cast<U> (),
|
|
||||||
e.template cast<U> ()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t S, typename T>
|
|
||||||
constexpr
|
|
||||||
util::region<S,T>
|
|
||||||
util::region<S,T>::max (void)
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
util::point <S,T> {std::numeric_limits<T>::lowest () / 2},
|
|
||||||
util::extent<S,T> {std::numeric_limits<T>::max ()}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <size_t S, typename T>
|
|
||||||
constexpr
|
|
||||||
util::region<S,T>
|
|
||||||
util::region<S,T>::unit (void)
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
point_t::origin (),
|
|
||||||
extent_t {1}
|
|
||||||
};
|
|
||||||
}
|
|
124
signal.hpp
124
signal.hpp
@ -14,11 +14,14 @@
|
|||||||
* Copyright 2011-2015 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2011-2015 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_SIGNAL_HPP
|
#ifndef CRUFT_UTIL_SIGNAL_HPP
|
||||||
#define __UTIL_SIGNAL_HPP
|
#define CRUFT_UTIL_SIGNAL_HPP
|
||||||
|
|
||||||
#include "types/traits.hpp"
|
#include "types/traits.hpp"
|
||||||
|
#include "debug.hpp"
|
||||||
|
#include "nocopy.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
@ -77,50 +80,137 @@ namespace util {
|
|||||||
struct cookie;
|
struct cookie;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
signal ();
|
signal () = default;
|
||||||
~signal ();
|
~signal ()
|
||||||
|
{
|
||||||
|
CHECK (empty ());
|
||||||
|
}
|
||||||
|
|
||||||
/// Add a callback to list.
|
/// Add a callback to list.
|
||||||
cookie connect [[nodiscard]] (callback&&);
|
cookie connect [[nodiscard]] (callback &&_cb)
|
||||||
cookie connect [[nodiscard]] (const callback&);
|
{
|
||||||
|
return cookie (
|
||||||
|
m_children.insert (
|
||||||
|
m_children.end (),
|
||||||
|
std::move (_cb)
|
||||||
|
),
|
||||||
|
*this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void disconnect (cookie&);
|
cookie connect [[nodiscard]] (const callback &_cb)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
return cookie (
|
||||||
|
m_children.insert (
|
||||||
|
m_children.end (),
|
||||||
|
std::move (_cb)
|
||||||
|
),
|
||||||
|
*this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void disconnect (cookie &c)
|
||||||
|
{
|
||||||
|
m_children.erase (c.m_position);
|
||||||
|
c.m_position = m_children.end ();
|
||||||
|
}
|
||||||
|
|
||||||
/// Disconnect all callbacks
|
/// Disconnect all callbacks
|
||||||
void clear (void);
|
void clear (void)
|
||||||
|
{
|
||||||
|
m_children.clear ();
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the number of callbacks connected.
|
/// Returns the number of callbacks connected.
|
||||||
size_t size (void) const;
|
size_t size (void) const
|
||||||
bool empty (void) const;
|
{
|
||||||
|
return m_children.size ();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty (void) const
|
||||||
|
{
|
||||||
|
return m_children.empty ();
|
||||||
|
}
|
||||||
|
|
||||||
/// Execute all callbacks
|
/// Execute all callbacks
|
||||||
template <typename ...Args>
|
template <typename ...Args>
|
||||||
R
|
R
|
||||||
operator() (Args&&... tail);
|
operator() (Args&&... tail)
|
||||||
|
{
|
||||||
|
if (m_children.empty ())
|
||||||
|
return R();
|
||||||
|
|
||||||
|
C<F> combiner;
|
||||||
|
return combiner (
|
||||||
|
m_children.begin (),
|
||||||
|
m_children.end (),
|
||||||
|
std::forward<Args> (tail)...
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::list<callback> group;
|
typedef std::list<callback> group;
|
||||||
group m_children;
|
group m_children;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
template <typename F, template <typename> class C>
|
||||||
|
struct signal<F,C>::cookie : public nocopy {
|
||||||
|
cookie (typename group::iterator _position,
|
||||||
|
signal<F,C> &_parent):
|
||||||
|
m_position (_position),
|
||||||
|
m_parent (_parent)
|
||||||
|
{ ; }
|
||||||
|
|
||||||
|
cookie (cookie &&rhs):
|
||||||
|
m_position (rhs.m_position),
|
||||||
|
m_parent (rhs.m_parent)
|
||||||
|
{
|
||||||
|
rhs.m_position = rhs.m_parent.m_children.end ();
|
||||||
|
}
|
||||||
|
|
||||||
|
~cookie ()
|
||||||
|
{
|
||||||
|
if (m_parent.m_children.end () != m_position)
|
||||||
|
m_parent.disconnect (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset (callback &&cb)
|
||||||
|
{
|
||||||
|
*m_position = std::move (cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
typename group::iterator m_position;
|
||||||
|
signal<F,C> &m_parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// wrap a value in a signal and trigger on assignment
|
// wrap a value in a signal and trigger on assignment
|
||||||
//template <typename T, template <typename> class C>
|
//template <typename T, template <typename> class C>
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class value_signal : public signal<void(T)> {
|
class value_signal : public signal<void(T)> {
|
||||||
public:
|
public:
|
||||||
explicit value_signal (T);
|
explicit value_signal (T t): m_value (t) { ; }
|
||||||
value_signal () = default;
|
value_signal () = default;
|
||||||
|
|
||||||
operator const T&() const;
|
operator const T&() const { return m_value; }
|
||||||
|
|
||||||
value_signal<T>& operator= (const T&);
|
value_signal<T>&
|
||||||
|
operator= (const T &t)
|
||||||
|
{
|
||||||
|
m_value = t;
|
||||||
|
(*this) (m_value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T m_value;
|
T m_value;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "signal.ipp"
|
#endif
|
||||||
|
|
||||||
#endif // __SIGNAL_HPP
|
|
||||||
|
202
signal.ipp
202
signal.ipp
@ -1,202 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2011-2015 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __UTIL_SIGNAL_HPP
|
|
||||||
#error
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "debug.hpp"
|
|
||||||
#include "nocopy.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace util {
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename F, template <typename> class C>
|
|
||||||
struct signal<F,C>::cookie : public nocopy {
|
|
||||||
cookie (typename group::iterator, signal<F,C> &parent);
|
|
||||||
cookie (cookie &&rhs);
|
|
||||||
~cookie ();
|
|
||||||
|
|
||||||
void reset (callback &&cb);
|
|
||||||
|
|
||||||
typename group::iterator m_position;
|
|
||||||
signal<F,C> &m_parent;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename F, template <typename> class C>
|
|
||||||
signal<F,C>::cookie::cookie (typename group::iterator _position,
|
|
||||||
signal<F,C> &_parent):
|
|
||||||
m_position (_position),
|
|
||||||
m_parent (_parent)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename F, template <typename> class C>
|
|
||||||
signal<F,C>::cookie::cookie (cookie &&rhs):
|
|
||||||
m_position (rhs.m_position),
|
|
||||||
m_parent (rhs.m_parent)
|
|
||||||
{
|
|
||||||
rhs.m_position = rhs.m_parent.m_children.end ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename F, template <typename> class C>
|
|
||||||
signal<F,C>::cookie::~cookie ()
|
|
||||||
{
|
|
||||||
if (m_parent.m_children.end () != m_position)
|
|
||||||
m_parent.disconnect (*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename F, template <typename> class C>
|
|
||||||
void
|
|
||||||
signal<F,C>::cookie::reset (callback &&cb)
|
|
||||||
{
|
|
||||||
*m_position = std::move (cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename F, template <typename> class C>
|
|
||||||
signal<F,C>::signal ()
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename F, template <typename> class C>
|
|
||||||
signal<F,C>::~signal ()
|
|
||||||
{
|
|
||||||
CHECK (empty ());
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename F, template <typename> class C>
|
|
||||||
typename signal<F,C>::cookie
|
|
||||||
signal<F,C>::connect (const callback &_cb)
|
|
||||||
{
|
|
||||||
return cookie (
|
|
||||||
m_children.insert (
|
|
||||||
m_children.end (),
|
|
||||||
std::move (_cb)
|
|
||||||
),
|
|
||||||
*this
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename F, template <typename> class C>
|
|
||||||
typename signal<F,C>::cookie
|
|
||||||
signal<F,C>::connect (callback &&_cb)
|
|
||||||
{
|
|
||||||
return cookie (
|
|
||||||
m_children.insert (
|
|
||||||
m_children.end (),
|
|
||||||
std::move (_cb)
|
|
||||||
),
|
|
||||||
*this
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename F, template <typename> class C>
|
|
||||||
void
|
|
||||||
signal<F,C>::disconnect (cookie &c)
|
|
||||||
{
|
|
||||||
m_children.erase (c.m_position);
|
|
||||||
c.m_position = m_children.end ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
/// Disconnect all callbacks
|
|
||||||
template <typename F, template <typename> class C>
|
|
||||||
void
|
|
||||||
signal<F,C>::clear (void)
|
|
||||||
{
|
|
||||||
m_children.clear ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
/// Returns the number of callbacks connected.
|
|
||||||
template <typename F, template <typename> class C>
|
|
||||||
size_t
|
|
||||||
signal<F,C>::size (void) const
|
|
||||||
{
|
|
||||||
return m_children.size ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename F, template <typename> class C>
|
|
||||||
bool
|
|
||||||
signal<F,C>::empty (void) const
|
|
||||||
{
|
|
||||||
return m_children.empty ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename F, template <typename> class C>
|
|
||||||
template <typename ...Args>
|
|
||||||
typename signal<F,C>::R
|
|
||||||
signal<F,C>::operator () (Args&&... tail) {
|
|
||||||
if (m_children.empty ())
|
|
||||||
return R();
|
|
||||||
|
|
||||||
C<F> combiner;
|
|
||||||
return combiner (
|
|
||||||
m_children.begin (),
|
|
||||||
m_children.end (),
|
|
||||||
std::forward<Args> (tail)...
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T>
|
|
||||||
value_signal<T>::value_signal (T t):
|
|
||||||
m_value (t)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
value_signal<T>::operator const T&() const
|
|
||||||
{
|
|
||||||
return m_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
value_signal<T>&
|
|
||||||
value_signal<T>::operator= (const T &t)
|
|
||||||
{
|
|
||||||
m_value = t;
|
|
||||||
(*this) (m_value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
29
vector.hpp
29
vector.hpp
@ -35,24 +35,37 @@ namespace util {
|
|||||||
using coord::base<S,T,vector<S,T>>::base;
|
using coord::base<S,T,vector<S,T>>::base;
|
||||||
|
|
||||||
// representations
|
// representations
|
||||||
template <size_t D> vector<D,T> homog (void) const;
|
template <size_t D> vector<D,T> homog (void) const
|
||||||
|
{
|
||||||
|
static_assert (D > S, "reducing size loses data");
|
||||||
|
return (*this).template redim<D> (0.f);
|
||||||
|
}
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
static constexpr vector<S,T> ones (void);
|
static constexpr vector<S,T> ones (void) { return vector<S,T> {1}; }
|
||||||
static constexpr vector<S,T> zeros (void);
|
static constexpr vector<S,T> zeros (void) { return vector<S,T> {0}; }
|
||||||
|
|
||||||
void sanity (void) const;
|
void sanity (void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr
|
constexpr vector<3,T>
|
||||||
vector<3,T>
|
cross (vector<3,T> a, vector<3,T> b)
|
||||||
cross (vector<3,T>, vector<3,T>);
|
{
|
||||||
|
return {
|
||||||
|
a.y * b.z - a.z * b.y,
|
||||||
|
a.z * b.x - a.x * b.z,
|
||||||
|
a.x * b.y - a.y * b.x
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr
|
constexpr
|
||||||
T
|
T
|
||||||
cross (vector<2,T>, vector<2,T>);
|
cross (vector<2,T> a, vector<2,T> b)
|
||||||
|
{
|
||||||
|
return a[0] * b[1] - a[1] * b[0];
|
||||||
|
}
|
||||||
|
|
||||||
// polar/cartesian conversions; assumes (mag, angle) form.
|
// polar/cartesian conversions; assumes (mag, angle) form.
|
||||||
template <typename T> vector<2,T> polar_to_cartesian (vector<2,T>);
|
template <typename T> vector<2,T> polar_to_cartesian (vector<2,T>);
|
||||||
@ -145,7 +158,5 @@ namespace util {
|
|||||||
using vector4b = vector4<bool>;
|
using vector4b = vector4<bool>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "vector.ipp"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
78
vector.ipp
78
vector.ipp
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2011-2016 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(__UTIL_VECTOR_IPP)
|
|
||||||
#error
|
|
||||||
#else
|
|
||||||
#define __UTIL_VECTOR_IPP
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "maths.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t S, typename T>
|
|
||||||
template <size_t D>
|
|
||||||
util::vector<D,T>
|
|
||||||
util::vector<S,T>::homog (void) const
|
|
||||||
{
|
|
||||||
static_assert (D > S, "reducing size loses data");
|
|
||||||
return (*this).template redim<D> (0.f);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
|
||||||
util::vector<3,T>
|
|
||||||
util::cross (util::vector<3,T> a, util::vector<3,T> b)
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
a.y * b.z - a.z * b.y,
|
|
||||||
a.z * b.x - a.x * b.z,
|
|
||||||
a.x * b.y - a.y * b.x
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
constexpr
|
|
||||||
T
|
|
||||||
util::cross (util::vector<2,T> a, util::vector<2,T> b)
|
|
||||||
{
|
|
||||||
return a[0] * b[1] - a[1] * b[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t S, typename T>
|
|
||||||
constexpr
|
|
||||||
util::vector<S,T>
|
|
||||||
util::vector<S,T>::ones (void)
|
|
||||||
{
|
|
||||||
return vector<S,T> {1};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <size_t S, typename T>
|
|
||||||
constexpr
|
|
||||||
util::vector<S,T>
|
|
||||||
util::vector<S,T>::zeros (void)
|
|
||||||
{
|
|
||||||
return vector<S,T> {0};
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user