1 // Copyright (C) 2008 Davis E. King (davis@dlib.net) 2 // License: Boost Software License See LICENSE.txt for the full license. 3 #ifndef DLIB_MATRIx_ASSIGn_FWD_ 4 #define DLIB_MATRIx_ASSIGn_FWD_ 5 6 // GCC 4.8 gives false alarms about some variables being uninitialized. Disable these 7 // false warnings. 8 #if defined(__GNUC__) && ((__GNUC__ >= 4 && __GNUC_MINOR__ >= 8) || (__GNUC__ > 4)) 9 #pragma GCC diagnostic push 10 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 11 #endif 12 13 #include "../enable_if.h" 14 #include "matrix_data_layout.h" 15 #include "../algs.h" 16 17 namespace dlib 18 { 19 20 /* 21 The point of the matrix_assign() functions is to contain all the various 22 optimizations that help the matrix assign a matrix_exp to an actual matrix 23 object quickly. 24 */ 25 26 // ---------------------------------------------------------------------------------------- 27 28 namespace ma 29 { 30 // This template here controls how big a compile time sized matrix needs 31 // to be for it to get passed into the optimized versions of the 32 // matrix_assign() function. So small matrices are evaluated with a simple 33 // loop like the ones in this file and bigger matrices may get sent to BLAS 34 // routines or some other kind of optimized thing. 35 template < typename EXP, typename enable = void > 36 struct is_small_matrix { static const bool value = false; }; 37 template < typename EXP > 38 struct is_small_matrix<EXP, typename enable_if_c<EXP::NR>=1 && EXP::NC>=1 && 39 EXP::NR<=17 && EXP::NC<=17 && (EXP::cost <= 70)>::type> { static const bool value = true; }; 40 41 // I wouldn't use this mul object to do the multiply but visual studio 7.1 wouldn't 42 // compile otherwise. 43 template <long a, long b> 44 struct mul { const static long value = a*b; }; 45 46 template < typename EXP, typename enable = void > 47 struct is_very_small_matrix { static const bool value = false; }; 48 template < typename EXP > 49 struct is_very_small_matrix<EXP, typename enable_if_c<EXP::NR>=1 && EXP::NC>=1 && 50 (mul<EXP::NR,EXP::NC>::value <= 16) && (EXP::cost <= 70)>::type> { static const bool value = true; }; 51 52 53 template < typename EXP, typename enable = void > 54 struct has_column_major_layout { static const bool value = false; }; 55 template < typename EXP > 56 struct has_column_major_layout<EXP, typename enable_if<is_same_type<typename EXP::layout_type, column_major_layout> >::type > 57 { static const bool value = true; }; 58 59 60 61 } 62 63 // ---------------------------------------------------------------------------------------- 64 65 template < 66 typename EXP 67 > 68 class matrix_exp; 69 70 // ---------------------------------------------------------------------------------------- 71 72 template <typename EXP1, typename EXP2> 73 inline typename disable_if<ma::has_column_major_layout<EXP1> >::type 74 matrix_assign_default ( 75 EXP1& dest, 76 const EXP2& src 77 ) 78 /*! 79 requires 80 - src.destructively_aliases(dest) == false 81 - dest.nr() == src.nr() 82 - dest.nc() == src.nc() 83 ensures 84 - #dest == src 85 !*/ 86 { 87 for (long r = 0; r < src.nr(); ++r) 88 { 89 for (long c = 0; c < src.nc(); ++c) 90 { 91 dest(r,c) = src(r,c); 92 } 93 } 94 } 95 96 // ---------------------------------------------------------------------------------------- 97 98 template <typename EXP1, typename EXP2> 99 inline typename enable_if<ma::has_column_major_layout<EXP1> >::type 100 matrix_assign_default ( 101 EXP1& dest, 102 const EXP2& src 103 ) 104 /*! 105 requires 106 - src.destructively_aliases(dest) == false 107 - dest.nr() == src.nr() 108 - dest.nc() == src.nc() 109 ensures 110 - #dest == src 111 !*/ 112 { 113 for (long c = 0; c < src.nc(); ++c) 114 { 115 for (long r = 0; r < src.nr(); ++r) 116 { 117 dest(r,c) = src(r,c); 118 } 119 } 120 } 121 122 // ---------------------------------------------------------------------------------------- 123 124 template <typename EXP1, typename EXP2> 125 inline typename disable_if<ma::has_column_major_layout<EXP1> >::type 126 matrix_assign_default ( 127 EXP1& dest, 128 const EXP2& src, 129 typename EXP2::type alpha, 130 bool add_to 131 ) 132 /*! 133 requires 134 - src.destructively_aliases(dest) == false 135 - dest.nr() == src.nr() 136 - dest.nc() == src.nc() 137 ensures 138 - if (add_to == false) then 139 - #dest == alpha*src 140 - else 141 - #dest == dest + alpha*src 142 !*/ 143 { 144 if (add_to) 145 { 146 if (alpha == static_cast<typename EXP2::type>(1)) 147 { 148 for (long r = 0; r < src.nr(); ++r) 149 { 150 for (long c = 0; c < src.nc(); ++c) 151 { 152 dest(r,c) += src(r,c); 153 } 154 } 155 } 156 else if (alpha == static_cast<typename EXP2::type>(-1)) 157 { 158 for (long r = 0; r < src.nr(); ++r) 159 { 160 for (long c = 0; c < src.nc(); ++c) 161 { 162 dest(r,c) -= src(r,c); 163 } 164 } 165 } 166 else 167 { 168 for (long r = 0; r < src.nr(); ++r) 169 { 170 for (long c = 0; c < src.nc(); ++c) 171 { 172 dest(r,c) += alpha*src(r,c); 173 } 174 } 175 } 176 } 177 else 178 { 179 if (alpha == static_cast<typename EXP2::type>(1)) 180 { 181 for (long r = 0; r < src.nr(); ++r) 182 { 183 for (long c = 0; c < src.nc(); ++c) 184 { 185 dest(r,c) = src(r,c); 186 } 187 } 188 } 189 else 190 { 191 for (long r = 0; r < src.nr(); ++r) 192 { 193 for (long c = 0; c < src.nc(); ++c) 194 { 195 dest(r,c) = alpha*src(r,c); 196 } 197 } 198 } 199 } 200 } 201 202 // ---------------------------------------------------------------------------------------- 203 204 template <typename EXP1, typename EXP2> 205 inline typename enable_if<ma::has_column_major_layout<EXP1> >::type 206 matrix_assign_default ( 207 EXP1& dest, 208 const EXP2& src, 209 typename EXP2::type alpha, 210 bool add_to 211 ) 212 /*! 213 requires 214 - src.destructively_aliases(dest) == false 215 - dest.nr() == src.nr() 216 - dest.nc() == src.nc() 217 ensures 218 - if (add_to == false) then 219 - #dest == alpha*src 220 - else 221 - #dest == dest + alpha*src 222 !*/ 223 { 224 if (add_to) 225 { 226 if (alpha == static_cast<typename EXP2::type>(1)) 227 { 228 for (long c = 0; c < src.nc(); ++c) 229 { 230 for (long r = 0; r < src.nr(); ++r) 231 { 232 dest(r,c) += src(r,c); 233 } 234 } 235 } 236 else if (alpha == static_cast<typename EXP2::type>(-1)) 237 { 238 for (long c = 0; c < src.nc(); ++c) 239 { 240 for (long r = 0; r < src.nr(); ++r) 241 { 242 dest(r,c) -= src(r,c); 243 } 244 } 245 } 246 else 247 { 248 for (long c = 0; c < src.nc(); ++c) 249 { 250 for (long r = 0; r < src.nr(); ++r) 251 { 252 dest(r,c) += alpha*src(r,c); 253 } 254 } 255 } 256 } 257 else 258 { 259 if (alpha == static_cast<typename EXP2::type>(1)) 260 { 261 for (long c = 0; c < src.nc(); ++c) 262 { 263 for (long r = 0; r < src.nr(); ++r) 264 { 265 dest(r,c) = src(r,c); 266 } 267 } 268 } 269 else 270 { 271 for (long c = 0; c < src.nc(); ++c) 272 { 273 for (long r = 0; r < src.nr(); ++r) 274 { 275 dest(r,c) = alpha*src(r,c); 276 } 277 } 278 } 279 } 280 } 281 282 // ---------------------------------------------------------------------------------------- 283 284 template < 285 typename matrix_dest_type, 286 typename src_exp 287 > 288 void matrix_assign_big ( 289 matrix_dest_type& dest, 290 const matrix_exp<src_exp>& src 291 ) 292 { 293 matrix_assign_default(dest,src); 294 } 295 296 // ---------------------------------------------------------------------------------------- 297 298 template < 299 typename matrix_dest_type, 300 typename src_exp 301 > 302 inline typename disable_if<ma::is_small_matrix<src_exp> >::type matrix_assign ( 303 matrix_dest_type& dest, 304 const matrix_exp<src_exp>& src 305 ) 306 /*! 307 requires 308 - src.destructively_aliases(dest) == false 309 - dest.nr() == src.nr() 310 - dest.nc() == src.nc() 311 ensures 312 - #dest == src 313 !*/ 314 { 315 // Call src.ref() here so that the derived type of the matrix_exp shows 316 // up so we can overload matrix_assign_big() based on various matrix expression 317 // types. 318 matrix_assign_big(dest,src.ref()); 319 } 320 321 // ---------------------------------------------------------------------------------------- 322 // ---------------------------------------------------------------------------------------- 323 324 // this code is here to perform an unrolled version of the matrix_assign() function 325 template < typename DEST, typename SRC, long NR, long NC, 326 long R = 0, long C = 0, bool base_case = (R==NR) > 327 struct matrix_unroll_helper 328 { 329 inline static void go ( DEST& dest, const SRC& src) 330 { 331 dest(R,C) = src(R,C); 332 matrix_unroll_helper<DEST,SRC,NR,NC, R + (C+1)/NC, (C+1)%NC>::go(dest,src); 333 } 334 }; 335 336 template < typename DEST, typename SRC, long NR, long NC, long R, long C > 337 struct matrix_unroll_helper<DEST,SRC,NR,NC,R,C,true> 338 { inline static void go ( DEST& , const SRC& ) {} }; 339 340 template <typename DEST, typename SRC> 341 inline void matrix_assign_unrolled ( 342 DEST& dest, 343 const SRC& src 344 ) 345 /*! 346 requires 347 - src.destructively_aliases(dest) == false 348 - dest.nr() == src.nr() 349 - dest.nc() == src.nc() 350 ensures 351 - #dest == src 352 !*/ 353 { 354 COMPILE_TIME_ASSERT(SRC::NR*SRC::NC != 0); 355 matrix_unroll_helper<DEST,SRC, SRC::NR, SRC::NC>::go(dest,src); 356 } 357 358 // ---------------------------------------------------------------------------------------- 359 // ---------------------------------------------------------------------------------------- 360 361 template < 362 typename matrix_dest_type, 363 typename src_exp 364 > 365 inline typename enable_if_c<ma::is_small_matrix<src_exp>::value && ma::is_very_small_matrix<src_exp>::value==false >::type matrix_assign ( 366 matrix_dest_type& dest, 367 const matrix_exp<src_exp>& src 368 ) 369 /*! 370 requires 371 - src.destructively_aliases(dest) == false 372 - dest.nr() == src.nr() 373 - dest.nc() == src.nc() 374 ensures 375 - #dest == src 376 !*/ 377 { 378 matrix_assign_default(dest,src.ref()); 379 } 380 381 // ---------------------------------------------------------------------------------------- 382 383 template < 384 typename matrix_dest_type, 385 typename src_exp 386 > 387 inline typename enable_if_c<ma::is_small_matrix<src_exp>::value && ma::is_very_small_matrix<src_exp>::value==true >::type matrix_assign ( 388 matrix_dest_type& dest, 389 const matrix_exp<src_exp>& src 390 ) 391 /*! 392 requires 393 - src.destructively_aliases(dest) == false 394 - dest.nr() == src.nr() 395 - dest.nc() == src.nc() 396 ensures 397 - #dest == src 398 !*/ 399 { 400 matrix_assign_unrolled(dest,src.ref()); 401 } 402 403 // ---------------------------------------------------------------------------------------- 404 405 } 406 407 #if defined(__GNUC__) && ((__GNUC__ >= 4 && __GNUC_MINOR__ >= 8) || (__GNUC__ > 4)) 408 #pragma GCC diagnostic pop 409 #endif 410 411 #endif // DLIB_MATRIx_ASSIGn_FWD_ 412 413 414