GCC Code Coverage Report


Directory: ./
File: bindings/python/crocoddyl/utils/cast.hpp
Date: 2025-05-13 10:30:51
Exec Total Coverage
Lines: 0 16 0.0%
Branches: 0 11 0.0%

Line Branch Exec Source
1
2
3 ///////////////////////////////////////////////////////////////////////////////
4 // BSD 3-Clause License
5 //
6 // Copyright (C) 2024-2025, Heriot-Watt University
7 // Copyright note valid unless otherwise stated in individual files.
8 // All rights reserved.
9 ///////////////////////////////////////////////////////////////////////////////
10
11 #ifndef BINDINGS_PYTHON_CROCODDYL_UTILS_CAST_HPP_
12 #define BINDINGS_PYTHON_CROCODDYL_UTILS_CAST_HPP_
13
14 #include <boost/python.hpp>
15
16 #include "crocoddyl/core/utils/conversions.hpp"
17 #include "python/crocoddyl/utils/scalar.hpp"
18
19 namespace crocoddyl {
20 namespace python {
21
22 namespace bp = boost::python;
23
24 /**
25 * @brief Add the Python method cast to allow casting of this by predefined cast
26 * types.
27 */
28 template <typename Model, bool FTypesOnly = false>
29 struct CastVisitor : public bp::def_visitor<CastVisitor<Model, FTypesOnly>> {
30 template <class PyClass>
31 void visit(PyClass& cl) const {
32 cl.def("cast", &cast_instance<FTypesOnly>, bp::arg("dtype"),
33 "Returns a copy of *this.");
34 }
35
36 private:
37 // Helper function for casting, using std::enable_if to handle specific types
38 template <typename ScalarType>
39 static bp::object cast_instance_impl(const Model& self, std::true_type) {
40 // No cast needed if ScalarType is the correct type
41 return bp::object(self);
42 }
43
44 template <typename ScalarType>
45 static bp::object cast_instance_impl(const Model& self, std::false_type) {
46 // Otherwise, perform the cast to the requested type
47 return bp::object(self.template cast<ScalarType>());
48 }
49
50 // Main cast instance function that uses SFINAE
51 template <bool IsFTypesOnly = FTypesOnly>
52 static typename std::enable_if<!IsFTypesOnly, bp::object>::type cast_instance(
53 const Model& self, DType dtype) {
54 switch (dtype) {
55 case DType::Float64:
56 return cast_instance_impl<Float64>(
57 self, std::is_same<typename Model::Scalar, Float64>());
58 case DType::Float32:
59 return cast_instance_impl<Float32>(
60 self, std::is_same<typename Model::Scalar, Float32>());
61 #ifdef CROCODDYL_WITH_CODEGEN
62 case DType::ADFloat64:
63 return cast_instance_impl<ADFloat64>(
64 self, std::is_same<typename Model::Scalar, ADFloat64>());
65 #endif
66 default:
67 PyErr_SetString(PyExc_TypeError, "Unsupported dtype.");
68 bp::throw_error_already_set();
69 return bp::object();
70 }
71 }
72
73 template <bool IsFTypesOnly = FTypesOnly>
74 static typename std::enable_if<IsFTypesOnly, bp::object>::type cast_instance(
75 const Model& self, DType dtype) {
76 switch (dtype) {
77 case DType::Float64:
78 return cast_instance_impl<Float64>(
79 self, std::is_same<typename Model::Scalar, Float64>());
80 case DType::Float32:
81 return cast_instance_impl<Float32>(
82 self, std::is_same<typename Model::Scalar, Float32>());
83 default:
84 PyErr_SetString(PyExc_TypeError, "Unsupported dtype.");
85 bp::throw_error_already_set();
86 return bp::object();
87 }
88 }
89 };
90
91 } // namespace python
92 } // namespace crocoddyl
93
94 #endif // BINDINGS_PYTHON_CROCODDYL_UTILS_CAST_HPP_
95