type restrictions of basic math functions

This commit is contained in:
BlackMATov
2020-11-26 20:06:57 +07:00
parent 4d62fd034a
commit bba60b0aad
6 changed files with 204 additions and 67 deletions

View File

@@ -510,7 +510,7 @@ namespace vmath_hpp
template < typename T, std::size_t Size >
T angle(const vec<T, Size>& x, const vec<T, Size>& y) {
return acos(dot(x, y) * invsqrt(length2(x) * length2(y)));
return acos(dot(x, y) * rsqrt(length2(x) * length2(y)));
}
// rotate

View File

@@ -15,31 +15,94 @@
namespace vmath_hpp
{
template < typename T >
constexpr T radians(T degrees) noexcept {
std::enable_if_t<std::is_floating_point_v<T>, T>
constexpr radians(T degrees) noexcept {
return degrees * T(0.01745329251994329576923690768489);
}
template < typename T >
constexpr T degrees(T radians) noexcept {
std::enable_if_t<std::is_floating_point_v<T>, T>
constexpr degrees(T radians) noexcept {
return radians * T(57.295779513082320876798154814105);
}
using ::std::sin;
using ::std::cos;
using ::std::tan;
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
sin(T x) noexcept {
return std::sin(x);
}
using ::std::asin;
using ::std::acos;
using ::std::atan;
using ::std::atan2;
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
cos(T x) noexcept {
return std::cos(x);
}
using ::std::sinh;
using ::std::cosh;
using ::std::tanh;
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
tan(T x) noexcept {
return std::tan(x);
}
using ::std::asinh;
using ::std::acosh;
using ::std::atanh;
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
asin(T x) noexcept {
return std::asin(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
acos(T x) noexcept {
return std::acos(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
atan(T x) noexcept {
return std::atan(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
atan2(T y, T x) noexcept {
return std::atan2(y, x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
sinh(T x) noexcept {
return std::sinh(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
cosh(T x) noexcept {
return std::cosh(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
tanh(T x) noexcept {
return std::tanh(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
asinh(T x) noexcept {
return std::asinh(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
acosh(T x) noexcept {
return std::acosh(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
atanh(T x) noexcept {
return std::atanh(x);
}
}
//
@@ -48,15 +111,45 @@ namespace vmath_hpp
namespace vmath_hpp
{
using ::std::pow;
using ::std::exp;
using ::std::log;
using ::std::exp2;
using ::std::log2;
using ::std::sqrt;
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
pow(T x, T y) noexcept {
return std::pow(x, y);
}
template < typename T >
T invsqrt(T x) noexcept {
std::enable_if_t<std::is_floating_point_v<T>, T>
exp(T x) noexcept {
return std::exp(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
log(T x) noexcept {
return std::log(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
exp2(T x) noexcept {
return std::exp2(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
log2(T x) noexcept {
return std::log2(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
sqrt(T x) noexcept {
return std::sqrt(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
rsqrt(T x) noexcept {
return T(1) / sqrt(x);
}
}
@@ -80,48 +173,92 @@ namespace vmath_hpp
}
template < typename T >
constexpr T sign(T x) noexcept {
std::enable_if_t<std::is_arithmetic_v<T>, T>
constexpr sign(T x) noexcept {
return static_cast<T>((T(0) < x) - (x < T(0)));
}
using ::std::floor;
using ::std::trunc;
using ::std::round;
using ::std::ceil;
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
floor(T x) noexcept {
return std::floor(x);
}
template < typename T >
T fract(T x) noexcept {
std::enable_if_t<std::is_floating_point_v<T>, T>
trunc(T x) noexcept {
return std::trunc(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
round(T x) noexcept {
return std::round(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
ceil(T x) noexcept {
return std::ceil(x);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
fract(T x) noexcept {
return x - floor(x);
}
using ::std::fmod;
using ::std::modf;
using ::std::min;
using ::std::max;
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
fmod(T x, T y) noexcept {
return std::fmod(x, y);
}
template < typename T >
constexpr T clamp(T x, T min_x, T max_x) noexcept {
std::enable_if_t<std::is_floating_point_v<T>, T>
modf(T x, T* y) noexcept {
return std::modf(x, y);
}
template < typename T >
std::enable_if_t<std::is_arithmetic_v<T>, T>
constexpr min(T x, T y) noexcept {
return std::min(x, y);
}
template < typename T >
std::enable_if_t<std::is_arithmetic_v<T>, T>
constexpr max(T x, T y) noexcept {
return std::max(x, y);
}
template < typename T >
std::enable_if_t<std::is_arithmetic_v<T>, T>
constexpr clamp(T x, T min_x, T max_x) noexcept {
return min(max(x, min_x), max_x);
}
template < typename T >
constexpr T saturate(T x) noexcept {
std::enable_if_t<std::is_arithmetic_v<T>, T>
constexpr saturate(T x) noexcept {
return clamp(x, T(0), T(1));
}
template < typename T >
constexpr T lerp(T x, T y, T a) noexcept {
std::enable_if_t<std::is_floating_point_v<T>, T>
constexpr lerp(T x, T y, T a) noexcept {
return x * (T(1) - a) + y * a;
}
template < typename T >
constexpr T step(T edge, T x) noexcept {
std::enable_if_t<std::is_floating_point_v<T>, T>
constexpr step(T edge, T x) noexcept {
return x < edge ? T(0) : T(1);
}
template < typename T >
constexpr T smoothstep(T edge0, T edge1, T x) noexcept {
std::enable_if_t<std::is_floating_point_v<T>, T>
constexpr smoothstep(T edge0, T edge1, T x) noexcept {
const T t = clamp((x - edge0) / (edge1 - edge0), T(0), T(1));
return t * t * (T(3) - T(2) * t);
}
@@ -129,16 +266,24 @@ namespace vmath_hpp
using ::std::isnan;
using ::std::isinf;
using ::std::isfinite;
using ::std::isnormal;
template < typename T >
bool issubnormal(T x) noexcept {
return std::fpclassify(x) == FP_SUBNORMAL;
std::enable_if_t<std::is_floating_point_v<T>, T>
fma(T x, T y, T z) noexcept {
return std::fma(x, y, z);
}
using ::std::fma;
using ::std::frexp;
using ::std::ldexp;
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
frexp(T x, int* exp) noexcept {
return std::frexp(x, exp);
}
template < typename T >
std::enable_if_t<std::is_floating_point_v<T>, T>
ldexp(T x, int exp) noexcept {
return std::ldexp(x, exp);
}
}
//
@@ -174,7 +319,7 @@ namespace vmath_hpp
template < typename T >
T normalize(T x) noexcept {
return x * invsqrt(dot(x, x));
return x * rsqrt(dot(x, x));
}
template < typename T >

View File

@@ -6,13 +6,11 @@
#pragma once
#include <cassert>
#include <cmath>
#include <cstddef>
#include <algorithm>
#include <functional>
#include <iterator>
#include <stdexcept>
#include <type_traits>
#include <utility>
@@ -45,6 +43,10 @@ namespace vmath_hpp
using size2 = vec<std::size_t, 2>;
using size3 = vec<std::size_t, 3>;
using size4 = vec<std::size_t, 4>;
using ptrdiff2 = vec<std::ptrdiff_t, 2>;
using ptrdiff3 = vec<std::ptrdiff_t, 3>;
using ptrdiff4 = vec<std::ptrdiff_t, 4>;
}
namespace vmath_hpp
@@ -75,4 +77,8 @@ namespace vmath_hpp
using size2x2 = mat<std::size_t, 2>;
using size3x3 = mat<std::size_t, 3>;
using size4x4 = mat<std::size_t, 4>;
using ptrdiff2x2 = mat<std::ptrdiff_t, 2>;
using ptrdiff3x3 = mat<std::ptrdiff_t, 3>;
using ptrdiff4x4 = mat<std::ptrdiff_t, 4>;
}

View File

@@ -370,8 +370,8 @@ namespace vmath_hpp
}
template < typename T, std::size_t Size >
vec<T, Size> invsqrt(const vec<T, Size>& xs) {
return map([](T x) { return invsqrt(x); }, xs);
vec<T, Size> rsqrt(const vec<T, Size>& xs) {
return map([](T x) { return rsqrt(x); }, xs);
}
}
@@ -529,16 +529,6 @@ namespace vmath_hpp
return map([](T x) { return isfinite(x); }, xs);
}
template < typename T, std::size_t Size >
vec<bool, Size> isnormal(const vec<T, Size>& xs) {
return map([](T x) { return isnormal(x); }, xs);
}
template < typename T, std::size_t Size >
vec<bool, Size> issubnormal(const vec<T, Size>& xs) {
return map([](T x) { return issubnormal(x); }, xs);
}
template < typename T, std::size_t Size >
vec<T, Size> fma(const vec<T, Size>& as, const vec<T, Size>& bs, const vec<T, Size>& cs) {
return zip([](T a, T b, T c) { return fma(a, b, c); }, as, bs, cs);
@@ -611,7 +601,7 @@ namespace vmath_hpp
template < typename T, std::size_t Size >
vec<T, Size> normalize(const vec<T, Size>& xs) {
return xs * invsqrt(dot(xs, xs));
return xs * rsqrt(dot(xs, xs));
}
template < typename T, std::size_t Size >

View File

@@ -47,7 +47,7 @@ TEST_CASE("vmath/fun") {
(void)exp2(2.f);
(void)log2(2.f);
(void)sqrt(2.f);
(void)invsqrt(2.f);
(void)rsqrt(2.f);
}
SECTION("Common Functions") {
@@ -98,8 +98,6 @@ TEST_CASE("vmath/fun") {
REQUIRE_FALSE(isnan(1.f));
REQUIRE_FALSE(isinf(1.f));
REQUIRE(isfinite(1.f));
REQUIRE(isnormal(1.f));
REQUIRE_FALSE(issubnormal(1.f));
REQUIRE(fma(2.f, 3.f, 4.f) == approx(10.f));

View File

@@ -95,7 +95,7 @@ TEST_CASE("vmath/vec_fun") {
(void)exp2(float2(1.f));
(void)log2(float2(1.f));
(void)sqrt(float2(1.f));
(void)invsqrt(float2(1.f));
(void)rsqrt(float2(1.f));
}
SECTION("Common Functions") {
@@ -144,8 +144,6 @@ TEST_CASE("vmath/vec_fun") {
REQUIRE_FALSE(isnan(float2(1.f)).x);
REQUIRE_FALSE(isinf(float2(1.f)).x);
REQUIRE(isfinite(float2(1.f)).x);
REQUIRE(isnormal(float2(1.f)).x);
REQUIRE_FALSE(issubnormal(float2(1.f)).x);
REQUIRE_FALSE(fma(float2(2.f), float2(3.f), float2(4.f)).x == Approx(12.f));