Skip to content

Commit 88a49bb

Browse files
authored
Merge branch 'master' into svd
2 parents 9c2f133 + 3bdcc82 commit 88a49bb

11 files changed

+655
-5
lines changed

doc/specs/stdlib_linalg.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,107 @@ Specifically, upper Hessenberg matrices satisfy `a_ij = 0` when `j < i-1`, and l
600600
{!example/linalg/example_is_hessenberg.f90!}
601601
```
602602

603+
## `solve` - Solves a linear matrix equation or a linear system of equations.
604+
605+
### Status
606+
607+
Experimental
608+
609+
### Description
610+
611+
This function computes the solution to a linear matrix equation \( A \cdot x = b \), where \( A \) is a square, full-rank, `real` or `complex` matrix.
612+
613+
Result vector or array `x` returns the exact solution to within numerical precision, provided that the matrix is not ill-conditioned.
614+
An error is returned if the matrix is rank-deficient or singular to working precision.
615+
The solver is based on LAPACK's `*GESV` backends.
616+
617+
### Syntax
618+
619+
`Pure` interface:
620+
621+
`x = ` [[stdlib_linalg(module):solve(interface)]] `(a, b)`
622+
623+
Expert interface:
624+
625+
`x = ` [[stdlib_linalg(module):solve(interface)]] `(a, b [, overwrite_a], err)`
626+
627+
### Arguments
628+
629+
`a`: Shall be a rank-2 `real` or `complex` square array containing the coefficient matrix. It is normally an `intent(in)` argument. If `overwrite_a=.true.`, it is an `intent(inout)` argument and is destroyed by the call.
630+
631+
`b`: Shall be a rank-1 or rank-2 array of the same kind as `a`, containing the right-hand-side vector(s). It is an `intent(in)` argument.
632+
633+
`overwrite_a` (optional): Shall be an input logical flag. if `.true.`, input matrix `a` will be used as temporary storage and overwritten. This avoids internal data allocation. This is an `intent(in)` argument.
634+
635+
`err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument. The function is not `pure` if this argument is provided.
636+
637+
### Return value
638+
639+
For a full-rank matrix, returns an array value that represents the solution to the linear system of equations.
640+
641+
Raises `LINALG_ERROR` if the matrix is singular to working precision.
642+
Raises `LINALG_VALUE_ERROR` if the matrix and rhs vectors have invalid/incompatible sizes.
643+
If `err` is not present, exceptions trigger an `error stop`.
644+
645+
### Example
646+
647+
```fortran
648+
{!example/linalg/example_solve1.f90!}
649+
650+
{!example/linalg/example_solve2.f90!}
651+
```
652+
653+
## `solve_lu` - Solves a linear matrix equation or a linear system of equations (subroutine interface).
654+
655+
### Status
656+
657+
Experimental
658+
659+
### Description
660+
661+
This subroutine computes the solution to a linear matrix equation \( A \cdot x = b \), where \( A \) is a square, full-rank, `real` or `complex` matrix.
662+
663+
Result vector or array `x` returns the exact solution to within numerical precision, provided that the matrix is not ill-conditioned.
664+
An error is returned if the matrix is rank-deficient or singular to working precision.
665+
If all optional arrays are provided by the user, no internal allocations take place.
666+
The solver is based on LAPACK's `*GESV` backends.
667+
668+
### Syntax
669+
670+
Simple (`Pure`) interface:
671+
672+
`call ` [[stdlib_linalg(module):solve_lu(interface)]] `(a, b, x)`
673+
674+
Expert (`Pure`) interface:
675+
676+
`call ` [[stdlib_linalg(module):solve_lu(interface)]] `(a, b, x [, pivot, overwrite_a, err])`
677+
678+
### Arguments
679+
680+
`a`: Shall be a rank-2 `real` or `complex` square array containing the coefficient matrix. It is normally an `intent(in)` argument. If `overwrite_a=.true.`, it is an `intent(inout)` argument and is destroyed by the call.
681+
682+
`b`: Shall be a rank-1 or rank-2 array of the same kind as `a`, containing the right-hand-side vector(s). It is an `intent(in)` argument.
683+
684+
`x`: Shall be a rank-1 or rank-2 array of the same kind and size as `b`, that returns the solution(s) to the system. It is an `intent(inout)` argument, and must have the `contiguous` property.
685+
686+
`pivot` (optional): Shall be a rank-1 array of the same kind and matrix dimension as `a`, providing storage for the diagonal pivot indices. It is an `intent(inout)` arguments, and returns the diagonal pivot indices.
687+
688+
`overwrite_a` (optional): Shall be an input logical flag. if `.true.`, input matrix `a` will be used as temporary storage and overwritten. This avoids internal data allocation. This is an `intent(in)` argument.
689+
690+
### Return value
691+
692+
For a full-rank matrix, returns an array value that represents the solution to the linear system of equations.
693+
694+
Raises `LINALG_ERROR` if the matrix is singular to working precision.
695+
Raises `LINALG_VALUE_ERROR` if the matrix and rhs vectors have invalid/incompatible sizes.
696+
If `err` is not present, exceptions trigger an `error stop`.
697+
698+
### Example
699+
700+
```fortran
701+
{!example/linalg/example_solve3.f90!}
702+
```
703+
603704
## `lstsq` - Computes the least squares solution to a linear matrix equation.
604705

