File: identical_zero.cpp

package info (click to toggle)
cppad 2026.00.00.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 11,584 kB
  • sloc: cpp: 112,960; sh: 6,146; ansic: 179; python: 71; sed: 12; makefile: 10
file content (162 lines) | stat: -rw-r--r-- 3,972 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>
// SPDX-FileContributor: 2003-22 Bradley M. Bell
// ----------------------------------------------------------------------------
/*
{xrst_begin atomic_four_mat_mul_identical_zero.cpp}

Atomic Matrix Multiply Identical Zero: Example and Test
#######################################################

Purpose
*******
This example demonstrates how the
:ref:`atomic_four_mat_mul_for_type.hpp-name`
routine uses the *identical_zero_enum* type to reduce the number
of variables.

Zero
****
The first case computes the following matrix product

.. math::

   \left( \begin{array}{ccc}
   u_0 & 0   & 0 \\
   0   & u_1 & 0 \\
   0   & 0   & u_2
   \end{array} \right)
   \left( \begin{array}{ccc}
   u_3 & 0   & 0 \\
   0   & u_4 & 0 \\
   0   & 0   & u_5
   \end{array} \right)
   =
   \left( \begin{array}{ccc}
   u_0 u_3 & 0       & 0 \\
   0       & u_1 u_4 & 0 \\
   0       & 0       & u_2 u_5
   \end{array} \right)

The result matrix for this case has three variables,
one for each product on the diagonal.

One
***
The second case computes the following matrix product

.. math::

   \left( \begin{array}{ccc}
   u_0 & 1   & 1 \\
   1   & u_1 & 1 \\
   1   & 1   & u_2
   \end{array} \right)
   \left( \begin{array}{ccc}
   u_3 & 1   & 1 \\
   1   & u_4 & 1 \\
   1   & 1   & u_5
   \end{array} \right)
   =
   \left( \begin{array}{ccc}
   u_0 u_3 + 2   & u_0 + u_3 + 1 & u_0 + u_5 + 1 \\
   u_1 + u_3 + 1 & u_1 u_4 + 2   & u_1 + u_5 + 1  \\
   u_2 + u_3 + 1 & u_2 + u_4 + 1 & u_2 u_5 + 2
   \end{array} \right)

The result matrix for this case has nine variables,
one for each of its elements.

Source
******
{xrst_literal
   // BEGIN C++
   // END C++
}

{xrst_end atomic_four_mat_mul_identical_zero.cpp}
*/
// BEGIN C++
# include <cppad/cppad.hpp>
# include <cppad/example/atomic_four/mat_mul/mat_mul.hpp>

bool identical_zero(void)
{  // ok, eps
   bool ok = true;
   //
   // AD, NearEqual
   using CppAD::AD;
   using CppAD::NearEqual;
   // -----------------------------------------------------------------------
   // Record f
   // -----------------------------------------------------------------------
   //
   // afun
   CppAD::atomic_mat_mul<double> afun("atomic_mat_mul");
   //
   // nleft
   size_t size = 3;
   //
   // size_var
   size_t size_var[2];
   //
   // zero_one
   for(size_t zero_one = 0; zero_one < 2; ++zero_one)
   {  //
      // n_right, n_middle
      size_t n_left = size, n_middle = size, n_right = size;
      //
      // nu, au
      size_t nu = 2 * size;
      CPPAD_TESTVECTOR( AD<double> ) au(nu);
      for(size_t j = 0; j < nu; ++j)
         au[j] = AD<double>(j + 2);
      CppAD::Independent(au);
      //
      // offset
      size_t offset = size * size;
      //
      // nx, ax
      size_t nx = size * (size + size);
      CPPAD_TESTVECTOR( AD<double> ) ax(nx);
      for(size_t i = 0; i < size; ++i)
      {  for(size_t j = 0; j < size; ++j)
         {  // left
            size_t ij = i * size + j;
            if( i == j )
               ax[ij] = au[j];
            else
               ax[ij] = AD<double>(zero_one);
            // right
            ij = offset + i * n_right + j;
            if( i == j )
               ax[ij] = au[i];
            else
               ax[ij] = AD<double>(zero_one);
         }
      }
      //
      // ay
      size_t ny = size * size;
      CPPAD_TESTVECTOR( AD<double> ) ay(ny);
      size_t call_id = afun.set(n_left, n_middle, n_right);
      afun(call_id, ax, ay);
      //
      // av
      size_t nv = size;
      CPPAD_TESTVECTOR( AD<double> ) av(nv);
      for(size_t i = 0; i < nv; ++i)
         av[i] += ay[i * size + i];
      //
      // f
      CppAD::ADFun<double> f(au, av);
      //
      // size_var
      size_var[zero_one] = f.size_var();
   }
   // ok
   ok = size_var[1] - size_var[0] == size * size - size;
   //
   return ok;
}
// END C++