Skip to content

Commit e88daa3

Browse files
authored
Provide BLAS, LAPACK backends and interfaces (#772)
2 parents 95f0c59 + c12b3c3 commit e88daa3

28 files changed

+561837
-19
lines changed

.github/workflows/fpm-deployment.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ jobs:
3131
--slave /usr/bin/gcov gcov /usr/bin/gcov-${{ env.GCC_V }}
3232
3333
- name: Install fpm latest release
34-
uses: fortran-lang/setup-fpm@v3
34+
uses: fortran-lang/setup-fpm@v5
3535
with:
36-
fpm-version: 'v0.4.0'
36+
fpm-version: 'v0.10.0'
3737

3838
- name: Run fpm test ⚙
3939
run: |

ci/fpm.toml

+3
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ copyright = "2019-2021 stdlib contributors"
88
[dev-dependencies]
99
test-drive.git = "https://github.com/fortran-lang/test-drive"
1010
test-drive.tag = "v0.4.0"
11+
12+
[preprocess]
13+
[preprocess.cpp]

cmake/stdlib.cmake

+7
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,10 @@ function (fypp_f90 fyppopts fyppfiles f90files)
4040
preprocess("${FYPP}" "${fyppopts}" "fypp" "f90" "${fyppfiles}" _f90files)
4141
set(${f90files} ${_f90files} PARENT_SCOPE)
4242
endfunction()
43+
44+
# For fortran sources that contain C preprocessor flags: create ".F90" files
45+
function (fypp_f90pp fyppopts fyppfiles F90files)
46+
preprocess("${FYPP}" "${fyppopts}" "fypp" "F90" "${fyppfiles}" _F90files)
47+
set(${F90files} ${_F90files} PARENT_SCOPE)
48+
endfunction()
49+

doc/specs/stdlib_linalg.md

+170
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,176 @@ title: linalg
66

77
[TOC]
88

9+
The `stdlib` linear algebra library provides high-level APIs for dealing with common linear algebra operations.
10+
11+
## BLAS and LAPACK
12+
13+
### Status
14+
15+
Experimental
16+
17+
### Description
18+
19+
`BLAS` and `LAPACK` backends provide efficient low level implementations of many linear algebra algorithms, and are employed for non-trivial operators.
20+
A Modern Fortran version of the [Reference-LAPACK 3.10.1](http://github.com/reference-LAPACK) implementation is provided as a backend.
21+
Modern Fortran modules with full explicit typing features are provided after an
22+
[automated conversion](https://github.com/perazz/fortran-lapack/blob/main/scripts/modularize_blas.py)
23+
of the legacy codes:
24+
- [stdlib_linalg_blas(module)], [stdlib_linalg_lapack(module)] provide kind-agnostic interfaces to all functions.
25+
- Both libraries are available for 32- (`sp`), 64- (`dp`) and 128-bit (`qp`) `real` and `complex` numbers (the latter if available in the current build)
26+
- Free format, lower-case style
27+
- `implicit none(type, external)` applied to all procedures and modules
28+
- `intent` added and all `pure` procedures where possible
29+
- `stdlib` provides all procedures in two different flavors: (a) original BLAS/LAPACK names with a prefix `stdlib_?<name>` (ex: `stdlib_dgemv`, `stdlib_sgemv`); (b) A generic, kind agnostic `<name>`, i.e. `gemv`.
30+
- F77-style `parameter`s removed, and all numeric constants have been generalized with KIND-dependent Fortran intrinsics.
31+
- preprocessor-based OpenMP directives retained.
32+
The single-source module structure hopefully allows for cross-procedural inlining which is otherwise impossible without link-time optimization.
33+
34+
When available, highly optimized libraries that take advantage of specialized processor instructions should be preferred over the `stdlib` implementation.
35+
Examples of such libraries are: OpenBLAS, MKL (TM), Accelerate, and ATLAS. In order to enable their usage, simply ensure that the following pre-processor macros are defined:
36+
37+
- `STDLIB_EXTERNAL_BLAS` wraps all BLAS procedures (except for the 128-bit ones) to an external library
38+
- `STDLIB_EXTERNAL_LAPACK` wraps all LAPACK procedures (except for the 128-bit ones) to an external library
39+
40+
These can be enabled during the build process. For example, with CMake, one can enable these preprocessor directives using `add_compile_definitions(STDLIB_EXTERNAL_BLAS STDLIB_EXTERNAL_LAPACK)`.
41+
The same is possible from the `fpm` branch, where the `cpp` preprocessor is enabled by default. For example, the macros can be added to the project's manifest:
42+
43+
```toml
44+
[dependencies]
45+
stdlib="*"
46+
47+
# Macros are only needed if using an external library
48+
[preprocess]
49+
[preprocess.cpp]
50+
macros = ["STDLIB_EXTERNAL_BLAS", "STDLIB_EXTERNAL_LAPACK"]
51+
```
52+
53+
or directly via compiler flags:
54+
55+
`fpm build --flag "-DSTDLIB_EXTERNAL_BLAS -DSTDLIB_EXTERNAL_LAPACK -lblas -llapack"`.
56+
57+
### Syntax
58+
59+
All procedures in the `BLAS` and `LAPACK` backends follow the standard interfaces from the
60+
[Reference LAPACK](https://www.netlib.org/lapack/). So, the online [Users Guide](https://www.netlib.org/lapack/explore-html/)
61+
should be consulted for the full API and descriptions of procedure arguments and their usage.
62+
63+
The `stdlib` implementation makes both kind-agnostic and specific procedure interfaces available via modules
64+
[stdlib_linalg_blas(module)] and [stdlib_linalg_lapack(module)]. Because all procedures start with a letter
65+
[that indicates the base datatype](https://www.netlib.org/lapack/lug/node24.html), the `stdlib` generic
66+
interface drops the heading letter and contains all kind-dependent implementations. For example, the generic
67+
interface to the `axpy` function looks like:
68+
69+
```fortran
70+
!> AXPY: constant times a vector plus a vector.
71+
interface axpy
72+
module procedure stdlib_saxpy
73+
module procedure stdlib_daxpy
74+
module procedure stdlib_qaxpy
75+
module procedure stdlib_caxpy
76+
module procedure stdlib_zaxpy
77+
module procedure stdlib_waxpy
78+
end interface axpy
79+
```
80+
81+
The generic interface is the endpoint for using an external library. Whenever the latter is used, references
82+
to the internal `module procedure`s are replaced with interfaces to the external library,
83+
for example:
84+
85+
```fortran
86+
!> AXPY: constant times a vector plus a vector.
87+
interface axpy
88+
pure subroutine caxpy(n,ca,cx,incx,cy,incy)
89+
import sp,dp,qp,ilp,lk
90+
implicit none(type,external)
91+
complex(sp), intent(in) :: ca,cx(*)
92+
integer(ilp), intent(in) :: incx,incy,n
93+
complex(sp), intent(inout) :: cy(*)
94+
end subroutine caxpy
95+
! [....]
96+
module procedure stdlib_qaxpy
97+
end interface axpy
98+
```
99+
100+
Note that the 128-bit functions are only provided by `stdlib` and always point to the internal implementation.
101+
Because 128-bit precision is identified as [stdlib_kinds(module):qp], initials for 128-bit procedures were
102+
labelled as `q` (quadruple-precision reals) and `w` ("wide" or quadruple-precision complex numbers).
103+
Extended precision ([stdlib_kinds(module):xdp]) calculations are currently not supported.
104+
105+
### Example
106+
107+
```fortran
108+
{!example/linalg/example_blas_gemv.f90!}
109+
```
110+
111+
```fortran
112+
{!example/linalg/example_lapack_getrf.f90!}
113+
```
114+
115+
### Licensing
116+
117+
The Fortran Standard Library is distributed under the MIT License. `LAPACK` and its contained `BLAS` are a
118+
freely-available software package. They are available from [netlib](https://www.netlib.org/lapack/) via anonymous
119+
ftp and the World Wide Web. Thus, they can be included in commercial software packages (and have been).
120+
The license used for the `BLAS` and `LAPACK` backends is the [modified BSD license](https://www.netlib.org/lapack/LICENSE.txt).
121+
122+
The header of the `LICENSE.txt` file has as its licensing requirements:
123+
124+
Copyright (c) 1992-2013 The University of Tennessee and The University
125+
of Tennessee Research Foundation. All rights
126+
reserved.
127+
Copyright (c) 2000-2013 The University of California Berkeley. All
128+
rights reserved.
129+
Copyright (c) 2006-2013 The University of Colorado Denver. All rights
130+
reserved.
131+
132+
$COPYRIGHT$
133+
134+
Additional copyrights may follow
135+
136+
$HEADER$
137+
138+
Redistribution and use in source and binary forms, with or without
139+
modification, are permitted provided that the following conditions are
140+
met:
141+
142+
- Redistributions of source code must retain the above copyright
143+
notice, this list of conditions and the following disclaimer.
144+
145+
- Redistributions in binary form must reproduce the above copyright
146+
notice, this list of conditions and the following disclaimer listed
147+
in this license in the documentation and/or other materials
148+
provided with the distribution.
149+
150+
- Neither the name of the copyright holders nor the names of its
151+
contributors may be used to endorse or promote products derived from
152+
this software without specific prior written permission.
153+
154+
The copyright holders provide no reassurances that the source code
155+
provided does not infringe any patent, copyright, or any other
156+
intellectual property rights of third parties. The copyright holders
157+
disclaim any liability to any recipient for claims brought against
158+
recipient by any third party for infringement of that parties
159+
intellectual property rights.
160+
161+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
162+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
163+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
164+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
165+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
166+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
167+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
168+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
169+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
170+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
171+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
172+
173+
So the license for the `LICENSE.txt` code is compatible with the use of
174+
modified versions of the code in the Fortran Standard Library under the MIT license.
175+
Credit for the `BLAS`, `LAPACK` libraries should be given to the [LAPACK authors](https://www.netlib.org/lapack/contributor-list.html).
176+
According to the original license, we also changed the name of the routines and commented the changes made
177+
to the original.
178+
9179
## `diag` - Create a diagonal array or extract the diagonal elements of an array
10180

11181
### Status

example/linalg/example_blas_gemv.f90

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
program example_gemv
2+
use stdlib_linalg, only: eye
3+
use stdlib_linalg_blas, only: sp,gemv
4+
implicit none(type,external)
5+
real(sp) :: A(2, 2), B(2)
6+
B = [1.0,2.0]
7+
A = eye(2)
8+
9+
! Use legacy BLAS interface
10+
call gemv('No transpose',m=size(A,1),n=size(A,2),alpha=1.0,a=A,lda=size(A,1),x=B,incx=1,beta=0.0,y=B,incy=1)
11+
12+
print *, B ! returns 1.0 2.0
13+
14+
end program example_gemv
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
program example_getrf
2+
use stdlib_linalg, only: eye
3+
use stdlib_linalg_lapack, only: dp,ilp,getrf
4+
implicit none(type,external)
5+
real(dp) :: A(3, 3)
6+
integer(ilp) :: ipiv(3),info
7+
8+
A = eye(3)
9+
10+
! LAPACK matrix factorization interface (overwrite result)
11+
call getrf(size(A,1),size(A,2),A,size(A,1),ipiv,info)
12+
print *, info ! info==0: Success!
13+
14+
end program example_getrf

include/common.fypp

-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@
8787
#! Whether Fortran 90 compatible code should be generated
8888
#:set VERSION90 = defined('VERSION90')
8989

90-
9190
#! Ranks to be generated when templates are created
9291
#:if not defined('MAXRANK')
9392
#:if VERSION90

src/CMakeLists.txt

+22
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,29 @@ set(fppFiles
6464
stdlib_version.fypp
6565
)
6666

67+
# Preprocessed files to contain preprocessor directives -> .F90
68+
set(cppFiles
69+
stdlib_linalg_constants.fypp
70+
stdlib_linalg_blas.fypp
71+
stdlib_linalg_blas_aux.fypp
72+
stdlib_linalg_blas_s.fypp
73+
stdlib_linalg_blas_d.fypp
74+
stdlib_linalg_blas_q.fypp
75+
stdlib_linalg_blas_c.fypp
76+
stdlib_linalg_blas_z.fypp
77+
stdlib_linalg_blas_w.fypp
78+
stdlib_linalg_lapack.fypp
79+
stdlib_linalg_lapack_aux.fypp
80+
stdlib_linalg_lapack_s.fypp
81+
stdlib_linalg_lapack_d.fypp
82+
stdlib_linalg_lapack_q.fypp
83+
stdlib_linalg_lapack_c.fypp
84+
stdlib_linalg_lapack_z.fypp
85+
stdlib_linalg_lapack_w.fypp
86+
)
6787

6888
fypp_f90("${fyppFlags}" "${fppFiles}" outFiles)
89+
fypp_f90pp("${fyppFlags}" "${cppFiles}" outPreprocFiles)
6990

7091
set(SRC
7192
stdlib_ansi.f90
@@ -85,6 +106,7 @@ set(SRC
85106
stdlib_quadrature_gauss.f90
86107
stdlib_stringlist_type.f90
87108
${outFiles}
109+
${outPreprocFiles}
88110
)
89111

90112
add_library(${PROJECT_NAME} ${SRC})

0 commit comments

Comments
 (0)