Skip to content

Commit 7d9b916

Browse files
committed
addition of stdlib_experimental_stats mean
1 parent c4f81f7 commit 7d9b916

15 files changed

+665
-1
lines changed

.github/workflows/CI.yml

+3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ jobs:
3939
if: contains(matrix.os, 'ubuntu')
4040
run: ci/install_cmake.sh
4141

42+
- name: Install fypp
43+
run: pip install --upgrade fypp
44+
4245
- name: Install GFortran Linux
4346
if: contains( matrix.os, 'ubuntu')
4447
run: |

CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ endif()
1515
include(CheckFortranSourceCompiles)
1616
include(CheckFortranSourceRuns)
1717
check_fortran_source_compiles("error stop i; end" f18errorstop SRC_EXT f90)
18+
check_fortran_source_compiles("real, allocatable :: array(:, :, :, :, :, :, :, :, :, :); end" f03rank SRC_EXT f90)
1819
check_fortran_source_runs("use, intrinsic :: iso_fortran_env, only : real128; real(real128) :: x; x = x+1; end" f03real128)
1920

2021
add_subdirectory(src)

Makefile.manual

+2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
FC = gfortran
44
FFLAGS = -Wall -Wextra -Wimplicit-interface -fPIC -g -fcheck=all
5+
FYPPFLAGS=
56

67
export FC
78
export FFLAGS
9+
export FYPPFLAGS
810

911
.PHONY: all clean test
1012

src/CMakeLists.txt

+43
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,53 @@
1+
### Pre-process: .fpp -> .f90 via Fypp
2+
3+
# Create a list of the files to be preprocessed
4+
set(fppFiles
5+
stdlib_experimental_stats.fypp
6+
stdlib_experimental_stats_mean.fypp
7+
)
8+
9+
# Pre-process
10+
foreach(infileName IN LISTS fppFiles)
11+
12+
# Generate output file name
13+
string(REGEX REPLACE ".fypp\$" ".f90" outfileName "${infileName}")
14+
15+
# Create the full path for the new file
16+
set(outfile "${CMAKE_CURRENT_BINARY_DIR}/${outfileName}")
17+
18+
# Generate input file name
19+
set(infile "${CMAKE_CURRENT_SOURCE_DIR}/${infileName}")
20+
21+
# Custom command to do the processing
22+
if(f03rank)
23+
add_custom_command(
24+
OUTPUT "${outfile}"
25+
COMMAND fypp "${infile}" "${outfile}"
26+
MAIN_DEPENDENCY "${infile}"
27+
VERBATIM)
28+
else()
29+
add_custom_command(
30+
OUTPUT "${outfile}"
31+
COMMAND fypp -DVERSION90 "${infile}" "${outfile}"
32+
MAIN_DEPENDENCY "${infile}"
33+
VERBATIM)
34+
endif()
35+
36+
# Finally add output file to a list
37+
set(outFiles ${outFiles} "${outfile}")
38+
39+
endforeach(infileName)
40+
41+
42+
143
set(SRC
244
stdlib_experimental_ascii.f90
345
stdlib_experimental_io.f90
446
stdlib_experimental_error.f90
547
stdlib_experimental_kinds.f90
648
stdlib_experimental_optval.f90
749
stdlib_experimental_system.F90
50+
${outFiles}
851
)
952

1053
add_library(fortran_stdlib ${SRC})

src/Makefile.manual

+11-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ SRC = stdlib_experimental_ascii.f90 \
33
stdlib_experimental_io.f90 \
44
stdlib_experimental_optval.f90 \
55
stdlib_experimental_kinds.f90 \
6-
f18estop.f90
6+
f18estop.f90 \
7+
stdlib_experimental_stats.f90 \
8+
stdlib_experimental_stats_mean.f90
79

810
LIB = libstdlib.a
911

@@ -26,6 +28,8 @@ clean:
2628
%.o: %.f90
2729
$(FC) $(FFLAGS) -c $<
2830

