mirror of
https://github.com/BlackMATov/vmath.hpp.git
synced 2025-12-16 22:19:51 +07:00
single value math funcs
This commit is contained in:
169
headers/vmath.hpp/vmath_fun.hpp
Normal file
169
headers/vmath.hpp/vmath_fun.hpp
Normal file
@@ -0,0 +1,169 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/vmath.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2020, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "vmath_fwd.hpp"
|
||||
|
||||
//
|
||||
// Angle and Trigonometry Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T >
|
||||
constexpr T radians(T degrees) noexcept {
|
||||
return degrees * T(0.01745329251994329576923690768489);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
constexpr T degrees(T radians) noexcept {
|
||||
return radians * T(57.295779513082320876798154814105);
|
||||
}
|
||||
|
||||
using ::std::sin;
|
||||
using ::std::cos;
|
||||
using ::std::tan;
|
||||
|
||||
using ::std::asin;
|
||||
using ::std::acos;
|
||||
using ::std::atan;
|
||||
using ::std::atan2;
|
||||
|
||||
using ::std::sinh;
|
||||
using ::std::cosh;
|
||||
using ::std::tanh;
|
||||
|
||||
using ::std::asinh;
|
||||
using ::std::acosh;
|
||||
using ::std::atanh;
|
||||
}
|
||||
|
||||
//
|
||||
// Exponential Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
using ::std::pow;
|
||||
using ::std::exp;
|
||||
using ::std::log;
|
||||
using ::std::exp2;
|
||||
using ::std::log2;
|
||||
using ::std::sqrt;
|
||||
|
||||
template < typename T >
|
||||
T invsqrt(T x) noexcept {
|
||||
return T(1) / sqrt(x);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Common Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
using ::std::abs;
|
||||
|
||||
template < typename T >
|
||||
T sign(T x) noexcept {
|
||||
return (T(0) < x) - (x < T(0));
|
||||
}
|
||||
|
||||
using ::std::floor;
|
||||
using ::std::trunc;
|
||||
using ::std::round;
|
||||
using ::std::ceil;
|
||||
|
||||
template < typename 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 >
|
||||
constexpr T clamp(T x, T min_x, T max_x) noexcept {
|
||||
return min(max(x, min_x), max_x);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
constexpr T mix(T x, T y, T a) noexcept {
|
||||
return x * (T(1) - a) + y * a;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
constexpr T mix(T x, T y, bool a) noexcept {
|
||||
return a ? y : x;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
constexpr T 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 {
|
||||
const T t = clamp((x - edge0) / (edge1 - edge0), T(0), T(1));
|
||||
return t * t * (T(3) - T(2) * t);
|
||||
}
|
||||
|
||||
using ::std::isnan;
|
||||
using ::std::isinf;
|
||||
using ::std::fma;
|
||||
|
||||
using ::std::frexp;
|
||||
using ::std::ldexp;
|
||||
}
|
||||
|
||||
//
|
||||
// Geometric Functions
|
||||
//
|
||||
|
||||
namespace vmath_hpp
|
||||
{
|
||||
template < typename T >
|
||||
T length(T x) noexcept {
|
||||
return abs(x);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
T distance(T p0, T p1) noexcept {
|
||||
return length(p0 - p1);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
T dot(T x, T y) noexcept {
|
||||
return x * y;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
T normalize(T x) noexcept {
|
||||
return x * invsqrt(dot(x, x));
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
T faceforward(T n, T i, T nref) noexcept {
|
||||
return dot(nref, i) < T(0) ? n : -n;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
T reflect(T i, T n) noexcept {
|
||||
return i - n * dot(n, i) * T(2);
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
T refract(T i, T n, T eta) noexcept {
|
||||
const T d = dot(n, i);
|
||||
const T k = T(1) - eta * eta * (T(1) - d * d);
|
||||
return T(k >= T(0)) * (eta * i - (eta * d + sqrt(k)) * n);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
|
||||
135
untests/vmath_fun_tests.cpp
Normal file
135
untests/vmath_fun_tests.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/vmath.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2020, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include <vmath.hpp/vmath_fun.hpp>
|
||||
|
||||
#define CATCH_CONFIG_FAST_COMPILE
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
template < typename T >
|
||||
class approx {
|
||||
public:
|
||||
explicit constexpr approx(T v) : value_(v) {}
|
||||
|
||||
friend constexpr bool operator==(const T& l, const approx& r) {
|
||||
return (r.value_ < l + epsilon)
|
||||
&& (l < r.value_ + epsilon);
|
||||
}
|
||||
private:
|
||||
T value_;
|
||||
static constexpr T epsilon = std::numeric_limits<T>::epsilon() * 100;
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("vmath/fun") {
|
||||
using namespace vmath_hpp;
|
||||
|
||||
SECTION("Angle and Trigonometry Functions") {
|
||||
STATIC_REQUIRE(radians(degrees(12.13f)) == approx(12.13f));
|
||||
STATIC_REQUIRE(degrees(radians(12.13f)) == approx(12.13f));
|
||||
|
||||
sin(0.f);
|
||||
cos(0.f);
|
||||
tan(0.f);
|
||||
|
||||
asin(0.f);
|
||||
acos(0.f);
|
||||
atan(0.f);
|
||||
atan2(0.f, 0.f);
|
||||
|
||||
sinh(0.f);
|
||||
cosh(0.f);
|
||||
tanh(0.f);
|
||||
|
||||
asinh(0.f);
|
||||
acosh(0.f);
|
||||
atanh(0.f);
|
||||
}
|
||||
|
||||
SECTION("Exponential Functions") {
|
||||
pow(2.f, 3.f);
|
||||
exp(2.f);
|
||||
log(2.f);
|
||||
exp2(2.f);
|
||||
log2(2.f);
|
||||
sqrt(2.f);
|
||||
invsqrt(2.f);
|
||||
}
|
||||
|
||||
SECTION("Common Functions") {
|
||||
REQUIRE(abs(1) == 1);
|
||||
REQUIRE(abs(-1) == 1);
|
||||
REQUIRE(abs(1.f) == approx(1.f));
|
||||
REQUIRE(abs(-1.f) == approx(1.f));
|
||||
|
||||
REQUIRE(sign(2) == 1);
|
||||
REQUIRE(sign(-2) == -1);
|
||||
REQUIRE(sign(0) == 0);
|
||||
REQUIRE(sign(2.f) == approx(1.f));
|
||||
REQUIRE(sign(-2.f) == approx(-1.f));
|
||||
REQUIRE(sign(0.f) == approx(0.f));
|
||||
|
||||
REQUIRE(floor(1.7f) == approx(1.f));
|
||||
REQUIRE(trunc(1.7f) == approx(1.f));
|
||||
REQUIRE(round(1.7f) == approx(2.f));
|
||||
REQUIRE(ceil(1.7f) == approx(2.f));
|
||||
|
||||
REQUIRE(fract(1.7f) == approx(0.7f));
|
||||
REQUIRE(fract(-2.3f) == approx(0.7f));
|
||||
|
||||
REQUIRE(fmod(1.7f, 1.2f) == approx(0.5f));
|
||||
|
||||
{
|
||||
float out_i{};
|
||||
REQUIRE(modf(1.7f, &out_i) == approx(0.7f));
|
||||
REQUIRE(out_i == approx(1.f));
|
||||
}
|
||||
|
||||
STATIC_REQUIRE(min(1.f, 2.f) == approx(1.f));
|
||||
STATIC_REQUIRE(max(1.f, 2.f) == approx(2.f));
|
||||
|
||||
STATIC_REQUIRE(clamp(1.0f, 2.f, 3.f) == approx(2.0f));
|
||||
STATIC_REQUIRE(clamp(2.5f, 2.f, 3.f) == approx(2.5f));
|
||||
STATIC_REQUIRE(clamp(3.5f, 2.f, 3.f) == approx(3.0f));
|
||||
|
||||
STATIC_REQUIRE(mix(0.f, 10.f, 0.5f) == approx(5.f));
|
||||
STATIC_REQUIRE(mix(0.f, 10.f, false) == approx(0.f));
|
||||
STATIC_REQUIRE(mix(0.f, 10.f, true) == approx(10.f));
|
||||
STATIC_REQUIRE(step(0.5f, 0.4f) == approx(0.f));
|
||||
STATIC_REQUIRE(step(0.5f, 0.6f) == approx(1.f));
|
||||
STATIC_REQUIRE(smoothstep(0.f, 1.f, 0.1f) == approx(0.028f));
|
||||
|
||||
REQUIRE_FALSE(isnan(1.f));
|
||||
REQUIRE_FALSE(isinf(1.f));
|
||||
|
||||
REQUIRE(fma(2.f, 3.f, 4.f) == approx(10.f));
|
||||
|
||||
{
|
||||
int out_exp{};
|
||||
REQUIRE(frexp(1.7f, &out_exp) == approx(0.85f));
|
||||
REQUIRE(out_exp == 1);
|
||||
}
|
||||
|
||||
REQUIRE(ldexp(0.85f, 1) == approx(1.7f));
|
||||
}
|
||||
|
||||
SECTION("Geometric Functions") {
|
||||
REQUIRE(length(10.f) == approx(10.f));
|
||||
REQUIRE(length(-10.f) == approx(10.f));
|
||||
|
||||
REQUIRE(distance(5.f, 10.f) == approx(5.f));
|
||||
REQUIRE(distance(-5.f, -10.f) == approx(5.f));
|
||||
|
||||
REQUIRE(dot(2.f, 5.f) == approx(10.f));
|
||||
REQUIRE(normalize(0.5f) == approx(1.f));
|
||||
|
||||
REQUIRE(faceforward(1.f, 2.f, 3.f) == approx(-1.f));
|
||||
REQUIRE(reflect(1.f, 2.f) == approx(-7.f));
|
||||
REQUIRE(refract(1.f, 2.f, 1.f) == approx(-7.f));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user