00001
00010 #ifndef BS_EXPRESSION_TEMPLATES_MATRIX_ARITHMETIC_H_
00011 #define BS_EXPRESSION_TEMPLATES_MATRIX_ARITHMETIC_H_
00012
00013 namespace blue_sky
00014 {
00015
00016 struct ref_trait {};
00017 struct ref_unsafe_trait {};
00018 struct const_trait {};
00019 struct const_unsafe_trait {};
00020
00021 template <typename array_t_, typename trait_t = const_trait>
00022 struct mx_holder
00023 {
00024 typedef array_t_ array_t;
00025 typedef typename array_t::value_type value_type;
00026 typedef mx_holder <array_t, trait_t> this_t;
00027
00028 mx_holder (const array_t &array_, size_t size)
00029 : array_ (array_)
00030 , block_size_ (size * size)
00031 {
00032 BS_ASSERT (block_size_ <= 9) (block_size_);
00033 }
00034
00035 value_type
00036 operator [] (size_t i) const
00037 {
00038 return array_[i];
00039 }
00040
00041 size_t
00042 block_size () const
00043 {
00044 return block_size_;
00045 }
00046
00047 const array_t &array_;
00048 size_t block_size_;
00049 };
00050 template <typename array_t_>
00051 struct mx_holder <array_t_, ref_trait>
00052 {
00053
00054 typedef array_t_ array_t;
00055 typedef typename array_t::value_type value_type;
00056 typedef mx_holder <array_t, ref_trait> this_t;
00057
00058 mx_holder (array_t &array_, size_t idx, size_t size)
00059 : array_ (array_)
00060 , block_size_ (size * size)
00061 , idx_ (idx * block_size_)
00062 {
00063 BS_ASSERT (block_size_ <= 9) (block_size_);
00064 }
00065
00066 template <typename op_t>
00067 this_t &
00068 operator= (const op_t &op)
00069 {
00070 for (size_t i = 0, cnt = block_size_; i < cnt; ++i)
00071 {
00072 array_[i + idx_] = op[i];
00073 }
00074
00075 return *this;
00076 }
00077
00078 template <typename op_t>
00079 this_t &
00080 operator+= (const op_t &op)
00081 {
00082 for (size_t i = 0, cnt = block_size_; i < cnt; ++i)
00083 {
00084 array_[i + idx_] += op[i];
00085 }
00086
00087 return *this;
00088 }
00089
00090 value_type &
00091 operator [] (size_t index)
00092 {
00093 if (idx_ + index >= array_.size ())
00094 throw bs_exception ("mx_holder[]", "index out of range");
00095
00096 return array_[idx_ + index];
00097 }
00098
00099 array_t &array_;
00100 size_t block_size_;
00101 size_t idx_;
00102 };
00103 template <typename array_t_, typename trait_t = const_trait>
00104 struct clmn_holder
00105 {
00106
00107 typedef array_t_ array_t;
00108 typedef typename array_t::value_type value_type;
00109 typedef clmn_holder <array_t, trait_t> this_t;
00110
00111 clmn_holder (const array_t &array_, size_t size)
00112 : array_ (array_)
00113 , block_size_ (size)
00114 {
00115 BS_ASSERT (block_size_ <= 3) (block_size_);
00116 }
00117
00118 value_type
00119 operator [] (size_t i) const
00120 {
00121 return array_[i % block_size_];
00122 }
00123
00124 size_t
00125 block_size () const
00126 {
00127 return block_size_;
00128 }
00129
00130 const array_t &array_;
00131 size_t block_size_;
00132 };
00133 template <typename array_t_>
00134 struct clmn_holder <array_t_, const_unsafe_trait>
00135 {
00136 typedef array_t_ array_t;
00137 typedef typename array_t::value_type value_type;
00138 typedef clmn_holder <array_t, const_unsafe_trait> this_t;
00139
00140 clmn_holder (const array_t &array_, size_t index, size_t size)
00141 : array_ (array_)
00142 , index_ (index * size)
00143 , block_size_ (size)
00144 , unsafe_array_ (&array_[index_])
00145 {
00146 BS_ASSERT (block_size_ <= 3) (block_size_);
00147 }
00148
00149 value_type
00150 operator [] (size_t i) const
00151 {
00152 return unsafe_array_[i % block_size_];
00153 }
00154
00155 size_t
00156 block_size () const
00157 {
00158 return block_size_;
00159 }
00160
00161 const array_t &array_;
00162 size_t index_;
00163 size_t block_size_;
00164 const value_type *unsafe_array_;
00165 };
00166 template <typename array_t_>
00167 struct clmn_holder <array_t_, ref_trait>
00168 {
00169 typedef array_t_ array_t;
00170 typedef typename array_t::value_type value_type;
00171 typedef clmn_holder <array_t, ref_trait> this_t;
00172
00173 clmn_holder (array_t &array, size_t idx, size_t size)
00174 : array_ (array)
00175 , idx_ (idx * size)
00176 , block_size_ (size)
00177 {
00178 BS_ASSERT (block_size_ <= 3) (block_size_);
00179 }
00180
00181 template <typename op_t>
00182 this_t &
00183 operator= (const op_t &op)
00184 {
00185 for (size_t i = 0, cnt = block_size_; i < cnt; ++i)
00186 {
00187 array_[idx_ + i] = op[i];
00188 }
00189
00190 return *this;
00191 }
00192
00193 array_t &array_;
00194 size_t idx_;
00195 size_t block_size_;
00196 };
00197
00198 template <typename array_type, typename trait_t = const_trait>
00199 struct line_holder
00200 {
00201 typedef array_type array_t;
00202 typedef typename array_t::value_type value_type;
00203 typedef line_holder <array_t, trait_t> this_t;
00204
00205 line_holder (const array_t &array_, size_t size)
00206 : array_ (array_)
00207 , block_size_ (size)
00208 {
00209 BS_ASSERT (block_size_ <= 3) (block_size_);
00210 }
00211
00212 value_type
00213 operator [] (size_t i) const
00214 {
00215 return array_[i % block_size_];
00216 }
00217 size_t
00218 block_size () const
00219 {
00220 return block_size_;
00221 }
00222
00223 const array_t &array_;
00224 size_t block_size_;
00225 };
00226
00227 template <typename array_type>
00228 struct line_holder <array_type, const_unsafe_trait>
00229 {
00230 typedef array_type array_t;
00231 typedef typename array_t::value_type value_type;
00232 typedef line_holder <array_t, const_unsafe_trait> this_t;
00233
00234 line_holder (const array_t &array_, size_t index, size_t size)
00235 : array_ (array_)
00236 , index_ (index)
00237 , block_size_ (size)
00238 , unsafe_array_ (&array_[index_ * block_size_])
00239 {
00240 BS_ASSERT (block_size_ <= 3) (block_size_);
00241 }
00242
00243 value_type
00244 operator [] (size_t i) const
00245 {
00246 return unsafe_array_[i % block_size_];
00247 }
00248 size_t
00249 block_size () const
00250 {
00251 return block_size_;
00252 }
00253
00254 const array_t &array_;
00255 size_t block_size_;
00256 size_t index_;
00257 const value_type *unsafe_array_;
00258 };
00259
00260 template <typename array_type>
00261 struct line_holder <array_type, ref_unsafe_trait>
00262 {
00263 typedef array_type array_t;
00264 typedef typename array_t::value_type value_type;
00265 typedef line_holder <array_t, ref_unsafe_trait> this_t;
00266
00267 line_holder (const array_t &array_, size_t index, size_t size)
00268 : array_ (array_)
00269 , index_ (index)
00270 , block_size_ (size)
00271 , unsafe_array_ (&array_[index_ * block_size_])
00272 {
00273 BS_ASSERT (block_size_ <= 3) (block_size_);
00274 }
00275
00276 template <typename op_t>
00277 this_t &
00278 operator= (const op_t &op)
00279 {
00280 for (size_t i = 0, cnt = block_size_; i < cnt; ++i)
00281 {
00282 unsafe_array_[i] = op [i];
00283 }
00284
00285 return *this;
00286 }
00287
00288 const array_t &array_;
00289 size_t block_size_;
00290 size_t index_;
00291 const value_type *unsafe_array_;
00292 };
00293
00294 template <typename array_type>
00295 struct line_holder <array_type, ref_trait>
00296 {
00297 typedef array_type array_t;
00298 typedef typename array_t::value_type value_type;
00299 typedef line_holder <array_t, ref_trait> this_t;
00300
00301 line_holder (array_t &array_, size_t size)
00302 : array_ (array_)
00303 , block_size_ (size)
00304 {
00305 BS_ASSERT (block_size_ <= 3) (block_size_);
00306 }
00307
00308 template <typename op_t>
00309 this_t &
00310 operator= (const op_t &op)
00311 {
00312 for (size_t i = 0, cnt = block_size_; i < cnt; ++i)
00313 {
00314 array_[i] = op[i];
00315 }
00316
00317 return *this;
00318 }
00319
00320 array_t &array_;
00321 size_t block_size_;
00322 };
00323
00324 template <typename mx_op_t>
00325 struct mx_op
00326 {
00327 typedef typename mx_op_t::value_type value_type;
00328 typedef mx_op_t op_t;
00329
00330 mx_op (const mx_op_t &mx_op_)
00331 : mx_op_ (mx_op_)
00332 {
00333 }
00334
00335 value_type
00336 operator [] (size_t i) const
00337 {
00338 return mx_op_[i];
00339 }
00340
00341 size_t
00342 block_size () const
00343 {
00344 return mx_op_.block_size ();
00345 }
00346
00347 mx_op_t mx_op_;
00348 };
00349
00350 template <typename clmn_op_t>
00351 struct clmn_op
00352 {
00353 typedef typename clmn_op_t::value_type value_type;
00354 typedef clmn_op_t op_t;
00355
00356 clmn_op (const clmn_op_t &clmn_op_)
00357 : clmn_op_ (clmn_op_)
00358 {
00359 }
00360
00361 value_type
00362 operator [] (size_t i) const
00363 {
00364 return clmn_op_ [i];
00365 }
00366
00367 size_t
00368 block_size () const
00369 {
00370 return clmn_op_.block_size ();
00371 }
00372
00373 clmn_op_t clmn_op_;
00374 };
00375
00376 template <typename line_op_t>
00377 struct line_op
00378 {
00379 typedef typename line_op_t::value_type value_type;
00380 typedef line_op_t op_t;
00381
00382 line_op (const line_op_t &line_op)
00383 : line_op_ (line_op)
00384 {
00385 }
00386
00387 value_type
00388 operator [] (size_t i) const
00389 {
00390 return line_op_[i];
00391 }
00392
00393 size_t
00394 block_size () const
00395 {
00396 return line_op_.block_size ();
00397 }
00398
00399 line_op_t line_op_;
00400 };
00401
00402 template <typename scalar_op_t>
00403 struct scalar_op
00404 {
00405 typedef scalar_op_t op_t;
00406 typedef typename op_t::value_type value_type;
00407
00408 scalar_op (const op_t &op)
00409 : op_ (op)
00410 {
00411 }
00412
00413 operator value_type () const
00414 {
00415 return op_;
00416 }
00417
00418 op_t op_;
00419 };
00420
00422 template <typename lhs_t, typename rhs_t>
00423 struct mx_mul
00424 {
00425 typedef typename lhs_t::value_type value_type;
00426
00427 mx_mul (const lhs_t &lhs, const rhs_t &rhs)
00428 : lhs_ (lhs)
00429 , rhs_ (rhs)
00430 {
00431 }
00432
00433 template <typename array_t>
00434 mx_mul (const lhs_t &lhs, const array_t &array)
00435 : lhs_ (lhs)
00436 , rhs_ (rhs_t (array))
00437 {
00438 }
00439
00440 template <typename array_t>
00441 mx_mul (const array_t &array, const rhs_t &rhs)
00442 : lhs_ (lhs_t (array))
00443 , rhs_ (rhs)
00444 {
00445 }
00446
00447 value_type
00448 operator [] (size_t i) const
00449 {
00450 size_t bs = lhs_.block_size ();
00451 size_t ri = i / bs;
00452 size_t ci = i % bs;
00453
00454 value_type res = 0;
00455 for (size_t j = 0; j < bs; ++j)
00456 {
00457 res += lhs_[ri * bs + j] * rhs_[j * bs + ci];
00458 }
00459
00460 return res;
00461 }
00462
00463 size_t
00464 block_size () const
00465 {
00466 return lhs_.block_size ();
00467 }
00468
00469 lhs_t lhs_;
00470 rhs_t rhs_;
00471 };
00472
00473 template <typename lhs_t, typename rhs_t>
00474 struct mx_sub
00475 {
00476 typedef typename lhs_t::value_type value_type;
00477
00478 mx_sub (const lhs_t &lhs, const rhs_t &rhs)
00479 : lhs_ (lhs)
00480 , rhs_ (rhs)
00481 {
00482 }
00483
00484 template <typename array_t>
00485 mx_sub (const lhs_t &lhs, const array_t &array)
00486 : lhs_ (lhs)
00487 , rhs_ (rhs_t (array))
00488 {
00489 }
00490
00491 template <typename array_t>
00492 mx_sub (const array_t &array, const rhs_t &rhs)
00493 : lhs_ (lhs_t (array))
00494 , rhs_ (rhs)
00495 {
00496 }
00497
00498 value_type
00499 operator [] (size_t i) const
00500 {
00501 return lhs_[i] - rhs_[i];
00502 }
00503
00504 size_t
00505 block_size () const
00506 {
00507 return lhs_.block_size ();
00508 }
00509
00510 lhs_t lhs_;
00511 rhs_t rhs_;
00512 };
00513
00514 template <typename lhs_t, typename rhs_t>
00515 struct mx_clmn_mul
00516 {
00517 typedef typename lhs_t::value_type value_type;
00518
00519 mx_clmn_mul (const lhs_t &lhs, const rhs_t &rhs)
00520 : lhs_ (lhs)
00521 , rhs_ (rhs)
00522 {
00523 }
00524
00525 value_type
00526 operator [] (size_t i) const
00527 {
00528 return lhs_[i] * rhs_[i / lhs_.block_size ()];
00529 }
00530
00531 size_t
00532 block_size () const
00533 {
00534 return lhs_.block_size ();
00535 }
00536
00537 lhs_t lhs_;
00538 rhs_t rhs_;
00539 };
00540
00541 template <typename lhs_t, typename rhs_t>
00542 struct clmn_line_mul
00543 {
00544 typedef typename lhs_t::value_type value_type;
00545
00546 clmn_line_mul (const lhs_t &lhs, const rhs_t &rhs)
00547 : lhs_ (lhs)
00548 , rhs_ (rhs)
00549 {
00550 }
00551
00552 value_type
00553 operator [] (size_t i) const
00554 {
00555 size_t bs = lhs_.block_size ();
00556 size_t ri = i / bs;
00557 size_t ci = i % bs;
00558
00559 return lhs_[ri] * rhs_[ci];
00560 }
00561
00562 size_t
00563 block_size () const
00564 {
00565 return lhs_.block_size ();
00566 }
00567
00568 const lhs_t &lhs_;
00569 const rhs_t &rhs_;
00570 };
00571 template <typename lhs_t, typename rhs_t>
00572 struct line_clmn_mul
00573 {
00574 typedef typename lhs_t::value_type value_type;
00575
00576 line_clmn_mul (const lhs_t &lhs, const rhs_t &rhs)
00577 : lhs_ (lhs)
00578 , rhs_ (rhs)
00579 {
00580 }
00581
00582 operator value_type () const
00583 {
00584 value_type res = 0;
00585 for (size_t i = 0, cnt = lhs_.block_size (); i < cnt; ++i)
00586 {
00587 res += lhs_[i] * rhs_[i];
00588 }
00589
00590 return res;
00591 }
00592
00593 lhs_t lhs_;
00594 rhs_t rhs_;
00595 };
00596
00597
00598 template <typename lhs_t, typename rhs_t>
00599 struct clmn_sub
00600 {
00601 typedef typename lhs_t::value_type value_type;
00602
00603 clmn_sub (const lhs_t &lhs, const rhs_t &rhs)
00604 : lhs_ (lhs)
00605 , rhs_ (rhs)
00606 {
00607 }
00608
00609 value_type
00610 operator [] (size_t i) const
00611 {
00612 return lhs_[i] - rhs_[i];
00613 }
00614
00615 size_t
00616 block_size () const
00617 {
00618 return lhs_.block_size ();
00619 }
00620
00621 lhs_t lhs_;
00622 rhs_t rhs_;
00623 };
00624
00625 template <typename array_t_>
00626 struct mx_scalar_mul
00627 {
00628 typedef array_t_ array_t;
00629 typedef typename array_t::value_type value_type;
00630 typedef mx_scalar_mul <array_t> this_t;
00631
00632 mx_scalar_mul (const array_t &lhs, value_type rhs, size_t size)
00633 : lhs_ (lhs)
00634 , rhs_ (rhs)
00635 , block_size_ (size * size)
00636 {
00637 BS_ASSERT (block_size_ <= 9) (block_size_);
00638 }
00639
00640 value_type
00641 operator [] (size_t i) const
00642 {
00643 return lhs_[i] * rhs_;
00644 }
00645
00646 size_t
00647 block_size () const
00648 {
00649 return block_size_;
00650 }
00651
00652 array_t lhs_;
00653 value_type rhs_;
00654 size_t block_size_;
00655 };
00656 template <typename array_type>
00657 struct clmn_scalar_mul
00658 {
00659 typedef array_type array_t;
00660 typedef typename array_t::value_type value_type;
00661 typedef clmn_scalar_mul <array_t> this_t;
00662
00663 clmn_scalar_mul (const array_t &lhs, value_type rhs, size_t size)
00664 : lhs_ (lhs)
00665 , rhs_ (rhs)
00666 , block_size_ (size)
00667 {
00668 BS_ASSERT (block_size_ <= 3) (block_size_);
00669 }
00670
00671 value_type
00672 operator [] (size_t i) const
00673 {
00674 BS_ASSERT (i < block_size_);
00675 return lhs_[i] * rhs_;
00676 }
00677
00678 size_t
00679 block_size () const
00680 {
00681 return block_size_;
00682 }
00683
00684 const array_t &lhs_;
00685 value_type rhs_;
00686 size_t block_size_;
00687 };
00688
00689 template <typename lhs_t, typename rhs_t>
00690 struct line_mul
00691 {
00692 typedef typename lhs_t::value_type value_type;
00693
00694 line_mul (const lhs_t &lhs, const rhs_t &rhs)
00695 : lhs_ (lhs)
00696 , rhs_ (rhs)
00697 {
00698 }
00699
00700 value_type
00701 operator [] (size_t i) const
00702 {
00703 return lhs_[i] * rhs_[i];
00704 }
00705
00706 size_t
00707 block_size () const
00708 {
00709 return lhs_.block_size ();
00710 }
00711
00712 lhs_t lhs_;
00713 rhs_t rhs_;
00714 };
00715 template <typename lhs_t, typename rhs_t>
00716 struct line_sub
00717 {
00718 typedef typename lhs_t::value_type value_type;
00719
00720 line_sub (const lhs_t &lhs, const rhs_t &rhs)
00721 : lhs_ (lhs)
00722 , rhs_ (rhs)
00723 {
00724 }
00725
00726 value_type
00727 operator [] (size_t i) const
00728 {
00729 return lhs_[i] - rhs_[i];
00730 }
00731
00732 size_t
00733 block_size () const
00734 {
00735 return lhs_.block_size ();
00736 }
00737
00738 lhs_t lhs_;
00739 rhs_t rhs_;
00740 };
00741
00742
00743 template <typename array_t_>
00744 struct mx_inverse
00745 {
00746 typedef array_t_ array_t;
00747 typedef typename array_t::value_type value_type;
00748 typedef mx_inverse <array_t> this_t;
00749
00750 mx_inverse (const array_t &mx, size_t size)
00751 : mx_ (mx)
00752 , block_size_ (size * size)
00753 {
00754 BS_ASSERT (block_size_ <= 9) (block_size_);
00755 calc_inverse_matrix (block_size_, mx_);
00756 }
00757
00758 value_type
00759 operator [] (size_t i) const
00760 {
00761 return mx_[i];
00762 }
00763
00764 size_t
00765 block_size () const
00766 {
00767 return block_size_;
00768 }
00769
00770 array_t mx_;
00771 size_t block_size_;
00772 };
00773
00775 template <typename lhs_t, typename rhs_t>
00776 mx_op <mx_mul <lhs_t, rhs_t> >
00777 operator* (const mx_op <lhs_t> &lhs, const mx_op <rhs_t> &rhs)
00778 {
00779 return mx_op <mx_mul <lhs_t, rhs_t> > (mx_mul <lhs_t, rhs_t> (lhs.mx_op_, rhs.mx_op_));
00780 }
00781 template <typename lhs_t, typename array_t>
00782 mx_op <mx_mul <lhs_t, mx_holder <array_t> > >
00783 operator* (const mx_op <lhs_t> &lhs, const mx_holder <array_t> &rhs)
00784 {
00785 return mx_op <mx_mul <lhs_t, mx_holder <array_t> > > (mx_mul <lhs_t, mx_holder <array_t> > (lhs.mx_op_, rhs));
00786 }
00787 template <typename array_t, typename rhs_t>
00788 mx_op <mx_mul <mx_holder <array_t>, rhs_t> >
00789 operator* (const mx_holder <array_t> &lhs, const mx_op <rhs_t> &rhs)
00790 {
00791 return mx_op <mx_mul <mx_holder <array_t>, rhs_t> > (mx_mul <mx_holder <array_t>, rhs_t> (lhs, rhs.mx_op_));
00792 }
00793 template <typename array_t, typename rhs_t>
00794 mx_op <mx_sub <mx_holder <array_t>, rhs_t> >
00795 operator- (const mx_holder <array_t> &lhs, const mx_op <rhs_t> &rhs)
00796 {
00797 return mx_op <mx_sub <mx_holder <array_t>, rhs_t> > (mx_sub <mx_holder <array_t>, rhs_t> (lhs, rhs.mx_op_));
00798 }
00799 template <typename lhs_t, typename array_t>
00800 mx_op <mx_sub <lhs_t, mx_holder <array_t> > >
00801 operator- (const mx_op <lhs_t> &lhs, const mx_holder <array_t> &rhs)
00802 {
00803 return mx_op <mx_sub <lhs_t, mx_holder <array_t> > > (mx_sub <lhs_t, mx_holder <array_t> > (lhs.mx_op_, rhs));
00804 }
00805 template <typename lhs_t, typename rhs_t>
00806 mx_op <mx_sub <lhs_t, rhs_t> >
00807 operator- (const mx_op <lhs_t> &lhs, const mx_op <rhs_t> &rhs)
00808 {
00809 return mx_op <mx_sub <lhs_t, rhs_t> > (mx_sub <lhs_t, rhs_t> (lhs.mx_op_, rhs.mx_op_));
00810 }
00811
00812 template <typename lhs_t, typename rhs_t>
00813 mx_op <clmn_line_mul <clmn_holder <lhs_t>, line_holder <rhs_t> > >
00814 operator* (const clmn_holder <lhs_t> &lhs, const line_holder <rhs_t> &rhs)
00815 {
00816 return mx_op <clmn_line_mul <clmn_holder <lhs_t>, line_holder <rhs_t> > > (clmn_line_mul <clmn_holder <lhs_t>, line_holder <rhs_t> > (lhs, rhs));
00817 }
00818 template <typename lhs_t, typename rhs_t>
00819 mx_op <clmn_line_mul <clmn_holder <lhs_t>, line_holder <rhs_t, const_unsafe_trait> > >
00820 operator* (const clmn_holder <lhs_t> &lhs, const line_holder <rhs_t, const_unsafe_trait> &rhs)
00821 {
00822 return mx_op <clmn_line_mul <clmn_holder <lhs_t>, line_holder <rhs_t, const_unsafe_trait> > > (clmn_line_mul <clmn_holder <lhs_t>, line_holder <rhs_t, const_unsafe_trait> > (lhs, rhs));
00823 }
00824 template <typename lhs_t, typename rhs_t>
00825 mx_op <clmn_line_mul <lhs_t, line_holder <rhs_t> > >
00826 operator* (const clmn_op <lhs_t> &lhs, line_holder <rhs_t> &rhs)
00827 {
00828 return mx_op <clmn_line_mul <lhs_t, line_holder <rhs_t> > > (clmn_line_mul <lhs_t, line_holder <rhs_t> > (lhs.clmn_op_, rhs));
00829 }
00830 template <typename lhs_t, typename rhs_t>
00831 line_op <line_mul <line_holder <lhs_t>, line_holder <rhs_t, const_unsafe_trait> > >
00832 operator* (const line_holder <lhs_t> &lhs, const line_holder <rhs_t, const_unsafe_trait> &rhs)
00833 {
00834 return line_op <line_mul <line_holder <lhs_t>, line_holder <rhs_t, const_unsafe_trait> > > (line_mul <line_holder <lhs_t>, line_holder <rhs_t, const_unsafe_trait> > (lhs, rhs));
00835 }
00836 template <typename lhs_t, typename lhs_trait_t, typename rhs_t, typename rhs_trait_t>
00837 scalar_op <line_clmn_mul <line_holder <lhs_t, lhs_trait_t>, clmn_holder <rhs_t, rhs_trait_t> > >
00838 operator* (const line_holder <lhs_t, lhs_trait_t> &lhs, const clmn_holder <rhs_t, rhs_trait_t> &rhs)
00839 {
00840 return scalar_op <line_clmn_mul <line_holder <lhs_t, lhs_trait_t>, clmn_holder <rhs_t, rhs_trait_t> > > (line_clmn_mul <line_holder <lhs_t, lhs_trait_t>, clmn_holder <rhs_t, rhs_trait_t> > (lhs, rhs));
00841 }
00842 template <typename lhs_t, typename rhs_t, typename rhs_trait_t>
00843 scalar_op <line_clmn_mul <lhs_t, clmn_holder <rhs_t, rhs_trait_t> > >
00844 operator* (const line_op <lhs_t> &lhs, const clmn_holder <rhs_t, rhs_trait_t> &rhs)
00845 {
00846 return scalar_op <line_clmn_mul <lhs_t, clmn_holder <rhs_t, rhs_trait_t> > > (line_clmn_mul <lhs_t, clmn_holder <rhs_t, rhs_trait_t> > (lhs.line_op_, rhs));
00847 }
00848 template <typename lhs_t, typename rhs_t>
00849 line_op <line_mul <lhs_t, rhs_t> >
00850 operator* (const line_op <lhs_t> &lhs, const line_op <rhs_t> &rhs)
00851 {
00852 return line_op <line_mul <lhs_t, rhs_t> > (line_mul <lhs_t, rhs_t> (lhs.line_op_, rhs.line_op_));
00853 }
00854 template <typename lhs_t, typename rhs_t, typename rhs_trait_t>
00855 line_op <line_mul <lhs_t, line_holder <rhs_t, rhs_trait_t> > >
00856 operator* (const line_op <lhs_t> &lhs, const line_holder <rhs_t, rhs_trait_t> &rhs)
00857 {
00858 return line_op <line_mul <lhs_t, line_holder <rhs_t, rhs_trait_t> > > (line_mul <lhs_t, line_holder <rhs_t, rhs_trait_t> > (lhs.line_op_, rhs));
00859 }
00860 template <typename lhs_t, typename lhs_trait_t, typename rhs_t>
00861 line_op <line_sub <line_holder <lhs_t, lhs_trait_t>, rhs_t> >
00862 operator- (const line_holder <lhs_t, lhs_trait_t> &lhs, const line_op <rhs_t> &rhs)
00863 {
00864 return line_op <line_sub <line_holder <lhs_t, lhs_trait_t>, rhs_t> > (line_sub <line_holder <lhs_t, lhs_trait_t>, rhs_t> (lhs, rhs.line_op_));
00865 }
00866 template <typename lhs_t, typename rhs_t>
00867 line_op <line_sub <lhs_t, rhs_t> >
00868 operator- (const line_op <lhs_t> &lhs, const line_op <rhs_t> &rhs)
00869 {
00870 return line_op <line_sub <lhs_t, rhs_t> > (line_sub <lhs_t, rhs_t> (lhs.line_op_, rhs.line_op_));
00871 }
00872 template <typename array_t>
00873 clmn_op <mx_clmn_mul <mx_holder <array_t>, clmn_holder <array_t> > >
00874 operator* (const mx_holder <array_t> &mx, const clmn_holder<array_t> &column)
00875 {
00876 return clmn_op <mx_clmn_mul <mx_holder <array_t>, clmn_holder <array_t> > > (mx_clmn_mul <mx_holder <array_t>, clmn_holder <array_t> > (mx, column));
00877 }
00878 template <typename lhs_t, typename array_t>
00879 clmn_op <mx_clmn_mul <lhs_t, clmn_holder <array_t> > >
00880 operator* (const mx_op <lhs_t> &lhs, const clmn_holder <array_t> &column)
00881 {
00882 return clmn_op <mx_clmn_mul <lhs_t, clmn_holder <array_t> > > (mx_clmn_mul <lhs_t, clmn_holder <array_t> > (lhs.mx_op_, column));
00883 }
00884
00885 template <typename lhs_t, typename rhs_t>
00886 clmn_op <clmn_sub <lhs_t, rhs_t> >
00887 operator- (const clmn_op <lhs_t> &lhs, const clmn_op <rhs_t> &rhs)
00888 {
00889 return clmn_op <clmn_sub <lhs_t, rhs_t> > (clmn_sub <lhs_t, rhs_t> (lhs.clmn_op_, rhs.clmn_op_));
00890 }
00891 template <typename lhs_t, typename lhs_trait_t, typename rhs_t, typename rhs_trait_t>
00892 clmn_op <clmn_sub <clmn_holder <lhs_t, lhs_trait_t>, clmn_holder <rhs_t, rhs_trait_t> > >
00893 operator- (const clmn_holder <lhs_t, lhs_trait_t> &lhs, const clmn_holder <rhs_t, rhs_trait_t> &rhs)
00894 {
00895 return clmn_op <clmn_sub <clmn_holder <lhs_t, lhs_trait_t>, clmn_holder <rhs_t, rhs_trait_t> > > (clmn_sub <clmn_holder <lhs_t, lhs_trait_t>, clmn_holder <rhs_t, rhs_trait_t> > (lhs, rhs));
00896 }
00897 template <typename lhs_t, typename lhs_trait_t, typename rhs_t>
00898 clmn_op <clmn_sub <clmn_holder <lhs_t, lhs_trait_t>, rhs_t> >
00899 operator- (const clmn_holder <lhs_t, lhs_trait_t> &lhs, const clmn_op <rhs_t> &rhs)
00900 {
00901 return clmn_op <clmn_sub <clmn_holder <lhs_t, lhs_trait_t>, rhs_t> > (clmn_sub <clmn_holder <lhs_t, lhs_trait_t>, rhs_t> (lhs, rhs.clmn_op_));
00902 }
00903
00904 template <typename mx_t>
00905 mx_op <mx_scalar_mul <typename mx_t::array_t> >
00906 operator* (const mx_t &mx, typename mx_t::value_type scalar)
00907 {
00908 return mx_op <mx_scalar_mul <typename mx_t::array_t> > (mx_scalar_mul <typename mx_t::array_t> (mx.array_, scalar, mx.block_size_));
00909 }
00910 template <typename lhs_t>
00911 mx_op <mx_scalar_mul <lhs_t> >
00912 operator* (const mx_op <lhs_t> &mx, typename lhs_t::value_type scalar)
00913 {
00914 return mx_op <mx_scalar_mul <lhs_t> > (mx_scalar_mul <lhs_t> (mx.mx_op_, scalar, (size_t)mx.block_size ()));
00915 }
00916 template <typename array_t>
00917 clmn_op <clmn_scalar_mul <array_t> >
00918 operator* (const clmn_holder <array_t> &clmn, typename array_t::value_type scalar)
00919 {
00920 return clmn_op <clmn_scalar_mul <array_t> > (clmn_scalar_mul <array_t> (clmn.array_, scalar, clmn.block_size_));
00921 }
00922 template <typename lhs_t>
00923 clmn_op <clmn_scalar_mul <lhs_t> >
00924 operator* (const clmn_op <lhs_t> &clmn, typename lhs_t::value_type scalar)
00925 {
00926 return clmn_op <clmn_scalar_mul <lhs_t> > (clmn_scalar_mul <lhs_t> (clmn.clmn_op_, scalar, (size_t)clmn.block_size ()));
00927 }
00928 template <typename array_t>
00929 clmn_op <clmn_scalar_mul <array_t> >
00930 operator* (typename array_t::value_type scalar, const clmn_holder <array_t> &clmn)
00931 {
00932 return clmn_op <clmn_scalar_mul <array_t> > (clmn_scalar_mul <array_t> (clmn.array_, scalar, clmn.block_size_));
00933 }
00934 template <typename lhs_t, typename rhs_t, typename rhs_trait_t>
00935 line_op <clmn_scalar_mul <rhs_t> >
00936 operator* (lhs_t scalar, const line_holder <rhs_t, rhs_trait_t> &rhs)
00937 {
00938 return line_op <clmn_scalar_mul <rhs_t> > (clmn_scalar_mul <rhs_t> (rhs.array_, scalar, rhs.block_size ()));
00939 }
00940 template <typename lhs_t, typename lhs_trait_t>
00941 line_op <clmn_scalar_mul <lhs_t> >
00942 operator* (const line_holder <lhs_t, lhs_trait_t> &lhs, typename lhs_t::value_type scalar)
00943 {
00944 return line_op <clmn_scalar_mul <lhs_t> > (clmn_scalar_mul <lhs_t> (lhs.array_, scalar, lhs.block_size ()));
00945 }
00946 template <typename item_t, typename rhs_t>
00947 item_t
00948 operator- (item_t lhs, const scalar_op <rhs_t> &rhs)
00949 {
00950 return lhs - static_cast <item_t> (rhs);
00951 }
00952
00953 template <typename mx_t>
00954 mx_op <mx_inverse <typename mx_t::array_t> >
00955 inverse (const mx_t &mx)
00956 {
00957 return mx_op <mx_inverse <typename mx_t::array_t> > (mx_inverse <typename mx_t::array_t> (mx.array_, mx.block_size_));
00958 }
00959
00960 }
00961
00962
00963 #endif // #ifndef BS_EXPRESSION_TEMPLATES_MATRIX_ARITHEMTIC_H_
00964