@@ -13,6 +13,7 @@ module stdlib_sparse_kinds
13
13
private
14
14
public :: sparse_full, sparse_lower, sparse_upper
15
15
public :: sparse_op_none, sparse_op_transpose, sparse_op_hermitian
16
+ public :: Tridiagonal, dense
16
17
!! version: experimental
17
18
!!
18
19
!! Base sparse type holding the meta data related to the storage capacity of a matrix.
@@ -128,6 +129,81 @@ module stdlib_sparse_kinds
128
129
end type
129
130
#:endfor
130
131
132
+ !------------------------------------------------------
133
+ !----- -----
134
+ !----- Tridiagonal matrix implementations -----
135
+ !----- -----
136
+ !------------------------------------------------------
137
+
138
+ !! version: experimental
139
+ !!
140
+ !! Tridiagonal matrix
141
+ #:for k1, t1, s1 in (KINDS_TYPES)
142
+ type, public, extends(sparse_type) :: Tridiagonal_${s1}$_type
143
+ ${t1}$, allocatable :: dl(:), dv(:), du(:)
144
+ end type
145
+ #:endfor
146
+
147
+ interface Tridiagonal
148
+ !! This interface provides different methods to construct a
149
+ !! `Tridiagonal` matrix. Only the non-zero elements of \( A \) are
150
+ !! stored, i.e.
151
+ !!
152
+ !! \[
153
+ !! A
154
+ !! =
155
+ !! \begin{bmatrix}
156
+ !! a_1 & b_1 \\
157
+ !! c_1 & a_2 & b_2 \\
158
+ !! & \ddots & \ddots & \ddots \\
159
+ !! & & c_{n-2} & a_{n-1} & b_{n-1} \\
160
+ !! & & & c_{n-1} & a_n
161
+ !! \end{bmatrix}.
162
+ !! \]
163
+ !!
164
+ !! #### Syntax
165
+ !!
166
+ !! - Construct a real `Tridiagonal` matrix from rank-1 arrays:
167
+ !!
168
+ !! ```fortran
169
+ !! integer, parameter :: n
170
+ !! real(dp), allocatable :: dl(:), dv(:), du(:)
171
+ !! type(Tridiagonal_rdp_type) :: A
172
+ !! integer :: i
173
+ !!
174
+ !! dl = [(i, i=1, n-1)]; dv = [(2*i, i=1, n)]; du = [(3*i, i=1, n)]
175
+ !! A = Tridiagonal(dl, dv, du)
176
+ !! ```
177
+ !!
178
+ !! - Construct a real `Tridiagonal` matrix with constant diagonals:
179
+ !!
180
+ !! ```fortran
181
+ !! integer, parameter :: n
182
+ !! real(dp), parameter :: a = 1.0_dp, b = 1.0_dp, c = 2.0_dp
183
+ !! type(Tridiagonal_rdp_type) :: A
184
+ !!
185
+ !! A = Tridiagonal(a, b, c, n)
186
+ !! ```
187
+ #:for k1, t1, s1 in (KINDS_TYPES)
188
+ module procedure initialize_tridiagonal_${s1}$
189
+ module procedure initialize_constant_tridiagonal_${s1}$
190
+ #:endfor
191
+ end interface
192
+
193
+ interface dense
194
+ !! This interface provides methods to convert a `Tridiagonal` matrix
195
+ !! to a regular rank-2 array.
196
+ !!
197
+ !! #### Syntax
198
+ !!
199
+ !! ```fortran
200
+ !! B = dense(A)
201
+ !! ```
202
+ #:for k1, t1, s1 in (KINDS_TYPES)
203
+ module procedure tridiagonal_to_dense_${s1}$
204
+ #:endfor
205
+ end interface
206
+
131
207
contains
132
208
133
209
!! (re)Allocate matrix memory for the COO type
@@ -589,5 +665,77 @@ contains
589
665
end subroutine
590
666
591
667
#:endfor
668
+
669
+ !------------------------------------------------------
670
+ !----- -----
671
+ !----- Tridiagonal matrix implementations -----
672
+ !----- -----
673
+ !------------------------------------------------------
674
+
675
+ #:for k1, t1, s1 in (KINDS_TYPES)
676
+ pure function initialize_tridiagonal_${s1}$(dl, dv, du) result(A)
677
+ !! Construct a `Tridiagonal` matrix from the rank-1 arrays
678
+ !! `dl`, `dv` and `du`.
679
+ ${t1}$, intent(in) :: dl(:), dv(:), du(:)
680
+ !! Tridiagonal matrix elements.
681
+ type(Tridiagonal_${s1}$_type) :: A
682
+ !! Corresponding Tridiagonal matrix.
683
+
684
+ ! Internal variables.
685
+ integer(ilp) :: n
686
+
687
+ ! Sanity check.
688
+ n = size(dv)
689
+ if (size(dl) /= n-1) error stop "Vector dl does not have the correct length."
690
+ if (size(du) /= n-1) error stop "Vector du does not have the correct length."
691
+
692
+ ! Description of the matrix.
693
+ A%nrows = n ; A%ncols = n ; A%nnz = n + 2*(n-1)
694
+ ! Matrix elements.
695
+ A%dl = dl ; A%dv = dv ; A%du = du
696
+ end function
697
+
698
+ pure function initialize_constant_tridiagonal_${s1}$(dl, dv, du, n) result(A)
699
+ !! Construct a `Tridiagonal` matrix with constant elements.
700
+ ${t1}$, intent(in) :: dl, dv, du
701
+ !! Tridiagonal matrix elements.
702
+ integer(ilp), intent(in) :: n
703
+ !! Matrix dimension.
704
+ type(Tridiagonal_${s1}$_type) :: A
705
+ !! Corresponding Tridiagonal matrix.
706
+
707
+ ! Internal variables.
708
+ integer(ilp) :: i
709
+
710
+ ! Description of the matrix.
711
+ A%nrows = n ; A%ncols = n ; A%nnz = n + 2*(n-1)
712
+ ! Matrix elements.
713
+ A%dl = [(dl, i = 1, n-1)]
714
+ A%dv = [(dv, i = 1, n)]
715
+ A%du = [(du, i = 1, n-1)]
716
+ end function
717
+
718
+ pure function tridiagonal_to_dense_${s1}$(A) result(B)
719
+ !! Convert a `Tridiagonal` matrix to its dense representation.
720
+ type(Tridiagonal_${s1}$_type), intent(in) :: A
721
+ !! Input Tridiagonal matrix.
722
+ ${t1}$, allocatable :: B(:, :)
723
+ !! Corresponding dense matrix.
724
+
725
+ ! Internal variables.
726
+ integer(ilp) :: i
727
+
728
+ associate (n => A%nrows)
729
+ allocate(B(n, n)) ; B = 0.0_${k1}$
730
+ B(1, 1) = A%dv(1) ; B(1, 2) = A%du(1)
731
+ do concurrent (i=2:n-1)
732
+ B(i, i-1) = A%dl(i-1)
733
+ B(i, i) = A%dv(i)
734
+ B(i, i+1) = A%du(i)
735
+ enddo
736
+ B(n, n-1) = A%dl(n-1) ; B(n, n) = A%dv(n)
737
+ end associate
738
+ end function
739
+ #:endfor
592
740
593
- end module stdlib_sparse_kinds
741
+ end module stdlib_sparse_kinds
0 commit comments