1
+
1
2
#:include "common.fypp"
2
3
#:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES
3
- ! Test Schur decomposition
4
+ ! Test the matrix exponential.
4
5
module test_linalg_expm
5
6
use testdrive, only: error_type, check, new_unittest, unittest_type
7
+ use stdlib_constants
6
8
use stdlib_linalg_constants
7
9
use stdlib_linalg, only: expm, eye, norm, matrix_exp
8
10
use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling, LINALG_ERROR, &
@@ -14,99 +16,120 @@ module test_linalg_expm
14
16
15
17
contains
16
18
17
- !> schur decomposition tests
19
+ ! gcc-15 bugfix utility
20
+ subroutine add_test(tests,new_test)
21
+ type(unittest_type), allocatable, intent(inout) :: tests(:)
22
+ type(unittest_type), intent(in) :: new_test
23
+
24
+ integer :: n
25
+ type(unittest_type), allocatable :: new_tests(:)
26
+
27
+ if (allocated(tests)) then
28
+ n = size(tests)
29
+ else
30
+ n = 0
31
+ end if
32
+
33
+ allocate(new_tests(n+1))
34
+ if (n>0) new_tests(1:n) = tests(1:n)
35
+ new_tests(1+n) = new_test
36
+ call move_alloc(from=new_tests,to=tests)
37
+
38
+ end subroutine add_test
39
+
40
+ !> Exponent of matrix tests
18
41
subroutine test_expm_computation(tests)
19
42
!> Collection of tests
20
43
type(unittest_type), allocatable, intent(out) :: tests(:)
21
44
22
- allocate(tests(0))
23
-
24
- #:for rk,rt,ri in RC_KINDS_TYPES
25
- tests = [tests, new_unittest("expm_${ri}$",test_expm_${ri}$)]
26
- tests = [tests, new_unittest("Error-handling expm_${ri}$",test_error_handling_expm_${ri}$)]
27
- #:endfor
45
+ call add_test(tests,new_unittest("expm",test_expm))
46
+ call add_test(tests,new_unittest("error_handling_expm",test_error_handling_expm))
28
47
29
48
end subroutine test_expm_computation
30
49
31
50
!> Matrix exponential with analytic expression.
32
- #:for rk,rt,ri in RC_KINDS_TYPES
33
- subroutine test_expm_${ri}$(error)
51
+ subroutine test_expm(error)
34
52
type(error_type), allocatable, intent(out) :: error
35
53
! Problem dimension.
36
54
integer(ilp), parameter :: n = 5, m = 6
37
55
! Test matrix.
38
- ${rt}$ :: A(n, n), E(n, n), Eref(n, n)
39
- real(${rk}$) :: err
40
56
integer(ilp) :: i, j
41
57
42
- ! Initialize matrix.
43
- A = 0.0_${rk}$
44
- do i = 1, n-1
45
- A(i, i+1) = m*1.0_${rk}$
46
- enddo
47
-
48
- ! Reference with analytical exponential.
49
- Eref = eye(n, mold=1.0_${rk}$)
50
- do i = 1, n-1
51
- do j = 1, n-i
52
- Eref(i, i+j) = Eref(i, i+j-1)*m/j
58
+ #:for rk,rt,ri in RC_KINDS_TYPES
59
+ block
60
+ ${rt}$ :: A(n, n), E(n, n), Eref(n, n)
61
+ real(${rk}$) :: err
62
+
63
+ ! Initialize matrix.
64
+ A = zero_${rk}$
65
+ do i = 1, n-1
66
+ A(i, i+1) = m*one_${rk}$
67
+ enddo
68
+
69
+ ! Reference with analytical exponential
70
+ Eref = eye(n, mold=one_${rk}$)
71
+ do i = 1, n-1
72
+ do j = 1, n-i
73
+ Eref(i, i+j) = Eref(i, i+j-1)*m/j
74
+ enddo
53
75
enddo
54
- enddo
55
76
56
- ! Compute matrix exponential.
57
- E = expm(A)
77
+ ! Compute matrix exponential.
78
+ E = expm(A)
58
79
59
- ! Check result.
60
- err = norm(Eref - E, "inf")
61
- call check(error, err < (n**2)*epsilon(1.0_${rk}$), "Analytical matrix exponential.")
62
- if (allocated(error)) return
63
- return
64
- end subroutine test_expm_${ri}$
65
- #:endfor
80
+ ! Check result.
81
+ err = norm(Eref - E, "inf")
82
+ print *, err , (n**2)*epsilon(1.0_${rk}$)
83
+ call check(error, err < (n**2)*epsilon(1.0_${rk}$), "Analytical matrix exponential.")
84
+ if (allocated(error)) return
85
+ end block
86
+ #:endfor
87
+ end subroutine test_expm
66
88
67
89
!> Test error handler.
68
- #:for rk,rt,ri in RC_KINDS_TYPES
69
- subroutine test_error_handling_expm_${ri}$(error)
90
+ subroutine test_error_handling_expm(error)
70
91
type(error_type), allocatable, intent(out) :: error
71
92
! Problem dimension.
72
93
integer(ilp), parameter :: n = 5, m = 6
73
94
! Test matrix.
74
- ${rt}$ :: A(n, n), E(n, n)
95
+
75
96
type(linalg_state_type) :: err
76
97
integer(ilp) :: i
77
98
78
- ! Initialize matrix.
79
- A = 0.0_${rk}$
80
- do i = 1, n-1
81
- A(i, i+1) = m*1.0_${rk}$
82
- enddo
83
-
84
- ! Compute matrix exponential.
85
- call matrix_exp(A, E, order=-1, err=err)
86
- ! Check result.
87
- call check(error, err%error(), "Negative Pade order")
88
- if (allocated(error)) return
89
-
90
- call matrix_exp(A, order=-1, err=err)
91
- ! Check result.
92
- call check(error, err%error(), "Negative Pade order")
93
- if (allocated(error)) return
94
-
95
- ! Compute matrix exponential.
96
- call matrix_exp(A, E(:n, :n-1), err=err)
97
- ! Check result.
98
- call check(error, err%error(), "Invalid matrix size")
99
- if (allocated(error)) return
100
-
101
- ! Compute matrix exponential.
102
- call matrix_exp(A(:n, :n-1), err=err)
103
- ! Check result.
104
- call check(error, err%error(), "Invalid matrix size")
105
- if (allocated(error)) return
106
-
107
- return
108
- end subroutine test_error_handling_expm_${ri}$
109
- #:endfor
99
+ #:for rk,rt,ri in RC_KINDS_TYPES
100
+ block
101
+ ${rt}$ :: A(n, n), E(n, n)
102
+ ! Initialize matrix.
103
+ A = zero_${rk}$
104
+ do i = 1, n-1
105
+ A(i, i+1) = m*one_${rk}$
106
+ enddo
107
+
108
+ ! Compute matrix exponential.
109
+ call matrix_exp(A, E, order=-1, err=err)
110
+ ! Check result.
111
+ call check(error, err%error(), "Negative Pade order")
112
+ if (allocated(error)) return
113
+
114
+ call matrix_exp(A, order=-1, err=err)
115
+ ! Check result.
116
+ call check(error, err%error(), "Negative Pade order")
117
+ if (allocated(error)) return
118
+
119
+ ! Compute matrix exponential.
120
+ call matrix_exp(A, E(:n, :n-1), err=err)
121
+ ! Check result.
122
+ call check(error, err%error(), "Invalid matrix size")
123
+ if (allocated(error)) return
124
+
125
+ ! Compute matrix exponential.
126
+ call matrix_exp(A(:n, :n-1), err=err)
127
+ ! Check result.
128
+ call check(error, err%error(), "Invalid matrix size")
129
+ if (allocated(error)) return
130
+ end block
131
+ #:endfor
132
+ end subroutine test_error_handling_expm
110
133
111
134
end module test_linalg_expm
112
135
0 commit comments