gps_pvt 0.9.3 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- 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).
|