single value math funcs

This commit is contained in:
BlackMATov
2020-11-23 05:37:15 +07:00
parent 59739ea85b
commit 2cee3a4d42
3 changed files with 305 additions and 0 deletions

View 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);
}
}

View File

@@ -10,6 +10,7 @@
#include <cmath>
#include <cstddef>
#include <algorithm>
#include <functional>
#include <iterator>
#include <stdexcept>

135
untests/vmath_fun_tests.cpp Normal file
View 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));
}
}