1 // Copyright (C) 2006 Davis E. King (davis@dlib.net) 2 // License: Boost Software License See LICENSE.txt for the full license. 3 #ifndef DLIB_MATRIx_SUBEXP_ 4 #define DLIB_MATRIx_SUBEXP_ 5 6 #include "matrix_subexp_abstract.h" 7 #include "matrix_op.h" 8 #include "matrix.h" 9 #include "../geometry/rectangle.h" 10 #include "matrix_expressions.h" 11 #include "matrix_mat.h" 12 13 14 15 namespace dlib 16 { 17 18 // ---------------------------------------------------------------------------------------- 19 // ---------------------------------------------------------------------------------------- 20 // ---------------------------------------------------------------------------------------- 21 22 template <long start, long inc, long end> range()23 const matrix_range_static_exp<start,inc,end> range ( 24 ) 25 { 26 COMPILE_TIME_ASSERT(inc > 0); 27 return matrix_range_static_exp<start,inc,end>(); 28 } 29 30 template <long start, long end> range()31 const matrix_range_static_exp<start,1,end> range ( 32 ) 33 { 34 return matrix_range_static_exp<start,1,end>(); 35 } 36 range(long start,long end)37 inline const matrix_range_exp<long> range ( 38 long start, 39 long end 40 ) 41 { 42 return matrix_range_exp<long>(start,end); 43 } 44 range(long start,long inc,long end)45 inline const matrix_range_exp<long> range ( 46 long start, 47 long inc, 48 long end 49 ) 50 { 51 DLIB_ASSERT(inc > 0, 52 "\tconst matrix_exp range(start, inc, end)" 53 << "\n\tInvalid inputs to this function" 54 << "\n\tstart: " << start 55 << "\n\tinc: " << inc 56 << "\n\tend: " << end 57 ); 58 59 return matrix_range_exp<long>(start,inc,end); 60 } 61 62 // ---------------------------------------------------------------------------------------- 63 64 template <typename M> 65 struct op_subm 66 { op_submop_subm67 op_subm ( 68 const M& m_x, 69 const long& r_x, 70 const long& c_x, 71 const long& nr_x, 72 const long& nc_x 73 ) : m(m_x), r_(r_x), c_(c_x), nr_(nr_x), nc_(nc_x) { } 74 75 const M& m; 76 const long r_; 77 const long c_; 78 const long nr_; 79 const long nc_; 80 81 const static long cost = M::cost+1; 82 typedef typename M::type type; 83 typedef typename M::const_ret_type const_ret_type; 84 typedef typename M::mem_manager_type mem_manager_type; 85 typedef typename M::layout_type layout_type; 86 const static long NR = 0; 87 const static long NC = 0; 88 applyop_subm89 const_ret_type apply ( long r, long c) const { return m(r+r_,c+c_); } 90 nrop_subm91 long nr () const { return nr_; } ncop_subm92 long nc () const { return nc_; } 93 aliasesop_subm94 template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } destructively_aliasesop_subm95 template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } 96 }; 97 98 template < 99 typename EXP 100 > subm(const matrix_exp<EXP> & m,long r,long c,long nr,long nc)101 const matrix_op<op_subm<EXP> > subm ( 102 const matrix_exp<EXP>& m, 103 long r, 104 long c, 105 long nr, 106 long nc 107 ) 108 { 109 DLIB_ASSERT(r >= 0 && c >= 0 && nr >= 0 && nc >= 0 && r+nr <= m.nr() && c+nc <= m.nc(), 110 "\tconst matrix_exp subm(const matrix_exp& m, r, c, nr, nc)" 111 << "\n\tYou have specified invalid sub matrix dimensions" 112 << "\n\tm.nr(): " << m.nr() 113 << "\n\tm.nc(): " << m.nc() 114 << "\n\tr: " << r 115 << "\n\tc: " << c 116 << "\n\tnr: " << nr 117 << "\n\tnc: " << nc 118 ); 119 120 typedef op_subm<EXP> op; 121 return matrix_op<op>(op(m.ref(),r,c,nr,nc)); 122 } 123 124 // ---------------------------------------------------------------------------------------- 125 126 template < 127 typename EXP 128 > subm_clipped(const matrix_exp<EXP> & m,long r,long c,long nr,long nc)129 const matrix_op<op_subm<EXP> > subm_clipped ( 130 const matrix_exp<EXP>& m, 131 long r, 132 long c, 133 long nr, 134 long nc 135 ) 136 { 137 rectangle box(c,r,c+nc-1,r+nr-1); 138 box = box.intersect(get_rect(m)); 139 typedef op_subm<EXP> op; 140 return matrix_op<op>(op(m.ref(),box.top(),box.left(),box.height(),box.width())); 141 } 142 143 // ---------------------------------------------------------------------------------------- 144 145 template < 146 typename EXP 147 > subm(const matrix_exp<EXP> & m,const rectangle & rect)148 const matrix_op<op_subm<EXP> > subm ( 149 const matrix_exp<EXP>& m, 150 const rectangle& rect 151 ) 152 { 153 DLIB_ASSERT(get_rect(m).contains(rect) == true, 154 "\tconst matrix_exp subm(const matrix_exp& m, const rectangle& rect)" 155 << "\n\tYou have specified invalid sub matrix dimensions" 156 << "\n\tm.nr(): " << m.nr() 157 << "\n\tm.nc(): " << m.nc() 158 << "\n\trect.left(): " << rect.left() 159 << "\n\trect.top(): " << rect.top() 160 << "\n\trect.right(): " << rect.right() 161 << "\n\trect.bottom(): " << rect.bottom() 162 ); 163 164 typedef op_subm<EXP> op; 165 return matrix_op<op>(op(m.ref(),rect.top(),rect.left(),rect.height(),rect.width())); 166 } 167 168 // ---------------------------------------------------------------------------------------- 169 170 template < 171 typename EXP 172 > subm_clipped(const matrix_exp<EXP> & m,rectangle rect)173 const matrix_op<op_subm<EXP> > subm_clipped ( 174 const matrix_exp<EXP>& m, 175 rectangle rect 176 ) 177 { 178 rect = rect.intersect(get_rect(m)); 179 180 typedef op_subm<EXP> op; 181 return matrix_op<op>(op(m.ref(),rect.top(),rect.left(),rect.height(),rect.width())); 182 } 183 184 // ---------------------------------------------------------------------------------------- 185 186 template <typename M1, typename M2, typename M3> 187 struct op_subm_range 188 { op_subm_rangeop_subm_range189 op_subm_range( const M1& m1_, const M2& rows_, const M3& cols_) : 190 m1(m1_), rows(rows_), cols(cols_) {} 191 const M1& m1; 192 const M2& rows; 193 const M3& cols; 194 195 const static long cost = M1::cost+M2::cost+M3::cost; 196 typedef typename M1::type type; 197 typedef typename M1::const_ret_type const_ret_type; 198 typedef typename M1::mem_manager_type mem_manager_type; 199 typedef typename M1::layout_type layout_type; 200 const static long NR = M2::NC*M2::NR; 201 const static long NC = M3::NC*M3::NR; 202 applyop_subm_range203 const_ret_type apply ( long r, long c) const { return m1(rows(r),cols(c)); } 204 nrop_subm_range205 long nr () const { return rows.size(); } ncop_subm_range206 long nc () const { return cols.size(); } 207 aliasesop_subm_range208 template <typename U> bool aliases ( const matrix_exp<U>& item) const 209 { return m1.aliases(item) || rows.aliases(item) || cols.aliases(item); } destructively_aliasesop_subm_range210 template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const 211 { return m1.aliases(item) || rows.aliases(item) || cols.aliases(item); } 212 }; 213 214 template < 215 typename EXP, 216 typename EXPr, 217 typename EXPc 218 > subm(const matrix_exp<EXP> & m,const matrix_exp<EXPr> & rows,const matrix_exp<EXPc> & cols)219 const matrix_op<op_subm_range<EXP,EXPr,EXPc> > subm ( 220 const matrix_exp<EXP>& m, 221 const matrix_exp<EXPr>& rows, 222 const matrix_exp<EXPc>& cols 223 ) 224 { 225 // the rows and cols matrices must contain integer elements 226 COMPILE_TIME_ASSERT(std::numeric_limits<typename EXPr::type>::is_integer); 227 COMPILE_TIME_ASSERT(std::numeric_limits<typename EXPc::type>::is_integer); 228 229 DLIB_ASSERT(0 <= min(rows) && max(rows) < m.nr() && 0 <= min(cols) && max(cols) < m.nc() && 230 (rows.nr() == 1 || rows.nc() == 1) && (cols.nr() == 1 || cols.nc() == 1), 231 "\tconst matrix_exp subm(const matrix_exp& m, const matrix_exp& rows, const matrix_exp& cols)" 232 << "\n\tYou have given invalid arguments to this function" 233 << "\n\tm.nr(): " << m.nr() 234 << "\n\tm.nc(): " << m.nc() 235 << "\n\tmin(rows): " << min(rows) 236 << "\n\tmax(rows): " << max(rows) 237 << "\n\tmin(cols): " << min(cols) 238 << "\n\tmax(cols): " << max(cols) 239 << "\n\trows.nr(): " << rows.nr() 240 << "\n\trows.nc(): " << rows.nc() 241 << "\n\tcols.nr(): " << cols.nr() 242 << "\n\tcols.nc(): " << cols.nc() 243 ); 244 245 typedef op_subm_range<EXP,EXPr,EXPc> op; 246 return matrix_op<op>(op(m.ref(),rows.ref(),cols.ref())); 247 } 248 249 // ---------------------------------------------------------------------------------------- 250 251 template <typename M> 252 struct op_rowm 253 { op_rowmop_rowm254 op_rowm(const M& m_, const long& row_) : m(m_), row(row_) {} 255 const M& m; 256 const long row; 257 258 const static long cost = M::cost; 259 const static long NR = 1; 260 const static long NC = M::NC; 261 typedef typename M::type type; 262 typedef typename M::const_ret_type const_ret_type; 263 typedef typename M::mem_manager_type mem_manager_type; 264 typedef typename M::layout_type layout_type; applyop_rowm265 const_ret_type apply ( long, long c) const { return m(row,c); } 266 nrop_rowm267 long nr () const { return 1; } ncop_rowm268 long nc () const { return m.nc(); } 269 aliasesop_rowm270 template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } destructively_aliasesop_rowm271 template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } 272 }; 273 274 template < 275 typename EXP 276 > rowm(const matrix_exp<EXP> & m,long row)277 const matrix_op<op_rowm<EXP> > rowm ( 278 const matrix_exp<EXP>& m, 279 long row 280 ) 281 { 282 DLIB_ASSERT(row >= 0 && row < m.nr(), 283 "\tconst matrix_exp rowm(const matrix_exp& m, row)" 284 << "\n\tYou have specified invalid sub matrix dimensions" 285 << "\n\tm.nr(): " << m.nr() 286 << "\n\tm.nc(): " << m.nc() 287 << "\n\trow: " << row 288 ); 289 290 typedef op_rowm<EXP> op; 291 return matrix_op<op>(op(m.ref(),row)); 292 } 293 294 template <typename EXP> 295 struct rowm_exp 296 { 297 typedef matrix_op<op_rowm<EXP> > type; 298 }; 299 300 // ---------------------------------------------------------------------------------------- 301 302 template <typename M> 303 struct op_rowm2 304 { op_rowm2op_rowm2305 op_rowm2(const M& m_, const long& row_, const long& len) : m(m_), row(row_), length(len) {} 306 const M& m; 307 const long row; 308 const long length; 309 310 const static long cost = M::cost; 311 const static long NR = 1; 312 const static long NC = 0; 313 typedef typename M::type type; 314 typedef typename M::const_ret_type const_ret_type; 315 typedef typename M::mem_manager_type mem_manager_type; 316 typedef typename M::layout_type layout_type; applyop_rowm2317 const_ret_type apply ( long , long c) const { return m(row,c); } 318 nrop_rowm2319 long nr () const { return 1; } ncop_rowm2320 long nc () const { return length; } 321 aliasesop_rowm2322 template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } destructively_aliasesop_rowm2323 template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } 324 }; 325 326 template < 327 typename EXP 328 > rowm(const matrix_exp<EXP> & m,long row,long length)329 const matrix_op<op_rowm2<EXP> > rowm ( 330 const matrix_exp<EXP>& m, 331 long row, 332 long length 333 ) 334 { 335 DLIB_ASSERT(row >= 0 && row < m.nr() && 336 length >= 0 && length <= m.nc(), 337 "\tconst matrix_exp rowm(const matrix_exp& m, row, length)" 338 << "\n\tYou have specified invalid sub matrix dimensions" 339 << "\n\tm.nr(): " << m.nr() 340 << "\n\tm.nc(): " << m.nc() 341 << "\n\trow: " << row 342 << "\n\tlength: " << length 343 ); 344 345 typedef op_rowm2<EXP> op; 346 return matrix_op<op>(op(m.ref(), row, length)); 347 } 348 349 // ---------------------------------------------------------------------------------------- 350 351 template <typename M1, typename M2> 352 struct op_rowm_range 353 { op_rowm_rangeop_rowm_range354 op_rowm_range( const M1& m1_, const M2& rows_) : m1(m1_), rows(rows_) {} 355 const M1& m1; 356 const M2& rows; 357 358 const static long cost = M1::cost+M2::cost; 359 typedef typename M1::type type; 360 typedef typename M1::const_ret_type const_ret_type; 361 typedef typename M1::mem_manager_type mem_manager_type; 362 typedef typename M1::layout_type layout_type; 363 const static long NR = M2::NC*M2::NR; 364 const static long NC = M1::NC; 365 applyop_rowm_range366 const_ret_type apply ( long r, long c) const { return m1(rows(r),c); } 367 nrop_rowm_range368 long nr () const { return rows.size(); } ncop_rowm_range369 long nc () const { return m1.nc(); } 370 aliasesop_rowm_range371 template <typename U> bool aliases ( const matrix_exp<U>& item) const 372 { return m1.aliases(item) || rows.aliases(item); } destructively_aliasesop_rowm_range373 template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const 374 { return m1.aliases(item) || rows.aliases(item); } 375 }; 376 377 template < 378 typename EXP1, 379 typename EXP2 380 > rowm(const matrix_exp<EXP1> & m,const matrix_exp<EXP2> & rows)381 const matrix_op<op_rowm_range<EXP1,EXP2> > rowm ( 382 const matrix_exp<EXP1>& m, 383 const matrix_exp<EXP2>& rows 384 ) 385 { 386 // the rows matrix must contain integer elements 387 COMPILE_TIME_ASSERT(std::numeric_limits<typename EXP2::type>::is_integer); 388 389 #ifdef ENABLE_ASSERTS 390 if (rows.size() != 0) { 391 DLIB_ASSERT(0 <= min(rows) && max(rows) < m.nr() && (rows.nr() == 1 || rows.nc() == 1), 392 "\tconst matrix_exp rowm(const matrix_exp& m, const matrix_exp& rows)" 393 << "\n\tYou have given invalid arguments to this function" 394 << "\n\tm.nr(): " << m.nr() 395 << "\n\tm.nc(): " << m.nc() 396 << "\n\tmin(rows): " << min(rows) 397 << "\n\tmax(rows): " << max(rows) 398 << "\n\trows.nr(): " << rows.nr() 399 << "\n\trows.nc(): " << rows.nc() 400 ); 401 } 402 #endif // ENABLE_ASSERTS 403 404 typedef op_rowm_range<EXP1,EXP2> op; 405 return matrix_op<op>(op(m.ref(),rows.ref())); 406 } 407 408 // ---------------------------------------------------------------------------------------- 409 410 template <typename M> 411 struct op_colm 412 { op_colmop_colm413 op_colm(const M& m_, const long& col_) : m(m_), col(col_) {} 414 const M& m; 415 const long col; 416 417 const static long cost = M::cost; 418 const static long NR = M::NR; 419 const static long NC = 1; 420 typedef typename M::type type; 421 typedef typename M::const_ret_type const_ret_type; 422 typedef typename M::mem_manager_type mem_manager_type; 423 typedef typename M::layout_type layout_type; applyop_colm424 const_ret_type apply ( long r, long) const { return m(r,col); } 425 nrop_colm426 long nr () const { return m.nr(); } ncop_colm427 long nc () const { return 1; } 428 aliasesop_colm429 template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } destructively_aliasesop_colm430 template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } 431 }; 432 433 template < 434 typename EXP 435 > colm(const matrix_exp<EXP> & m,long col)436 const matrix_op<op_colm<EXP> > colm ( 437 const matrix_exp<EXP>& m, 438 long col 439 ) 440 { 441 DLIB_ASSERT(col >= 0 && col < m.nc(), 442 "\tconst matrix_exp colm(const matrix_exp& m, row)" 443 << "\n\tYou have specified invalid sub matrix dimensions" 444 << "\n\tm.nr(): " << m.nr() 445 << "\n\tm.nc(): " << m.nc() 446 << "\n\tcol: " << col 447 ); 448 449 typedef op_colm<EXP> op; 450 return matrix_op<op>(op(m.ref(),col)); 451 } 452 453 template <typename EXP> 454 struct colm_exp 455 { 456 typedef matrix_op<op_colm<EXP> > type; 457 }; 458 459 // ---------------------------------------------------------------------------------------- 460 461 template <typename M> 462 struct op_colm2 463 { op_colm2op_colm2464 op_colm2(const M& m_, const long& col_, const long& len) : m(m_), col(col_), length(len) {} 465 const M& m; 466 const long col; 467 const long length; 468 469 const static long cost = M::cost; 470 const static long NR = 0; 471 const static long NC = 1; 472 typedef typename M::type type; 473 typedef typename M::const_ret_type const_ret_type; 474 typedef typename M::mem_manager_type mem_manager_type; 475 typedef typename M::layout_type layout_type; applyop_colm2476 const_ret_type apply ( long r, long ) const { return m(r,col); } 477 nrop_colm2478 long nr () const { return length; } ncop_colm2479 long nc () const { return 1; } 480 aliasesop_colm2481 template <typename U> bool aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } destructively_aliasesop_colm2482 template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const { return m.aliases(item); } 483 }; 484 485 template < 486 typename EXP 487 > colm(const matrix_exp<EXP> & m,long col,long length)488 const matrix_op<op_colm2<EXP> > colm ( 489 const matrix_exp<EXP>& m, 490 long col, 491 long length 492 ) 493 { 494 DLIB_ASSERT(col >= 0 && col < m.nc() && 495 length >= 0 && length <= m.nr(), 496 "\tconst matrix_exp colm(const matrix_exp& m, col, length)" 497 << "\n\tYou have specified invalid sub matrix dimensions" 498 << "\n\tm.nr(): " << m.nr() 499 << "\n\tm.nc(): " << m.nc() 500 << "\n\tcol: " << col 501 << "\n\tlength: " << length 502 ); 503 504 typedef op_colm2<EXP> op; 505 return matrix_op<op>(op(m.ref(),col, length)); 506 } 507 508 // ---------------------------------------------------------------------------------------- 509 510 template <typename M1, typename M2> 511 struct op_colm_range 512 { op_colm_rangeop_colm_range513 op_colm_range( const M1& m1_, const M2& cols_) : m1(m1_), cols(cols_) {} 514 const M1& m1; 515 const M2& cols; 516 517 typedef typename M1::type type; 518 typedef typename M1::const_ret_type const_ret_type; 519 typedef typename M1::mem_manager_type mem_manager_type; 520 typedef typename M1::layout_type layout_type; 521 const static long NR = M1::NR; 522 const static long NC = M2::NC*M2::NR; 523 const static long cost = M1::cost+M2::cost; 524 applyop_colm_range525 const_ret_type apply (long r, long c) const { return m1(r,cols(c)); } 526 nrop_colm_range527 long nr () const { return m1.nr(); } ncop_colm_range528 long nc () const { return cols.size(); } 529 aliasesop_colm_range530 template <typename U> bool aliases ( const matrix_exp<U>& item) const 531 { return m1.aliases(item) || cols.aliases(item); } destructively_aliasesop_colm_range532 template <typename U> bool destructively_aliases ( const matrix_exp<U>& item) const 533 { return m1.aliases(item) || cols.aliases(item); } 534 }; 535 536 template < 537 typename EXP1, 538 typename EXP2 539 > colm(const matrix_exp<EXP1> & m,const matrix_exp<EXP2> & cols)540 const matrix_op<op_colm_range<EXP1,EXP2> > colm ( 541 const matrix_exp<EXP1>& m, 542 const matrix_exp<EXP2>& cols 543 ) 544 { 545 // the rows matrix must contain integer elements 546 COMPILE_TIME_ASSERT(std::numeric_limits<typename EXP2::type>::is_integer); 547 548 #ifdef ENABLE_ASSERTS 549 if (cols.size() != 0) { 550 DLIB_ASSERT(0 <= min(cols) && max(cols) < m.nc() && (cols.nr() == 1 || cols.nc() == 1), 551 "\tconst matrix_exp colm(const matrix_exp& m, const matrix_exp& cols)" 552 << "\n\tYou have given invalid arguments to this function" 553 << "\n\tm.nr(): " << m.nr() 554 << "\n\tm.nc(): " << m.nc() 555 << "\n\tmin(cols): " << min(cols) 556 << "\n\tmax(cols): " << max(cols) 557 << "\n\tcols.nr(): " << cols.nr() 558 << "\n\tcols.nc(): " << cols.nc() 559 ); 560 } 561 #endif // ENABLE_ASSERTS 562 563 typedef op_colm_range<EXP1,EXP2> op; 564 return matrix_op<op>(op(m.ref(),cols.ref())); 565 } 566 567 // ---------------------------------------------------------------------------------------- 568 569 template <typename T> 570 class assignable_ptr_matrix 571 { 572 public: 573 typedef T type; 574 typedef row_major_layout layout_type; 575 typedef matrix<T,0,0,default_memory_manager,layout_type> matrix_type; 576 assignable_ptr_matrix(T * ptr_,long nr_,long nc_)577 assignable_ptr_matrix( 578 T* ptr_, 579 long nr_, 580 long nc_ 581 ) : ptr(ptr_), height(nr_), width(nc_){} 582 operator()583 T& operator() ( 584 long r, 585 long c 586 ) 587 { 588 return ptr[r*width + c]; 589 } 590 operator()591 const T& operator() ( 592 long r, 593 long c 594 ) const 595 { 596 return ptr[r*width + c]; 597 } 598 nr()599 long nr() const { return height; } nc()600 long nc() const { return width; } 601 602 template <typename EXP> 603 assignable_ptr_matrix& operator= ( 604 const matrix_exp<EXP>& exp 605 ) 606 { 607 // You can only assign to a set_ptrm() expression with a source matrix that 608 // contains the same type of elements as the target (i.e. you can't mix double 609 // and float types). 610 COMPILE_TIME_ASSERT((is_same_type<T, typename EXP::type>::value == true)); 611 612 DLIB_ASSERT( exp.nr() == height && exp.nc() == width, 613 "\tassignable_matrix_expression set_ptrm()" 614 << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" 615 << "\n\texp.nr() (source matrix): " << exp.nr() 616 << "\n\texp.nc() (source matrix): " << exp.nc() 617 << "\n\twidth (target matrix): " << width 618 << "\n\theight (target matrix): " << height 619 ); 620 621 if (exp.destructively_aliases(mat(ptr,height,width)) == false) 622 { 623 matrix_assign(*this, exp); 624 } 625 else 626 { 627 // make a temporary copy of the matrix we are going to assign to ptr to 628 // avoid aliasing issues during the copy 629 this->operator=(tmp(exp)); 630 } 631 632 return *this; 633 } 634 635 template <typename EXP> 636 assignable_ptr_matrix& operator+= ( 637 const matrix_exp<EXP>& exp 638 ) 639 { 640 // You can only assign to a set_ptrm() expression with a source matrix that 641 // contains the same type of elements as the target (i.e. you can't mix double 642 // and float types). 643 COMPILE_TIME_ASSERT((is_same_type<T, typename EXP::type>::value == true)); 644 645 DLIB_ASSERT( exp.nr() == height && exp.nc() == width, 646 "\tassignable_matrix_expression set_ptrm()" 647 << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" 648 << "\n\texp.nr() (source matrix): " << exp.nr() 649 << "\n\texp.nc() (source matrix): " << exp.nc() 650 << "\n\twidth (target matrix): " << width 651 << "\n\theight (target matrix): " << height 652 ); 653 654 if (exp.destructively_aliases(mat(ptr,height,width)) == false) 655 { 656 matrix_assign(*this, mat(ptr,height,width)+exp); 657 } 658 else 659 { 660 // make a temporary copy of the matrix we are going to assign to ptr to 661 // avoid aliasing issues during the copy 662 this->operator+=(tmp(exp)); 663 } 664 665 return *this; 666 } 667 668 template <typename EXP> 669 assignable_ptr_matrix& operator-= ( 670 const matrix_exp<EXP>& exp 671 ) 672 { 673 // You can only assign to a set_ptrm() expression with a source matrix that 674 // contains the same type of elements as the target (i.e. you can't mix double 675 // and float types). 676 COMPILE_TIME_ASSERT((is_same_type<T, typename EXP::type>::value == true)); 677 678 DLIB_ASSERT( exp.nr() == height && exp.nc() == width, 679 "\tassignable_matrix_expression set_ptrm()" 680 << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" 681 << "\n\texp.nr() (source matrix): " << exp.nr() 682 << "\n\texp.nc() (source matrix): " << exp.nc() 683 << "\n\twidth (target matrix): " << width 684 << "\n\theight (target matrix): " << height 685 ); 686 687 if (exp.destructively_aliases(mat(ptr,height,width)) == false) 688 { 689 matrix_assign(*this, mat(ptr,height,width)-exp); 690 } 691 else 692 { 693 // make a temporary copy of the matrix we are going to assign to ptr to 694 // avoid aliasing issues during the copy 695 this->operator-=(tmp(exp)); 696 } 697 698 return *this; 699 } 700 701 assignable_ptr_matrix& operator= ( 702 const T& value 703 ) 704 { 705 const long size = width*height; 706 for (long i = 0; i < size; ++i) 707 ptr[i] = value; 708 709 return *this; 710 } 711 712 assignable_ptr_matrix& operator+= ( 713 const T& value 714 ) 715 { 716 const long size = width*height; 717 for (long i = 0; i < size; ++i) 718 ptr[i] += value; 719 720 return *this; 721 } 722 723 assignable_ptr_matrix& operator-= ( 724 const T& value 725 ) 726 { 727 const long size = width*height; 728 for (long i = 0; i < size; ++i) 729 ptr[i] -= value; 730 731 return *this; 732 } 733 734 735 T* ptr; 736 const long height; 737 const long width; 738 }; 739 740 741 template <typename T> 742 assignable_ptr_matrix<T> set_ptrm ( 743 T* ptr, 744 long nr, 745 long nc = 1 746 ) 747 { 748 DLIB_ASSERT(nr >= 0 && nc >= 0, 749 "\t assignable_matrix_expression set_ptrm(T* ptr, long nr, long nc)" 750 << "\n\t The dimensions can't be negative." 751 << "\n\t nr: " << nr 752 << "\n\t nc: " << nc 753 ); 754 755 756 return assignable_ptr_matrix<T>(ptr,nr,nc); 757 } 758 759 // ---------------------------------------------------------------------------------------- 760 761 template <typename T, long NR, long NC, typename mm, typename l> 762 class assignable_sub_matrix 763 { 764 public: 765 typedef T type; 766 typedef l layout_type; 767 typedef matrix<T,NR,NC,mm,l> matrix_type; 768 assignable_sub_matrix(matrix<T,NR,NC,mm,l> & m_,long top_,long left_,long height_,long width_)769 assignable_sub_matrix( 770 matrix<T,NR,NC,mm,l>& m_, 771 long top_, 772 long left_, 773 long height_, 774 long width_ 775 ) : m(m_), left(left_), top(top_), width(width_), height(height_) {} 776 operator()777 T& operator() ( 778 long r, 779 long c 780 ) 781 { 782 return m(r+top,c+left); 783 } 784 operator()785 const T& operator() ( 786 long r, 787 long c 788 ) const 789 { 790 return m(r+top,c+left); 791 } 792 nr()793 long nr() const { return height; } nc()794 long nc() const { return width; } 795 796 template <typename EXP> 797 assignable_sub_matrix& operator= ( 798 const matrix_exp<EXP>& exp 799 ) 800 { 801 DLIB_ASSERT( exp.nr() == height && exp.nc() == width, 802 "\tassignable_matrix_expression set_subm()" 803 << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" 804 << "\n\texp.nr() (source matrix): " << exp.nr() 805 << "\n\texp.nc() (source matrix): " << exp.nc() 806 << "\n\twidth (target matrix): " << width 807 << "\n\theight (target matrix): " << height 808 ); 809 810 if (exp.destructively_aliases(m) == false) 811 { 812 matrix_assign(*this, exp); 813 } 814 else 815 { 816 // make a temporary copy of the matrix we are going to assign to m to 817 // avoid aliasing issues during the copy 818 this->operator=(tmp(exp)); 819 } 820 821 return *this; 822 } 823 824 template <typename EXP> 825 assignable_sub_matrix& operator+= ( 826 const matrix_exp<EXP>& exp 827 ) 828 { 829 DLIB_ASSERT( exp.nr() == height && exp.nc() == width, 830 "\tassignable_matrix_expression set_subm()" 831 << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" 832 << "\n\texp.nr() (source matrix): " << exp.nr() 833 << "\n\texp.nc() (source matrix): " << exp.nc() 834 << "\n\twidth (target matrix): " << width 835 << "\n\theight (target matrix): " << height 836 ); 837 838 if (exp.destructively_aliases(m) == false) 839 { 840 matrix_assign(*this, subm(m,top,left,height,width)+exp); 841 } 842 else 843 { 844 // make a temporary copy of the matrix we are going to assign to m to 845 // avoid aliasing issues during the copy 846 this->operator+=(tmp(exp)); 847 } 848 849 return *this; 850 } 851 852 template <typename EXP> 853 assignable_sub_matrix& operator-= ( 854 const matrix_exp<EXP>& exp 855 ) 856 { 857 DLIB_ASSERT( exp.nr() == height && exp.nc() == width, 858 "\tassignable_matrix_expression set_subm()" 859 << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" 860 << "\n\texp.nr() (source matrix): " << exp.nr() 861 << "\n\texp.nc() (source matrix): " << exp.nc() 862 << "\n\twidth (target matrix): " << width 863 << "\n\theight (target matrix): " << height 864 ); 865 866 if (exp.destructively_aliases(m) == false) 867 { 868 matrix_assign(*this, subm(m,top,left,height,width)-exp); 869 } 870 else 871 { 872 // make a temporary copy of the matrix we are going to assign to m to 873 // avoid aliasing issues during the copy 874 this->operator-=(tmp(exp)); 875 } 876 877 return *this; 878 } 879 880 assignable_sub_matrix& operator= ( 881 const T& value 882 ) 883 { 884 const long bottom = top+height-1; 885 const long right = left+width-1; 886 for (long r = top; r <= bottom; ++r) 887 { 888 for (long c = left; c <= right; ++c) 889 { 890 m(r,c) = value; 891 } 892 } 893 894 return *this; 895 } 896 897 assignable_sub_matrix& operator+= ( 898 const T& value 899 ) 900 { 901 const long bottom = top+height-1; 902 const long right = left+width-1; 903 for (long r = top; r <= bottom; ++r) 904 { 905 for (long c = left; c <= right; ++c) 906 { 907 m(r,c) += value; 908 } 909 } 910 911 return *this; 912 } 913 914 assignable_sub_matrix& operator-= ( 915 const T& value 916 ) 917 { 918 const long bottom = top+height-1; 919 const long right = left+width-1; 920 for (long r = top; r <= bottom; ++r) 921 { 922 for (long c = left; c <= right; ++c) 923 { 924 m(r,c) -= value; 925 } 926 } 927 928 return *this; 929 } 930 931 932 matrix<T,NR,NC,mm,l>& m; 933 const long left, top, width, height; 934 }; 935 936 937 template <typename T, long NR, long NC, typename mm, typename l> set_subm(matrix<T,NR,NC,mm,l> & m,const rectangle & rect)938 assignable_sub_matrix<T,NR,NC,mm,l> set_subm ( 939 matrix<T,NR,NC,mm,l>& m, 940 const rectangle& rect 941 ) 942 { 943 DLIB_ASSERT(get_rect(m).contains(rect) == true, 944 "\tassignable_matrix_expression set_subm(matrix& m, const rectangle& rect)" 945 << "\n\tYou have specified invalid sub matrix dimensions" 946 << "\n\tm.nr(): " << m.nr() 947 << "\n\tm.nc(): " << m.nc() 948 << "\n\trect.left(): " << rect.left() 949 << "\n\trect.top(): " << rect.top() 950 << "\n\trect.right(): " << rect.right() 951 << "\n\trect.bottom(): " << rect.bottom() 952 ); 953 954 955 return assignable_sub_matrix<T,NR,NC,mm,l>(m,rect.top(), rect.left(), rect.height(), rect.width()); 956 } 957 958 959 template <typename T, long NR, long NC, typename mm, typename l> set_subm(matrix<T,NR,NC,mm,l> & m,long r,long c,long nr,long nc)960 assignable_sub_matrix<T,NR,NC,mm,l> set_subm ( 961 matrix<T,NR,NC,mm,l>& m, 962 long r, 963 long c, 964 long nr, 965 long nc 966 ) 967 { 968 DLIB_ASSERT(r >= 0 && c >= 0 && nr >= 0 && nc >= 0 && r+nr <= m.nr() && c+nc <= m.nc(), 969 "\tassignable_matrix_expression set_subm(matrix& m, r, c, nr, nc)" 970 << "\n\tYou have specified invalid sub matrix dimensions" 971 << "\n\tm.nr(): " << m.nr() 972 << "\n\tm.nc(): " << m.nc() 973 << "\n\tr: " << r 974 << "\n\tc: " << c 975 << "\n\tnr: " << nr 976 << "\n\tnc: " << nc 977 ); 978 979 return assignable_sub_matrix<T,NR,NC,mm,l>(m,r,c, nr, nc); 980 } 981 982 // ---------------------------------------------------------------------------------------- 983 984 template <typename T, long NR, long NC, typename mm, typename l, typename EXPr, typename EXPc> 985 class assignable_sub_range_matrix 986 { 987 public: 988 typedef T type; 989 typedef l layout_type; 990 typedef matrix<T,NR,NC,mm,l> matrix_type; 991 assignable_sub_range_matrix(matrix<T,NR,NC,mm,l> & m_,const EXPr & rows_,const EXPc & cols_)992 assignable_sub_range_matrix( 993 matrix<T,NR,NC,mm,l>& m_, 994 const EXPr& rows_, 995 const EXPc& cols_ 996 ) : m(m_), rows(rows_), cols(cols_) {} 997 operator()998 T& operator() ( 999 long r, 1000 long c 1001 ) 1002 { 1003 return m(rows(r),cols(c)); 1004 } 1005 nr()1006 long nr() const { return rows.size(); } nc()1007 long nc() const { return cols.size(); } 1008 1009 1010 template <typename EXP> 1011 assignable_sub_range_matrix& operator= ( 1012 const matrix_exp<EXP>& exp 1013 ) 1014 { 1015 DLIB_ASSERT( exp.nr() == rows.size() && exp.nc() == cols.size(), 1016 "\tassignable_matrix_expression set_subm(matrix& m, const matrix_exp rows, const matrix_exp cols)" 1017 << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" 1018 << "\n\texp.nr() (source matrix): " << exp.nr() 1019 << "\n\texp.nc() (source matrix): " << exp.nc() 1020 << "\n\trows.size() (target matrix): " << rows.size() 1021 << "\n\tcols.size() (target matrix): " << cols.size() 1022 ); 1023 1024 if (exp.destructively_aliases(m) == false) 1025 { 1026 matrix_assign(*this, exp); 1027 } 1028 else 1029 { 1030 // make a temporary copy of the matrix we are going to assign to m to 1031 // avoid aliasing issues during the copy 1032 this->operator=(tmp(exp)); 1033 } 1034 1035 return *this; 1036 } 1037 1038 template <typename EXP> 1039 assignable_sub_range_matrix& operator+= ( 1040 const matrix_exp<EXP>& exp 1041 ) 1042 { 1043 DLIB_ASSERT( exp.nr() == rows.size() && exp.nc() == cols.size(), 1044 "\tassignable_matrix_expression set_subm(matrix& m, const matrix_exp rows, const matrix_exp cols)" 1045 << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" 1046 << "\n\texp.nr() (source matrix): " << exp.nr() 1047 << "\n\texp.nc() (source matrix): " << exp.nc() 1048 << "\n\trows.size() (target matrix): " << rows.size() 1049 << "\n\tcols.size() (target matrix): " << cols.size() 1050 ); 1051 1052 if (exp.destructively_aliases(m) == false) 1053 { 1054 matrix_assign(*this, subm(m,rows,cols)+exp); 1055 } 1056 else 1057 { 1058 // make a temporary copy of the matrix we are going to assign to m to 1059 // avoid aliasing issues during the copy 1060 this->operator+=(tmp(exp)); 1061 } 1062 1063 return *this; 1064 } 1065 1066 template <typename EXP> 1067 assignable_sub_range_matrix& operator-= ( 1068 const matrix_exp<EXP>& exp 1069 ) 1070 { 1071 DLIB_ASSERT( exp.nr() == rows.size() && exp.nc() == cols.size(), 1072 "\tassignable_matrix_expression set_subm(matrix& m, const matrix_exp rows, const matrix_exp cols)" 1073 << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" 1074 << "\n\texp.nr() (source matrix): " << exp.nr() 1075 << "\n\texp.nc() (source matrix): " << exp.nc() 1076 << "\n\trows.size() (target matrix): " << rows.size() 1077 << "\n\tcols.size() (target matrix): " << cols.size() 1078 ); 1079 1080 if (exp.destructively_aliases(m) == false) 1081 { 1082 matrix_assign(*this, subm(m,rows,cols)-exp); 1083 } 1084 else 1085 { 1086 // make a temporary copy of the matrix we are going to assign to m to 1087 // avoid aliasing issues during the copy 1088 this->operator-=(tmp(exp)); 1089 } 1090 1091 return *this; 1092 } 1093 1094 assignable_sub_range_matrix& operator= ( 1095 const T& value 1096 ) 1097 { 1098 for (long r = 0; r < rows.size(); ++r) 1099 { 1100 for (long c = 0; c < cols.size(); ++c) 1101 { 1102 m(rows(r),cols(c)) = value; 1103 } 1104 } 1105 1106 return *this; 1107 } 1108 1109 assignable_sub_range_matrix& operator+= ( 1110 const T& value 1111 ) 1112 { 1113 for (long r = 0; r < rows.size(); ++r) 1114 { 1115 for (long c = 0; c < cols.size(); ++c) 1116 { 1117 m(rows(r),cols(c)) += value; 1118 } 1119 } 1120 1121 return *this; 1122 } 1123 1124 assignable_sub_range_matrix& operator-= ( 1125 const T& value 1126 ) 1127 { 1128 for (long r = 0; r < rows.size(); ++r) 1129 { 1130 for (long c = 0; c < cols.size(); ++c) 1131 { 1132 m(rows(r),cols(c)) -= value; 1133 } 1134 } 1135 1136 return *this; 1137 } 1138 1139 private: 1140 1141 matrix<T,NR,NC,mm,l>& m; 1142 const EXPr rows; 1143 const EXPc cols; 1144 }; 1145 1146 template <typename T, long NR, long NC, typename mm, typename l, typename EXPr, typename EXPc> set_subm(matrix<T,NR,NC,mm,l> & m,const matrix_exp<EXPr> & rows,const matrix_exp<EXPc> & cols)1147 assignable_sub_range_matrix<T,NR,NC,mm,l,EXPr,EXPc > set_subm ( 1148 matrix<T,NR,NC,mm,l>& m, 1149 const matrix_exp<EXPr>& rows, 1150 const matrix_exp<EXPc>& cols 1151 ) 1152 { 1153 DLIB_ASSERT(0 <= min(rows) && max(rows) < m.nr() && 0 <= min(cols) && max(cols) < m.nc() && 1154 (rows.nr() == 1 || rows.nc() == 1) && (cols.nr() == 1 || cols.nc() == 1), 1155 "\tassignable_matrix_expression set_subm(matrix& m, const matrix_exp& rows, const matrix_exp& cols)" 1156 << "\n\tYou have specified invalid sub matrix dimensions" 1157 << "\n\tm.nr(): " << m.nr() 1158 << "\n\tm.nc(): " << m.nc() 1159 << "\n\tmin(rows): " << min(rows) 1160 << "\n\tmax(rows): " << max(rows) 1161 << "\n\tmin(cols): " << min(cols) 1162 << "\n\tmax(cols): " << max(cols) 1163 << "\n\trows.nr(): " << rows.nr() 1164 << "\n\trows.nc(): " << rows.nc() 1165 << "\n\tcols.nr(): " << cols.nr() 1166 << "\n\tcols.nc(): " << cols.nc() 1167 ); 1168 1169 return assignable_sub_range_matrix<T,NR,NC,mm,l,EXPr,EXPc >(m,rows.ref(),cols.ref()); 1170 } 1171 1172 // ---------------------------------------------------------------------------------------- 1173 1174 template <typename T, long NR, long NC, typename mm, typename l, typename EXPr> set_rowm(matrix<T,NR,NC,mm,l> & m,const matrix_exp<EXPr> & rows)1175 assignable_sub_range_matrix<T,NR,NC,mm,l,EXPr,matrix_range_exp<long> > set_rowm ( 1176 matrix<T,NR,NC,mm,l>& m, 1177 const matrix_exp<EXPr>& rows 1178 ) 1179 { 1180 DLIB_ASSERT(0 <= min(rows) && max(rows) < m.nr() && (rows.nr() == 1 || rows.nc() == 1), 1181 "\tassignable_matrix_expression set_rowm(matrix& m, const matrix_exp& rows)" 1182 << "\n\tYou have specified invalid sub matrix dimensions" 1183 << "\n\tm.nr(): " << m.nr() 1184 << "\n\tm.nc(): " << m.nc() 1185 << "\n\tmin(rows): " << min(rows) 1186 << "\n\tmax(rows): " << max(rows) 1187 << "\n\trows.nr(): " << rows.nr() 1188 << "\n\trows.nc(): " << rows.nc() 1189 ); 1190 1191 return assignable_sub_range_matrix<T,NR,NC,mm,l,EXPr,matrix_range_exp<long> >(m,rows.ref(),range(0,m.nc()-1)); 1192 } 1193 1194 // ---------------------------------------------------------------------------------------- 1195 1196 template <typename T, long NR, long NC, typename mm, typename l, typename EXPc> set_colm(matrix<T,NR,NC,mm,l> & m,const matrix_exp<EXPc> & cols)1197 assignable_sub_range_matrix<T,NR,NC,mm,l,matrix_range_exp<long>,EXPc > set_colm ( 1198 matrix<T,NR,NC,mm,l>& m, 1199 const matrix_exp<EXPc>& cols 1200 ) 1201 { 1202 DLIB_ASSERT(0 <= min(cols) && max(cols) < m.nc() && (cols.nr() == 1 || cols.nc() == 1), 1203 "\tassignable_matrix_expression set_colm(matrix& m, const matrix_exp& cols)" 1204 << "\n\tYou have specified invalid sub matrix dimensions" 1205 << "\n\tm.nr(): " << m.nr() 1206 << "\n\tm.nc(): " << m.nc() 1207 << "\n\tmin(cols): " << min(cols) 1208 << "\n\tmax(cols): " << max(cols) 1209 << "\n\tcols.nr(): " << cols.nr() 1210 << "\n\tcols.nc(): " << cols.nc() 1211 ); 1212 1213 return assignable_sub_range_matrix<T,NR,NC,mm,l,matrix_range_exp<long>,EXPc >(m,range(0,m.nr()-1),cols.ref()); 1214 } 1215 1216 // ---------------------------------------------------------------------------------------- 1217 1218 template <typename T, long NR, long NC, typename mm, typename l> 1219 class assignable_col_matrix 1220 { 1221 public: 1222 typedef T type; 1223 typedef l layout_type; 1224 typedef matrix<T,NR,NC,mm,l> matrix_type; 1225 assignable_col_matrix(matrix<T,NR,NC,mm,l> & m_,const long col_)1226 assignable_col_matrix( 1227 matrix<T,NR,NC,mm,l>& m_, 1228 const long col_ 1229 ) : m(m_), col(col_) {} 1230 operator()1231 T& operator() ( 1232 long r, 1233 long 1234 ) 1235 { 1236 return m(r,col); 1237 } 1238 operator()1239 const T& operator() ( 1240 long r, 1241 long 1242 ) const 1243 { 1244 return m(r,col); 1245 } 1246 nr()1247 long nr() const { return m.nr(); } nc()1248 long nc() const { return 1; } 1249 1250 template <typename EXP> 1251 assignable_col_matrix& operator= ( 1252 const matrix_exp<EXP>& exp 1253 ) 1254 { 1255 DLIB_ASSERT( exp.nc() == 1 && exp.nr() == m.nr(), 1256 "\tassignable_matrix_expression set_colm()" 1257 << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" 1258 << "\n\texp.nr() (source matrix): " << exp.nr() 1259 << "\n\texp.nc() (source matrix): " << exp.nc() 1260 << "\n\tm.nr() (target matrix): " << m.nr() 1261 ); 1262 1263 if (exp.destructively_aliases(m) == false) 1264 { 1265 matrix_assign(*this, exp); 1266 } 1267 else 1268 { 1269 // make a temporary copy of the matrix we are going to assign to m to 1270 // avoid aliasing issues during the copy 1271 this->operator=(tmp(exp)); 1272 } 1273 1274 return *this; 1275 } 1276 1277 template <typename EXP> 1278 assignable_col_matrix& operator+= ( 1279 const matrix_exp<EXP>& exp 1280 ) 1281 { 1282 DLIB_ASSERT( exp.nc() == 1 && exp.nr() == m.nr(), 1283 "\tassignable_matrix_expression set_colm()" 1284 << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" 1285 << "\n\texp.nr() (source matrix): " << exp.nr() 1286 << "\n\texp.nc() (source matrix): " << exp.nc() 1287 << "\n\tm.nr() (target matrix): " << m.nr() 1288 ); 1289 1290 if (exp.destructively_aliases(m) == false) 1291 { 1292 matrix_assign(*this, colm(m,col)+exp); 1293 } 1294 else 1295 { 1296 // make a temporary copy of the matrix we are going to assign to m to 1297 // avoid aliasing issues during the copy 1298 this->operator+=(tmp(exp)); 1299 } 1300 1301 return *this; 1302 } 1303 1304 template <typename EXP> 1305 assignable_col_matrix& operator-= ( 1306 const matrix_exp<EXP>& exp 1307 ) 1308 { 1309 DLIB_ASSERT( exp.nc() == 1 && exp.nr() == m.nr(), 1310 "\tassignable_matrix_expression set_colm()" 1311 << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" 1312 << "\n\texp.nr() (source matrix): " << exp.nr() 1313 << "\n\texp.nc() (source matrix): " << exp.nc() 1314 << "\n\tm.nr() (target matrix): " << m.nr() 1315 ); 1316 1317 if (exp.destructively_aliases(m) == false) 1318 { 1319 matrix_assign(*this, colm(m,col)-exp); 1320 } 1321 else 1322 { 1323 // make a temporary copy of the matrix we are going to assign to m to 1324 // avoid aliasing issues during the copy 1325 this->operator-=(tmp(exp)); 1326 } 1327 1328 return *this; 1329 } 1330 1331 assignable_col_matrix& operator= ( 1332 const T& value 1333 ) 1334 { 1335 for (long i = 0; i < m.nr(); ++i) 1336 { 1337 m(i,col) = value; 1338 } 1339 1340 return *this; 1341 } 1342 1343 assignable_col_matrix& operator+= ( 1344 const T& value 1345 ) 1346 { 1347 for (long i = 0; i < m.nr(); ++i) 1348 { 1349 m(i,col) += value; 1350 } 1351 1352 return *this; 1353 } 1354 1355 assignable_col_matrix& operator-= ( 1356 const T& value 1357 ) 1358 { 1359 for (long i = 0; i < m.nr(); ++i) 1360 { 1361 m(i,col) -= value; 1362 } 1363 1364 return *this; 1365 } 1366 1367 1368 matrix<T,NR,NC,mm,l>& m; 1369 const long col; 1370 }; 1371 1372 1373 template <typename T, long NR, long NC, typename mm, typename l> set_colm(matrix<T,NR,NC,mm,l> & m,const long col)1374 assignable_col_matrix<T,NR,NC,mm,l> set_colm ( 1375 matrix<T,NR,NC,mm,l>& m, 1376 const long col 1377 ) 1378 { 1379 DLIB_ASSERT(col >= 0 && col < m.nc(), 1380 "\tassignable_matrix_expression set_colm(matrix& m, col)" 1381 << "\n\tYou have specified invalid sub matrix dimensions" 1382 << "\n\tm.nr(): " << m.nr() 1383 << "\n\tm.nc(): " << m.nc() 1384 << "\n\tcol: " << col 1385 ); 1386 1387 1388 return assignable_col_matrix<T,NR,NC,mm,l>(m,col); 1389 } 1390 1391 // ---------------------------------------------------------------------------------------- 1392 1393 1394 template <typename T, long NR, long NC, typename mm, typename l> 1395 class assignable_row_matrix 1396 { 1397 public: 1398 typedef T type; 1399 typedef l layout_type; 1400 typedef matrix<T,NR,NC,mm,l> matrix_type; 1401 assignable_row_matrix(matrix<T,NR,NC,mm,l> & m_,const long row_)1402 assignable_row_matrix( 1403 matrix<T,NR,NC,mm,l>& m_, 1404 const long row_ 1405 ) : m(m_), row(row_) {} 1406 1407 operator()1408 T& operator() ( 1409 long , 1410 long c 1411 ) 1412 { 1413 return m(row,c); 1414 } 1415 operator()1416 const T& operator() ( 1417 long , 1418 long c 1419 ) const 1420 { 1421 return m(row,c); 1422 } 1423 nr()1424 long nr() const { return 1; } nc()1425 long nc() const { return m.nc(); } 1426 1427 1428 template <typename EXP> 1429 assignable_row_matrix& operator= ( 1430 const matrix_exp<EXP>& exp 1431 ) 1432 { 1433 DLIB_ASSERT( exp.nr() == 1 && exp.nc() == m.nc(), 1434 "\tassignable_matrix_expression set_rowm()" 1435 << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" 1436 << "\n\texp.nr() (source matrix): " << exp.nr() 1437 << "\n\texp.nc() (source matrix): " << exp.nc() 1438 << "\n\tm.nc() (target matrix): " << m.nc() 1439 ); 1440 1441 if (exp.destructively_aliases(m) == false) 1442 { 1443 matrix_assign(*this, exp); 1444 } 1445 else 1446 { 1447 // make a temporary copy of the matrix we are going to assign to m to 1448 // avoid aliasing issues during the copy 1449 this->operator=(tmp(exp)); 1450 } 1451 1452 return *this; 1453 } 1454 1455 template <typename EXP> 1456 assignable_row_matrix& operator+= ( 1457 const matrix_exp<EXP>& exp 1458 ) 1459 { 1460 DLIB_ASSERT( exp.nr() == 1 && exp.nc() == m.nc(), 1461 "\tassignable_matrix_expression set_rowm()" 1462 << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" 1463 << "\n\texp.nr() (source matrix): " << exp.nr() 1464 << "\n\texp.nc() (source matrix): " << exp.nc() 1465 << "\n\tm.nc() (target matrix): " << m.nc() 1466 ); 1467 1468 if (exp.destructively_aliases(m) == false) 1469 { 1470 matrix_assign(*this, rowm(m,row)+exp); 1471 } 1472 else 1473 { 1474 // make a temporary copy of the matrix we are going to assign to m to 1475 // avoid aliasing issues during the copy 1476 this->operator+=(tmp(exp)); 1477 } 1478 1479 return *this; 1480 } 1481 1482 template <typename EXP> 1483 assignable_row_matrix& operator-= ( 1484 const matrix_exp<EXP>& exp 1485 ) 1486 { 1487 DLIB_ASSERT( exp.nr() == 1 && exp.nc() == m.nc(), 1488 "\tassignable_matrix_expression set_rowm()" 1489 << "\n\tYou have tried to assign to this object using a matrix that isn't the right size" 1490 << "\n\texp.nr() (source matrix): " << exp.nr() 1491 << "\n\texp.nc() (source matrix): " << exp.nc() 1492 << "\n\tm.nc() (target matrix): " << m.nc() 1493 ); 1494 1495 if (exp.destructively_aliases(m) == false) 1496 { 1497 matrix_assign(*this, rowm(m,row)-exp); 1498 } 1499 else 1500 { 1501 // make a temporary copy of the matrix we are going to assign to m to 1502 // avoid aliasing issues during the copy 1503 this->operator-=(tmp(exp)); 1504 } 1505 1506 return *this; 1507 } 1508 1509 assignable_row_matrix& operator= ( 1510 const T& value 1511 ) 1512 { 1513 for (long i = 0; i < m.nc(); ++i) 1514 { 1515 m(row,i) = value; 1516 } 1517 1518 return *this; 1519 } 1520 1521 assignable_row_matrix& operator+= ( 1522 const T& value 1523 ) 1524 { 1525 for (long i = 0; i < m.nc(); ++i) 1526 { 1527 m(row,i) += value; 1528 } 1529 1530 return *this; 1531 } 1532 1533 assignable_row_matrix& operator-= ( 1534 const T& value 1535 ) 1536 { 1537 for (long i = 0; i < m.nc(); ++i) 1538 { 1539 m(row,i) -= value; 1540 } 1541 1542 return *this; 1543 } 1544 1545 1546 matrix<T,NR,NC,mm,l>& m; 1547 const long row; 1548 }; 1549 1550 1551 template <typename T, long NR, long NC, typename mm, typename l> set_rowm(matrix<T,NR,NC,mm,l> & m,const long row)1552 assignable_row_matrix<T,NR,NC,mm,l> set_rowm ( 1553 matrix<T,NR,NC,mm,l>& m, 1554 const long row 1555 ) 1556 { 1557 DLIB_ASSERT(row >= 0 && row < m.nr(), 1558 "\tassignable_matrix_expression set_rowm(matrix& m, row)" 1559 << "\n\tYou have specified invalid sub matrix dimensions" 1560 << "\n\tm.nr(): " << m.nr() 1561 << "\n\tm.nc(): " << m.nc() 1562 << "\n\trow: " << row 1563 ); 1564 1565 1566 return assignable_row_matrix<T,NR,NC,mm,l>(m,row); 1567 } 1568 1569 // ---------------------------------------------------------------------------------------- 1570 1571 } 1572 1573 #endif // DLIB_MATRIx_SUBEXP_ 1574 1575