cg.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2021 INRIA
3  */
4 
5 #ifndef __pycppad_codegen_cg_hpp__
6 #define __pycppad_codegen_cg_hpp__
7 
8 #include <cppad/cg/cppadcg.hpp>
9 
10 #include <eigenpy/user-type.hpp>
11 #include <eigenpy/ufunc.hpp>
12 
13 #include "pycppad/cast.hpp"
14 
15 namespace eigenpy {
16 
17 template <typename Scalar, typename To>
18 struct cast<::CppAD::cg::CG<Scalar>, To>
19 {
20  typedef ::CppAD::cg::CG<Scalar> From;
21  static To run(const From & from) {
22  return ::pycppad::internal::Cast<From, To>::run(from);
23  }
24 };
25 
26 template <typename From, typename Scalar>
27 struct cast<From,::CppAD::cg::CG<Scalar>>
28 {
29  typedef ::CppAD::cg::CG<Scalar> To;
30  static To run(const From & from) {
31  return To(static_cast<Scalar>(from));
32  }
33 };
34 
35 namespace internal {
36 
37 template <typename Scalar>
38 struct getitem<::CppAD::cg::CG<Scalar>> {
39 
40  typedef ::CppAD::cg::CG<Scalar> CG;
41 
42  static PyObject* run(void* data, void* /* arr */) {
43  CG & cg = *static_cast<CG*>(data);
44 
45  if(!cg.isValueDefined()) // not initialized
46  cg.setValue(static_cast<Scalar>(0));
47 
48  bp::object m(cg);
49  Py_INCREF(m.ptr());
50  return m.ptr();
51  }
52 };
53 
54 } // namespace internal
55 } // namespace eigenpy
56 
57 namespace pycppad
58 {
59  namespace internal
60  {
61 
62  template<typename Scalar>
63  struct CppADValue<::CppAD::cg::CG<Scalar>>
64  {
65  static const Scalar & get(const ::CppAD::AD<::CppAD::cg::CG<Scalar>> & v)
66  {
67  return ::CppAD::Value<::CppAD::cg::CG<Scalar>>(v).getValue();
68  }
69  };
70 
71  template<typename Scalar, typename To>
72  struct Cast<::CppAD::cg::CG<Scalar>,To>
73  {
74  typedef ::CppAD::cg::CG<Scalar> From;
75  static To run(const From & from)
76  {
77  return static_cast<To>(::CppAD::Value<From>(from).getValue());
78  }
79  };
80  }
81 
82  namespace codegen
83  {
84 
85  namespace bp = boost::python;
86 
87  template<typename Scalar>
88  class CGVisitor
89  : public bp::def_visitor< CGVisitor<Scalar> >
90  {
91  public:
92  typedef ::CppAD::cg::CG<Scalar> CG;
93 
94  template<class PyClass>
95  void visit(PyClass& cl) const
96  {
97  cl
98  .def(bp::init<>(bp::arg("self"),"Default constructor"))
99  .def(bp::init<Scalar>(bp::args("self","value"),
100  std::string("Constructor from a ").append(bp::type_id<Scalar>().name()).c_str()))
101  .def(bp::init<CG>(bp::args("self","other"),"Copy constructor"))
102  .def("isIdenticalZero", &CG::isIdenticalZero, bp::arg("self"))
103  .def("isIdenticalOne", &CG::isIdenticalOne, bp::arg("self"))
104  .def("isValueDefined", &CG::isValueDefined, bp::arg("self"))
105  .def("isParameter", &CG::isParameter, bp::arg("self"))
106  .def("isVariable", &CG::isVariable, bp::arg("self"))
107 
108  .def(bp::self + bp::self)
109  .def(bp::self - bp::self)
110  .def(bp::self * bp::self)
111  .def(bp::self / bp::self)
112  .def(bp::self += bp::self)
113 #ifdef __clang__
114 #pragma GCC diagnostic push
115 #pragma GCC diagnostic ignored "-Wself-assign-overloaded"
116 #endif
117  .def(bp::self /= bp::self)
118  .def(bp::self -= bp::self) // See https://bugs.llvm.org/show_bug.cgi?id=43124 for the bug
119 #ifdef __clang__
120 #pragma GCC diagnostic pop
121 #endif
122  .def(bp::self *= bp::self)
123  .add_property("value",
124  bp::make_function(&CG::getValue,
125  bp::return_value_policy<bp::copy_const_reference>()),
126  &CG::setValue)
127  .def("__str__",&print)
128  .def("__repr__",&print)
129  .add_property("__float__",
130  bp::make_function(&CG::getValue,
131  bp::return_value_policy<bp::copy_const_reference>()),
132  &CG::setValue)
133  .def("__int__",&internal::Cast<CG,int64_t>::run)
134  ;
135  }
136 
137  private:
138 
139  static std::string print(const CG & self)
140  {
141  std::stringstream ss;
142  ss << get_class_name() << "(" << self <<")";
143  return ss.str();
144  }
145 
146  protected:
147 
148  static std::string & get_class_name()
149  {
150  static std::string class_name;
151  return class_name;
152  }
153 
154  static void set_class_name(const std::string & class_name)
155  {
156  get_class_name() = class_name;
157  }
158 
159  public:
160 
161  static void expose(const std::string & class_name = "CG")
162  {
163  set_class_name(class_name);
164  bp::class_<CG>(class_name.c_str(),
165  std::string("CG type corresponding to the scalar type ").append(bp::type_id<Scalar>().name()).c_str(),
166  bp::no_init)
167  .def(CGVisitor<Scalar>());
168 
169  eigenpy::registerNewType<CG>();
170  eigenpy::registerCommonUfunc<CG>();
171 
172  eigenpy::registerCast<CG,double>(false);
173  eigenpy::registerCast<double,CG>(true);
174  eigenpy::registerCast<CG,float>(false);
175  eigenpy::registerCast<float,CG>(true);
176  eigenpy::registerCast<CG,long>(false);
177  eigenpy::registerCast<long,CG>(true);
178  eigenpy::registerCast<CG,int>(false);
179  eigenpy::registerCast<int,CG>(true);
180  }
181  };
182 
183  }
184 }
185 #endif //#ifndef __pycppad_codegen_cg_hpp__
Definition: cg.hpp:90
static void set_class_name(const std::string &class_name)
Definition: cg.hpp:154
::CppAD::cg::CG< Scalar > CG
Definition: cg.hpp:92
void visit(PyClass &cl) const
Definition: cg.hpp:95
static std::string & get_class_name()
Definition: cg.hpp:148
static void expose(const std::string &class_name="CG")
Definition: cg.hpp:161
Definition: cast.hpp:47
Definition: ad.hpp:15
static To run(const From &from)
Definition: cg.hpp:30
::CppAD::cg::CG< Scalar > To
Definition: cg.hpp:29
static To run(const From &from)
Definition: cg.hpp:21
::CppAD::cg::CG< Scalar > From
Definition: cg.hpp:20
static PyObject * run(void *data, void *)
Definition: cg.hpp:42
::CppAD::cg::CG< Scalar > CG
Definition: cg.hpp:40
static To run(const From &from)
Definition: cg.hpp:75
::CppAD::cg::CG< Scalar > From
Definition: cg.hpp:74
Definition: cast.hpp:19
static const Scalar & get(const ::CppAD::AD<::CppAD::cg::CG< Scalar >> &v)
Definition: cg.hpp:65
Definition: cast.hpp:28