CppAD: A C++ Algorithmic Differentiation Package
20130918
|
00001 /* $Id$ */ 00002 /* -------------------------------------------------------------------------- 00003 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell 00004 00005 CppAD is distributed under multiple licenses. This distribution is under 00006 the terms of the 00007 Eclipse Public License Version 1.0. 00008 00009 A copy of this license is included in the COPYING file of this distribution. 00010 Please visit http://www.coin-or.org/CppAD/ for information on other licenses. 00011 -------------------------------------------------------------------------- */ 00012 00013 /* 00014 $begin link_mat_mul$$ 00015 $spell 00016 mul 00017 bool 00018 CppAD 00019 dz 00020 $$ 00021 00022 $index link_mat_mul$$ 00023 $index matrix, multiply speed test$$ 00024 $index multiply, matrix speed test$$ 00025 $index speed, test matrix multiple$$ 00026 $index test, matrix multiple speed$$ 00027 00028 $section Speed Testing Derivative of Matrix Multiply$$ 00029 00030 $head Prototype$$ 00031 $codei%extern bool link_mat_mul( 00032 size_t %size% , 00033 size_t %repeat% , 00034 CppAD::vector<double>& %x% , 00035 CppAD::vector<double>& %z% , 00036 CppAD::vector<double>& %dz% 00037 ); 00038 %$$ 00039 00040 $head Purpose$$ 00041 Each $cref/package/speed_main/package/$$ 00042 must define a version of this routine as specified below. 00043 This is used by the $cref speed_main$$ program 00044 to run the corresponding speed and correctness tests. 00045 00046 $head Return Value$$ 00047 If this speed test is not yet 00048 supported by a particular $icode package$$, 00049 the corresponding return value for $code link_mat_mul$$ 00050 should be $code false$$. 00051 00052 $head n$$ 00053 The argument $icode n$$ is the number of rows and columns 00054 in the square matrix $icode x$$. 00055 00056 $head repeat$$ 00057 The argument $icode repeat$$ is the number of different argument values 00058 that the derivative of $icode z$$ (or just the value of $icode z$$) 00059 will be computed. 00060 00061 $head x$$ 00062 The argument $icode x$$ is a vector with 00063 $icode%x%.size() = %size% * %size%$$ elements. 00064 The input value of its elements does not matter. 00065 The output value of its elements is the last random matrix 00066 that is multiplied and then summed to form $icode z$$; 00067 $latex \[ 00068 x_{i,j} = x[ i * s + j ] 00069 \] $$ 00070 where $icode%s% = %size%$$. 00071 00072 $head z$$ 00073 The argument $icode z$$ is a vector with one element. 00074 The input value of the element does not matter. 00075 The output of its element the sum of the elements of 00076 $icode%y% = %x% * %x%$$; i.e., 00077 $latex \[ 00078 \begin{array}{rcl} 00079 y_{i,j} & = & \sum_{k=0}^{s-1} x_{i,k} x_{k, j} 00080 \\ 00081 z & = & \sum_{i=0}^{s-1} \sum_{j=0}^{s-1} y_{i,j} 00082 \end{array} 00083 \] $$ 00084 00085 $head dz$$ 00086 The argument $icode dz$$ is a vector with 00087 $icode%dz%.size() = %size% * %size%$$. 00088 The input values of its elements do not matter. 00089 The output value of its elements form the 00090 derivative of $icode z$$ with respect to $icode x$$. 00091 00092 $end 00093 ----------------------------------------------------------------------------- 00094 */ 00095 # include <cppad/vector.hpp> 00096 # include <cppad/near_equal.hpp> 00097 00098 extern bool link_mat_mul( 00099 size_t size , 00100 size_t repeat , 00101 CppAD::vector<double>& x , 00102 CppAD::vector<double>& z , 00103 CppAD::vector<double>& dz 00104 ); 00105 bool available_mat_mul(void) 00106 { size_t size = 2; 00107 size_t repeat = 1; 00108 CppAD::vector<double> x(size * size), z(1), dz(size * size); 00109 00110 return link_mat_mul(size, repeat, x, z, dz); 00111 } 00112 bool correct_mat_mul(bool is_package_double) 00113 { size_t size = 2; 00114 size_t repeat = 1; 00115 CppAD::vector<double> x(size * size), z(1), dz(size * size); 00116 00117 link_mat_mul(size, repeat, x, z, dz); 00118 00119 double x00 = x[0 * size + 0]; 00120 double x01 = x[0 * size + 1]; 00121 double x10 = x[1 * size + 0]; 00122 double x11 = x[1 * size + 1]; 00123 bool ok = true; 00124 double check; 00125 if( is_package_double ) 00126 { check = 0; 00127 check += x00 * x00 + x01 * x10; // y00 00128 check += x00 * x01 + x01 * x11; // y01 00129 check += x10 * x00 + x11 * x10; // y10 00130 check += x10 * x01 + x11 * x11; // y11 00131 ok &= CppAD::NearEqual(check, z[0], 1e-10, 1e-10); 00132 return ok; 00133 } 00134 // partial w.r.t. x00 00135 check = x00 + x00 + x01 + x10; 00136 ok &= CppAD::NearEqual(check, dz[0 * size + 0], 1e-10, 1e-10); 00137 // partial w.r.t. x01 00138 check = x10 + x00 + x11 + x10; 00139 ok &= CppAD::NearEqual(check, dz[0 * size + 1], 1e-10, 1e-10); 00140 // partial w.r.t. x10 00141 check = x01 + x00 + x11 + x01; 00142 ok &= CppAD::NearEqual(check, dz[1 * size + 0], 1e-10, 1e-10); 00143 // partial w.r.t. x11 00144 check = x01 + x10 + x11 + x11; 00145 ok &= CppAD::NearEqual(check, dz[1 * size + 1], 1e-10, 1e-10); 00146 00147 return ok; 00148 } 00149 00150 void speed_mat_mul(size_t size, size_t repeat) 00151 { CppAD::vector<double> x(size * size), z(1), dz(size * size); 00152 00153 link_mat_mul(size, repeat, x, z, dz); 00154 return; 00155 }