5
5
#:set CHAR_TYPES_ALT_NAME = list(zip(["character(len=*)"], ["character(len=:)"], ["character(len=len(array))"], ["char"]))
6
6
#:set BITSET_TYPES_ALT_NAME = list(zip(BITSET_TYPES, BITSET_TYPES, BITSET_TYPES, BITSET_KINDS))
7
7
8
+ #:set INT_INDEX_TYPES_ALT_NAME = list(zip(["int_index", "int_index_low"], ["integer(int_index)", "integer(int_index_low)"], ["default", "low"]))
9
+
8
10
#! For better code reuse in fypp, make lists that contain the input types,
9
11
#! with each having output types and a separate name prefix for subroutines
10
12
#! This approach allows us to have the same code for all input types.
@@ -66,9 +68,10 @@ submodule(stdlib_sorting) stdlib_sorting_sort_index
66
68
67
69
contains
68
70
69
- #:for t1, t2, t3, name1 in IRSCB_TYPES_ALT_NAME
71
+ #:for ki, ti, namei in INT_INDEX_TYPES_ALT_NAME
72
+ #:for t1, t2, t3, name1 in IRSCB_TYPES_ALT_NAME
70
73
71
- module subroutine ${name1}$_sort_index ( array, index, work, iwork, reverse )
74
+ module subroutine ${name1}$_sort_index_${namei}$ ( array, index, work, iwork, reverse )
72
75
! A modification of `${name1}$_ord_sort` to return an array of indices that
73
76
! would perform a stable sort of the `ARRAY` as input, and also sort `ARRAY`
74
77
! as desired. The indices by default
@@ -94,16 +97,16 @@ contains
94
97
! used as scratch memory.
95
98
96
99
${t1}$, intent(inout) :: array(0:)
97
- integer(int_index) , intent(out) :: index(0:)
100
+ ${ti}$ , intent(out) :: index(0:)
98
101
${t3}$, intent(out), optional :: work(0:)
99
- integer(int_index) , intent(out), optional :: iwork(0:)
102
+ ${ti}$ , intent(out), optional :: iwork(0:)
100
103
logical, intent(in), optional :: reverse
101
104
102
- integer(int_index) :: array_size, i, stat
105
+ ${ti}$ :: array_size, i, stat
103
106
${t2}$, allocatable :: buf(:)
104
- integer(int_index) , allocatable :: ibuf(:)
107
+ ${ti}$ , allocatable :: ibuf(:)
105
108
106
- array_size = size(array, kind=int_index )
109
+ array_size = size(array, kind=${ki}$ )
107
110
108
111
do i = 0, array_size-1
109
112
index(i) = i+1
@@ -115,11 +118,11 @@ contains
115
118
116
119
! If necessary allocate buffers to serve as scratch memory.
117
120
if ( present(work) ) then
118
- if ( size(work, kind=int_index ) < array_size/2 ) then
121
+ if ( size(work, kind=${ki}$ ) < array_size/2 ) then
119
122
error stop "work array is too small."
120
123
end if
121
124
if ( present(iwork) ) then
122
- if ( size(iwork, kind=int_index ) < array_size/2 ) then
125
+ if ( size(iwork, kind=${ki}$ ) < array_size/2 ) then
123
126
error stop "iwork array is too small."
124
127
endif
125
128
call merge_sort( array, index, work, iwork )
@@ -137,7 +140,7 @@ contains
137
140
#:endif
138
141
if ( stat /= 0 ) error stop "Allocation of array buffer failed."
139
142
if ( present(iwork) ) then
140
- if ( size(iwork, kind=int_index ) < array_size/2 ) then
143
+ if ( size(iwork, kind=${ki}$ ) < array_size/2 ) then
141
144
error stop "iwork array is too small."
142
145
endif
143
146
call merge_sort( array, index, buf, iwork )
@@ -158,17 +161,17 @@ contains
158
161
!! Returns the minimum length of a run from 32-63 so that N/MIN_RUN is
159
162
!! less than or equal to a power of two. See
160
163
!! https://svn.python.org/projects/python/trunk/Objects/listsort.txt
161
- integer(int_index) :: min_run
162
- integer(int_index) , intent(in) :: n
164
+ ${ti}$ :: min_run
165
+ ${ti}$ , intent(in) :: n
163
166
164
- integer(int_index) :: num, r
167
+ ${ti}$ :: num, r
165
168
166
169
num = n
167
- r = 0_int_index
170
+ r = 0_${ki}$
168
171
169
172
do while( num >= 64 )
170
- r = ior( r, iand(num, 1_int_index ) )
171
- num = ishft(num, -1_int_index )
173
+ r = ior( r, iand(num, 1_${ki}$ ) )
174
+ num = ishft(num, -1_${ki}$ )
172
175
end do
173
176
min_run = num + r
174
177
@@ -179,12 +182,12 @@ contains
179
182
! Sorts `ARRAY` using an insertion sort, while maintaining consistency in
180
183
! location of the indices in `INDEX` to the elements of `ARRAY`.
181
184
${t1}$, intent(inout) :: array(0:)
182
- integer(int_index) , intent(inout) :: index(0:)
185
+ ${ti}$ , intent(inout) :: index(0:)
183
186
184
- integer(int_index) :: i, j, key_index
187
+ ${ti}$ :: i, j, key_index
185
188
${t3}$ :: key
186
189
187
- do j=1, size(array, kind=int_index )-1
190
+ do j=1, size(array, kind=${ki}$ )-1
188
191
key = array(j)
189
192
key_index = index(j)
190
193
i = j - 1
@@ -208,13 +211,13 @@ contains
208
211
! 1. len(-3) > len(-2) + len(-1)
209
212
! 2. len(-2) > len(-1)
210
213
211
- integer(int_index) :: r
212
- type(run_type ), intent(in), target :: runs(0:)
214
+ ${ti}$ :: r
215
+ type(run_type_${namei}$ ), intent(in), target :: runs(0:)
213
216
214
- integer(int_index) :: n
217
+ ${ti}$ :: n
215
218
logical :: test
216
219
217
- n = size(runs, kind=int_index )
220
+ n = size(runs, kind=${ki}$ )
218
221
test = .false.
219
222
if (n >= 2) then
220
223
if ( runs( n-1 ) % base == 0 .or. &
@@ -263,14 +266,14 @@ contains
263
266
! are maintained.
264
267
265
268
${t1}$, intent(inout) :: array(0:)
266
- integer(int_index) , intent(inout) :: index(0:)
269
+ ${ti}$ , intent(inout) :: index(0:)
267
270
268
271
${t3}$ :: tmp
269
- integer(int_index) :: i, tmp_index
272
+ ${ti}$ :: i, tmp_index
270
273
271
274
tmp = array(0)
272
275
tmp_index = index(0)
273
- find_hole: do i=1, size(array, kind=int_index )-1
276
+ find_hole: do i=1, size(array, kind=${ki}$ )-1
274
277
if ( array(i) >= tmp ) exit find_hole
275
278
array(i-1) = array(i)
276
279
index(i-1) = index(i)
@@ -303,15 +306,15 @@ contains
303
306
! `array` are maintained.
304
307
305
308
${t1}$, intent(inout) :: array(0:)
306
- integer(int_index) , intent(inout) :: index(0:)
309
+ ${ti}$ , intent(inout) :: index(0:)
307
310
${t3}$, intent(inout) :: buf(0:)
308
- integer(int_index) , intent(inout) :: ibuf(0:)
311
+ ${ti}$ , intent(inout) :: ibuf(0:)
309
312
310
- integer(int_index) :: array_size, finish, min_run, r, r_count, &
313
+ ${ti}$ :: array_size, finish, min_run, r, r_count, &
311
314
start
312
- type(run_type ) :: runs(0:max_merge_stack-1), left, right
315
+ type(run_type_${namei}$ ) :: runs(0:max_merge_stack-1), left, right
313
316
314
- array_size = size(array, kind=int_index )
317
+ array_size = size(array, kind=${ki}$ )
315
318
316
319
! Very short runs are extended using insertion sort to span at least this
317
320
! many elements. Slices of up to this length are sorted using insertion sort.
@@ -359,7 +362,7 @@ contains
359
362
end do Insert
360
363
if ( start == 0 .and. finish == array_size - 1 ) return
361
364
362
- runs(r_count) = run_type ( base = start, &
365
+ runs(r_count) = run_type_${namei}$ ( base = start, &
363
366
len = finish - start + 1 )
364
367
finish = start-1
365
368
r_count = r_count + 1
@@ -377,7 +380,7 @@ contains
377
380
index( left % base: &
378
381
right % base + right % len - 1 ), ibuf )
379
382
380
- runs(r) = run_type ( base = left % base, &
383
+ runs(r) = run_type_${namei}$ ( base = left % base, &
381
384
len = left % len + right % len )
382
385
if ( r == r_count - 3 ) runs(r+1) = runs(r+2)
383
386
r_count = r_count - 1
@@ -396,14 +399,14 @@ contains
396
399
! `ARRAY(0:)`. `MID` must be > 0, and < `SIZE(ARRAY)-1`. Buffer `BUF`
397
400
! must be long enough to hold the shorter of the two runs.
398
401
${t1}$, intent(inout) :: array(0:)
399
- integer(int_index) , intent(in) :: mid
402
+ ${ti}$ , intent(in) :: mid
400
403
${t3}$, intent(inout) :: buf(0:)
401
- integer(int_index) , intent(inout) :: index(0:)
402
- integer(int_index) , intent(inout) :: ibuf(0:)
404
+ ${ti}$ , intent(inout) :: index(0:)
405
+ ${ti}$ , intent(inout) :: ibuf(0:)
403
406
404
- integer(int_index) :: array_len, i, j, k
407
+ ${ti}$ :: array_len, i, j, k
405
408
406
- array_len = size(array, kind=int_index )
409
+ array_len = size(array, kind=${ki}$ )
407
410
408
411
! Merge first copies the shorter run into `buf`. Then, depending on which
409
412
! run was shorter, it traces the copied run and the longer run forwards
@@ -461,13 +464,13 @@ contains
461
464
pure subroutine reverse_segment( array, index )
462
465
! Reverse a segment of an array in place
463
466
${t1}$, intent(inout) :: array(0:)
464
- integer(int_index) , intent(inout) :: index(0:)
467
+ ${ti}$ , intent(inout) :: index(0:)
465
468
466
- integer(int_index) :: itemp, lo, hi
469
+ ${ti}$ :: itemp, lo, hi
467
470
${t3}$ :: temp
468
471
469
472
lo = 0
470
- hi = size( array, kind=int_index ) - 1
473
+ hi = size( array, kind=${ki}$ ) - 1
471
474
do while( lo < hi )
472
475
temp = array(lo)
473
476
array(lo) = array(hi)
@@ -481,8 +484,9 @@ contains
481
484
482
485
end subroutine reverse_segment
483
486
484
- end subroutine ${name1}$_sort_index
487
+ end subroutine ${name1}$_sort_index_${namei}$
485
488
489
+ #:endfor
486
490
#:endfor
487
491
488
492
end submodule stdlib_sorting_sort_index
0 commit comments