<?xml version='1.0'?>
<html xmlns='http://www.w3.org/1999/xhtml'
      xmlns:math='http://www.w3.org/1998/Math/MathML'
>
<head>
<title>User Atomic Matrix Multiply: Example and Test</title>
<meta name="description" id="description" content="User Atomic Matrix Multiply: Example and Test"/>
<meta name="keywords" id="keywords" content=" atomic matrix multiply example "/>
<style type='text/css'>
body { color : black }
body { background-color : white }
A:link { color : blue }
A:visited { color : purple }
A:active { color : purple }
</style>
<script type='text/javascript' language='JavaScript' src='_atomic_mat_mul.cpp_xml.js'>
</script>
</head>
<body>
<table><tr>
<td>
<a href="http://www.coin-or.org/CppAD/" target="_top"><img border="0" src="_image.gif"/></a>
</td>
<td><a href="atomic_tangent.cpp.xml" target="_top">Prev</a>
</td><td><a href="atomic_matrix_mul.hpp.xml" target="_top">Next</a>
</td><td>
<select onchange='choose_across0(this)'>
<option>Index-&gt;</option>
<option>contents</option>
<option>reference</option>
<option>index</option>
<option>search</option>
<option>external</option>
</select>
</td>
<td>
<select onchange='choose_up0(this)'>
<option>Up-&gt;</option>
<option>CppAD</option>
<option>AD</option>
<option>ADValued</option>
<option>atomic</option>
<option>atomic_base</option>
<option>atomic_mat_mul.cpp</option>
</select>
</td>
<td>
<select onchange='choose_down3(this)'>
<option>ADValued-&gt;</option>
<option>Arithmetic</option>
<option>std_math_ad</option>
<option>MathOther</option>
<option>CondExp</option>
<option>Discrete</option>
<option>atomic</option>
</select>
</td>
<td>
<select onchange='choose_down2(this)'>
<option>atomic-&gt;</option>
<option>checkpoint</option>
<option>atomic_base</option>
</select>
</td>
<td>
<select onchange='choose_down1(this)'>
<option>atomic_base-&gt;</option>
<option>atomic_ctor</option>
<option>atomic_option</option>
<option>atomic_afun</option>
<option>atomic_forward</option>
<option>atomic_reverse</option>
<option>atomic_for_sparse_jac</option>
<option>atomic_rev_sparse_jac</option>
<option>atomic_rev_sparse_hes</option>
<option>atomic_base_clear</option>
<option>atomic_get_started.cpp</option>
<option>atomic_norm_sq.cpp</option>
<option>atomic_reciprocal.cpp</option>
<option>atomic_tangent.cpp</option>
<option>atomic_mat_mul.cpp</option>
</select>
</td>
<td>
<select onchange='choose_down0(this)'>
<option>atomic_mat_mul.cpp-&gt;</option>
<option>atomic_matrix_mul.hpp</option>
</select>
</td>
<td>
<select onchange='choose_current0(this)'>
<option>Headings-&gt;</option>
<option>Class Definition</option>
<option>Use Atomic Function</option>
<option>---..Constructor</option>
<option>---..Recording</option>
<option>---..forward</option>
<option>---..reverse</option>
<option>---..option</option>
<option>---..for_sparse_jac</option>
<option>---..rev_sparse_jac</option>
<option>---..rev_sparse_hes</option>
</select>
</td>
</tr></table><br/>



<center><b><big><big>User Atomic Matrix Multiply: Example and Test</big></big></b></center>
<br/>
<b><big><a name="Class Definition" id="Class Definition">Class Definition</a></big></b>
<br/>
This example uses the file <a href="atomic_matrix_mul.hpp.xml" target="_top"><span style='white-space: nowrap'>atomic_matrix_mul.hpp</span></a>

which defines matrix multiply as a <a href="atomic_base.xml" target="_top"><span style='white-space: nowrap'>atomic_base</span></a>
 operation.



<br/>
<br/>
<b><big><a name="Use Atomic Function" id="Use Atomic Function">Use Atomic Function</a></big></b>

<code><font color='blue'><pre style='display:inline'> 
# include &lt;cppad/cppad.hpp&gt;
# include &lt;cppad/example/matrix_mul.hpp&gt;

