Skip to content

Commit 4ccfba8

Browse files
authored
Merge branch 'fortran-lang:master' into linalg_ilp64
2 parents 34b7a81 + cc30d4c commit 4ccfba8

13 files changed

+666
-34
lines changed

.github/workflows/CI.yml

+5-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
strategy:
2020
fail-fast: false
2121
matrix:
22-
os: [ubuntu-latest, macos-12]
22+
os: [ubuntu-latest, macos-13]
2323
toolchain:
2424
- {compiler: gcc, version: 10}
2525
- {compiler: gcc, version: 11}
@@ -34,9 +34,11 @@ jobs:
3434
toolchain:
3535
- {compiler: gcc, version: 10}
3636
exclude:
37-
- os: macos-12
37+
- os: macos-13
38+
toolchain: {compiler: intel-classic, version: '2021.9'}
39+
- os: macos-13
3840
toolchain: {compiler: intel, version: '2024.1'}
39-
- os: macos-12
41+
- os: macos-13
4042
toolchain: {compiler: gcc, version: 13}
4143
env:
4244
BUILD_DIR: ${{ matrix.build == 'cmake' && 'build' || '.' }}

doc/specs/stdlib_ascii.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Converts input character variable to all lowercase.
3838

3939
#### Class
4040

41-
Pure function.
41+
Elemental function.
4242

4343
#### Argument
4444

@@ -70,7 +70,7 @@ Converts input character variable to all uppercase.
7070

7171
#### Class
7272

73-
Pure function.
73+
Elemental function.
7474

7575
#### Argument
7676

@@ -107,7 +107,7 @@ or numeral present next to either of its 2 ends.
107107

108108
#### Class
109109

110-
Pure function.
110+
Elemental function.
111111

112112
#### Argument
113113

@@ -142,7 +142,7 @@ transformed to lowercase.
142142

143143
#### Class
144144

145-
Pure function.
145+
Elemental function.
146146

147147
#### Argument
148148

@@ -174,7 +174,7 @@ Reverses the order of all characters in the input character type.
174174

175175
#### Class
176176

177-
Pure function.
177+
Elemental function.
178178

179179
#### Argument
180180

doc/specs/stdlib_linalg.md

