mirror of
https://github.com/BlackMATov/vmath.hpp.git
synced 2025-12-14 20:31:25 +07:00
type restrictions of basic math functions
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 >
|
||||
|
||||
@@ -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>;
|
||||
}
|
||||
|
||||
@@ -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 >
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user