bool mat_mul(void)
{	bool ok = true;
	using CppAD::AD;
	using CppAD::vector;
	size_t i, j;
</pre></font></code>

<br/>
<br/>
<b><a name="Use Atomic Function.Constructor" id="Use Atomic Function.Constructor">Constructor</a></b>

<code><font color='blue'><pre style='display:inline'> 
	// -------------------------------------------------------------------
	// object that multiplies  2 x 2  matrices
	size_t nr_result = 2;
	size_t n_middle  = 2;
	size_t nc_result = 2;
	matrix_mul afun(nr_result, n_middle, nc_result);
</pre></font></code>

<br/>
<br/>
<b><a name="Use Atomic Function.Recording" id="Use Atomic Function.Recording">Recording</a></b>

<code><font color='blue'><pre style='display:inline'> 
	// start recording with four independent varables
	size_t n = 4;
	vector&lt;double&gt; x(n);
	vector&lt; <a href="ad.xml" target="_top">AD</a>&lt;double&gt; &gt; ax(n);
	for(j = 0; j &lt; n; j++)
		ax[j] = x[j] = j + 1;
	CppAD::<a href="independent.xml" target="_top">Independent</a>(ax);

	// ------------------------------------------------------------------
	vector&lt; <a href="ad.xml" target="_top">AD</a>&lt;double&gt; &gt; atom_x(nr_result * n_middle + n_middle * nc_result);

	// left matrix
	atom_x[0] = ax[0];  // left[0, 0] = x0
	atom_x[1] = ax[1];  // left[0, 1] = x1
	atom_x[2] = 5.;     // left[1, 0] = 5
	atom_x[3] = 6.;     // left[1, 1] = 6

	// right matix
	atom_x[4] = ax[2];  // right[0, 0] = x2
	atom_x[5] = 7.;     // right[0, 1] = 7
	atom_x[6] = ax[3];  // right[1, 0] = x3
	atom_x[7] = 8.;     // right[1, 1] = 8
	// ------------------------------------------------------------------
	/*
	[ x0 , x1 ] * [ x2 , 7 ] = [ x0*x2 + x1*x3 , x0*7 + x1*8 ]
	[ 5  , 6  ]   [ x3 , 8 ]   [  5*x2 +  6*x3 ,  5*7 +  6*8 ]
	*/
	vector&lt; <a href="ad.xml" target="_top">AD</a>&lt;double&gt; &gt; atom_y(nr_result * nc_result);
	afun(atom_x, atom_y);

	ok &amp;= (atom_y[0] == x[0]*x[2] + x[1]*x[3]) &amp; Variable(atom_y[0]);
	ok &amp;= (atom_y[1] == x[0]*7.   + x[1]*8.  ) &amp; Variable(atom_y[1]);
	ok &amp;= (atom_y[2] ==   5.*x[2] +   6.*x[3]) &amp; Variable(atom_y[2]);
	ok &amp;= (atom_y[3] ==   5.*7.   +   6.*8.  ) &amp; Parameter(atom_y[3]);

	// ------------------------------------------------------------------
	// define the function g : x -&gt; atom_y
	// g(x) = [ x0*x2 + x1*x3 , x0*7 + x1*8 , 5*x2  + 6*x3  , 5*7 + 6*8 ]^T
	CppAD::<a href="funconstruct.xml" target="_top">ADFun</a>&lt;double&gt; g(ax, atom_y);
</pre></font></code>

<br/>
<br/>
<b><a name="Use Atomic Function.forward" id="Use Atomic Function.forward">forward</a></b>

<code><font color='blue'><pre style='display:inline'> 
	// Test zero order forward mode evaluation of g(x)
	size_t m = atom_y.size();
	vector&lt;double&gt; y(m);
	for(j = 0; j &lt;  n; j++)
		x[j] = j + 2;
	y = g.<a href="forward.xml" target="_top">Forward</a>(0, x);
	ok &amp;= y[0] == x[0] * x[2] + x[1] * x[3];
	ok &amp;= y[1] == x[0] * 7.   + x[1] * 8.;
	ok &amp;= y[2] == 5. * x[2]   + 6. * x[3];
	ok &amp;= y[3] == 5. * 7.     + 6. * 8.;

	//----------------------------------------------------------------------
	// Test first order forward mode evaluation of g'(x) * [1, 2, 3, 4]^T 
	// g'(x) = [ x2, x3, x0, x1 ]
	//         [ 7 ,  8,  0, 0  ]
	//         [ 0 ,  0,  5, 6  ]
	//         [ 0 ,  0,  0, 0  ] 
	CppAD::vector&lt;double&gt; dx(n), dy(m);
	for(j = 0; j &lt;  n; j++)
		dx[j] = j + 1;
	dy = g.<a href="forward.xml" target="_top">Forward</a>(1, dx);
	ok &amp;= dy[0] == 1. * x[2] + 2. * x[3] + 3. * x[0] + 4. * x[1];
	ok &amp;= dy[1] == 1. * 7.   + 2. * 8.   + 3. * 0.   + 4. * 0.;
	ok &amp;= dy[2] == 1. * 0.   + 2. * 0.   + 3. * 5.   + 4. * 6.;
	ok &amp;= dy[3] == 1. * 0.   + 2. * 0.   + 3. * 0.   + 4. * 0.;

	//----------------------------------------------------------------------
	// Test second order forward mode 
	// g_0^2 (x) = [ 0, 0, 1, 0 ], g_0^2 (x) * [1] = [3]
	//             [ 0, 0, 0, 1 ]              [2]   [4]
	//             [ 1, 0, 0, 0 ]              [3]   [1]
	//             [ 0, 1, 0, 0 ]              [4]   [2]
	CppAD::vector&lt;double&gt; ddx(n), ddy(m);
	for(j = 0; j &lt;  n; j++)
		ddx[j] = 0.;
	ddy = g.<a href="forward.xml" target="_top">Forward</a>(2, ddx);

	// [1, 2, 3, 4] * g_0^2 (x) * [1, 2, 3, 4]^T = 1*3 + 2*4 + 3*1 + 4*2
	ok &amp;= 2. * ddy[0] == 1. * 3. + 2. * 4. + 3. * 1. + 4. * 2.; 

	// for i &gt; 0, [1, 2, 3, 4] * g_i^2 (x) * [1, 2, 3, 4]^T = 0
	ok &amp;= ddy[1] == 0.;
	ok &amp;= ddy[2] == 0.;
	ok &amp;= ddy[3] == 0.;
</pre></font></code>

<br/>
<br/>
<b><a name="Use Atomic Function.reverse" id="Use Atomic Function.reverse">reverse</a></b>

<code><font color='blue'><pre style='display:inline'> 
	// Test second order reverse mode 
	CppAD::vector&lt;double&gt; w(m), dw(2 * n);
	for(i = 0; i &lt; m; i++)
		w[i] = 0.;
	w[0] = 1.;
	dw = g.<a href="reverse.xml" target="_top">Reverse</a>(2, w);

	// g_0'(x) = [ x2, x3, x0, x1 ]
	ok &amp;= dw[0*2 + 0] == x[2];
	ok &amp;= dw[1*2 + 0] == x[3];
	ok &amp;= dw[2*2 + 0] == x[0];
	ok &amp;= dw[3*2 + 0] == x[1];

	// g_0'(x)   * [1, 2, 3, 4]  = 1 * x2 + 2 * x3 + 3 * x0 + 4 * x1
	// g_0^2 (x) * [1, 2, 3, 4]  = [3, 4, 1, 2]
	ok &amp;= dw[0*2 + 1] == 3.;
	ok &amp;= dw[1*2 + 1] == 4.;
	ok &amp;= dw[2*2 + 1] == 1.;
	ok &amp;= dw[3*2 + 1] == 2.;
</pre></font></code>

<br/>
<br/>
<b><a name="Use Atomic Function.option" id="Use Atomic Function.option">option</a></b>

<code><font color='blue'><pre style='display:inline'> 
	//----------------------------------------------------------------------
	// Test both the boolean and set sparsity at the atomic level
	for(size_t sparse_index = 0; sparse_index &lt; 2; sparse_index++)
	{	if( sparse_index == 0 )
			afun.option( CppAD::atomic_base&lt;double&gt;::bool_sparsity_enum );
		else	afun.option( CppAD::atomic_base&lt;double&gt;::set_sparsity_enum );
</pre></font></code>

<br/>
<br/>
<b><a name="Use Atomic Function.for_sparse_jac" id="Use Atomic Function.for_sparse_jac">for_sparse_jac</a></b>

<code><font color='blue'><pre style='display:inline'> 
	// Test forward Jacobian sparsity pattern
	/*
	g(x) = [ x0*x2 + x1*x3 , x0*7 + x1*8 , 5*x2  + 6*x3  , 5*7 + 6*8 ]^T
	so the sparsity pattern should be
	s[0] = {0, 1, 2, 3}
	s[1] = {0, 1}
	s[2] = {2, 3}
	s[3] = {}
	*/
	CppAD::vector&lt; std::set&lt;size_t&gt; &gt; r(n), s(m);
	for(j = 0; j &lt;  n; j++)
	{	assert( r[j].empty() );
		r[j].insert(j);
	}
	s = g.ForSparseJac(n, r);
	for(j = 0; j &lt;  n; j++)
	{	// s[0] = {0, 1, 2, 3}
		ok &amp;= s[0].find(j) != s[0].end();
		// s[1] = {0, 1}
		if( j == 0 || j == 1 )
			ok &amp;= s[1].find(j) != s[1].end();
		else	ok &amp;= s[1].find(j) == s[1].end();
		// s[2] = {2, 3}
		if( j == 2 || j == 3 )
			ok &amp;= s[2].find(j) != s[2].end();
		else	ok &amp;= s[2].find(j) == s[2].end();
	}
	// s[3] == {}
	ok &amp;= s[3].empty();
</pre></font></code>

<br/>
<br/>
<b><a name="Use Atomic Function.rev_sparse_jac" id="Use Atomic Function.rev_sparse_jac">rev_sparse_jac</a></b>

<code><font color='blue'><pre style='display:inline'> 
	// Test reverse Jacobian sparsity pattern
	for(i = 0; i &lt;  m; i++)
	{	s[i].clear();
		s[i].insert(i);
	}
	r = g.RevSparseJac(m, s);
	for(j = 0; j &lt;  n ; j++)
	{	// r[0] = {0, 1, 2, 3}
		ok &amp;= r[0].find(j) != r[0].end();
		// r[1] = {0, 1}
		if( j == 0 || j == 1 )
			ok &amp;= r[1].find(j) != r[1].end();
		else	ok &amp;= r[1].find(j) == r[1].end();
		// r[2] = {2, 3}
		if( j == 2 || j == 3 )
			ok &amp;= r[2].find(j) != r[2].end();
		else	ok &amp;= r[2].find(j) == r[2].end();
	}
	// r[3] == {}
	ok &amp;= r[3].empty();
</pre></font></code>

<br/>
<br/>
<b><a name="Use Atomic Function.rev_sparse_hes" id="Use Atomic Function.rev_sparse_hes">rev_sparse_hes</a></b>

<code><font color='blue'><pre style='display:inline'> 
	/* Test reverse Hessian sparsity pattern
	g_0^2 (x) = [ 0, 0, 1, 0 ] and for i &gt; 0, g_i^2 = 0
	            [ 0, 0, 0, 1 ]
	            [ 1, 0, 0, 0 ]
	            [ 0, 1, 0, 0 ]
	so for the sparsity pattern for the first component of g is
	h[0] = {2}
	h[1] = {3}
	h[2] = {0}
	h[3] = {1}
	*/
	CppAD::vector&lt; std::set&lt;size_t&gt; &gt; h(n), t(1);
	t[0].clear();
	t[0].insert(0);
	h = g.RevSparseHes(n, t);
	size_t check[] = {2, 3, 0, 1};
	for(j = 0; j &lt;  n; j++)
	{	// h[j] = { check[j] }
		for(i = 0; i &lt; n; i++) 
		{	if( i == check[j] )
				ok &amp;= h[j].find(i) != h[j].end();
			else	ok &amp;= h[j].find(i) == h[j].end();
		}
	}
	t[0].clear();
	for( j = 1; j &lt; n; j++)
			t[0].insert(j);
	h = g.RevSparseHes(n, t);
	for(j = 0; j &lt;  n; j++)
	{	// h[j] = { }
		for(i = 0; i &lt; n; i++) 
			ok &amp;= h[j].find(i) == h[j].end();
	}

	//-----------------------------------------------------------------
	} // end for(size_t sparse_index  ...
	//-----------------------------------------------------------------
	
	return ok;
}
</pre></font></code>

 

<hr/>Input File: example/atomic/mat_mul.cpp

</body>
</html>
