-
Notifications
You must be signed in to change notification settings - Fork 184
/
Copy pathstdlib_array.fypp
120 lines (103 loc) · 3.92 KB
/
stdlib_array.fypp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
! SPDX-Identifier: MIT
#:include "common.fypp"
#:set RANKS = range(1, MAXRANK + 1)
#:set KINDS_TYPES = REAL_KINDS_TYPES + INT_KINDS_TYPES + CMPLX_KINDS_TYPES
!> Module for index manipulation and general array handling
!>
!> The specification of this module is available [here](../page/specs/stdlib_array.html).
module stdlib_array
use stdlib_kinds, only: int8, int16, int32, int64, sp, dp, xdp, qp
implicit none
private
public :: trueloc, falseloc
!> Helper class to allocate t_array as an abstract type.
type, public :: t_array_wrapper
class(t_array), allocatable :: array
contains
#:for k1, t1 in KINDS_TYPES
#:for rank in RANKS
generic :: allocate_array => allocate_array_${t1[0]}$${k1}$_${rank}$
procedure :: allocate_array_${t1[0]}$${k1}$_${rank}$
#:endfor
#:endfor
end type
type, abstract, public :: t_array
character(:), allocatable :: name
end type
#:for k1, t1 in KINDS_TYPES
#:for rank in RANKS
type, extends(t_array), public :: t_array_${t1[0]}$${k1}$_${rank}$
${t1}$, allocatable :: values${ranksuffix(rank)}$
end type
#:endfor
#:endfor
contains
#:for k1, t1 in KINDS_TYPES
#:for rank in RANKS
!> Allocate an instance of the array within the wrapper.
subroutine allocate_array_${t1[0]}$${k1}$_${rank}$ (wrapper, array, stat, msg)
class(t_array_wrapper), intent(out) :: wrapper
${t1}$, intent(in) :: array${ranksuffix(rank)}$
integer, intent(out) :: stat
character(len=:), allocatable, intent(out) :: msg
allocate (t_array_${t1[0]}$${k1}$_${rank}$ :: wrapper%array, stat=stat)
if (stat /= 0) then
msg = 'Failed to allocate array.'; return
end if
select type (typed_array => wrapper%array)
class is (t_array_${t1[0]}$${k1}$_${rank}$)
typed_array%values = array
class default
msg = 'Failed to allocate values.'; stat = 1; return
end select
end
#:endfor
#:endfor
!> Version: experimental
!>
!> Return the positions of the true elements in array.
!> [Specification](../page/specs/stdlib_array.html#trueloc)
pure function trueloc(array, lbound) result(loc)
!> Mask of logicals
logical, intent(in) :: array(:)
!> Lower bound of array to index
integer, intent(in), optional :: lbound
!> Locations of true elements
integer :: loc(count(array))
call logicalloc(loc, array, .true., lbound)
end
!> Version: experimental
!>
!> Return the positions of the false elements in array.
!> [Specification](../page/specs/stdlib_array.html#falseloc)
pure function falseloc(array, lbound) result(loc)
!> Mask of logicals
logical, intent(in) :: array(:)
!> Lower bound of array to index
integer, intent(in), optional :: lbound
!> Locations of false elements
integer :: loc(count(.not. array))
call logicalloc(loc, array, .false., lbound)
end
!> Return the positions of the truthy elements in array
pure subroutine logicalloc(loc, array, truth, lbound)
!> Locations of truthy elements
integer, intent(out) :: loc(:)
!> Mask of logicals
logical, intent(in) :: array(:)
!> Truthy value
logical, intent(in) :: truth
!> Lower bound of array to index
integer, intent(in), optional :: lbound
integer :: i, pos, offset
offset = 0
if (present(lbound)) offset = lbound - 1
i = 0
do pos = 1, size(array)
if (array(pos) .eqv. truth) then
i = i + 1
loc(i) = pos + offset
end if
end do
end
end