coord: add general vector comparison function

This commit is contained in:
Danny Robson 2017-08-27 12:32:00 +10:00
parent e7fe5d044a
commit 3799135236
5 changed files with 87 additions and 27 deletions

View File

@ -185,5 +185,6 @@ namespace util::coord {
}; };
} }
#include "../vector.hpp"
#endif #endif

View File

@ -11,11 +11,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
* Copyright 2012-2016 Danny Robson <danny@nerdcruft.net> * Copyright 2012-2017 Danny Robson <danny@nerdcruft.net>
*/ */
#ifndef __UTIL_COORDS_OPS #ifndef CRUFT_UTIL_COORDS_OPS
#define __UTIL_COORDS_OPS #define CRUFT_UTIL_COORDS_OPS
#include "./fwd.hpp" #include "./fwd.hpp"
@ -28,6 +28,7 @@
#include <cmath> #include <cmath>
#include <cstdlib> #include <cstdlib>
#include <iterator> #include <iterator>
#include <functional>
namespace util { namespace util {
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
@ -293,6 +294,63 @@ namespace util {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// logic operators // logic operators
namespace detail {
template <
std::size_t S,
typename T,
template <std::size_t,typename> class K,
typename FuncT,
typename = std::enable_if_t<
is_coord_v<K<S,T>>,
void
>,
std::size_t ...Indices
>
constexpr auto
compare (FuncT &&func, std::index_sequence<Indices...>, const K<S,T> a, const K<S,T> b)
{
return vector<S,bool> {
std::invoke (func, a[Indices], b[Indices])...
};
}
}
//-------------------------------------------------------------------------
template <
std::size_t S,
typename T,
template <std::size_t,typename> class K,
typename FuncT,
typename = std::enable_if_t<
is_coord_v<K<S,T>>,
void
>,
typename Indices = std::make_index_sequence<S>
>
constexpr auto
compare (const K<S,T> a, const K<S,T> b, FuncT &&func)
{
return detail::compare (std::forward<FuncT> (func), Indices{}, a, b);
}
//-------------------------------------------------------------------------
template <
std::size_t S,
typename T,
template <std::size_t,typename> class K,
typename = std::enable_if_t<
is_coord_v<K<S,T>>,
void
>
>
constexpr auto
compare (const K<S,T> a, const K<S,T> b)
{
return compare (a, b, std::equal_to<T> {});
}
/// elementwise equality operator /// elementwise equality operator
template < template <
@ -303,16 +361,10 @@ namespace util {
is_coord_v<K<S,T>>, void is_coord_v<K<S,T>>, void
> >
> >
constexpr constexpr bool
bool
operator== (const K<S,T> a, const K<S,T> b) operator== (const K<S,T> a, const K<S,T> b)
{ {
bool (*predicate)(const T&, const T&) = almost_equal; return all (compare (a, b, std::equal_to<T> {}));
return std::equal (std::cbegin (a),
std::cend (a),
std::cbegin (b),
predicate);
} }
///------------------------------------------------------------------------ ///------------------------------------------------------------------------
@ -325,11 +377,10 @@ namespace util {
is_coord_v<K<S,T>>, void is_coord_v<K<S,T>>, void
> >
> >
constexpr constexpr bool
bool operator!= (const K<S,T> a, const K<S,T> b)
operator!= (K<S,T> a, K<S,T> b)
{ {
return !(a == b); return any (compare (a, b, std::not_equal_to<T> {}));
} }
@ -909,6 +960,7 @@ namespace util {
SCALAR_OP(>) SCALAR_OP(>)
SCALAR_OP(<=) SCALAR_OP(<=)
SCALAR_OP(>=) SCALAR_OP(>=)
SCALAR_OP(==)
SCALAR_OP(&&) SCALAR_OP(&&)
SCALAR_OP(||) SCALAR_OP(||)
@ -1026,6 +1078,7 @@ namespace util {
return k; return k;
} }
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
template < template <
size_t S, size_t S,

View File

@ -23,13 +23,6 @@ main (void)
tap.expect_eq (-p, util::point2i { 1, -2 }, "unary point negation"); tap.expect_eq (-p, util::point2i { 1, -2 }, "unary point negation");
tap.expect_eq ( p, p, "unary point addition"); tap.expect_eq ( p, p, "unary point addition");
tap.expect (
std::is_same<
bool,
decltype(!p)::value_type
>::value,
"unary point boolean negation has type bool"
);
auto vec = util::vector4f (0.5f); auto vec = util::vector4f (0.5f);
tap.expect_eq (vec, util::normalised (vec), "normalisation of normalised vector"); tap.expect_eq (vec, util::normalised (vec), "normalisation of normalised vector");

View File

@ -203,7 +203,14 @@ main (void)
euler = mod (euler + 4 * PI2, PI2); euler = mod (euler + 4 * PI2, PI2);
truth = mod (truth + 4 * PI2, PI2); truth = mod (truth + 4 * PI2, PI2);
tap.expect_eq (truth, euler, "matrix-to-euler, %s", t.msg); tap.expect (
all (compare (
truth, euler,
[] (auto a, auto b) { return util::almost_equal (a, b); }
)),
"matrix-to-euler, %s",
t.msg
);
} }
} }

View File

@ -11,15 +11,21 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
* Copyright 2011-2016 Danny Robson <danny@nerdcruft.net> * Copyright 2011-2017 Danny Robson <danny@nerdcruft.net>
*/ */
#ifndef __UTIL_VECTOR_HPP #ifndef CRUFT_UTIL_VECTOR_HPP
#define __UTIL_VECTOR_HPP #define CRUFT_UTIL_VECTOR_HPP
#include "./coord/fwd.hpp"
#include "./coord.hpp"
#include "coord.hpp"
#include "json/fwd.hpp" #include "json/fwd.hpp"
#include <cstddef>
///////////////////////////////////////////////////////////////////////////////
namespace util { namespace util {
template <size_t S, typename T> template <size_t S, typename T>
struct vector : public coord::base<S,T,vector,coord::xyzw,coord::stpq> struct vector : public coord::base<S,T,vector,coord::xyzw,coord::stpq>