|
|
|
@ -56,17 +56,6 @@ namespace Implementation { |
|
|
|
template<class> struct IsBoolVectorOrScalar: std::false_type {}; |
|
|
|
template<class> struct IsBoolVectorOrScalar: std::false_type {}; |
|
|
|
template<> struct IsBoolVectorOrScalar<bool>: std::true_type {}; |
|
|
|
template<> struct IsBoolVectorOrScalar<bool>: std::true_type {}; |
|
|
|
template<std::size_t size> struct IsBoolVectorOrScalar<BoolVector<size>>: std::true_type {}; |
|
|
|
template<std::size_t size> struct IsBoolVectorOrScalar<BoolVector<size>>: std::true_type {}; |
|
|
|
|
|
|
|
|
|
|
|
template<class T> struct IsVectorOrScalar: std::is_arithmetic<T>::type {}; |
|
|
|
|
|
|
|
template<template<class> class Derived, class T> struct IsVectorOrScalar<Unit<Derived, T>>: std::true_type {}; |
|
|
|
|
|
|
|
template<class T> struct IsVectorOrScalar<Deg<T>>: std::true_type {}; |
|
|
|
|
|
|
|
template<class T> struct IsVectorOrScalar<Rad<T>>: std::true_type {}; |
|
|
|
|
|
|
|
template<std::size_t size, class T> struct IsVectorOrScalar<Vector<size, T>>: std::true_type {}; |
|
|
|
|
|
|
|
template<class T> struct IsVectorOrScalar<Vector2<T>>: std::true_type {}; |
|
|
|
|
|
|
|
template<class T> struct IsVectorOrScalar<Vector3<T>>: std::true_type {}; |
|
|
|
|
|
|
|
template<class T> struct IsVectorOrScalar<Vector4<T>>: std::true_type {}; |
|
|
|
|
|
|
|
template<class T> struct IsVectorOrScalar<Color3<T>>: std::true_type {}; |
|
|
|
|
|
|
|
template<class T> struct IsVectorOrScalar<Color4<T>>: std::true_type {}; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@ -113,7 +102,8 @@ Equivalent to the following, but possibly done in a single CPU instruction: |
|
|
|
@snippet MagnumMath.cpp div-equivalent |
|
|
|
@snippet MagnumMath.cpp div-equivalent |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
template<class Integral> inline std::pair<Integral, Integral> div(Integral x, Integral y) { |
|
|
|
template<class Integral> inline std::pair<Integral, Integral> div(Integral x, Integral y) { |
|
|
|
static_assert(std::is_integral<Integral>{}, "Math::div(): not an integral type"); |
|
|
|
static_assert(IsIntegral<Integral>::value && IsScalar<Integral>::value, |
|
|
|
|
|
|
|
"scalar integral type expected"); |
|
|
|
const auto result = std::div(x, y); |
|
|
|
const auto result = std::div(x, y); |
|
|
|
return {result.quot, result.rem}; |
|
|
|
return {result.quot, result.rem}; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -123,15 +113,15 @@ template<class Integral> inline std::pair<Integral, Integral> div(Integral x, In |
|
|
|
|
|
|
|
|
|
|
|
@see @ref isNan(), @ref Constants::inf() |
|
|
|
@see @ref isNan(), @ref Constants::inf() |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, bool>::type isInf(T value) { |
|
|
|
template<class T> inline typename std::enable_if<IsScalar<T>::value, bool>::type isInf(T value) { |
|
|
|
return std::isinf(value); |
|
|
|
return std::isinf(UnderlyingTypeOf<T>(value)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** @overload */ |
|
|
|
/** @overload */ |
|
|
|
template<std::size_t size, class T> inline BoolVector<size> isInf(const Vector<size, T>& value) { |
|
|
|
template<std::size_t size, class T> inline BoolVector<size> isInf(const Vector<size, T>& value) { |
|
|
|
BoolVector<size> out; |
|
|
|
BoolVector<size> out; |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
out.set(i, std::isinf(value[i])); |
|
|
|
out.set(i, Math::isInf(value[i])); |
|
|
|
return out; |
|
|
|
return out; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -141,15 +131,15 @@ template<std::size_t size, class T> inline BoolVector<size> isInf(const Vector<s |
|
|
|
Equivalent to @cpp value != value @ce. |
|
|
|
Equivalent to @cpp value != value @ce. |
|
|
|
@see @ref isInf(), @ref Constants::nan() |
|
|
|
@see @ref isInf(), @ref Constants::nan() |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, bool>::type isNan(T value) { |
|
|
|
template<class T> inline typename std::enable_if<IsScalar<T>::value, bool>::type isNan(T value) { |
|
|
|
return std::isnan(value); |
|
|
|
return std::isnan(UnderlyingTypeOf<T>(value)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** @overload */ |
|
|
|
/** @overload */ |
|
|
|
template<std::size_t size, class T> inline BoolVector<size> isNan(const Vector<size, T>& value) { |
|
|
|
template<std::size_t size, class T> inline BoolVector<size> isNan(const Vector<size, T>& value) { |
|
|
|
BoolVector<size> out; |
|
|
|
BoolVector<size> out; |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
out.set(i, std::isnan(value[i])); |
|
|
|
out.set(i, Math::isNan(value[i])); |
|
|
|
return out; |
|
|
|
return out; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -217,27 +207,29 @@ template<class T> inline Rad<T> atan(T value) { return Rad<T>(std::atan(value)); |
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@{ @name Scalar/vector functions |
|
|
|
@{ @name Scalar/vector functions |
|
|
|
|
|
|
|
|
|
|
|
These functions are overloaded for both scalar and vector types. Scalar |
|
|
|
These functions are overloaded for both scalar and vector types, including |
|
|
|
versions function exactly as their possible STL equivalents, vector overloads |
|
|
|
@ref Deg and @ref Rad. Scalar versions function exactly as their possible STL |
|
|
|
perform the operations component-wise. |
|
|
|
equivalents, vector overloads perform the operations component-wise. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@brief Integral power |
|
|
|
@brief Integral power |
|
|
|
|
|
|
|
|
|
|
|
Returns integral power of base to the exponent. |
|
|
|
Returns integral power of base to the exponent. Works only on types that |
|
|
|
|
|
|
|
satisfy @ref IsUnitless. |
|
|
|
@see @ref pow(T, T) |
|
|
|
@see @ref pow(T, T) |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
template<UnsignedInt exponent, class T> constexpr T pow(T base); |
|
|
|
template<UnsignedInt exponent, class T> constexpr T pow(T base); |
|
|
|
#else |
|
|
|
#else |
|
|
|
template<UnsignedInt exponent, class T> constexpr typename std::enable_if<std::is_arithmetic<T>::value, T>::type pow(T base) { |
|
|
|
template<UnsignedInt exponent, class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type pow(T base) { |
|
|
|
|
|
|
|
static_assert(IsUnitless<T>::value, "expected an unitless type"); |
|
|
|
return Implementation::Pow<exponent>::pow(base); |
|
|
|
return Implementation::Pow<exponent>::pow(base); |
|
|
|
} |
|
|
|
} |
|
|
|
template<UnsignedInt exponent, std::size_t size, class T> inline Vector<size, T> pow(const Vector<size, T>& base) { |
|
|
|
template<UnsignedInt exponent, std::size_t size, class T> inline Vector<size, T> pow(const Vector<size, T>& base) { |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
out[i] = Implementation::Pow<exponent>::pow(base[i]); |
|
|
|
out[i] = Math::pow<exponent>(base[i]); |
|
|
|
return out; |
|
|
|
return out; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
@ -245,19 +237,21 @@ template<UnsignedInt exponent, std::size_t size, class T> inline Vector<size, T> |
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@brief Power |
|
|
|
@brief Power |
|
|
|
|
|
|
|
|
|
|
|
Returns power of @p base to the @p exponent. |
|
|
|
Returns power of @p base to the @p exponent. Works only on types that satisfy |
|
|
|
|
|
|
|
@ref IsUnitless. |
|
|
|
@see @ref pow(T), @ref exp() |
|
|
|
@see @ref pow(T), @ref exp() |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
template<class T> T pow(T base, T exponent); |
|
|
|
template<class T> T pow(T base, T exponent); |
|
|
|
#else |
|
|
|
#else |
|
|
|
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type pow(T base, T exponent) { |
|
|
|
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type pow(T base, T exponent) { |
|
|
|
|
|
|
|
static_assert(IsUnitless<T>::value, "expected an unitless type"); |
|
|
|
return std::pow(base, exponent); |
|
|
|
return std::pow(base, exponent); |
|
|
|
} |
|
|
|
} |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> pow(const Vector<size, T>& base, T exponent) { |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> pow(const Vector<size, T>& base, T exponent) { |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
out[i] = std::pow(base[i], exponent); |
|
|
|
out[i] = Math::pow(base[i], exponent); |
|
|
|
return out; |
|
|
|
return out; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
@ -326,7 +320,7 @@ template<std::size_t size, class T> inline Vector<size, T> max(const Vector<size |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
template<class T> inline std::pair<T, T> minmax(const T& a, const T& b); |
|
|
|
template<class T> inline std::pair<T, T> minmax(const T& a, const T& b); |
|
|
|
#else |
|
|
|
#else |
|
|
|
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, std::pair<T, T>>::type minmax(T a, T b) { |
|
|
|
template<class T> inline typename std::enable_if<IsScalar<T>::value, std::pair<T, T>>::type minmax(T a, T b) { |
|
|
|
return a < b ? std::make_pair(a, b) : std::make_pair(b, a); |
|
|
|
return a < b ? std::make_pair(a, b) : std::make_pair(b, a); |
|
|
|
} |
|
|
|
} |
|
|
|
template<std::size_t size, class T> inline std::pair<Vector<size, T>, Vector<size, T>> minmax(const Vector<size, T>& a, const Vector<size, T>& b) { |
|
|
|
template<std::size_t size, class T> inline std::pair<Vector<size, T>, Vector<size, T>> minmax(const Vector<size, T>& a, const Vector<size, T>& b) { |
|
|
|
@ -352,13 +346,13 @@ set to @p max. Equivalent to: |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
template<class T, class U> inline T clamp(const T& value, const T& min, const T& max); |
|
|
|
template<class T, class U> inline T clamp(const T& value, const T& min, const T& max); |
|
|
|
#else |
|
|
|
#else |
|
|
|
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type clamp(T value, T min, T max) { |
|
|
|
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type clamp(T value, T min, T max) { |
|
|
|
return Math::min(Math::max(value, min), max); |
|
|
|
return Math::min(Math::max(value, min), max); |
|
|
|
} |
|
|
|
} |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> clamp(const Vector<size, T>& value, const Vector<size, T>& min, const Vector<size, T>& max) { |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> clamp(const Vector<size, T>& value, const Vector<size, T>& min, const Vector<size, T>& max) { |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
out[i] = clamp(value[i], min[i], max[i]); |
|
|
|
out[i] = Math::clamp(value[i], min[i], max[i]); |
|
|
|
return out; |
|
|
|
return out; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
@ -367,7 +361,7 @@ template<std::size_t size, class T> inline Vector<size, T> clamp(const Vector<si |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> clamp(const Vector<size, T>& value, T min, T max) { |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> clamp(const Vector<size, T>& value, T min, T max) { |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
out[i] = clamp(value[i], min, max); |
|
|
|
out[i] = Math::clamp(value[i], min, max); |
|
|
|
return out; |
|
|
|
return out; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -379,7 +373,7 @@ Returns `1` if @p x > 0, `0` if @p x = 0 and `-1` if @p x < 0. |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
template<class T> inline T sign(const T scalar); |
|
|
|
template<class T> inline T sign(const T scalar); |
|
|
|
#else |
|
|
|
#else |
|
|
|
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type sign(const T& scalar) { |
|
|
|
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type sign(const T& scalar) { |
|
|
|
if(scalar > T(0)) return T(1); |
|
|
|
if(scalar > T(0)) return T(1); |
|
|
|
if(scalar < T(0)) return T(-1); |
|
|
|
if(scalar < T(0)) return T(-1); |
|
|
|
return T(0); |
|
|
|
return T(0); |
|
|
|
@ -387,7 +381,7 @@ template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> sign(const Vector<size, T>& a) { |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> sign(const Vector<size, T>& a) { |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
out[i] = sign(a[i]); |
|
|
|
out[i] = Math::sign(a[i]); |
|
|
|
return out; |
|
|
|
return out; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
@ -396,13 +390,13 @@ template<std::size_t size, class T> inline Vector<size, T> sign(const Vector<siz |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
template<class T> inline T abs(const T& a); |
|
|
|
template<class T> inline T abs(const T& a); |
|
|
|
#else |
|
|
|
#else |
|
|
|
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type abs(T a) { |
|
|
|
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type abs(T a) { |
|
|
|
return std::abs(a); |
|
|
|
return T(std::abs(UnderlyingTypeOf<T>(a))); |
|
|
|
} |
|
|
|
} |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> abs(const Vector<size, T>& a) { |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> abs(const Vector<size, T>& a) { |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
out[i] = std::abs(a[i]); |
|
|
|
out[i] = Math::abs(a[i]); |
|
|
|
return out; |
|
|
|
return out; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
@ -411,13 +405,13 @@ template<std::size_t size, class T> inline Vector<size, T> abs(const Vector<size |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
template<class T> inline T floor(const T& a); |
|
|
|
template<class T> inline T floor(const T& a); |
|
|
|
#else |
|
|
|
#else |
|
|
|
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type floor(T a) { |
|
|
|
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type floor(T a) { |
|
|
|
return std::floor(a); |
|
|
|
return T(std::floor(UnderlyingTypeOf<T>(a))); |
|
|
|
} |
|
|
|
} |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> floor(const Vector<size, T>& a) { |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> floor(const Vector<size, T>& a) { |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
out[i] = std::floor(a[i]); |
|
|
|
out[i] = Math::floor(a[i]); |
|
|
|
return out; |
|
|
|
return out; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
@ -426,13 +420,13 @@ template<std::size_t size, class T> inline Vector<size, T> floor(const Vector<si |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
template<class T> inline T round(const T& a); |
|
|
|
template<class T> inline T round(const T& a); |
|
|
|
#else |
|
|
|
#else |
|
|
|
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type round(T a) { |
|
|
|
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type round(T a) { |
|
|
|
return std::round(a); |
|
|
|
return T(std::round(UnderlyingTypeOf<T>(a))); |
|
|
|
} |
|
|
|
} |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> round(const Vector<size, T>& a) { |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> round(const Vector<size, T>& a) { |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
out[i] = std::round(a[i]); |
|
|
|
out[i] = Math::round(a[i]); |
|
|
|
return out; |
|
|
|
return out; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
@ -441,13 +435,13 @@ template<std::size_t size, class T> inline Vector<size, T> round(const Vector<si |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
template<class T> inline T ceil(const T& a); |
|
|
|
template<class T> inline T ceil(const T& a); |
|
|
|
#else |
|
|
|
#else |
|
|
|
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type ceil(T a) { |
|
|
|
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type ceil(T a) { |
|
|
|
return std::ceil(a); |
|
|
|
return T(std::ceil(UnderlyingTypeOf<T>(a))); |
|
|
|
} |
|
|
|
} |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> ceil(const Vector<size, T>& a) { |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> ceil(const Vector<size, T>& a) { |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
out[i] = std::ceil(a[i]); |
|
|
|
out[i] = Math::ceil(a[i]); |
|
|
|
return out; |
|
|
|
return out; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
@ -455,18 +449,20 @@ template<std::size_t size, class T> inline Vector<size, T> ceil(const Vector<siz |
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@brief Square root |
|
|
|
@brief Square root |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Works only on types that satisfy @ref IsUnitless. |
|
|
|
@see @ref sqrtInverted(), @ref Vector::length(), @ref sqrt(const Dual<T>&) |
|
|
|
@see @ref sqrtInverted(), @ref Vector::length(), @ref sqrt(const Dual<T>&) |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
template<class T> inline T sqrt(const T& a); |
|
|
|
template<class T> inline T sqrt(const T& a); |
|
|
|
#else |
|
|
|
#else |
|
|
|
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type sqrt(T a) { |
|
|
|
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type sqrt(T a) { |
|
|
|
return T(std::sqrt(a)); |
|
|
|
static_assert(IsUnitless<T>::value, "expecting an unitless type"); |
|
|
|
|
|
|
|
return std::sqrt(a); |
|
|
|
} |
|
|
|
} |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> sqrt(const Vector<size, T>& a) { |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> sqrt(const Vector<size, T>& a) { |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
Vector<size, T> out{NoInit}; |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
for(std::size_t i = 0; i != size; ++i) |
|
|
|
out[i] = T(std::sqrt(a[i])); |
|
|
|
out[i] = Math::sqrt(a[i]); |
|
|
|
return out; |
|
|
|
return out; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
@ -474,17 +470,19 @@ template<std::size_t size, class T> inline Vector<size, T> sqrt(const Vector<siz |
|
|
|
/**
|
|
|
|
/**
|
|
|
|
@brief Inverse square root |
|
|
|
@brief Inverse square root |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Works only on types that satisfy @ref IsUnitless. |
|
|
|
@see @ref sqrt(), @ref Vector::lengthInverted() |
|
|
|
@see @ref sqrt(), @ref Vector::lengthInverted() |
|
|
|
@m_keyword{inversesqrt(),GLSL inversesqrt(),} |
|
|
|
@m_keyword{inversesqrt(),GLSL inversesqrt(),} |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
template<class T> inline T sqrtInverted(const T& a); |
|
|
|
template<class T> inline T sqrtInverted(const T& a); |
|
|
|
#else |
|
|
|
#else |
|
|
|
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type sqrtInverted(T a) { |
|
|
|
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type sqrtInverted(T a) { |
|
|
|
|
|
|
|
static_assert(IsUnitless<T>::value, "expecting an unitless type"); |
|
|
|
return T(1)/std::sqrt(a); |
|
|
|
return T(1)/std::sqrt(a); |
|
|
|
} |
|
|
|
} |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> sqrtInverted(const Vector<size, T>& a) { |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> sqrtInverted(const Vector<size, T>& a) { |
|
|
|
return Vector<size, T>(T(1))/sqrt(a); |
|
|
|
return Vector<size, T>(T(1))/Math::sqrt(a); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
@ -509,7 +507,7 @@ See @ref select() for constant interpolation using the same API and |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
template<class T, class U> inline |
|
|
|
template<class T, class U> inline |
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
|
|
typename std::enable_if<Implementation::IsVectorOrScalar<T>::value && !Implementation::IsBoolVectorOrScalar<U>::value, T>::type |
|
|
|
typename std::enable_if<(IsVector<T>::value || IsScalar<T>::value) && !Implementation::IsBoolVectorOrScalar<U>::value, T>::type |
|
|
|
#else |
|
|
|
#else |
|
|
|
T |
|
|
|
T |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
@ -562,10 +560,10 @@ Returns interpolation phase *t*: @f[ |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
template<class T> inline T lerpInverted(const T& a, const T& b, const T& lerp); |
|
|
|
template<class T> inline T lerpInverted(const T& a, const T& b, const T& lerp); |
|
|
|
#else |
|
|
|
#else |
|
|
|
template<class T> inline T lerpInverted(T a, T b, T lerp) { |
|
|
|
template<class T> inline UnderlyingTypeOf<typename std::enable_if<IsScalar<T>::value, T>::type> lerpInverted(T a, T b, T lerp) { |
|
|
|
return (lerp - a)/(b - a); |
|
|
|
return (lerp - a)/(b - a); |
|
|
|
} |
|
|
|
} |
|
|
|
template<std::size_t size, class T, class U> inline Vector<size, T> lerpInverted(const Vector<size, T>& a, const Vector<size, T>& b, const Vector<size, T>& lerp) { |
|
|
|
template<std::size_t size, class T> inline Vector<size, UnderlyingTypeOf<T>> lerpInverted(const Vector<size, T>& a, const Vector<size, T>& b, const Vector<size, T>& lerp) { |
|
|
|
return (lerp - a)/(b - a); |
|
|
|
return (lerp - a)/(b - a); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
@ -593,12 +591,14 @@ template<class T, class U> constexpr T select(const T& a, const T& b, U t) { |
|
|
|
@brief Fused multiply-add |
|
|
|
@brief Fused multiply-add |
|
|
|
|
|
|
|
|
|
|
|
Computes and returns @f$ ab + c @f$. On some architectures might be faster than |
|
|
|
Computes and returns @f$ ab + c @f$. On some architectures might be faster than |
|
|
|
doing the computation manually. |
|
|
|
doing the computation manually. Works only on types that satisfy |
|
|
|
|
|
|
|
@ref IsUnitless. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
|
|
template<class T> inline T fma(const T& a, const T& b, const T& c); |
|
|
|
template<class T> inline T fma(const T& a, const T& b, const T& c); |
|
|
|
#else |
|
|
|
#else |
|
|
|
template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type fma(T a, T b, T c) { |
|
|
|
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type fma(T a, T b, T c) { |
|
|
|
|
|
|
|
static_assert(IsUnitless<T>::value, "expecting an unitless type"); |
|
|
|
/* On Emscripten it works with -O2 but not with -O1 (function not defined).
|
|
|
|
/* On Emscripten it works with -O2 but not with -O1 (function not defined).
|
|
|
|
I guess that's only because -O2 optimizes it out, so disabling it there. */ |
|
|
|
I guess that's only because -O2 optimizes it out, so disabling it there. */ |
|
|
|
#ifndef CORRADE_TARGET_EMSCRIPTEN |
|
|
|
#ifndef CORRADE_TARGET_EMSCRIPTEN |
|
|
|
@ -608,6 +608,7 @@ template<class T> inline typename std::enable_if<std::is_arithmetic<T>::value, T |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> fma(const Vector<size, T>& a, const Vector<size, T>& b, const Vector<size, T>& c) { |
|
|
|
template<std::size_t size, class T> inline Vector<size, T> fma(const Vector<size, T>& a, const Vector<size, T>& b, const Vector<size, T>& c) { |
|
|
|
|
|
|
|
static_assert(IsUnitless<T>::value, "expecting an unitless type"); |
|
|
|
return a*b + c; |
|
|
|
return a*b + c; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|