From e9ba5bf8c73bf6c9962214701a30d5a33cde4798 Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Sun, 11 Feb 2024 17:05:57 -0500 Subject: [PATCH] Add math section to users guide --- docs/users-guide/examples/CMakeLists.txt | 2 + .../examples/GuideExampleMatrix.cxx | 62 +++ .../examples/GuideExampleNewtonsMethod.cxx | 113 ++++++ docs/users-guide/math.rst | 373 ++++++++++++++++++ docs/users-guide/part-advanced.rst | 1 + vtkm/Math.h | 204 ++++++++-- vtkm/Math.h.in | 204 ++++++++-- vtkm/Matrix.h | 8 +- vtkm/NewtonsMethod.h | 24 ++ vtkm/VectorAnalysis.h | 51 +-- 10 files changed, 932 insertions(+), 110 deletions(-) create mode 100644 docs/users-guide/examples/GuideExampleMatrix.cxx create mode 100644 docs/users-guide/examples/GuideExampleNewtonsMethod.cxx create mode 100644 docs/users-guide/math.rst diff --git a/docs/users-guide/examples/CMakeLists.txt b/docs/users-guide/examples/CMakeLists.txt index 77659948c..6749c1b0e 100644 --- a/docs/users-guide/examples/CMakeLists.txt +++ b/docs/users-guide/examples/CMakeLists.txt @@ -16,6 +16,8 @@ set(examples GuideExampleInitialization.cxx GuideExampleIO.cxx GuideExampleLists.cxx + GuideExampleMatrix.cxx + GuideExampleNewtonsMethod.cxx GuideExampleProvidedFilters.cxx GuideExampleRendering.cxx GuideExampleRuntimeDeviceTracker.cxx diff --git a/docs/users-guide/examples/GuideExampleMatrix.cxx b/docs/users-guide/examples/GuideExampleMatrix.cxx new file mode 100644 index 000000000..78c278eec --- /dev/null +++ b/docs/users-guide/examples/GuideExampleMatrix.cxx @@ -0,0 +1,62 @@ +//============================================================================= +// +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +// +//============================================================================= + +#include + +#include + +namespace +{ + +VTKM_CONT +void BuildMatrix() +{ + std::cout << "Building matrix containing " << std::endl + << "| 0 1 2 |" << std::endl + << "| 10 11 12 |" << std::endl; + + //// + //// BEGIN-EXAMPLE BuildMatrix + //// + vtkm::Matrix matrix; + + // Using parenthesis notation. + matrix(0, 0) = 0.0f; + matrix(0, 1) = 1.0f; + matrix(0, 2) = 2.0f; + + // Using bracket notation. + matrix[1][0] = 10.0f; + matrix[1][1] = 11.0f; + matrix[1][2] = 12.0f; + //// + //// END-EXAMPLE BuildMatrix + //// + + vtkm::Vec2f_32 termVec(1.0f, 0.1f); + vtkm::Vec3f_32 multVec = vtkm::MatrixMultiply(termVec, matrix); + // std::cout << multVec << std::endl; + VTKM_TEST_ASSERT(test_equal(multVec, vtkm::make_Vec(1.0, 2.1, 3.2)), + "Unexpected product."); +} + +void Run() +{ + BuildMatrix(); +} + +} // anonymous namespace + +int GuideExampleMatrix(int argc, char* argv[]) +{ + return vtkm::testing::Testing::Run(Run, argc, argv); +} diff --git a/docs/users-guide/examples/GuideExampleNewtonsMethod.cxx b/docs/users-guide/examples/GuideExampleNewtonsMethod.cxx new file mode 100644 index 000000000..953299fc4 --- /dev/null +++ b/docs/users-guide/examples/GuideExampleNewtonsMethod.cxx @@ -0,0 +1,113 @@ +//============================================================================= +// +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +// +//============================================================================= + +#include +#include + +#include + +namespace +{ + +//// +//// BEGIN-EXAMPLE NewtonsMethod +//// +// A functor for the mathematical function f(x) = [dot(x,x),x[0]*x[1]] +struct FunctionFunctor +{ + template + VTKM_EXEC_CONT vtkm::Vec operator()(const vtkm::Vec& x) const + { + return vtkm::make_Vec(vtkm::Dot(x, x), x[0] * x[1]); + } +}; + +// A functor for the Jacobian of the mathematical function +// f(x) = [dot(x,x),x[0]*x[1]], which is +// | 2*x[0] 2*x[1] | +// | x[1] x[0] | +struct JacobianFunctor +{ + template + VTKM_EXEC_CONT vtkm::Matrix operator()(const vtkm::Vec& x) const + { + vtkm::Matrix jacobian; + jacobian(0, 0) = 2 * x[0]; + jacobian(0, 1) = 2 * x[1]; + jacobian(1, 0) = x[1]; + jacobian(1, 1) = x[0]; + + return jacobian; + } +}; + +VTKM_EXEC +void SolveNonlinear() +{ + // Use Newton's method to solve the nonlinear system of equations: + // + // x^2 + y^2 = 2 + // x*y = 1 + // + // There are two possible solutions, which are (x=1,y=1) and (x=-1,y=-1). + // The one found depends on the starting value. + vtkm::NewtonsMethodResult answer1 = + vtkm::NewtonsMethod(JacobianFunctor(), + FunctionFunctor(), + vtkm::make_Vec(2.0f, 1.0f), + vtkm::make_Vec(1.0f, 0.0f)); + if (!answer1.Valid || !answer1.Converged) + { + // Failed to find solution + //// PAUSE-EXAMPLE + VTKM_TEST_FAIL("Could not find answer1"); + //// RESUME-EXAMPLE + } + // answer1.Solution is [1,1] + + vtkm::NewtonsMethodResult answer2 = + vtkm::NewtonsMethod(JacobianFunctor(), + FunctionFunctor(), + vtkm::make_Vec(2.0f, 1.0f), + vtkm::make_Vec(0.0f, -2.0f)); + if (!answer2.Valid || !answer2.Converged) + { + // Failed to find solution + //// PAUSE-EXAMPLE + VTKM_TEST_FAIL("Could not find answer2"); + //// RESUME-EXAMPLE + } + // answer2 is [-1,-1] + //// PAUSE-EXAMPLE + std::cout << answer1.Solution << " " << answer2.Solution << std::endl; + + VTKM_TEST_ASSERT(test_equal(answer1.Solution, vtkm::make_Vec(1, 1), 0.01), + "Bad answer 1."); + VTKM_TEST_ASSERT(test_equal(answer2.Solution, vtkm::make_Vec(-1, -1), 0.01), + "Bad answer 2."); + //// RESUME-EXAMPLE +} +//// +//// END-EXAMPLE NewtonsMethod +//// + +void Run() +{ + SolveNonlinear(); +} + +} // anonymous namespace + +int GuideExampleNewtonsMethod(int argc, char* argv[]) +{ + return vtkm::testing::Testing::Run(Run, argc, argv); +} diff --git a/docs/users-guide/math.rst b/docs/users-guide/math.rst new file mode 100644 index 000000000..8aeafd33a --- /dev/null +++ b/docs/users-guide/math.rst @@ -0,0 +1,373 @@ +============================== +Math +============================== + +.. index:: math + +|VTKm| comes with several math functions that tend to be useful for visualization algorithms. +The implementation of basic math operations can vary subtly on different accelerators, and these functions provide cross platform support. + +All math functions are located in the ``vtkm`` package. +The functions are most useful in the execution environment, but they can also be used in the control environment when needed. + +------------------------------ +Basic Math +------------------------------ + +The :file:`vtkm/Math.h` header file contains several math functions that replicate the behavior of the basic POSIX math functions as well as related functionality. + +.. didyouknow:: + When writing worklets, you should favor using these math functions provided by |VTKm| over the standard math functions in :file:`vtkm/Math.h`. + |VTKm|'s implementation manages several compiling and efficiency issues when porting. + +Exponentials +============================== + +.. doxygenfunction:: vtkm::Exp(vtkm::Float32) +.. doxygenfunction:: vtkm::Exp(vtkm::Float64) +.. doxygenfunction:: vtkm::Exp(const T&) +.. doxygenfunction:: vtkm::Exp(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::Exp10(vtkm::Float32) +.. doxygenfunction:: vtkm::Exp10(vtkm::Float64) +.. doxygenfunction:: vtkm::Exp10(T) +.. doxygenfunction:: vtkm::Exp10(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::Exp2(vtkm::Float32) +.. doxygenfunction:: vtkm::Exp2(vtkm::Float64) +.. doxygenfunction:: vtkm::Exp2(const T&) +.. doxygenfunction:: vtkm::Exp2(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::ExpM1(vtkm::Float32) +.. doxygenfunction:: vtkm::ExpM1(vtkm::Float64) +.. doxygenfunction:: vtkm::ExpM1(const T&) +.. doxygenfunction:: vtkm::ExpM1(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::Log(vtkm::Float32) +.. doxygenfunction:: vtkm::Log(vtkm::Float64) +.. doxygenfunction:: vtkm::Log(const T&) +.. doxygenfunction:: vtkm::Log(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::Log10(vtkm::Float32) +.. doxygenfunction:: vtkm::Log10(vtkm::Float64) +.. doxygenfunction:: vtkm::Log10(const T&) +.. doxygenfunction:: vtkm::Log10(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::Log1P(vtkm::Float32) +.. doxygenfunction:: vtkm::Log1P(vtkm::Float64) +.. doxygenfunction:: vtkm::Log1P(const T&) +.. doxygenfunction:: vtkm::Log1P(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::Log2(vtkm::Float32) +.. doxygenfunction:: vtkm::Log2(vtkm::Float64) +.. doxygenfunction:: vtkm::Log2(const T&) +.. doxygenfunction:: vtkm::Log2(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::Pow(vtkm::Float32, vtkm::Float32) +.. doxygenfunction:: vtkm::Pow(vtkm::Float64, vtkm::Float64) + +Non-finites +============================== + +.. doxygenfunction:: Infinity +.. doxygenfunction:: Infinity32 +.. doxygenfunction:: Infinity64 + +.. doxygenfunction:: IsFinite +.. doxygenfunction:: IsInf +.. doxygenfunction:: IsNan +.. doxygenfunction:: IsNegative(vtkm::Float32) +.. doxygenfunction:: IsNegative(vtkm::Float64) + +.. doxygenfunction:: Nan +.. doxygenfunction:: Nan32 +.. doxygenfunction:: Nan64 + +.. doxygenfunction:: NegativeInfinity +.. doxygenfunction:: NegativeInfinity32 +.. doxygenfunction:: NegativeInfinity64 + +Polynomials +============================== + +.. doxygenfunction:: vtkm::Cbrt(vtkm::Float32) +.. doxygenfunction:: vtkm::Cbrt(vtkm::Float64) +.. doxygenfunction:: vtkm::Cbrt(const T&) +.. doxygenfunction:: vtkm::Cbrt(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::QuadraticRoots + +.. doxygenfunction:: vtkm::RCbrt(vtkm::Float32) +.. doxygenfunction:: vtkm::RCbrt(vtkm::Float64) +.. doxygenfunction:: vtkm::RCbrt(T) +.. doxygenfunction:: vtkm::RCbrt(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::RSqrt(vtkm::Float32) +.. doxygenfunction:: vtkm::RSqrt(vtkm::Float64) +.. doxygenfunction:: vtkm::RSqrt(T) +.. doxygenfunction:: vtkm::RSqrt(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::Sqrt(vtkm::Float32) +.. doxygenfunction:: vtkm::Sqrt(vtkm::Float64) +.. doxygenfunction:: vtkm::Sqrt(const T&) +.. doxygenfunction:: vtkm::Sqrt(const vtkm::Vec&) + +Remainders and Quotient +============================== + +.. doxygenfunction:: vtkm::ModF(vtkm::Float32, vtkm::Float32&) +.. doxygenfunction:: vtkm::ModF(vtkm::Float64, vtkm::Float64&) + +.. doxygenfunction:: vtkm::Remainder(vtkm::Float32, vtkm::Float32) +.. doxygenfunction:: vtkm::Remainder(vtkm::Float64, vtkm::Float64) + +.. doxygenfunction:: RemainderQuotient(vtkm::Float32, vtkm::Float32, QType&) +.. doxygenfunction:: RemainderQuotient(vtkm::Float64, vtkm::Float64, QType&) + +Rounding and Precision +============================== + +.. doxygenfunction:: vtkm::Ceil(vtkm::Float32) +.. doxygenfunction:: vtkm::Ceil(vtkm::Float64) +.. doxygenfunction:: vtkm::Ceil(const T&) +.. doxygenfunction:: vtkm::Ceil(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::CopySign(vtkm::Float32, vtkm::Float32) +.. doxygenfunction:: vtkm::CopySign(vtkm::Float64, vtkm::Float64) +.. doxygenfunction:: vtkm::CopySign(const vtkm::Vec&, const vtkm::Vec&) + +.. doxygenfunction:: Epsilon +.. doxygenfunction:: Epsilon32 +.. doxygenfunction:: Epsilon64 + +.. doxygenfunction:: vtkm::FMod(vtkm::Float32, vtkm::Float32) +.. doxygenfunction:: vtkm::FMod(vtkm::Float64, vtkm::Float64) + +.. doxygenfunction:: vtkm::Round(vtkm::Float32) +.. doxygenfunction:: vtkm::Round(vtkm::Float64) +.. doxygenfunction:: vtkm::Round(const T&) +.. doxygenfunction:: vtkm::Round(const vtkm::Vec&) + +Sign +============================== + +.. doxygenfunction:: vtkm::Abs(vtkm::Int32) +.. doxygenfunction:: vtkm::Abs(vtkm::Int64) +.. doxygenfunction:: vtkm::Abs(vtkm::Float32) +.. doxygenfunction:: vtkm::Abs(vtkm::Float64) +.. doxygenfunction:: vtkm::Abs(T) +.. doxygenfunction:: vtkm::Abs(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::Floor(vtkm::Float32) +.. doxygenfunction:: vtkm::Floor(vtkm::Float64) +.. doxygenfunction:: vtkm::Floor(const T&) +.. doxygenfunction:: vtkm::Floor(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::SignBit(vtkm::Float32) +.. doxygenfunction:: vtkm::SignBit(vtkm::Float64) + +Trigonometry +============================== + +.. doxygenfunction:: vtkm::ACos(vtkm::Float32) +.. doxygenfunction:: vtkm::ACos(vtkm::Float64) +.. doxygenfunction:: vtkm::ACos(const T&) +.. doxygenfunction:: vtkm::ACos(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::ACosH(vtkm::Float32) +.. doxygenfunction:: vtkm::ACosH(vtkm::Float64) +.. doxygenfunction:: vtkm::ACosH(const T&) +.. doxygenfunction:: vtkm::ACosH(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::ASin(vtkm::Float32) +.. doxygenfunction:: vtkm::ASin(vtkm::Float64) +.. doxygenfunction:: vtkm::ASin(const T&) +.. doxygenfunction:: vtkm::ASin(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::ASinH(vtkm::Float32) +.. doxygenfunction:: vtkm::ASinH(vtkm::Float64) +.. doxygenfunction:: vtkm::ASinH(const T&) +.. doxygenfunction:: vtkm::ASinH(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::ATan(vtkm::Float32) +.. doxygenfunction:: vtkm::ATan(vtkm::Float64) +.. doxygenfunction:: vtkm::ATan(const T&) +.. doxygenfunction:: vtkm::ATan(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::ATan2(vtkm::Float32, vtkm::Float32) +.. doxygenfunction:: vtkm::ATan2(vtkm::Float64, vtkm::Float64) + +.. doxygenfunction:: vtkm::ATanH(vtkm::Float32) +.. doxygenfunction:: vtkm::ATanH(vtkm::Float64) +.. doxygenfunction:: vtkm::ATanH(const T&) +.. doxygenfunction:: vtkm::ATanH(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::Cos(vtkm::Float32) +.. doxygenfunction:: vtkm::Cos(vtkm::Float64) +.. doxygenfunction:: vtkm::Cos(const T&) +.. doxygenfunction:: vtkm::Cos(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::CosH(vtkm::Float32) +.. doxygenfunction:: vtkm::CosH(vtkm::Float64) +.. doxygenfunction:: vtkm::CosH(const T&) +.. doxygenfunction:: vtkm::CosH(const vtkm::Vec&) + +.. doxygenfunction:: Pi +.. doxygenfunction:: Pi_2 +.. doxygenfunction:: Pi_3 +.. doxygenfunction:: Pi_4 +.. doxygenfunction:: Pi_180 + +.. doxygenfunction:: vtkm::Sin(vtkm::Float32) +.. doxygenfunction:: vtkm::Sin(vtkm::Float64) +.. doxygenfunction:: vtkm::Sin(const T&) +.. doxygenfunction:: vtkm::Sin(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::SinH(vtkm::Float32) +.. doxygenfunction:: vtkm::SinH(vtkm::Float64) +.. doxygenfunction:: vtkm::SinH(const T&) +.. doxygenfunction:: vtkm::SinH(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::Tan(vtkm::Float32) +.. doxygenfunction:: vtkm::Tan(vtkm::Float64) +.. doxygenfunction:: vtkm::Tan(const T&) +.. doxygenfunction:: vtkm::Tan(const vtkm::Vec&) + +.. doxygenfunction:: vtkm::TanH(vtkm::Float32) +.. doxygenfunction:: vtkm::TanH(vtkm::Float64) +.. doxygenfunction:: vtkm::TanH(const T&) +.. doxygenfunction:: vtkm::TanH(const vtkm::Vec&) + +.. doxygenfunction:: TwoPi + +Miscellaneous +============================== + +.. doxygenfunction:: FloatDistance(vtkm::Float64, vtkm::Float64) +.. doxygenfunction:: FloatDistance(vtkm::Float32, vtkm::Float32) + +.. doxygenfunction:: Max(const T&, const T&) +.. doxygenfunction:: Min(const T&, const T&) + + +------------------------------ +Vector Analysis +------------------------------ + +.. index:: vector analysis + +Visualization and computational geometry algorithms often perform vector analysis operations. +The :file:`vtkm/VectorAnalysis.h` header file provides functions that perform the basic common vector analysis operations. + +.. doxygenfunction:: vtkm::Cross +.. doxygenfunction:: vtkm::Lerp(const ValueType&, const ValueType&, const WeightType&) +.. doxygenfunction:: vtkm::Magnitude +.. doxygenfunction:: vtkm::MagnitudeSquared +.. doxygenfunction:: vtkm::Normal +.. doxygenfunction:: vtkm::Normalize +.. doxygenfunction:: vtkm::Orthonormalize +.. doxygenfunction:: vtkm::Project +.. doxygenfunction:: vtkm::ProjectedDistance +.. doxygenfunction:: vtkm::RMagnitude +.. doxygenfunction:: vtkm::TriangleNormal + + +------------------------------ +Matrices +------------------------------ + +.. index:: matrix + +Linear algebra operations on small matrices that are done on a single thread are located in :file:`vtkm/Matrix.h`. + +This header defines the :class:`vtkm::Matrix` templated class. +The template parameters are first the type of component, then the number of rows, then the number of columns. +The overloaded parentheses operator can be used to retrieve values based on row and column indices. +Likewise, the bracket operators can be used to reference the :class:`vtkm::Matrix` as a 2D array (indexed by row first). + +.. doxygenclass:: vtkm::Matrix + :members: + +The following example builds a :class:`vtkm::Matrix` that contains the values + +.. math:: + \left| + \begin{array}{ccc} + 0 & 1 & 2 \\ + 10 & 11 & 12 + \end{array} + \right| + +.. load-example:: BuildMatrix + :file: GuideExampleMatrix.cxx + :caption: Creating a :class:`vtkm::Matrix`. + +The :file:`vtkm/Matrix.h` header also defines the following functions +that operate on matrices. + +.. index:: + single: matrix; determinant + single: determinant + +.. doxygenfunction:: vtkm::MatrixDeterminant(const vtkm::Matrix&) + +.. doxygenfunction:: vtkm::MatrixGetColumn +.. doxygenfunction:: vtkm::MatrixGetRow + +.. index:: + double: identity; matrix + +.. doxygenfunction:: vtkm::MatrixIdentity() +.. doxygenfunction:: vtkm::MatrixIdentity(vtkm::Matrix&) + +.. index:: + double: inverse; matrix + +.. doxygenfunction:: vtkm::MatrixInverse + +.. doxygenfunction:: vtkm::MatrixMultiply(const vtkm::Matrix&, const vtkm::Matrix&) +.. doxygenfunction:: vtkm::MatrixMultiply(const vtkm::Matrix&, const vtkm::Vec&) +.. doxygenfunction:: vtkm::MatrixMultiply(const vtkm::Vec&, const vtkm::Matrix&) + +.. doxygenfunction:: vtkm::MatrixSetColumn +.. doxygenfunction:: vtkm::MatrixSetRow + +.. index:: + double: transpose; matrix + +.. doxygenfunction:: vtkm::MatrixTranspose + +.. index:: linear system + +.. doxygenfunction:: vtkm::SolveLinearSystem + + +------------------------------ +Newton's Method +------------------------------ + +.. index:: Newton's method + +|VTKm|'s matrix methods (documented in :secref:`math:Matrices`) +provide a method to solve a small linear system of equations. However, +sometimes it is necessary to solve a small nonlinear system of equations. +This can be done with the :func:`vtkm::NewtonsMethod` function defined in the +:file:`vtkm/NewtonsMethod.h` header. + +The :func:`vtkm::NewtonsMethod` function assumes that the number of +variables equals the number of equations. Newton's method operates on an +iterative evaluate and search. Evaluations are performed using the functors +passed into the :func:`vtkm::NewtonsMethod`. + +.. doxygenfunction:: vtkm::NewtonsMethod + +The :func:`vtkm::NewtonsMethod` function returns a \vtkm{NewtonsMethodResult} object. +\textidentifier{NewtonsMethodResult} is a \textcode{struct} templated on the type and number of input values of the nonlinear system. +\textidentifier{NewtonsMethodResult} contains the following items. + +.. doxygenstruct:: vtkm::NewtonsMethodResult + :members: + +.. load-example:: NewtonsMethod + :file: GuideExampleNewtonsMethod.cxx + :caption: Using :func:`vtkm::NewtonsMethod` to solve a small system of nonlinear equations. diff --git a/docs/users-guide/part-advanced.rst b/docs/users-guide/part-advanced.rst index 9e624e9c5..bb06efd85 100644 --- a/docs/users-guide/part-advanced.rst +++ b/docs/users-guide/part-advanced.rst @@ -9,3 +9,4 @@ Advanced Development logging.rst worklet-types.rst worklet-error-handling.rst + math.rst diff --git a/vtkm/Math.h b/vtkm/Math.h index 7093d7f7c..e59ccde72 100644 --- a/vtkm/Math.h +++ b/vtkm/Math.h @@ -159,6 +159,7 @@ static constexpr inline VTKM_EXEC_CONT vtkm::Float32 Pi_180f() // clang-format off +///@{ /// Compute the sine of \p x. /// @@ -217,7 +218,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::Sin(x[0]), vtkm::Sin(x[1])); } +///@} +///@{ /// Compute the cosine of \p x. /// @@ -276,7 +279,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::Cos(x[0]), vtkm::Cos(x[1])); } +///@} +///@{ /// Compute the tangent of \p x. /// @@ -335,7 +340,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::Tan(x[0]), vtkm::Tan(x[1])); } +///@} +///@{ /// Compute the arc sine of \p x. /// @@ -394,7 +401,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::ASin(x[0]), vtkm::ASin(x[1])); } +///@} +///@{ /// Compute the arc cosine of \p x. /// @@ -453,7 +462,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::ACos(x[0]), vtkm::ACos(x[1])); } +///@} +///@{ /// Compute the arc tangent of \p x. /// @@ -512,7 +523,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::ATan(x[0]), vtkm::ATan(x[1])); } +///@} +///@{ /// Compute the arc tangent of \p x / \p y using the signs of both arguments /// to determine the quadrant of the return value. /// @@ -532,7 +545,9 @@ static inline VTKM_EXEC_CONT vtkm::Float64 ATan2(vtkm::Float64 x, vtkm::Float64 return std::atan2(x, y); #endif } +///@} +///@{ /// Compute the hyperbolic sine of \p x. /// @@ -591,7 +606,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::SinH(x[0]), vtkm::SinH(x[1])); } +///@} +///@{ /// Compute the hyperbolic cosine of \p x. /// @@ -650,7 +667,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::CosH(x[0]), vtkm::CosH(x[1])); } +///@} +///@{ /// Compute the hyperbolic tangent of \p x. /// @@ -709,7 +728,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::TanH(x[0]), vtkm::TanH(x[1])); } +///@} +///@{ /// Compute the hyperbolic arc sine of \p x. /// @@ -768,7 +789,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::ASinH(x[0]), vtkm::ASinH(x[1])); } +///@} +///@{ /// Compute the hyperbolic arc cosine of \p x. /// @@ -827,7 +850,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::ACosH(x[0]), vtkm::ACosH(x[1])); } +///@} +///@{ /// Compute the hyperbolic arc tangent of \p x. /// @@ -886,8 +911,10 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::ATanH(x[0]), vtkm::ATanH(x[1])); } +///@} //----------------------------------------------------------------------------- +///@{ /// Computes \p x raised to the power of \p y. /// static inline VTKM_EXEC_CONT vtkm::Float32 Pow(vtkm::Float32 x, vtkm::Float32 y) @@ -906,9 +933,12 @@ static inline VTKM_EXEC_CONT vtkm::Float64 Pow(vtkm::Float64 x, vtkm::Float64 y) return std::pow(x, y); #endif } +///@} +///@{ /// Compute the square root of \p x. -/// +/// On some hardware it is faster to find the reciprocal square root, so `RSqrt` +/// should be used if you actually plan to divide by the square root. inline VTKM_EXEC_CONT vtkm::Float32 Sqrt(vtkm::Float32 x) { @@ -965,7 +995,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::Sqrt(x[0]), vtkm::Sqrt(x[1])); } +///@} +///@{ /// Compute the reciprocal square root of \p x. The result of this function is /// equivalent to 1/Sqrt(x). However, on some devices it is faster to /// compute the reciprocal square root than the regular square root. Thus, you @@ -1033,7 +1065,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::RSqrt(x[0]), vtkm::RSqrt(x[1])); } +///@} +///@{ /// Compute the cube root of \p x. /// @@ -1092,7 +1126,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::Cbrt(x[0]), vtkm::Cbrt(x[1])); } +///@} +///@{ /// Compute the reciprocal cube root of \p x. The result of this function is /// equivalent to 1/Cbrt(x). However, on some devices it is faster to /// compute the reciprocal cube root than the regular cube root. Thus, you @@ -1160,8 +1196,10 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::RCbrt(x[0]), vtkm::RCbrt(x[1])); } +///@} -/// Computes e**\p x, the base-e exponential of \p x. +///@{ +/// Computes e^x, the base-e exponential of `x`. /// inline VTKM_EXEC_CONT vtkm::Float32 Exp(vtkm::Float32 x) @@ -1219,8 +1257,10 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::Exp(x[0]), vtkm::Exp(x[1])); } +///@} -/// Computes 2**\p x, the base-2 exponential of \p x. +///@{ +/// Computes 2^x, the base-2 exponential of `x`. /// inline VTKM_EXEC_CONT vtkm::Float32 Exp2(vtkm::Float32 x) @@ -1278,9 +1318,11 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::Exp2(x[0]), vtkm::Exp2(x[1])); } +///@} -/// Computes (e**\p x) - 1, the of base-e exponental of \p x then minus 1. The -/// accuracy of this function is good even for very small values of x. +///@{ +/// Computes (e^x) - 1, the of base-e exponental of `x` then minus 1. The +/// accuracy of this function is good even for very small values of `x`. /// inline VTKM_EXEC_CONT vtkm::Float32 ExpM1(vtkm::Float32 x) @@ -1338,8 +1380,10 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::ExpM1(x[0]), vtkm::ExpM1(x[1])); } +///@} -/// Computes 10**\p x, the base-10 exponential of \p x. +///@{ +/// Computes 10^x, the base-10 exponential of `x`. /// #ifdef VTKM_CUDA static inline VTKM_EXEC_CONT vtkm::Float32 Exp10(vtkm::Float32 x) @@ -1403,7 +1447,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::Exp10(x[0]), vtkm::Exp10(x[1])); } +///@} +///@{ /// Computes the natural logarithm of \p x. /// @@ -1462,7 +1508,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::Log(x[0]), vtkm::Log(x[1])); } +///@} +///@{ /// Computes the logarithm base 2 of \p x. /// @@ -1521,7 +1569,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::Log2(x[0]), vtkm::Log2(x[1])); } +///@} +///@{ /// Computes the logarithm base 10 of \p x. /// @@ -1580,9 +1630,11 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::Log10(x[0]), vtkm::Log10(x[1])); } +///@} -/// Computes the value of log(1+x) accurately for very small values of x. -/// +///@{ +/// Computes the value of log(1+x). This method is more accurate for very small values of x +/// than the `vtkm::Log` function. inline VTKM_EXEC_CONT vtkm::Float32 Log1P(vtkm::Float32 x) { @@ -1639,8 +1691,10 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::Log1P(x[0]), vtkm::Log1P(x[1])); } +///@} //----------------------------------------------------------------------------- +///@{ /// Returns \p x or \p y, whichever is larger. /// template @@ -1672,7 +1726,9 @@ static inline VTKM_EXEC_CONT vtkm::Float64 Max(vtkm::Float64 x, vtkm::Float64 y) #endif } #endif // !VTKM_USE_STL +///@} +///@{ /// Returns \p x or \p y, whichever is smaller. /// template @@ -1704,6 +1760,7 @@ static inline VTKM_EXEC_CONT vtkm::Float64 Min(vtkm::Float64 x, vtkm::Float64 y) #endif } #endif // !VTKM_USE_STL +///@} namespace detail { @@ -1764,9 +1821,9 @@ static inline VTKM_EXEC_CONT T Min(const T& x, const T& y) return detail::Min(x, y, typename vtkm::TypeTraits::DimensionalityTag()); } +///@{ /// Clamp \p x to the given range. /// - inline VTKM_EXEC_CONT vtkm::Float32 Clamp(vtkm::Float32 x, vtkm::Float32 lo, vtkm::Float32 hi) { return x > lo ? (x < hi ? x : hi) : lo; @@ -1776,6 +1833,8 @@ inline VTKM_EXEC_CONT vtkm::Float64 Clamp(vtkm::Float64 x, vtkm::Float64 lo, vtk { return x > lo ? (x < hi ? x : hi) : lo; } +///@} + //----------------------------------------------------------------------------- //#ifdef VTKM_CUDA @@ -1945,33 +2004,49 @@ struct FloatLimits> } // namespace detail -/// Returns the representation for not-a-number (NaN). -/// +/// Returns the representation for infinity. The result is greater than any other +/// number except another infinity or NaN. When comparing two infinities or infinity +/// to NaN, neither is greater than, less than, nor equal to the other. The +/// `Infinity` method is templated to specify either a 32 or 64 bit floating point +/// number. The convenience methods `Infinity32` and`Infinity64` are non-templated +/// versions that return the precision for a particular precision. template static inline VTKM_EXEC_CONT T Nan() { return detail::FloatLimits::Nan(); } -/// Returns the representation for infinity. -/// +/// Returns the representation for infinity. The result is greater than any other +/// number except another infinity or NaN. When comparing two infinities or infinity +/// to NaN, neither is greater than, less than, nor equal to the other. The +/// `Infinity` method is templated to specify either a 32 or 64 bit floating point +/// number. The convenience methods `Infinity32` and`Infinity64` are non-templated +/// versions that return the precision for a particular precision. template static inline VTKM_EXEC_CONT T Infinity() { return detail::FloatLimits::Infinity(); } -/// Returns the representation for negative infinity. -/// +/// Returns the representation for negative infinity. The result is less than any +/// other number except another negative infinity or NaN. When comparing two +/// negative infinities or negative infinity to NaN, neither is greater than, less +/// than, nor equal to the other. The `NegativeInfinity` method is templated to +/// specify either a 32 or 64 bit floating point number. The convenience methods +/// `NegativeInfinity32` and`NegativeInfinity64` are non-templated versions that +/// return the precision for a particular precision. template static inline VTKM_EXEC_CONT T NegativeInfinity() { return detail::FloatLimits::NegativeInfinity(); } -/// Returns the difference between 1 and the least value greater than 1 -/// that is representable. -/// +/// Returns the difference between 1 and the least value greater than 1 that +/// is representable by a floating point number. Epsilon is useful for specifying +/// the tolerance one should have when considering numerical error. The `Epsilon` +/// method is templated to specify either a 32 or 64 bit floating point number. The +/// convenience methods `Epsilon32` and`Epsilon64` are non-templated versions that +/// return the precision for a particular precision. template static inline VTKM_EXEC_CONT T Epsilon() { @@ -1980,33 +2055,49 @@ static inline VTKM_EXEC_CONT T Epsilon() #else // !VTKM_USE_IEEE_NONFINITE -/// Returns the representation for not-a-number (NaN). -/// +/// Returns the representation for infinity. The result is greater than any other +/// number except another infinity or NaN. When comparing two infinities or infinity +/// to NaN, neither is greater than, less than, nor equal to the other. The +/// `Infinity` method is templated to specify either a 32 or 64 bit floating point +/// number. The convenience methods `Infinity32` and`Infinity64` are non-templated +/// versions that return the precision for a particular precision. template static inline VTKM_EXEC_CONT T Nan() { return std::numeric_limits::quiet_NaN(); } -/// Returns the representation for infinity. -/// +/// Returns the representation for infinity. The result is greater than any other +/// number except another infinity or NaN. When comparing two infinities or infinity +/// to NaN, neither is greater than, less than, nor equal to the other. The +/// `Infinity` method is templated to specify either a 32 or 64 bit floating point +/// number. The convenience methods `Infinity32` and`Infinity64` are non-templated +/// versions that return the precision for a particular precision. template static inline VTKM_EXEC_CONT T Infinity() { return std::numeric_limits::infinity(); } -/// Returns the representation for negative infinity. -/// +/// Returns the representation for negative infinity. The result is less than any +/// other number except another negative infinity or NaN. When comparing two +/// negative infinities or negative infinity to NaN, neither is greater than, less +/// than, nor equal to the other. The `NegativeInfinity` method is templated to +/// specify either a 32 or 64 bit floating point number. The convenience methods +/// `NegativeInfinity32` and`NegativeInfinity64` are non-templated versions that +/// return the precision for a particular precision. template static inline VTKM_EXEC_CONT T NegativeInfinity() { return -std::numeric_limits::infinity(); } -/// Returns the difference between 1 and the least value greater than 1 -/// that is representable. -/// +/// Returns the difference between 1 and the least value greater than 1 that +/// is representable by a floating point number. Epsilon is useful for specifying +/// the tolerance one should have when considering numerical error. The `Epsilon` +/// method is templated to specify either a 32 or 64 bit floating point number. The +/// convenience methods `Epsilon32` and`Epsilon64` are non-templated versions that +/// return the precision for a particular precision. template static inline VTKM_EXEC_CONT T Epsilon() { @@ -2014,46 +2105,45 @@ static inline VTKM_EXEC_CONT T Epsilon() } #endif // !VTKM_USE_IEEE_NONFINITE -/// Returns the representation for not-a-number (NaN). -/// +/// @copydoc Nan static inline VTKM_EXEC_CONT vtkm::Float32 Nan32() { return vtkm::Nan(); } +/// @copydoc Nan static inline VTKM_EXEC_CONT vtkm::Float64 Nan64() { return vtkm::Nan(); } -/// Returns the representation for infinity. -/// +/// @copydoc Infinity static inline VTKM_EXEC_CONT vtkm::Float32 Infinity32() { return vtkm::Infinity(); } +/// @copydoc Infinity static inline VTKM_EXEC_CONT vtkm::Float64 Infinity64() { return vtkm::Infinity(); } -/// Returns the representation for negative infinity. -/// +/// @copydoc NegativeInfinity static inline VTKM_EXEC_CONT vtkm::Float32 NegativeInfinity32() { return vtkm::NegativeInfinity(); } +/// @copydoc NegativeInfinity static inline VTKM_EXEC_CONT vtkm::Float64 NegativeInfinity64() { return vtkm::NegativeInfinity(); } -/// Returns the difference between 1 and the least value greater than 1 -/// that is representable. -/// +/// @copydoc Epsilon static inline VTKM_EXEC_CONT vtkm::Float32 Epsilon32() { return vtkm::Epsilon(); } +/// @copydoc Epsilon static inline VTKM_EXEC_CONT vtkm::Float64 Epsilon64() { return vtkm::Epsilon(); @@ -2094,6 +2184,7 @@ static inline VTKM_EXEC_CONT bool IsFinite(T x) } //----------------------------------------------------------------------------- +///@{ /// Round \p x to the smallest integer value not less than x. /// @@ -2152,7 +2243,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::Ceil(x[0]), vtkm::Ceil(x[1])); } +///@} +///@{ /// Round \p x to the largest integer value not greater than x. /// @@ -2211,7 +2304,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::Floor(x[0]), vtkm::Floor(x[1])); } +///@} +///@{ /// Round \p x to the nearest integral value. /// @@ -2270,8 +2365,10 @@ static inline VTKM_EXEC_CONT vtkm::Vec::Type, 2>(vtkm::Round(x[0]), vtkm::Round(x[1])); } +///@} //----------------------------------------------------------------------------- +///@{ /// Computes the remainder on division of 2 floating point numbers. The return /// value is \p numerator - n \p denominator, where n is the quotient of \p /// numerator divided by \p denominator rounded towards zero to an integer. For @@ -2293,7 +2390,9 @@ static inline VTKM_EXEC_CONT vtkm::Float64 FMod(vtkm::Float64 x, vtkm::Float64 y return std::fmod(x, y); #endif } +///@} +///@{ /// Computes the remainder on division of 2 floating point numbers. The return /// value is \p numerator - n \p denominator, where n is the quotient of \p /// numerator divided by \p denominator rounded towards the nearest integer @@ -2325,7 +2424,9 @@ static inline VTKM_EXEC_CONT vtkm::Float64 Remainder(vtkm::Float64 x, vtkm::Floa #endif } #endif // !VTKM_MSVC +///@} +///@{ /// Returns the remainder on division of 2 floating point numbers just like /// Remainder. In addition, this function also returns the \c quotient used to /// get that remainder. @@ -2361,7 +2462,9 @@ static inline VTKM_EXEC_CONT vtkm::Float64 RemainderQuotient(vtkm::Float64 numer quotient = static_cast(iQuotient); return result; } +///@} +///@{ /// Gets the integral and fractional parts of \c x. The return value is the /// fractional part and \c integral is set to the integral part. /// @@ -2382,8 +2485,10 @@ static inline VTKM_EXEC_CONT vtkm::Float64 ModF(vtkm::Float64 x, vtkm::Float64& return std::modf(x, &integral); #endif } +///@} //----------------------------------------------------------------------------- +///@{ /// Return the absolute value of \p x. That is, return \p x if it is positive or /// \p -x if it is negative. /// @@ -2451,7 +2556,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec Abs(const vtkm::Vec& x) { return vtkm::Vec(vtkm::Abs(x[0]), vtkm::Abs(x[1])); } +///@} +///@{ /// Returns a nonzero value if \p x is negative. /// static inline VTKM_EXEC_CONT vtkm::Int32 SignBit(vtkm::Float32 x) @@ -2468,7 +2575,9 @@ static inline VTKM_EXEC_CONT vtkm::Int32 SignBit(vtkm::Float64 x) #endif return static_cast(signbit(x)); } +///@} +///@{ /// Returns true if \p x is less than zero, false otherwise. /// static inline VTKM_EXEC_CONT bool IsNegative(vtkm::Float32 x) @@ -2479,7 +2588,9 @@ static inline VTKM_EXEC_CONT bool IsNegative(vtkm::Float64 x) { return (vtkm::SignBit(x) != 0); } +///@} +///@{ /// Copies the sign of \p y onto \p x. If \p y is positive, returns Abs(\p x). /// If \p y is negative, returns -Abs(\p x). /// @@ -2511,10 +2622,11 @@ static inline VTKM_EXEC_CONT vtkm::Vec CopySign(const vtkm::Vec& x, } return result; } +///@} +///@{ /// Decompose floating poing value /// - inline VTKM_EXEC_CONT vtkm::Float32 Frexp(vtkm::Float32 x, vtkm::Int32 *exponent) { // See: https://github.com/ROCm-Developer-Tools/HIP/issues/2169 @@ -2533,6 +2645,7 @@ inline VTKM_EXEC_CONT vtkm::Float64 Frexp(vtkm::Float64 x, vtkm::Int32 *exponent return std::frexp(x, exponent); #endif } +///@} inline VTKM_EXEC_CONT vtkm::Float32 Ldexp(vtkm::Float32 x, vtkm::Int32 exponent) { @@ -2601,6 +2714,9 @@ inline VTKM_EXEC_CONT vtkm::UInt64 FloatDistancePositive(vtkm::Float32 x, vtkm:: } // namespace detail +/// Computes the number of representables between two floating point numbers. This function +/// is non-negative and symmetric in its arguments. If either argument is non-finite, the +/// value returned is the maximum value allowed by 64-bit unsigned integers: 2^64-1. inline VTKM_EXEC_CONT vtkm::UInt64 FloatDistance(vtkm::Float64 x, vtkm::Float64 y) { static_assert(sizeof(vtkm::Float64) == sizeof(vtkm::UInt64), "vtkm::Float64 is incorrect size."); @@ -2640,6 +2756,7 @@ inline VTKM_EXEC_CONT vtkm::UInt64 FloatDistance(vtkm::Float64 x, vtkm::Float64 return detail::FloatDistancePositive(x, y); } +/// @copydoc FloatDistance inline VTKM_EXEC_CONT vtkm::UInt64 FloatDistance(vtkm::Float32 x, vtkm::Float32 y) { static_assert(sizeof(vtkm::Float32) == sizeof(vtkm::Int32), "vtkm::Float32 is incorrect size."); @@ -2688,11 +2805,14 @@ inline VTKM_EXEC_CONT T DifferenceOfProducts(T a, T b, T c, T d) return dop + err; } -// Solves ax² + bx + c = 0. -// Only returns the real roots. -// If there are real roots, the first element of the pair is <= the second. -// If there are no real roots, both elements are NaNs. -// The error should be at most 3 ulps. +/// @brief Solves ax² + bx + c = 0. +/// +/// Only returns the real roots. +/// If there are real roots, the first element of the pair is less than or equal to the second. +/// If there are no real roots, both elements are NaNs. +/// If VTK-m is compiled with FMA support, each root is accurate to 3 ulps; otherwise +/// the discriminant is prone to catastrophic subtractive cancellation and no accuracy +/// guarantees can be provided. template inline VTKM_EXEC_CONT vtkm::Vec QuadraticRoots(T a, T b, T c) { diff --git a/vtkm/Math.h.in b/vtkm/Math.h.in index 5da53a386..a82e7d87f 100644 --- a/vtkm/Math.h.in +++ b/vtkm/Math.h.in @@ -309,74 +309,106 @@ static constexpr inline VTKM_EXEC_CONT vtkm::Float32 Pi_180f() // clang-format off +///@{ /// Compute the sine of \p x. /// $unary_math_function('Sin', 'sin')\ +///@} +///@{ /// Compute the cosine of \p x. /// $unary_math_function('Cos', 'cos')\ +///@} +///@{ /// Compute the tangent of \p x. /// $unary_math_function('Tan', 'tan')\ +///@} +///@{ /// Compute the arc sine of \p x. /// $unary_math_function('ASin', 'asin')\ +///@} +///@{ /// Compute the arc cosine of \p x. /// $unary_math_function('ACos', 'acos')\ +///@} +///@{ /// Compute the arc tangent of \p x. /// $unary_math_function('ATan', 'atan')\ +///@} +///@{ /// Compute the arc tangent of \p x / \p y using the signs of both arguments /// to determine the quadrant of the return value. /// $binary_math_function('ATan2', 'atan2')\ +///@} +///@{ /// Compute the hyperbolic sine of \p x. /// $unary_math_function('SinH', 'sinh')\ +///@} +///@{ /// Compute the hyperbolic cosine of \p x. /// $unary_math_function('CosH', 'cosh')\ +///@} +///@{ /// Compute the hyperbolic tangent of \p x. /// $unary_math_function('TanH', 'tanh')\ +///@} +///@{ /// Compute the hyperbolic arc sine of \p x. /// $unary_math_function_no_vec('ASinH', 'asinh')\ $# $unary_Vec_function('ASinH')\ +///@} +///@{ /// Compute the hyperbolic arc cosine of \p x. /// $unary_math_function_no_vec('ACosH', 'acosh')\ $# $unary_Vec_function('ACosH')\ +///@} +///@{ /// Compute the hyperbolic arc tangent of \p x. /// $unary_math_function_no_vec('ATanH', 'atanh')\ $# $unary_Vec_function('ATanH')\ +///@} //----------------------------------------------------------------------------- +///@{ /// Computes \p x raised to the power of \p y. /// $binary_math_function('Pow', 'pow')\ +///@} +///@{ /// Compute the square root of \p x. -/// +/// On some hardware it is faster to find the reciprocal square root, so `RSqrt` +/// should be used if you actually plan to divide by the square root. $unary_math_function('Sqrt', 'sqrt')\ +///@} +///@{ /// Compute the reciprocal square root of \p x. The result of this function is /// equivalent to 1/Sqrt(x). However, on some devices it is faster to /// compute the reciprocal square root than the regular square root. Thus, you @@ -413,13 +445,17 @@ static inline VTKM_EXEC_CONT vtkm::Float64 RSqrt(T x) #endif // !VTKM_CUDA $unary_Vec_function('RSqrt')\ +///@} +///@{ /// Compute the cube root of \p x. /// $unary_math_function_no_vec('Cbrt', 'cbrt')\ $# $unary_Vec_function('Cbrt')\ +///@} +///@{ /// Compute the reciprocal cube root of \p x. The result of this function is /// equivalent to 1/Cbrt(x). However, on some devices it is faster to /// compute the reciprocal cube root than the regular cube root. Thus, you @@ -456,25 +492,33 @@ static inline VTKM_EXEC_CONT vtkm::Float64 RCbrt(T x) #endif // !VTKM_CUDA $unary_Vec_function('RCbrt')\ +///@} -/// Computes e**\p x, the base-e exponential of \p x. +///@{ +/// Computes e^x, the base-e exponential of `x`. /// $unary_math_function('Exp', 'exp')\ +///@} -/// Computes 2**\p x, the base-2 exponential of \p x. +///@{ +/// Computes 2^x, the base-2 exponential of `x`. /// $unary_math_function_no_vec('Exp2', 'exp2')\ $# $unary_Vec_function('Exp2')\ +///@} -/// Computes (e**\p x) - 1, the of base-e exponental of \p x then minus 1. The -/// accuracy of this function is good even for very small values of x. +///@{ +/// Computes (e^x) - 1, the of base-e exponental of `x` then minus 1. The +/// accuracy of this function is good even for very small values of `x`. /// $unary_math_function_no_vec('ExpM1', 'expm1')\ $# $unary_Vec_function('ExpM1')\ +///@} -/// Computes 10**\p x, the base-10 exponential of \p x. +///@{ +/// Computes 10^x, the base-10 exponential of `x`. /// #ifdef VTKM_CUDA static inline VTKM_EXEC_CONT vtkm::Float32 Exp10(vtkm::Float32 x) @@ -507,28 +551,38 @@ static inline VTKM_EXEC_CONT vtkm::Float64 Exp10(T x) #endif // !VTKM_CUDA $unary_Vec_function('Exp10')\ +///@} +///@{ /// Computes the natural logarithm of \p x. /// $unary_math_function('Log', 'log')\ +///@} +///@{ /// Computes the logarithm base 2 of \p x. /// $unary_math_function_no_vec('Log2', 'log2')\ $# $unary_Vec_function('Log2')\ +///@} +///@{ /// Computes the logarithm base 10 of \p x. /// $unary_math_function('Log10', 'log10')\ +///@} -/// Computes the value of log(1+x) accurately for very small values of x. -/// +///@{ +/// Computes the value of log(1+x). This method is more accurate for very small values of x +/// than the `vtkm::Log` function. $unary_math_function_no_vec('Log1P', 'log1p')\ $# $unary_Vec_function('Log1P')\ +///@} //----------------------------------------------------------------------------- +///@{ /// Returns \p x or \p y, whichever is larger. /// template @@ -540,7 +594,9 @@ $# $binary_math_function('Max', 'fmax')\ $# #endif // !VTKM_USE_STL +///@} +///@{ /// Returns \p x or \p y, whichever is smaller. /// template @@ -552,6 +608,7 @@ $# $binary_math_function('Min', 'fmin')\ $# #endif // !VTKM_USE_STL +///@} namespace detail { @@ -612,9 +669,9 @@ static inline VTKM_EXEC_CONT T Min(const T& x, const T& y) return detail::Min(x, y, typename vtkm::TypeTraits::DimensionalityTag()); } +///@{ /// Clamp \p x to the given range. /// - inline VTKM_EXEC_CONT vtkm::Float32 Clamp(vtkm::Float32 x, vtkm::Float32 lo, vtkm::Float32 hi) { return x > lo ? (x < hi ? x : hi) : lo; @@ -624,6 +681,8 @@ inline VTKM_EXEC_CONT vtkm::Float64 Clamp(vtkm::Float64 x, vtkm::Float64 lo, vtk { return x > lo ? (x < hi ? x : hi) : lo; } +///@} + //----------------------------------------------------------------------------- //#ifdef VTKM_CUDA @@ -793,33 +852,49 @@ struct FloatLimits> } // namespace detail -/// Returns the representation for not-a-number (NaN). -/// +/// Returns the representation for infinity. The result is greater than any other +/// number except another infinity or NaN. When comparing two infinities or infinity +/// to NaN, neither is greater than, less than, nor equal to the other. The +/// `Infinity` method is templated to specify either a 32 or 64 bit floating point +/// number. The convenience methods `Infinity32` and`Infinity64` are non-templated +/// versions that return the precision for a particular precision. template static inline VTKM_EXEC_CONT T Nan() { return detail::FloatLimits::Nan(); } -/// Returns the representation for infinity. -/// +/// Returns the representation for infinity. The result is greater than any other +/// number except another infinity or NaN. When comparing two infinities or infinity +/// to NaN, neither is greater than, less than, nor equal to the other. The +/// `Infinity` method is templated to specify either a 32 or 64 bit floating point +/// number. The convenience methods `Infinity32` and`Infinity64` are non-templated +/// versions that return the precision for a particular precision. template static inline VTKM_EXEC_CONT T Infinity() { return detail::FloatLimits::Infinity(); } -/// Returns the representation for negative infinity. -/// +/// Returns the representation for negative infinity. The result is less than any +/// other number except another negative infinity or NaN. When comparing two +/// negative infinities or negative infinity to NaN, neither is greater than, less +/// than, nor equal to the other. The `NegativeInfinity` method is templated to +/// specify either a 32 or 64 bit floating point number. The convenience methods +/// `NegativeInfinity32` and`NegativeInfinity64` are non-templated versions that +/// return the precision for a particular precision. template static inline VTKM_EXEC_CONT T NegativeInfinity() { return detail::FloatLimits::NegativeInfinity(); } -/// Returns the difference between 1 and the least value greater than 1 -/// that is representable. -/// +/// Returns the difference between 1 and the least value greater than 1 that +/// is representable by a floating point number. Epsilon is useful for specifying +/// the tolerance one should have when considering numerical error. The `Epsilon` +/// method is templated to specify either a 32 or 64 bit floating point number. The +/// convenience methods `Epsilon32` and`Epsilon64` are non-templated versions that +/// return the precision for a particular precision. template static inline VTKM_EXEC_CONT T Epsilon() { @@ -828,33 +903,49 @@ static inline VTKM_EXEC_CONT T Epsilon() #else // !VTKM_USE_IEEE_NONFINITE -/// Returns the representation for not-a-number (NaN). -/// +/// Returns the representation for infinity. The result is greater than any other +/// number except another infinity or NaN. When comparing two infinities or infinity +/// to NaN, neither is greater than, less than, nor equal to the other. The +/// `Infinity` method is templated to specify either a 32 or 64 bit floating point +/// number. The convenience methods `Infinity32` and`Infinity64` are non-templated +/// versions that return the precision for a particular precision. template static inline VTKM_EXEC_CONT T Nan() { return std::numeric_limits::quiet_NaN(); } -/// Returns the representation for infinity. -/// +/// Returns the representation for infinity. The result is greater than any other +/// number except another infinity or NaN. When comparing two infinities or infinity +/// to NaN, neither is greater than, less than, nor equal to the other. The +/// `Infinity` method is templated to specify either a 32 or 64 bit floating point +/// number. The convenience methods `Infinity32` and`Infinity64` are non-templated +/// versions that return the precision for a particular precision. template static inline VTKM_EXEC_CONT T Infinity() { return std::numeric_limits::infinity(); } -/// Returns the representation for negative infinity. -/// +/// Returns the representation for negative infinity. The result is less than any +/// other number except another negative infinity or NaN. When comparing two +/// negative infinities or negative infinity to NaN, neither is greater than, less +/// than, nor equal to the other. The `NegativeInfinity` method is templated to +/// specify either a 32 or 64 bit floating point number. The convenience methods +/// `NegativeInfinity32` and`NegativeInfinity64` are non-templated versions that +/// return the precision for a particular precision. template static inline VTKM_EXEC_CONT T NegativeInfinity() { return -std::numeric_limits::infinity(); } -/// Returns the difference between 1 and the least value greater than 1 -/// that is representable. -/// +/// Returns the difference between 1 and the least value greater than 1 that +/// is representable by a floating point number. Epsilon is useful for specifying +/// the tolerance one should have when considering numerical error. The `Epsilon` +/// method is templated to specify either a 32 or 64 bit floating point number. The +/// convenience methods `Epsilon32` and`Epsilon64` are non-templated versions that +/// return the precision for a particular precision. template static inline VTKM_EXEC_CONT T Epsilon() { @@ -862,46 +953,45 @@ static inline VTKM_EXEC_CONT T Epsilon() } #endif // !VTKM_USE_IEEE_NONFINITE -/// Returns the representation for not-a-number (NaN). -/// +/// @copydoc Nan static inline VTKM_EXEC_CONT vtkm::Float32 Nan32() { return vtkm::Nan(); } +/// @copydoc Nan static inline VTKM_EXEC_CONT vtkm::Float64 Nan64() { return vtkm::Nan(); } -/// Returns the representation for infinity. -/// +/// @copydoc Infinity static inline VTKM_EXEC_CONT vtkm::Float32 Infinity32() { return vtkm::Infinity(); } +/// @copydoc Infinity static inline VTKM_EXEC_CONT vtkm::Float64 Infinity64() { return vtkm::Infinity(); } -/// Returns the representation for negative infinity. -/// +/// @copydoc NegativeInfinity static inline VTKM_EXEC_CONT vtkm::Float32 NegativeInfinity32() { return vtkm::NegativeInfinity(); } +/// @copydoc NegativeInfinity static inline VTKM_EXEC_CONT vtkm::Float64 NegativeInfinity64() { return vtkm::NegativeInfinity(); } -/// Returns the difference between 1 and the least value greater than 1 -/// that is representable. -/// +/// @copydoc Epsilon static inline VTKM_EXEC_CONT vtkm::Float32 Epsilon32() { return vtkm::Epsilon(); } +/// @copydoc Epsilon static inline VTKM_EXEC_CONT vtkm::Float64 Epsilon64() { return vtkm::Epsilon(); @@ -942,28 +1032,37 @@ static inline VTKM_EXEC_CONT bool IsFinite(T x) } //----------------------------------------------------------------------------- +///@{ /// Round \p x to the smallest integer value not less than x. /// $unary_math_function('Ceil', 'ceil')\ +///@} +///@{ /// Round \p x to the largest integer value not greater than x. /// $unary_math_function('Floor', 'floor')\ +///@} +///@{ /// Round \p x to the nearest integral value. /// $unary_math_function_no_vec('Round', 'round')\ $# $unary_Vec_function('Round')\ +///@} //----------------------------------------------------------------------------- +///@{ /// Computes the remainder on division of 2 floating point numbers. The return /// value is \p numerator - n \p denominator, where n is the quotient of \p /// numerator divided by \p denominator rounded towards zero to an integer. For /// example, FMod(6.5, 2.3) returns 1.9, which is 6.5 - 2*2.3. /// $binary_math_function('FMod', 'fmod')\ +///@} +///@{ /// Computes the remainder on division of 2 floating point numbers. The return /// value is \p numerator - n \p denominator, where n is the quotient of \p /// numerator divided by \p denominator rounded towards the nearest integer @@ -981,7 +1080,9 @@ static inline VTKM_EXEC_CONT T Remainder(T numerator, T denominator) $binary_math_function('Remainder', 'remainder')\ $# #endif // !VTKM_MSVC +///@} +///@{ /// Returns the remainder on division of 2 floating point numbers just like /// Remainder. In addition, this function also returns the \c quotient used to /// get that remainder. @@ -1017,7 +1118,9 @@ static inline VTKM_EXEC_CONT vtkm::Float64 RemainderQuotient(vtkm::Float64 numer quotient = static_cast(iQuotient); return result; } +///@} +///@{ /// Gets the integral and fractional parts of \c x. The return value is the /// fractional part and \c integral is set to the integral part. /// @@ -1038,8 +1141,10 @@ static inline VTKM_EXEC_CONT vtkm::Float64 ModF(vtkm::Float64 x, vtkm::Float64& return std::modf(x, &integral); #endif } +///@} //----------------------------------------------------------------------------- +///@{ /// Return the absolute value of \p x. That is, return \p x if it is positive or /// \p -x if it is negative. /// @@ -1107,7 +1212,9 @@ static inline VTKM_EXEC_CONT vtkm::Vec Abs(const vtkm::Vec& x) { return vtkm::Vec(vtkm::Abs(x[0]), vtkm::Abs(x[1])); } +///@} +///@{ /// Returns a nonzero value if \p x is negative. /// $unary_template_function_no_vec('SignBit', @@ -1117,11 +1224,15 @@ $unary_template_function_no_vec('SignBit', using std::signbit; #endif ''')\ +///@} +///@{ /// Returns true if \p x is less than zero, false otherwise. /// $unary_template_function_no_vec('IsNegative', '(vtkm::SignBit(x) != 0)', 'bool')\ +///@} +///@{ /// Copies the sign of \p y onto \p x. If \p y is positive, returns Abs(\p x). /// If \p y is negative, returns -Abs(\p x). /// @@ -1139,10 +1250,11 @@ static inline VTKM_EXEC_CONT vtkm::Vec CopySign(const vtkm::Vec& x, } return result; } +///@} +///@{ /// Decompose floating poing value /// - inline VTKM_EXEC_CONT vtkm::Float32 Frexp(vtkm::Float32 x, vtkm::Int32 *exponent) { // See: https://github.com/ROCm-Developer-Tools/HIP/issues/2169 @@ -1161,6 +1273,7 @@ inline VTKM_EXEC_CONT vtkm::Float64 Frexp(vtkm::Float64 x, vtkm::Int32 *exponent return std::frexp(x, exponent); #endif } +///@} inline VTKM_EXEC_CONT vtkm::Float32 Ldexp(vtkm::Float32 x, vtkm::Int32 exponent) { @@ -1229,6 +1342,9 @@ inline VTKM_EXEC_CONT vtkm::UInt64 FloatDistancePositive(vtkm::Float32 x, vtkm:: } // namespace detail +/// Computes the number of representables between two floating point numbers. This function +/// is non-negative and symmetric in its arguments. If either argument is non-finite, the +/// value returned is the maximum value allowed by 64-bit unsigned integers: 2^64-1. inline VTKM_EXEC_CONT vtkm::UInt64 FloatDistance(vtkm::Float64 x, vtkm::Float64 y) { static_assert(sizeof(vtkm::Float64) == sizeof(vtkm::UInt64), "vtkm::Float64 is incorrect size."); @@ -1268,6 +1384,7 @@ inline VTKM_EXEC_CONT vtkm::UInt64 FloatDistance(vtkm::Float64 x, vtkm::Float64 return detail::FloatDistancePositive(x, y); } +/// @copydoc FloatDistance inline VTKM_EXEC_CONT vtkm::UInt64 FloatDistance(vtkm::Float32 x, vtkm::Float32 y) { static_assert(sizeof(vtkm::Float32) == sizeof(vtkm::Int32), "vtkm::Float32 is incorrect size."); @@ -1316,11 +1433,14 @@ inline VTKM_EXEC_CONT T DifferenceOfProducts(T a, T b, T c, T d) return dop + err; } -// Solves ax² + bx + c = 0. -// Only returns the real roots. -// If there are real roots, the first element of the pair is <= the second. -// If there are no real roots, both elements are NaNs. -// The error should be at most 3 ulps. +/// @brief Solves ax² + bx + c = 0. +/// +/// Only returns the real roots. +/// If there are real roots, the first element of the pair is less than or equal to the second. +/// If there are no real roots, both elements are NaNs. +/// If VTK-m is compiled with FMA support, each root is accurate to 3 ulps; otherwise +/// the discriminant is prone to catastrophic subtractive cancellation and no accuracy +/// guarantees can be provided. template inline VTKM_EXEC_CONT vtkm::Vec QuadraticRoots(T a, T b, T c) { diff --git a/vtkm/Matrix.h b/vtkm/Matrix.h index 9e50839d9..ccac8864b 100644 --- a/vtkm/Matrix.h +++ b/vtkm/Matrix.h @@ -19,7 +19,7 @@ namespace vtkm { -/// \brief Basic Matrix type. +/// @brief Basic Matrix type. /// /// The Matrix class holds a small two dimensional array for simple linear /// algebra and vector operations. VTK-m provides several Matrix-based @@ -37,9 +37,11 @@ public: static constexpr vtkm::IdComponent NUM_ROWS = NumRow; static constexpr vtkm::IdComponent NUM_COLUMNS = NumCol; + /// Creates an uninitialized matrix. The values in the matrix are not determined. VTKM_EXEC_CONT Matrix() {} + /// Creates a matrix initialized with all values set to the provided `value`. VTKM_EXEC_CONT explicit Matrix(const ComponentType& value) : Components(vtkm::Vec(value)) @@ -110,7 +112,7 @@ VTKM_EXEC_CONT const vtkm::Vec& MatrixGetRow( } /// Returns a tuple containing the given column (indexed from 0) of the given -/// matrix. Might not be as efficient as the \c MatrixGetRow function. +/// matrix. Might not be as efficient as the `MatrixGetRow()` function. /// template VTKM_EXEC_CONT vtkm::Vec MatrixGetColumn(const vtkm::Matrix& matrix, @@ -439,7 +441,7 @@ VTKM_EXEC_CONT vtkm::Vec MatrixLUPSolve( } // namespace detail -/// Solve the linear system Ax = b for x. If a single solution is found, valid +/// Solve the linear system Ax = b for x. If a single solution is found, `valid` /// is set to true, false otherwise. /// template diff --git a/vtkm/NewtonsMethod.h b/vtkm/NewtonsMethod.h index 363e61072..05fa80544 100644 --- a/vtkm/NewtonsMethod.h +++ b/vtkm/NewtonsMethod.h @@ -16,11 +16,18 @@ namespace vtkm { +/// An object returned from `NewtonsMethod()` that contains the result and +/// other information about the final state. template struct NewtonsMethodResult { + /// True if Newton's method ran into a singularity. bool Valid; + /// True if Newton's method converted to below the convergence value. bool Converged; + /// The solution found by Newton's method. If `Converged` is false, + /// then this value is likely inaccurate. If `Valid` is false, then + /// this value is undefined. vtkm::Vec Solution; }; @@ -34,6 +41,23 @@ struct NewtonsMethodResult /// that evaluates to the desired output, or the closest point found, is /// returned. /// +/// @param[in] jacobianEvaluator A functor whose operation takes a `vtkm::Vec` +/// and returns a `vtkm::Matrix` containing the math function's +/// Jacobian vector at that point. +/// @param[in] functionEvaluator A functor whose operation takes a `vtkm::Vec` +/// and returns the evaluation of the math function at that point as +/// another `vtkm::Vec`. +/// @param[in] desiredFunctionOutput The desired output of the function. +/// @param[in] initialGuess The initial guess to search from. If not specified, +/// the origin is used. +/// @param[in] convergeDifference The convergence distance. If the iterative method +/// changes all values less than this amount. Once all values change less, +/// it considers the solution found. If not specified, set to 0.001. +/// @param[in] maxIterations The maximum amount of iterations to run before giving up and +/// returning the best solution found. If not specified, set to 10. +/// +/// @returns A `vtkm::NewtonsMethodResult` containing the best found result and state +/// about its validity. VTKM_SUPPRESS_EXEC_WARNINGS template v0 is returned if w=1 => v1 is returned. +/// `Lerp` returns the linear interpolation of two values based on a weight. If +/// `weight` is outside [0,1] then `Lerp` +/// extrapolates. If `weight`=0 then `value0` is returned. If `weight`=1 then +/// `value1` is returned. /// template inline VTKM_EXEC_CONT ValueType Lerp(const ValueType& value0, @@ -54,10 +54,10 @@ VTKM_EXEC_CONT vtkm::Vec Lerp(const vtkm::Vec& value } // ---------------------------------------------------------------------------- -/// \brief Returns the square of the magnitude of a vector. +/// @brief Returns the square of the magnitude of a vector. /// /// It is usually much faster to compute the square of the magnitude than the -/// square, so you should use this function in place of Magnitude or RMagnitude +/// magnitude, so you should use this function in place of Magnitude or RMagnitude /// when possible. /// template @@ -88,7 +88,7 @@ VTKM_EXEC_CONT typename detail::FloatingPointReturnType::Type MagnitudeTempla } // namespace detail -/// \brief Returns the magnitude of a vector. +/// @brief Returns the magnitude of a vector. /// /// It is usually much faster to compute MagnitudeSquared, so that should be /// substituted when possible (unless you are just going to take the square @@ -122,10 +122,11 @@ VTKM_EXEC_CONT typename detail::FloatingPointReturnType::Type RMagnitudeTempl } } // namespace detail -/// \brief Returns the reciprocal magnitude of a vector. +/// @brief Returns the reciprocal magnitude of a vector. /// -/// On some hardware RMagnitude is faster than Magnitude, but neither is -/// as fast as MagnitudeSquared. +/// On some hardware `RMagnitude` is faster than `Magnitude`, but neither is +/// as fast as `MagnitudeSquared`. This function works on scalars as well +/// as vectors, in which case it just returns the reciprocal of the scalar. /// template VTKM_EXEC_CONT typename detail::FloatingPointReturnType::Type RMagnitude(const T& x) @@ -149,7 +150,7 @@ VTKM_EXEC_CONT T NormalTemplate(const T& x, vtkm::TypeTraitsVectorTag) } } // namespace detail -/// \brief Returns a normalized version of the given vector. +/// @brief Returns a normalized version of the given vector. /// /// The resulting vector points in the same direction but has unit length. /// @@ -160,7 +161,7 @@ VTKM_EXEC_CONT T Normal(const T& x) } // ---------------------------------------------------------------------------- -/// \brief Changes a vector to be normal. +/// @brief Changes a vector to be normal. /// /// The given vector is scaled to be unit length. /// @@ -171,8 +172,10 @@ VTKM_EXEC_CONT void Normalize(T& x) } // ---------------------------------------------------------------------------- -/// \brief Find the cross product of two vectors. +/// @brief Find the cross product of two vectors. /// +/// If VTK-m is compiled with FMA support, it uses Kahan's difference of +/// products algorithm to achieve a maximum error of 1.5 ulps in each component. template VTKM_EXEC_CONT vtkm::Vec::Type, 3> Cross( const vtkm::Vec& x, @@ -185,7 +188,7 @@ VTKM_EXEC_CONT vtkm::Vec::Type, 3> C } //----------------------------------------------------------------------------- -/// \brief Find the normal of a triangle. +/// @brief Find the normal of a triangle. /// /// Given three coordinates in space, which, unless degenerate, uniquely define /// a triangle and the plane the triangle is on, returns a vector perpendicular @@ -193,7 +196,7 @@ VTKM_EXEC_CONT vtkm::Vec::Type, 3> C /// /// Note that the returned vector might not be a unit vector. In fact, the length /// is equal to twice the area of the triangle. If you want a unit vector, -/// send the result through the \c Normal function. +/// send the result through the `vtkm::Normal()` or `vtkm::Normalize()` function. /// template VTKM_EXEC_CONT vtkm::Vec::Type, 3> @@ -203,12 +206,12 @@ TriangleNormal(const vtkm::Vec& a, const vtkm::Vec& b, const vtkm::V } //----------------------------------------------------------------------------- -/// \brief Project a vector onto another vector. +/// @brief Project a vector onto another vector. /// /// This method computes the orthogonal projection of the vector v onto u; /// that is, it projects its first argument onto its second. /// -/// Note that if the vector \a u has zero length, the output +/// Note that if the vector `u` has zero length, the output /// vector will have all its entries equal to NaN. template VTKM_EXEC_CONT vtkm::Vec Project(const vtkm::Vec& v, const vtkm::Vec& u) @@ -221,12 +224,12 @@ VTKM_EXEC_CONT vtkm::Vec Project(const vtkm::Vec& v, const vtkm::Vec } //----------------------------------------------------------------------------- -/// \brief Project a vector onto another vector, returning only the projected distance. +/// @brief Project a vector onto another vector, returning only the projected distance. /// /// This method computes the orthogonal projection of the vector v onto u; /// that is, it projects its first argument onto its second. /// -/// Note that if the vector \a u has zero length, the output will be NaN. +/// Note that if the vector `u` has zero length, the output will be NaN. template VTKM_EXEC_CONT T ProjectedDistance(const vtkm::Vec& v, const vtkm::Vec& u) { @@ -237,9 +240,9 @@ VTKM_EXEC_CONT T ProjectedDistance(const vtkm::Vec& v, const vtkm::Vec& v, const vtkm::Vec VTKM_EXEC_CONT int Orthonormalize(const vtkm::Vec, N>& inputs, vtkm::Vec, N>& outputs,