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
|
||||
posix/dir.cpp
|
||||
posix/dir.hpp
|
||||
posix/dir.ipp
|
||||
posix/except.cpp
|
||||
posix/except.hpp
|
||||
posix/fd.cpp
|
||||
@ -97,7 +96,6 @@ if (NOT WINDOWS)
|
||||
debug_posix.cpp
|
||||
io_posix.cpp
|
||||
io_posix.hpp
|
||||
io_posix.ipp
|
||||
library_posix.hpp
|
||||
library_posix.cpp
|
||||
posix/fwd.hpp
|
||||
@ -116,7 +114,6 @@ if (WINDOWS)
|
||||
exe_win32.cpp
|
||||
io_win32.cpp
|
||||
io_win32.hpp
|
||||
io_win32.ipp
|
||||
library_win32.hpp
|
||||
library_win32.cpp
|
||||
time_win32.cpp
|
||||
@ -138,14 +135,11 @@ list (
|
||||
adapter.cpp
|
||||
algo/sort.cpp
|
||||
algo/sort.hpp
|
||||
algo/sort.ipp
|
||||
alloc/fwd.hpp
|
||||
alloc/allocator.cpp
|
||||
alloc/allocator.hpp
|
||||
alloc/allocator.ipp
|
||||
alloc/arena.cpp
|
||||
alloc/arena.hpp
|
||||
alloc/arena.ipp
|
||||
alloc/raw/affix.cpp
|
||||
alloc/raw/affix.hpp
|
||||
alloc/raw/aligned.hpp
|
||||
@ -173,10 +167,8 @@ list (
|
||||
cast.hpp
|
||||
cmdopt.cpp
|
||||
cmdopt.hpp
|
||||
cmdopt.ipp
|
||||
colour.cpp
|
||||
colour.hpp
|
||||
colour.ipp
|
||||
coord/fwd.hpp
|
||||
coord/base.hpp
|
||||
coord.hpp
|
||||
@ -187,7 +179,6 @@ list (
|
||||
coord/traits.hpp
|
||||
debug.cpp
|
||||
debug.hpp
|
||||
debug.ipp
|
||||
encode/base.cpp
|
||||
encode/base.hpp
|
||||
endian.cpp
|
||||
@ -195,7 +186,6 @@ list (
|
||||
exe.hpp
|
||||
extent.cpp
|
||||
extent.hpp
|
||||
extent.ipp
|
||||
fixed.cpp
|
||||
fixed.hpp
|
||||
float.cpp
|
||||
@ -211,7 +201,6 @@ list (
|
||||
geom/cylinder.hpp
|
||||
geom/ellipse.cpp
|
||||
geom/ellipse.hpp
|
||||
geom/ellipse.ipp
|
||||
geom/iostream.cpp
|
||||
geom/iostream.hpp
|
||||
geom/ops.hpp
|
||||
@ -258,7 +247,6 @@ list (
|
||||
introspection.hpp
|
||||
io.cpp
|
||||
io.hpp
|
||||
io.ipp
|
||||
iterator.hpp
|
||||
job/queue.cpp
|
||||
job/queue.hpp
|
||||
@ -286,7 +274,6 @@ list (
|
||||
library.hpp
|
||||
log.cpp
|
||||
log.hpp
|
||||
log.ipp
|
||||
maths.cpp
|
||||
maths.hpp
|
||||
matrix.cpp
|
||||
@ -304,18 +291,14 @@ list (
|
||||
platform.hpp
|
||||
point.cpp
|
||||
point.hpp
|
||||
point.ipp
|
||||
pointer.hpp
|
||||
polynomial.cpp
|
||||
polynomial.hpp
|
||||
polynomial.ipp
|
||||
pool.cpp
|
||||
pool.hpp
|
||||
pool.ipp
|
||||
preprocessor.hpp
|
||||
quaternion.cpp
|
||||
quaternion.hpp
|
||||
quaternion.ipp
|
||||
raii.hpp
|
||||
rand/lcg.cpp
|
||||
rand/lcg.hpp
|
||||
@ -327,20 +310,16 @@ list (
|
||||
random.hpp
|
||||
range.cpp
|
||||
range.hpp
|
||||
range.ipp
|
||||
rational.cpp
|
||||
rational.hpp
|
||||
rational.ipp
|
||||
region.cpp
|
||||
region.hpp
|
||||
region.ipp
|
||||
roots/bisection.hpp
|
||||
sarray.cpp
|
||||
sarray.hpp
|
||||
si.cpp
|
||||
signal.cpp
|
||||
signal.hpp
|
||||
signal.ipp
|
||||
si.hpp
|
||||
stats.cpp
|
||||
stats.hpp
|
||||
@ -378,7 +357,6 @@ list (
|
||||
variadic.hpp
|
||||
vector.cpp
|
||||
vector.hpp
|
||||
vector.ipp
|
||||
version.cpp
|
||||
version.hpp
|
||||
view.cpp
|
||||
|
116
algo/sort.hpp
116
algo/sort.hpp
@ -18,7 +18,39 @@
|
||||
#ifndef 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 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
|
||||
// ...tail by moving values to the positions described by the mapping of
|
||||
@ -31,7 +63,38 @@ namespace cruft::util::sort {
|
||||
// the operation.
|
||||
template <typename IndexIt, typename ValueIt, typename ...OtherIt>
|
||||
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
|
||||
@ -41,9 +104,54 @@ namespace cruft::util::sort {
|
||||
// sorting is performed in-place and will invariably allocate memory.
|
||||
template <typename RandomIt, class Comparator, class ...Args>
|
||||
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
|
||||
|
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
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
// C++11 allocator concept conformant allocator adaptor, going from our
|
||||
// allocator interface to that of the STL and friends.
|
||||
namespace util::alloc {
|
||||
template <class B, class T>
|
||||
template <class BackingT, class ValueT>
|
||||
class allocator {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef ValueT value_type;
|
||||
|
||||
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:
|
||||
B &m_backing;
|
||||
BackingT &m_backing;
|
||||
};
|
||||
}
|
||||
|
||||
#include "allocator.ipp"
|
||||
|
||||
#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>
|
||||
class arena {
|
||||
public:
|
||||
explicit arena (T &store);
|
||||
explicit arena (T &store):
|
||||
m_store (store)
|
||||
{ ; }
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
template <typename U, typename ...Args>
|
||||
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>
|
||||
void
|
||||
release (U*);
|
||||
release (U *u)
|
||||
{
|
||||
u->~U ();
|
||||
m_store.deallocate (reinterpret_cast<void*> (u), sizeof (U));
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
template <typename U>
|
||||
@ -68,6 +89,4 @@ namespace util::alloc {
|
||||
};
|
||||
}
|
||||
|
||||
#include "arena.ipp"
|
||||
|
||||
#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
|
||||
#define __UTIL_CMDLINE_HPP
|
||||
#ifndef CRUFT_UTIL_CMDLINE_HPP
|
||||
#define CRUFT_UTIL_CMDLINE_HPP
|
||||
|
||||
#include "introspection.hpp"
|
||||
#include "iterator.hpp"
|
||||
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
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 {
|
||||
class base {
|
||||
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>
|
||||
class value : public base {
|
||||
public:
|
||||
explicit value (T&);
|
||||
explicit value (T &_data): m_data (_data) { }
|
||||
explicit value (T&&) = delete;
|
||||
|
||||
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&;
|
||||
T& data (void) &;
|
||||
T& data (T) &;
|
||||
is >> m_data;
|
||||
} catch (...) {
|
||||
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:
|
||||
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>
|
||||
class count : public value<T> {
|
||||
@ -132,11 +285,29 @@ namespace util::cmdopt {
|
||||
T& add (char shortname,
|
||||
std::string longname,
|
||||
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>
|
||||
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);
|
||||
|
||||
@ -160,56 +331,6 @@ namespace util::cmdopt {
|
||||
>
|
||||
> 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
|
||||
|
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;
|
||||
}
|
||||
|
||||
#include "colour.ipp"
|
||||
|
||||
#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>
|
||||
constexpr
|
||||
void panic [[noreturn]] (const char (&fmt)[N], const Args&...);
|
||||
constexpr void
|
||||
panic [[noreturn]] (const char (&fmt)[N], const Args&... args)
|
||||
{
|
||||
util::debug::detail::panic (fmt, args...);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
constexpr void not_implemented [[noreturn]] (void);
|
||||
constexpr void not_implemented [[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]] (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]] (const char *msg) { not_implemented (msg); }
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
constexpr void unreachable [[noreturn]] (void);
|
||||
constexpr void unreachable [[noreturn]] (const char*);
|
||||
constexpr void
|
||||
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 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,
|
||||
// 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>
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_EXTENT_HPP
|
||||
#define __UTIL_EXTENT_HPP
|
||||
#ifndef CRUFT_UTIL_EXTENT_HPP
|
||||
#define CRUFT_UTIL_EXTENT_HPP
|
||||
|
||||
#include "coord/fwd.hpp"
|
||||
#include "coord/base.hpp"
|
||||
@ -36,12 +36,34 @@ namespace util {
|
||||
extent () = default;
|
||||
explicit extent (::util::vector<S,T>);
|
||||
|
||||
constexpr T area (void) const;
|
||||
constexpr T diameter (void) const;
|
||||
constexpr T
|
||||
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>
|
||||
constexpr
|
||||
U aspect (void) const;
|
||||
U aspect (void) const
|
||||
{
|
||||
return static_cast<U> (this->w) / this->h;
|
||||
}
|
||||
|
||||
/// tests whether a point would lie within:
|
||||
/// region { origin, *this }, inclusive of borders.
|
||||
@ -70,8 +92,20 @@ namespace util {
|
||||
|
||||
bool empty (void) const;
|
||||
|
||||
static constexpr ::util::extent<S,T> max (void);
|
||||
static constexpr ::util::extent<S,T> min (void);
|
||||
static constexpr
|
||||
::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>
|
||||
@ -147,6 +181,4 @@ namespace util {
|
||||
}
|
||||
|
||||
|
||||
#include "extent.ipp"
|
||||
|
||||
#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 {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <size_t S, typename T>
|
||||
template <size_t S, typename ValueT>
|
||||
struct ellipse {
|
||||
util::point<S,T> origin;
|
||||
util::vector<S,T> radius;
|
||||
util::point<S,ValueT> origin;
|
||||
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
|
||||
|
@ -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 {
|
||||
explicit indented (const T &_data);
|
||||
const T &data;
|
||||
explicit indented (const ValueT &_data):
|
||||
data (_data)
|
||||
{ ; }
|
||||
|
||||
const ValueT &data;
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
indented<T>
|
||||
make_indented (const T &_data);
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
template <typename ValueT>
|
||||
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"
|
||||
#endif
|
||||
|
||||
#include "io.ipp"
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
#include "io_posix.ipp"
|
||||
|
||||
#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>
|
||||
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>
|
||||
util::view<T*>
|
||||
as_view () &;
|
||||
as_view () &
|
||||
{
|
||||
return {
|
||||
reinterpret_cast<T *> (begin ()),
|
||||
reinterpret_cast<T *> (align (end (), alignof(T)))
|
||||
};
|
||||
}
|
||||
|
||||
private:
|
||||
::util::win32::handle m_file;
|
||||
@ -102,6 +114,4 @@ namespace util {
|
||||
typedef detail::win32::mapped_file mapped_file;
|
||||
}
|
||||
|
||||
#include "io_win32.ipp"
|
||||
|
||||
#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>
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_POINT_HPP
|
||||
#define __UTIL_POINT_HPP
|
||||
#ifndef CRUFT_UTIL_POINT_HPP
|
||||
#define CRUFT_UTIL_POINT_HPP
|
||||
|
||||
#include "vector.hpp"
|
||||
#include "coord.hpp"
|
||||
#include "maths.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
|
||||
namespace util {
|
||||
@ -35,7 +37,29 @@ namespace util {
|
||||
vector<S,T> to (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
|
||||
@ -54,7 +78,10 @@ namespace util {
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
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.
|
||||
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.
|
||||
///
|
||||
/// useful if you just need to compare distances because it avoids a sqrt
|
||||
/// operation.
|
||||
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
|
||||
/// distance between `a' and `b' where travel is only allowed beween the 8
|
||||
/// grid neighbours and cost for diagonals is proportionally larger than
|
||||
/// cardinal movement. see also: chebyshev.
|
||||
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
|
||||
/// distance where travel is only allowed along cardinal directions.
|
||||
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
|
||||
/// shortest distance between `a' and `b' where travel is only allowed
|
||||
/// between the 8 grid neighbours and cost for diagonals is the same as
|
||||
/// cardinal movement. see also: octile.
|
||||
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
|
||||
template <typename T> using point1 = point<1,T>;
|
||||
@ -122,6 +191,4 @@ namespace util {
|
||||
typedef point4<int> point4i;
|
||||
}
|
||||
|
||||
#include "point.ipp"
|
||||
|
||||
#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>
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_POLYNOMIAL_HPP
|
||||
#define __UTIL_POLYNOMIAL_HPP
|
||||
#ifndef CRUFT_UTIL_POLYNOMIAL_HPP
|
||||
#define CRUFT_UTIL_POLYNOMIAL_HPP
|
||||
|
||||
#include <array>
|
||||
#include <cstdlib>
|
||||
@ -30,9 +30,18 @@ namespace util::polynomial {
|
||||
|
||||
template <size_t S, typename T, typename U>
|
||||
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
|
||||
|
@ -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>
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_POOL_HPP
|
||||
#define __UTIL_POOL_HPP
|
||||
#ifndef CRUFT_UTIL_POOL_HPP
|
||||
#define CRUFT_UTIL_POOL_HPP
|
||||
|
||||
#include "nocopy.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
|
||||
namespace util {
|
||||
/// a simple pre-allocated pool for storage of PODs.
|
||||
@ -42,19 +44,85 @@ namespace util {
|
||||
|
||||
public:
|
||||
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
|
||||
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;
|
||||
size_t size (void) const;
|
||||
bool empty (void) const;
|
||||
// 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;
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
#define __UTIL_POSIX_DIR_HPP
|
||||
|
||||
#include "except.hpp"
|
||||
|
||||
#include <cerrno>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <functional>
|
||||
#include <experimental/filesystem>
|
||||
|
||||
|
||||
namespace util::posix {
|
||||
struct dir {
|
||||
public:
|
||||
@ -30,13 +34,18 @@ namespace util::posix {
|
||||
|
||||
operator DIR* (void);
|
||||
|
||||
template <typename ...Args>
|
||||
// run a callback for each entry in the provided directory
|
||||
template <typename FunctionT, typename ...Args>
|
||||
void
|
||||
scan (std::function<void(const std::experimental::filesystem::path&, Args&...)>, Args&...);
|
||||
scan (FunctionT &&func, Args&&...args)
|
||||
{
|
||||
rewind ();
|
||||
|
||||
template <typename ...Args>
|
||||
void
|
||||
scan (void (*) (const std::experimental::filesystem::path&, Args&...), Args&...);
|
||||
for (dirent *cursor; errno = 0, cursor = readdir (m_handle); )
|
||||
func (cursor->d_name, args...);
|
||||
|
||||
error::try_code ();
|
||||
}
|
||||
|
||||
//entry begin (void) { rewind (); return { readdir (m_handle), m_handle }; }
|
||||
//entry end (void) { return { nullptr, m_handle }; }
|
||||
@ -48,6 +57,4 @@ namespace util::posix {
|
||||
};
|
||||
}
|
||||
|
||||
#include "dir.ipp"
|
||||
|
||||
#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 "maths.hpp"
|
||||
#include "vector.hpp"
|
||||
#include "matrix.hpp"
|
||||
|
||||
@ -48,10 +49,15 @@ namespace util {
|
||||
|
||||
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>
|
||||
struct arity<quaternion<T>,void>
|
||||
:std::integral_constant<std::size_t, 4>
|
||||
@ -68,22 +74,43 @@ namespace util {
|
||||
template <typename T>
|
||||
constexpr
|
||||
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>
|
||||
constexpr
|
||||
T
|
||||
norm (quaternion<T>);
|
||||
norm (quaternion<T> q)
|
||||
{
|
||||
return std::sqrt (norm2 (q));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
constexpr
|
||||
bool
|
||||
is_normalised (quaternion<T>);
|
||||
is_normalised (quaternion<T> q)
|
||||
{
|
||||
return almost_equal (T{1}, norm2 (q));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
constexpr
|
||||
quaternion<T>
|
||||
normalised (quaternion<T>);
|
||||
normalised (quaternion<T> q)
|
||||
{
|
||||
return q / norm (q);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -97,32 +124,46 @@ namespace util {
|
||||
quaternion<T>
|
||||
operator* (quaternion<T>, quaternion<T>);
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
quaternion<T>&
|
||||
operator*= (quaternion<T>&, quaternion<T>);
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
quaternion<T>
|
||||
operator/ (quaternion<T>, quaternion<T>);
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
constexpr
|
||||
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>
|
||||
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>
|
||||
bool almost_equal (quaternion<T>, quaternion<T>);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
typedef quaternion<float> quaternionf;
|
||||
typedef quaternion<double> quaterniond;
|
||||
@ -134,6 +175,4 @@ namespace util {
|
||||
operator<< (std::ostream&, quaternion<T>);
|
||||
}
|
||||
|
||||
#include "quaternion.ipp"
|
||||
|
||||
#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 <ostream>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
namespace util {
|
||||
/**
|
||||
@ -55,7 +57,15 @@ namespace util {
|
||||
/// bounds, it is the caller's responsibility to clamp the result if
|
||||
/// needed.
|
||||
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) const;
|
||||
@ -78,10 +88,32 @@ namespace util {
|
||||
{ return !(*this == rhs); }
|
||||
|
||||
/// A range which is guaranteed to contain all elements type T
|
||||
static constexpr range<T> unlimited (void);
|
||||
static constexpr range<T> max (void);
|
||||
static constexpr 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 ()
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
static constexpr range<T> unit (void);
|
||||
static constexpr range<T> unit (void)
|
||||
{
|
||||
return {
|
||||
T {0}, T {1}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void sanity (void) const;
|
||||
};
|
||||
@ -101,6 +133,4 @@ namespace util {
|
||||
}
|
||||
}
|
||||
|
||||
#include "range.ipp"
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename U>
|
||||
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>
|
||||
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
|
||||
|
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>
|
||||
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;
|
||||
@ -114,8 +121,21 @@ namespace util {
|
||||
{ return !(*this == rhs); }
|
||||
|
||||
// Utility constants
|
||||
static constexpr region<S,T> max (void);
|
||||
static constexpr region<S,T> unit (void);
|
||||
static constexpr 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 ()}
|
||||
};
|
||||
}
|
||||
|
||||
static constexpr region<S,T> unit (void)
|
||||
{
|
||||
return {
|
||||
point_t::origin (),
|
||||
extent_t {1}
|
||||
};
|
||||
}
|
||||
|
||||
static constexpr region<S,T> zero (void)
|
||||
{ return { point_t {0}, extent_t {0} }; }
|
||||
@ -231,6 +251,4 @@ namespace util {
|
||||
std::ostream& operator<< (std::ostream&, const util::region<S,T>&);
|
||||
}
|
||||
|
||||
#include "region.ipp"
|
||||
|
||||
#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>
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_SIGNAL_HPP
|
||||
#define __UTIL_SIGNAL_HPP
|
||||
#ifndef CRUFT_UTIL_SIGNAL_HPP
|
||||
#define CRUFT_UTIL_SIGNAL_HPP
|
||||
|
||||
#include "types/traits.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "nocopy.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
|
||||
@ -77,50 +80,137 @@ namespace util {
|
||||
struct cookie;
|
||||
|
||||
public:
|
||||
signal ();
|
||||
~signal ();
|
||||
signal () = default;
|
||||
~signal ()
|
||||
{
|
||||
CHECK (empty ());
|
||||
}
|
||||
|
||||
/// Add a callback to list.
|
||||
cookie connect [[nodiscard]] (callback&&);
|
||||
cookie connect [[nodiscard]] (const callback&);
|
||||
cookie connect [[nodiscard]] (callback &&_cb)
|
||||
{
|
||||
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
|
||||
void clear (void);
|
||||
void clear (void)
|
||||
{
|
||||
m_children.clear ();
|
||||
}
|
||||
|
||||
/// Returns the number of callbacks connected.
|
||||
size_t size (void) const;
|
||||
bool empty (void) const;
|
||||
size_t size (void) const
|
||||
{
|
||||
return m_children.size ();
|
||||
}
|
||||
|
||||
bool empty (void) const
|
||||
{
|
||||
return m_children.empty ();
|
||||
}
|
||||
|
||||
/// Execute all callbacks
|
||||
template <typename ...Args>
|
||||
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:
|
||||
typedef std::list<callback> group;
|
||||
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
|
||||
//template <typename T, template <typename> class C>
|
||||
template <typename T>
|
||||
class value_signal : public signal<void(T)> {
|
||||
public:
|
||||
explicit value_signal (T);
|
||||
explicit value_signal (T t): m_value (t) { ; }
|
||||
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:
|
||||
T m_value;
|
||||
};
|
||||
}
|
||||
|
||||
#include "signal.ipp"
|
||||
|
||||
#endif // __SIGNAL_HPP
|
||||
#endif
|
||||
|
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;
|
||||
|
||||
// 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
|
||||
static constexpr vector<S,T> ones (void);
|
||||
static constexpr vector<S,T> zeros (void);
|
||||
static constexpr vector<S,T> ones (void) { return vector<S,T> {1}; }
|
||||
static constexpr vector<S,T> zeros (void) { return vector<S,T> {0}; }
|
||||
|
||||
void sanity (void) const;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr
|
||||
vector<3,T>
|
||||
cross (vector<3,T>, vector<3,T>);
|
||||
constexpr vector<3,T>
|
||||
cross (vector<3,T> a, 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
|
||||
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.
|
||||
template <typename T> vector<2,T> polar_to_cartesian (vector<2,T>);
|
||||
@ -145,7 +158,5 @@ namespace util {
|
||||
using vector4b = vector4<bool>;
|
||||
}
|
||||
|
||||
#include "vector.ipp"
|
||||
|
||||
#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