gps_pvt 0.9.3 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +159 -3
  3. data/README.md +4 -3
  4. data/Rakefile +24 -0
  5. data/exe/gps2ubx +12 -5
  6. data/exe/gps_pvt +7 -2
  7. data/ext/gps_pvt/Coordinate/Coordinate_wrap.cxx +53 -19
  8. data/ext/gps_pvt/GPS/GPS_wrap.cxx +39 -7
  9. data/ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx +5210 -2058
  10. data/ext/gps_pvt/extconf.rb +6 -5
  11. data/ext/ninja-scan-light/tool/navigation/GLONASS_Solver.h +1 -1
  12. data/ext/ninja-scan-light/tool/navigation/GPS.h +6 -2
  13. data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +1 -1
  14. data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +3 -1
  15. data/ext/ninja-scan-light/tool/navigation/GPS_Solver_MultiFrequency.h +3 -0
  16. data/ext/ninja-scan-light/tool/navigation/RINEX.h +9 -9
  17. data/ext/ninja-scan-light/tool/navigation/SBAS_Solver.h +1 -1
  18. data/ext/ninja-scan-light/tool/navigation/coordinate.h +13 -6
  19. data/ext/ninja-scan-light/tool/param/matrix.h +1020 -247
  20. data/ext/ninja-scan-light/tool/param/matrix_fixed.h +26 -0
  21. data/ext/ninja-scan-light/tool/swig/GPS.i +6 -4
  22. data/ext/ninja-scan-light/tool/swig/SylphideMath.i +139 -36
  23. data/ext/ninja-scan-light/tool/swig/spec/SylphideMath_spec.rb +115 -5
  24. data/gps_pvt.gemspec +3 -1
  25. data/lib/gps_pvt/asn1/asn1.rb +888 -0
  26. data/lib/gps_pvt/asn1/asn1.y +903 -0
  27. data/lib/gps_pvt/asn1/per.rb +182 -0
  28. data/lib/gps_pvt/ntrip.rb +1 -1
  29. data/lib/gps_pvt/receiver/agps.rb +31 -0
  30. data/lib/gps_pvt/receiver/extension.rb +94 -0
  31. data/lib/gps_pvt/receiver/rtcm3.rb +6 -4
  32. data/lib/gps_pvt/receiver.rb +41 -24
  33. data/lib/gps_pvt/rtcm3.rb +24 -34
  34. data/lib/gps_pvt/supl.rb +567 -0
  35. data/lib/gps_pvt/ubx.rb +15 -0
  36. data/lib/gps_pvt/upl/LPP-V17_5_0-Release17.asn +6441 -0
  37. data/lib/gps_pvt/upl/RRLP-V17_0_0-Release17.asn +2780 -0
  38. data/lib/gps_pvt/upl/ULP-V2_0_6-20200720-D.asn +2185 -0
  39. data/lib/gps_pvt/upl/upl.json.gz +0 -0
  40. data/lib/gps_pvt/upl/upl.rb +99 -0
  41. data/lib/gps_pvt/util.rb +1 -0
  42. data/lib/gps_pvt/version.rb +1 -1
  43. metadata +41 -3
@@ -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).