diff --git a/CMakeLists.txt b/CMakeLists.txt index a4cbf600..684465ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/algo/sort.hpp b/algo/sort.hpp index 09c07037..2e9b9258 100644 --- a/algo/sort.hpp +++ b/algo/sort.hpp @@ -18,7 +18,39 @@ #ifndef CRUFT_UTIL_ALGO_SORT_HPP #define CRUFT_UTIL_ALGO_SORT_HPP +#include "../debug.hpp" + +#include +#include +#include +#include + + namespace cruft::util::sort { + namespace detail { + template + void + index_swap (IndexA a, IndexB b, RandomIt value) + { + static_assert( + std::is_base_of< + std::random_access_iterator_tag, + typename std::iterator_traits::iterator_category + >::value + ); + + std::swap (value[a], value[b]); + } + + template + 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 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::iterator_category + >::value + ); + + static_assert ( + std::is_base_of< + std::random_access_iterator_tag, + typename std::iterator_traits::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 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::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 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 diff --git a/algo/sort.ipp b/algo/sort.ipp deleted file mode 100644 index f48a8e2f..00000000 --- a/algo/sort.ipp +++ /dev/null @@ -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 - */ - -#ifdef CRUFT_UTIL_ALGO_SORT_IPP -#error -#endif - -#define CRUFT_UTIL_ALGO_SORT_IPP - -#include -#include -#include -#include -#include -#include -#include - -#include "../debug.hpp" -#include "../tuple.hpp" - - -/////////////////////////////////////////////////////////////////////////////// -namespace cruft::util::sort::detail { - template - void - index_swap (IndexA a, IndexB b, RandomIt value) - { - static_assert( - std::is_base_of< - std::random_access_iterator_tag, - typename std::iterator_traits::iterator_category - >::value - ); - - std::swap (value[a], value[b]); - } - - template - void - index_swap (IndexA a, IndexB b, RandomIt value, Tail ...tail) - { - index_swap (a, b, value); - index_swap (a, b, tail...); - }; -} - - -/////////////////////////////////////////////////////////////////////////////// -template -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::iterator_category - >::value - ); - - static_assert ( - std::is_base_of< - std::random_access_iterator_tag, - typename std::iterator_traits::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 -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::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 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...); -}; diff --git a/alloc/allocator.hpp b/alloc/allocator.hpp index 1b4babc0..ef5d0e61 100644 --- a/alloc/allocator.hpp +++ b/alloc/allocator.hpp @@ -18,26 +18,38 @@ #define __UTIL_ALLOC_ALLOCATOR_HPP #include +#include // C++11 allocator concept conformant allocator adaptor, going from our // allocator interface to that of the STL and friends. namespace util::alloc { - template + template class allocator { public: - typedef T value_type; + typedef ValueT value_type; template - explicit allocator (Args&& ...args); + explicit allocator (Args&& ...args): + m_backing (std::forward (args)...) + { ; } + + + ValueT* allocate (size_t count) + { + return m_backing.template allocate (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 diff --git a/alloc/allocator.ipp b/alloc/allocator.ipp deleted file mode 100644 index 2cb45793..00000000 --- a/alloc/allocator.ipp +++ /dev/null @@ -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 - */ - - -#ifdef __UTIL_ALLOC_ALLOCATOR_IPP -#error -#endif - -#define __UTIL_ALLOC_ALLOCATOR_IPP - -#include - -/////////////////////////////////////////////////////////////////////////////// -template -template -util::alloc::allocator::allocator (Args&& ...args): - m_backing (std::forward (args)...) -{ ; } - - -/////////////////////////////////////////////////////////////////////////////// -template -T* -util::alloc::allocator::allocate (std::size_t count) -{ - return m_backing.template allocate (count); -} - - -//----------------------------------------------------------------------------- -template -void -util::alloc::allocator::deallocate (T *t, std::size_t count) -{ - return m_backing.template deallocate (t, count); -} diff --git a/alloc/arena.hpp b/alloc/arena.hpp index f9ca676a..55e13317 100644 --- a/alloc/arena.hpp +++ b/alloc/arena.hpp @@ -28,17 +28,38 @@ namespace util::alloc { template class arena { public: - explicit arena (T &store); + explicit arena (T &store): + m_store (store) + { ; } //--------------------------------------------------------------------- template U* - acquire (Args&&...); + acquire (Args&&... args) + { + U *data = reinterpret_cast ( + m_store.allocate (sizeof (U), alignof (U)) + ); + + try { + new (data) U (std::forward (args)...); + } catch (...) { + m_store.deallocate (data, sizeof (U)); + throw; + } + + return data; + } //--------------------------------------------------------------------- template void - release (U*); + release (U *u) + { + u->~U (); + m_store.deallocate (reinterpret_cast (u), sizeof (U)); + } + //--------------------------------------------------------------------- template @@ -68,6 +89,4 @@ namespace util::alloc { }; } -#include "arena.ipp" - #endif diff --git a/alloc/arena.ipp b/alloc/arena.ipp deleted file mode 100644 index dddfb3f2..00000000 --- a/alloc/arena.ipp +++ /dev/null @@ -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 - */ - -#ifdef __UTIL_ALLOC_ARENA_IPP -#error -#endif - -#define __UTIL_ALLOC_ARENA_IPP - - -/////////////////////////////////////////////////////////////////////////////// -template -util::alloc::arena::arena (T &store): - m_store (store) -{ ; } - - -/////////////////////////////////////////////////////////////////////////////// -template -template -U* -util::alloc::arena::acquire (Args&& ...args) -{ - U *data = reinterpret_cast ( - m_store.allocate (sizeof (U), alignof (U)) - ); - - try { - new (data) U (std::forward (args)...); - } catch (...) { - m_store.deallocate (data, sizeof (U)); - throw; - } - - return data; -} - - -//----------------------------------------------------------------------------- -template -template -void -util::alloc::arena::release (U *u) -{ - u->~U (); - m_store.deallocate (reinterpret_cast (u), sizeof (U)); -} - - diff --git a/cmdopt.hpp b/cmdopt.hpp index 9dd29c7e..ba3abe8b 100644 --- a/cmdopt.hpp +++ b/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 #include #include -#include #include #include #include +#include /////////////////////////////////////////////////////////////////////////////// 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 + std::enable_if_t::value, const std::string&> + value_example (void) + { + static const std::string EXAMPLE = + std::string {"<"} + + std::string {to_string ()} + + std::string {">"}; + + return EXAMPLE; + } + + template + std::enable_if_t::value, const std::string&> + value_example (void) + { + static const std::string EXAMPLE = [] (void) { + std::ostringstream os; + std::copy (std::cbegin (enum_traits::names), + std::cend (enum_traits::names), + infix_iterator (os, "|")); + return os.str (); + } (); + return EXAMPLE; + } + } + + template 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 (); + } + + 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::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 class count : public value { @@ -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 (std::forward (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 T& - append (std::string description, Args&&...); + append (std::string description, Args&&...args) + { + auto handler = std::make_unique (std::forward (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 diff --git a/cmdopt.ipp b/cmdopt.ipp deleted file mode 100644 index 4153b850..00000000 --- a/cmdopt.ipp +++ /dev/null @@ -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 - */ - -#ifdef __UTIL_CMDLINE_IPP -#error -#endif -#define __UTIL_CMDLINE_IPP - -#include -#include -#include - -#include "introspection.hpp" -#include "iterator.hpp" - -namespace util::cmdopt { - /////////////////////////////////////////////////////////////////////////// - template - option::value::value (T &_data): - m_data (_data) - { ; } - - - //------------------------------------------------------------------------- - template - inline void - option::value::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::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 - std::enable_if_t::value, const std::string&> - value_example (void) - { - static const std::string EXAMPLE = - std::string {"<"} + - std::string {to_string ()} + - std::string {">"}; - - return EXAMPLE; - } - - template - std::enable_if_t::value, const std::string&> - value_example (void) - { - static const std::string EXAMPLE = [] (void) { - std::ostringstream os; - std::copy (std::cbegin (enum_traits::names), - std::cend (enum_traits::names), - infix_iterator (os, "|")); - return os.str (); - } (); - return EXAMPLE; - } - } - - - //------------------------------------------------------------------------- - template - const std::string& - option::value::example (void) const - { - return detail::value_example (); - } - - - //----------------------------------------------------------------------------- - template - const T& - option::value::data (void) const& - { - return m_data; - } - - - //----------------------------------------------------------------------------- - template - T& - option::value::data (void) & - { - return m_data; - } - - - //----------------------------------------------------------------------------- - template - T& - option::value::data (T _data) & - { - return m_data = _data; - } - - - /////////////////////////////////////////////////////////////////////////// - template - T& - parser::add (char shortname, - std::string longname, - std::string description, - Args&&... args) - { - auto handler = std::make_unique (std::forward (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 - T& - parser::append (std::string description, - Args &&...args) - { - auto handler = std::make_unique (std::forward (args)...); - auto &ref = *handler; - m_positional.push_back (ref); - m_options.emplace_back (std::move (description), std::move (handler)); - return ref; - } -} diff --git a/colour.hpp b/colour.hpp index 3c7273eb..7d436108 100644 --- a/colour.hpp +++ b/colour.hpp @@ -115,6 +115,4 @@ namespace util { constexpr auto is_colour_v = is_colour::value; } -#include "colour.ipp" - #endif diff --git a/colour.ipp b/colour.ipp deleted file mode 100644 index 0f334864..00000000 --- a/colour.ipp +++ /dev/null @@ -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 - */ - -#ifdef __UTIL_COLOUR_IPP -#error -#endif -#define __UTIL_COLOUR_IPP - diff --git a/debug.hpp b/debug.hpp index 8911dec4..718e395f 100644 --- a/debug.hpp +++ b/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 + 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 -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 diff --git a/debug.ipp b/debug.ipp deleted file mode 100644 index 6e29671d..00000000 --- a/debug.ipp +++ /dev/null @@ -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 - */ - -#ifdef __UTIL_DEBUG_IPP -#error -#endif - -#define __UTIL_DEBUG_IPP - -#include "backtrace.hpp" -#include "format.hpp" - -#include -#include - - -/////////////////////////////////////////////////////////////////////////////// -namespace util::debug::detail { - void panic [[noreturn]] (const char *msg); - - template - 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 -constexpr -void -panic [[noreturn]] (const char (&fmt)[N], const Args& ...args) -{ - util::debug::detail::panic (fmt, args...); -} diff --git a/extent.hpp b/extent.hpp index c23bac95..4f154755 100644 --- a/extent.hpp +++ b/extent.hpp @@ -14,8 +14,8 @@ * Copyright 2010-2017 Danny Robson */ -#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); - 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 ()); + } + + constexpr T + diameter (void) const + { + return static_cast ( + std::sqrt ( + std::accumulate (std::begin (this->data), + std::end (this->data), + T {0}, + [] (auto a, auto b) { return a + b * b; }) + ) + ); + } template constexpr - U aspect (void) const; + U aspect (void) const + { + return static_cast (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 max (void); - static constexpr ::util::extent min (void); + static constexpr + ::util::extent max (void) + { + return extent { + std::numeric_limits::max () + }; + } + + + static constexpr + ::util::extent min (void) + { + return extent { 0 }; + } }; template @@ -147,6 +181,4 @@ namespace util { } -#include "extent.ipp" - #endif diff --git a/extent.ipp b/extent.ipp deleted file mode 100644 index 8c725523..00000000 --- a/extent.ipp +++ /dev/null @@ -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 - */ - - -#ifdef __UTIL_EXTENT_IPP -#error -#endif - -#define __UTIL_EXTENT_IPP - -#include -#include - - -/////////////////////////////////////////////////////////////////////////////// -template -constexpr -T -util::extent::diameter (void) const -{ - return static_cast ( - std::sqrt ( - std::accumulate (std::begin (this->data), - std::end (this->data), - T {0}, - [] (auto a, auto b) { return a + b * b; }) - ) - ); -} - - -/////////////////////////////////////////////////////////////////////////////// -template -constexpr -T -util::extent::area (void) const -{ - return std::accumulate (std::begin (this->data), - std::end (this->data), - T {1}, - std::multiplies ()); -} - - -/////////////////////////////////////////////////////////////////////////////// -template -template -constexpr -U -util::extent::aspect (void) const -{ - return static_cast (this->w) / this->h; -} - - -/////////////////////////////////////////////////////////////////////////////// -template -constexpr -util::extent -util::extent::max (void) -{ - return extent { - std::numeric_limits::max () - }; -} - - -//----------------------------------------------------------------------------- -template -constexpr -util::extent -util::extent::min (void) -{ - return extent { 0 }; -} diff --git a/geom/ellipse.hpp b/geom/ellipse.hpp index 0dc6aa69..6e8a8ad4 100644 --- a/geom/ellipse.hpp +++ b/geom/ellipse.hpp @@ -24,13 +24,37 @@ namespace util::geom { /////////////////////////////////////////////////////////////////////////// - template + template struct ellipse { - util::point origin; - util::vector radius; + util::point origin; + util::vector radius; }; } -#include "ellipse.ipp" + +/////////////////////////////////////////////////////////////////////////////// +#include "sample.hpp" + +#include +#include + +namespace util::geom { + template 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 dist; + + float phi = dist (g) * 2 * PI; + float rho = std::sqrt (dist (g)); + + return util::point<2,T> { + std::cos (phi), + std::sin (phi) + } * rho * k.radius + k.origin.template as (); + } + }; +} #endif diff --git a/geom/ellipse.ipp b/geom/ellipse.ipp deleted file mode 100644 index 69305603..00000000 --- a/geom/ellipse.ipp +++ /dev/null @@ -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 - */ - -#if defined(__UTIL_GEOM_ELLIPSE_IPP) -#error -#endif - -#define __UTIL_GEOM_ELLIPSE_IPP - -#include "sample.hpp" - -#include -#include - -/////////////////////////////////////////////////////////////////////////////// -namespace util::geom { - template 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 dist; - - float phi = dist (g) * 2 * PI; - float rho = std::sqrt (dist (g)); - - return util::point<2,T> { - std::cos (phi), - std::sin (phi) - } * rho * k.radius + k.origin.template as (); - } - }; -} diff --git a/io.hpp b/io.hpp index 1eca94e1..45ba73ed 100644 --- a/io.hpp +++ b/io.hpp @@ -94,23 +94,27 @@ namespace util { }; //------------------------------------------------------------------------- - template + // a wrapper type that implicitly indents a single value when passed to an + // ostream operator. + template struct indented { - explicit indented (const T &_data); - const T &data; + explicit indented (const ValueT &_data): + data (_data) + { ; } + + const ValueT &data; }; //------------------------------------------------------------------------- - template - indented - make_indented (const T &_data); - - - //------------------------------------------------------------------------- - template + template std::ostream& - operator<< (std::ostream &os, const util::indented &v); + operator<< (std::ostream &os, const util::indented &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 diff --git a/io.ipp b/io.ipp deleted file mode 100644 index 2c3b1737..00000000 --- a/io.ipp +++ /dev/null @@ -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 - */ - - -#ifdef __UTIL_IO_IPP -#error "multiple inclusions" -#else -#define __UTIL__IO_IPP -#endif - -namespace util { - //------------------------------------------------------------------------- - template - indented::indented (const T &_data): - data (_data) - { ; } - - - //------------------------------------------------------------------------- - template - indented - make_indented (const T &_data) { - return indented (_data); - } - - - //------------------------------------------------------------------------- - template - std::ostream& - operator<< (std::ostream &os, const util::indented &&v) { - util::indenter raii (os); - os << v.data; - return os; - } -} diff --git a/io_posix.hpp b/io_posix.hpp index 9409bf95..5b5301f8 100644 --- a/io_posix.hpp +++ b/io_posix.hpp @@ -81,6 +81,4 @@ namespace util { typedef detail::posix::mapped_file mapped_file; } -#include "io_posix.ipp" - #endif diff --git a/io_posix.ipp b/io_posix.ipp deleted file mode 100644 index b6f991c8..00000000 --- a/io_posix.ipp +++ /dev/null @@ -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 - */ - -#ifdef __UTIL_IO_POSIX_IPP -#error -#endif - -#define __UTIL_IO_POSIX_IPP - -#include "pointer.hpp" diff --git a/io_win32.hpp b/io_win32.hpp index eef0e3b8..356d222a 100644 --- a/io_win32.hpp +++ b/io_win32.hpp @@ -84,11 +84,23 @@ namespace util { template util::view*> - as_view () const &; + as_view () const & + { + return { + reinterpret_cast (cbegin ()), + reinterpret_cast (align (cend (), alignof (T))) + }; + } template util::view - as_view () &; + as_view () & + { + return { + reinterpret_cast (begin ()), + reinterpret_cast (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 diff --git a/io_win32.ipp b/io_win32.ipp deleted file mode 100644 index ce4b53a6..00000000 --- a/io_win32.ipp +++ /dev/null @@ -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 - */ - - -#ifdef __UTIL_IO_WIN32_IPP -#error -#endif - -#define __UTIL_IO_WIN32_IPP - -#include "pointer.hpp" - - -/////////////////////////////////////////////////////////////////////////////// -template -util::view*> -util::detail::win32::mapped_file::as_view (void) const& -{ - return { - reinterpret_cast (cbegin ()), - reinterpret_cast (align (cend (), alignof (T))) - }; -} - - -//----------------------------------------------------------------------------- -template -util::view -util::detail::win32::mapped_file::as_view (void) & -{ - return { - reinterpret_cast (begin ()), - reinterpret_cast (align (end (), alignof(T))) - }; -} diff --git a/log.hpp b/log.hpp index 8868c919..8d939555 100644 --- a/log.hpp +++ b/log.hpp @@ -135,7 +135,5 @@ namespace util { }; } -#include "log.ipp" - #endif diff --git a/log.ipp b/log.ipp deleted file mode 100644 index 2027df36..00000000 --- a/log.ipp +++ /dev/null @@ -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 - */ diff --git a/point.hpp b/point.hpp index c29b9876..8026cd5c 100644 --- a/point.hpp +++ b/point.hpp @@ -14,12 +14,14 @@ * Copyright 2011-2016 Danny Robson */ -#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 #include namespace util { @@ -35,7 +37,29 @@ namespace util { vector to (point) const; vector from (point) const; - template point homog (void) const; + /// expand point to use homogenous coordinates of a higher dimension. + /// ie, fill with (0,..,0,1) + template + point + homog (void) const + { + static_assert (D > S, "homog will not overwrite data"); + + point 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 origin (void); + point origin (void) + { + return point {0}; + } /////////////////////////////////////////////////////////////////////// @@ -66,33 +93,75 @@ namespace util { /// computes the exact euclidean distance between two points. template - typename std::common_type::type distance (point, point); + typename std::common_type::type + distance (point a, point b) + { + using type_t = typename std::common_type::type; + static_assert (std::is_floating_point::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 - constexpr typename std::common_type::type distance2 (point, point); + constexpr typename std::common_type::type + distance2 (point a, point 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 std::common_type::type octile (point<2,T>, point<2,U>); + typename std::common_type::type + octile (point<2,T> a, point<2,U> b) + { + using type_t = typename std::common_type::type; + static_assert (!std::is_integral::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 - constexpr typename std::common_type::type manhattan (point, point); + constexpr typename std::common_type::type + manhattan (point a, point 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 - constexpr typename std::common_type::type chebyshev (point, point); + constexpr typename std::common_type::type + chebyshev (point a, point b) + { + return util::max (abs (a - b)); + } // Convenience typedefs template using point1 = point<1,T>; @@ -122,6 +191,4 @@ namespace util { typedef point4 point4i; } -#include "point.ipp" - #endif // __UTIL_POINT_HPP diff --git a/point.ipp b/point.ipp deleted file mode 100644 index d3fab7db..00000000 --- a/point.ipp +++ /dev/null @@ -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 - */ - -#include "maths.hpp" - -#include - - -/////////////////////////////////////////////////////////////////////////////// -/// expand point to use homogenous coordinates of a higher dimension. -/// ie, fill with (0,..,0,1) -template -template -util::point -util::point::homog (void) const -{ - static_assert (D > S, "homog will not overwrite data"); - - point 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 -constexpr -util::point -util::point::origin (void) -{ - return point {0}; -} - - -/////////////////////////////////////////////////////////////////////////////// -template -typename std::common_type::type -util::distance (point a, point b) -{ - using type_t = typename std::common_type::type; - static_assert (std::is_floating_point::value, - "sqrt likely requires fractional types"); - - return std::sqrt (distance2 (a, b)); -} - - -/////////////////////////////////////////////////////////////////////////////// -template -constexpr typename std::common_type::type -util::distance2 (point a, point b) -{ - return sum (pow2 (a - b)); -} - - -/////////////////////////////////////////////////////////////////////////////// -template -typename std::common_type::type -util::octile (point2 a, point2 b) -{ - using type_t = typename std::common_type::type; - static_assert (!std::is_integral::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 -constexpr typename std::common_type::type -util::manhattan (point a, point b) -{ - return sum (abs (a - b)); -} - - -/////////////////////////////////////////////////////////////////////////////// -template -constexpr typename std::common_type::type -util::chebyshev(point a, point b) -{ - return util::max (abs (a - b)); -} diff --git a/polynomial.hpp b/polynomial.hpp index 25d8ea62..5e8ed6d0 100644 --- a/polynomial.hpp +++ b/polynomial.hpp @@ -14,8 +14,8 @@ * Copyright 2015 Danny Robson */ -#ifndef __UTIL_POLYNOMIAL_HPP -#define __UTIL_POLYNOMIAL_HPP +#ifndef CRUFT_UTIL_POLYNOMIAL_HPP +#define CRUFT_UTIL_POLYNOMIAL_HPP #include #include @@ -30,9 +30,18 @@ namespace util::polynomial { template T - eval (std::array, U x); + eval (std::array 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 diff --git a/polynomial.ipp b/polynomial.ipp deleted file mode 100644 index 89e6747e..00000000 --- a/polynomial.ipp +++ /dev/null @@ -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 - */ - - -#ifdef __UTIL_POLYNOMIAL_IPP -#error "twice included ipp" -#endif - -#define __UTIL_POLYNOMIAL_IPP - - -/////////////////////////////////////////////////////////////////////////////// -template -T -util::polynomial::eval (const std::array 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; -} diff --git a/pool.hpp b/pool.hpp index d3ea16ef..c65923c6 100644 --- a/pool.hpp +++ b/pool.hpp @@ -14,12 +14,14 @@ * Copyright 2011-2016 Danny Robson */ -#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 +#include 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'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 (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 - 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 (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 (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 diff --git a/pool.ipp b/pool.ipp deleted file mode 100644 index 34a53f1f..00000000 --- a/pool.ipp +++ /dev/null @@ -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 - */ - -#ifdef __UTIL_POOL_IPP -#error -#endif - -#define __UTIL_POOL_IPP - -#include "debug.hpp" - -#include -#include -#include - - -namespace util { - //------------------------------------------------------------------------- - template - pool::pool (unsigned int _capacity): - m_capacity (_capacity), - m_size (0u) - { - static_assert (sizeof (T) >= sizeof (uintptr_t), - "pool'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 (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 - pool::~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 - size_t - pool::capacity (void) const - { - return m_capacity; - } - - - //------------------------------------------------------------------------- - template - size_t - pool::size (void) const - { - return m_size; - } - - - //------------------------------------------------------------------------- - template - bool - pool::empty (void) const - { - return m_size == m_capacity; - } - - - //------------------------------------------------------------------------- - template - template - T* - pool::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 (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 - void - pool::release (T *data) - { - CHECK_NEZ (m_size); - - data->~T(); - node *newnode = reinterpret_cast (data); - - newnode->_node = m_next; - m_next = newnode; - m_size--; - } -} - - diff --git a/posix/dir.hpp b/posix/dir.hpp index 8476a12e..2e5b39de 100644 --- a/posix/dir.hpp +++ b/posix/dir.hpp @@ -17,11 +17,15 @@ #ifndef __UTIL_POSIX_DIR_HPP #define __UTIL_POSIX_DIR_HPP +#include "except.hpp" + +#include #include #include #include + namespace util::posix { struct dir { public: @@ -30,13 +34,18 @@ namespace util::posix { operator DIR* (void); - template + // run a callback for each entry in the provided directory + template void - scan (std::function, Args&...); + scan (FunctionT &&func, Args&&...args) + { + rewind (); - template - 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 diff --git a/posix/dir.ipp b/posix/dir.ipp deleted file mode 100644 index a2e05053..00000000 --- a/posix/dir.ipp +++ /dev/null @@ -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 - */ - -#include "except.hpp" - -#include - - -/////////////////////////////////////////////////////////////////////////////// -template -void -util::posix::dir::scan(std::function cb, Args &...args) -{ - rewind (); - - for (dirent *cursor; errno = 0, cursor = readdir (m_handle); ) - cb (cursor->d_name, args...); - - error::try_code (); -} - - -//----------------------------------------------------------------------------- -template -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 (); -} diff --git a/quaternion.hpp b/quaternion.hpp index 101f8699..78fc4fbc 100644 --- a/quaternion.hpp +++ b/quaternion.hpp @@ -19,6 +19,7 @@ #include "coord/traits.hpp" +#include "maths.hpp" #include "vector.hpp" #include "matrix.hpp" @@ -48,10 +49,15 @@ namespace util { matrix4 as_matrix (void) const; - static constexpr quaternion identity (void); + static constexpr + quaternion identity (void) + { + return { 1, 0, 0, 0 }; + } }; + //------------------------------------------------------------------------- template struct arity,void> :std::integral_constant @@ -68,22 +74,43 @@ namespace util { template constexpr T - norm2 (quaternion); + norm2 (quaternion q) + { + return q.w * q.w + + q.x * q.x + + q.y * q.y + + q.z * q.z; + } + + //------------------------------------------------------------------------- template constexpr T - norm (quaternion); + norm (quaternion q) + { + return std::sqrt (norm2 (q)); + } + + //------------------------------------------------------------------------- template constexpr bool - is_normalised (quaternion); + is_normalised (quaternion q) + { + return almost_equal (T{1}, norm2 (q)); + } + + //------------------------------------------------------------------------- template constexpr quaternion - normalised (quaternion); + normalised (quaternion q) + { + return q / norm (q); + } /////////////////////////////////////////////////////////////////////////// @@ -97,32 +124,46 @@ namespace util { quaternion operator* (quaternion, quaternion); + //------------------------------------------------------------------------- template quaternion& operator*= (quaternion&, quaternion); + //------------------------------------------------------------------------- template quaternion operator/ (quaternion, quaternion); + //------------------------------------------------------------------------- template constexpr quaternion - operator/ (quaternion, T); + operator/ (quaternion q, T t) + { + return { q.w / t, q.x / t, q.y / t, q.z / t }; + } /////////////////////////////////////////////////////////////////////////// template constexpr - bool operator== (quaternion, quaternion); + bool operator== (quaternion a, quaternion 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 bool almost_equal (quaternion, quaternion); + /////////////////////////////////////////////////////////////////////////// typedef quaternion quaternionf; typedef quaternion quaterniond; @@ -134,6 +175,4 @@ namespace util { operator<< (std::ostream&, quaternion); } -#include "quaternion.ipp" - #endif diff --git a/quaternion.ipp b/quaternion.ipp deleted file mode 100644 index 93e4e11f..00000000 --- a/quaternion.ipp +++ /dev/null @@ -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 - */ - -#if defined(CRUFT_UTIL_QUATERNION_IPP) -#error -#endif - -#define CRUFT_UTIL_QUATERNION_IPP - -#include - - -/////////////////////////////////////////////////////////////////////////////// -template -constexpr -util::quaternion -util::quaternion::identity (void) -{ - return { 1, 0, 0, 0 }; -} - - -/////////////////////////////////////////////////////////////////////////////// -template -constexpr -T -util::norm2 (quaternion q) -{ - return q.w * q.w + - q.x * q.x + - q.y * q.y + - q.z * q.z; -} - - -//----------------------------------------------------------------------------- -template -constexpr -T -util::norm (quaternion q) -{ - return std::sqrt (norm2 (q)); -} - - -//----------------------------------------------------------------------------- -template -constexpr -bool -util::is_normalised (quaternion q) -{ - return almost_equal (T{1}, norm2 (q)); -} - - -//----------------------------------------------------------------------------- -template -constexpr -util::quaternion -util::normalised (quaternion q) -{ - return q / norm (q); -} - - -/////////////////////////////////////////////////////////////////////////////// -template -constexpr -util::quaternion -util::operator/ (quaternion q, T t) -{ - return { q.w / t, q.x / t, q.y / t, q.z / t }; -} - - -/////////////////////////////////////////////////////////////////////////////// -template -constexpr -bool -util::operator== (quaternion a, quaternion 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); -} diff --git a/range.hpp b/range.hpp index 2a7983ec..9cc031d2 100644 --- a/range.hpp +++ b/range.hpp @@ -20,6 +20,8 @@ #include #include +#include +#include namespace util { /** @@ -55,7 +57,15 @@ namespace util { /// bounds, it is the caller's responsibility to clamp the result if /// needed. template - U normalise (T val) const; + U + normalise (T val) const + { + static_assert (std::is_floating_point::value, + "normalise isn't implemented for integer types"); + + return static_cast (val - lo) / + static_cast ( 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 unlimited (void); - static constexpr range max (void); + static constexpr range unlimited (void) + { + return { + std::numeric_limits::has_infinity ? -std::numeric_limits::infinity () : + std::numeric_limits::lowest (), + std::numeric_limits::has_infinity ? std::numeric_limits::infinity () : + std::numeric_limits::max () + }; + } + + static constexpr range max (void) + { + return { + std::numeric_limits::lowest (), + std::numeric_limits::max () + }; + } + /// A range which only contains elements between 0 and 1 inclusive - static constexpr range unit (void); + static constexpr range unit (void) + { + return { + T {0}, T {1} + }; + } + void sanity (void) const; }; @@ -101,6 +133,4 @@ namespace util { } } -#include "range.ipp" - #endif diff --git a/range.ipp b/range.ipp deleted file mode 100644 index f5709792..00000000 --- a/range.ipp +++ /dev/null @@ -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 - */ - -#ifdef __UTIL_RANGE_IPP -#error -#else -#define __UTIL_RANGE_IPP -#endif - -#include -#include - - -//----------------------------------------------------------------------------- -template -template -U -util::range::normalise (T val) const -{ - static_assert (std::is_floating_point::value, - "normalise isn't implemented for integer types"); - - return static_cast (val - lo) / - static_cast ( hi - lo); -} - - -/////////////////////////////////////////////////////////////////////////////// -template -constexpr -util::range -util::range::unlimited (void) -{ - return { - std::numeric_limits::has_infinity ? -std::numeric_limits::infinity () : - std::numeric_limits::lowest (), - std::numeric_limits::has_infinity ? std::numeric_limits::infinity () : - std::numeric_limits::max () - }; -} - - -//----------------------------------------------------------------------------- -template -constexpr -util::range -util::range::max (void) -{ - return { - std::numeric_limits::lowest (), - std::numeric_limits::max () - }; -} - - -//----------------------------------------------------------------------------- -template -constexpr -util::range -util::range::unit (void) -{ - return { - T {0}, T {1} - }; -} diff --git a/rational.hpp b/rational.hpp index f5fb5e29..04758506 100644 --- a/rational.hpp +++ b/rational.hpp @@ -51,15 +51,24 @@ namespace util { T d; }; + + /////////////////////////////////////////////////////////////////////////// template rational::type> - operator/ (U, rational); + operator/ (U lhs, rational rhs) + { + return rhs.inverse () * lhs; + } + + //------------------------------------------------------------------------- template rational::type> - operator* (U, rational); -} + operator* (U lhs, rational rhs) + { + return rhs * lhs; + } +}; -#include "rational.ipp" #endif diff --git a/rational.ipp b/rational.ipp deleted file mode 100644 index 7412af26..00000000 --- a/rational.ipp +++ /dev/null @@ -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 - */ - -#ifdef __UTIL_RATIONAL_IPP -#error -#endif -#define __UTIL_RATIONAL_IPP - - -//----------------------------------------------------------------------------- -template -util::rational::type> -util::operator/ (U lhs, rational rhs) -{ - return rhs.inverse () * lhs; -} - - -//----------------------------------------------------------------------------- -template -util::rational::type> -util::operator* (U lhs, rational rhs) -{ - return rhs * lhs; -} diff --git a/region.hpp b/region.hpp index 7299b726..710b6d8f 100644 --- a/region.hpp +++ b/region.hpp @@ -51,7 +51,14 @@ namespace util { //--------------------------------------------------------------------- template - constexpr region cast (void) const; + constexpr region + cast (void) const + { + return { + p.template cast (), + e.template cast () + }; + } //--------------------------------------------------------------------- T area (void) const; @@ -114,8 +121,21 @@ namespace util { { return !(*this == rhs); } // Utility constants - static constexpr region max (void); - static constexpr region unit (void); + static constexpr region max (void) + { + return { + util::point {std::numeric_limits::lowest () / 2}, + util::extent {std::numeric_limits::max ()} + }; + } + + static constexpr region unit (void) + { + return { + point_t::origin (), + extent_t {1} + }; + } static constexpr region zero (void) { return { point_t {0}, extent_t {0} }; } @@ -231,6 +251,4 @@ namespace util { std::ostream& operator<< (std::ostream&, const util::region&); } -#include "region.ipp" - #endif diff --git a/region.ipp b/region.ipp deleted file mode 100644 index 2209f445..00000000 --- a/region.ipp +++ /dev/null @@ -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 - */ - -#ifdef __UTIL_REGION_IPP -#error -#endif -#define __UTIL_REGION_IPP - - -/////////////////////////////////////////////////////////////////////////////// -template -template -constexpr util::region -util::region::cast (void) const -{ - return { - p.template cast (), - e.template cast () - }; -} - - -/////////////////////////////////////////////////////////////////////////////// -template -constexpr -util::region -util::region::max (void) -{ - return { - util::point {std::numeric_limits::lowest () / 2}, - util::extent {std::numeric_limits::max ()} - }; -} - - -//----------------------------------------------------------------------------- -template -constexpr -util::region -util::region::unit (void) -{ - return { - point_t::origin (), - extent_t {1} - }; -} diff --git a/signal.hpp b/signal.hpp index d176c28b..0ad382ea 100644 --- a/signal.hpp +++ b/signal.hpp @@ -14,11 +14,14 @@ * Copyright 2011-2015 Danny Robson */ -#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 #include #include @@ -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 R - operator() (Args&&... tail); + operator() (Args&&... tail) + { + if (m_children.empty ()) + return R(); + + C combiner; + return combiner ( + m_children.begin (), + m_children.end (), + std::forward (tail)... + ); + } private: typedef std::list group; group m_children; }; + + /////////////////////////////////////////////////////////////////////////// + template class C> + struct signal::cookie : public nocopy { + cookie (typename group::iterator _position, + signal &_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 &m_parent; + }; + + + /////////////////////////////////////////////////////////////////////////// // wrap a value in a signal and trigger on assignment //template class C> template class value_signal : public signal { 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& operator= (const T&); + value_signal& + operator= (const T &t) + { + m_value = t; + (*this) (m_value); + return *this; + } private: T m_value; }; } -#include "signal.ipp" - -#endif // __SIGNAL_HPP +#endif diff --git a/signal.ipp b/signal.ipp deleted file mode 100644 index 73cdef12..00000000 --- a/signal.ipp +++ /dev/null @@ -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 - */ - -#ifndef __UTIL_SIGNAL_HPP -#error -#endif - -#include "debug.hpp" -#include "nocopy.hpp" - -#include - -namespace util { - /////////////////////////////////////////////////////////////////////////// - template class C> - struct signal::cookie : public nocopy { - cookie (typename group::iterator, signal &parent); - cookie (cookie &&rhs); - ~cookie (); - - void reset (callback &&cb); - - typename group::iterator m_position; - signal &m_parent; - }; - - - /////////////////////////////////////////////////////////////////////////// - template class C> - signal::cookie::cookie (typename group::iterator _position, - signal &_parent): - m_position (_position), - m_parent (_parent) - { ; } - - - //------------------------------------------------------------------------- - template class C> - signal::cookie::cookie (cookie &&rhs): - m_position (rhs.m_position), - m_parent (rhs.m_parent) - { - rhs.m_position = rhs.m_parent.m_children.end (); - } - - - //------------------------------------------------------------------------- - template class C> - signal::cookie::~cookie () - { - if (m_parent.m_children.end () != m_position) - m_parent.disconnect (*this); - } - - - /////////////////////////////////////////////////////////////////////////// - template class C> - void - signal::cookie::reset (callback &&cb) - { - *m_position = std::move (cb); - } - - - /////////////////////////////////////////////////////////////////////////// - template class C> - signal::signal () - { ; } - - - //------------------------------------------------------------------------- - template class C> - signal::~signal () - { - CHECK (empty ()); - } - - /////////////////////////////////////////////////////////////////////////// - template class C> - typename signal::cookie - signal::connect (const callback &_cb) - { - return cookie ( - m_children.insert ( - m_children.end (), - std::move (_cb) - ), - *this - ); - } - - - //------------------------------------------------------------------------- - template class C> - typename signal::cookie - signal::connect (callback &&_cb) - { - return cookie ( - m_children.insert ( - m_children.end (), - std::move (_cb) - ), - *this - ); - } - - - //------------------------------------------------------------------------- - template class C> - void - signal::disconnect (cookie &c) - { - m_children.erase (c.m_position); - c.m_position = m_children.end (); - } - - - //------------------------------------------------------------------------- - /// Disconnect all callbacks - template class C> - void - signal::clear (void) - { - m_children.clear (); - } - - - /////////////////////////////////////////////////////////////////////////// - /// Returns the number of callbacks connected. - template class C> - size_t - signal::size (void) const - { - return m_children.size (); - } - - - //------------------------------------------------------------------------- - template class C> - bool - signal::empty (void) const - { - return m_children.empty (); - } - - - /////////////////////////////////////////////////////////////////////////// - template class C> - template - typename signal::R - signal::operator () (Args&&... tail) { - if (m_children.empty ()) - return R(); - - C combiner; - return combiner ( - m_children.begin (), - m_children.end (), - std::forward (tail)... - ); - } - - - /////////////////////////////////////////////////////////////////////////// - template - value_signal::value_signal (T t): - m_value (t) - { ; } - - - //------------------------------------------------------------------------- - template - value_signal::operator const T&() const - { - return m_value; - } - - - //------------------------------------------------------------------------- - template - value_signal& - value_signal::operator= (const T &t) - { - m_value = t; - (*this) (m_value); - return *this; - } -} - diff --git a/vector.hpp b/vector.hpp index 29c3aece..8116d10b 100644 --- a/vector.hpp +++ b/vector.hpp @@ -35,24 +35,37 @@ namespace util { using coord::base>::base; // representations - template vector homog (void) const; + template vector homog (void) const + { + static_assert (D > S, "reducing size loses data"); + return (*this).template redim (0.f); + } // constants - static constexpr vector ones (void); - static constexpr vector zeros (void); + static constexpr vector ones (void) { return vector {1}; } + static constexpr vector zeros (void) { return vector {0}; } void sanity (void) const; }; template - 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 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 vector<2,T> polar_to_cartesian (vector<2,T>); @@ -145,7 +158,5 @@ namespace util { using vector4b = vector4; } -#include "vector.ipp" - #endif diff --git a/vector.ipp b/vector.ipp deleted file mode 100644 index a390fd7e..00000000 --- a/vector.ipp +++ /dev/null @@ -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 - */ - -#if defined(__UTIL_VECTOR_IPP) -#error -#else -#define __UTIL_VECTOR_IPP -#endif - -#include "maths.hpp" - - -/////////////////////////////////////////////////////////////////////////////// -template -template -util::vector -util::vector::homog (void) const -{ - static_assert (D > S, "reducing size loses data"); - return (*this).template redim (0.f); -} - - -/////////////////////////////////////////////////////////////////////////////// -template -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 -constexpr -T -util::cross (util::vector<2,T> a, util::vector<2,T> b) -{ - return a[0] * b[1] - a[1] * b[0]; -} - - -/////////////////////////////////////////////////////////////////////////////// -template -constexpr -util::vector -util::vector::ones (void) -{ - return vector {1}; -} - - -//----------------------------------------------------------------------------- -template -constexpr -util::vector -util::vector::zeros (void) -{ - return vector {0}; -}