32#ifndef FENNEC_MATH_COMMON_H
33#define FENNEC_MATH_COMMON_H
272#include <fennec/math/detail/_math.h>
278#if FENNEC_COMPILER_MSVC
279#define isnanf(x) isnan(x)
280#define isinff(x) isinf(x)
305template<
typename genType>
306constexpr genType
sign(genType x) {
307 return (x < genType(0) ? genType(-1) : genType(1)) *
static_cast<genType
>(x != 0);
321template<
typename genType>
322constexpr genType
abs(genType x) {
347template<
typename genType>
364template<
typename genType>
365constexpr genType
ceil(genType x) {
382template<
typename genType>
constexpr genType
round(genType x) {
398template<
typename genType>
417template<
typename genType>
420 int I =
static_cast<int>(x);
421 genType i =
static_cast<genType
>(I);
423 if (
abs(f - genType(0.5)) >
e)
427 return dir ? i + 1 : i;
461template<
typename genType>
463 return x - ::floor(x);
478template<
typename genType>
479constexpr genType
mod(genType x, genType y) {
495template<
typename genType>
496constexpr genType
modf(genType x, genType& i) {
516template<
typename genType,
typename genBType =
bool_t>
requires(is_bool_v<genBType>)
517constexpr genBType
isnan(genType x) {
532template<
typename genType,
typename genBType =
bool_t>
requires(is_bool_v<genBType>)
533constexpr genBType
isinf(genType x) {
543template<
typename genType,
typename genIType =
int_t>
requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and
sizeof(genType) ==
sizeof(genIType))
545 return fennec::bit_cast<genIType>(x);
565template<
typename genType,
typename genUType = u
int_t>
requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and
sizeof(genType) ==
sizeof(genUType))
567 return fennec::bit_cast<genUType>(x);
573template<
typename genType =
float_t,
typename genIType =
int_t>
requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and
sizeof(genType) ==
sizeof(genIType))
575 return fennec::bit_cast<genType>(x);
593template<
typename genType =
float_t,
typename genUType = u
int_t>
requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and
sizeof(genType) ==
sizeof(genUType))
595 return fennec::bit_cast<genType>(x);
612template<
typename genType>
613constexpr genType
fma(genType a, genType b, genType c) {
614 return genType(::fma(a, b, c));
635template<
typename genType,
typename genIType =
int_t>
requires(is_integral_v<genIType>)
636constexpr genType
frexp(genType x, genIType& exp) {
637 return ::frexp(x, &
exp);
660template<
typename genType,
typename genIType =
int_t>
requires(is_integral_v<genIType>)
661constexpr genType
ldexp(genType x, genIType exp) {
662 return ::ldexp(x,
exp);
687template<
typename genType>
688constexpr genType
min(genType x, genType y) {
689 return (
y < x) ?
y : x;
704template<
typename genType>
705constexpr genType
max(genType x, genType y) {
706 return (x <
y) ?
y : x;
722template<
typename genType>
723constexpr genType
clamp(genType x, genType minVal, genType maxVal) {
724 return min(
max(x, minVal), maxVal);
749template<
typename genType>
requires(is_floating_point_v<genType>)
750constexpr genType
step(genType edge, genType x) {
751 return static_cast<genType
>(not(x < edge));
777template<
typename genType>
requires(is_floating_point_v<genType>)
778constexpr genType
smoothstep(genType edge0, genType edge1, genType x) {
779 genType t =
fennec::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
return t * t * (3 - 2 * t);
798template<
typename genType>
requires(is_floating_point_v<genType>)
799constexpr genType
mix(genType x, genType y, genType a) {
800 return x * (genType(1.0) - a) +
y * a;
821template<
typename genType,
typename genBType =
bool_t>
requires(is_bool_v<genBType> and is_floating_point_v<genType>)
822constexpr genType
mix(genType x, genType y, genBType a) {
829template<
typename genType,
size_t...i>
830constexpr vector<genType, i...> sign(
const vector<genType, i...>& x) {
831 return vector<genType, i...>(fennec::sign(x[i]) ...);
834template<
typename genType,
size_t...i>
835constexpr vector<genType, i...>
abs(
const vector<genType, i...>& x) {
836 return vector<genType, i...>(
fennec::abs(x[i]) ...);
839template<
typename genType,
size_t...i>
840constexpr vector<genType, i...>
floor(
const vector<genType, i...>& x) {
844template<
typename genType,
size_t...i>
845constexpr vector<genType, i...>
ceil(
const vector<genType, i...>& x) {
849template<
typename genType,
size_t...i>
850constexpr vector<genType, i...>
round(
const vector<genType, i...>& x) {
854template<
typename genType,
size_t...i>
855constexpr vector<genType, i...>
trunc(
const vector<genType, i...>& x) {
859template<
typename genType,
size_t...i>
860constexpr vector<genType, i...>
roundEven(
const vector<genType, i...>& x) {
864template<
typename genType,
size_t...i>
865constexpr vector<genType, i...>
fract(
const vector<genType, i...>& x) {
869template<
typename genType,
size_t...i>
870constexpr vector<genType, i...>
mod(
const vector<genType, i...>& x, genType y) {
874template<
typename genType,
size_t...i>
875constexpr vector<genType, i...>
mod(
const vector<genType, i...>& x,
const vector<genType, i...>& y) {
879template<
typename genType,
size_t...i>
880constexpr vector<genType, i...>
modf(
const vector<genType, i...>& x, vector<genType, i...>& I) {
884template<
typename genType,
typename genBType =
bool_t,
size_t...i>
requires(is_bool_v<genBType>)
885constexpr vector<genBType, i...>
isnan(
const vector<genType, i...>& x) {
889template<
typename genType,
typename genBType =
bool_t,
size_t...i>
requires(is_bool_v<genBType>)
890constexpr vector<genBType, i...>
isinf(
const vector<genType, i...>& x) {
894template<
typename genType =
float_t,
typename genIType =
int_t,
size_t...i>
requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and
sizeof(genType) ==
sizeof(genIType))
895constexpr vector<genIType, i...>
floatBitsToInt(
const vector<genType, i...>& x) {
896 return vector<genIType, i...>(fennec::bit_cast<genIType>(x[i])...);
899template<
typename genType =
float_t,
typename genUType =
uint_t,
size_t...i>
requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and
sizeof(genType) ==
sizeof(genUType))
900constexpr vector<genUType, i...>
floatBitsToUint(
const vector<genType, i...>& x) {
901 return vector<genUType, i...>(fennec::bit_cast<genUType>(x[i])...);
904template<
typename genType =
float_t,
typename genIType =
int_t,
size_t...i>
requires(is_floating_point_v<genType> and is_integral_v<genIType> and is_signed_v<genIType> and
sizeof(genType) ==
sizeof(genIType))
905constexpr vector<genType, i...>
intBitsToFloat(
const vector<genIType, i...>& x) {
906 return vector<genType, i...>(fennec::bit_cast<genType>(x[i]) ...);
909template<
typename genType =
float_t,
typename genUType =
uint_t,
size_t...i>
requires(is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and
sizeof(genType) ==
sizeof(genUType))
910constexpr vector<genType, i...>
uintBitsToFloat(
const vector<genUType, i...>& x) {
911 return vector<genType, i...>(fennec::bit_cast<genType>(x[i]) ...);
914template<
typename genType,
size_t...i>
915constexpr vector<genType, i...>
fma(
const vector<genType, i...>& a,
const vector<genType, i...>& b,
const vector<genType, i...>& c) {
916 return vector<genType, i...>(
fennec::fma(a[i], b[i], c[i]) ...);
919template<
typename genType,
typename genIType =
int_t,
size_t...i>
requires(is_integral_v<genIType>)
920constexpr vector<genType, i...>
frexp(
const vector<genType, i...>& x, vector<genIType, i...>& exp) {
921 return vector<genType, i...>(
fennec::frexp(x[i], exp[i])...);
924template<
typename genType,
typename genIType =
int_t,
size_t...i>
requires(is_integral_v<genIType>)
925constexpr vector<genType, i...>
ldexp(
const vector<genType, i...>& x,
const vector<genIType, i...>& exp) {
926 return vector<genType, i...>(
fennec::ldexp(x[i], exp[i])...);
929template<
typename genType,
size_t...i>
930constexpr vector<genType, i...>
min(genType x,
const vector<genType, i...>& y) {
931 return vector<genType, i...>(
fennec::min(x, y[i]) ...);
934template<
typename genType,
size_t...i>
935constexpr vector<genType, i...>
min(
const vector<genType, i...>& x, genType y) {
936 return vector<genType, i...>(
fennec::min(x[i], y) ...);
939template<
typename genType,
size_t...i>
940constexpr vector<genType, i...>
min(
const vector<genType, i...>& x,
const vector<genType, i...>& y) {
941 return vector<genType, i...>(
fennec::min(x[i], y[i]) ...);
944template<
typename genType,
size_t...i>
945constexpr vector<genType, i...>
max(genType x,
const vector<genType, i...>& y) {
946 return vector<genType, i...>(
fennec::max(x, y[i]) ...);
949template<
typename genType,
size_t...i>
950constexpr vector<genType, i...>
max(
const vector<genType, i...>& x, genType y) {
951 return vector<genType, i...>(
fennec::max(x[i], y) ...);
954template<
typename genType,
size_t...i>
955constexpr vector<genType, i...>
max(
const vector<genType, i...>& x,
const vector<genType, i...>& y) {
956 return vector<genType, i...>(
fennec::max(x[i], y[i]) ...);
959template<
typename genType,
size_t...i>
960constexpr vector<genType, i...>
clamp(
const vector<genType, i...>& x, genType minVal, genType maxVal) {
961 return vector<genType, i...>(
fennec::min(fennec::max(x[i], minVal), maxVal)...);
964template<
typename genType,
size_t...i>
965constexpr vector<genType, i...>
clamp(
const vector<genType, i...>& x,
const vector<genType, i...>& minVal,
const vector<genType, i...>& maxVal) {
966 return vector<genType, i...>(
fennec::min(fennec::max(x[i], minVal[i]), maxVal[i])...);
969template<
typename genType,
size_t...i>
requires(is_floating_point_v<genType>)
970constexpr vector<genType, i...>
step(genType edge,
const vector<genType, i...>& x) {
971 return vector<genType, i...>(
fennec::step(edge, x[i]) ...);
974template<
typename genType,
size_t...i>
requires(is_floating_point_v<genType>)
975constexpr vector<genType, i...>
step(
const vector<genType, i...>& edge,
const vector<genType, i...>& x) {
976 return vector<genType, i...>(
fennec::step(edge[i], x[i]) ...);
979template<
typename genType,
size_t...i>
requires(is_floating_point_v<genType>)
980constexpr vector<genType, i...>
smoothstep(genType edge0, genType edge1,
const vector<genType, i...>& x) {
984template<
typename genType,
size_t...i>
requires(is_floating_point_v<genType>)
985constexpr vector<genType, i...>
smoothstep(
const vector<genType, i...>& edge0,
const vector<genType, i...>& edge1,
const vector<genType, i...>& x) {
989template<
typename genType,
size_t...i>
requires(is_floating_point_v<genType>)
990constexpr vector<genType, i...>
mix(
const vector<genType, i...>& x,
const vector<genType, i...>& y, genType a) {
991 return x * (genType(1.0) - a) + y * a;
994template<
typename genType,
size_t...i>
requires(is_floating_point_v<genType>)
995constexpr vector<genType, i...>
mix(
const vector<genType, i...>& x,
const vector<genType, i...>& y,
const vector<genType, i...>& a) {
996 return x * (genType(1.0) - a) + y * a;
999template<
typename genType,
typename genBType =
bool_t,
size_t...i>
requires(is_bool_v<genBType> and is_floating_point_v<genType>)
1000constexpr vector<genType, i...>
mix(
const vector<genType, i...>& x,
const vector<genType, i...>& y, genBType a) {
1001 return genDType((a ? y[i] : x[i])...);
1005template<
typename genBType =
bool_t,
size_t...i>
requires(is_bool_v<genBType>)
1006constexpr vector<genBType, i...>
mix(
const vector<genBType, i...>& x,
const vector<genBType, i...>& y,
const vector<genBType, i...>& a) {
1007 return genBType((a[i] ? y[i] : x[i])...);
1010template<
typename genType,
typename genBType =
bool_t,
size_t...i>
requires(is_bool_v<genBType> and is_floating_point_v<genType>)
1011constexpr vector<genType, i...>
mix(
const vector<genType, i...>& x,
const vector<genType, i...>& y,
const vector<genBType, i...>& a) {
1012 return genDType((a[i] ? y[i] : x[i])...);
constexpr genType exp(genType x)
Returns the natural exponentiation of , i.e., .
Definition exponential.h:122
constexpr genType min(genType x, genType y)
Returns if otherwise it returns .
Definition common.h:688
constexpr genBType isnan(genType x)
Returns true if holds a NaN. Returns false otherwise.
Definition common.h:517
constexpr genType uintBitsToFloat(genUType x)
Returns a floating-point value corresponding to a signed or unsigned integer encoding of a floating-p...
Definition common.h:594
constexpr genUType floatBitsToUint(genType x)
Returns a signed or unsigned integer value representing the encoding of a floating-point value....
Definition common.h:566
constexpr genType mod(genType x, genType y)
Modulus. Returns .
Definition common.h:479
constexpr genType smoothstep(genType edge0, genType edge1, genType x)
Returns if and if , and performs smooth Hermite interpolation between and when .
Definition common.h:778
constexpr genType step(genType edge, genType x)
Returns if , otherwise, it returns .
Definition common.h:750
constexpr genType intBitsToFloat(genIType x)
Definition common.h:574
constexpr genType ldexp(genType x, genIType exp)
Builds a floating-point number from and the corresponding integral exponent of two in .
Definition common.h:661
constexpr genType max(genType x, genType y)
Returns if , otherwise it returns .
Definition common.h:705
constexpr genType trunc(genType x)
Returns a value equal to the nearest integer that is less than or equal to .
Definition common.h:399
constexpr genType roundEven(genType x)
Returns a value equal to the nearest integer. In C++, a fractional part of will always round to the ...
Definition common.h:418
constexpr genType ceil(genType x)
Returns a value equal to the nearest integer that is greater than or equal to .
Definition common.h:365
constexpr genType sign(genType x)
Returns if , if , or if .
Definition common.h:306
constexpr genType floor(genType x)
Returns a value equal to the nearest integer that is less than or equal to .
Definition common.h:348
constexpr genType mix(genType x, genType y, genType a)
Returns the linear blend of and , i.e., .
Definition common.h:799
constexpr genType fma(genType a, genType b, genType c)
Computes and returns .
Definition common.h:613
constexpr genType frexp(genType x, genIType &exp)
Splits into a floating-point significand in the range , and an integral exponent of two,...
Definition common.h:636
constexpr genType abs(genType x)
Returns if , otherwise it returns .
Definition common.h:322
constexpr genType fract(genType x)
Returns .
Definition common.h:462
constexpr genIType floatBitsToInt(genType x)
Definition common.h:544
constexpr genType clamp(genType x, genType minVal, genType maxVal)
Returns .
Definition common.h:723
constexpr genType round(genType x)
Returns a value equal to the nearest integer. In C++, a fractional part of will always round up.
Definition common.h:382
constexpr genBType isinf(genType x)
Returns true if holds a positive or negative infinity. Returns false otherwise.
Definition common.h:533
constexpr genType modf(genType x, genType &i)
Returns the fractional part of and stores the integral part in .
Definition common.h:496
constexpr genType y()
Definition constants.h:672
constexpr genType e()
Definition constants.h:635
static constexpr TypeT epsilon()
Returns the difference between 1.0 and the next representable value.
Definition limits.h:255
bool bool_t
A conditional type.
Definition types.h:214
unsigned int uint_t
An unsigned integer type, size varies by implementation, but typically 32-bit.
Definition types.h:226
signed int int_t
A signed integer type, size varies by implementation, but typically 32-bit.
Definition types.h:225
float float_t
A single-precision floating-point type, typically with a size of 32-bits.
Definition types.h:234