GCC Code Coverage Report


Directory: ./
File: include/crocoddyl/core/utils/math.hpp
Date: 2025-03-26 19:23:43
Exec Total Coverage
Lines: 17 17 100.0%
Branches: 18 36 50.0%

Line Branch Exec Source
1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (C) 2019-2025, LAAS-CNRS, Heriot-Watt University
5 // Copyright note valid unless otherwise stated in individual files.
6 // All rights reserved.
7 ///////////////////////////////////////////////////////////////////////////////
8
9 #ifndef CROCODDYL_CORE_UTILS_MATH_HPP_
10 #define CROCODDYL_CORE_UTILS_MATH_HPP_
11
12 #include <Eigen/Dense>
13 #include <algorithm>
14 #include <cmath>
15 #include <limits>
16 #include <type_traits>
17
18 #ifdef CROCODDYL_WITH_CODEGEN
19 #include <cppad/cg/support/cppadcg_eigen.hpp>
20 #endif
21
22 #ifdef CROCODDYL_WITH_CODEGEN
23 #include <cppad/cg/cg.hpp>
24 #include <cppad/cppad.hpp>
25 #endif
26
27 namespace crocoddyl {
28
29 template <typename Scalar>
30 1882 constexpr Scalar pi() {
31 1882 return static_cast<Scalar>(3.14159265358979323846264338327950288);
32 }
33
34 template <typename Scalar>
35 typename std::enable_if<std::is_floating_point<Scalar>::value, bool>::type
36 78299 isfinite(const Scalar& value) {
37 78299 return std::isfinite(value);
38 }
39
40 template <typename MatrixLike,
41 bool value =
42 (Eigen::NumTraits<typename MatrixLike::Scalar>::IsInteger == 0)>
43 struct pseudoInverseAlgo {
44 typedef typename MatrixLike::Scalar Scalar;
45 typedef typename MatrixLike::RealScalar RealScalar;
46
47 11314 static MatrixLike run(const Eigen::MatrixBase<MatrixLike>& a,
48 const RealScalar& epsilon) {
49 using std::max;
50
2/4
✓ Branch 1 taken 11314 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11314 times.
✗ Branch 5 not taken.
11314 Eigen::JacobiSVD<MatrixLike> svd(a,
51 Eigen::ComputeThinU | Eigen::ComputeThinV);
52 33942 RealScalar tolerance = epsilon *
53 11314 static_cast<Scalar>(max(a.cols(), a.rows())) *
54
4/8
✓ Branch 1 taken 11314 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11314 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 11314 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 11314 times.
✗ Branch 11 not taken.
11314 svd.singularValues().array().abs()(0);
55 // FIX: Replace select() with a lambda function
56 Eigen::Matrix<typename MatrixLike::Scalar, Eigen::Dynamic, 1>
57
1/2
✓ Branch 1 taken 11314 times.
✗ Branch 2 not taken.
11314 invSingularValues =
58
2/4
✓ Branch 1 taken 11314 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11314 times.
✗ Branch 5 not taken.
11314 svd.singularValues().unaryExpr([&](const Scalar& x) {
59
2/4
✓ Branch 0 taken 194148 times.
✓ Branch 1 taken 513 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
194661 return (x > tolerance) ? Scalar(1) / x : Scalar(0);
60 });
61
4/8
✓ Branch 1 taken 11314 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11314 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 11314 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 11314 times.
✗ Branch 11 not taken.
11314 return svd.matrixV() * invSingularValues.asDiagonal() *
62
3/6
✓ Branch 1 taken 11314 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11314 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 11314 times.
✗ Branch 8 not taken.
33942 svd.matrixU().adjoint();
63 11314 }
64 };
65
66 template <typename MatrixLike>
67 struct pseudoInverseAlgo<MatrixLike, false> {
68 typedef typename MatrixLike::Scalar Scalar;
69 typedef typename MatrixLike::RealScalar RealScalar;
70
71 static MatrixLike run(const Eigen::MatrixBase<MatrixLike>& a,
72 const RealScalar&) {
73 return Eigen::MatrixBase<MatrixLike>::Zero(a.rows(), a.cols());
74 }
75 };
76
77 template <typename MatrixLike>
78 11314 MatrixLike pseudoInverse(
79 const Eigen::MatrixBase<MatrixLike>& a,
80 const typename MatrixLike::RealScalar& epsilon =
81 Eigen::NumTraits<typename MatrixLike::Scalar>::dummy_precision()) {
82 11314 return pseudoInverseAlgo<MatrixLike>::run(a, epsilon);
83 }
84
85 } // namespace crocoddyl
86
87 #ifdef CROCODDYL_WITH_CODEGEN
88 template <typename Scalar>
89 bool isfinite(const CppAD::AD<Scalar>& value) {
90 return std::isfinite(CppAD::Value(value));
91 }
92
93 namespace CppAD {
94 template <class Scalar>
95 bool isfinite(const CppAD::AD<CppAD::cg::CG<Scalar>>& x) {
96 return std::isfinite(static_cast<Scalar>(CppAD::Value(x).getValue()));
97 }
98 } // namespace CppAD
99
100 namespace Eigen {
101
102 // Overload for Eigen::pow with CppAD-compatible types
103 template <typename Derived>
104 auto pow(const Eigen::ArrayBase<Derived>& base, double exponent) {
105 return base.unaryExpr([exponent](const typename Derived::Scalar& x) {
106 return CppAD::pow(x, typename Derived::Scalar(exponent));
107 });
108 }
109
110 // Overload for Eigen::sqrt with CppAD-compatible types
111 template <typename Derived>
112 typename std::enable_if<std::is_base_of<CppAD::cg::CG<typename Derived::Scalar>,
113 typename Derived::Scalar>::value,
114 Eigen::Array<typename Derived::Scalar, Eigen::Dynamic,
115 Eigen::Dynamic>>::type
116 sqrt(const Eigen::ArrayBase<Derived>& base) {
117 return base.unaryExpr(
118 [](const typename Derived::Scalar& x) { return CppAD::sqrt(x); });
119 }
120
121 } // namespace Eigen
122 #endif
123
124 #endif // CROCODDYL_CORE_UTILS_MATH_HPP_
125