CppADCodeGen  2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
arithmetic.hpp
1 #ifndef CPPAD_CG_ARITHMETIC_INCLUDED
2 #define CPPAD_CG_ARITHMETIC_INCLUDED
3 /* --------------------------------------------------------------------------
4  * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5  * Copyright (C) 2012 Ciengis
6  *
7  * CppADCodeGen is distributed under multiple licenses:
8  *
9  * - Eclipse Public License Version 1.0 (EPL1), and
10  * - GNU General Public License Version 3 (GPL3).
11  *
12  * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
13  * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
14  * ----------------------------------------------------------------------------
15  * Author: Joao Leal
16  */
17 
18 namespace CppAD {
19 namespace cg {
20 
21 template<class Base>
22 CodeHandler<Base>* getHandler(const CG<Base>& left,
23  const CG<Base>& right) {
24 
25  CPPADCG_ASSERT_UNKNOWN(!left.isParameter() || !right.isParameter());
26 
27  CodeHandler<Base>* lh = left.getCodeHandler();
28  CodeHandler<Base>* rh = right.getCodeHandler();
29 
30  if (lh == nullptr) {
31  return rh;
32  } else if (rh == nullptr) {
33  return lh;
34  } else {
35  if (lh != rh) {
36  throw CGException("Attempting to use several source code generation handlers in the same source code generation");
37  }
38  return lh;
39  }
40 }
41 
42 template<class Base>
43 inline CG<Base> operator+(const CG<Base>& left, const CG<Base>& right) {
44  if (left.isParameter() && right.isParameter()) {
45  return CG<Base> (left.getValue() + right.getValue());
46 
47  } else {
48  if (left.isParameter()) {
49  if (left.isIdenticalZero()) {
50  return right;
51  }
52  } else if (right.isParameter()) {
53  if (right.isIdenticalZero()) {
54  return left;
55  }
56  }
57 
58  CodeHandler<Base>* handler = getHandler(left, right);
59 
60  CG<Base> result(*handler->makeNode(CGOpCode::Add,{left.argument(), right.argument()}));
61  if (left.isValueDefined() && right.isValueDefined()) {
62  result.setValue(left.getValue() + right.getValue());
63  }
64  return result;
65  }
66 }
67 
68 template<class Base>
69 inline CG<Base> operator-(const CG<Base>& left, const CG<Base>& right) {
70  if (left.isParameter() && right.isParameter()) {
71  return CG<Base> (left.getValue() - right.getValue());
72 
73  } else {
74  if (right.isParameter()) {
75  if (right.isIdenticalZero()) {
76  return left;
77  }
78  }
79 
80  CodeHandler<Base>* handler = getHandler(left, right);
81 
82  CG<Base> result(*handler->makeNode(CGOpCode::Sub,{left.argument(), right.argument()}));
83  if (left.isValueDefined() && right.isValueDefined()) {
84  result.setValue(left.getValue() - right.getValue());
85  }
86  return result;
87  }
88 }
89 
90 template<class Base>
91 inline CG<Base> operator*(const CG<Base>& left, const CG<Base>& right) {
92  if (left.isParameter() && right.isParameter()) {
93  return CG<Base> (left.getValue() * right.getValue());
94 
95  } else {
96  if (left.isParameter()) {
97  if (left.isIdenticalZero()) {
98  return CG<Base> (Base(0.0)); // does not consider the possibility of right being infinity
99  } else if (left.isIdenticalOne()) {
100  return right;
101  }
102  } else if (right.isParameter()) {
103  if (right.isIdenticalZero()) {
104  return CG<Base> (Base(0.0)); // does not consider the possibility of left being infinity
105  } else if (right.isIdenticalOne()) {
106  return left;
107  }
108  }
109 
110  CodeHandler<Base>* handler = getHandler(left, right);
111 
112  CG<Base> result(*handler->makeNode(CGOpCode::Mul,{left.argument(), right.argument()}));
113  if (left.isValueDefined() && right.isValueDefined()) {
114  result.setValue(left.getValue() * right.getValue());
115  }
116  return result;
117  }
118 }
119 
120 template<class Base>
121 inline CG<Base> operator/(const CG<Base>& left, const CG<Base>& right) {
122  if (left.isParameter() && right.isParameter()) {
123  return CG<Base> (left.getValue() / right.getValue());
124 
125  } else {
126  if (left.isParameter()) {
127  if (left.isIdenticalZero()) {
128  return CG<Base> (Base(0.0)); // does not consider the possibility of right being infinity or zero
129  }
130  } else if (right.isParameter()) {
131  if (right.isIdenticalOne()) {
132  return left;
133  }
134  } else if (left.getOperationNode() == right.getOperationNode()) {
135  return CG<Base>(Base(1.0)); // does not consider the possibility of left/right being infinity or zero
136  }
137 
138  CodeHandler<Base>* handler = getHandler(left, right);
139 
140  CG<Base> result(*handler->makeNode(CGOpCode::Div,{left.argument(), right.argument()}));
141  if (left.isValueDefined() && right.isValueDefined()) {
142  result.setValue(left.getValue() / right.getValue());
143  }
144  return result;
145  }
146 }
147 
148 template<class Base>
149 inline CG<Base> operator+(const Base& left, const CG<Base>& right) {
150  return CG<Base>(left) + right;
151 }
152 
153 template<class Base>
154 inline CG<Base> operator+(const CG<Base>& left, const Base& right) {
155  return left + CG<Base>(right);
156 }
157 
158 template<class Base>
159 inline CG<Base> operator-(const Base& left, const CG<Base>& right) {
160  return CG<Base>(left) - right;
161 }
162 
163 template<class Base>
164 inline CG<Base> operator-(const CG<Base>& left, const Base& right) {
165  return left - CG<Base>(right);
166 }
167 
168 template<class Base>
169 inline CG<Base> operator/(const Base& left, const CG<Base>& right) {
170  return CG<Base>(left) / right;
171 }
172 
173 template<class Base>
174 inline CG<Base> operator/(const CG<Base>& left, const Base& right) {
175  return left / CG<Base>(right);
176 }
177 
178 template<class Base>
179 inline CG<Base> operator*(const Base& left, const CG<Base>& right) {
180  return CG<Base>(left) * right;
181 }
182 
183 template<class Base>
184 inline CG<Base> operator*(const CG<Base>& left, const Base& right) {
185  return left * CG<Base>(right);
186 }
187 
188 /*******************************************************************************
189  * Operations with other types
190  ******************************************************************************/
191 
192 template<class Base, class T>
193 inline
194 typename std::enable_if<std::is_constructible<Base, const T&>::value, CG<Base> >::type
195 operator+(const T& left, const CG<Base>& right) {
196  return CG<Base>(Base(left)) + right;
197 }
198 
199 template<class Base, class T>
200 inline
201 typename std::enable_if<std::is_constructible<Base, const T&>::value, CG<Base> >::type
202 operator+(const CG<Base>& left, const T& right) {
203  return left + CG<Base>(Base(right));
204 }
205 
206 template<class Base, class T>
207 inline
208 typename std::enable_if<std::is_constructible<Base, const T&>::value, CG<Base> >::type
209 operator-(const T& left, const CG<Base>& right) {
210  return CG<Base>(Base(left)) - right;
211 }
212 
213 template<class Base, class T>
214 inline
215 typename std::enable_if<std::is_constructible<Base, const T&>::value, CG<Base> >::type
216 operator-(const CG<Base>& left, const T& right) {
217  return left - CG<Base>(Base(right));
218 }
219 
220 template<class Base, class T>
221 inline
222 typename std::enable_if<std::is_constructible<Base, const T&>::value, CG<Base> >::type
223 operator/(const T& left, const CG<Base>& right) {
224  return CG<Base>(Base(left)) / right;
225 }
226 
227 template<class Base, class T>
228 inline
229 typename std::enable_if<std::is_constructible<Base, const T&>::value, CG<Base> >::type
230 operator/(const CG<Base>& left, const T& right) {
231  return left / CG<Base>(Base(right));
232 }
233 
234 template<class Base, class T>
235 inline
236 typename std::enable_if<std::is_constructible<Base, const T&>::value, CG<Base> >::type
237 operator*(const T& left, const CG<Base>& right) {
238  return CG<Base>(Base(left)) * right;
239 }
240 
241 template<class Base, class T>
242 inline
243 typename std::enable_if<std::is_constructible<Base, const T&>::value, CG<Base> >::type
244 operator*(const CG<Base>& left, const T& right) {
245  return left * CG<Base>(Base(right));
246 }
247 
248 } // END cg namespace
249 } // END CppAD namespace
250 
251 #endif
252 
CppAD
Definition: abstract_atomic_fun.hpp:19