1 # ifndef CPPAD_LOCAL_ZMUL_OP_HPP
2 # define CPPAD_LOCAL_ZMUL_OP_HPP
3 
4 /* --------------------------------------------------------------------------
5 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
6 
7 CppAD is distributed under multiple licenses. This distribution is under
8 the terms of the
9                     Eclipse Public License Version 1.0.
10 
11 A copy of this license is included in the COPYING file of this distribution.
12 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
13 -------------------------------------------------------------------------- */
14 
15 namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
16 /*!
17 \file mul_op.hpp
18 Forward and reverse mode calculations for z = azmul(x, y).
19 */
20 
21 // --------------------------- Zmulvv -----------------------------------------
22 /*!
23 Compute forward mode Taylor coefficients for result of op = ZmulvvOp.
24 
25 The C++ source code corresponding to this operation is
26 \verbatim
27 	z = azmul(x, y)
28 \endverbatim
29 In the documentation below,
30 this operations is for the case where both x and y are variables
31 and the argument \a parameter is not used.
32 
33 \copydetails CppAD::local::forward_binary_op
34 */
35 
36 template <class Base>
forward_zmulvv_op(size_t p,size_t q,size_t i_z,const addr_t * arg,const Base * parameter,size_t cap_order,Base * taylor)37 inline void forward_zmulvv_op(
38 	size_t        p           ,
39 	size_t        q           ,
40 	size_t        i_z         ,
41 	const addr_t* arg         ,
42 	const Base*   parameter   ,
43 	size_t        cap_order   ,
44 	Base*         taylor      )
45 {
46 	// check assumptions
47 	CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvvOp) == 2 );
48 	CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvvOp) == 1 );
49 	CPPAD_ASSERT_UNKNOWN( q < cap_order );
50 	CPPAD_ASSERT_UNKNOWN( p <= q );
51 
52 	// Taylor coefficients corresponding to arguments and result
53 	Base* x = taylor + arg[0] * cap_order;
54 	Base* y = taylor + arg[1] * cap_order;
55 	Base* z = taylor + i_z    * cap_order;
56 
57 	size_t k;
58 	for(size_t d = p; d <= q; d++)
59 	{	z[d] = Base(0.0);
60 		for(k = 0; k <= d; k++)
61 			z[d] += azmul(x[d-k], y[k]);
62 	}
63 }
64 /*!
65 Multiple directions forward mode Taylor coefficients for op = ZmulvvOp.
66 
67 The C++ source code corresponding to this operation is
68 \verbatim
69 	z = azmul(x, y)
70 \endverbatim
71 In the documentation below,
72 this operations is for the case where both x and y are variables
73 and the argument \a parameter is not used.
74 
75 \copydetails CppAD::local::forward_binary_op_dir
76 */
77 
78 template <class Base>
forward_zmulvv_op_dir(size_t q,size_t r,size_t i_z,const addr_t * arg,const Base * parameter,size_t cap_order,Base * taylor)79 inline void forward_zmulvv_op_dir(
80 	size_t        q           ,
81 	size_t        r           ,
82 	size_t        i_z         ,
83 	const addr_t* arg         ,
84 	const Base*   parameter   ,
85 	size_t        cap_order   ,
86 	Base*         taylor      )
87 {
88 	// check assumptions
89 	CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvvOp) == 2 );
90 	CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvvOp) == 1 );
91 	CPPAD_ASSERT_UNKNOWN( 0 < q );
92 	CPPAD_ASSERT_UNKNOWN( q < cap_order );
93 
94 	// Taylor coefficients corresponding to arguments and result
95 	size_t num_taylor_per_var = (cap_order-1) * r + 1;
96 	Base* x = taylor + arg[0] * num_taylor_per_var;
97 	Base* y = taylor + arg[1] * num_taylor_per_var;
98 	Base* z = taylor +    i_z * num_taylor_per_var;
99 
100 	size_t k, ell, m;
101 	for(ell = 0; ell < r; ell++)
102 	{	m = (q-1)*r + ell + 1;
103 		z[m] = azmul(x[0], y[m]) + azmul(x[m],  y[0]);
104 		for(k = 1; k < q; k++)
105 			z[m] += azmul(x[(q-k-1)*r + ell + 1], y[(k-1)*r + ell + 1]);
106 	}
107 }
108 
109 /*!
110 Compute zero order forward mode Taylor coefficients for result of op = ZmulvvOp.
111 
112 The C++ source code corresponding to this operation is
113 \verbatim
114 	z = azmul(x, y)
115 \endverbatim
116 In the documentation below,
117 this operations is for the case where both x and y are variables
118 and the argument \a parameter is not used.
119 
120 \copydetails CppAD::local::forward_binary_op_0
121 */
122 
123 template <class Base>
forward_zmulvv_op_0(size_t i_z,const addr_t * arg,const Base * parameter,size_t cap_order,Base * taylor)124 inline void forward_zmulvv_op_0(
125 	size_t        i_z         ,
126 	const addr_t* arg         ,
127 	const Base*   parameter   ,
128 	size_t        cap_order   ,
129 	Base*         taylor      )
130 {
131 	// check assumptions
132 	CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvvOp) == 2 );
133 	CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvvOp) == 1 );
134 
135 	// Taylor coefficients corresponding to arguments and result
136 	Base* x = taylor + arg[0] * cap_order;
137 	Base* y = taylor + arg[1] * cap_order;
138 	Base* z = taylor + i_z    * cap_order;
139 
140 	z[0] = azmul(x[0], y[0]);
141 }
142 
143 /*!
144 Compute reverse mode partial derivatives for result of op = ZmulvvOp.
145 
146 The C++ source code corresponding to this operation is
147 \verbatim
148 	z = azmul(x, y)
149 \endverbatim
150 In the documentation below,
151 this operations is for the case where both x and y are variables
152 and the argument \a parameter is not used.
153 
154 \copydetails CppAD::local::reverse_binary_op
155 */
156 
157 template <class Base>
reverse_zmulvv_op(size_t d,size_t i_z,const addr_t * arg,const Base * parameter,size_t cap_order,const Base * taylor,size_t nc_partial,Base * partial)158 inline void reverse_zmulvv_op(
159 	size_t        d           ,
160 	size_t        i_z         ,
161 	const addr_t* arg         ,
162 	const Base*   parameter   ,
163 	size_t        cap_order   ,
164 	const Base*   taylor      ,
165 	size_t        nc_partial  ,
166 	Base*         partial     )
167 {
168 	// check assumptions
169 	CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvvOp) == 2 );
170 	CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvvOp) == 1 );
171 	CPPAD_ASSERT_UNKNOWN( d < cap_order );
172 	CPPAD_ASSERT_UNKNOWN( d < nc_partial );
173 
174 	// Arguments
175 	const Base* x  = taylor + arg[0] * cap_order;
176 	const Base* y  = taylor + arg[1] * cap_order;
177 
178 	// Partial derivatives corresponding to arguments and result
179 	Base* px = partial + arg[0] * nc_partial;
180 	Base* py = partial + arg[1] * nc_partial;
181 	Base* pz = partial + i_z    * nc_partial;
182 
183 	// number of indices to access
184 	size_t j = d + 1;
185 	size_t k;
186 	while(j)
187 	{	--j;
188 		for(k = 0; k <= j; k++)
189 		{
190 			px[j-k] += azmul(pz[j], y[k]);
191 			py[k]   += azmul(pz[j], x[j-k]);
192 		}
193 	}
194 }
195 // --------------------------- Zmulpv -----------------------------------------
196 /*!
197 Compute forward mode Taylor coefficients for result of op = ZmulpvOp.
198 
199 The C++ source code corresponding to this operation is
200 \verbatim
201 	z = azmul(x, y)
202 \endverbatim
203 In the documentation below,
204 this operations is for the case where x is a parameter and y is a variable.
205 
206 \copydetails CppAD::local::forward_binary_op
207 */
208 
209 template <class Base>
forward_zmulpv_op(size_t p,size_t q,size_t i_z,const addr_t * arg,const Base * parameter,size_t cap_order,Base * taylor)210 inline void forward_zmulpv_op(
211 	size_t        p           ,
212 	size_t        q           ,
213 	size_t        i_z         ,
214 	const addr_t* arg         ,
215 	const Base*   parameter   ,
216 	size_t        cap_order   ,
217 	Base*         taylor      )
218 {
219 	// check assumptions
220 	CPPAD_ASSERT_UNKNOWN( NumArg(ZmulpvOp) == 2 );
221 	CPPAD_ASSERT_UNKNOWN( NumRes(ZmulpvOp) == 1 );
222 	CPPAD_ASSERT_UNKNOWN( q < cap_order );
223 	CPPAD_ASSERT_UNKNOWN( p <= q );
224 
225 	// Taylor coefficients corresponding to arguments and result
226 	Base* y = taylor + arg[1] * cap_order;
227 	Base* z = taylor + i_z    * cap_order;
228 
229 	// Paraemter value
230 	Base x = parameter[ arg[0] ];
231 
232 	for(size_t d = p; d <= q; d++)
233 		z[d] = azmul(x, y[d]);
234 }
235 /*!
236 Multiple directions forward mode Taylor coefficients for op = ZmulpvOp.
237 
238 The C++ source code corresponding to this operation is
239 \verbatim
240 	z = azmul(x, y)
241 \endverbatim
242 In the documentation below,
243 this operations is for the case where x is a parameter and y is a variable.
244 
245 \copydetails CppAD::local::forward_binary_op_dir
246 */
247 
248 template <class Base>
forward_zmulpv_op_dir(size_t q,size_t r,size_t i_z,const addr_t * arg,const Base * parameter,size_t cap_order,Base * taylor)249 inline void forward_zmulpv_op_dir(
250 	size_t        q           ,
251 	size_t        r           ,
252 	size_t        i_z         ,
253 	const addr_t* arg         ,
254 	const Base*   parameter   ,
255 	size_t        cap_order   ,
256 	Base*         taylor      )
257 {
258 	// check assumptions
259 	CPPAD_ASSERT_UNKNOWN( NumArg(ZmulpvOp) == 2 );
260 	CPPAD_ASSERT_UNKNOWN( NumRes(ZmulpvOp) == 1 );
261 	CPPAD_ASSERT_UNKNOWN( 0 < q );
262 	CPPAD_ASSERT_UNKNOWN( q < cap_order );
263 
264 	// Taylor coefficients corresponding to arguments and result
265 	size_t num_taylor_per_var = (cap_order-1) * r + 1;
266 	size_t m                  = (q-1) * r + 1;
267 	Base* y = taylor + arg[1] * num_taylor_per_var + m;
268 	Base* z = taylor + i_z    * num_taylor_per_var + m;
269 
270 	// Paraemter value
271 	Base x = parameter[ arg[0] ];
272 
273 	for(size_t ell = 0; ell < r; ell++)
274 		z[ell] = azmul(x, y[ell]);
275 }
276 /*!
277 Compute zero order forward mode Taylor coefficient for result of op = ZmulpvOp.
278 
279 The C++ source code corresponding to this operation is
280 \verbatim
281 	z = azmul(x, y)
282 \endverbatim
283 In the documentation below,
284 this operations is for the case where x is a parameter and y is a variable.
285 
286 \copydetails CppAD::local::forward_binary_op_0
287 */
288 
289 template <class Base>
forward_zmulpv_op_0(size_t i_z,const addr_t * arg,const Base * parameter,size_t cap_order,Base * taylor)290 inline void forward_zmulpv_op_0(
291 	size_t        i_z         ,
292 	const addr_t* arg         ,
293 	const Base*   parameter   ,
294 	size_t        cap_order   ,
295 	Base*         taylor      )
296 {
297 	// check assumptions
298 	CPPAD_ASSERT_UNKNOWN( NumArg(ZmulpvOp) == 2 );
299 	CPPAD_ASSERT_UNKNOWN( NumRes(ZmulpvOp) == 1 );
300 
301 	// Paraemter value
302 	Base x = parameter[ arg[0] ];
303 
304 	// Taylor coefficients corresponding to arguments and result
305 	Base* y = taylor + arg[1] * cap_order;
306 	Base* z = taylor + i_z    * cap_order;
307 
308 	z[0] = azmul(x, y[0]);
309 }
310 
311 /*!
312 Compute reverse mode partial derivative for result of op = ZmulpvOp.
313 
314 The C++ source code corresponding to this operation is
315 \verbatim
316 	z = azmul(x, y)
317 \endverbatim
318 In the documentation below,
319 this operations is for the case where x is a parameter and y is a variable.
320 
321 \copydetails CppAD::local::reverse_binary_op
322 */
323 
324 template <class Base>
reverse_zmulpv_op(size_t d,size_t i_z,const addr_t * arg,const Base * parameter,size_t cap_order,const Base * taylor,size_t nc_partial,Base * partial)325 inline void reverse_zmulpv_op(
326 	size_t        d           ,
327 	size_t        i_z         ,
328 	const addr_t* arg         ,
329 	const Base*   parameter   ,
330 	size_t        cap_order   ,
331 	const Base*   taylor      ,
332 	size_t        nc_partial  ,
333 	Base*         partial     )
334 {
335 	// check assumptions
336 	CPPAD_ASSERT_UNKNOWN( NumArg(ZmulpvOp) == 2 );
337 	CPPAD_ASSERT_UNKNOWN( NumRes(ZmulpvOp) == 1 );
338 	CPPAD_ASSERT_UNKNOWN( d < cap_order );
339 	CPPAD_ASSERT_UNKNOWN( d < nc_partial );
340 
341 	// Arguments
342 	Base x  = parameter[ arg[0] ];
343 
344 	// Partial derivatives corresponding to arguments and result
345 	Base* py = partial + arg[1] * nc_partial;
346 	Base* pz = partial + i_z    * nc_partial;
347 
348 	// number of indices to access
349 	size_t j = d + 1;
350 	while(j)
351 	{	--j;
352 		py[j] += azmul(pz[j], x);
353 	}
354 }
355 // --------------------------- Zmulvp -----------------------------------------
356 /*!
357 Compute forward mode Taylor coefficients for result of op = ZmulvpOp.
358 
359 The C++ source code corresponding to this operation is
360 \verbatim
361 	z = azmul(x, y)
362 \endverbatim
363 In the documentation below,
364 this operations is for the case where x is a parameter and y is a variable.
365 
366 \copydetails CppAD::local::forward_binary_op
367 */
368 
369 template <class Base>
forward_zmulvp_op(size_t p,size_t q,size_t i_z,const addr_t * arg,const Base * parameter,size_t cap_order,Base * taylor)370 inline void forward_zmulvp_op(
371 	size_t        p           ,
372 	size_t        q           ,
373 	size_t        i_z         ,
374 	const addr_t* arg         ,
375 	const Base*   parameter   ,
376 	size_t        cap_order   ,
377 	Base*         taylor      )
378 {
379 	// check assumptions
380 	CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvpOp) == 2 );
381 	CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvpOp) == 1 );
382 	CPPAD_ASSERT_UNKNOWN( q < cap_order );
383 	CPPAD_ASSERT_UNKNOWN( p <= q );
384 
385 	// Taylor coefficients corresponding to arguments and result
386 	Base* x = taylor + arg[0] * cap_order;
387 	Base* z = taylor + i_z    * cap_order;
388 
389 	// Paraemter value
390 	Base y = parameter[ arg[1] ];
391 
392 	for(size_t d = p; d <= q; d++)
393 		z[d] = azmul(x[d], y);
394 }
395 /*!
396 Multiple directions forward mode Taylor coefficients for op = ZmulvpOp.
397 
398 The C++ source code corresponding to this operation is
399 \verbatim
400 	z = azmul(x, y)
401 \endverbatim
402 In the documentation below,
403 this operations is for the case where x is a parameter and y is a variable.
404 
405 \copydetails CppAD::local::forward_binary_op_dir
406 */
407 
408 template <class Base>
forward_zmulvp_op_dir(size_t q,size_t r,size_t i_z,const addr_t * arg,const Base * parameter,size_t cap_order,Base * taylor)409 inline void forward_zmulvp_op_dir(
410 	size_t        q           ,
411 	size_t        r           ,
412 	size_t        i_z         ,
413 	const addr_t* arg         ,
414 	const Base*   parameter   ,
415 	size_t        cap_order   ,
416 	Base*         taylor      )
417 {
418 	// check assumptions
419 	CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvpOp) == 2 );
420 	CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvpOp) == 1 );
421 	CPPAD_ASSERT_UNKNOWN( 0 < q );
422 	CPPAD_ASSERT_UNKNOWN( q < cap_order );
423 
424 	// Taylor coefficients corresponding to arguments and result
425 	size_t num_taylor_per_var = (cap_order-1) * r + 1;
426 	size_t m                  = (q-1) * r + 1;
427 	Base* x = taylor + arg[0] * num_taylor_per_var + m;
428 	Base* z = taylor + i_z    * num_taylor_per_var + m;
429 
430 	// Paraemter value
431 	Base y = parameter[ arg[1] ];
432 
433 	for(size_t ell = 0; ell < r; ell++)
434 		z[ell] = azmul(x[ell], y);
435 }
436 /*!
437 Compute zero order forward mode Taylor coefficient for result of op = ZmulvpOp.
438 
439 The C++ source code corresponding to this operation is
440 \verbatim
441 	z = azmul(x, y)
442 \endverbatim
443 In the documentation below,
444 this operations is for the case where x is a parameter and y is a variable.
445 
446 \copydetails CppAD::local::forward_binary_op_0
447 */
448 
449 template <class Base>
forward_zmulvp_op_0(size_t i_z,const addr_t * arg,const Base * parameter,size_t cap_order,Base * taylor)450 inline void forward_zmulvp_op_0(
451 	size_t        i_z         ,
452 	const addr_t* arg         ,
453 	const Base*   parameter   ,
454 	size_t        cap_order   ,
455 	Base*         taylor      )
456 {
457 	// check assumptions
458 	CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvpOp) == 2 );
459 	CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvpOp) == 1 );
460 
461 	// Paraemter value
462 	Base y = parameter[ arg[1] ];
463 
464 	// Taylor coefficients corresponding to arguments and result
465 	Base* x = taylor + arg[0] * cap_order;
466 	Base* z = taylor + i_z    * cap_order;
467 
468 	z[0] = azmul(x[0], y);
469 }
470 
471 /*!
472 Compute reverse mode partial derivative for result of op = ZmulvpOp.
473 
474 The C++ source code corresponding to this operation is
475 \verbatim
476 	z = azmul(x, y)
477 \endverbatim
478 In the documentation below,
479 this operations is for the case where x is a parameter and y is a variable.
480 
481 \copydetails CppAD::local::reverse_binary_op
482 */
483 
484 template <class Base>
reverse_zmulvp_op(size_t d,size_t i_z,const addr_t * arg,const Base * parameter,size_t cap_order,const Base * taylor,size_t nc_partial,Base * partial)485 inline void reverse_zmulvp_op(
486 	size_t        d           ,
487 	size_t        i_z         ,
488 	const addr_t* arg         ,
489 	const Base*   parameter   ,
490 	size_t        cap_order   ,
491 	const Base*   taylor      ,
492 	size_t        nc_partial  ,
493 	Base*         partial     )
494 {
495 	// check assumptions
496 	CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvpOp) == 2 );
497 	CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvpOp) == 1 );
498 	CPPAD_ASSERT_UNKNOWN( d < cap_order );
499 	CPPAD_ASSERT_UNKNOWN( d < nc_partial );
500 
501 	// Arguments
502 	Base y  = parameter[ arg[1] ];
503 
504 	// Partial derivatives corresponding to arguments and result
505 	Base* px = partial + arg[0] * nc_partial;
506 	Base* pz = partial + i_z    * nc_partial;
507 
508 	// number of indices to access
509 	size_t j = d + 1;
510 	while(j)
511 	{	--j;
512 		px[j] += azmul(pz[j], y);
513 	}
514 }
515 
516 } } // END_CPPAD_LOCAL_NAMESPACE
517 # endif
518