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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +159 -3
- data/README.md +4 -3
- data/Rakefile +24 -0
- data/exe/gps2ubx +12 -5
- data/exe/gps_pvt +7 -2
- data/ext/gps_pvt/Coordinate/Coordinate_wrap.cxx +53 -19
- data/ext/gps_pvt/GPS/GPS_wrap.cxx +39 -7
- data/ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx +5210 -2058
- data/ext/gps_pvt/extconf.rb +6 -5
- data/ext/ninja-scan-light/tool/navigation/GLONASS_Solver.h +1 -1
- data/ext/ninja-scan-light/tool/navigation/GPS.h +6 -2
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +1 -1
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +3 -1
- data/ext/ninja-scan-light/tool/navigation/GPS_Solver_MultiFrequency.h +3 -0
- data/ext/ninja-scan-light/tool/navigation/RINEX.h +9 -9
- data/ext/ninja-scan-light/tool/navigation/SBAS_Solver.h +1 -1
- data/ext/ninja-scan-light/tool/navigation/coordinate.h +13 -6
- data/ext/ninja-scan-light/tool/param/matrix.h +1020 -247
- data/ext/ninja-scan-light/tool/param/matrix_fixed.h +26 -0
- data/ext/ninja-scan-light/tool/swig/GPS.i +6 -4
- data/ext/ninja-scan-light/tool/swig/SylphideMath.i +139 -36
- data/ext/ninja-scan-light/tool/swig/spec/SylphideMath_spec.rb +115 -5
- data/gps_pvt.gemspec +3 -1
- data/lib/gps_pvt/asn1/asn1.rb +888 -0
- data/lib/gps_pvt/asn1/asn1.y +903 -0
- data/lib/gps_pvt/asn1/per.rb +182 -0
- data/lib/gps_pvt/ntrip.rb +1 -1
- data/lib/gps_pvt/receiver/agps.rb +31 -0
- data/lib/gps_pvt/receiver/extension.rb +94 -0
- data/lib/gps_pvt/receiver/rtcm3.rb +6 -4
- data/lib/gps_pvt/receiver.rb +41 -24
- data/lib/gps_pvt/rtcm3.rb +24 -34
- data/lib/gps_pvt/supl.rb +567 -0
- data/lib/gps_pvt/ubx.rb +15 -0
- data/lib/gps_pvt/upl/LPP-V17_5_0-Release17.asn +6441 -0
- data/lib/gps_pvt/upl/RRLP-V17_0_0-Release17.asn +2780 -0
- data/lib/gps_pvt/upl/ULP-V2_0_6-20200720-D.asn +2185 -0
- data/lib/gps_pvt/upl/upl.json.gz +0 -0
- data/lib/gps_pvt/upl/upl.rb +99 -0
- data/lib/gps_pvt/util.rb +1 -0
- data/lib/gps_pvt/version.rb +1 -1
- 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
|
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
|
1145
|
-
struct check_complex_t<
|
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
|
1318
|
-
|
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)
|
1327
|
-
|
1328
|
-
|
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()
|
1444
|
+
//iterator_t() // ctor.
|
1336
1445
|
|
1337
1446
|
// required for bidirectional iterator
|
1338
|
-
self_type &operator--() {
|
1339
|
-
self_type operator--(int) {
|
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
|
-
|
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
|
1384
|
-
|
1783
|
+
typedef const T reference;
|
1784
|
+
struct pointer {
|
1785
|
+
reference value;
|
1786
|
+
const T *operator->() const {return &value;}
|
1787
|
+
};
|
1385
1788
|
protected:
|
1386
|
-
typedef
|
1789
|
+
typedef MapperT<const_iterator_skelton_t<MapperT> > base_t;
|
1387
1790
|
self_t mat;
|
1388
|
-
mutable T tmp;
|
1389
1791
|
public:
|
1390
|
-
|
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
|
-
|
1794
|
+
pointer p = {operator*()};
|
1795
|
+
return p;
|
1398
1796
|
}
|
1399
|
-
|
1400
|
-
: base_t(idx_), mat(mat_)
|
1401
|
-
|
1402
|
-
: base_t(), mat()
|
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
|
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
|
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)
|
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
|
-
|
1619
|
-
|
1620
|
-
|
1621
|
-
|
1622
|
-
|
1623
|
-
|
1624
|
-
|
1625
|
-
|
1626
|
-
|
1627
|
-
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
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
|
-
|
2071
|
-
|
2072
|
-
|
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
|
2076
|
-
|
2077
|
-
|
2078
|
-
|
2079
|
-
|
2080
|
-
|
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
|
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
|
-
|
2085
|
-
|
2086
|
-
|
2087
|
-
|
2088
|
-
|
2089
|
-
|
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
|
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>::
|
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
|
-
*
|
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
|
-
|
2262
|
-
return (*this)(0, 0);
|
2263
|
-
|
2264
|
-
|
2265
|
-
|
2266
|
-
|
2267
|
-
|
2268
|
-
|
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
|
-
|
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)
|
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)
|
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
|
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
|
-
|
2467
|
-
|
2468
|
-
|
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)
|
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)
|
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)
|
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)
|
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
|
-
|
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
|
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
|
2651
|
-
// return
|
2652
|
-
/* The above is as definition, however, double calculation may
|
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
|
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 +=
|
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
|
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
|
3340
|
+
typename value_t::real_t x_abs2(x.norm2F());
|
2679
3341
|
if(x_abs2 == 0){return x_abs2;}
|
2680
3342
|
|
2681
|
-
typename
|
2682
|
-
typename
|
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
|
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
|
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
|
-
(!
|
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
|
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
|
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
|
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
|
2887
|
-
typename
|
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<
|
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
|
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
|
-
|
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
|
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(
|
3036
|
-
throw std::runtime_error("
|
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
|
3041
|
-
A_m2_abs(
|
3042
|
-
A_m1_abs(
|
3043
|
-
typename
|
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(
|
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(
|
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
|
3090
|
-
approx_lambda +=
|
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
|
3100
|
-
typename
|
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) /=
|
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
|
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
|
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
|
-
|
3549
|
-
|
3550
|
-
|
3551
|
-
|
3552
|
-
|
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
|
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).
|