Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 407798c

Browse files
authored
Provide state/error handling for linear algebra (#774)
2 parents e19d4b6 + dfd03fc commit 407798c

File tree

9 files changed

+701
-6
lines changed

9 files changed

+701
-6
lines changed

‎doc/specs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ This is an index/directory of the specifications (specs) for each new module/fea
2222
- [io](./stdlib_io.html) - Input/output helper & convenience
2323
- [kinds](./stdlib_kinds.html) - Kind parameters
2424
- [linalg](./stdlib_linalg.html) - Linear Algebra
25+
- [linalg_state_type](./stdlib_linalg_state_type.html) - Linear Algebra state and error handling
2526
- [logger](./stdlib_logger.html) - Runtime logging system
2627
- [math](./stdlib_math.html) - General purpose mathematical functions
2728
- [optval](./stdlib_optval.html) - Fallback value for optional arguments

‎doc/specs/stdlib_linalg_state_type.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
title: linalg_state_type
3+
---
4+
5+
# Linear Algebra -- State and Error Handling Module
6+
7+
[TOC]
8+
9+
## Introduction
10+
11+
The `stdlib_linalg_state` module provides a derived type holding information on the
12+
state of linear algebra operations, and procedures for expert control of linear algebra workflows.
13+
All linear algebra procedures are engineered to support returning an optional `linalg_state_type`
14+
variable to holds such information, as a form of expert API. If the user does not require state
15+
information, but fatal errors are encountered during the execution of linear algebra routines, the
16+
program will undergo a hard stop.
17+
Instead, if the state argument is present, the program will never stop, but will return detailed error
18+
information into the state handler.
19+
20+
## Derived types provided
21+
22+
<!-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -->
23+
### The `linalg_state_type` derived type
24+
25+
The `linalg_state_type` is defined as a derived type containing an integer error flag, and
26+
fixed-size character strings to store an error message and the location of the error state change.
27+
Fixed-size string storage was chosen to facilitate the compiler's memory allocation and ultimately
28+
ensure maximum computational performance.
29+
30+
A similarly named generic interface, `linalg_state_type`, is provided to allow the developer to
31+
create diagnostic messages and raise error flags easily. The call starts with an error flag or
32+
the location of the event, and is followed by an arbitrary list of `integer`, `real`, `complex` or
33+
`character` variables. Numeric variables may be provided as either scalars or rank-1 (array) inputs.
34+
35+
#### Type-bound procedures
36+
37+
The following convenience type-bound procedures are provided:
38+
- `print()` returns an allocatable character string containing state location, message, and error flag;
39+
- `print_message()` returns an allocatable character string containing the state message;
40+
- `ok()` returns a `logical` flag that is `.true.` in case of successful state (`flag==LINALG_SUCCESS`);
41+
- `error()` returns a `logical` flag that is `.true.` in case of error state (`flag/=LINALG_SUCCESS`).
42+
43+
#### Status
44+
45+
Experimental
46+
47+
#### Example
48+
49+
```fortran
50+
{!example/linalg/example_state1.f90!}
51+
```
52+
53+
## Error flags provided
54+
55+
The module provides the following state flags:
56+
- `LINALG_SUCCESS`: Successful execution
57+
- `LINALG_VALUE_ERROR`: Numerical errors (such as infinity, not-a-number, range bounds) are encountered.
58+
- `LINALG_ERROR`: Linear Algebra errors are encountered, such as: non-converging iterations, impossible operations, etc.
59+
- `LINALG_INTERNAL_ERROR`: Provided as a developer safeguard for internal errors that should never occur.
60+
61+
## Comparison operators provided
62+
63+
The module provides overloaded comparison operators for all comparisons of a `linalg_state_type` variable
64+
with an integer error flag: `<`, `<=`, `==`, `>=`, `>`, `/=`.

‎example/linalg/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ ADD_EXAMPLE(is_symmetric)
1414
ADD_EXAMPLE(is_triangular)
1515
ADD_EXAMPLE(outer_product)
1616
ADD_EXAMPLE(trace)
17+
ADD_EXAMPLE(state1)
18+
ADD_EXAMPLE(state2)
19+
ADD_EXAMPLE(blas_gemv)
20+
ADD_EXAMPLE(lapack_getrf)

‎example/linalg/example_state1.f90

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
program example_state1
2+
use stdlib_linalg_state, only: linalg_state_type, LINALG_SUCCESS, LINALG_VALUE_ERROR, &
3+
operator(/=)
4+
implicit none
5+
type(linalg_state_type) :: err
6+
7+
! To create a state variable, we enter its integer state flag, followed by a list of variables
8+
! that will be automatically assembled into a formatted error message. No need to provide string formats
9+
err = linalg_state_type(LINALG_VALUE_ERROR,'just an example with scalar ',&
10+
'integer=',1,'real=',2.0,'complex=',(3.0,1.0),'and array ',[1,2,3],'inputs')
11+
12+
! Print flag
13+
print *, err%print()
14+
15+
! Check success
16+
print *, 'Check error: ',err%error()
17+
print *, 'Check flag : ',err /= LINALG_SUCCESS
18+
19+
20+
end program example_state1

‎example/linalg/example_state2.f90

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
program example_state2
2+
!! This example shows how to set a `type(linalg_state_type)` variable to process output conditions
3+
!! out of a simple division routine. The example is meant to highlight:
4+
!! 1) the different mechanisms that can be used to initialize the `linalg_state` variable providing
5+
!! strings, scalars, or arrays, on input to it;
6+
!! 2) `pure` setup of the error control
7+
use stdlib_linalg_state, only: linalg_state_type, LINALG_VALUE_ERROR, LINALG_SUCCESS, &
8+
linalg_error_handling
9+
implicit none
10+
integer :: info
11+
type(linalg_state_type) :: err
12+
real :: a_div_b
13+
14+
! OK
15+
call very_simple_division(0.0,2.0,a_div_b,err)
16+
print *, err%print()
17+
18+
! Division by zero
19+
call very_simple_division(1.0,0.0,a_div_b,err)
20+
print *, err%print()
21+
22+
! Out of bounds
23+
call very_simple_division(huge(0.0),0.001,a_div_b,err)
24+
print *, err%print()
25+
26+
contains
27+
28+
!> Simple division returning an integer flag (LAPACK style)
29+
elemental subroutine very_simple_division(a,b,a_div_b,err)
30+
real, intent(in) :: a,b
31+
real, intent(out) :: a_div_b
32+
type(linalg_state_type), optional, intent(out) :: err
33+
34+
type(linalg_state_type) :: err0
35+
real, parameter :: MAXABS = huge(0.0)
36+
character(*), parameter :: this = 'simple division'
37+
38+
!> Check a
39+
if (b==0.0) then
40+
! Division by zero
41+
err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'Division by zero trying ',a,'/',b)
42+
elseif (.not.abs(b)<MAXABS) then
43+
! B is out of bounds
44+
err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'B is infinity in a/b: ',[a,b]) ! use an array
45+
elseif (.not.abs(a)<MAXABS) then
46+
! A is out of bounds
47+
err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'A is infinity in a/b: a=',a,' b=',b)
48+
else
49+
a_div_b = a/b
50+
if (.not.abs(a_div_b)<MAXABS) then
51+
! Result is out of bounds
52+
err0 = linalg_state_type(this,LINALG_VALUE_ERROR,'A/B is infinity in a/b: a=',a,' b=',b)
53+
else
54+
err0%state = LINALG_SUCCESS
55+
end if
56+
end if
57+
58+
! Return error flag, or hard stop on failure
59+
call linalg_error_handling(err0,err)
60+
61+
end subroutine very_simple_division
62+
63+
64+
end program example_state2

‎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_state.fypp
2728
stdlib_optval.fypp
2829
stdlib_selection.fypp
2930
stdlib_sorting.fypp

‎src/stdlib_linalg_constants.fypp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ module stdlib_linalg_constants
77
public
88

99

10-
1110
! Integer size support for ILP64 builds should be done here
1211
integer, parameter :: ilp = int32
1312
private :: int32, int64

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /