Skip to content

Commit 6aa4ed1

Browse files
committed
coeffwise scalar assignment, diagonal non-const access via operator(), bug fixing and testing of triangular TS, minor changes
1 parent 62573a0 commit 6aa4ed1

8 files changed

Lines changed: 124 additions & 88 deletions

File tree

fdaPDE/linear_algebra.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ template <typename XprType> struct MatrixCoeffWiseExpr;
3333
// triangular views
3434
[[maybe_unused]] constexpr int Upper = 0; // lower triangular view of matrix
3535
[[maybe_unused]] constexpr int Lower = 1; // upper triangular view of matrix
36-
[[maybe_unused]] constexpr int UnitUpper = 2; // lower triangular view of matrix with ones on the diagonal
37-
[[maybe_unused]] constexpr int UnitLower = 3; // upper triangular view of matrix with ones on the diagonal
3836

3937
[[maybe_unused]] static constexpr int LhsMode = 0;
4038
[[maybe_unused]] static constexpr int RhsMode = 1;

fdaPDE/src/linear_algebra/coeffwise.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,13 @@ struct MatrixCoeffWiseOp : public MatrixCoeffWiseExpr<MatrixCoeffWiseOp<XprType_
137137
template <typename XprType__>
138138
requires(std::is_constructible_v<XprTypeNested, XprType__>)
139139
constexpr MatrixCoeffWiseOp(XprType__&& xpr, CoeffOp op) : xpr_(std::forward<XprType__>(xpr)), op_(op) { }
140+
// scalar assignment
141+
template <typename Scalar_>
142+
requires(std::is_convertible_v<Scalar_, Scalar>)
143+
constexpr MatrixCoeffWiseOp& operator=(Scalar_ rhs) {
144+
internals::scalar_cwise_assignment_executor::run(*this, rhs, [](auto& l, const Scalar_& r) { l = r; });
145+
return *this;
146+
}
140147
// access
141148
constexpr Scalar operator()(int i, int j) const {
142149
fdapde_assert(i >= 0 && i < rows() && j >= 0 && j < cols());

fdaPDE/src/linear_algebra/diagonal.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,18 @@ template <typename XprType_> struct Diagonal : public MatrixExpr<Diagonal<XprTyp
8484
using Base::operator=;
8585
// const access
8686
constexpr Scalar operator()(int i, int j) const {
87-
fdapde_assert(i >= 0 && i < rows() && j >= 0 && j < 1);
87+
fdapde_assert(i >= 0 && i < rows() && j >= 0 && j < cols());
8888
return xpr_(i, i);
8989
}
9090
constexpr Scalar operator[](int i) const {
9191
fdapde_assert(i >= 0 && i < rows());
9292
return xpr_(i, i);
9393
}
9494
// non-const access
95+
constexpr Scalar& operator()(int i, int j) {
96+
fdapde_assert(i >= 0 && i < rows() && j >= 0 && j < cols());
97+
return xpr_(i, i);
98+
}
9599
constexpr Scalar& operator[](int i) {
96100
fdapde_assert(i >= 0 && i < rows());
97101
return xpr_(i, i);

fdaPDE/src/linear_algebra/matrix.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ class MatrixBase : public MatrixExpr<MatrixType> {
141141
static constexpr int NestAsRef = MatrixType::NestAsRef;
142142
static constexpr int ReadOnly = std::is_const_v<Scalar_>;
143143
using assignment_executor = std::conditional_t<
144-
Rows_ == 1 || Cols_ == 1, internals::vector_assignment_executor, internals::generic_assignment_executor>;
144+
(Rows_ == 1 || Cols_ == 1) && !(Rows_ == 1 && Cols_ == 1), internals::vector_assignment_executor,
145+
internals::generic_assignment_executor>;
145146

146147
// constructors
147148
constexpr MatrixBase() :

fdaPDE/src/linear_algebra/partial_piv_lu.h

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@ template <typename XprType_> class PartialPivLU {
3232
using Scalar = typename XprType::Scalar;
3333
public:
3434
// constructors
35-
constexpr PartialPivLU() : lu_(), P_(), info_(0), rank_(0) { }
35+
constexpr PartialPivLU() : L_(), U_(), P_(), info_(0), rank_(0) { }
3636
template <typename XprType>
37-
constexpr explicit PartialPivLU(const MatrixExpr<XprType>& m) : lu_(), P_(), info_(0), rank_(0) {
37+
constexpr explicit PartialPivLU(const MatrixExpr<XprType>& m) : L_(), U_(), P_(), info_(0), rank_(0) {
3838
compute(m);
3939
}
4040

4141
// build LU factorization of m via Doolittle LU with partial pivoting
4242
template <typename XprType> constexpr void compute(const MatrixExpr<XprType>& m) {
4343
const int n = m.rows();
44-
lu_ = m;
44+
Matrix<Scalar, Rows, Cols> lu = m;
4545
Scalar pivot_threshold = std::numeric_limits<Scalar>::epsilon() * m.inf_norm();
4646
// initialization
4747
Vector<int, Rows> perm;
@@ -55,7 +55,7 @@ template <typename XprType_> class PartialPivLU {
5555
int pivot_index = k;
5656
Scalar max_val = Scalar(0);
5757
for (int r = k; r < n; ++r) {
58-
Scalar av = fdapde::abs(lu_(r, k));
58+
Scalar av = fdapde::abs(lu(r, k));
5959
if (av > max_val) {
6060
max_val = av;
6161
pivot_index = r;
@@ -68,44 +68,48 @@ template <typename XprType_> class PartialPivLU {
6868
break;
6969
}
7070
if (pivot_index != k) { // row swap
71-
for (int c = 0; c < m.cols(); ++c) { std::swap(lu_(k, c), lu_(pivot_index, c)); }
71+
for (int c = 0; c < m.cols(); ++c) { std::swap(lu(k, c), lu(pivot_index, c)); }
7272
std::swap(perm[k], perm[pivot_index]);
7373
}
7474
// eliminate column below pivot
7575
for (int r = k + 1; r < n; ++r) {
76-
Scalar alpha = lu_(r, k) / lu_(k, k);
77-
lu_(r, k) = alpha;
78-
for (int c = k + 1; c < m.cols(); ++c) { lu_(r, c) -= alpha * lu_(k, c); }
76+
Scalar alpha = lu(r, k) / lu(k, k);
77+
lu(r, k) = alpha;
78+
for (int c = k + 1; c < m.cols(); ++c) { lu(r, c) -= alpha * lu(k, c); }
7979
}
8080
}
81+
L_ = lu.template triangular_block<Lower>();
82+
L_.diagonal().cwise() = 1; // L_ is unit-lower
83+
U_ = lu.template triangular_block<Upper>();
8184
P_ = PermutationMatrix<Rows, Cols>(perm);
8285
return;
8386
}
8487
// observers
8588
constexpr const PermutationMatrix<Rows, Cols>& P() const { return P_; }
86-
constexpr auto L() const { return lu_.template triangular_block<UnitLower>(); }
87-
constexpr auto U() const { return lu_.template triangular_block<Upper>(); }
89+
constexpr auto L() const { return L_; }
90+
constexpr auto U() const { return U_; }
8891
constexpr int info() const { return info_; } // 0 = success, >0 = first zero pivot
8992
constexpr int rank() const { return rank_; }
9093
constexpr Scalar determinant() const {
9194
Scalar d = 1;
92-
for (int i = 0, n = lu_.rows(); i < n; ++i) { d *= lu_(i, i); }
95+
for (int i = 0, n = U_.rows(); i < n; ++i) { d *= U_(i, i); }
9396
return P_.determinant() * d;
9497
}
9598
// solve Ax = b via PA = LU
9699
template <typename RhsXprType> constexpr auto solve(const MatrixExpr<RhsXprType>& b) const {
97-
fdapde_assert(b.rows() == lu_.rows() && b.cols() > 0);
100+
fdapde_assert(b.rows() == L_.rows() && b.rows() == U_.rows() && b.cols() > 0);
98101
fdapde_assert(info_ == 0);
99102

100103
constexpr int RhsRows = RhsXprType::Rows;
101104
constexpr int RhsCols = RhsXprType::Cols;
102105
Matrix<Scalar, RhsRows, RhsCols> y = P_ * b;
103-
auto z = L().solve(y); // forward substitute
104-
auto x = U().solve(z); // backward substitute
106+
auto z = L_.solve(y); // forward substitute
107+
auto x = U_.solve(z); // backward substitute
105108
return x;
106109
}
107110
private:
108-
Matrix<Scalar, Rows, Cols, RowMajor> lu_; // holds both L (unit lower) and U (upper)
111+
TriangularMatrix<Scalar, Rows, Cols, Lower> L_;
112+
TriangularMatrix<Scalar, Rows, Cols, Upper> U_;
109113
PermutationMatrix<Rows, Cols> P_;
110114
int info_;
111115
int rank_;

fdaPDE/src/linear_algebra/traits.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ static constexpr bool same_static_shape_weak_v = same_static_shape_weak<LhsXprTy
7979
// true if Xpr represents a vector expression
8080
template <typename XprType_> struct is_vector_shaped {
8181
using XprType = std::decay_t<XprType_>;
82-
static constexpr bool value = (XprType::Rows == 1 || XprType::Cols == 1);
82+
static constexpr bool value =
83+
(XprType::Rows == 1 || XprType::Cols == 1) && !(XprType::Rows == 1 && XprType::Cols == 1);
8384
};
8485
template <typename XprType> static constexpr bool is_vector_shaped_v = is_vector_shaped<XprType>::value;
8586

0 commit comments

Comments
 (0)