Classes | |
class | glue_times |
Class which implements the immediate multiplication of two or more matrices. More... | |
class | glue_times_diag |
class | glue_times_vec |
Functions | |
template<typename T1 , typename T2 > | |
static void | glue_times::apply (Mat< typename T1::elem_type > &out, const Glue< T1, T2, glue_times > &X) |
template<typename T1 > | |
static void | glue_times::apply_inplace (Mat< typename T1::elem_type > &out, const T1 &X) |
template<typename eT1 , typename eT2 > | |
static void | glue_times::apply_mixed (Mat< typename promote_type< eT1, eT2 >::result > &out, const Mat< eT1 > &X, const Mat< eT2 > &Y) |
matrix multiplication with different element types | |
template<typename eT > | |
static arma_inline u32 | glue_times::mul_storage_cost (const Mat< eT > &X, const Mat< eT > &Y) |
template<typename eT > | |
static void | glue_times::apply_noalias (Mat< eT > &out, const Mat< eT > &A, const Mat< eT > &B) |
multiply matrices A and B, storing the result in 'out' assumes that A and B are not aliases of 'out' | |
template<typename eT > | |
static void | glue_times::apply (Mat< eT > &out, const Mat< eT > &A, const Mat< eT > &B) |
template<typename eT > | |
static void | glue_times::apply (Mat< eT > &out, const Mat< eT > &A, const Mat< eT > &B, const Mat< eT > &C) |
template<typename eT > | |
static eT | glue_times::direct_rowvec_mat_colvec (const eT *A_mem, const Mat< eT > &B, const eT *C_mem) |
template<typename eT > | |
static eT | glue_times::direct_rowvec_diagmat_colvec (const eT *A_mem, const Mat< eT > &B, const eT *C_mem) |
template<typename eT > | |
static eT | glue_times::direct_rowvec_invdiagmat_colvec (const eT *A_mem, const Mat< eT > &B, const eT *C_mem) |
template<typename eT > | |
static eT | glue_times::direct_rowvec_invdiagvec_colvec (const eT *A_mem, const Mat< eT > &B, const eT *C_mem) |
template<typename eT > | |
static void | glue_times::apply (Mat< eT > &out, const Glue< Mat< eT >, Mat< eT >, glue_times > &X) |
template<typename eT > | |
static void | glue_times::apply (Mat< eT > &out, const Glue< Glue< Mat< eT >, Mat< eT >, glue_times >, Mat< eT >, glue_times > &X) |
template<typename T1 , typename T2 > | |
static void | glue_times::apply (Mat< typename T1::elem_type > &out, const Glue< T1, Op< T2, op_trans >, glue_times > &X) |
out = T1 * trans(T2) | |
template<typename T1 , typename T2 > | |
static void | glue_times::apply (Mat< typename T1::elem_type > &out, const Glue< Op< T1, op_trans >, T2, glue_times > &X) |
out = trans(T1) * T2 | |
template<typename T1 , typename T2 > | |
static void | glue_times::apply (Mat< typename T1::elem_type > &out, const Glue< Op< T1, op_trans >, Op< T2, op_trans >, glue_times > &X) |
out = trans(T1) * trans(T2) | |
template<typename T1 , typename T2 > | |
static void | glue_times::apply (Mat< typename T1::elem_type > &out, const Glue< Op< T1, op_neg >, T2, glue_times > &X) |
out = -T1 * T2 | |
template<typename T1 , typename T2 > | |
static void | glue_times::apply_inplace (Mat< typename T1::elem_type > &out, const Glue< T1, T2, glue_times > &X) |
template<typename T1 , typename T2 > | |
static void | glue_times_diag::apply (Mat< typename T1::elem_type > &out, const T1 &A, const Op< T2, op_diagmat > &B) |
template<typename T1 , typename T2 > | |
static void | glue_times_diag::apply (Mat< typename T1::elem_type > &out, const Op< T1, op_diagmat > &A, const T2 &B) |
template<typename T1 , typename T2 > | |
static void | glue_times_diag::apply (Mat< typename T1::elem_type > &out, const Op< T1, op_diagmat > &A, const Op< T2, op_diagmat > &B) |
template<typename T1 , typename T2 > | |
static void | glue_times_diag::apply (Mat< typename T1::elem_type > &out, const Glue< T1, Op< T2, op_diagmat >, glue_times_diag > &X) |
template<typename T1 , typename T2 > | |
static void | glue_times_diag::apply (Mat< typename T1::elem_type > &out, const Glue< Op< T1, op_diagmat >, T2, glue_times_diag > &X) |
template<typename T1 , typename T2 > | |
static void | glue_times_diag::apply (Mat< typename T1::elem_type > &out, const Glue< Op< T1, op_diagmat >, Op< T2, op_diagmat >, glue_times_diag > &X) |
template<typename T1 , typename T2 > | |
static void | glue_times_vec::apply (Mat< typename T1::elem_type > &out, const Glue< T1, T2, glue_times_vec > &X) |
at least one of T1 and T2 is a vector (both could be vectors) | |
template<typename eT > | |
static void | glue_times_vec::mul_col_row (Mat< eT > &out, const eT *A_mem, const eT *B_mem) |
template<typename eT > | |
static void | glue_times_vec::mul_col_row_inplace_add (Mat< eT > &out, const eT *A_mem, const eT *B_mem) |
template<typename eT > | |
static void | glue_times_vec::apply (Mat< eT > &out, const Glue< Col< eT >, Row< eT >, glue_times_vec > &X) |
template<typename eT > | |
static void | glue_times_vec::apply (Mat< eT > &out, const Glue< Op< Row< eT >, op_trans >, Row< eT >, glue_times_vec > &X) |
template<typename eT > | |
static void | glue_times_vec::apply (Mat< eT > &out, const Glue< Col< eT >, Op< Col< eT >, op_trans >, glue_times_vec > &X) |
template<typename T1 > | |
static void | glue_times_vec::apply (Mat< typename T1::elem_type > &out, const Glue< Op< T1, op_trans >, Col< typename T1::elem_type >, glue_times_vec > &X) |
void glue_times::apply | ( | Mat< typename T1::elem_type > & | out, | |
const Glue< T1, T2, glue_times > & | X | |||
) | [inline, static, inherited] |
Definition at line 23 of file glue_times_meat.hpp.
References Glue< T1, T2, glue_type >::A, apply_noalias(), Glue< T1, T2, glue_type >::B, mul_storage_cost(), Mat< eT >::n_cols, and Mat< eT >::n_rows.
Referenced by apply(), apply_inplace(), apply_mixed(), and apply_noalias().
00024 { 00025 arma_extra_debug_sigprint(); 00026 00027 typedef typename T1::elem_type eT; 00028 00029 const s32 N_mat = 1 + depth_lhs< glue_times, Glue<T1,T2,glue_times> >::num; 00030 00031 arma_extra_debug_print(arma_boost::format("N_mat = %d") % N_mat); 00032 00033 if(N_mat == 2) 00034 { 00035 const unwrap<T1> tmp1(X.A); 00036 const unwrap<T2> tmp2(X.B); 00037 00038 glue_times::apply(out, tmp1.M, tmp2.M); 00039 } 00040 else 00041 { 00042 // we have at least three matrices 00043 00044 const Mat<eT>* ptrs[N_mat]; 00045 bool del[N_mat]; 00046 00047 // takes care of any aliasing problems 00048 mat_ptrs_outcheck<glue_times, Glue<T1,T2,glue_times> >::get_ptrs(ptrs, del, X, &out); 00049 00050 for(s32 i=0; i<N_mat; ++i) arma_extra_debug_print( arma_boost::format("ptrs[%d] = %x") % i % ptrs[i] ); 00051 for(s32 i=0; i<N_mat; ++i) arma_extra_debug_print( arma_boost::format(" del[%d] = %d") % i % del[i] ); 00052 00053 00054 arma_extra_debug_print( arma_boost::format("required size of 'out': %d, %d") % ptrs[0]->n_rows % ptrs[N_mat-1]->n_cols ); 00055 00056 int order[N_mat]; for(s32 i=0; i<N_mat; ++i) order[i] = -1; 00057 00058 int first_id = 0; 00059 int last_id = N_mat-1; 00060 int starting_id = -1; 00061 00062 int mat_count = N_mat; 00063 00064 int largest_size = 0; 00065 00066 while(mat_count != 0) 00067 { 00068 00069 for(s32 i=first_id; i != N_mat; ++i) 00070 { 00071 if(order[i] == -1) { first_id = i; break; } 00072 } 00073 00074 for(s32 i=last_id; i != -1; --i) 00075 { 00076 if(order[i] == -1) { last_id = i; break; } 00077 } 00078 00079 arma_extra_debug_print(); 00080 arma_extra_debug_print(arma_boost::format("mat_count = %d") % mat_count ); 00081 arma_extra_debug_print(arma_boost::format("first_id = %d") % first_id ); 00082 arma_extra_debug_print(arma_boost::format("last_id = %d") % last_id ); 00083 00084 if(first_id == last_id) { order[first_id] = 0; starting_id = first_id; break; } 00085 00086 s32 storage_cost_wo_last = mul_storage_cost( *ptrs[ first_id ], *ptrs[ last_id-1 ] ); 00087 s32 storage_cost_wo_first = mul_storage_cost( *ptrs[ first_id+1 ], *ptrs[ last_id ] ); 00088 00089 if(storage_cost_wo_last < storage_cost_wo_first) 00090 { 00091 order[last_id] = mat_count-1; 00092 if(storage_cost_wo_last > largest_size) largest_size = storage_cost_wo_last; 00093 } 00094 else 00095 { 00096 order[first_id] = mat_count-1; 00097 if(storage_cost_wo_first > largest_size) largest_size = storage_cost_wo_first; 00098 } 00099 00100 arma_extra_debug_print(arma_boost::format("storage_cost_wo_last = %d") % storage_cost_wo_last ); 00101 arma_extra_debug_print(arma_boost::format("storage_cost_wo_first = %d") % storage_cost_wo_first ); 00102 00103 arma_extra_debug_print("order = "); 00104 for(s32 i=0; i != N_mat; ++i) arma_extra_debug_print(order[i]); 00105 00106 --mat_count; 00107 } 00108 00109 arma_extra_debug_print("final order = "); 00110 for(s32 i=0; i != N_mat; ++i) arma_extra_debug_print(order[i]); 00111 00112 arma_extra_debug_print(arma_boost::format("*** largest_size = %d") % largest_size); 00113 arma_extra_debug_print(arma_boost::format("starting_id = %d") % starting_id); 00114 00115 00116 // multiply based on order 00117 // if there are only three matrices, we need only one temporary store: 00118 // out = a*b*c translates to: tmp1 = a*b, out = tmp1*c 00119 // 00120 // if there are four matrices, we need two temporary stores 00121 // out = a*b*c*d translates to: tmp1 = a*b, tmp2 = tmp1*c, out = tmp2*d 00122 // 00123 // if there are five matrices, we need two temporary stores 00124 // out = a*b*c*d*e translates to: tmp1 = a*b, tmp2 = tmp1*c, tmp1 = tmp2*d, out = tmp1*e 00125 // 00126 // if there are six matrices, we need two temporary stores 00127 // out = a*b*c*d*e*f translates to: tmp1 = a*b, tmp2 = tmp1*c, tmp1 = tmp2*d, tmp2 = tmp1*e, out = tmp2*f 00128 // 00129 00130 00131 const u32 N_mul = N_mat - 1; 00132 int mul_count = N_mul; 00133 int current_id = starting_id; 00134 00135 const Mat<eT>* src_mat_1_ptr = ptrs[current_id]; 00136 const Mat<eT>* src_mat_2_ptr = 0; 00137 00138 // TODO: 00139 // allocate two storage areas (of size 'largest_size'), not two matrices 00140 00141 00142 Mat<eT> tmp_mat_1; 00143 Mat<eT> tmp_mat_2; 00144 00145 Mat<eT>* tmp_mat_1_ptr = &tmp_mat_1; 00146 Mat<eT>* tmp_mat_2_ptr = (N_mul <= 2) ? 0 : &tmp_mat_2; 00147 00148 Mat<eT>* dest_mat_ptr = tmp_mat_2_ptr; 00149 00150 arma_extra_debug_print(arma_boost::format("tmp_mat_1_ptr = %x") % tmp_mat_1_ptr ); 00151 arma_extra_debug_print(arma_boost::format("tmp_mat_2_ptr = %x") % tmp_mat_2_ptr ); 00152 arma_extra_debug_print(arma_boost::format("&out = %x") % &out ); 00153 00154 while(mul_count != 0) 00155 { 00156 arma_extra_debug_print(""); 00157 arma_extra_debug_print(""); 00158 arma_extra_debug_print(arma_boost::format("mul_count = %d") % mul_count); 00159 00160 arma_extra_debug_print("order = "); 00161 for(s32 i=0; i != N_mat; ++i) arma_extra_debug_print(order[i]); 00162 arma_extra_debug_print(""); 00163 00164 // only one multiplication left, hence destination matrix is the out matrix 00165 if(mul_count == 1) 00166 { 00167 arma_extra_debug_print("dest_mat = &out"); 00168 dest_mat_ptr = &out; 00169 } 00170 else 00171 { 00172 if(dest_mat_ptr == tmp_mat_2_ptr) 00173 { 00174 arma_extra_debug_print("dest_mat_ptr = tmp_mat_2_ptr"); 00175 dest_mat_ptr = tmp_mat_1_ptr; 00176 } 00177 else 00178 { 00179 arma_extra_debug_print("dest_mat_ptr = tmp_mat_1_ptr"); 00180 dest_mat_ptr = tmp_mat_2_ptr; 00181 } 00182 } 00183 00184 arma_extra_debug_print(arma_boost::format("dest_mat_ptr = %x") % dest_mat_ptr ); 00185 00186 // search on either side of current_pos for a useable value. unuseable values are equal to -1 00187 s32 left_val = N_mat; 00188 s32 left_id = -1; 00189 00190 s32 right_val = N_mat; 00191 s32 right_id = -1; 00192 00193 // go left from current_pos 00194 for(s32 i=current_id-1; i >= 0; --i) 00195 if( order[i] > order[current_id] ) { left_val = order[i]; left_id = i; break; } 00196 00197 // go right from current_pos 00198 for(s32 i=current_id+1; i < N_mat; ++i) 00199 if( order[current_id] < order[i] ) { right_val = order[i]; right_id = i; break; } 00200 00201 arma_extra_debug_print(""); 00202 arma_extra_debug_print(arma_boost::format("left_id = %d") % left_id ); 00203 arma_extra_debug_print(arma_boost::format("left_val = %f") % left_val ); 00204 00205 arma_extra_debug_print(""); 00206 arma_extra_debug_print(arma_boost::format("right_id = %d") % right_id ); 00207 arma_extra_debug_print(arma_boost::format("right_val = %f") % right_val ); 00208 00209 00210 if(left_val < right_val) 00211 { 00212 // a pre-multiply 00213 src_mat_2_ptr = ptrs[left_id]; 00214 00215 arma_extra_debug_print(""); 00216 arma_extra_debug_print(arma_boost::format("case pre-multiply with matrix %d") % left_id); 00217 arma_extra_debug_print(arma_boost::format("required destination size: %d, %d (%d)") % src_mat_2_ptr->n_rows % src_mat_1_ptr->n_cols % (src_mat_2_ptr->n_rows * src_mat_1_ptr->n_cols) ); 00218 00219 glue_times::apply_noalias(*dest_mat_ptr, *src_mat_2_ptr, *src_mat_1_ptr); 00220 00221 order[current_id] = -1; 00222 current_id = left_id; 00223 } 00224 else 00225 { 00226 // a post-multiply 00227 src_mat_2_ptr = ptrs[right_id]; 00228 00229 arma_extra_debug_print(""); 00230 arma_extra_debug_print(arma_boost::format("case post-multiply with matrix %d") % right_id); 00231 arma_extra_debug_print(arma_boost::format("required destination size: %d, %d (%d)") % src_mat_1_ptr->n_rows % src_mat_2_ptr->n_cols % (src_mat_1_ptr->n_rows * src_mat_2_ptr->n_cols) ); 00232 00233 glue_times::apply_noalias(*dest_mat_ptr, *src_mat_1_ptr, *src_mat_2_ptr); 00234 00235 order[current_id] = -1; 00236 current_id = right_id; 00237 } 00238 00239 // update pointer to source matrix: must point to last multiplication result 00240 src_mat_1_ptr = dest_mat_ptr; 00241 00242 --mul_count; 00243 } 00244 00245 00246 for(s32 i=0; i<N_mat; ++i) 00247 { 00248 if(del[i] == true) 00249 { 00250 arma_extra_debug_print(arma_boost::format("delete mat_ptr[%d]") % i ); 00251 delete ptrs[i]; 00252 } 00253 } 00254 } 00255 }
void glue_times::apply_inplace | ( | Mat< typename T1::elem_type > & | out, | |
const T1 & | X | |||
) | [inline, static, inherited] |
Definition at line 262 of file glue_times_meat.hpp.
References apply(), Mat< eT >::at(), Mat< eT >::colptr(), podarray< T1 >::memptr(), Mat< eT >::n_cols, and Mat< eT >::n_rows.
Referenced by Mat< eT >::operator*=(), and subview< eT >::times_inplace().
00263 { 00264 arma_extra_debug_sigprint(); 00265 00266 typedef typename T1::elem_type eT; 00267 00268 const unwrap<T1> tmp(X); 00269 const Mat<eT>& B = tmp.M; 00270 00271 arma_debug_assert_mul_size(out, B, "matrix multiply"); 00272 00273 if(out.n_cols == B.n_cols) 00274 { 00275 podarray<eT> tmp(out.n_cols); 00276 eT* tmp_rowdata = tmp.memptr(); 00277 00278 for(u32 out_row=0; out_row < out.n_rows; ++out_row) 00279 { 00280 for(u32 out_col=0; out_col < out.n_cols; ++out_col) 00281 { 00282 tmp_rowdata[out_col] = out.at(out_row,out_col); 00283 } 00284 00285 for(u32 B_col=0; B_col < B.n_cols; ++B_col) 00286 { 00287 const eT* B_coldata = B.colptr(B_col); 00288 00289 eT val = eT(0); 00290 for(u32 i=0; i < B.n_rows; ++i) 00291 { 00292 val += tmp_rowdata[i] * B_coldata[i]; 00293 } 00294 00295 out.at(out_row,B_col) = val; 00296 } 00297 } 00298 00299 } 00300 else 00301 { 00302 const Mat<eT> tmp(out); 00303 glue_times::apply(out, tmp, B); 00304 } 00305 00306 }
void glue_times::apply_mixed | ( | Mat< typename promote_type< eT1, eT2 >::result > & | out, | |
const Mat< eT1 > & | X, | |||
const Mat< eT2 > & | Y | |||
) | [inline, static, inherited] |
matrix multiplication with different element types
Definition at line 314 of file glue_times_meat.hpp.
References apply(), Mat< eT >::n_cols, and Mat< eT >::n_rows.
Referenced by operator*().
00315 { 00316 arma_extra_debug_sigprint(); 00317 00318 typedef typename promote_type<eT1,eT2>::result out_eT; 00319 00320 arma_debug_assert_mul_size(X,Y, "matrix multiply"); 00321 00322 out.set_size(X.n_rows,Y.n_cols); 00323 gemm_mixed<>::apply(out, X, Y); 00324 }
arma_inline u32 glue_times::mul_storage_cost | ( | const Mat< eT > & | X, | |
const Mat< eT > & | Y | |||
) | [inline, static, inherited] |
Definition at line 330 of file glue_times_meat.hpp.
References Mat< eT >::n_cols, and Mat< eT >::n_rows.
Referenced by apply().
void glue_times::apply_noalias | ( | Mat< eT > & | out, | |
const Mat< eT > & | A, | |||
const Mat< eT > & | B | |||
) | [inline, static, inherited] |
multiply matrices A and B, storing the result in 'out' assumes that A and B are not aliases of 'out'
Definition at line 342 of file glue_times_meat.hpp.
References apply(), Mat< eT >::n_cols, Mat< eT >::n_rows, and Mat< eT >::set_size().
Referenced by apply().
00343 { 00344 arma_extra_debug_sigprint(); 00345 00346 arma_debug_assert_mul_size(A, B, "matrix multiply"); 00347 00348 out.set_size(A.n_rows,B.n_cols); 00349 gemm<>::apply(out,A,B); 00350 }
void glue_times::apply | ( | Mat< eT > & | out, | |
const Mat< eT > & | A, | |||
const Mat< eT > & | B | |||
) | [inline, static, inherited] |
Definition at line 357 of file glue_times_meat.hpp.
References apply_noalias().
00358 { 00359 arma_extra_debug_sigprint(); 00360 00361 if( (&out != &A_in) && (&out != &B_in) ) 00362 { 00363 glue_times::apply_noalias(out,A_in,B_in); 00364 } 00365 else 00366 { 00367 00368 if( (&out == &A_in) && (&out != &B_in) ) 00369 { 00370 Mat<eT> A_copy(A_in); 00371 glue_times::apply_noalias(out,A_copy,B_in); 00372 } 00373 else 00374 if( (&out != &A_in) && (&out == &B_in) ) 00375 { 00376 Mat<eT> B_copy(B_in); 00377 glue_times::apply_noalias(out,A_in,B_copy); 00378 } 00379 else 00380 if( (&out == &A_in) && (&out == &B_in) ) 00381 { 00382 Mat<eT> tmp(A_in); 00383 glue_times::apply_noalias(out,tmp,tmp); 00384 } 00385 00386 } 00387 00388 }
void glue_times::apply | ( | Mat< eT > & | out, | |
const Mat< eT > & | A, | |||
const Mat< eT > & | B, | |||
const Mat< eT > & | C | |||
) | [inline, static, inherited] |
Definition at line 394 of file glue_times_meat.hpp.
References apply_noalias(), and mul_storage_cost().
00395 { 00396 arma_extra_debug_sigprint(); 00397 00398 arma_debug_assert_mul_size(A, B, "matrix multiply"); 00399 arma_debug_assert_mul_size(B, C, "matrix multiply"); 00400 00401 if( mul_storage_cost(A,B) <= mul_storage_cost(B,C) ) 00402 { 00403 Mat<eT> tmp; 00404 glue_times::apply_noalias(tmp, A, B); 00405 00406 if(&out != &C) 00407 { 00408 glue_times::apply_noalias(out, tmp, C); 00409 } 00410 else 00411 { 00412 Mat<eT> C_copy = C; 00413 glue_times::apply_noalias(out, tmp, C_copy); 00414 } 00415 00416 } 00417 else 00418 { 00419 Mat<eT> tmp; 00420 glue_times::apply_noalias(tmp, B, C); 00421 00422 if(&out != &A) 00423 { 00424 glue_times::apply_noalias(out, A, tmp); 00425 } 00426 else 00427 { 00428 Mat<eT> A_copy = A; 00429 glue_times::apply_noalias(out, A_copy, tmp); 00430 } 00431 } 00432 00433 }
eT glue_times::direct_rowvec_mat_colvec | ( | const eT * | A_mem, | |
const Mat< eT > & | B, | |||
const eT * | C_mem | |||
) | [inline, static, inherited] |
Definition at line 441 of file glue_times_meat.hpp.
References Mat< eT >::at(), Mat< eT >::colptr(), op_dot::direct_dot(), podarray< T1 >::mem, Mat< eT >::n_cols, and Mat< eT >::n_rows.
Referenced by operator*().
00446 { 00447 arma_extra_debug_sigprint(); 00448 00449 const u32 cost_AB = B.n_cols; 00450 const u32 cost_BC = B.n_rows; 00451 00452 if(cost_AB <= cost_BC) 00453 { 00454 podarray<eT> tmp(B.n_cols); 00455 00456 for(u32 col=0; col<B.n_cols; ++col) 00457 { 00458 const eT* B_coldata = B.colptr(col); 00459 00460 eT val = eT(0); 00461 for(u32 i=0; i<B.n_rows; ++i) 00462 { 00463 val += A_mem[i] * B_coldata[i]; 00464 } 00465 00466 tmp[col] = val; 00467 } 00468 00469 return op_dot::direct_dot(B.n_cols, tmp.mem, C_mem); 00470 } 00471 else 00472 { 00473 podarray<eT> tmp(B.n_rows); 00474 00475 for(u32 row=0; row<B.n_rows; ++row) 00476 { 00477 eT val = eT(0); 00478 for(u32 col=0; col<B.n_cols; ++col) 00479 { 00480 val += B.at(row,col) * C_mem[col]; 00481 } 00482 00483 tmp[row] = val; 00484 } 00485 00486 return op_dot::direct_dot(B.n_rows, A_mem, tmp.mem); 00487 } 00488 00489 00490 }
eT glue_times::direct_rowvec_diagmat_colvec | ( | const eT * | A_mem, | |
const Mat< eT > & | B, | |||
const eT * | C_mem | |||
) | [inline, static, inherited] |
Definition at line 498 of file glue_times_meat.hpp.
References Mat< eT >::at(), and Mat< eT >::n_rows.
Referenced by operator*().
eT glue_times::direct_rowvec_invdiagmat_colvec | ( | const eT * | A_mem, | |
const Mat< eT > & | B, | |||
const eT * | C_mem | |||
) | [inline, static, inherited] |
Definition at line 522 of file glue_times_meat.hpp.
References Mat< eT >::at(), and Mat< eT >::n_rows.
Referenced by operator*().
eT glue_times::direct_rowvec_invdiagvec_colvec | ( | const eT * | A_mem, | |
const Mat< eT > & | B, | |||
const eT * | C_mem | |||
) | [inline, static, inherited] |
Definition at line 546 of file glue_times_meat.hpp.
References Mat< eT >::mem, and Mat< eT >::n_elem.
Referenced by operator*().
void glue_times::apply | ( | Mat< eT > & | out, | |
const Glue< Mat< eT >, Mat< eT >, glue_times > & | X | |||
) | [inline, static, inherited] |
Definition at line 574 of file glue_times_meat.hpp.
References apply().
00575 { 00576 glue_times::apply(out, X.A, X.B); 00577 }
void glue_times::apply | ( | Mat< eT > & | out, | |
const Glue< Glue< Mat< eT >, Mat< eT >, glue_times >, Mat< eT >, glue_times > & | X | |||
) | [inline, static, inherited] |
Definition at line 584 of file glue_times_meat.hpp.
References apply().
00585 { 00586 glue_times::apply(out, X.A.A, X.A.B, X.B); 00587 }
void glue_times::apply | ( | Mat< typename T1::elem_type > & | out, | |
const Glue< T1, Op< T2, op_trans >, glue_times > & | X | |||
) | [inline, static, inherited] |
out = T1 * trans(T2)
Definition at line 595 of file glue_times_meat.hpp.
References apply(), Mat< eT >::at(), Mat< eT >::colptr(), Mat< eT >::n_cols, Mat< eT >::n_rows, and Mat< eT >::set_size().
00596 { 00597 arma_extra_debug_sigprint(); 00598 00599 00600 typedef typename T1::elem_type eT; 00601 00602 // checks for aliases are done later 00603 00604 const unwrap<T1> tmp1(X.A); 00605 const unwrap<T2> tmp2(X.B.m); 00606 00607 const Mat<eT>& A = tmp1.M; 00608 const Mat<eT>& B = tmp2.M; 00609 00610 arma_debug_assert_mul_size(A.n_rows, A.n_cols, B.n_cols, B.n_rows, "matrix multiply"); 00611 00612 if( (A.n_rows*B.n_rows) > 0) 00613 { 00614 if(&A != &B) // A*B' 00615 { 00616 unwrap_check< Mat<eT> > A_safe_tmp(A, out); 00617 unwrap_check< Mat<eT> > B_safe_tmp(B, out); 00618 00619 const Mat<eT>& A_safe = A_safe_tmp.M; 00620 const Mat<eT>& B_safe = B_safe_tmp.M; 00621 00622 out.set_size(A_safe.n_rows, B_safe.n_rows); 00623 00624 gemm<false,true>::apply(out, A, B); 00625 } 00626 else // A*A' 00627 { 00628 arma_extra_debug_print("glue_times::apply(): detected A*A'"); 00629 00630 Mat<eT> tmp; 00631 op_trans::apply(tmp,A); 00632 00633 // no aliasing problem 00634 out.set_size(A.n_rows, A.n_rows); 00635 00636 for(u32 row=0; row != A.n_rows; ++row) 00637 { 00638 for(u32 col=0; col <= row; ++col) 00639 { 00640 const eT* coldata1 = tmp.colptr(row); 00641 const eT* coldata2 = tmp.colptr(col); 00642 00643 eT val = eT(0); 00644 for(u32 i=0; i < tmp.n_rows; ++i) 00645 { 00646 val += coldata1[i] * coldata2[i]; 00647 } 00648 00649 out.at(row,col) = val; 00650 out.at(col,row) = val; 00651 } 00652 } 00653 00654 } 00655 00656 } 00657 00658 }
void glue_times::apply | ( | Mat< typename T1::elem_type > & | out, | |
const Glue< Op< T1, op_trans >, T2, glue_times > & | X | |||
) | [inline, static, inherited] |
out = trans(T1) * T2
Definition at line 666 of file glue_times_meat.hpp.
References apply(), Mat< eT >::n_cols, Mat< eT >::n_rows, and Mat< eT >::set_size().
00667 { 00668 arma_extra_debug_sigprint(); 00669 00670 typedef typename T1::elem_type eT; 00671 00672 const unwrap_check<T1> tmp1(X.A.m, out); 00673 const unwrap_check<T2> tmp2(X.B, out); 00674 00675 const Mat<eT>& A = tmp1.M; 00676 const Mat<eT>& B = tmp2.M; 00677 00678 arma_debug_assert_mul_size(A.n_cols, A.n_rows, B.n_rows, B.n_cols, "matrix multiply"); 00679 00680 if( (A.n_cols*B.n_cols) > 0 ) 00681 { 00682 out.set_size(A.n_cols, B.n_cols); 00683 00684 gemm<true,false>::apply(out, A, B); 00685 } 00686 00687 }
void glue_times::apply | ( | Mat< typename T1::elem_type > & | out, | |
const Glue< Op< T1, op_trans >, Op< T2, op_trans >, glue_times > & | X | |||
) | [inline, static, inherited] |
out = trans(T1) * trans(T2)
Definition at line 695 of file glue_times_meat.hpp.
References apply(), Mat< eT >::n_cols, Mat< eT >::n_rows, and Mat< eT >::set_size().
00696 { 00697 arma_extra_debug_sigprint(); 00698 00699 typedef typename T1::elem_type eT; 00700 00701 const unwrap_check<T1> tmp1(X.A.m, out); 00702 const unwrap_check<T2> tmp2(X.B.m, out); 00703 00704 const Mat<eT>& A = tmp1.M; 00705 const Mat<eT>& B = tmp2.M; 00706 00707 arma_debug_assert_mul_size(A.n_cols, A.n_rows, B.n_cols, B.n_rows, "matrix multiply"); 00708 00709 if( (A.n_cols*B.n_rows) > 0 ) 00710 { 00711 out.set_size(A.n_cols, B.n_rows); 00712 00713 gemm<true,true>::apply(out, A, B); 00714 00715 } 00716 00717 }
void glue_times::apply | ( | Mat< typename T1::elem_type > & | out, | |
const Glue< Op< T1, op_neg >, T2, glue_times > & | X | |||
) | [inline, static, inherited] |
out = -T1 * T2
Definition at line 726 of file glue_times_meat.hpp.
References apply(), and Mat< eT >::n_elem.
00727 { 00728 arma_extra_debug_sigprint(); 00729 00730 typedef typename T1::elem_type eT; 00731 00732 const unwrap_check<T1> tmp1(X.A.m, out); 00733 const unwrap_check<T2> tmp2(X.B, out); 00734 00735 const Mat<eT>& A = tmp1.M; 00736 const Mat<eT>& B = tmp2.M; 00737 00738 glue_times::apply(out, A, B); 00739 00740 const u32 n_elem = out.n_elem; 00741 for(u32 i=0; i<n_elem; ++i) 00742 { 00743 out[i] = -out[i]; 00744 } 00745 }
void glue_times::apply_inplace | ( | Mat< typename T1::elem_type > & | out, | |
const Glue< T1, T2, glue_times > & | X | |||
) | [inline, static, inherited] |
Definition at line 752 of file glue_times_meat.hpp.
void glue_times_diag::apply | ( | Mat< typename T1::elem_type > & | out, | |
const T1 & | A, | |||
const Op< T2, op_diagmat > & | B | |||
) | [inline, static, inherited] |
Definition at line 772 of file glue_times_meat.hpp.
References Mat< eT >::at(), Mat< eT >::colptr(), Mat< eT >::is_square(), Op< T1, op_type >::m, Mat< eT >::n_cols, Mat< eT >::n_rows, and Mat< eT >::set_size().
Referenced by glue_times_diag::apply().
00773 { 00774 arma_extra_debug_sigprint(); 00775 00776 isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check(); 00777 00778 const unwrap_check<T1> tmp1(A_orig, out); 00779 const unwrap_check<T2> tmp2(B_orig.m, out); 00780 00781 typedef typename T1::elem_type eT; 00782 00783 const Mat<eT>& A = tmp1.M; 00784 const Mat<eT>& B = tmp2.M; 00785 00786 arma_debug_check( (B.is_square() == false), "glue_times_diag::apply(): incompatible matrix dimensions" ); 00787 arma_debug_assert_mul_size(A.n_rows, A.n_cols, B.n_rows, B.n_cols, "matrix multiply"); 00788 00789 out.set_size(A.n_rows, B.n_cols); 00790 00791 for(u32 col=0; col<A.n_cols; ++col) 00792 { 00793 const eT val = B.at(col,col); 00794 00795 const eT* A_coldata = A.colptr(col); 00796 eT* out_coldata = out.colptr(col); 00797 00798 for(u32 row=0; row<B.n_rows; ++row) 00799 { 00800 out_coldata[row] = A_coldata[row] * val; 00801 } 00802 00803 } 00804 00805 }
void glue_times_diag::apply | ( | Mat< typename T1::elem_type > & | out, | |
const Op< T1, op_diagmat > & | A, | |||
const T2 & | B | |||
) | [inline, static, inherited] |
Definition at line 812 of file glue_times_meat.hpp.
References Mat< eT >::at(), Mat< eT >::colptr(), Mat< eT >::is_square(), Op< T1, op_type >::m, Mat< eT >::n_cols, Mat< eT >::n_rows, and Mat< eT >::set_size().
00813 { 00814 arma_extra_debug_sigprint(); 00815 00816 isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check(); 00817 00818 const unwrap_check<T1> tmp1(A_orig.m, out); 00819 const unwrap_check<T2> tmp2(B_orig, out); 00820 00821 typedef typename T1::elem_type eT; 00822 00823 const Mat<eT>& A = tmp1.M; 00824 const Mat<eT>& B = tmp2.M; 00825 00826 arma_debug_check( (A.is_square() == false), "glue_times_diag::apply(): incompatible matrix dimensions" ); 00827 arma_debug_assert_mul_size(A.n_rows, A.n_cols, B.n_rows, B.n_cols, "matrix multiply"); 00828 00829 out.set_size(A.n_rows, B.n_cols); 00830 00831 00832 for(u32 col=0; col<A.n_cols; ++col) 00833 { 00834 const eT* B_coldata = B.colptr(col); 00835 eT* out_coldata = out.colptr(col); 00836 00837 for(u32 row=0; row<B.n_rows; ++row) 00838 { 00839 out_coldata[row] = A.at(row,row) * B_coldata[row]; 00840 } 00841 00842 } 00843 00844 }
void glue_times_diag::apply | ( | Mat< typename T1::elem_type > & | out, | |
const Op< T1, op_diagmat > & | A, | |||
const Op< T2, op_diagmat > & | B | |||
) | [inline, static, inherited] |
Definition at line 851 of file glue_times_meat.hpp.
References Mat< eT >::at(), Mat< eT >::is_square(), Op< T1, op_type >::m, Mat< eT >::n_cols, Mat< eT >::n_rows, and Mat< eT >::zeros().
00852 { 00853 arma_extra_debug_sigprint(); 00854 00855 isnt_same_type<typename T1::elem_type, typename T2::elem_type>::check(); 00856 00857 unwrap_check<T1> tmp1(A_orig.m, out); 00858 unwrap_check<T2> tmp2(B_orig.m, out); 00859 00860 typedef typename T1::elem_type eT; 00861 00862 const Mat<eT>& A = tmp1.M; 00863 const Mat<eT>& B = tmp2.M; 00864 00865 arma_debug_check( !A.is_square() || !B.is_square(), "glue_times_diag::apply(): incompatible matrix dimensions" ); 00866 arma_debug_assert_mul_size(A.n_rows, A.n_cols, B.n_rows, B.n_cols, "matrix multiply"); 00867 00868 out.zeros(A.n_rows, B.n_cols); 00869 00870 for(u32 i=0; i<A.n_rows; ++i) 00871 { 00872 out.at(i,i) = A.at(i,i) * B.at(i,i); 00873 } 00874 }
void glue_times_diag::apply | ( | Mat< typename T1::elem_type > & | out, | |
const Glue< T1, Op< T2, op_diagmat >, glue_times_diag > & | X | |||
) | [inline, static, inherited] |
Definition at line 881 of file glue_times_meat.hpp.
References glue_times_diag::apply().
00882 { 00883 glue_times_diag::apply(out, X.A, X.B); 00884 }
void glue_times_diag::apply | ( | Mat< typename T1::elem_type > & | out, | |
const Glue< Op< T1, op_diagmat >, T2, glue_times_diag > & | X | |||
) | [inline, static, inherited] |
Definition at line 891 of file glue_times_meat.hpp.
References glue_times_diag::apply().
00892 { 00893 glue_times_diag::apply(out, X.A, X.B); 00894 }
void glue_times_diag::apply | ( | Mat< typename T1::elem_type > & | out, | |
const Glue< Op< T1, op_diagmat >, Op< T2, op_diagmat >, glue_times_diag > & | X | |||
) | [inline, static, inherited] |
Definition at line 901 of file glue_times_meat.hpp.
References glue_times_diag::apply().
00902 { 00903 glue_times_diag::apply(out, X.A, X.B); 00904 }
void glue_times_vec::apply | ( | Mat< typename T1::elem_type > & | out, | |
const Glue< T1, T2, glue_times_vec > & | X | |||
) | [inline, static, inherited] |
at least one of T1 and T2 is a vector (both could be vectors)
Definition at line 916 of file glue_times_meat.hpp.
References Glue< T1, T2, glue_type >::A, Glue< T1, T2, glue_type >::B, op_dot::direct_dot(), Mat< eT >::mem, Mat< eT >::memptr(), glue_times_vec::mul_col_row(), Mat< eT >::n_cols, Mat< eT >::n_elem, Mat< eT >::n_rows, and Mat< eT >::set_size().
Referenced by glue_times_vec::apply().
00917 { 00918 arma_extra_debug_sigprint(); 00919 00920 typedef typename T1::elem_type eT; 00921 00922 unwrap_check<T1> tmp1(X.A, out); 00923 unwrap_check<T2> tmp2(X.B, out); 00924 00925 const Mat<eT>& A = tmp1.M; 00926 const Mat<eT>& B = tmp2.M; 00927 00928 arma_debug_assert_mul_size(A, B, "vector multiply"); 00929 00930 // col * row --> outer product 00931 // mat * row --> only makes sense if mat is a col vector, hence equiv to col * row 00932 // col * mat --> only makes sense if mat is a row vector, hence equiv to col * row 00933 00934 // row * col --> dot product 00935 // row * mat --> ok 00936 00937 // mat * col --> ok 00938 00939 out.set_size(A.n_rows, B.n_cols); 00940 00941 if(A.n_cols == 1) // A is a column vector 00942 { 00943 glue_times_vec::mul_col_row(out, A.mem, B.mem); 00944 } 00945 else 00946 { 00947 if(A.n_rows == 1) // A is a row vector 00948 { 00949 if(B.n_cols == 1) 00950 { 00951 out[0] = op_dot::direct_dot(A.n_elem, A.mem, B.mem); 00952 } 00953 else 00954 { 00955 gemv<true>::apply(out.memptr(), B, A.mem); 00956 } 00957 } 00958 else // A is a matrix 00959 { 00960 gemv<>::apply(out.memptr(), A, B.mem); 00961 } 00962 } 00963 00964 }
void glue_times_vec::mul_col_row | ( | Mat< eT > & | out, | |
const eT * | A_mem, | |||
const eT * | B_mem | |||
) | [inline, static, inherited] |
Definition at line 971 of file glue_times_meat.hpp.
References Mat< eT >::colptr(), Mat< eT >::n_cols, and Mat< eT >::n_rows.
Referenced by glue_times_vec::apply().
00972 { 00973 const u32 n_rows = out.n_rows; 00974 const u32 n_cols = out.n_cols; 00975 00976 for(u32 col=0; col < n_cols; ++col) 00977 { 00978 const eT val = B[col]; 00979 00980 eT* out_coldata = out.colptr(col); 00981 00982 for(u32 row=0; row < n_rows; ++row) 00983 { 00984 out_coldata[row] = A[row] * val; 00985 } 00986 } 00987 00988 }
void glue_times_vec::mul_col_row_inplace_add | ( | Mat< eT > & | out, | |
const eT * | A_mem, | |||
const eT * | B_mem | |||
) | [inline, static, inherited] |
Definition at line 995 of file glue_times_meat.hpp.
References Mat< eT >::colptr(), Mat< eT >::n_cols, and Mat< eT >::n_rows.
Referenced by glue_plus::apply_inplace().
00996 { 00997 const u32 n_rows = out.n_rows; 00998 const u32 n_cols = out.n_cols; 00999 01000 for(u32 col=0; col < n_cols; ++col) 01001 { 01002 const eT val = B[col]; 01003 01004 eT* out_coldata = out.colptr(col); 01005 01006 for(u32 row=0; row < n_rows; ++row) 01007 { 01008 out_coldata[row] += A[row] * val; 01009 } 01010 } 01011 01012 }
void glue_times_vec::apply | ( | Mat< eT > & | out, | |
const Glue< Col< eT >, Row< eT >, glue_times_vec > & | X | |||
) | [inline, static, inherited] |
Definition at line 1023 of file glue_times_meat.hpp.
References Mat< eT >::mem, glue_times_vec::mul_col_row(), Mat< eT >::n_cols, Mat< eT >::n_rows, and Mat< eT >::set_size().
01024 { 01025 arma_extra_debug_sigprint(); 01026 01027 unwrap_check< Col<eT> > tmp1(X.A, out); 01028 unwrap_check< Row<eT> > tmp2(X.B, out); 01029 01030 const Col<eT>& A = tmp1.M; 01031 const Row<eT>& B = tmp2.M; 01032 01033 arma_debug_assert_mul_size(A, B, "vector multiply"); 01034 01035 out.set_size(A.n_rows, B.n_cols); 01036 01037 glue_times_vec::mul_col_row(out, A.mem, B.mem); 01038 }
void glue_times_vec::apply | ( | Mat< eT > & | out, | |
const Glue< Op< Row< eT >, op_trans >, Row< eT >, glue_times_vec > & | X | |||
) | [inline, static, inherited] |
Definition at line 1045 of file glue_times_meat.hpp.
References Mat< eT >::mem, glue_times_vec::mul_col_row(), Mat< eT >::n_cols, Mat< eT >::n_rows, and Mat< eT >::set_size().
01046 { 01047 arma_extra_debug_sigprint(); 01048 01049 unwrap_check< Row<eT> > tmp1(X.A.m, out); 01050 unwrap_check< Row<eT> > tmp2(X.B, out); 01051 01052 const Row<eT>& A = tmp1.M; 01053 const Row<eT>& B = tmp2.M; 01054 01055 arma_debug_assert_mul_size(A.n_cols, A.n_rows, B.n_rows, B.n_cols, "vector multiply"); 01056 01057 out.set_size(A.n_cols, B.n_cols); 01058 01059 glue_times_vec::mul_col_row(out, A.mem, B.mem); 01060 }
void glue_times_vec::apply | ( | Mat< eT > & | out, | |
const Glue< Col< eT >, Op< Col< eT >, op_trans >, glue_times_vec > & | X | |||
) | [inline, static, inherited] |
Definition at line 1067 of file glue_times_meat.hpp.
References Mat< eT >::mem, glue_times_vec::mul_col_row(), Mat< eT >::n_cols, Mat< eT >::n_rows, and Mat< eT >::set_size().
01068 { 01069 arma_extra_debug_sigprint(); 01070 01071 unwrap_check< Col<eT> > tmp1(X.A, out); 01072 unwrap_check< Col<eT> > tmp2(X.B.m, out); 01073 01074 const Col<eT>& A = tmp1.M; 01075 const Col<eT>& B = tmp2.M; 01076 01077 arma_debug_assert_mul_size(A.n_rows, A.n_cols, B.n_cols, B.n_rows, "vector multiply"); 01078 01079 out.set_size(A.n_rows, B.n_rows); 01080 01081 glue_times_vec::mul_col_row(out, A.mem, B.mem); 01082 }
void glue_times_vec::apply | ( | Mat< typename T1::elem_type > & | out, | |
const Glue< Op< T1, op_trans >, Col< typename T1::elem_type >, glue_times_vec > & | X | |||
) | [inline, static, inherited] |
Definition at line 1089 of file glue_times_meat.hpp.
References glue_times_vec::apply(), Mat< eT >::mem, Mat< eT >::memptr(), Mat< eT >::n_cols, Mat< eT >::n_rows, and Mat< eT >::set_size().
01090 { 01091 arma_extra_debug_sigprint(); 01092 01093 typedef typename T1::elem_type eT; 01094 01095 unwrap_check< T1 > tmp1(X.A.m, out); 01096 unwrap_check< Col<eT> > tmp2(X.B, out); 01097 01098 const Mat<eT>& A = tmp1.M; 01099 const Col<eT>& B = tmp2.M; 01100 01101 arma_debug_assert_mul_size(A.n_cols, A.n_rows, B.n_rows, B.n_cols, "vector multiply"); 01102 01103 out.set_size(A.n_cols, B.n_cols); 01104 01105 // eT* out_mem = out.memptr(); 01106 // const eT* B_mem = B.mem; 01107 // 01108 // const u32 A_n_cols = A.n_cols; 01109 // const u32 B_n_rows = B.n_rows; 01110 // 01111 // for(u32 col=0; col < A_n_cols; ++col) 01112 // { 01113 // const eT* A_col = A.colptr(col); 01114 // 01115 // eT val = eT(0); 01116 // for(u32 row=0; row<B_n_rows; ++row) 01117 // { 01118 // val += A_col[row] * B_mem[row]; 01119 // } 01120 // 01121 // out_mem[col] = val; 01122 // } 01123 01124 gemv<true>::apply(out.memptr(), A, B.mem); 01125 }