Skip to content

Commit

Permalink
gtest, double, improve recursive api
Browse files Browse the repository at this point in the history
  • Loading branch information
Ubpa committed Jun 14, 2021
1 parent 381dad3 commit 891223b
Show file tree
Hide file tree
Showing 28 changed files with 256 additions and 130 deletions.
11 changes: 10 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)

project(UGM VERSION 0.7.3)
project(UGM VERSION 0.7.4)
message(STATUS "[Project] ${PROJECT_NAME}")

include(cmake/InitUCMake.cmake)
Expand All @@ -13,6 +13,15 @@ option(Ubpa_UGM_UseSSE_4_1 "use SSE 4.1" ON)
message(STATUS "Ubpa_UGM_UseSIMD : ${Ubpa_UGM_UseSIMD}")
message(STATUS "Ubpa_UGM_UseSSE_4_1 : ${Ubpa_UGM_UseSSE_4_1}")

if(Ubpa_BuildTest_UGM)
find_package(GTest QUIET)
if(GTest_FOUND)
message(NOTICE "GTest Found")
else()
message(NOTICE "GTest not Found, so we ignore some targets depending on GTest")
endif()
endif()

Ubpa_AddDep(UTemplate 0.7.2)

Ubpa_AddSubDirsRec(include)
Expand Down
15 changes: 0 additions & 15 deletions include/UGM/Interfaces/IArray/IArray1D_Util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,6 @@ namespace Ubpa {
using F = SI_ImplTraits_F<Impl>;
static constexpr size_t N = SI_ImplTraits_N<Impl>;

Impl abs() const noexcept {
const auto& x = static_cast<const Impl&>(*this);
#ifdef UBPA_UGM_USE_SIMD
if constexpr (SI_ImplTraits_SupportSIMD<Impl>)
return _mm_abs_ps(x);
else
#endif // UBPA_UGM_USE_SIMD
{
Impl rst;
for (size_t i = 0; i < N; i++)
rst[i] = std::abs(x[i]);
return rst;
}
}

T& min_component() noexcept {
return (*this)[min_dim()];
}
Expand Down
40 changes: 37 additions & 3 deletions include/UGM/Interfaces/IArray/IArrayUtil.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ namespace Ubpa {

bool is_all_zero() const noexcept {
for (size_t i = 0; i < N; i++) {
if (!is_zero((*this)[i]))
if (!Ubpa::is_all_zero((*this)[i]))
return false;
}
return true;
}

bool has_nan() const noexcept {
bool is_any_nan() const noexcept {
for (size_t i = 0; i < N; i++) {
if (is_nan((*this)[i]))
if (Ubpa::is_any_nan((*this)[i]))
return true;
}
return false;
Expand All @@ -55,6 +55,25 @@ namespace Ubpa {
return lerp(x, y, t);
}

static Impl hadamard_product(const Impl& x, const Impl& y) noexcept {
#ifdef UBPA_UGM_USE_SIMD
if constexpr (SI_ImplTraits_SupportSIMD<Impl>)
return _mm_mul_ps(x, y);
else
#endif // UBPA_UGM_USE_SIMD
{
Impl rst;
for (size_t i = 0; i < N; i++)
rst[i] = Ubpa::hadamard_product(x[i], y[i]);
return rst;
}
}

Impl hadamard_product(const Impl& y) const noexcept {
const auto& x = static_cast<const Impl&>(*this);
return hadamard_product(x, y);
}

static Impl mid(const Impl& x, const Impl& y) noexcept {
return lerp(x, y, static_cast<F>(0.5));
}
Expand Down Expand Up @@ -92,6 +111,21 @@ namespace Ubpa {
return rst;
}
}

Impl abs() const noexcept {
const auto& x = static_cast<const Impl&>(*this);
#ifdef UBPA_UGM_USE_SIMD
if constexpr (SI_ImplTraits_SupportSIMD<Impl>)
return _mm_abs_ps(x);
else
#endif // UBPA_UGM_USE_SIMD
{
Impl rst;
for (size_t i = 0; i < N; i++)
rst[i] = Ubpa::abs(x[i]);
return rst;
}
}
};
}

Expand Down
20 changes: 12 additions & 8 deletions include/UGM/Interfaces/IScalarMul.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ namespace Ubpa {

//static_assert(std::is_floating_point_v<F>);
template<typename U>
static constexpr bool support = std::is_same_v<U, F> && details::IScalarMul_::need_mul<Impl, U>;
static constexpr bool support = (std::is_floating_point_v<F> && std::is_floating_point_v<U> ||
!std::is_floating_point_v<F> && std::is_same_v<U, F>)
&& details::IScalarMul_::need_mul<Impl, U>;

using Base::Base;

Expand All @@ -28,29 +30,31 @@ namespace Ubpa {

template<typename U, std::enable_if_t<support<U>>* = nullptr>
Impl operator*(U k) const noexcept {
return static_cast<const Impl*>(this)->impl_scalar_mul(k);
return static_cast<const Impl*>(this)->impl_scalar_mul(static_cast<F>(k));
}

template<typename U, std::enable_if_t<support<U>>* = nullptr>
Impl& operator*=(U k) noexcept {
return static_cast<Impl*>(this)->impl_scalar_mul_to_self(k);
return static_cast<Impl*>(this)->impl_scalar_mul_to_self(static_cast<F>(k));
}

template<typename U, std::enable_if_t<support<U>>* = nullptr>
friend Impl operator*(U k, const Impl& x) noexcept {
return x * k;
}

Impl operator/(F k) const noexcept {
assert(k != static_cast<F>(0));
F inverseK = static_cast<F>(1) / k;
template<typename U, std::enable_if_t<support<U>>* = nullptr>
Impl operator/(U k) const noexcept {
assert(k != static_cast<U>(0));
F inverseK = static_cast<F>(1) / static_cast<F>(k);
const auto& x = static_cast<const Impl&>(*this);
return x * inverseK;
}

Impl& operator/=(F k) noexcept {
template<typename U, std::enable_if_t<support<U>>* = nullptr>
Impl& operator/=(U k) noexcept {
assert(k != static_cast<F>(0));
F inverseK = static_cast<F>(1) / k;
F inverseK = static_cast<F>(1) / static_cast<F>(k);
auto& x = static_cast<Impl&>(*this);
return x *= inverseK;
}
Expand Down
10 changes: 8 additions & 2 deletions include/UGM/basic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,20 @@ namespace Ubpa {
T sgn(T v) noexcept;

template<typename T>
bool is_zero(T v) noexcept;
bool is_all_zero(T v) noexcept;

template<typename T>
bool is_nan(T v) noexcept;
bool is_any_nan(T v) noexcept;

template<typename T, typename F>
T lerp(T x, T y, F t) noexcept;

template<typename T>
T hadamard_product(T x, T y) noexcept;

template<typename T>
T abs(T x) noexcept;

// 1 - epsilon, T: float / double
template<typename T>
constexpr T one_epsilon() noexcept;
Expand Down
7 changes: 7 additions & 0 deletions include/UGM/bbox.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ namespace Ubpa {
using bboxf2 = bboxf<2>;
using bboxf3 = bboxf<3>;

template<size_t N>
using bboxd = bbox<double, N>;

using bboxd1 = bboxd<1>;
using bboxd2 = bboxd<2>;
using bboxd3 = bboxd<3>;

template<size_t N>
using bboxi = bbox<int, N>;

Expand Down
161 changes: 61 additions & 100 deletions include/UGM/details/basic.inl
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,40 @@
#include <type_traits>
#include <limits>

namespace Ubpa::detail::Basic {
template<typename T> struct rmv_epsilon;
template<typename T> struct is_zero;
template<typename T> struct is_nan;
template<typename T, typename F> struct lerp;
#define UBPA_UGM_DEFINE_CONCEPT_BINARY_API(api_name) \
template<typename T> \
concept contains_##api_name = requires(const T& a, const T& b) { \
a.api_name(b); \
}

#define UBPA_UGM_USE_CONCEPT_BINARY_API(api_name, type) contains_##api_name<type>

namespace Ubpa::details {
template<typename T>
concept contains_rmv_epsilon = requires(const T & v) { v.rmv_epsilon(); };
template<typename T>
concept contains_is_all_zero = requires(const T & v) { v.is_all_zero(); };
template<typename T>
concept contains_is_any_nan = requires(const T & v) { v.is_any_nan(); };
template<typename T, typename F>
concept contains_lerp = requires(const T & a, const T& b, const F& t) { a.lerp(b, t); };
template<typename T>
concept contains_hadamard_product = requires(const T & a, const T & b) { a.hadamard_product(b); };
template<typename T>
concept contains_abs = requires(const T & v) { v.abs(); };
}

namespace Ubpa {
template<typename T>
T rmv_epsilon(T val) noexcept {
return detail::Basic::rmv_epsilon<T>::run(val);
if constexpr (details::contains_rmv_epsilon<T>)
return val.rmv_epsilon();
else {
if (std::abs(std::round(val) - val) < EPSILON<T>)
return static_cast<T>(std::round(val + EPSILON<T>)); // + epsilon for -0 case
else
return val;
}
}

template<typename T>
Expand All @@ -39,18 +62,45 @@ namespace Ubpa {
}

template<typename T>
bool is_zero(T v) noexcept {
return detail::Basic::is_zero<std::decay_t<T>>::run(v);
bool is_all_zero(T v) noexcept {
if constexpr (details::contains_is_all_zero<T>)
return v.is_all_zero();
else
return v == ZERO<T>;
}

template<typename T>
bool is_nan(T v) noexcept {
return detail::Basic::is_nan<std::decay_t<T>>::run(v);
bool is_any_nan(T v) noexcept {
if constexpr (details::contains_is_any_nan<T>)
return v.is_any_nan();
else
return std::isnan(v);
}

template<typename T, typename F>
T lerp(T x, T y, F t) noexcept {
return detail::Basic::lerp<T,F>::run(x, y, t);
if constexpr (details::contains_lerp<T, F>)
return x.lerp(y, t);
else if constexpr (std::is_floating_point_v<T> && std::is_floating_point_v<F>)
return std::lerp(x, y, t);
else
return static_cast<T>(std::lerp(static_cast<long double>(x), static_cast<long double>(y), static_cast<long double>(t)));
}

template<typename T>
T hadamard_product(T x, T y) noexcept {
if constexpr (details::contains_hadamard_product<T>)
return x.hadamard_product(y);
else
return x * y;
}

template<typename T>
T abs(T v) noexcept {
if constexpr (details::contains_abs<T>)
return v.abs();
else
return std::abs(v);
}

template<typename T>
Expand Down Expand Up @@ -108,92 +158,3 @@ namespace Ubpa {
return std::pow(value, static_cast<T>(5.0/11.0));
}
}

namespace Ubpa::detail::Basic {
template<typename T>
struct rmv_epsilon {
static T run(T val) noexcept {
if (std::abs(std::round(val) - val) < EPSILON<T>)
return static_cast<T>(std::round(val + EPSILON<T>)); // + epsilon for -0 case
else
return val;
}
};

template<typename T, size_t N, template<typename, size_t>class V >
struct rmv_epsilon<V<T, N>> {
static V<T, N> run(const V<T, N>& val) noexcept {
return val.rmv_epsilon();
}
};

template<typename T, template<typename>class V >
struct rmv_epsilon<V<T>> {
static V<T> run(const V<T>& val) noexcept {
return val.rmv_epsilon();
}
};

template<typename T>
struct is_zero {
static bool run(T v) noexcept {
return v == ZERO<T>;
}
};

template<typename T, size_t N, template<typename, size_t>class V >
struct is_zero<V<T, N>> {
static bool run(const V<T, N>& val) noexcept {
return val.is_all_zero();
}
};

template<typename T, template<typename>class V >
struct is_zero<V<T>> {
static bool run(const V<T>& val) noexcept {
return val.is_all_zero();
}
};

template<typename T>
struct is_nan {
static bool run(T val) noexcept {
return std::isnan(static_cast<float>(val));
}
};

template<typename T, size_t N, template<typename, size_t>class V >
struct is_nan<V<T, N>> {
static bool run(const V<T, N>& val) noexcept {
return val.has_nan();
}
};

template<typename T, template<typename>class V >
struct is_nan<V<T>> {
static bool run(const V<T>& val) noexcept {
return val.has_nan();
}
};

template<typename T, typename F>
struct lerp {
static T run(T x, T y, F t) noexcept {
return x * (static_cast<F>(1) - t) + y * t;
}
};

template<typename T, typename F, template<typename>class V >
struct lerp<V<T>, F> {
static V<T> run(V<T> x, V<T> y, F t) noexcept {
return V<T>::lerp(x, y, static_cast<T>(t));
}
};

template<typename T, size_t N, typename F, template<typename, size_t>class V >
struct lerp<V<T, N>, F> {
static V<T, N> run(V<T, N> x, V<T, N> y, F t) noexcept {
return V<T, N>::lerp(x, y, static_cast<T>(t));
}
};
}
1 change: 1 addition & 0 deletions include/UGM/euler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace Ubpa {
};

using eulerf = euler<float>;
using eulerd = euler<double>;

// maybe error in editor, but no compile error
static_assert(sizeof(eulerf) == 3 * sizeof(float));
Expand Down
Loading

0 comments on commit 891223b

Please sign in to comment.