+49
Original file line numberDiff line numberDiff line change
@@ -1565,4 +1565,53 @@ If `err` is not present, exceptions trigger an `error stop`.
15651565
{!example/linalg/example_norm.f90!}
15661566
```
15671567

1568+
## `mnorm` - Computes the matrix norm of a generic-rank array.
1569+
1570+
### Status
1571+
1572+
Experimental
1573+
1574+
### Description
1575+
1576+
This function computes one of several matrix norms of `real` or `complex` array \( A \), depending on
1577+
the value of the `order` input argument. \( A \) must be an array of rank 2 or higher. For arrays of rank > 2,
1578+
matrix norms are computed over specified dimensions.
1579+
1580+
### Syntax
1581+
1582+
`x = ` [[stdlib_linalg(module):mnorm(interface)]] `(a [, order, dim, err])`
1583+
1584+
### Arguments
1585+
1586+
`a`: Shall be a rank-n `real` or `complex` array containing the data, where n >= 2. It is an `intent(in)` argument.
1587+
1588+
`order` (optional): Shall be an `integer` value or a `character` flag that specifies the norm type, as follows. It is an `intent(in)` argument.
1589+
1590+
| Integer input | Character Input | Norm type |
1591+
|------------------|---------------------------------|-----------------------------------------------------------------------------|
1592+
| `1` | `'1'` | 1-norm (maximum column sum) \( \max_j \sum_i{ \left|a_{i,j}\right| } \) |
1593+
| `2` | `'2'` | 2-norm (largest singular value) |
1594+
| (not prov.) | `'Euclidean','Frobenius','Fro'` | Frobenius norm \( \sqrt{\sum_{i,j}{ \left|a_{i,j}\right|^2 }} \) |
1595+
| `huge(0)` | `'inf', 'Inf', 'INF'` | Infinity norm (maximum row sum) \( \max_i \sum_j{ \left|a_{i,j}\right| } \) |
1596+
1597+
`dim` (optional): For arrays of rank > 2, shall be an integer array of size 2 specifying the dimensions over which to compute the matrix norm. Default value is `[1,2]`. It is an `intent(in)` argument.
1598+
1599+
`err` (optional): Shall be a `type(linalg_state_type)` value. This is an `intent(out)` argument.
1600+
1601+
### Return value
1602+
1603+
For rank-2 input arrays, the return value `x` is a scalar containing the matrix norm.
1604+
For arrays of rank > 2, if the optional `dim` argument is present, `x` is a rank `n-2` array with the same shape as \( A \) except
1605+
for dimensions `dim(1)` and `dim(2)`, which are dropped. Each element of `x` contains the matrix norm of the corresponding submatrix of \( A \),
1606+
evaluated over the specified dimensions only, with the given order.
1607+
1608+
If an invalid norm type is provided, defaults to 1-norm and raises `LINALG_ERROR`.
1609+
Raises `LINALG_VALUE_ERROR` if any of the arguments has an invalid size.
1610+
If `err` is not present, exceptions trigger an `error stop`.
1611+
1612+
### Example
1613+
1614+
```fortran
1615+
{!example/linalg/example_mnorm.f90!}
1616+
```
15681617

doc/specs/stdlib_stats_distribution_normal.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ Experimental
6464

6565
The probability density function (pdf) of the single real variable normal distribution:
6666

67-
$$f(x) = \frac{1}{\sigma \sqrt{2}} \exp{\left[-\frac{1}{2}\left(\frac{x-\mu}{\sigma}\right)^{2}\right]}$$
67+
$$f(x) = \frac{1}{\sigma \sqrt{2\pi}} \exp{\left[-\frac{1}{2}\left(\frac{x-\mu}{\sigma}\right)^{2}\right]}$$
6868

6969
For a complex varible \( z=(x + y i) \) with independent real \( x \) and imaginary \( y \) parts, the joint probability density function is the product of the the corresponding real and imaginary marginal pdfs:[^2]
7070

71-
$$f(x + y \mathit{i}) = f(x) f(y) = \frac{1}{2\sigma_{x}\sigma_{y}} \exp{\left[-\frac{1}{2}\left(\left(\frac{x-\mu_x}{\sigma_{x}}\right)^{2}+\left(\frac{y-\mu_y}{\sigma_{y}}\right)^{2}\right)\right]}$$
71+
$$f(x + y \mathit{i}) = f(x) f(y) = \frac{1}{2\pi\sigma_{x}\sigma_{y}} \exp{\left[-\frac{1}{2}\left(\left(\frac{x-\mu_x}{\sigma_{x}}\right)^{2}+\left(\frac{y-\mu_y}{\sigma_{y}}\right)^{2}\right)\right]}$$
7272

7373
### Syntax
7474

example/linalg/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ ADD_EXAMPLE(lapack_getrf)
2929
ADD_EXAMPLE(lstsq1)
3030
ADD_EXAMPLE(lstsq2)
3131
ADD_EXAMPLE(norm)
32+
ADD_EXAMPLE(mnorm)
3233
ADD_EXAMPLE(get_norm)
3334
ADD_EXAMPLE(solve1)
3435
ADD_EXAMPLE(solve2)

example/linalg/example_mnorm.f90

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
program example_mnorm
2+
use stdlib_linalg, only: mnorm
3+
use stdlib_kinds, only: sp
4+
implicit none
5+
real(sp) :: a(3,3), na
6+
real(sp) :: b(3,3,4), nb(4) ! Array of 4 3x3 matrices
7+
8+
! Initialize example matrix
9+
a = reshape([1, 2, 3, 4, 5, 6, 7, 8, 9], [3, 3])
10+
11+
! Compute Euclidean norm of single matrix
12+
na = mnorm(a, 'Euclidean')
13+
print *, "Euclidean norm of matrix a:", na
14+
15+
! Initialize array of matrices
16+
b(:,:,1) = a
17+
b(:,:,2) = 2*a
18+
b(:,:,3) = 3*a
19+
b(:,:,4) = 4*a
20+
21+
! Compute infinity norm of each 3x3 matrix in b
22+
nb = mnorm(b, 'inf', dim=[1,2])
23+
24+
! 18.0000000 36.0000000 54.0000000 72.0000000
25+
print *, "Infinity norms of matrices in b:", nb
26+
end program example_mnorm

include/common.fypp

+45-1
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,22 @@ $:"s" if cmplx=="c" else "d" if cmplx=="z" else "x" if cmplx=="y" else "q" if cm
172172
#{if rank > 0}#(${"0" + ",0" * (rank - 1)}$)#{endif}#
173173
#:enddef
174174

175+
#! Generates an array rank suffix with a fixed integer size for all dimensions.
176+
#!
177+
#! Args:
178+
#! rank (int): Rank of the variable
179+
#! size (int): Size along each dimension
180+
#!
181+
#! Returns:
182+
#! Array rank suffix string
183+
#! E.g.,
184+
#! fixedranksuffix(3,4)
185+
#! -> (4,4,4)
186+
#!
187+
#:def fixedranksuffix(rank,size)
188+
#{if rank > 0}#(${str(size) + (","+str(size)) * (rank - 1)}$)#{endif}#
189+
#:enddef
190+
175191
#! Joins stripped lines with given character string
176192
#!
177193
#! Args:
@@ -242,7 +258,7 @@ ${prefix + joinstr.join([line.strip() for line in txt.split("\n")]) + suffix}$
242258
#! Array rank suffix string enclosed in braces
243259
#!
244260
#! E.g.,
245-
#! select_subarray(5 , [(4, 'i'), (5, 'j')])}$
261+
#! select_subarray(5 , [(4, 'i'), (5, 'j')])
246262
#! -> (:, :, :, i, j)
247263
#!
248264
#:def select_subarray(rank, selectors)
@@ -342,6 +358,34 @@ ${prefix + joinstr.join([line.strip() for line in txt.split("\n")]) + suffix}$
342358
#:endcall
343359
#:enddef
344360

361+
#!
362+
#! Generates a list of loop variables from an array
363+
#!
364+
#! Args:
365+
#! varname(str): Name of the array variable to be used as prefix
366+
#! n (int): Number of loop variables to be created
367+
#! offset (int): Optional index offset
368+
#!
369+
#! Returns:
370+
#! Variable definition string
371+
#!
372+
#! E.g.,
373+
#! loop_array_variables('j', 5)
374+
#! -> "j(1), j(2), j(3), j(4), j(5)
375+
#!
376+
#! loop_array_variables('j', 5, 2)
377+
#! -> "j(3), j(4), j(5), j(6), j(7)
378+
#!
379+
#:def loop_array_variables(varname, n, offset=0)
380+
#:assert n > 0
381+
#:call join_lines(joinstr=", ")
382+
#:for i in range(1, n + 1)
383+
${varname}$(${i+offset}$)
384+
#:endfor
385+
#:endcall
386+
#:enddef
387+
388+
345389
#! Generates an array shape specifier from an N-D array size
346390
#!
347391
#! Args:

src/stdlib_ascii.fypp

+12-12
Original file line numberDiff line numberDiff line change
@@ -70,35 +70,35 @@ module stdlib_ascii
7070

7171
!> Returns a new character sequence which is the lower case
7272
!> version of the input character sequence
73-
!> This method is pure and returns a character sequence
73+
!> This method is elemental and returns a character sequence
7474
interface to_lower
7575
module procedure :: to_lower
7676
end interface to_lower
7777

7878
!> Returns a new character sequence which is the upper case
7979
!> version of the input character sequence
80-
!> This method is pure and returns a character sequence
80+
!> This method is elemental and returns a character sequence
8181
interface to_upper
8282
module procedure :: to_upper
8383
end interface to_upper
8484

8585
!> Returns a new character sequence which is the title case
8686
!> version of the input character sequence
87-
!> This method is pure and returns a character sequence
87+
!> This method is elemental and returns a character sequence
8888
interface to_title
8989
module procedure :: to_title
9090
end interface to_title
9191

9292
!> Returns a new character sequence which is the sentence case
9393
!> version of the input character sequence
94-
!> This method is pure and returns a character sequence
94+
!> This method is elemental and returns a character sequence
9595
interface to_sentence
9696
module procedure :: to_sentence
9797
end interface to_sentence
9898

9999
!> Returns a new character sequence which is reverse of
100100
!> the input charater sequence
101-
!> This method is pure and returns a character sequence
101+
!> This method is elemental and returns a character sequence
102102
interface reverse
103103
module procedure :: reverse
104104
end interface reverse
@@ -220,7 +220,7 @@ contains
220220

221221
!> Returns the corresponding lowercase letter, if `c` is an uppercase
222222
!> ASCII character, otherwise `c` itself.
223-
pure function char_to_lower(c) result(t)
223+
elemental function char_to_lower(c) result(t)
224224
character(len=1), intent(in) :: c !! A character.
225225
character(len=1) :: t
226226
integer, parameter :: wp= iachar('a')-iachar('A'), BA=iachar('A'), BZ=iachar('Z')
@@ -234,7 +234,7 @@ contains
234234

235235
!> Returns the corresponding uppercase letter, if `c` is a lowercase
236236
!> ASCII character, otherwise `c` itself.
237-
pure function char_to_upper(c) result(t)
237+
elemental function char_to_upper(c) result(t)
238238
character(len=1), intent(in) :: c !! A character.
239239
character(len=1) :: t
240240
integer, parameter :: wp= iachar('a')-iachar('A'), la=iachar('a'), lz=iachar('z')
@@ -250,7 +250,7 @@ contains
250250
!> ([Specification](../page/specs/stdlib_ascii.html#to_lower))
251251
!>
252252
!> Version: experimental
253-
pure function to_lower(string) result(lower_string)
253+
elemental function to_lower(string) result(lower_string)
254254
character(len=*), intent(in) :: string
255255
character(len=len(string)) :: lower_string
256256
integer :: i
@@ -265,7 +265,7 @@ contains
265265
!> ([Specification](../page/specs/stdlib_ascii.html#to_upper))
266266
!>
267267
!> Version: experimental
268-
pure function to_upper(string) result(upper_string)
268+
elemental function to_upper(string) result(upper_string)
269269
character(len=*), intent(in) :: string
270270
character(len=len(string)) :: upper_string
271271
integer :: i
@@ -280,7 +280,7 @@ contains
280280
!> ([Specification](../page/specs/stdlib_ascii.html#to_title))
281281
!>
282282
!> Version: experimental
283-
pure function to_title(string) result(title_string)
283+
elemental function to_title(string) result(title_string)
284284
character(len=*), intent(in) :: string
285285
character(len=len(string)) :: title_string
286286
integer :: i
@@ -307,7 +307,7 @@ contains
307307
!> ([Specification](../page/specs/stdlib_ascii.html#to_sentence))
308308
!>
309309
!> Version: experimental
310-
pure function to_sentence(string) result(sentence_string)
310+
elemental function to_sentence(string) result(sentence_string)
311311
character(len=*), intent(in) :: string
312312
character(len=len(string)) :: sentence_string
313313
integer :: i, n
@@ -333,7 +333,7 @@ contains
333333
!> ([Specification](../page/specs/stdlib_ascii.html#reverse))
334334
!>
335335
!> Version: experimental
336-
pure function reverse(string) result(reverse_string)
336+
elemental function reverse(string) result(reverse_string)
337337
character(len=*), intent(in) :: string
338338
character(len=len(string)) :: reverse_string
339339
integer :: i, n

0 commit comments

Comments
 (0)