Skip to content

Commit 28ae6e0

Browse files
authored
Merge pull request #798 from perazz/determinant
linalg: determinant
2 parents f44133b + 3c72b06 commit 28ae6e0

File tree

9 files changed

+621
-2
lines changed

9 files changed

+621
-2
lines changed

doc/specs/stdlib_linalg.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,3 +599,77 @@ Specifically, upper Hessenberg matrices satisfy `a_ij = 0` when `j < i-1`, and l
599599
```fortran
600600
{!example/linalg/example_is_hessenberg.f90!}
601601
```
602+
603+
## `det` - Computes the determinant of a square matrix
604+
605+
### Status
606+
607+
Experimental
608+
609+
### Description
610+
611+
This function computes the determinant of a `real` or `complex` square matrix.
612+
613+
This interface comes with a `pure` version `det(a)`, and a non-pure version `det(a,overwrite_a,err)` that
614+
allows for more expert control.
615+
616+
### Syntax
617+
618+
`c = ` [[stdlib_linalg(module):det(interface)]] `(a [, overwrite_a, err])`
619+
620+
### Arguments
621+
622+
`a`: Shall be a rank-2 square array
623+
624+
`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.
625+
This is an `intent(in)` argument.
626+
627+
`err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument.
628+
629+
### Return value
630+
631+
Returns a `real` scalar value of the same kind of `a` that represents the determinant of the matrix.
632+
633+
Raises `LINALG_ERROR` if the matrix is singular.
634+
Raises `LINALG_VALUE_ERROR` if the matrix is non-square.
635+
Exceptions are returned to the `err` argument if provided; an `error stop` is triggered otherwise.
636+
637+
### Example
638+
639+
```fortran
640+
{!example/linalg/example_determinant.f90!}
641+
```
642+
643+
## `.det.` - Determinant operator of a square matrix
644+
645+
### Status
646+
647+
Experimental
648+
649+
### Description
650+
651+
This operator returns the determinant of a real square matrix.
652+
653+
This interface is equivalent to the `pure` version of determinant [[stdlib_linalg(module):det(interface)]].
654+
655+
### Syntax
656+
657+
`c = ` [[stdlib_linalg(module):operator(.det.)(interface)]] `(a)`
658+
659+
### Arguments
660+
661+
`a`: Shall be a rank-2 square array of any `real` or `complex` kinds. It is an `intent(in)` argument.
662+
663+
### Return value
664+
665+
Returns a real scalar value that represents the determinnt of the matrix.
666+
667+
Raises `LINALG_ERROR` if the matrix is singular.
668+
Raises `LINALG_VALUE_ERROR` if the matrix is non-square.
669+
Exceptions trigger an `error stop`.
670+
671+
### Example
672+
673+
```fortran
674+
{!example/linalg/example_determinant2.f90!}
675+
```

