gps_pvt 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -514,6 +514,108 @@ struct Array2D_Operator_Multiply_by_Scalar;
514
514
  template <class LHS_T, class RHS_T, bool rhs_positive>
515
515
  struct Array2D_Operator_Add;
516
516
 
517
+ template <class LHS_T, class RHS_T>
518
+ struct Array2D_Operator_EntrywiseMultiply;
519
+
520
+ template <class LHS_T, class RHS_T, bool rhs_horizontal>
521
+ struct Array2D_Operator_Stack;
522
+
523
+
524
+ template <class T>
525
+ struct MatrixValue_Special;
526
+
527
+ template <class T>
528
+ struct MatrixValue {
529
+ template <class T2>
530
+ struct check_complex_t {
531
+ static const bool hit = false;
532
+ typedef T2 r_t;
533
+ typedef Complex<T2> c_t;
534
+ };
535
+ template <class T2>
536
+ struct check_complex_t<Complex<T2> > {
537
+ static const bool hit = true;
538
+ typedef T2 r_t;
539
+ typedef Complex<T2> c_t;
540
+ };
541
+ static const bool is_complex = check_complex_t<T>::hit;
542
+ typedef typename check_complex_t<T>::r_t real_t;
543
+ typedef typename check_complex_t<T>::c_t complex_t;
544
+ static real_t get_real(const real_t &v) noexcept {
545
+ return v;
546
+ }
547
+ static real_t get_real(const complex_t &v) noexcept {
548
+ return v.real();
549
+ }
550
+ static complex_t get_sqrt(const real_t &v) noexcept {
551
+ return (v >= 0) ? complex_t(std::sqrt(v)) : complex_t(0, std::sqrt(-v));
552
+ }
553
+ static complex_t get_sqrt(const complex_t &v) noexcept {
554
+ return v.sqrt();
555
+ }
556
+ static real_t get_abs(const real_t &v) noexcept {
557
+ return std::abs(v);
558
+ }
559
+ static real_t get_abs(const complex_t &v) noexcept {
560
+ return v.abs();
561
+ }
562
+ static real_t get_abs2(const real_t &v) noexcept {
563
+ return v * v;
564
+ }
565
+ static real_t get_abs2(const complex_t &v) noexcept {
566
+ return v.abs2();
567
+ }
568
+ static bool is_nan_or_infinite(const real_t &v) noexcept {
569
+ #if defined(_MSC_VER)
570
+ return _isnan(v) || !_finite(v);
571
+ #else
572
+ return std::isnan(v) || !std::isfinite(v);
573
+ #endif
574
+ }
575
+ static bool is_nan_or_infinite(const complex_t &v) noexcept {
576
+ return is_nan_or_infinite(v.real()) || is_nan_or_infinite(v.imaginary());
577
+ }
578
+
579
+ static typename MatrixValue_Special<T>::zero_t zero; // System-wise zero
580
+ };
581
+
582
+ template <class T>
583
+ struct MatrixValue_Special {
584
+ typedef MatrixValue<T> v_t;
585
+ struct wide_zero_t {
586
+ typename v_t::real_t width, width_abs2;
587
+ wide_zero_t(const typename v_t::real_t &width_)
588
+ : width(v_t::get_abs(width_)), width_abs2(v_t::get_abs2(width_)) {}
589
+ wide_zero_t &operator=(const typename v_t::real_t &width_) {
590
+ width = v_t::get_abs(width_);
591
+ width_abs2 = v_t::get_abs2(width_);
592
+ return *this;
593
+ }
594
+ bool operator==(const typename v_t::real_t &v) const noexcept {return v_t::get_abs(v) <= width;}
595
+ bool operator==(const typename v_t::complex_t &v) const noexcept {return v_t::get_abs2(v) <= width_abs2;}
596
+ bool operator!=(const T &v) const noexcept {return !operator==(v);}
597
+ };
598
+ template <
599
+ bool is_integer = std::numeric_limits<T>::is_integer,
600
+ class U = void>
601
+ struct zero_selector_t {
602
+ typedef wide_zero_t res_t;
603
+ };
604
+ template <class U>
605
+ struct zero_selector_t<true, U> {
606
+ // When T is a kind of integer types, exact equalness is easiliy achievable.
607
+ typedef T res_t;
608
+ };
609
+ typedef typename zero_selector_t<>::res_t zero_t;
610
+ };
611
+
612
+ template <class T>
613
+ typename MatrixValue_Special<T>::zero_t MatrixValue<T>::zero = 0;
614
+
615
+ #if 0 // If exact zero is required, then specialization resolves it.
616
+ template <>
617
+ struct MatrixValue_Special<double> {typedef double zero_t;};
618
+ #endif
517
619
 
518
620
  template <class BaseView = void>
