|
fennec
|
#include <fennec/math/detail/_math.h>#include <fennec/lang/limits.h>#include <fennec/math/vector.h>Go to the source code of this file.
Functions | |
Sign Related Functions | |
| template<typename genType > | |
| constexpr genType | fennec::sign (genType x) |
| Returns \(1\) if \(x > 0\), \(0\) if \(x = 0\), or \(-1\) if \(x<0\). | |
| template<typename genType > | |
| constexpr genType | fennec::abs (genType x) |
| Returns \(x\) if \(x \ge 0\), otherwise it returns \(-x\). | |
Rounding Functions | |
| template<typename genType > | |
| constexpr genType | fennec::floor (genType x) |
| Returns a value equal to the nearest integer that is less than or equal to \(x\). | |
| template<typename genType > | |
| constexpr genType | fennec::ceil (genType x) |
| Returns a value equal to the nearest integer that is greater than or equal to \(x\). | |
| template<typename genType > | |
| constexpr genType | fennec::round (genType x) |
| Returns a value equal to the nearest integer. In C++, a fractional part of \(0.5\) will always round up. | |
| template<typename genType > | |
| constexpr genType | fennec::trunc (genType x) |
| Returns a value equal to the nearest integer that is less than or equal to \(x\). | |
| template<typename genType > | |
| constexpr genType | fennec::roundEven (genType x) |
| Returns a value equal to the nearest integer. In C++, a fractional part of \(0.5\) will always round to the nearest even integer. | |
Floating Point Functions | |
| template<typename genType > | |
| constexpr genType | fennec::fract (genType x) |
| Returns \(x - floor(x)\). | |
| template<typename genType > | |
| constexpr genType | fennec::mod (genType x, genType y) |
| Modulus. Returns \(x-y\cdot floor (x/y)\). | |
| template<typename genType > | |
| constexpr genType | fennec::modf (genType x, genType &i) |
| Returns the fractional part of \(x\) and stores the integral part in \(i\). | |
| template<typename genType , typename genBType = bool_t> requires (is_bool_v<genBType>) | |
| constexpr genBType | fennec::isnan (genType x) |
| Returns true if \(x\) holds a NaN. Returns false otherwise. | |
| template<typename genType , typename genBType = bool_t> requires (is_bool_v<genBType>) | |
| constexpr genBType | fennec::isinf (genType x) |
| Returns true if \(x\) holds a positive or negative infinity. Returns false otherwise. | |
| template<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)) | |
| constexpr genIType | fennec::floatBitsToInt (genType x) |
| template<typename genType , typename genUType = uint_t> requires (is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType)) | |
| constexpr genUType | fennec::floatBitsToUint (genType x) |
| Returns a signed or unsigned integer value representing the encoding of a floating-point value. The float value's bit-level representation is preserved. | |
| template<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)) | |
| constexpr genType | fennec::intBitsToFloat (genIType x) |
| template<typename genType = float_t, typename genUType = uint_t> requires (is_floating_point_v<genType> and is_integral_v<genUType> and is_unsigned_v<genUType> and sizeof(genType) == sizeof(genUType)) | |
| constexpr genType | fennec::uintBitsToFloat (genUType x) |
| Returns a floating-point value corresponding to a signed or unsigned integer encoding of a floating-point value. | |
| template<typename genType > | |
| constexpr genType | fennec::fma (genType a, genType b, genType c) |
| Computes and returns \(a \cdot b + c\). | |
| template<typename genType , typename genIType = int_t> requires (is_integral_v<genIType>) | |
| constexpr genType | fennec::frexp (genType x, genIType &exp) |
| Splits \(x\) into a floating-point significand in the range \([0.5,1.0]\), and an integral exponent of two, such that \(x=sig \cdot 2^{exp}\). | |
| template<typename genType , typename genIType = int_t> requires (is_integral_v<genIType>) | |
| constexpr genType | fennec::ldexp (genType x, genIType exp) |
| Builds a floating-point number from \(x\) and the corresponding integral exponent of two in \(exp\). | |
Comparison Functions | |
| template<typename genType > | |
| constexpr genType | fennec::min (genType x, genType y) |
| Returns \(y\) if \(x<y;\) otherwise it returns \(x\). | |
| template<typename genType > | |
| constexpr genType | fennec::max (genType x, genType y) |
| Returns \(y\) if \(y<x\), otherwise it returns \(x\). | |
| template<typename genType > | |
| constexpr genType | fennec::clamp (genType x, genType minVal, genType maxVal) |
| Returns \(min (max (x, minVal), maxVal)\). | |
Simple Curves | |
| template<typename genType > requires (is_floating_point_v<genType>) | |
| constexpr genType | fennec::step (genType edge, genType x) |
| Returns \(0.0\) if \(x<edge\), otherwise, it returns \(1.0\). | |
| template<typename genType > requires (is_floating_point_v<genType>) | |
| constexpr genType | fennec::smoothstep (genType edge0, genType edge1, genType x) |
| Returns \(0.0\) if \(x\le edge0\) and \(1.0\) if \(x\ge edge1\), and performs smooth Hermite interpolation between \(0\) and \(1\) when \(edge0<x<edge1\). | |
| template<typename genType > requires (is_floating_point_v<genType>) | |
| constexpr genType | fennec::mix (genType x, genType y, genType a) |
| Returns the linear blend of \(x\) and \(y\), i.e., \(x \cdot (1-a) + y \cdot a\). | |
| template<typename genType , typename genBType = bool_t> requires (is_bool_v<genBType> and is_floating_point_v<genType>) | |
| constexpr genType | fennec::mix (genType x, genType y, genBType a) |
| Selects which value to return. For Vectors, when the boolean is a scalar, it selects the vector, otherwise, each component is selected. | |
|
constexpr |
We can express this as,
\(\text{sign}(x) = \text{sgn}(x) = \left\{\begin{array}{lr} -1 & x < 0, \\ 0 & x = 0, \\ 1 & x > 0.\end{array}\right.\)
| x | input value |
|
constexpr |
We can express this as,
\(\text{abs}(x)=\left|x\right|\).
| x | input value |
|
constexpr |
We can express this as,
\(\text{floor}(x)=\lfloor x\rfloor\)
| x | input value |
|
constexpr |
We can express this as,
\(\text{ceil}(x)=\lceil{x}\rceil\)
| x | input value |
|
constexpr |
In C++, a fractional part of \(0.5\) will always round up.
We can express this as,
\(\text{round}(x) = \text{sgn}(x) \cdot \lfloor \left| x \right| + 0.5 \rfloor\)
| x | input value |
|
constexpr |
We can express this as,
\(\text{trunc}(x) = \text{sgn}(x) \cdot \lceil \left| x \right| - 0.5 \rceil\)
| x | input value |
|
constexpr |
In C++, a fractional part of \(0.5\) will always round to the nearest even integer.
We can express this as,
\(\text{roundEven}() = \begin{cases}\lfloor{x}\rfloor + \text{mod}(\lfloor{x}\rfloor, 2.0) & \text{fract}(x) = 0.5, \\ \text{round}(x) \end{cases}\)
| x | input value |
|
constexpr |
We can express this as,
\(\text{fract}(x)=x-\text{floor}\)
| x | input value |
|
constexpr |
We can express this as,
\(\text{fract}(x)=x-\text{floor}(\frac{x}{y})\)
| x | dividend |
| y | divisor |
|
constexpr |
We can express this as,
\(\text{modf}(x) = \text{trunc}(x),\, i := \text{fract}(x)\)
| x | input value |
| i | integral out |
|
constexpr |
\(NaN\) is a concept unique to computing. It strictly means, and more specifically, floating point values can only represent real numbers. This is why some functions, like sqrt(), return \(NaN\) when an expression would return a value in a different coordinate space. There are other cases, such as \(\frac{1}{x}\), where \(x=0\) is undefined, and respectively the return value is also \(NaN\).
To learn more, see IEEE 754
| x | input value |
|
constexpr |
\(\inf\), or \(\infty\), is used to express any function that is boundless, endless, or larger than any natural number. This function has applications in Set Theory and Mathematical Analysis.
| x | input value |
|
constexpr |
we can express this in set theory, i.e.
let \(B\) be a set, such that, \(B=\left\lbrace{b_{0},...b_{32}}\right\rbrace\) and \(b_{i} \in S\) where \(S=\left\lbrace{0, 1}\right\rbrace\)
let \(m_B=\frac{b_{0}}{2^1}+\cdots +\frac{b_{i}}{2^{i+1}}+\cdots +\frac{b_{22}}{2^{23}}\begin{cases}1&\end{cases}\)
let \(p_B=b_{23}\cdot 2^0+\cdots +b_i\cdot 2^{i-23}+\cdots +b_{30}\cdot 2^7-127\)
let \(s_B=\begin{cases}-1,&b_{31}=1 \\ 1\end{cases}\)
then, \(x_B=s_B m_B 2^{p_B}\)
and, \(i_B=-b_{31} 2^{31}+\sum_{i=0}^{30}{a_i 2^i}\)
and, \(u_B=\sum_{i=0}^{31}{a_i 2^i}\)
| x | value to convert |
|
constexpr |
we can express this in set theory, i.e.
let \(B\) be a set, such that, \(B=\left\lbrace{b_{0},...b_{32}}\right\rbrace\) and \(b_{i} \in S\) where \(S=\left\lbrace{0, 1}\right\rbrace\)
let \(m_B=\frac{b_{0}}{2^1}+\cdots +\frac{b_{i}}{2^{i+1}}+\cdots +\frac{b_{22}}{2^{23}}\begin{cases}1&\end{cases}\)
let \(p_B=b_{23}\cdot 2^0+\cdots +b_i\cdot 2^{i-23}+\cdots +b_{30}\cdot 2^7-127\)
let \(s_B=\begin{cases}-1,&b_{31}=1 \\ 1\end{cases}\)
then, \(x_B=s_B m_B 2^{p_B}\)
and, \(i_B=-b_{31} 2^{31}+\sum_{i=0}^{30}{a_i 2^i}\)
and, \(u_B=\sum_{i=0}^{31}{a_i 2^i}\)
| x | value to convert |
|
constexpr |
we can express this in set theory, i.e.
let \(B\) be a set, such that, \(B=\left\lbrace{b_{0},...b_{32}}\right\rbrace\) and \(b_{i} \in S\) where \(S=\left\lbrace{0, 1}\right\rbrace\)
let \(m_B=\frac{b_{0}}{2^1}+\cdots +\frac{b_{i}}{2^{i+1}}+\cdots +\frac{b_{22}}{2^{23}}\begin{cases}1&\end{cases}\)
let \(p_B=b_{23}\cdot 2^0+\cdots +b_i\cdot 2^{i-23}+\cdots +b_{30}\cdot 2^7-127\)
let \(s_B=\begin{cases}-1,&b_{31}=1 \\ 1\end{cases}\)
then, \(x_B=s_B m_B 2^{p_B}\)
and, \(i_B=-b_{31} 2^31+\sum_{i=0}^{30}{a_i 2^i}\)
and, \(u_B=\sum_{i=0}^{31}{a_i 2^i}\)
| x | value to convert |
|
constexpr |
we can express this in set theory, i.e.
let \(B\) be a set, such that, \(B=\left\lbrace{b_{0},...b_{32}}\right\rbrace\) and \(b_{i} \in S\) where \(S=\left\lbrace{0, 1}\right\rbrace\)
let \(m_B=\frac{b_{0}}{2^1}+\cdots +\frac{b_{i}}{2^{i+1}}+\cdots +\frac{b_{22}}{2^{23}}\begin{cases}1&\end{cases}\)
let \(p_B=b_{23}\cdot 2^0+\cdots +b_i\cdot 2^{i-23}+\cdots +b_{30}\cdot 2^7-127\)
let \(s_B=\begin{cases}-1,&b_{31}=1 \\ 1\end{cases}\)
then, \(x_B=s_B m_B 2^{p_B}\)
and, \(i_B=-b_{31} 2^31+\sum_{i=0}^{30}{a_i 2^i}\)
and, \(u_B=\sum_{i=0}^{31}{a_i 2^i}\)
| x | value to convert |
|
constexpr |
In C++, this function will use the fused multiply-add, when the instruction is present on the target architecture.
| a | the multiplicand |
| b | the multiplier |
| c | the addend |
|
constexpr |
The significand is returned by the function and the exponent is returned in the parameter \(exp\). For a floating-point value of zero, the significand and exponent are both zero. If an implementation supports signed zero, an input value of minus zero should return a significand of minus zero. For a floating-point value that is an infinity or is not a number, the results are undefined. If the input \(x\) is a vector, this operation is performed in a component-wise manner; the value returned by the function and the value written to \(exp\) are vectors with the same number of components as \(x\).
| x | The floating-point value to split |
| exp | The variable to store the exponent in |
|
constexpr |
Builds a floating-point number from x and the corresponding integral exponent of two in exp, returning: \({x}\cdot{2^{exp}}\). If this product is too large to be represented in the floating-point type, the result is undefined. If exp is greater than +128 (single-precision) or +1024 (double-precision), the value returned is undefined. If exp is less than -126 (single-precision) or -1022 (double-precision), the value returned may be flushed to zero. Additionally, splitting the value into a significand and exponent using frexp() and then reconstructing a floating-point value using ldexp() should yield the original input for zero and all finite non-subnormal values. If the input x is a vector, this operation is performed in a component-wise manner; the value passed in exp and returned by the function are vectors with the same number of components as x.
| x | The significand |
| exp | The exponent |
|
constexpr |
We can express this as,
\(\text{min}(x, y)=\begin{cases}y, & y < x \\ x\end{cases}\)
| x | input value \(x\) |
| y | input value \(y\) |
|
constexpr |
We can express this as,
\(\text{max}(x, y)=\begin{cases}y, & x < y \\ x\end{cases}\)
| x | first input value |
| y | second input value |
|
constexpr |
We can express this as,
\(\text{clamp}(x, min, max)=\begin{cases}min, & x < min \\ x \\ max, & x > max\end{cases}\)
| x | input value |
| minVal | minimum value |
| maxVal | maximum value |
|
constexpr |
We can express this as,
\(\text{step}(edge, x)=\begin{cases}0.0 & x < edge \\ 1.0 \end{cases}\)
| edge | The \(x\) coordinate of the discontinuity |
| x | The coordinate of the sample location |
|
constexpr |
This is useful in cases where you would want a threshold function with a smooth transition.
This is equivalent to:
Results are undefined if \(edge0\ge edge1\).
We can express this as,
\(\text{smoothstep}(e_0, e_1, x)=\begin{cases}0, & {x}\le{e_0} \\ 3{\frac{x-e_0}{e_1-e_0}}^{2} - 2{\frac{x-e_0}{e_1-e_0}}^{3}, & {e_0}\le{x}\le{e_1} \\ 1, & {1}\le{e_x}\end{cases}\)
| edge0 | \(x\) value where the function returns \(0.0\) |
| edge1 | \(x\) value where the function returns \(1.0\) |
| x | \(x\) coordinate input |
|
constexpr |
We can express this as,
\(\text{mix}(x, y, a)=x+a \cdot (y - x)\)
The reason for the difference between the mathematical definition and the glsl definition is due to floating-point precision errors. Multiplying \(x\) and \(y\) separately preserves their precision before the addition happens.
| x | First value |
| y | Second value |
| a | Interpolant |
|
constexpr |
Selects which value to return. For Vectors, when the boolean is a scalar, it selects the vector, otherwise, each component is selected.
This implementation uses the ternary operator:
Which will get reduced down to a conditional move instruction over branching.
We can express this as,
\(\text{mix}(x, y, A) = \begin{cases} x, & A=T \\ y & A=F \end{cases}\)
| x | True Value |
| y | False Value |
| a | Boolean Value |