example/linalg/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ ADD_EXAMPLE(state1)
1818
ADD_EXAMPLE(state2)
1919
ADD_EXAMPLE(blas_gemv)
2020
ADD_EXAMPLE(lapack_getrf)
21+
ADD_EXAMPLE(determinant)
22+
ADD_EXAMPLE(determinant2)
23+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
program example_determinant
2+
use stdlib_kinds, only: dp
3+
use stdlib_linalg, only: det, linalg_state_type
4+
implicit none
5+
type(linalg_state_type) :: err
6+
7+
real(dp) :: d
8+
9+
! Compute determinate of a real matrix
10+
d = det(reshape([real(dp)::1,2,3,4],[2,2]))
11+
12+
print *, d ! a*d-b*c = -2.0
13+
14+
end program example_determinant
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
program example_determinant2
2+
use stdlib_kinds, only: dp
3+
use stdlib_linalg, only: operator(.det.)
4+
implicit none
5+
6+
real(dp) :: d
7+
8+
! Compute determinate of a real matrix
9+
d = .det.reshape([real(dp)::1,2,3,4],[2,2])
10+
11+
print *, d ! a*d-b*c = -2.0
12+
13+
end program example_determinant2

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ set(fppFiles
2424
stdlib_linalg_outer_product.fypp
2525
stdlib_linalg_kronecker.fypp
2626
stdlib_linalg_cross_product.fypp
27+
stdlib_linalg_determinant.fypp
2728
stdlib_linalg_state.fypp
2829
stdlib_optval.fypp
2930
stdlib_selection.fypp

src/stdlib_linalg.fypp

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
#:include "common.fypp"
2-
#:set RCI_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES + INT_KINDS_TYPES
2+
#:set RC_KINDS_TYPES = REAL_KINDS_TYPES + CMPLX_KINDS_TYPES
3+
#:set RCI_KINDS_TYPES = RC_KINDS_TYPES + INT_KINDS_TYPES
34
module stdlib_linalg
45
!!Provides a support for various linear algebra procedures
56
!! ([Specification](../page/specs/stdlib_linalg.html))
6-
use stdlib_kinds, only: sp, dp, xdp, qp, &
7+
use stdlib_kinds, only: sp, dp, xdp, qp, lk, &
78
int8, int16, int32, int64
89
use stdlib_error, only: error_stop
910
use stdlib_optval, only: optval
11+
use stdlib_linalg_state, only: linalg_state_type, linalg_error_handling
1012
implicit none
1113
private
1214

15+
public :: det
16+
public :: operator(.det.)
1317
public :: diag
1418
public :: eye
1519
public :: trace
@@ -23,6 +27,9 @@ module stdlib_linalg
2327
public :: is_hermitian
2428
public :: is_triangular
2529
public :: is_hessenberg
30+
31+
! Export linalg error handling
32+
public :: linalg_state_type, linalg_error_handling
2633

2734
interface diag
2835
!! version: experimental
@@ -214,6 +221,109 @@ module stdlib_linalg
214221
#:endfor
215222
end interface is_hessenberg
216223

224+
225+
interface det
226+
!! version: experimental
227+
!!
228+
!! Computes the determinant of a square matrix
229+
!! ([Specification](../page/specs/stdlib_linalg.html#det-computes-the-determinant-of-a-square-matrix))
230+
!!
231+
!!### Summary
232+
!! Interface for computing matrix determinant.
233+
!!
234+
!!### Description
235+
!!
236+
!! This interface provides methods for computing the determinant of a matrix.
237+
!! Supported data types include `real` and `complex`.
238+
!!
239+
!!@note The provided functions are intended for square matrices only.
240+
!!@note BLAS/LAPACK backends do not currently support extended precision (``xdp``).
241+
!!
242+
!!### Example
243+
!!
244+
!!```fortran
245+
!!
246+
!! real(sp) :: a(3,3), d
247+
!! type(linalg_state_type) :: state
248+
!! a = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3])
249+
!!
250+
!! ! ...
251+
!! d = det(a,err=state)
252+
!! if (state%ok()) then
253+
!! print *, 'Success! det=',d
254+
!! else
255+
!! print *, state%print()
256+
!! endif
257+
!! ! ...
258+
!!```
259+
!!
260+
#:for rk,rt in RC_KINDS_TYPES
261+
#:if rk!="xdp"
262+
module procedure stdlib_linalg_${rt[0]}$${rk}$determinant
263+
module procedure stdlib_linalg_pure_${rt[0]}$${rk}$determinant
264+
#:endif
265+
#:endfor
266+
end interface det
267+
268+
interface operator(.det.)
269+
!! version: experimental
270+
!!
271+
!! Determinant operator of a square matrix
272+
!! ([Specification](../page/specs/stdlib_linalg.html#det-determinant-operator-of-a-square-matrix))
273+
!!
274+
!!### Summary
275+
!! Pure operator interface for computing matrix determinant.
276+
!!
277+
!!### Description
278+
!!
279+
!! This pure operator interface provides a convenient way to compute the determinant of a matrix.
280+
!! Supported data types include real and complex.
281+
!!
282+
!!@note The provided functions are intended for square matrices.
283+
!!@note BLAS/LAPACK backends do not currently support extended precision (``xdp``).
284+
!!
285+
!!### Example
286+
!!
287+
!!```fortran
288+
!!
289+
!! ! ...
290+
!! real(sp) :: matrix(3,3), d
291+
!! matrix = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3])
292+
!! d = .det.matrix
293+
!! ! ...
294+
!!
295+
!!```
296+
!
297+
#:for rk,rt in RC_KINDS_TYPES
298+
#:if rk!="xdp"
299+
module procedure stdlib_linalg_pure_${rt[0]}$${rk}$determinant
300+
#:endif
301+
#:endfor
302+
end interface operator(.det.)
303+
304+
interface
305+
#:for rk,rt in RC_KINDS_TYPES
306+
#:if rk!="xdp"
307+
module function stdlib_linalg_${rt[0]}$${rk}$determinant(a,overwrite_a,err) result(det)
308+
!> Input matrix a[m,n]
309+
${rt}$, intent(inout), target :: a(:,:)
310+
!> [optional] Can A data be overwritten and destroyed?
311+
logical(lk), optional, intent(in) :: overwrite_a
312+
!> State return flag.
313+
type(linalg_state_type), intent(out) :: err
314+
!> Matrix determinant
315+
${rt}$ :: det
316+
end function stdlib_linalg_${rt[0]}$${rk}$determinant
317+
pure module function stdlib_linalg_pure_${rt[0]}$${rk}$determinant(a) result(det)
318+
!> Input matrix a[m,n]
319+
${rt}$, intent(in) :: a(:,:)
320+
!> Matrix determinant
321+
${rt}$ :: det
322+
end function stdlib_linalg_pure_${rt[0]}$${rk}$determinant
323+
#:endif
324+
#:endfor
325+
end interface
326+
217327
contains
218328

219329

0 commit comments

Comments
 (0)