605706
### Status

example/linalg/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ ADD_EXAMPLE(blas_gemv)
2020
ADD_EXAMPLE(lapack_getrf)
2121
ADD_EXAMPLE(lstsq1)
2222
ADD_EXAMPLE(lstsq2)
23+
ADD_EXAMPLE(solve1)
24+
ADD_EXAMPLE(solve2)
25+
ADD_EXAMPLE(solve3)
2326
ADD_EXAMPLE(svd1)
2427
ADD_EXAMPLE(svd2)
2528
ADD_EXAMPLE(determinant)

example/linalg/example_solve1.f90

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
program example_solve1
2+
use stdlib_linalg_constants, only: sp
3+
use stdlib_linalg, only: solve, linalg_state_type
4+
implicit none
5+
6+
real(sp), allocatable :: A(:,:),b(:),x(:)
7+
8+
! Solve a system of 3 linear equations:
9+
! 4x + 3y + 2z = 25
10+
! -2x + 2y + 3z = -10
11+
! 3x - 5y + 2z = -4
12+
13+
! Note: Fortran is column-major! -> transpose
14+
A = transpose(reshape([ 4, 3, 2, &
15+
-2, 2, 3, &
16+
3,-5, 2], [3,3]))
17+
b = [25,-10,-4]
18+
19+
! Get coefficients of y = coef(1) + x*coef(2) + x^2*coef(3)
20+
x = solve(A,b)
21+
22+
print *, 'solution: ',x
23+
! 5.0, 3.0, -2.0
24+
25+
end program example_solve1
26+

example/linalg/example_solve2.f90

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
program example_solve2
2+
use stdlib_linalg_constants, only: sp
3+
use stdlib_linalg, only: solve, linalg_state_type
4+
implicit none
5+
6+
complex(sp), allocatable :: A(:,:),b(:),x(:)
7+
8+
! Solve a system of 3 complex linear equations:
9+
! 2x + iy + 2z = (5-i)
10+
! -ix + (4-3i)y + 6z = i
11+
! 4x + 3y + z = 1
12+
13+
! Note: Fortran is column-major! -> transpose
14+
A = transpose(reshape([(2.0, 0.0),(0.0, 1.0),(2.0,0.0), &
15+
(0.0,-1.0),(4.0,-3.0),(6.0,0.0), &
16+
(4.0, 0.0),(3.0, 0.0),(1.0,0.0)] , [3,3]))
17+
b = [(5.0,-1.0),(0.0,1.0),(1.0,0.0)]
18+
19+
! Get coefficients of y = coef(1) + x*coef(2) + x^2*coef(3)
20+
x = solve(A,b)
21+
22+
print *, 'solution: ',x
23+
! (1.0947,0.3674) (-1.519,-0.4539) (1.1784,-0.1078)
24+
25+
end program example_solve2
26+

