Skip to content

Commit 3b447b9

Browse files
authored
Merge pull request #1091 from Mahmood-Sinan/symtridiag
Add symmetric tridiagonal matrices module
2 parents 923f75f + d6b8572 commit 3b447b9

9 files changed

Lines changed: 970 additions & 128 deletions

doc/specs/stdlib_specialmatrices.md

Lines changed: 119 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ The `stdlib_specialmatrices` module provides derived types and specialized drive
1212
These include:
1313

1414
- Tridiagonal matrices
15-
- Symmetric Tridiagonal matrices (not yet supported)
15+
- Symmetric tridiagonal matrices
1616
- Circulant matrices (not yet supported)
1717
- Toeplitz matrices (not yet supported)
1818
- Hankel matrices (not yet supported)
@@ -32,7 +32,7 @@ Experimental
3232

3333
#### Description
3434

35-
Tridiagonal matrices are ubiquituous in scientific computing and often appear when discretizing 1D differential operators.
35+
Tridiagonal matrices are ubiquitous in scientific computing and often appear when discretizing 1D differential operators.
3636
A generic tridiagonal matrix has the following structure:
3737
$$
3838
A
@@ -64,18 +64,127 @@ Tridiagonal matrices are available with all supported data types as `tridiagonal
6464

6565
- To construct a tridiagonal matrix from already allocated arrays `dl` (lower diagonal, size `n-1`), `dv` (main diagonal, size `n`) and `du` (upper diagonal, size `n-1`):
6666

67-
`A = ` [[stdlib_specialmatrices(module):tridiagonal(interface)]] `(dl, dv, du)`
67+
`A = ` [[stdlib_specialmatrices(module):tridiagonal(interface)]] `(dl, dv, du [, err])`
6868

69-
- To construct a tridiagonal matrix of size `n x n` with constant diagonal elements `dl`, `dv`, and `du`:
69+
- To construct a tridiagonal matrix of size `n x n` with scalar diagonal elements `dl` (lower diagonal), `dv` (main diagonal), and `du` (upper diagonal):
7070

71-
`A = ` [[stdlib_specialmatrices(module):tridiagonal(interface)]] `(dl, dv, du, n)`
71+
`A = ` [[stdlib_specialmatrices(module):tridiagonal(interface)]] `(dl, dv, du, n [, err])`
72+
73+
#### Arguments
74+
75+
##### Constructing from arrays
76+
77+
`A = tridiagonal(dl, dv, du [, err])`
78+
79+
- `dl`: Shall be a rank-1 array of type `real` or `complex` with the same kind as the resulting matrix. It is an `intent(in)` argument.
80+
- `dv`: Shall be a rank-1 array of type `real` or `complex` with the same kind as the resulting matrix. It is an `intent(in)` argument.
81+
- `du`: Shall be a rank-1 array of type `real` or `complex` with the same kind as the resulting matrix. It is an `intent(in)` argument.
82+
- `err` (optional): Shall be a `type(linalg_state_type)` variable. It is an `intent(out)` argument.
83+
If the input arrays are not of compatible sizes, the routine calls `linalg_error_handling`.
84+
If `err` is present, it is assigned `LINALG_VALUE_ERROR`.
85+
If `err` is not present, the program terminates via `error stop`.
86+
In either case, the elements of the resulting matrix `A` are unassigned.
87+
88+
##### Constructing from constant diagonal values
89+
90+
`A = tridiagonal(dl, dv, du, n [, err])`
91+
92+
- `dl`: Shall be a scalar of type `real` or `complex` with the same kind as the resulting matrix. It is an `intent(in)` argument.
93+
- `dv`: Shall be a scalar of type `real` or `complex` with the same kind as the resulting matrix. It is an `intent(in)` argument.
94+
- `du`: Shall be a scalar of type `real` or `complex` with the same kind as the resulting matrix. It is an `intent(in)` argument.
95+
- `n`: Shall be a positive `integer`. It is an `intent(in)` argument.
96+
- `err` (optional): Shall be a `type(linalg_state_type)` variable. It is an `intent(out)` argument.
97+
If a non-positive matrix size is provided, the routine calls `linalg_error_handling`.
98+
If `err` is present, it is assigned `LINALG_VALUE_ERROR`.
99+
If `err` is not present, the program terminates via `error stop`.
100+
In either case, the elements of the resulting matrix `A` are unassigned.
72101

73102
#### Example
74103

75104
```fortran
76105
{!example/specialmatrices/example_tridiagonal_dp_type.f90!}
77106
```
78107

108+
### Symmetric tridiagonal matrices {#Sym_tridiagonal}
109+
110+
#### Status
111+
112+
Experimental
113+
114+
#### Description
115+
116+
Symmetric tridiagonal matrices are a special case of tridiagonal matrices in which the subdiagonal and superdiagonal are identical.
117+
A generic symmetric tridiagonal matrix has the following structure:
118+
$$
119+
A
120+
=
121+
\begin{bmatrix}
122+
a_1 & b_1 \\
123+
b_1 & a_2 & b_2 \\
124+
& \ddots & \ddots & \ddots \\
125+
& & b_{n-2} & a_{n-1} & b_{n-1} \\
126+
& & & b_{n-1} & a_n
127+
\end{bmatrix}.
128+
$$
129+
Hence, only one vector of size `n` and one vector of size `n-1` need to be stored to fully represent the matrix.
130+
This particular structure also lends itself to specialized implementations for many linear algebra tasks.
131+
Interfaces to the most common ones will soon be provided by `stdlib_specialmatrices`.
132+
Symmetric tridiagonal matrices are available with all supported data types as `sym_tridiagonal_<kind>_type`, for example:
133+
134+
- `sym_tridiagonal_sp_type` : Symmetric tridiagonal matrix of size `n` with `real`/`single precision` data.
135+
- `sym_tridiagonal_dp_type` : Symmetric tridiagonal matrix of size `n` with `real`/`double precision` data.
136+
- `sym_tridiagonal_xdp_type` : Symmetric tridiagonal matrix of size `n` with `real`/`extended precision` data.
137+
- `sym_tridiagonal_qp_type` : Symmetric tridiagonal matrix of size `n` with `real`/`quadruple precision` data.
138+
- `sym_tridiagonal_csp_type` : Symmetric tridiagonal matrix of size `n` with `complex`/`single precision` data.
139+
- `sym_tridiagonal_cdp_type` : Symmetric tridiagonal matrix of size `n` with `complex`/`double precision` data.
140+
- `sym_tridiagonal_cxdp_type` : Symmetric tridiagonal matrix of size `n` with `complex`/`extended precision` data.
141+
- `sym_tridiagonal_cqp_type` : Symmetric tridiagonal matrix of size `n` with `complex`/`quadruple precision` data.
142+
143+
144+
#### Syntax
145+
146+
- To construct a symmetric tridiagonal matrix from already allocated arrays `du` (off-diagonal, size `n-1`) and `dv` (main diagonal, size `n`):
147+
148+
`A = ` [[stdlib_specialmatrices(module):sym_tridiagonal(interface)]] `(du, dv [, err])`
149+
150+
- To construct a symmetric tridiagonal matrix of size `n x n` with scalar diagonal elements `du` (off-diagonal) and `dv` (main diagonal):
151+
152+
`A = ` [[stdlib_specialmatrices(module):sym_tridiagonal(interface)]] `(du, dv, n [, err])`
153+
154+
#### Arguments
155+
156+
##### Constructing from arrays
157+
158+
`A = sym_tridiagonal(du, dv [, err])`
159+
160+
- `du`: Shall be a rank-1 array of type `real` or `complex` with the same kind as the resulting matrix. It is an `intent(in)` argument.
161+
- `dv`: Shall be a rank-1 array of type `real` or `complex` with the same kind as the resulting matrix. It is an `intent(in)` argument.
162+
- `err` (optional): Shall be a `type(linalg_state_type)` variable. It is an `intent(out)` argument.
163+
If the input arrays are not of compatible sizes, the routine calls `linalg_error_handling`.
164+
If `err` is present, it is assigned `LINALG_VALUE_ERROR`.
165+
If `err` is not present, the program terminates via `error stop`.
166+
In either case, the elements of the resulting matrix `A` are unassigned.
167+
168+
##### Constructing from constant diagonal values
169+
170+
`A = sym_tridiagonal(du, dv, n [, err])`
171+
172+
- `du`: Shall be a scalar of type `real` or `complex` with the same kind as the resulting matrix. It is an `intent(in)` argument.
173+
- `dv`: Shall be a scalar of type `real` or `complex` with the same kind as the resulting matrix. It is an `intent(in)` argument.
174+
- `n`: Shall be a positive `integer`. It is an `intent(in)` argument.
175+
- `err` (optional): Shall be a `type(linalg_state_type)` variable. It is an `intent(out)` argument.
176+
If a non-positive matrix size is provided, the routine calls `linalg_error_handling`.
177+
If `err` is present, it is assigned `LINALG_VALUE_ERROR`.
178+
If `err` is not present, the program terminates via `error stop`.
179+
In either case, the elements of the resulting matrix `A` are unassigned.
180+
181+
#### Example
182+
183+
```fortran
184+
{!example/specialmatrices/example_sym_tridiagonal_dp_type.f90!}
185+
```
186+
187+
79188
## Specialized drivers for linear algebra tasks
80189

81190
Below is a list of all the specialized drivers for linear algebra tasks currently provided by the `stdlib_specialmatrices` module.
@@ -90,7 +199,7 @@ Experimental
90199

91200
With the exception of `extended precision` and `quadruple precision`, all the types provided by `stdlib_specialmatrices` benefit from specialized kernels for matrix-vector products accessible via the common `spmv` interface.
92201

93-
- For `tridiagonal` matrices, the backend is either LAPACK `lagtm` or the generalized routine `glagtm`, depending on the values and types of `alpha` and `beta`.
202+
- For `tridiagonal` and `symmetric tridiagonal` matrices, the backend is either LAPACK `lagtm` or the generalized routine `glagtm`, depending on the values and types of `alpha` and `beta`.
94203

95204
#### Syntax
96205

@@ -115,6 +224,9 @@ With the exception of `extended precision` and `quadruple precision`, all the ty
115224
```fortran
116225
{!example/specialmatrices/example_specialmatrices_dp_spmv.f90!}
117226
```
227+
```fortran
228+
{!example/specialmatrices/example_specialmatrices_cdp_spmv.f90!}
229+
```
118230

119231
## Utility functions
120232

@@ -186,7 +298,7 @@ Experimental
186298

187299
#### Description
188300

189-
The definition of all standard artihmetic operators have been overloaded to be applicable for the matrix types defined by `stdlib_specialmatrices`:
301+
The definition of all standard arithmetic operators have been overloaded to be applicable for the matrix types defined by `stdlib_specialmatrices`:
190302

191303
- Overloading the `+` operator for adding two matrices of the same type and kind.
192304
- Overloading the `-` operator for subtracting two matrices of the same type and kind.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
ADD_EXAMPLE(specialmatrices_dp_spmv)
22
ADD_EXAMPLE(specialmatrices_cdp_spmv)
33
ADD_EXAMPLE(tridiagonal_dp_type)
4+
ADD_EXAMPLE(sym_tridiagonal_dp_type)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
program example_sym_tridiagonal_matrix
2+
use stdlib_linalg_constants, only: dp
3+
use stdlib_specialmatrices, only: sym_tridiagonal_dp_type, sym_tridiagonal
4+
implicit none
5+
6+
integer, parameter :: n = 5
7+
type(sym_tridiagonal_dp_type) :: A
8+
real(dp) :: du(n - 1), dv(n)
9+
10+
! Generate random symmteric tridiagonal elements.
11+
call random_number(du)
12+
call random_number(dv)
13+
14+
! Create the corresponding symmetric tridiagonal matrix.
15+
A = sym_tridiagonal(du, dv)
16+
17+
end program example_sym_tridiagonal_matrix

example/specialmatrices/example_tridiagonal_dp_type.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
program example_tridiagonal_matrix
22
use stdlib_linalg_constants, only: dp
3-
use stdlib_specialmatrices
3+
use stdlib_specialmatrices, only: tridiagonal_dp_type, tridiagonal
44
implicit none
55

66
integer, parameter :: n = 5

src/specialmatrices/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
set(specialmatrices_fppFiles
22
stdlib_specialmatrices.fypp
33
stdlib_specialmatrices_tridiagonal.fypp
4+
stdlib_specialmatrices_sym_tridiagonal.fypp
45
)
56

67
set(specialmatrices_cppFiles

0 commit comments

Comments
 (0)