@@ -23,7 +23,9 @@ module test_linalg_solve_chol
2323
2424 #:for rk,rt,ri in RC_KINDS_TYPES
2525 call add_test(tests,new_unittest("solve_chol_${ri}$",test_solve_chol_${ri}$))
26+ call add_test(tests,new_unittest("solve_chol_upper_${ri}$",test_solve_chol_upper_${ri}$))
2627 call add_test(tests,new_unittest("cholesky_solve_${ri}$",test_cholesky_solve_${ri}$))
28+ call add_test(tests,new_unittest("cholesky_solve_upper_${ri}$",test_cholesky_solve_upper_${ri}$))
2729 call add_test(tests,new_unittest("cholesky_solve_overwrite_${ri}$",test_cholesky_solve_overwrite_${ri}$))
2830 call add_test(tests,new_unittest("solve_chol_multi_rhs_${ri}$",test_solve_chol_multi_rhs_${ri}$))
2931 #:endfor
@@ -71,6 +73,47 @@ module test_linalg_solve_chol
7173
7274 #:endfor
7375
76+ !> Test solve_chol with upper triangular factors (lower=.false.)
77+ #:for rk,rt,ri in RC_KINDS_TYPES
78+ subroutine test_solve_chol_upper_${ri}$(error)
79+ type(error_type), allocatable, intent(out) :: error
80+
81+ integer(ilp), parameter :: n = 3_ilp
82+ real(${rk}$), parameter :: tol = 100*sqrt(epsilon(0.0_${rk}$))
83+ ${rt}$ :: a(n,n), u(n,n), b(n), x(n), x_expected(n)
84+ type(linalg_state_type) :: state
85+
86+ ! Set symmetric positive definite matrix
87+ a(1,:) = [4, 2, 2]
88+ a(2,:) = [2, 5, 1]
89+ a(3,:) = [2, 1, 6]
90+
91+ ! Known solution
92+ x_expected = [1, 2, 3]
93+
94+ ! Compute RHS: b = A * x_expected
95+ b = matmul(a, x_expected)
96+
97+ ! Compute Cholesky factorization (upper triangular: A = U^T * U)
98+ call cholesky(a, u, lower=.false., err=state)
99+
100+ call check(error, state%ok(), 'cholesky factorization (upper) failed: '//state%print())
101+ if (allocated(error)) return
102+
103+ ! Solve using upper Cholesky factors
104+ call solve_chol(u, b, x, lower=.false., err=state)
105+
106+ call check(error, state%ok(), 'solve_chol (upper) failed: '//state%print())
107+ if (allocated(error)) return
108+
109+ ! Check solution
110+ call check(error, all(abs(x - x_expected) < tol), 'solve_chol (upper): solution mismatch')
111+ if (allocated(error)) return
112+
113+ end subroutine test_solve_chol_upper_${ri}$
114+
115+ #:endfor
116+
74117 !> Test cholesky_solve (one-shot) - default preserves A
75118 #:for rk,rt,ri in RC_KINDS_TYPES
76119 subroutine test_cholesky_solve_${ri}$(error)
@@ -111,6 +154,46 @@ module test_linalg_solve_chol
111154
112155 #:endfor
113156
157+ !> Test cholesky_solve with upper triangular (lower=.false.)
158+ #:for rk,rt,ri in RC_KINDS_TYPES
159+ subroutine test_cholesky_solve_upper_${ri}$(error)
160+ type(error_type), allocatable, intent(out) :: error
161+
162+ integer(ilp), parameter :: n = 3_ilp
163+ real(${rk}$), parameter :: tol = 100*sqrt(epsilon(0.0_${rk}$))
164+ ${rt}$ :: a(n,n), a_copy(n,n), b(n), x(n), x_expected(n)
165+ type(linalg_state_type) :: state
166+
167+ ! Set symmetric positive definite matrix
168+ a(1,:) = [4, 2, 2]
169+ a(2,:) = [2, 5, 1]
170+ a(3,:) = [2, 1, 6]
171+ a_copy = a
172+
173+ ! Known solution
174+ x_expected = [1, 2, 3]
175+
176+ ! Compute RHS: b = A * x_expected
177+ b = matmul(a, x_expected)
178+
179+ ! One-shot solve with upper triangular (A should be preserved by default)
180+ call cholesky_solve(a, b, x, lower=.false., err=state)
181+
182+ call check(error, state%ok(), 'cholesky_solve (upper) failed: '//state%print())
183+ if (allocated(error)) return
184+
185+ ! Check solution
186+ call check(error, all(abs(x - x_expected) < tol), 'cholesky_solve (upper): solution mismatch')
187+ if (allocated(error)) return
188+
189+ ! Check that A is preserved (default behavior)
190+ call check(error, all(abs(a - a_copy) < tol), 'cholesky_solve (upper): A should be preserved')
191+ if (allocated(error)) return
192+
193+ end subroutine test_cholesky_solve_upper_${ri}$
194+
195+ #:endfor
196+
114197 !> Test cholesky_solve with overwrite_a=.true.
115198 #:for rk,rt,ri in RC_KINDS_TYPES
116199 subroutine test_cholesky_solve_overwrite_${ri}$(error)
0 commit comments