31+
%.f90: %.fypp
32+
fypp $(FYPPFLAGS) $< $@
2933

3034
# Fortran module dependencies
3135
f18estop.o: stdlib_experimental_error.o
@@ -34,3 +38,9 @@ stdlib_experimental_io.o: \
3438
stdlib_experimental_optval.o \
3539
stdlib_experimental_kinds.o
3640
stdlib_experimental_optval.o: stdlib_experimental_kinds.o
41+
stdlib_experimental_stats_mean.o: \
42+
stdlib_experimental_optval.o \
43+
stdlib_experimental_kinds.o \
44+
stdlib_experimental_stats.o
45+
stdlib_experimental_stats.f90: stdlib_experimental_stats.fypp
46+
stdlib_experimental_stats_mean.f90: stdlib_experimental_stats_mean.fypp

src/stdlib_experimental_stats.fypp

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
module stdlib_experimental_stats
2+
3+
#:set VERSION90 = defined('VERSION90')
4+
#:set REALKINDS = ["sp", "dp", "qp"]
5+
#:set INTKINDS = ["int8", "int16", "int32", "int64"]
6+
#:set REALTYPES = ["real({})".format(k) for k in REALKINDS]
7+
#:set INTTYPES = ["integer({})".format(k) for k in INTKINDS]
8+
#:set iktr = list(zip(range(len(REALKINDS)), REALKINDS, REALTYPES))
9+
#:set ikti = list(zip(range(len(INTKINDS)), INTKINDS, INTTYPES))
10+
11+
use stdlib_experimental_kinds, only: sp, dp, qp, &
12+
int8, int16, int32, int64
13+
implicit none
14+
private
15+
! Public API
16+
public :: mean
17+
18+
interface mean
19+
#:for i1, k1, t1 in iktr
20+
module function mean_1_${k1}$_${k1}$(x) result(res)
21+
${t1}$, intent(in) :: x(:)
22+
${t1}$ :: res
23+
end function mean_1_${k1}$_${k1}$
24+
#:endfor
25+
26+
#:for i1, k1, t1 in ikti
27+
module function mean_1_${k1}$_dp(x) result(res)
28+
${t1}$, intent(in) :: x(:)
29+
real(dp) :: res
30+
end function mean_1_${k1}$_dp
31+
#:endfor
32+
33+
34+
#:for i1, k1, t1 in iktr
35+
module function mean_2_all_${k1}$_${k1}$(x) result(res)
36+
${t1}$, intent(in) :: x(:,:)
37+
${t1}$ :: res
38+
end function mean_2_all_${k1}$_${k1}$
39+
#:endfor
40+
41+
#:for i1, k1, t1 in ikti
42+
module function mean_2_all_${k1}$_dp(x) result(res)
43+
${t1}$, intent(in) :: x(:,:)
44+
real(dp) :: res
45+
end function mean_2_all_${k1}$_dp
46+
#:endfor
47+
48+
#:for i1, k1, t1 in iktr
49+
module function mean_2_${k1}$_${k1}$(x, dim) result(res)
50+
${t1}$, intent(in) :: x(:,:)
51+
integer, intent(in) :: dim
52+
${t1}$ :: res(size(x)/size(x, dim))
53+
end function mean_2_${k1}$_${k1}$
54+
#:endfor
55+
56+
#:for i1, k1, t1 in ikti
57+
module function mean_2_${k1}$_dp(x, dim) result(res)
58+
${t1}$, intent(in) :: x(:,:)
59+
integer, intent(in) :: dim
60+
real(dp) :: res(size(x)/size(x, dim))
61+
end function mean_2_${k1}$_dp
62+
#:endfor
63+
64+
65+
#:def ranksuffix(rank)
66+
#{if rank > 0}#(${":" + ",:" * (rank - 1)}$)#{endif}#
67+
#:enddef
68+
69+
#:if VERSION90
70+
#:set ranks = range(3,8)
71+
#:else
72+
#:set ranks = range(3,16)
73+
#:endif
74+
75+
76+
#:for i1, k1, t1 in iktr
77+
#:for rank in ranks
78+
module function mean_${rank}$_all_${k1}$_${k1}$(x) result(res)
79+
${t1}$, intent(in) :: x${ranksuffix(rank)}$
80+
${t1}$ :: res
81+
end function mean_${rank}$_all_${k1}$_${k1}$
82+
#:endfor
83+
#:endfor
84+
85+
#:for i1, k1, t1 in ikti
86+
#:for rank in ranks
87+
module function mean_${rank}$_all_${k1}$_dp(x) result(res)
88+
${t1}$, intent(in) :: x${ranksuffix(rank)}$
89+
real(dp) :: res
90+
end function mean_${rank}$_all_${k1}$_dp
91+
#:endfor
92+
#:endfor
93+
94+
#:for i1, k1, t1 in iktr
95+
#:for rank in ranks
96+
module function mean_${rank}$_${k1}$_${k1}$(x, dim) result(res)
97+
${t1}$, intent(in) :: x${ranksuffix(rank)}$
98+
integer, intent(in) :: dim
99+
${t1}$ :: res( &
100+
#:for imerge in range(1,rank-1)
101+
merge(size(x,${imerge}$),size(x,${imerge + 1}$),mask = ${imerge}$ < dim ), &
102+
#:endfor
103+
merge(size(x,${rank-1}$),size(x,${rank}$),mask = ${rank-1}$ < dim ) )
104+
end function mean_${rank}$_${k1}$_${k1}$
105+
#:endfor
106+
#:endfor
107+
108+
#:for i1, k1, t1 in ikti
109+
#:for rank in ranks
110+
module function mean_${rank}$_${k1}$_dp(x, dim) result(res)
111+
${t1}$, intent(in) :: x${ranksuffix(rank)}$
112+
integer, intent(in) :: dim
113+
real(dp) :: res( &
114+
#:for imerge in range(1,rank-1)
115+
merge(size(x,${imerge}$),size(x,${imerge + 1}$),mask = ${imerge}$ < dim ), &
116+
#:endfor
117+
merge(size(x,${rank-1}$),size(x,${rank}$),mask = ${rank-1}$ < dim ) )
118+
end function mean_${rank}$_${k1}$_dp
119+
#:endfor
120+
#:endfor
121+
122+
end interface
123+
124+
end module