519
621
  struct MatrixViewBase {
@@ -1137,12 +1239,12 @@ struct MatrixBuilder_ViewTransformerBase<
1137
1239
  typename MatrixViewBuilder<
1138
1240
  typename view_builder_t::loop_t>::offset_t>::size_variable_t> circular_t;
1139
1241
 
1140
- template <class T2 = T>
1242
+ template <bool is_complex = MatrixValue<T>::is_complex, class U = void>
1141
1243
  struct check_complex_t {
1142
1244
  typedef MatrixT<T, Array2D_Type, ViewType> conjugate_t;
1143
1245
  };
1144
- template <class T2>
1145
- struct check_complex_t<Complex<T2> > {
1246
+ template <class U>
1247
+ struct check_complex_t<true, U> {
1146
1248
  typedef MatrixT<T, Array2D_Type, typename view_builder_t::conjugate_t> conjugate_t;
1147
1249
  };
1148
1250
  typedef typename check_complex_t<>::conjugate_t conjugate_t;
@@ -1242,6 +1344,7 @@ class Matrix_Frozen {
1242
1344
  typedef ViewType view_t;
1243
1345
  typedef Matrix_Frozen<T, Array2D_Type, ViewType> self_t;
1244
1346
  typedef self_t frozen_t;
1347
+ typedef MatrixValue<T> value_t;
1245
1348
 
1246
1349
  typedef MatrixBuilder<self_t> builder_t;
1247
1350
 
@@ -1314,29 +1417,39 @@ class Matrix_Frozen {
1314
1417
  typedef std::random_access_iterator_tag iterator_category;
1315
1418
  protected:
1316
1419
  difference_type idx;
1317
- unsigned int row(const self_t &mat) const {
1318
- return (mat.columns() > 0) ? (idx / mat.columns()) : 0;
1319
- }
1320
- unsigned int column(const self_t &mat) const {
1321
- return (mat.columns() > 0) ? (idx % mat.columns()) : idx;
1322
- }
1420
+ unsigned int rows, columns;
1421
+ unsigned int r, c;
1323
1422
  public:
1423
+ const unsigned int &row() const {return r;}
1424
+ const unsigned int &column() const {return c;}
1425
+
1324
1426
  // @see http://www.cplusplus.com/reference/iterator/
1325
1427
  // required for input iterator
1326
- iterator_base_t(const difference_type &idx_ = 0) : idx(idx_) {}
1327
- self_type &operator++() {++idx; return static_cast<self_type &>(*this);}
1328
- self_type operator++(int) {self_type res(static_cast<self_type &>(*this)); ++idx; return res;}
1428
+ iterator_base_t(const self_t &mat, const difference_type &idx_ = 0)
1429
+ : idx(idx_), rows(mat.rows()), columns(mat.columns()), r(0), c(0) {}
1430
+ iterator_base_t()
1431
+ : idx(0), rows(0), columns(0), r(0), c(0) {}
1432
+ self_type &operator++() {return static_cast<self_type &>(*this).operator+=(1);}
1433
+ self_type operator++(int) {
1434
+ self_type res(static_cast<self_type &>(*this));
1435
+ static_cast<self_type &>(*this).operator++();
1436
+ return res;
1437
+ }
1329
1438
  friend bool operator==(const self_type &lhs, const self_type &rhs) {
1330
1439
  return lhs.idx == rhs.idx;
1331
1440
  }
1332
1441
  friend bool operator!=(const self_type &lhs, const self_type &rhs) {return !(lhs == rhs);}
1333
1442
 
1334
1443
  // required for forward iterator
1335
- //iterator_t() : mat(), idx(0) {}
1444
+ //iterator_t() // ctor.
1336
1445
 
1337
1446
  // required for bidirectional iterator
1338
- self_type &operator--() {--idx; return static_cast<self_type &>(*this);}
1339
- self_type operator--(int) {self_type res(static_cast<self_type &>(*this)); --idx; return res;}
1447
+ self_type &operator--() {return static_cast<self_type &>(*this).operator+=(-1);}
1448
+ self_type operator--(int) {
1449
+ self_type res(static_cast<self_type &>(*this));
1450
+ static_cast<self_type &>(*this).operator--();
1451
+ return res;
1452
+ }
1340
1453
 
1341
1454
  // required for random access iterator
1342
1455
  friend bool operator<(const self_type &lhs, const self_type &rhs){
@@ -1375,37 +1488,333 @@ class Matrix_Frozen {
1375
1488
  friend difference_type operator-(const self_type &lhs, const self_type &rhs){
1376
1489
  return lhs.idx - rhs.idx;
1377
1490
  }
1491
+
1492
+ self_type &head() {return static_cast<self_type &>(*this) -= idx;}
1493
+ self_type &tail() {return static_cast<self_type &>(*this) += (rows * columns - idx);}
1378
1494
  };
1379
1495
 
1380
- class const_iterator : public iterator_base_t<const_iterator> {
1496
+ struct iterator_mapper_t {
1497
+ template <class impl_t>
1498
+ class all_t : public iterator_base_t<impl_t> {
1499
+ protected:
1500
+ typedef iterator_base_t<impl_t> base_t;
1501
+ typename base_t::difference_type idx_max;
1502
+ void update(){
1503
+ if(base_t::idx <= 0){
1504
+ base_t::r = base_t::c = 0;
1505
+ }else if(base_t::idx >= idx_max){
1506
+ base_t::r = base_t::rows;
1507
+ base_t::c = 0;
1508
+ }else{
1509
+ std::div_t rc(std::div(base_t::idx, base_t::columns));
1510
+ base_t::r = (unsigned int)rc.quot;
1511
+ base_t::c = (unsigned int)rc.rem;
1512
+ }
1513
+ }
1514
+ public:
1515
+ all_t(const self_t &mat, const typename base_t::difference_type &idx_ = 0)
1516
+ : base_t(mat, idx_),
1517
+ idx_max((typename base_t::difference_type)(base_t::rows * base_t::columns)) {
1518
+ update();
1519
+ }
1520
+ all_t()
1521
+ : base_t(),
1522
+ idx_max((typename base_t::difference_type)(base_t::rows * base_t::columns)) {
1523
+ update();
1524
+ }
1525
+ impl_t &operator+=(const typename base_t::difference_type &n){
1526
+ base_t::operator+=(n);
1527
+ update();
1528
+ return static_cast<impl_t &>(*this);
1529
+ }
1530
+ using base_t::operator++;
1531
+ impl_t &operator++() {
1532
+ if(base_t::r < base_t::rows){
1533
+ if(++base_t::c == base_t::columns){
1534
+ ++base_t::r;
1535
+ base_t::c = 0;
1536
+ }
1537
+ }
1538
+ ++base_t::idx;
1539
+ return static_cast<impl_t &>(*this);
1540
+ }
1541
+ using base_t::operator--;
1542
+ impl_t &operator--() {
1543
+ if(base_t::idx-- > 0){
1544
+ if(base_t::c == 0){
1545
+ --base_t::r;
1546
+ base_t::c = base_t::columns;
1547
+ }
1548
+ --base_t::c;
1549
+ }
1550
+ return static_cast<impl_t &>(*this);
1551
+ }
1552
+ };
1553
+ template <class impl_t>
1554
+ class diagonal_t : public iterator_base_t<impl_t> {
1555
+ protected:
1556
+ typedef iterator_base_t<impl_t> base_t;
1557
+ typename base_t::difference_type idx_max;
1558
+ void update(){
1559
+ if(base_t::idx <= 0){
1560
+ base_t::idx = 0;
1561
+ }else if(base_t::idx >= idx_max){
1562
+ base_t::idx = idx_max;
1563
+ }
1564
+ base_t::r = base_t::c = base_t::idx;
1565
+ }
1566
+ public:
1567
+ diagonal_t(const self_t &mat, const typename base_t::difference_type &idx_ = 0)
1568
+ : base_t(mat, idx_),
1569
+ idx_max((typename base_t::difference_type)(
1570
+ (base_t::rows >= base_t::columns) ? base_t::columns : base_t::rows)) {
1571
+ update();
1572
+ }
1573
+ diagonal_t()
1574
+ : base_t(),
1575
+ idx_max((typename base_t::difference_type)(
1576
+ (base_t::rows >= base_t::columns) ? base_t::columns : base_t::rows)) {
1577
+ update();
1578
+ }
1579
+ impl_t &operator+=(const typename base_t::difference_type &n){
1580
+ base_t::operator+=(n);
1581
+ update();
1582
+ return static_cast<impl_t &>(*this);
1583
+ }
1584
+ impl_t &tail() {return static_cast<impl_t &>(*this) += (idx_max - base_t::idx);}
1585
+ };
1586
+ template <class impl_t>
1587
+ class offdiagonal_t : public iterator_base_t<impl_t> {
1588
+ protected:
1589
+ typedef iterator_base_t<impl_t> base_t;
1590
+ typename base_t::difference_type idx_max, offset;
1591
+ void setup(){
1592
+ idx_max = (typename base_t::difference_type)(base_t::rows * base_t::columns);
1593
+ if(idx_max == 0){
1594
+ offset = 0;
1595
+ }else if(base_t::rows >= base_t::columns){
1596
+ idx_max -= base_t::columns;
1597
+ offset = base_t::columns * (base_t::columns - 1);
1598
+ }else{
1599
+ idx_max -= base_t::rows;
1600
+ offset = idx_max;
1601
+ }
1602
+ }
1603
+ void update(){
1604
+ if(base_t::idx <= 0){
1605
+ base_t::idx = 0;
1606
+ }else if(base_t::idx >= idx_max){
1607
+ base_t::idx = idx_max;
1608
+ }
1609
+ if(base_t::idx >= offset){ // on row having no diagonal element
1610
+ std::div_t rc(std::div(base_t::idx - offset, base_t::columns));
1611
+ base_t::r = base_t::columns + (unsigned int)rc.quot;
1612
+ base_t::c = (unsigned int)rc.rem;
1613
+ }else{ // on row having a diagonal element
1614
+ std::div_t rc(std::div(base_t::idx, base_t::columns - 1));
1615
+ base_t::r = (unsigned int)rc.quot;
1616
+ base_t::c = (unsigned int)rc.rem;
1617
+ if(base_t::c >= base_t::r){++base_t::c;}
1618
+ }
1619
+ }
1620
+ public:
1621
+ offdiagonal_t(const self_t &mat, const typename base_t::difference_type &idx_ = 0)
1622
+ : base_t(mat, idx_) {
1623
+ setup();
1624
+ update();
1625
+ }
1626
+ offdiagonal_t() : base_t() {
1627
+ setup();
1628
+ update();
1629
+ }
1630
+ impl_t &operator+=(const typename base_t::difference_type &n){
1631
+ base_t::operator+=(n);
1632
+ update();
1633
+ return static_cast<impl_t &>(*this);
1634
+ }
1635
+ impl_t &tail() {return static_cast<impl_t &>(*this) += (idx_max - base_t::idx);}
1636
+ };
1637
+ template <bool is_lower, int right_shift = 0>
1638
+ struct triangular_t {
1639
+ template <class impl_t>
1640
+ class mapper_t : public iterator_base_t<impl_t> {
1641
+ protected:
1642
+ typedef iterator_base_t<impl_t> base_t;
1643
+ typename base_t::difference_type idx_max, offset1, offset2;
1644
+ void setup() {
1645
+ int shift(is_lower ? right_shift : -right_shift),
1646
+ len1((int)(is_lower ? base_t::rows : base_t::columns)),
1647
+ len2((int)(is_lower ? base_t::columns : base_t::rows));
1648
+ // calculation concept: (big triangle) - (2 small triangles if nesccesary)
1649
+ idx_max = offset1 = offset2 = 0;
1650
+ int triangle_len(shift + len1);
1651
+ if(triangle_len < 0){return;}
1652
+ if(shift > 0){ // exclude top left triangle
1653
+ int area_tl((shift + 1) * shift / 2);
1654
+ idx_max -= area_tl;
1655
+ if(is_lower){offset1 = area_tl;}
1656
+ else{offset2 = -shift * len1;}
1657
+ }
1658
+ idx_max += (triangle_len + 1) * triangle_len / 2; // add main triangle
1659
+ if(triangle_len > len2){ // exclude bottom right triangle
1660
+ int len_br(triangle_len - len2);
1661
+ int area_br((len_br + 1) * len_br / 2);
1662
+ idx_max -= area_br;
1663
+ if(is_lower){offset2 = -len_br * len2;}
1664
+ else{offset1 = area_br;}
1665
+ }
1666
+ offset2 += idx_max;
1667
+ }
1668
+ void update(){
1669
+ int idx(base_t::idx);
1670
+ if(idx < 0){
1671
+ idx = 0;
1672
+ }else if(idx > idx_max){
1673
+ idx = idx_max;
1674
+ }
1675
+ if(!is_lower){idx = idx_max - idx - 1;}
1676
+ if(idx <= offset2){ // in triangle
1677
+ idx += (offset1 + 1);
1678
+ int r_offset(std::ceil((std::sqrt((double)(8 * idx + 1)) - 1) / 2));
1679
+ base_t::r = r_offset;
1680
+ base_t::c = base_t::r + idx - (r_offset * (r_offset + 1) / 2);
1681
+ if(is_lower){
1682
+ base_t::r -= (right_shift + 1);
1683
+ base_t::c -= 1;
1684
+ }else{
1685
+ base_t::r = (base_t::columns - right_shift) - base_t::r;
1686
+ base_t::c = base_t::columns - base_t::c;
1687
+ }
1688
+ }else{ // in rectangle
1689
+ std::div_t rc(std::div(idx - offset2, base_t::columns));
1690
+ base_t::r = (unsigned int)rc.quot;
1691
+ base_t::c = (unsigned int)rc.rem;
1692
+ if(is_lower){
1693
+ base_t::r += (base_t::columns - right_shift);
1694
+ }else{
1695
+ base_t::r = -right_shift - base_t::r - 1;
1696
+ base_t::c = base_t::columns - base_t::c - 1;
1697
+ }
1698
+ }
1699
+ }
1700
+ public:
1701
+ mapper_t(const self_t &mat, const typename base_t::difference_type &idx_ = 0)
1702
+ : base_t(mat, idx_) {
1703
+ setup();
1704
+ update();
1705
+ }
1706
+ mapper_t() : base_t() {
1707
+ setup();
1708
+ update();
1709
+ }
1710
+ impl_t &operator+=(const typename base_t::difference_type &n){
1711
+ base_t::operator+=(n);
1712
+ update();
1713
+ return static_cast<impl_t &>(*this);
1714
+ }
1715
+ impl_t &tail() {return static_cast<impl_t &>(*this) += (idx_max - base_t::idx);}
1716
+ using base_t::operator++;
1717
+ impl_t &operator++() {
1718
+ if(base_t::idx++ < idx_max){
1719
+ ++base_t::c;
1720
+ if(is_lower){
1721
+ if((base_t::c == base_t::columns)
1722
+ || ((int)base_t::c == right_shift + 1 + (int)base_t::r)){
1723
+ ++base_t::r;
1724
+ base_t::c = 0;
1725
+ }
1726
+ }else{
1727
+ if(base_t::c == base_t::columns){
1728
+ ++base_t::r;
1729
+ base_t::c = ((int)base_t::r < -right_shift)
1730
+ ? 0
1731
+ : (unsigned int)(right_shift + (int)base_t::r);
1732
+ }
1733
+ }
1734
+ }
1735
+ return static_cast<impl_t &>(*this);
1736
+ }
1737
+ using base_t::operator--;
1738
+ impl_t &operator--() {
1739
+ if(base_t::idx-- > 0){
1740
+ if(is_lower){
1741
+ if(base_t::c == 0){
1742
+ base_t::c = (unsigned int)(right_shift + 1 + (int)(--base_t::r));
1743
+ if(base_t::c > base_t::columns){base_t::c = base_t::columns;}
1744
+ }
1745
+ }else{
1746
+ if((base_t::c == 0)
1747
+ || ((int)base_t::c == (right_shift + (int)base_t::r))){
1748
+ --base_t::r;
1749
+ base_t::c = base_t::columns;
1750
+ }
1751
+ }
1752
+ --base_t::c;
1753
+ }
1754
+ return static_cast<impl_t &>(*this);
1755
+ }
1756
+ };
1757
+ };
1758
+ #if defined(__cplusplus) && (__cplusplus >= 201103L)
1759
+ #define MAKE_TRIANGULAR_ALIAS(name, is_lower, right_shift) \
1760
+ template <class impl_t> using name \
1761
+ = typename triangular_t<is_lower, right_shift>::template mapper_t<impl_t>;
1762
+ #else
1763
+ #define MAKE_TRIANGULAR_ALIAS(name, is_lower, right_shift) \
1764
+ template <class impl_t> \
1765
+ struct name : public triangular_t<is_lower, right_shift>::template mapper_t<impl_t> { \
1766
+ typedef typename triangular_t<is_lower, right_shift>::template mapper_t<impl_t> base_t; \
1767
+ name(const self_t &mat, const typename base_t::difference_type &idx_ = 0) \
1768
+ : base_t(mat, idx_) {} \
1769
+ name() : base_t() {} \
1770
+ };
1771
+ #endif
1772
+ MAKE_TRIANGULAR_ALIAS(lower_triangular_t, true, 0);
1773
+ MAKE_TRIANGULAR_ALIAS(lower_triangular_offdiagonal_t, true, -1);
1774
+ MAKE_TRIANGULAR_ALIAS(upper_triangular_t, false, 0);
1775
+ MAKE_TRIANGULAR_ALIAS(upper_triangular_offdiagonal_t, false, 1);
1776
+ #undef MAKE_TRIANGULAR_ALIAS
1777
+ };
1778
+
1779
+ template <template <typename> class MapperT = iterator_base_t>
1780
+ class const_iterator_skelton_t : public MapperT<const_iterator_skelton_t<MapperT> > {
1381
1781
  public:
1382
1782
  typedef const T value_type;
1383
- typedef const T& reference;
1384
- typedef const T* pointer;
1783
+ typedef const T reference;
1784
+ struct pointer {
1785
+ reference value;
1786
+ const T *operator->() const {return &value;}
1787
+ };
1385
1788
  protected:
1386
- typedef iterator_base_t<const_iterator> base_t;
1789
+ typedef MapperT<const_iterator_skelton_t<MapperT> > base_t;
1387
1790
  self_t mat;
1388
- mutable T tmp;
1389
1791
  public:
1390
- unsigned int row() const {return base_t::row(mat);}
1391
- unsigned int column() const {return base_t::column(mat);}
1392
- reference operator*() const {
1393
- std::div_t rc(std::div(base_t::idx, mat.columns()));
1394
- return tmp = mat((unsigned int)rc.quot, (unsigned int)rc.rem);
1395
- }
1792
+ reference operator*() const {return mat(base_t::r, base_t::c);}
1396
1793
  pointer operator->() const {
1397
- return &(operator*());
1794
+ pointer p = {operator*()};
1795
+ return p;
1398
1796
  }
1399
- const_iterator(const self_t &mat_, const typename base_t::difference_type &idx_ = 0)
1400
- : base_t(idx_), mat(mat_), tmp() {}
1401
- const_iterator()
1402
- : base_t(), mat(), tmp() {}
1797
+ const_iterator_skelton_t(const self_t &mat_, const typename base_t::difference_type &idx_ = 0)
1798
+ : base_t(mat_, idx_), mat(mat_) {}
1799
+ const_iterator_skelton_t()
1800
+ : base_t(), mat() {}
1403
1801
  reference operator[](const typename base_t::difference_type &n) const {
1404
- return tmp = *((*this) + n);
1802
+ return *((*this) + n);
1405
1803
  }
1406
1804
  };
1805
+
1806
+ typedef const_iterator_skelton_t<iterator_mapper_t::template all_t> const_iterator;
1407
1807
  const_iterator begin() const {return const_iterator(*this);}
1408
- const_iterator end() const {return const_iterator(*this, rows() * columns());}
1808
+ const_iterator end() const {return const_iterator(*this).tail();}
1809
+
1810
+ template <template <typename> class MapperT>
1811
+ const_iterator_skelton_t<MapperT> begin() const {
1812
+ return const_iterator_skelton_t<MapperT>(*this);
1813
+ }
1814
+ template <template <typename> class MapperT>
1815
+ const_iterator_skelton_t<MapperT> end() const {
1816
+ return const_iterator_skelton_t<MapperT>(*this).tail();
1817
+ }
1409
1818
 
1410
1819
  /**
1411
1820
  * Copy constructor generating shallow copy linking to source matrix
@@ -1514,7 +1923,7 @@ class Matrix_Frozen {
1514
1923
  const unsigned int i_end(rows()), j_end(columns());
1515
1924
  for(unsigned int i(0); i < i_end; i++){
1516
1925
  for(unsigned int j(0); j < j_end; j++){
1517
- if((*this)(i, j) != matrix(i, j)){
1926
+ if(value_t::zero != ((*this)(i, j) - matrix(i, j))){
1518
1927
  return false;
1519
1928
  }
1520
1929
  }
@@ -1536,42 +1945,6 @@ class Matrix_Frozen {
1536
1945
  */
1537
1946
  bool isSquare() const noexcept {return rows() == columns();}
1538
1947
 
1539
- /**
1540
- * Test whether matrix is diagonal
1541
- *
1542
- * @return true when diagonal, otherwise false.
1543
- */
1544
- bool isDiagonal() const noexcept {
1545
- if(isSquare()){
1546
- const unsigned int i_end(rows()), j_end(columns());
1547
- for(unsigned int i(0); i < i_end; i++){
1548
- for(unsigned int j(i + 1); j < j_end; j++){
1549
- if(((*this)(i, j) != T(0)) || ((*this)(j, i) != T(0))){
1550
- return false;
1551
- }
1552
- }
1553
- }
1554
- return true;
1555
- }else{return false;}
1556
- }
1557
-
1558
- /**
1559
- * Test whether matrix is symmetric
1560
- *
1561
- * @return true when symmetric, otherwise false.
1562
- */
1563
- bool isSymmetric() const noexcept {
1564
- if(isSquare()){
1565
- const unsigned int i_end(rows()), j_end(columns());
1566
- for(unsigned int i(0); i < i_end; i++){
1567
- for(unsigned int j(i + 1); j < j_end; j++){
1568
- if((*this)(i, j) != (*this)(j, i)){return false;}
1569
- }
1570
- }
1571
- return true;
1572
- }else{return false;}
1573
- }
1574
-
1575
1948
  /**
1576
1949
  * Test whether size of matrices is different
1577
1950
  *
@@ -1614,25 +1987,59 @@ class Matrix_Frozen {
1614
1987
  return sum;
1615
1988
  }
1616
1989
 
1617
- /**
1618
- * Test whether matrix is LU decomposed.
1619
- * The assumption of elements is
1620
- * (0, 0)-(n-1, n-1): L matrix
1621
- * (0, n)-(n-1, 2n-1): U matrix
1622
- *
1623
- * @return true when LU, otherwise false.
1624
- */
1625
- bool isLU() const noexcept {
1626
- if(rows() * 2 != columns()){return false;}
1627
- const unsigned int i_end(rows() - 1), j_end(rows());
1628
- for(unsigned int i(0), i_U(rows()); i < i_end; i++, i_U++){
1629
- for(unsigned int j(i + 1); j < j_end; j++){
1630
- if((*this)(i, j) != T(0)){return false;} // check L
1631
- if((*this)(j, i_U) != T(0)){return false;} // check U
1990
+ protected:
1991
+ template <class T2>
1992
+ bool isEqual_Block(
1993
+ const T2 &v,
1994
+ const bool &upper_offdiagonal = true, const bool &lower_offdiagonal = false,
1995
+ const bool &diagonal = false) const {
1996
+ const unsigned int i_end(rows()), j_end(columns());
1997
+ if(upper_offdiagonal){
1998
+ for(unsigned int i(0); i < i_end; i++){
1999
+ for(unsigned int j(i + 1); j < j_end; j++){
2000
+ if(v != (*this)(i, j)){return false;}
2001
+ }
2002
+ }
2003
+ }
2004
+ if(lower_offdiagonal){
2005
+ for(unsigned int i(1); i < i_end; i++){
2006
+ for(unsigned int j(0); j < i; j++){
2007
+ if(v != (*this)(i, j)){return false;}
2008
+ }
2009
+ }
2010
+ }
2011
+ if(diagonal){
2012
+ for(unsigned int i2(0), i2_end((i_end < j_end) ? i_end : j_end); i2 < i2_end; i2++){
2013
+ if(v != (*this)(i2, i2)){return false;}
1632
2014
  }
1633
2015
  }
1634
2016
  return true;
1635
2017
  }
2018
+ public:
2019
+ /**
2020
+ * Test whether matrix is diagonal
2021
+ *
2022
+ * @return true when diagonal matrix, otherwise false.
2023
+ */
2024
+ bool isDiagonal() const noexcept {
2025
+ return isSquare() && isEqual_Block(value_t::zero, true, true);
2026
+ }
2027
+ /**
2028
+ * Test whether matrix is lower triangular
2029
+ *
2030
+ * @return true when lower triangular matrix, otherwise false.
2031
+ */
2032
+ bool isLowerTriangular() const noexcept {
2033
+ return isSquare() && isEqual_Block(value_t::zero, true, false);
2034
+ }
2035
+ /**
2036
+ * Test whether matrix is upper triangular
2037
+ *
2038
+ * @return true when upper triangular matrix, otherwise false.
2039
+ */
2040
+ bool isUpperTriangular() const noexcept {
2041
+ return isSquare() && isEqual_Block(value_t::zero, false, true);
2042
+ }
1636
2043
 
1637
2044
  typedef typename builder_t::transpose_t transpose_t;
1638
2045
  /**
@@ -1789,11 +2196,11 @@ class Matrix_Frozen {
1789
2196
  * as the same as index 1 (= 5 % 4) is selected.
1790
2197
  *
1791
2198
  * Another example; [4x3].circular(1,2,5,6) is
1792
- * 00 01 02 => 12 10 11 12 10
1793
- * 10 11 12 22 20 21 22 20
1794
- * 20 21 22 32 30 31 32 30
1795
- * 30 31 32 02 00 01 02 00
1796
- * 12 10 11 12 10
2199
+ * 00 01 02 => 12 10 11 12 10 11
2200
+ * 10 11 12 22 20 21 22 20 21
2201
+ * 20 21 22 32 30 31 32 30 31
2202
+ * 30 31 32 02 00 01 02 00 01
2203
+ * 12 10 11 12 10 11
1797
2204
  *
1798
2205
  * @param row_offset Upper row index of original matrix for circular matrix
1799
2206
  * @param column_offset Left column index of original matrix for circular matrix
@@ -1848,10 +2255,14 @@ class Matrix_Frozen {
1848
2255
 
1849
2256
 
1850
2257
  enum {
2258
+ OPERATOR_2_Generic,
1851
2259
  OPERATOR_2_Multiply_Matrix_by_Scalar,
1852
2260
  OPERATOR_2_Add_Matrix_to_Matrix,
1853
2261
  OPERATOR_2_Subtract_Matrix_from_Matrix,
1854
2262
  OPERATOR_2_Multiply_Matrix_by_Matrix,
2263
+ OPERATOR_2_Entrywise_Multiply_Matrix_by_Matrix,
2264
+ OPERATOR_2_Stack_Horizontal,
2265
+ OPERATOR_2_Stack_Vertical,
1855
2266
  OPERATOR_NONE,
1856
2267
  };
1857
2268
 
@@ -2058,6 +2469,98 @@ class Matrix_Frozen {
2058
2469
  return getScalar(matrix.rows(), scalar) - matrix;
2059
2470
  }
2060
2471
 
2472
+ template <class RHS_MatrixT>
2473
+ struct Entrywise_Multiply_Matrix_by_Matrix {
2474
+ typedef Array2D_Operator_EntrywiseMultiply<self_t, RHS_MatrixT> op_t;
2475
+ typedef Matrix_Frozen<T, Array2D_Operator<T, op_t> > mat_t;
2476
+ static mat_t generate(const self_t &mat1, const RHS_MatrixT &mat2){
2477
+ if(mat1.isDifferentSize(mat2)){throw std::invalid_argument("Incorrect size");}
2478
+ return mat_t(
2479
+ typename mat_t::storage_t(
2480
+ mat1.rows(), mat1.columns(), op_t(mat1, mat2)));
2481
+ }
2482
+ };
2483
+
2484
+ /**
2485
+ * Entrywise product of two matrices
2486
+ *
2487
+ * @param matrix Matrix to multiply
2488
+ * @return entrywise multiplied matrix
2489
+ * @throw std::invalid_argument When matrix sizes are not identical
2490
+ */
2491
+ template <class T2, class Array2D_Type2, class ViewType2>
2492
+ typename Entrywise_Multiply_Matrix_by_Matrix<Matrix_Frozen<T2, Array2D_Type2, ViewType2> >::mat_t
2493
+ entrywise_product(const Matrix_Frozen<T2, Array2D_Type2, ViewType2> &matrix) const {
2494
+ return Entrywise_Multiply_Matrix_by_Matrix<Matrix_Frozen<T2, Array2D_Type2, ViewType2> >::generate(*this, matrix);
2495
+ }
2496
+
2497
+ template <class RHS_MatrixT, bool rhs_horizontal = true>
2498
+ struct Stacked_Matrix {
2499
+ typedef Array2D_Operator_Stack<self_t, RHS_MatrixT, rhs_horizontal> op_t;
2500
+ typedef Matrix_Frozen<T, Array2D_Operator<T, op_t> > mat_t;
2501
+ static mat_t generate(const self_t &mat1, const RHS_MatrixT &mat2){
2502
+ if(rhs_horizontal ? (mat1.rows() > mat2.rows()) : (mat1.columns() > mat2.columns())){
2503
+ throw std::invalid_argument("Incorrect size");
2504
+ }
2505
+ return mat_t(
2506
+ typename mat_t::storage_t(
2507
+ mat1.rows() + (rhs_horizontal ? 0 : mat2.rows()),
2508
+ mat1.columns() + (rhs_horizontal ? mat2.columns() : 0),
2509
+ op_t(mat1, mat2)));
2510
+ }
2511
+ };
2512
+
2513
+ /**
2514
+ * Horizontal stack of two matrices
2515
+ *
2516
+ * @param matrix Matrix to stack horizontally, i.e., right side
2517
+ * @return stacked matrix
2518
+ * @throw std::invalid_argument When matrix row number is smaller
2519
+ */
2520
+ template <class T2, class Array2D_Type2, class ViewType2>
2521
+ typename Stacked_Matrix<Matrix_Frozen<T2, Array2D_Type2, ViewType2>, true>::mat_t
2522
+ hstack(const Matrix_Frozen<T2, Array2D_Type2, ViewType2> &matrix) const {
2523
+ return Stacked_Matrix<Matrix_Frozen<T2, Array2D_Type2, ViewType2>, true>::generate(*this, matrix);
2524
+ }
2525
+
2526
+ /**
2527
+ * Vertical stack of two matrices
2528
+ *
2529
+ * @param matrix Matrix to stack vertically, i.e., bottom side
2530
+ * @return stacked matrix
2531
+ * @throw std::invalid_argument When matrix row number is smaller
2532
+ */
2533
+ template <class T2, class Array2D_Type2, class ViewType2>
2534
+ typename Stacked_Matrix<Matrix_Frozen<T2, Array2D_Type2, ViewType2>, false>::mat_t
2535
+ vstack(const Matrix_Frozen<T2, Array2D_Type2, ViewType2> &matrix) const {
2536
+ return Stacked_Matrix<Matrix_Frozen<T2, Array2D_Type2, ViewType2>, false>::generate(*this, matrix);
2537
+ }
2538
+
2539
+ /**
2540
+ * Test whether matrix is symmetric
2541
+ *
2542
+ * @return true when symmetric, otherwise false.
2543
+ */
2544
+ bool isSymmetric() const noexcept {
2545
+ return isSquare() && ((*this) - transpose()).isEqual_Block(value_t::zero);
2546
+ }
2547
+ /**
2548
+ * Test whether matrix is Hermitian
2549
+ *
2550
+ * @return true when Hermitian matrix, otherwise false.
2551
+ */
2552
+ bool isHermitian() const noexcept {
2553
+ return isSquare() && ((*this) - adjoint()).isEqual_Block(value_t::zero);
2554
+ }
2555
+ /**
2556
+ * Test whether matrix is skew-symmetric
2557
+ *
2558
+ * @return true when skew-symmetric matrix, otherwise false.
2559
+ */
2560
+ bool isSkewSymmetric() const noexcept {
2561
+ return isSquare() && ((*this) + transpose()).isEqual_Block(value_t::zero);
2562
+ }
2563
+
2061
2564
 
2062
2565
  template <class LHS_T, class RHS_T>
2063
2566
  friend struct Array2D_Operator_Multiply_by_Matrix;
@@ -2067,37 +2570,71 @@ class Matrix_Frozen {
2067
2570
 
2068
2571
  template <class MatrixT, int tag = OperatorProperty<MatrixT>::tag>
2069
2572
  struct check_t {
2070
- template <bool is_binary, class U = void>
2071
- struct check_binary_t {
2072
- static const bool has_multi_mat_by_mat = false;
2573
+ #if defined(_MSC_VER)
2574
+ /* work-around of MSVC bug for non-type template parameter
2575
+ * @see https://stackoverflow.com/questions/2763836/sfinae-failing-with-enum-template-parameter
2576
+ */
2577
+ template <bool is_operator2, class U = void>
2578
+ struct check_op_t {
2579
+ static const int complexity_linear = 1;
2580
+ static const int complexity_square = 1;
2073
2581
  };
2074
2582
  template <class U>
2075
- struct check_binary_t<true, U> {
2076
- static const bool has_multi_mat_by_mat
2077
- = (check_t<typename OperatorProperty<MatrixT>::operator_t::lhs_t>
2078
- ::has_multi_mat_by_mat)
2079
- || (check_t<typename OperatorProperty<MatrixT>::operator_t::rhs_t>
2080
- ::has_multi_mat_by_mat);
2583
+ struct check_op_t<true, U> {
2584
+ typedef typename OperatorProperty<MatrixT>::operator_t op_t;
2585
+ static const int complexity_lhs = check_t<op_t::lhs_t>::complexity;
2586
+ static const int complexity_rhs = check_t<op_t::rhs_t>::complexity;
2587
+ static const int complexity_linear = complexity_lhs + complexity_rhs;
2588
+ static const int complexity_square = (complexity_lhs + 1) * (complexity_rhs + 1);
2081
2589
  };
2082
- static const bool has_multi_mat_by_mat
2590
+ static const bool is_operator2
2591
+ = (tag == OPERATOR_2_Multiply_Matrix_by_Scalar)
2592
+ || (tag == OPERATOR_2_Add_Matrix_to_Matrix)
2593
+ || (tag == OPERATOR_2_Subtract_Matrix_from_Matrix)
2594
+ || (tag == OPERATOR_2_Multiply_Matrix_by_Matrix)
2595
+ || (tag == OPERATOR_2_Entrywise_Multiply_Matrix_by_Matrix);
2596
+ static const int complexity
2083
2597
  = (tag == OPERATOR_2_Multiply_Matrix_by_Matrix)
2084
- || check_binary_t<
2085
- (tag == OPERATOR_2_Multiply_Matrix_by_Scalar)
2086
- || (tag == OPERATOR_2_Add_Matrix_to_Matrix)
2087
- || (tag == OPERATOR_2_Subtract_Matrix_from_Matrix)
2088
- || (tag == OPERATOR_2_Multiply_Matrix_by_Matrix)
2089
- >::has_multi_mat_by_mat;
2598
+ ? check_op_t<is_operator2>::complexity_square
2599
+ : check_op_t<is_operator2>::complexity_linear;
2600
+ #else
2601
+ template <int tag2, class U = void>
2602
+ struct check_operator_t {
2603
+ static const int complexity = 1;
2604
+ };
2605
+ template <class U>
2606
+ struct check_operator_t<OPERATOR_2_Generic, U> {
2607
+ typedef check_t<typename OperatorProperty<MatrixT>::operator_t::lhs_t> lhs_t;
2608
+ typedef check_t<typename OperatorProperty<MatrixT>::operator_t::rhs_t> rhs_t;
2609
+ static const int complexity = lhs_t::complexity + rhs_t::complexity; // linear
2610
+ };
2611
+ #define make_binary_item(tag_name) \
2612
+ template <class U> struct check_operator_t<tag_name, U> \
2613
+ : public check_operator_t<OPERATOR_2_Generic, U>
2614
+ make_binary_item(OPERATOR_2_Multiply_Matrix_by_Scalar) {};
2615
+ make_binary_item(OPERATOR_2_Add_Matrix_to_Matrix) {};
2616
+ make_binary_item(OPERATOR_2_Subtract_Matrix_from_Matrix) {};
2617
+ make_binary_item(OPERATOR_2_Multiply_Matrix_by_Matrix) {
2618
+ typedef check_operator_t<OPERATOR_2_Generic, U> super_t;
2619
+ static const int complexity // square power
2620
+ = (super_t::lhs_t::complexity + 1) * (super_t::rhs_t::complexity + 1);
2621
+ };
2622
+ make_binary_item(OPERATOR_2_Entrywise_Multiply_Matrix_by_Matrix) {};
2623
+ // Stack_Horizontal/Vertical is intentionally ignored.
2624
+ #undef make_binary_item
2625
+ static const int complexity = check_operator_t<tag>::complexity;
2626
+ #endif
2090
2627
  static const bool is_multi_mat_by_scalar
2091
2628
  = (tag == OPERATOR_2_Multiply_Matrix_by_Scalar);
2092
2629
  };
2093
2630
 
2094
2631
  /*
2095
2632
  * [Optimization policy 1]
2096
- * If each side include M * M, then use cache.
2633
+ * If each side includes complex calculation such as M * M, then use cache.
2097
2634
  * For example, (M * M) * M, and (M * M + M) * M use cache for the first parenthesis terms.
2098
2635
  * (M * M + M) * (M * M + M) uses cache for the first and second parenthesis terms.
2099
2636
  */
2100
- template <class MatrixT, bool cache_on = check_t<MatrixT>::has_multi_mat_by_mat>
2637
+ template <class MatrixT, bool cache_on = (check_t<MatrixT>::complexity >= 3)>
2101
2638
  struct optimizer1_t {
2102
2639
  typedef MatrixT res_t;
2103
2640
  };
@@ -2212,7 +2749,38 @@ class Matrix_Frozen {
2212
2749
  }
2213
2750
 
2214
2751
  /**
2215
- * Generate a matrix in which i-th row and j-th column are removed to calculate minor (determinant)
2752
+ * Test whether matrix is normal
2753
+ *
2754
+ * @return true when normal matrix, otherwise false.
2755
+ */
2756
+ bool isNormal() const noexcept {
2757
+ return isSquare()
2758
+ && ((*this) * adjoint() - adjoint() * (*this)).isEqual_Block(value_t::zero, true, false, true);
2759
+ }
2760
+ /**
2761
+ * Test whether matrix is orthogonal
2762
+ *
2763
+ * @return true when orthogonal matrix, otherwise false.
2764
+ */
2765
+ bool isOrthogonal() const noexcept {
2766
+ return isSquare()
2767
+ && ((*this) * transpose() - 1).isEqual_Block(value_t::zero, true, false, true)
2768
+ && (transpose() * (*this) - 1).isEqual_Block(value_t::zero, true, false, true);
2769
+ }
2770
+ /**
2771
+ * Test whether matrix is unitary
2772
+ *
2773
+ * @return true when unitary matrix, otherwise false.
2774
+ */
2775
+ bool isUnitary() const noexcept {
2776
+ return isSquare()
2777
+ && ((*this) * adjoint() - 1).isEqual_Block(value_t::zero, true, false, true)
2778
+ && (adjoint() * (*this) - 1).isEqual_Block(value_t::zero, true, false, true);
2779
+ }
2780
+
2781
+ /**
2782
+ * Generate a matrix in which i-th row and j-th column are removed
2783
+ * to calculate first-minor (��ꏬ�s�񎮁A1�s1�񂸂Ž�菜�����s��̍s��)
2216
2784
  *
2217
2785
  * @param row Row to be removed
2218
2786
  * @param column Column to be removed
@@ -2223,6 +2791,7 @@ class Matrix_Frozen {
2223
2791
  const unsigned int &column) const noexcept {
2224
2792
  typedef typename builder_t::template resize_t<-1, -1>::assignable_t res_t;
2225
2793
  res_t res(res_t::blank(rows() - 1, columns() - 1));
2794
+ #if 0
2226
2795
  unsigned int i(0), i2(0);
2227
2796
  const unsigned int i_end(res.rows()), j_end(res.columns());
2228
2797
  for( ; i < row; ++i, ++i2){
@@ -2246,11 +2815,15 @@ class Matrix_Frozen {
2246
2815
  res(i, j) = operator()(i2, j2);
2247
2816
  }
2248
2817
  }
2818
+ #else
2819
+ // equivalent version to use circular view
2820
+ res.circular(row, column).replace(circular(row + 1, column + 1, rows() - 1, columns() - 1), false);
2821
+ #endif
2249
2822
  return res;
2250
2823
  }
2251
2824
 
2252
2825
  /**
2253
- * Calculate determinant by using minor
2826
+ * Calculate determinant by using first-minor (slow algorithm)
2254
2827
  *
2255
2828
  * @param do_check Whether check size property. The default is true.
2256
2829
  * @return Determinant
@@ -2258,18 +2831,27 @@ class Matrix_Frozen {
2258
2831
  */
2259
2832
  T determinant_minor(const bool &do_check = true) const {
2260
2833
  if(do_check && !isSquare()){throw std::logic_error("rows() != columns()");}
2261
- if(rows() == 1){
2262
- return (*this)(0, 0);
2263
- }else{
2264
- T sum(0);
2265
- T sign(1);
2266
- for(unsigned int i(0), i_end(rows()); i < i_end; i++){
2267
- if((*this)(i, 0) != T(0)){
2268
- sum += (*this)(i, 0) * (matrix_for_minor(i, 0).determinant(false)) * sign;
2834
+ switch(rows()){
2835
+ case 1: return (*this)(0, 0);
2836
+ case 2: return (*this)(0, 0) * (*this)(1, 1) - (*this)(0, 1) * (*this)(1, 0);
2837
+ case 3:
2838
+ return (*this)(0, 0) * (*this)(1, 1) * (*this)(2, 2)
2839
+ + (*this)(0, 1) * (*this)(1, 2) * (*this)(2, 0)
2840
+ + (*this)(0, 2) * (*this)(1, 0) * (*this)(2, 1)
2841
+ - (*this)(0, 0) * (*this)(1, 2) * (*this)(2, 1)
2842
+ - (*this)(0, 1) * (*this)(1, 0) * (*this)(2, 2)
2843
+ - (*this)(0, 2) * (*this)(1, 1) * (*this)(2, 0);
2844
+ default: {
2845
+ T sum(0);
2846
+ T sign(1);
2847
+ for(unsigned int i(0), i_end(rows()); i < i_end; i++){
2848
+ if(value_t::zero != (*this)(i, 0)){
2849
+ sum += (*this)(i, 0) * (matrix_for_minor(i, 0).determinant_minor(false)) * sign;
2850
+ }
2851
+ sign = -sign;
2269
2852
  }
2270
- sign = -sign;
2853
+ return sum;
2271
2854
  }
2272
- return sum;
2273
2855
  }
2274
2856
  }
2275
2857
 
@@ -2318,13 +2900,13 @@ class Matrix_Frozen {
2318
2900
  }
2319
2901
  // apply Gaussian elimination
2320
2902
  for(unsigned int i(0); i < rows_; ++i){
2321
- if(U(i, i) == T(0)){ // check (i, i) is not zero
2903
+ if(value_t::zero == U(i, i)){ // check (i, i) is not zero
2322
2904
  unsigned int j(i);
2323
2905
  do{
2324
2906
  if(++j == rows_){
2325
2907
  throw std::runtime_error("LU decomposition cannot be performed");
2326
2908
  }
2327
- }while(U(i, j) == T(0));
2909
+ }while(value_t::zero == U(i, j));
2328
2910
  for(unsigned int i2(0); i2 < rows_; ++i2){ // swap i-th and j-th columns
2329
2911
  T temp(U(i2, i));
2330
2912
  U(i2, i) = U(i2, j);
@@ -2348,12 +2930,78 @@ class Matrix_Frozen {
2348
2930
  return LU;
2349
2931
  }
2350
2932
 
2933
+ void decomposeLUP_property(
2934
+ unsigned int &rank, T &determinant, unsigned int &pivot_num,
2935
+ const bool &do_check = true) const {
2936
+ // Algorithm is the same as decomposeLUP, but L matrix is not calculated
2937
+ // because rank/determinant can be obtained throught calculation of lower triangular of U.
2938
+ if(do_check && !isSquare()){throw std::logic_error("rows() != columns()");}
2939
+
2940
+ typename builder_t::assignable_t U(this->operator typename builder_t::assignable_t()); // copy
2941
+ const unsigned int rows_(rows());
2942
+ pivot_num = 0;
2943
+ determinant = T(1);
2944
+
2945
+ // apply Gaussian elimination
2946
+ for(unsigned int i(0); i < rows_; ++i){
2947
+ if(value_t::zero == U(i, i)){ // check (i, i) is not zero
2948
+ unsigned int j(i);
2949
+ do{
2950
+ if(++j == rows_){
2951
+ rank = i;
2952
+ return;
2953
+ }
2954
+ }while(value_t::zero == U(i, j));
2955
+ for(unsigned int i2(i); i2 < rows_; ++i2){ // swap i-th and j-th columns
2956
+ T temp(U(i2, i));
2957
+ U(i2, i) = U(i2, j);
2958
+ U(i2, j) = temp;
2959
+ }
2960
+ pivot_num++;
2961
+ }
2962
+ #if 0
2963
+ for(unsigned int i2(i + 1); i2 < rows_; ++i2){
2964
+ T L_i2_i(U(i2, i) / U(i, i)); // equivalent to L(i2, i) = U(i2, i) / U(i, i); skip U(i2, i) = T(0);
2965
+ for(unsigned int j2(i + 1); j2 < rows_; ++j2){
2966
+ U(i2, j2) -= L_i2_i * U(i, j2);
2967
+ }
2968
+ }
2969
+ determinant *= U(i, i);
2970
+ #else
2971
+ // integer preservation algorithm (Bareiss)
2972
+ for(unsigned int i2(i + 1); i2 < rows_; ++i2){
2973
+ for(unsigned int j2(i + 1); j2 < rows_; ++j2){
2974
+ ((U(i2, j2) *= U(i, i)) -= U(i2, i) * U(i, j2)) /= determinant;
2975
+ }
2976
+ }
2977
+ determinant = U(i, i);
2978
+ #endif
2979
+ }
2980
+ rank = rows_;
2981
+ determinant *= ((pivot_num % 2 == 0) ? 1 : -1);
2982
+ }
2983
+
2351
2984
  typename builder_t::template resize_t<0, 0, 1, 2>::assignable_t decomposeLU(
2352
2985
  const bool &do_check = true) const {
2353
2986
  unsigned int pivot_num;
2354
2987
  return decomposeLUP(pivot_num, NULL, do_check);
2355
2988
  }
2356
2989
 
2990
+ /**
2991
+ * Test whether matrix is LU decomposed.
2992
+ * The assumption of elements is
2993
+ * (0, 0)-(n-1, n-1): L matrix
2994
+ * (0, n)-(n-1, 2n-1): U matrix
2995
+ *
2996
+ * @return true when LU, otherwise false.
2997
+ */
2998
+ bool isLU() const noexcept {
2999
+ const unsigned int r(rows());
3000
+ return (r * 2 == columns())
3001
+ && partial(r, r).isLowerTriangular()
3002
+ && partial(r, r, 0, r).isUpperTriangular();
3003
+ }
3004
+
2357
3005
  /**
2358
3006
  * Resolve x of (Ax = y), where this matrix is A and has already been decomposed as LU.
2359
3007
  *
@@ -2420,8 +3068,83 @@ class Matrix_Frozen {
2420
3068
  return res;
2421
3069
  }
2422
3070
 
3071
+ /**
3072
+ * Calculate determinant by using LU decomposition (faster algorithm)
3073
+ *
3074
+ * @param do_check Whether check size property. The default is true.
3075
+ * @return Determinant
3076
+ */
3077
+ T determinant_LU2(const bool &do_check = true) const {
3078
+ unsigned int pivot_num, rank;
3079
+ T res;
3080
+ decomposeLUP_property(rank, res, pivot_num, do_check);
3081
+ if(rank != rows()){
3082
+ throw std::runtime_error("LU decomposition cannot be performed");
3083
+ }
3084
+ return res;
3085
+ }
3086
+
2423
3087
  T determinant(const bool &do_check = true) const {
2424
- return determinant_LU(do_check);
3088
+ return determinant_LU2(do_check);
3089
+ }
3090
+
3091
+ /**
3092
+ * Calculate rank by using LU decomposition
3093
+ *
3094
+ * @param do_check Whether check size property. The default is true.
3095
+ * @return rank
3096
+ */
3097
+ unsigned int rank_LU2(const bool &do_check = true) const {
3098
+ unsigned int pivot_num, res;
3099
+ T det;
3100
+ decomposeLUP_property(res, det, pivot_num, do_check);
3101
+ return res;
3102
+ }
3103
+
3104
+ unsigned int rank(const bool &do_check = true) const {
3105
+ return rank_LU2(do_check);
3106
+ }
3107
+
3108
+ /**
3109
+ * Calculate cofactor (�]���q), i.e.,
3110
+ * determinant of smaller square matrix removing specified one row and column
3111
+ * fro original matrix.
3112
+ *
3113
+ * @param row
3114
+ * @param column
3115
+ * @param do_check check size (true) or not (false). The default is true.
3116
+ * @return Cofactor
3117
+ */
3118
+ T cofactor(
3119
+ const unsigned int &row, const unsigned int &column,
3120
+ const bool &do_check = true) const {
3121
+ if(do_check && !isSquare()){throw std::logic_error("rows != columns");}
3122
+ if((row >= rows()) || (column >= columns())){
3123
+ throw std::out_of_range("incorrect row and/or column indices");
3124
+ }
3125
+ // circular.determinant is equivalent to matrix_for_minor.determinant
3126
+ // in terms of absolute values (polarity should be taken care of.)
3127
+ //return matrix_for_minor(row, column).determinant(false) * (((row + column) % 2 == 0) ? 1 : -1);
3128
+ return circular(row + 1, column + 1, rows() - 1, columns() - 1).determinant(false)
3129
+ * (((rows() % 2 == 1) || ((row + column) % 2 == 0)) ? 1 : -1);
3130
+ }
3131
+
3132
+ /**
3133
+ * Return adjugate (�]���q�s��), i.e. transposed cofactor matrix.
3134
+ * X * adjugate(X) = det(X) I
3135
+ *
3136
+ * @param do_check check size (true) or not (false). The default is true.
3137
+ * @return Adjugate
3138
+ */
3139
+ typename builder_t::assignable_t adjugate(const bool &do_check = true) const {
3140
+ if(do_check && !isSquare()){throw std::logic_error("rows != columns");}
3141
+ typename builder_t::assignable_t res(builder_t::assignable_t::blank(rows(), columns()));
3142
+ for(unsigned int i(0), i_end(rows()); i < i_end; ++i){
3143
+ for(unsigned int j(0), j_end(columns()); j < j_end; ++j){
3144
+ res(i, j) = cofactor(j, i, false);
3145
+ }
3146
+ }
3147
+ return res;
2425
3148
  }
2426
3149
 
2427
3150
  /**
@@ -2463,16 +3186,9 @@ class Matrix_Frozen {
2463
3186
 
2464
3187
  #if 0
2465
3188
  // Cramer (slow); �N�����[��
2466
- mat_t result(rows(), columns());
2467
- T det;
2468
- if((det = mat.determinant()) == 0){throw std::runtime_error("Operation void!!");}
2469
- const unsigned int i_end(mat.rows()), j_end(mat.columns());
2470
- for(unsigned int i(0); i < i_end; i++){
2471
- for(unsigned int j(0); j < j_end; j++){
2472
- result(i, j) = mat.matrix_for_minor(i, j).determinant() * ((i + j) % 2 == 0 ? 1 : -1);
2473
- }
2474
- }
2475
- return result.transpose() / det;
3189
+ T det(mat.determinant(false));
3190
+ if(value_t::zero == det){throw std::runtime_error("Operation void!!");}
3191
+ return mat.adjugate() / det;
2476
3192
  #endif
2477
3193
 
2478
3194
  // Gaussian elimination; �K�E�X�����@
@@ -2480,13 +3196,13 @@ class Matrix_Frozen {
2480
3196
  mat_t right(getI(mat.rows()));
2481
3197
  const unsigned int rows_(left.rows()), columns_(left.columns());
2482
3198
  for(unsigned int i(0); i < rows_; i++){
2483
- if(left(i, i) == T(0)){
3199
+ if(value_t::zero == left(i, i)){
2484
3200
  unsigned int i2(i);
2485
3201
  do{
2486
3202
  if(++i2 == rows_){
2487
3203
  throw std::runtime_error("invert matrix not exist");
2488
3204
  }
2489
- }while(left(i2, i) == T(0));
3205
+ }while(value_t::zero == left(i2, i));
2490
3206
  // swap i-th and i2-th rows
2491
3207
  for(unsigned int j(i); j < columns_; ++j){
2492
3208
  T temp(left(i, j));
@@ -2495,14 +3211,14 @@ class Matrix_Frozen {
2495
3211
  }
2496
3212
  right.swapRows(i, i2);
2497
3213
  }
2498
- if(left(i, i) != T(1)){
3214
+ if(value_t::zero != (left(i, i) - 1)){
2499
3215
  for(unsigned int j(0); j < columns_; j++){right(i, j) /= left(i, i);}
2500
3216
  for(unsigned int j(i+1); j < columns_; j++){left(i, j) /= left(i, i);}
2501
3217
  left(i, i) = T(1);
2502
3218
  }
2503
3219
  for(unsigned int k(0); k < rows_; k++){
2504
3220
  if(k == i){continue;}
2505
- if(left(k, i) != T(0)){
3221
+ if(value_t::zero != left(k, i)){
2506
3222
  for(unsigned int j(0); j < columns_; j++){right(k, j) -= right(i, j) * left(k, i);}
2507
3223
  for(unsigned int j(i+1); j < columns_; j++){left(k, j) -= left(i, j) * left(k, i);}
2508
3224
  left(k, i) = T(0);
@@ -2583,63 +3299,9 @@ class Matrix_Frozen {
2583
3299
  return this->operator typename builder_t::assignable_t().pivotMerge(row, column, matrix);
2584
3300
  }
2585
3301
 
2586
- struct complex_t {
2587
- template <class T2>
2588
- struct check_t {
2589
- static const bool hit = false;
2590
- typedef T2 r_t;
2591
- typedef Complex<T2> c_t;
2592
- };
2593
- template <class T2>
2594
- struct check_t<Complex<T2> > {
2595
- static const bool hit = true;
2596
- typedef T2 r_t;
2597
- typedef Complex<T2> c_t;
2598
- };
2599
- static const bool is_complex = check_t<T>::hit;
2600
- typedef typename check_t<T>::c_t v_t;
2601
- typedef typename builder_t::template cast_t<v_t>::assignable_t m_t;
2602
- typedef typename check_t<T>::r_t real_t;
2603
- static real_t get_real(const real_t &v) noexcept {
2604
- return v;
2605
- }
2606
- static real_t get_real(const v_t &v) noexcept {
2607
- return v.real();
2608
- }
2609
- static v_t get_sqrt(const real_t &v) noexcept {
2610
- return (v >= 0) ? v_t(std::sqrt(v)) : v_t(0, std::sqrt(-v));
2611
- }
2612
- static v_t get_sqrt(const v_t &v) noexcept {
2613
- return v.sqrt();
2614
- }
2615
- static real_t get_abs(const real_t &v) noexcept {
2616
- return std::abs(v);
2617
- }
2618
- static real_t get_abs(const v_t &v) noexcept {
2619
- return v.abs();
2620
- }
2621
- static real_t get_abs2(const real_t &v) noexcept {
2622
- return v * v;
2623
- }
2624
- static real_t get_abs2(const v_t &v) noexcept {
2625
- return v.abs2();
2626
- }
2627
- static bool is_nan_or_infinite(const real_t &v) noexcept {
2628
- #if defined(_MSC_VER)
2629
- return _isnan(v) || !_finite(v);
2630
- #else
2631
- return std::isnan(v) || !std::isfinite(v);
2632
- #endif
2633
- }
2634
- static bool is_nan_or_infinite(const v_t &v) noexcept {
2635
- return is_nan_or_infinite(v.real())
2636
- || is_nan_or_infinite(v.imaginary());
2637
- }
2638
- };
2639
-
2640
- Matrix_Frozen<typename complex_t::v_t, Array2D_Type, ViewType>
3302
+ Matrix_Frozen<typename value_t::complex_t, Array2D_Type, ViewType>
2641
3303
  complex() const noexcept {
2642
- return Matrix_Frozen<typename complex_t::v_t, Array2D_Type, ViewType>(*this);
3304
+ return Matrix_Frozen<typename value_t::complex_t, Array2D_Type, ViewType>(*this);
2643
3305
  }
2644
3306
 
2645
3307
  /**
@@ -2647,17 +3309,17 @@ class Matrix_Frozen {
2647
3309
  *
2648
3310
  * @return tr(A* * A)
2649
3311
  */
2650
- typename complex_t::real_t norm2F() const noexcept {
2651
- // return complex_t::get_real((adjoint() * (*this)).trace(false));
2652
- /* The above is as definition, however, double calculation may occure
3312
+ typename value_t::real_t norm2F() const noexcept {
3313
+ // return value_t::get_real((adjoint() * (*this)).trace(false));
3314
+ /* The above is as definition, however, double calculation may occur
2653
3315
  * when (*this) is a expression matrix such as multiplication.
2654
3316
  * To avoid such overhead, its expansion form to take summation of
2655
3317
  * abs(element)**2 is used.
2656
3318
  */
2657
- typename complex_t::real_t res(0);
3319
+ typename value_t::real_t res(0);
2658
3320
  for(unsigned int i(0), i_end(rows()); i < i_end; ++i){
2659
3321
  for(unsigned int j(0), j_end(columns()); j < j_end; ++j){
2660
- res += complex_t::get_abs2((*this)(i, j));
3322
+ res += value_t::get_abs2((*this)(i, j));
2661
3323
  }
2662
3324
  }
2663
3325
  return res;
@@ -2671,15 +3333,15 @@ class Matrix_Frozen {
2671
3333
  * @return 2nd power of Frobenius norm of x
2672
3334
  */
2673
3335
  template <class Array2D_Type2, class ViewType2>
2674
- static typename complex_t::real_t householder_vector(
3336
+ static typename value_t::real_t householder_vector(
2675
3337
  Matrix<T, Array2D_Type2, ViewType2> &x){
2676
3338
  // x = {(0,0), (1,0), ..., (N-1,0)}^{T}
2677
3339
 
2678
- typename complex_t::real_t x_abs2(x.norm2F());
3340
+ typename value_t::real_t x_abs2(x.norm2F());
2679
3341
  if(x_abs2 == 0){return x_abs2;}
2680
3342
 
2681
- typename complex_t::real_t x_abs(std::sqrt(x_abs2));
2682
- typename complex_t::real_t x_top_abs(std::abs(x(0, 0))); // x(0,0)
3343
+ typename value_t::real_t x_abs(std::sqrt(x_abs2));
3344
+ typename value_t::real_t x_top_abs(std::abs(x(0, 0))); // x(0,0)
2683
3345
  T rho(x(0, 0) / x_top_abs * -1);
2684
3346
  // if x(0,0) is real, then rho = -sign(x(0,0)),
2685
3347
  // otherwise rho = - e^{i \phi}, where x(0,0) \equiv e^{i \phi} |x(0,0)|
@@ -2690,7 +3352,7 @@ class Matrix_Frozen {
2690
3352
  // = x_abs2 * (1 + \rho \bar{\rho}) - x_abs * (\rho \bar{x(0,0)} + \bar{\rho} x(0,0))
2691
3353
  // = (x_abs2 + x_top_abs * x_abs) * 2
2692
3354
  x(0, 0) -= rho * x_abs;
2693
- typename complex_t::real_t x_dash_abs2((x_abs2 + x_top_abs * x_abs) * 2);
3355
+ typename value_t::real_t x_dash_abs2((x_abs2 + x_top_abs * x_abs) * 2);
2694
3356
 
2695
3357
  return x_dash_abs2;
2696
3358
  }
@@ -2737,7 +3399,7 @@ class Matrix_Frozen {
2737
3399
  // x_0 = {(0,0), (1,0), ..., (N-1,0)}^{T}, (N-1)*1
2738
3400
  // x_1 = {(1,1), (2,1), ..., (N-1,1)}^{T}, (N-2)*1, ...
2739
3401
 
2740
- typename complex_t::real_t x_abs2(householder_vector(x));
3402
+ typename value_t::real_t x_abs2(householder_vector(x));
2741
3403
  // x_0 <- {(0,0) - \rho |x|, (1,0), ..., (N-1,0)}^{T}
2742
3404
  // x_1 <- {(1,1) - \rho |x|, (2,1), ..., (N-1,1)}^{T}, ...
2743
3405
  if(x_abs2 == 0){continue;}
@@ -2798,7 +3460,7 @@ class Matrix_Frozen {
2798
3460
  }
2799
3461
 
2800
3462
  bool real_symmetric(
2801
- (!complex_t::is_complex)
3463
+ (!value_t::is_complex)
2802
3464
  && ((opt.mat_prop == opt_hessenberg_t::SYMMETRIC)
2803
3465
  || ((opt.mat_prop == opt_hessenberg_t::NOT_CHECKED) && isSymmetric())));
2804
3466
 
@@ -2811,7 +3473,7 @@ class Matrix_Frozen {
2811
3473
  // x_0 = {(1,0), (2,0), ..., (N-1,0)}^{T}, (N-1)*1
2812
3474
  // x_1 = {(2,1), (3,1), ..., (N-1,1)}^{T}, (N-2)*1, ...
2813
3475
 
2814
- typename complex_t::real_t x_abs2(householder_vector(x));
3476
+ typename value_t::real_t x_abs2(householder_vector(x));
2815
3477
  // x_0 <- {(1,0) - \rho |x|, (2,0), ..., (N-1,0)}^{T}
2816
3478
  // x_1 <- {(2,1) - \rho |x|, (3,1), ..., (N-1,1)}^{T}, ...
2817
3479
  if(x_abs2 == 0){continue;}
@@ -2870,11 +3532,11 @@ class Matrix_Frozen {
2870
3532
  */
2871
3533
  void eigen22(
2872
3534
  const unsigned int &row, const unsigned int &column,
2873
- typename complex_t::v_t &upper, typename complex_t::v_t &lower) const {
3535
+ typename value_t::complex_t &upper, typename value_t::complex_t &lower) const {
2874
3536
  const T
2875
3537
  &a((*this)(row, column)), &b((*this)(row, column + 1)),
2876
3538
  &c((*this)(row + 1, column)), &d((*this)(row + 1, column + 1));
2877
- typename complex_t::v_t root(complex_t::get_sqrt((a - d) * (a - d) + b * c * 4));
3539
+ typename value_t::complex_t root(value_t::get_sqrt((a - d) * (a - d) + b * c * 4));
2878
3540
  upper = ((root + a + d) / 2);
2879
3541
  lower = ((-root + a + d) / 2);
2880
3542
  }
@@ -2883,8 +3545,8 @@ class Matrix_Frozen {
2883
3545
  enum {
2884
3546
  NOT_CHECKED, SQUARE,
2885
3547
  } mat_prop;
2886
- typename complex_t::real_t threshold_abs; ///< Absolute error to be used for convergence determination
2887
- typename complex_t::real_t threshold_rel; ///< Relative error to be used for convergence determination
3548
+ typename value_t::real_t threshold_abs; ///< Absolute error to be used for convergence determination
3549
+ typename value_t::real_t threshold_rel; ///< Relative error to be used for convergence determination
2888
3550
  unsigned int inverse_power_max_iter;
2889
3551
 
2890
3552
  opt_eigen_t()
@@ -2905,10 +3567,12 @@ class Matrix_Frozen {
2905
3567
  * @throw std::logic_error When operation is undefined
2906
3568
  * @throw std::runtime_error When operation is unavailable
2907
3569
  */
2908
- typename MatrixBuilder<typename complex_t::m_t>::template resize_t<0, 1>::assignable_t eigen(
3570
+ typename MatrixBuilder< // a.k.a. (assignable complex matrix)(r, c+1)
3571
+ typename builder_t::template cast_t<typename value_t::complex_t>::assignable_t>
3572
+ ::template resize_t<0, 1>::assignable_t eigen(
2909
3573
  const opt_eigen_t &opt = opt_eigen_t()) const {
2910
3574
 
2911
- typedef typename complex_t::m_t cmat_t;
3575
+ typedef typename builder_t::template cast_t<typename value_t::complex_t>::assignable_t cmat_t;
2912
3576
  typedef typename MatrixBuilder<cmat_t>::template resize_t<0, 1, 1, 0>::assignable_t cvec_t;
2913
3577
  typedef typename MatrixBuilder<cmat_t>::template resize_t<0, 1>::assignable_t res_t;
2914
3578
 
@@ -2944,7 +3608,7 @@ class Matrix_Frozen {
2944
3608
 
2945
3609
  // Double QR method
2946
3610
  /* <Procedure>
2947
- * 1) Transform upper Hessenburg's matrix by using Householder's method
3611
+ * 1) Transform this to upper Hessenburg's matrix by using Householder's method
2948
3612
  * �n�E�X�z���_�[�@��K�p���āA��w�b�Z���x���N�s��ɒu����
2949
3613
  * 2) Then, Apply double QR method to get eigenvalues
2950
3614
  * �_�u��QR�@��K�p�B
@@ -2954,10 +3618,10 @@ class Matrix_Frozen {
2954
3618
 
2955
3619
  const unsigned int &_rows(rows());
2956
3620
 
2957
- // ���ʂ̊i�[�p�̍s��
3621
+ // Buffer to store resultant; ���ʂ̊i�[�p�̍s��
2958
3622
  res_t result(res_t::blank(_rows, _rows + 1));
2959
3623
 
2960
- // �ŗL�l�̌v�Z
3624
+ // Eigenvalue computation; �ŗL�l�̌v�Z
2961
3625
  #define lambda(i) result(i, _rows)
2962
3626
 
2963
3627
  int m = _rows;
@@ -2979,7 +3643,7 @@ class Matrix_Frozen {
2979
3643
  break;
2980
3644
  }
2981
3645
 
2982
- //�n�E�X�z���_�[�ϊ����J��Ԃ�
3646
+ // Apply Householder transformation iteratively; �n�E�X�z���_�[�ϊ����J��Ԃ�
2983
3647
  for(int i(0); i < m - 1; i++){
2984
3648
  typename builder_t::template resize_t<3, 1, 0, 0>::assignable_t omega(3, 1);
2985
3649
  if(i == 0){ // calculate double shift of initial Householder transformation
@@ -2996,7 +3660,7 @@ class Matrix_Frozen {
2996
3660
  // caution: omega size is 3x3 if i in [0, m-2), however, 2x2 when i == m-2
2997
3661
  }
2998
3662
 
2999
- typename complex_t::real_t omega_abs2(householder_vector(omega));
3663
+ typename value_t::real_t omega_abs2(householder_vector(omega));
3000
3664
  if(omega_abs2 == 0){continue;}
3001
3665
  //std::cout << "omega_abs(" << m << ") " << omega_abs << std::endl;
3002
3666
 
@@ -3032,23 +3696,23 @@ class Matrix_Frozen {
3032
3696
  }
3033
3697
  //std::cout << "A_scl(" << m << ") " << A(m-1,m-2) << std::endl;
3034
3698
 
3035
- if(complex_t::is_nan_or_infinite(A(m-1,m-2))){
3036
- throw std::runtime_error("eigen values calculation failed");
3699
+ if(value_t::is_nan_or_infinite(A(m-1,m-2))){
3700
+ throw std::runtime_error("eigenvalues calculation failed");
3037
3701
  }
3038
3702
 
3039
3703
  // Convergence test; ��������
3040
- typename complex_t::real_t
3041
- A_m2_abs(complex_t::get_abs(A(m-2, m-2))),
3042
- A_m1_abs(complex_t::get_abs(A(m-1, m-1)));
3043
- typename complex_t::real_t epsilon(opt.threshold_abs
3704
+ typename value_t::real_t
3705
+ A_m2_abs(value_t::get_abs(A(m-2, m-2))),
3706
+ A_m1_abs(value_t::get_abs(A(m-1, m-1)));
3707
+ typename value_t::real_t epsilon(opt.threshold_abs
3044
3708
  + opt.threshold_rel * ((A_m2_abs < A_m1_abs) ? A_m2_abs : A_m1_abs));
3045
3709
 
3046
3710
  //std::cout << "epsil(" << m << ") " << epsilon << std::endl;
3047
3711
 
3048
- if(complex_t::get_abs(A(m-1, m-2)) < epsilon){
3712
+ if(value_t::get_abs(A(m-1, m-2)) < epsilon){
3049
3713
  --m;
3050
3714
  lambda(m) = A(m, m);
3051
- }else if(complex_t::get_abs(A(m-2, m-3)) < epsilon){
3715
+ }else if(value_t::get_abs(A(m-2, m-3)) < epsilon){
3052
3716
  A.eigen22(m-2, m-2, lambda(m-1), lambda(m-2));
3053
3717
  m -= 2;
3054
3718
  }
@@ -3086,8 +3750,8 @@ class Matrix_Frozen {
3086
3750
  * http://www.nrbook.com/a/bookcpdf/c11-7.pdf
3087
3751
  * is also utilized in case some eigenvalues are identical.
3088
3752
  */
3089
- typename complex_t::v_t approx_lambda(lambda(j));
3090
- approx_lambda += complex_t::get_abs(approx_lambda) * 1E-4; // 0.01%
3753
+ typename value_t::complex_t approx_lambda(lambda(j));
3754
+ approx_lambda += value_t::get_abs(approx_lambda) * 1E-4; // 0.01%
3091
3755
  typename MatrixBuilder<cmat_t>::template resize_t<0, 0, 1, 2>::assignable_t
3092
3756
  A_C_lambda_LU((A_.complex() - approx_lambda).decomposeLU(false));
3093
3757
 
@@ -3096,8 +3760,8 @@ class Matrix_Frozen {
3096
3760
  for(unsigned int loop(0); true; loop++){
3097
3761
  cvec_t target_x_new(
3098
3762
  A_C_lambda_LU.solve_linear_eq_with_LU(target_x, false));
3099
- typename complex_t::v_t mu((target_x_new.adjoint() * target_x)(0, 0)); // inner product
3100
- typename complex_t::real_t v2(target_x_new.norm2F());
3763
+ typename value_t::complex_t mu((target_x_new.adjoint() * target_x)(0, 0)); // inner product
3764
+ typename value_t::real_t v2(target_x_new.norm2F());
3101
3765
  target_x.replace(target_x_new / std::sqrt(v2), false);
3102
3766
  //std::cout << j << ": " << target_x.transpose() << ", " << mu << ", " << v2 << std::endl;
3103
3767
  if(std::abs(mu.abs2() / v2 - 1) < opt.threshold_abs){
@@ -3128,7 +3792,7 @@ class Matrix_Frozen {
3128
3792
  #if 0
3129
3793
  // Normalization(���K��) is skipable due to transform matrix is unitary
3130
3794
  for(unsigned int j(0), j_end(x.columns()); j < j_end; j++){
3131
- result.columnVector(j) /= complex_t::get_sqrt(result.columnVector(j).norm2F());
3795
+ result.columnVector(j) /= value_t::get_sqrt(result.columnVector(j).norm2F());
3132
3796
  }
3133
3797
  #endif
3134
3798
  #undef lambda
@@ -3172,10 +3836,11 @@ class Matrix_Frozen {
3172
3836
  * Calculate square root of a matrix
3173
3837
  *
3174
3838
  * @param opt option to calculate eigenvalue/eigenvector
3175
- * @return square root
3839
+ * @return square root (assignable complex matrix)
3176
3840
  * @see eigen(const opt_eigen_t &)
3177
3841
  */
3178
- typename complex_t::m_t sqrt(const opt_eigen_t &opt = opt_eigen_t()) const {
3842
+ typename builder_t::template cast_t<typename value_t::complex_t>::assignable_t sqrt(
3843
+ const opt_eigen_t &opt = opt_eigen_t()) const {
3179
3844
  return sqrt(eigen(opt));
3180
3845
  }
3181
3846
 
@@ -3234,6 +3899,10 @@ class Matrix_Frozen {
3234
3899
  return (*this) << op.lhs << ", " << op.rhs;
3235
3900
  }
3236
3901
  template <class LHS_T, class RHS_T>
3902
+ format_t &operator<<(const Array2D_Operator_EntrywiseMultiply<LHS_T, RHS_T> &op){
3903
+ return (*this) << op.lhs << ", " << op.rhs;
3904
+ }
3905
+ template <class LHS_T, class RHS_T>
3237
3906
  format_t &operator<<(const Array2D_Operator_Multiply_by_Scalar<LHS_T, RHS_T> &op){
3238
3907
  return (*this) << op.lhs << ", " << op.rhs;
3239
3908
  }
@@ -3241,6 +3910,10 @@ class Matrix_Frozen {
3241
3910
  format_t &operator<<(const Array2D_Operator_Multiply_by_Matrix<LHS_T, RHS_T> &op){
3242
3911
  return (*this) << op.lhs << ", " << op.rhs;
3243
3912
  }
3913
+ template <class LHS_T, class RHS_T, bool rhs_horizontal>
3914
+ format_t &operator<<(const Array2D_Operator_Stack<LHS_T, RHS_T, rhs_horizontal> &op){
3915
+ return (*this) << op.lhs << ", " << op.rhs;
3916
+ }
3244
3917
 
3245
3918
  template <class T2, class T2_op, class OperatorT, class View_Type2>
3246
3919
  format_t &operator<<(
@@ -3255,6 +3928,12 @@ class Matrix_Frozen {
3255
3928
  symbol = "+"; break;
3256
3929
  case OPERATOR_2_Subtract_Matrix_from_Matrix:
3257
3930
  symbol = "-"; break;
3931
+ case OPERATOR_2_Entrywise_Multiply_Matrix_by_Matrix:
3932
+ symbol = ".*"; break;
3933
+ case OPERATOR_2_Stack_Horizontal:
3934
+ symbol = "H"; break;
3935
+ case OPERATOR_2_Stack_Vertical:
3936
+ symbol = "V"; break;
3258
3937
  default:
3259
3938
  return (*this) << "(?)";
3260
3939
  }
@@ -3355,6 +4034,60 @@ struct Array2D_Operator_Add<
3355
4034
  }
3356
4035
  };
3357
4036
 
4037
+ template <
4038
+ class T, class Array2D_Type, class ViewType,
4039
+ class T2, class Array2D_Type2, class ViewType2>
4040
+ struct Array2D_Operator_EntrywiseMultiply<
4041
+ Matrix_Frozen<T, Array2D_Type, ViewType>,
4042
+ Matrix_Frozen<T2, Array2D_Type2, ViewType2> >
4043
+ : public Array2D_Operator_Binary<
4044
+ Matrix_Frozen<T, Array2D_Type, ViewType>,
4045
+ Matrix_Frozen<T2, Array2D_Type2, ViewType2> >{
4046
+ typedef Array2D_Operator_Binary<
4047
+ Matrix_Frozen<T, Array2D_Type, ViewType>,
4048
+ Matrix_Frozen<T2, Array2D_Type2, ViewType2> > super_t;
4049
+ static const int tag = super_t::lhs_t::OPERATOR_2_Entrywise_Multiply_Matrix_by_Matrix;
4050
+ Array2D_Operator_EntrywiseMultiply(
4051
+ const typename super_t::lhs_t &_lhs,
4052
+ const typename super_t::rhs_t &_rhs) noexcept
4053
+ : super_t(_lhs, _rhs) {}
4054
+ T operator()(const unsigned int &row, const unsigned int &column) const noexcept {
4055
+ return super_t::lhs(row, column) * super_t::rhs(row, column);
4056
+ }
4057
+ };
4058
+
4059
+ template <
4060
+ class T, class Array2D_Type, class ViewType,
4061
+ class T2, class Array2D_Type2, class ViewType2,
4062
+ bool rhs_horizontal>
4063
+ struct Array2D_Operator_Stack<
4064
+ Matrix_Frozen<T, Array2D_Type, ViewType>,
4065
+ Matrix_Frozen<T2, Array2D_Type2, ViewType2>,
4066
+ rhs_horizontal>
4067
+ : public Array2D_Operator_Binary<
4068
+ Matrix_Frozen<T, Array2D_Type, ViewType>,
4069
+ Matrix_Frozen<T2, Array2D_Type2, ViewType2> >{
4070
+ typedef Array2D_Operator_Binary<
4071
+ Matrix_Frozen<T, Array2D_Type, ViewType>,
4072
+ Matrix_Frozen<T2, Array2D_Type2, ViewType2> > super_t;
4073
+ static const int tag = rhs_horizontal
4074
+ ? super_t::lhs_t::OPERATOR_2_Stack_Horizontal
4075
+ : super_t::lhs_t::OPERATOR_2_Stack_Vertical;
4076
+ const unsigned int threshold;
4077
+ Array2D_Operator_Stack(
4078
+ const typename super_t::lhs_t &_lhs,
4079
+ const typename super_t::rhs_t &_rhs) noexcept
4080
+ : super_t(_lhs, _rhs),
4081
+ threshold(rhs_horizontal ? _lhs.columns() : _lhs.rows()) {}
4082
+ T operator()(const unsigned int &row, const unsigned int &column) const noexcept {
4083
+ if(rhs_horizontal){
4084
+ return (column < threshold) ? super_t::lhs(row, column) : super_t::rhs(row, column - threshold);
4085
+ }else{
4086
+ return (row < threshold) ? super_t::lhs(row, column) : super_t::rhs(row - threshold, column);
4087
+ }
4088
+ }
4089
+ };
4090
+
3358
4091
  template <
3359
4092
  class T, class Array2D_Type, class ViewType,
3360
4093
  class T2, class Array2D_Type2, class ViewType2>
@@ -3443,6 +4176,27 @@ private:
3443
4176
  };
3444
4177
  typedef typename check_op_t<>::res_t mat_t;
3445
4178
  };
4179
+ template <class LHS_T, class RHS_T, bool rhs_horizontal>
4180
+ struct unpack_op_t<Array2D_Operator_Stack<LHS_T, RHS_T, rhs_horizontal> > { // (H/V, M, M)
4181
+ template <
4182
+ class OperatorT_L = typename LHS_T::template OperatorProperty<>::operator_t,
4183
+ class OperatorT_R = typename RHS_T::template OperatorProperty<>::operator_t,
4184
+ class U = void>
4185
+ struct check_op_t {
4186
+ typedef Matrix_Frozen<T, Array2D_Operator<T, Array2D_Operator_Stack<
4187
+ typename MatrixBuilder<LHS_T>::assignable_t::frozen_t,
4188
+ typename MatrixBuilder<RHS_T>::assignable_t::frozen_t,
4189
+ rhs_horizontal> >, ViewType> res_t;
4190
+ };
4191
+ template <class U>
4192
+ struct check_op_t<void, void, U> {
4193
+ // active when both left and right hand side terms are none operator
4194
+ // This may be overwritten by (H/V, M, M) if its MatrixBuilder specialization exists
4195
+ typedef typename MatrixBuilder<LHS_T>
4196
+ ::template view_apply_t<ViewType>::applied_t res_t;
4197
+ };
4198
+ typedef typename check_op_t<>::res_t mat_t;
4199
+ };
3446
4200
 
3447
4201
  typedef MatrixBuilder<typename unpack_op_t<OperatorT>::mat_t> gen_t;
3448
4202
  public:
@@ -3536,39 +4290,51 @@ class Matrix : public Matrix_Frozen<T, Array2D_Type, ViewType> {
3536
4290
  using super_t::rows;
3537
4291
  using super_t::columns;
3538
4292
 
3539
- class iterator : public super_t::template iterator_base_t<iterator> {
4293
+ template <template <typename> class MapperT = super_t::template iterator_base_t>
4294
+ class iterator_skelton_t : public MapperT<iterator_skelton_t<MapperT> > {
3540
4295
  public:
3541
4296
  typedef T value_type;
3542
4297
  typedef T& reference;
3543
4298
  typedef T* pointer;
3544
4299
  protected:
4300
+ typedef MapperT<iterator_skelton_t<MapperT> > base_t;
3545
4301
  self_t mat;
3546
- typedef typename super_t::template iterator_base_t<iterator> base_t;
3547
4302
  public:
3548
- unsigned int row() const {return base_t::row(mat);}
3549
- unsigned int column() const {return base_t::column(mat);}
3550
- reference operator*() {
3551
- std::div_t rc(std::div(base_t::idx, mat.columns()));
3552
- return mat((unsigned int)rc.quot, (unsigned int)rc.rem);
3553
- }
3554
- pointer operator->() {
3555
- return &(operator*());
3556
- }
3557
- iterator(const self_t &mat_, const typename base_t::difference_type &idx_ = 0)
3558
- : base_t(idx_), mat(mat_) {}
3559
- iterator()
4303
+ reference operator*() {return mat(base_t::r, base_t::c);}
4304
+ pointer operator->() {return &(operator*());}
4305
+ iterator_skelton_t(const self_t &mat_, const typename base_t::difference_type &idx_ = 0)
4306
+ : base_t(mat_, idx_), mat(mat_) {}
4307
+ iterator_skelton_t()
3560
4308
  : base_t(), mat() {}
3561
4309
  reference operator[](const typename base_t::difference_type &n){
3562
4310
  return *((*this) + n);
3563
4311
  }
3564
4312
  };
4313
+ typedef iterator_skelton_t<super_t::iterator_mapper_t::template all_t> iterator;
3565
4314
  using super_t::begin;
3566
4315
  iterator begin() {return iterator(*this);}
3567
4316
  typename super_t::const_iterator cbegin() const {return super_t::begin();}
3568
4317
  using super_t::end;
3569
- iterator end() {return iterator(*this, rows() * columns());}
4318
+ iterator end() {return iterator(*this).tail();}
3570
4319
  typename super_t::const_iterator cend() const {return super_t::end();}
3571
4320
 
4321
+ template <template <typename> class MapperT>
4322
+ iterator_skelton_t<MapperT> begin() {
4323
+ return iterator_skelton_t<MapperT>(*this);
4324
+ }
4325
+ template <template <typename> class MapperT>
4326
+ typename super_t::template const_iterator_skelton_t<MapperT> cbegin() const {
4327
+ return super_t::template begin<MapperT>();
4328
+ }
4329
+ template <template <typename> class MapperT>
4330
+ iterator_skelton_t<MapperT> end() {
4331
+ return iterator_skelton_t<MapperT>(*this).tail();
4332
+ }
4333
+ template <template <typename> class MapperT>
4334
+ typename super_t::template const_iterator_skelton_t<MapperT> cend() const {
4335
+ return super_t::template end<MapperT>();
4336
+ }
4337
+
3572
4338
  /**
3573
4339
  * Clear elements.
3574
4340
  *
@@ -3911,8 +4677,15 @@ class Matrix : public Matrix_Frozen<T, Array2D_Type, ViewType> {
3911
4677
  using super_t::isSquare;
3912
4678
  using super_t::isDiagonal;
3913
4679
  using super_t::isSymmetric;
4680
+ using super_t::isLowerTriangular;
4681
+ using super_t::isUpperTriangular;
4682
+ using super_t::isHermitian;
3914
4683
  using super_t::isDifferentSize;
3915
4684
  using super_t::isLU;
4685
+ using super_t::isSkewSymmetric;
4686
+ using super_t::isNormal;
4687
+ using super_t::isOrthogonal;
4688
+ using super_t::isUnitary;
3916
4689
 
3917
4690
  /*
3918
4691
  * operator+=, operator-=, operator*=, operator/= are shortcuts of this->replace((*this) op another).