Browse Source

Math: don't hide the vector/scalar overloads from docs.

People should be able to see the IsScalar requirements and how the
vector types are passed around as well.
pull/342/head
Vladimír Vondruš 7 years ago
parent
commit
d9da018af7
  1. 2
      src/Magnum/Math/Dual.h
  2. 96
      src/Magnum/Math/Functions.h

2
src/Magnum/Math/Dual.h

@ -363,7 +363,7 @@ template<class T> Corrade::Utility::Debug& operator<<(Corrade::Utility::Debug& d
@f[ @f[
\sqrt{\hat a} = \sqrt{a_0} + \epsilon \frac{a_\epsilon}{2 \sqrt{a_0}} \sqrt{\hat a} = \sqrt{a_0} + \epsilon \frac{a_\epsilon}{2 \sqrt{a_0}}
@f] @f]
@see @ref sqrt(const T&) @see @ref sqrt(T)
*/ */
template<class T> Dual<T> sqrt(const Dual<T>& dual) { template<class T> Dual<T> sqrt(const Dual<T>& dual) {
T sqrt0 = std::sqrt(dual.real()); T sqrt0 = std::sqrt(dual.real());

96
src/Magnum/Math/Functions.h

@ -219,20 +219,18 @@ Returns integral power of base to the exponent. Works only on types that
satisfy @ref IsUnitless. satisfy @ref IsUnitless.
@see @ref pow(T, T) @see @ref pow(T, T)
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt exponent, class T> constexpr T pow(T base);
#else
template<UnsignedInt exponent, class T> constexpr typename std::enable_if<IsScalar<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"); static_assert(IsUnitless<T>::value, "expected an unitless type");
return Implementation::Pow<exponent>::pow(base); return Implementation::Pow<exponent>::pow(base);
} }
/** @overload */
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] = Math::pow<exponent>(base[i]); out[i] = Math::pow<exponent>(base[i]);
return out; return out;
} }
#endif
/** /**
@brief Power @brief Power
@ -241,20 +239,18 @@ Returns power of @p base to the @p exponent. Works only on types that satisfy
@ref IsUnitless. @ref IsUnitless.
@see @ref pow(T), @ref exp() @see @ref pow(T), @ref exp()
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> T pow(T base, T exponent);
#else
template<class T> inline typename std::enable_if<IsScalar<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"); static_assert(IsUnitless<T>::value, "expected an unitless type");
return std::pow(base, exponent); return std::pow(base, exponent);
} }
/** @overload */
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] = Math::pow(base[i], exponent); out[i] = Math::pow(base[i], exponent);
return out; return out;
} }
#endif
/** /**
@brief Minimum @brief Minimum
@ -263,17 +259,16 @@ template<std::size_t size, class T> inline Vector<size, T> pow(const Vector<size
@see @ref max(), @ref minmax(), @ref clamp(), @see @ref max(), @ref minmax(), @ref clamp(),
@ref min(Corrade::Containers::ArrayView<const T>), @ref Vector::min() @ref min(Corrade::Containers::ArrayView<const T>), @ref Vector::min()
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT /* defined in Vector.h */
template<class T> inline T min(T value, T min); template<class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type min(T value, T min);
#else
/* min() for scalars defined in Vector.h */ /** @overload */
template<std::size_t size, class T> inline Vector<size, T> min(const Vector<size, T>& value, const Vector<size, T>& min) { template<std::size_t size, class T> inline Vector<size, T> min(const Vector<size, T>& value, const Vector<size, T>& min) {
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] = Math::min(value[i], min[i]); out[i] = Math::min(value[i], min[i]);
return out; return out;
} }
#endif
/** @overload */ /** @overload */
template<std::size_t size, class T> inline Vector<size, T> min(const Vector<size, T>& value, T min) { template<std::size_t size, class T> inline Vector<size, T> min(const Vector<size, T>& value, T min) {
@ -290,17 +285,16 @@ template<std::size_t size, class T> inline Vector<size, T> min(const Vector<size
@see @ref min(), @ref minmax(), @ref clamp(), @see @ref min(), @ref minmax(), @ref clamp(),
@ref max(Corrade::Containers::ArrayView<const T>), @ref Vector::max() @ref max(Corrade::Containers::ArrayView<const T>), @ref Vector::max()
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT /* defined in Vector.h */
template<class T> inline T max(T value, T max); template<class T> constexpr typename std::enable_if<IsScalar<T>::value, T>::type max(T a, T b);
#else
/* max() for scalars defined in Vector.h */ /** @overload */
template<std::size_t size, class T> Vector<size, T> max(const Vector<size, T>& value, const Vector<size, T>& max) { template<std::size_t size, class T> Vector<size, T> max(const Vector<size, T>& value, 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] = Math::max(value[i], max[i]); out[i] = Math::max(value[i], max[i]);
return out; return out;
} }
#endif
/** @overload */ /** @overload */
template<std::size_t size, class T> inline Vector<size, T> max(const Vector<size, T>& value, T max) { template<std::size_t size, class T> inline Vector<size, T> max(const Vector<size, T>& value, T max) {
@ -317,12 +311,11 @@ template<std::size_t size, class T> inline Vector<size, T> max(const Vector<size
@ref minmax(Corrade::Containers::ArrayView<const T>), @ref Vector::minmax(), @ref minmax(Corrade::Containers::ArrayView<const T>), @ref Vector::minmax(),
@ref Range::Range(const std::pair<VectorType, VectorType>&) @ref Range::Range(const std::pair<VectorType, VectorType>&)
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline std::pair<T, T> minmax(const T& a, const T& b);
#else
template<class T> inline typename std::enable_if<IsScalar<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);
} }
/** @overload */
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) {
using std::swap; using std::swap;
std::pair<Vector<size, T>, Vector<size, T>> out{a, b}; std::pair<Vector<size, T>, Vector<size, T>> out{a, b};
@ -330,7 +323,6 @@ template<std::size_t size, class T> inline std::pair<Vector<size, T>, Vector<siz
if(out.first[i] > out.second[i]) swap(out.first[i], out.second[i]); if(out.first[i] > out.second[i]) swap(out.first[i], out.second[i]);
return out; return out;
} }
#endif
/** /**
@brief Clamp value @brief Clamp value
@ -343,19 +335,17 @@ set to @p max. Equivalent to:
<em>NaN</em>s passed in @p value parameter are propagated. <em>NaN</em>s passed in @p value parameter are propagated.
@see @ref min(), @ref max() @see @ref min(), @ref max()
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T, class U> inline T clamp(const T& value, const T& min, const T& max);
#else
template<class T> inline typename std::enable_if<IsScalar<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);
} }
/** @overload */
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] = Math::clamp(value[i], min[i], max[i]); out[i] = Math::clamp(value[i], min[i], max[i]);
return out; return out;
} }
#endif
/** @overload */ /** @overload */
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) {
@ -370,81 +360,71 @@ template<std::size_t size, class T> inline Vector<size, T> clamp(const Vector<si
Returns `1` if @p x > 0, `0` if @p x = 0 and `-1` if @p x < 0. Returns `1` if @p x > 0, `0` if @p x = 0 and `-1` if @p x < 0.
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline T sign(const T scalar);
#else
template<class T> inline typename std::enable_if<IsScalar<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);
} }
/** @overload */
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] = Math::sign(a[i]); out[i] = Math::sign(a[i]);
return out; return out;
} }
#endif
/** @brief Absolute value */ /** @brief Absolute value */
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline T abs(const T& a);
#else
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type abs(T a) { template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type abs(T a) {
return T(std::abs(UnderlyingTypeOf<T>(a))); return T(std::abs(UnderlyingTypeOf<T>(a)));
} }
/** @overload */
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] = Math::abs(a[i]); out[i] = Math::abs(a[i]);
return out; return out;
} }
#endif
/** @brief Nearest not larger integer */ /** @brief Nearest not larger integer */
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline T floor(const T& a);
#else
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type floor(T a) { template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type floor(T a) {
return T(std::floor(UnderlyingTypeOf<T>(a))); return T(std::floor(UnderlyingTypeOf<T>(a)));
} }
/** @overload */
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] = Math::floor(a[i]); out[i] = Math::floor(a[i]);
return out; return out;
} }
#endif
/** @brief Round value to nearest integer */ /** @brief Round value to nearest integer */
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline T round(const T& a);
#else
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type round(T a) { template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type round(T a) {
return T(std::round(UnderlyingTypeOf<T>(a))); return T(std::round(UnderlyingTypeOf<T>(a)));
} }
/** @overload */
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] = Math::round(a[i]); out[i] = Math::round(a[i]);
return out; return out;
} }
#endif
/** @brief Nearest not smaller integer */ /** @brief Nearest not smaller integer */
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline T ceil(const T& a);
#else
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type ceil(T a) { template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type ceil(T a) {
return T(std::ceil(UnderlyingTypeOf<T>(a))); return T(std::ceil(UnderlyingTypeOf<T>(a)));
} }
/** @overload */
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] = Math::ceil(a[i]); out[i] = Math::ceil(a[i]);
return out; return out;
} }
#endif
/** /**
@brief Square root @brief Square root
@ -452,20 +432,18 @@ template<std::size_t size, class T> inline Vector<size, T> ceil(const Vector<siz
Works only on types that satisfy @ref IsUnitless. 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
template<class T> inline T sqrt(const T& a);
#else
template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type sqrt(T a) { template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type sqrt(T a) {
static_assert(IsUnitless<T>::value, "expecting an unitless type"); static_assert(IsUnitless<T>::value, "expecting an unitless type");
return std::sqrt(a); return std::sqrt(a);
} }
/** @overload */
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] = Math::sqrt(a[i]); out[i] = Math::sqrt(a[i]);
return out; return out;
} }
#endif
/** /**
@brief Inverse square root @brief Inverse square root
@ -474,17 +452,15 @@ 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
template<class T> inline T sqrtInverted(const T& a);
#else
template<class T> inline typename std::enable_if<IsScalar<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"); static_assert(IsUnitless<T>::value, "expecting an unitless type");
return T(1)/std::sqrt(a); return T(1)/std::sqrt(a);
} }
/** @overload */
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))/Math::sqrt(a); return Vector<size, T>(T(1))/Math::sqrt(a);
} }
#endif
/** /**
@brief Linear interpolation of two values @brief Linear interpolation of two values
@ -557,16 +533,14 @@ Returns interpolation phase *t*: @f[
@f] @f]
@see @ref lerp(), @ref select() @see @ref lerp(), @ref select()
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline T lerpInverted(const T& a, const T& b, const T& lerp);
#else
template<class T> inline UnderlyingTypeOf<typename std::enable_if<IsScalar<T>::value, T>::type> 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);
} }
/** @overload */
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) { 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
/** /**
@brief Constant interpolation of two values @brief Constant interpolation of two values
@ -594,9 +568,6 @@ Computes and returns @f$ ab + c @f$. On some architectures might be faster than
doing the computation manually. Works only on types that satisfy doing the computation manually. Works only on types that satisfy
@ref IsUnitless. @ref IsUnitless.
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline T fma(const T& a, const T& b, const T& c);
#else
template<class T> inline typename std::enable_if<IsScalar<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"); 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).
@ -607,11 +578,12 @@ template<class T> inline typename std::enable_if<IsScalar<T>::value, T>::type fm
return a*b + c; return a*b + c;
#endif #endif
} }
/** @overload */
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"); static_assert(IsUnitless<T>::value, "expecting an unitless type");
return a*b + c; return a*b + c;
} }
#endif
/*@}*/ /*@}*/

Loading…
Cancel
Save