src/stdlib_experimental_stats.md

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Descriptive statistics
2+
3+
## Implemented
4+
5+
* `mean`
6+
7+
## `mean` - mean of array elements
8+
9+
### Description
10+
11+
Returns the mean of all the elements of `array`, or of the elements of `array` along dimension `dim` if provided.
12+
13+
### Syntax
14+
15+
`result = mean(array)`
16+
17+
`result = mean(array, dim)`
18+
19+
### Arguments
20+
21+
`array`: Shall be an array of type `integer`, or `real`.
22+
23+
`dim`: Shall be a scalar of type `integer` with a value in the range from 1 to n, where n is the rank of `array`.
24+
25+
### Return value
26+
27+
If `array` is of type `real`, the result is of the same type as `array`.
28+
If `array` is of type `integer`, the result is of type `double precision`.
29+
30+
If `dim` is absent, a scalar with the mean of all elements in `array` is returned. Otherwise, an array of rank n-1, where n equals the rank of `array`, and a shape similar to that of `array` with dimension `dim` dropped is returned.
31+
32+
### Example
33+
34+
```fortran
35+
program test
36+
use stdlib_experimental_stats, only: mean
37+
implicit none
38+
real :: x(1:6) = [ 1., 2., 3., 4., 5., 6. ]
39+
print *, mean(x) !returns 21.
40+
print *, mean( reshape(x, [ 2, 3 ] )) !returns 21.
41+
print *, mean( reshape(x, [ 2, 3 ] ), 1) !returns [ 3., 7., 11. ]
42+
end program
43+
```

0 commit comments

Comments
 (0)