example/linalg/example_solve3.f90

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
program example_solve3
2+
use stdlib_linalg_constants, only: sp,ilp
3+
use stdlib_linalg, only: solve_lu, linalg_state_type
4+
implicit none
5+
6+
integer(ilp) :: test
7+
integer(ilp), allocatable :: pivot(:)
8+
complex(sp), allocatable :: A(:,:),b(:),x(:)
9+
10+
! Solve a system of 3 complex linear equations:
11+
! 2x + iy + 2z = (5-i)
12+
! -ix + (4-3i)y + 6z = i
13+
! 4x + 3y + z = 1
14+
15+
! Note: Fortran is column-major! -> transpose
16+
A = transpose(reshape([(2.0, 0.0),(0.0, 1.0),(2.0,0.0), &
17+
(0.0,-1.0),(4.0,-3.0),(6.0,0.0), &
18+
(4.0, 0.0),(3.0, 0.0),(1.0,0.0)] , [3,3]))
19+
20+
! Pre-allocate x
21+
allocate(b(size(A,2)),pivot(size(A,2)))
22+
allocate(x,mold=b)
23+
24+
! Call system many times avoiding reallocation
25+
do test=1,100
26+
b = test*[(5.0,-1.0),(0.0,1.0),(1.0,0.0)]
27+
call solve_lu(A,b,x,pivot)
28+
print "(i3,'-th solution: ',*(1x,f12.6))", test,x
29+
end do
30+
31+
end program example_solve3
32+

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ set(fppFiles
2525
stdlib_linalg_outer_product.fypp
2626
stdlib_linalg_kronecker.fypp
2727
stdlib_linalg_cross_product.fypp
28+
stdlib_linalg_solve.fypp
2829
stdlib_linalg_determinant.fypp
2930
stdlib_linalg_state.fypp
3031
stdlib_linalg_svd.fypp

src/stdlib_linalg.fypp

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ module stdlib_linalg
2222
public :: eye
2323
public :: lstsq
2424
public :: lstsq_space
25+
public :: solve
26+
public :: solve_lu
2527
public :: solve_lstsq
2628
public :: trace
2729
public :: svd
@@ -230,6 +232,100 @@ module stdlib_linalg
230232
#:endfor
231233
end interface is_hessenberg
232234

235+
! Solve linear system system Ax=b.
236+
interface solve
237+
!! version: experimental
238+
!!
239+
!! Solves the linear system \( A \cdot x = b \) for the unknown vector \( x \) from a square matrix \( A \).
240+
!! ([Specification](../page/specs/stdlib_linalg.html#solve-solves-a-linear-matrix-equation-or-a-linear-system-of-equations))
241+
!!
242+
!!### Summary
243+
!! Interface for solving a linear system arising from a general matrix.
244+
!!
245+
!!### Description
246+
!!
247+
!! This interface provides methods for computing the solution of a linear matrix system.
248+
!! Supported data types include `real` and `complex`. No assumption is made on the matrix
249+
!! structure.
250+
!! The function can solve simultaneously either one (from a 1-d right-hand-side vector `b(:)`)
251+
!! or several (from a 2-d right-hand-side vector `b(:,:)`) systems.
252+
!!
253+
!!@note The solution is based on LAPACK's generic LU decomposition based solvers `*GESV`.
254+
!!@note BLAS/LAPACK backends do not currently support extended precision (``xdp``).
255+
!!
256+
#:for nd,ndsuf,nde in ALL_RHS
257+
#:for rk,rt,ri in RC_KINDS_TYPES
258+
#:if rk!="xdp"
259+
module function stdlib_linalg_${ri}$_solve_${ndsuf}$(a,b,overwrite_a,err) result(x)
260+
!> Input matrix a[n,n]
261+
${rt}$, intent(inout), target :: a(:,:)
262+
!> Right hand side vector or array, b[n] or b[n,nrhs]
263+
${rt}$, intent(in) :: b${nd}$
264+
!> [optional] Can A data be overwritten and destroyed?
265+
logical(lk), optional, intent(in) :: overwrite_a
266+
!> [optional] state return flag. On error if not requested, the code will stop
267+
type(linalg_state_type), intent(out) :: err
268+
!> Result array/matrix x[n] or x[n,nrhs]
269+
${rt}$, allocatable, target :: x${nd}$
270+
end function stdlib_linalg_${ri}$_solve_${ndsuf}$
271+
pure module function stdlib_linalg_${ri}$_pure_solve_${ndsuf}$(a,b) result(x)
272+
!> Input matrix a[n,n]
273+
${rt}$, intent(in) :: a(:,:)
274+
!> Right hand side vector or array, b[n] or b[n,nrhs]
275+
${rt}$, intent(in) :: b${nd}$
276+
!> Result array/matrix x[n] or x[n,nrhs]
277+
${rt}$, allocatable, target :: x${nd}$
278+
end function stdlib_linalg_${ri}$_pure_solve_${ndsuf}$
279+
#:endif
280+
#:endfor
281+
#:endfor
282+
end interface solve
283+
284+
! Solve linear system Ax = b using LU decomposition (subroutine interface).
285+
interface solve_lu
286+
!! version: experimental
287+
!!
288+
!! Solves the linear system \( A \cdot x = b \) for the unknown vector \( x \) from a square matrix \( A \).
289+
!! ([Specification](../page/specs/stdlib_linalg.html#solve-lu-solves-a-linear-matrix-equation-or-a-linear-system-of-equations-subroutine-interface))
290+
!!
291+
!!### Summary
292+
!! Subroutine interface for solving a linear system using LU decomposition.
293+
!!
294+
!!### Description
295+
!!
296+
!! This interface provides methods for computing the solution of a linear matrix system using
297+
!! a subroutine. Supported data types include `real` and `complex`. No assumption is made on the matrix
298+
!! structure. Preallocated space for the solution vector `x` is user-provided, and it may be provided
299+
!! for the array of pivot indices, `pivot`. If all pre-allocated work spaces are provided, no internal
300+
!! memory allocations take place when using this interface.
301+
!! The function can solve simultaneously either one (from a 1-d right-hand-side vector `b(:)`)
302+
!! or several (from a 2-d right-hand-side vector `b(:,:)`) systems.
303+
!!
304+
!!@note The solution is based on LAPACK's generic LU decomposition based solvers `*GESV`.
305+
!!@note BLAS/LAPACK backends do not currently support extended precision (``xdp``).
306+
!!
307+
#:for nd,ndsuf,nde in ALL_RHS
308+
#:for rk,rt,ri in RC_KINDS_TYPES
309+
#:if rk!="xdp"
310+
pure module subroutine stdlib_linalg_${ri}$_solve_lu_${ndsuf}$(a,b,x,pivot,overwrite_a,err)
311+
!> Input matrix a[n,n]
312+
${rt}$, intent(inout), target :: a(:,:)
313+
!> Right hand side vector or array, b[n] or b[n,nrhs]
314+
${rt}$, intent(in) :: b${nd}$
315+
!> Result array/matrix x[n] or x[n,nrhs]
316+
${rt}$, intent(inout), contiguous, target :: x${nd}$
317+
!> [optional] Storage array for the diagonal pivot indices
318+
integer(ilp), optional, intent(inout), target :: pivot(:)
319+
!> [optional] Can A data be overwritten and destroyed?
320+
logical(lk), optional, intent(in) :: overwrite_a
321+
!> [optional] state return flag. On error if not requested, the code will stop
322+
type(linalg_state_type), optional, intent(out) :: err
323+
end subroutine stdlib_linalg_${ri}$_solve_lu_${ndsuf}$
324+
#:endif
325+
#:endfor
326+
#:endfor
327+
end interface solve_lu
328+
233329
! Least squares solution to system Ax=b, i.e. such that the 2-norm abs(b-Ax) is minimized.
234330
interface lstsq
235331
!! version: experimental

0 commit comments

Comments
 (0)