@@ -80,44 +80,45 @@ contains
8080! a non-increasing sort. The logic of the determination of indexing largely
8181! follows the `"Rust" sort` found in `slice.rs`:
8282! https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs#L2159
83- ! The Rust version is a simplification of the Timsort algorithm described
84- ! in https://svn.python.org/projects/python/trunk/Objects/listsort.txt, as
83+ ! The Rust version in turn is a simplification of the Timsort algorithm
84+ ! described in
85+ ! https://svn.python.org/projects/python/trunk/Objects/listsort.txt, as
8586! it drops both the use of 'galloping' to identify bounds of regions to be
8687! sorted and the estimation of the optimal `run size`. However it remains
8788! a hybrid sorting algorithm combining an iterative Merge sort controlled
8889! by a stack of `RUNS` identified by regions of uniformly decreasing or
89- ! non-decreasing sequences that may be expanded to a minimum run size, with 
90- ! an insertion sort.
90+ ! non-decreasing sequences that may be expanded to a minimum run size and 
91+ ! initially processed by  an insertion sort.
9192!
9293! Note the Fortran implementation simplifies the logic as it only has to
9394! deal with Fortran arrays of intrinsic types and not the full generality
9495! of Rust's arrays and lists for arbitrary types. It also adds the
9596! estimation of the optimal `run size` as suggested in Tim Peters'
96- ! original listsort.txt, and the optional `work` and `iwork` arrays to be
97+ ! original ` listsort.txt` , and the optional `work` and `iwork` arrays to be
9798! used as scratch memory.
9899
99-         ${t1}$, intent(inout)                     :: array(0:)
100+         ${t1}$, intent(inout)         :: array(0:)
100101        ${ti}$, intent(out)           :: index(0:)
101-         ${t3}$, intent(out), optional             :: work(0:)
102+         ${t3}$, intent(out), optional :: work(0:)
102103        ${ti}$, intent(out), optional :: iwork(0:)
103-         logical, intent(in), optional             :: reverse
104+         logical, intent(in), optional :: reverse
104105
105-         ${ti}$ :: array_size, i, stat
106106        ${t2}$, allocatable :: buf(:)
107107        ${ti}$, allocatable :: ibuf(:)
108+         integer(int_index) :: array_size, i, stat
108109
109-         if ( size(array, kind=int_index) > huge(1_${ki}$) ) then
110+         array_size = size(array, kind=int_index)
111+ 
112+         if ( array_size > huge(index)) then
110113            error stop "Too many entries for the kind of index."
111114        end if
112115
113-         array_size = size(array, kind=${ki}$)
114- 
115-         if ( size(index, kind=${ki}$) < array_size ) then
116-             error stop "index array is too small."
116+         if ( array_size > size(index, kind=int_index) ) then
117+             error stop "Too many entries for the size of index."
117118        end if
118119
119120        do i = 0, array_size-1
120-             index(i) = i+1
121+             index(i) = int( i+1, kind=${ki}$) 
121122        end do
122123
123124        if ( optval(reverse, .false.) ) then
@@ -126,11 +127,11 @@ contains
126127
127128! If necessary allocate buffers to serve as scratch memory.
128129        if ( present(work) ) then
129-             if ( size(work, kind=${ki}$ ) < array_size/2 ) then
130+             if ( size(work, kind=int_index ) < array_size/2 ) then
130131                error stop "work array is too small."
131132            end if
132133            if ( present(iwork) ) then
133-                 if ( size(iwork, kind=${ki}$ ) < array_size/2 ) then
134+                 if ( size(iwork, kind=int_index ) < array_size/2 ) then
134135                    error stop "iwork array is too small."
135136                endif
136137                call merge_sort( array, index, work, iwork )
@@ -148,7 +149,7 @@ contains
148149            #:endif
149150            if ( stat /= 0 ) error stop "Allocation of array buffer failed."
150151            if ( present(iwork) ) then
151-                 if ( size(iwork, kind=${ki}$ ) < array_size/2 ) then
152+                 if ( size(iwork, kind=int_index ) < array_size/2 ) then
152153                    error stop "iwork array is too small."
153154                endif
154155                call merge_sort( array, index, buf, iwork )
@@ -169,17 +170,17 @@ contains
169170!! Returns the minimum length of a run from 32-63 so that N/MIN_RUN is
170171!! less than or equal to a power of two. See
171172!! https://svn.python.org/projects/python/trunk/Objects/listsort.txt
172-             ${ti}$              :: min_run
173-             ${ti}$ , intent(in) :: n
173+             integer(int_index)              :: min_run
174+             integer(int_index) , intent(in) :: n
174175
175-             ${ti}$  :: num, r
176+             integer(int_index)  :: num, r
176177
177178            num = n
178-             r = 0_${ki}$ 
179+             r = 0_int_index 
179180
180181            do while( num >= 64 )
181-                 r = ior( r, iand(num, 1_${ki}$ ) )
182-                 num = ishft(num, -1_${ki}$ )
182+                 r = ior( r, iand(num, 1_int_index ) )
183+                 num = ishft(num, -1_int_index )
183184            end do
184185            min_run = num + r
185186
@@ -189,13 +190,14 @@ contains
189190        pure subroutine insertion_sort( array, index )
190191! Sorts `ARRAY` using an insertion sort, while maintaining consistency in
191192! location of the indices in `INDEX` to the elements of `ARRAY`.
192-             ${t1}$, intent(inout)             :: array(0:)
193+             ${t1}$, intent(inout) :: array(0:)
193194            ${ti}$, intent(inout) :: index(0:)
194195
195-             ${ti}$ :: i, j, key_index
196+             integer(int_index) :: i, j
197+             ${ti}$ :: key_index
196198            ${t3}$ :: key
197199
198-             do j=1, size(array, kind=${ki}$ )-1
200+             do j=1, size(array, kind=int_index )-1
199201                key = array(j)
200202                key_index = index(j)
201203                i = j - 1
@@ -218,14 +220,13 @@ contains
218220!
219221! 1. len(-3) > len(-2) + len(-1)
220222! 2. len(-2) > len(-1)
223+             integer(int_index) :: r
224+             type(run_type), intent(in), target :: runs(0:)
221225
222-             ${ti}$ :: r
223-             type(run_type_${namei}$), intent(in), target :: runs(0:)
224- 
225-             ${ti}$ :: n
226+             integer(int_index) :: n
226227            logical :: test
227228
228-             n = size(runs, kind=${ki}$ )
229+             n = size(runs, kind=int_index )
229230            test = .false.
230231            if (n >= 2) then
231232                if ( runs( n-1 ) % base == 0 .or. &
@@ -273,15 +274,16 @@ contains
273274! Consistency of the indices in `index` with the elements of `array`
274275! are maintained.
275276
276-             ${t1}$, intent(inout)             :: array(0:)
277+             ${t1}$, intent(inout) :: array(0:)
277278            ${ti}$, intent(inout) :: index(0:)
278279
279280            ${t3}$ :: tmp
280-             ${ti}$ :: i, tmp_index
281+             integer(int_index) :: i
282+             ${ti}$ :: tmp_index
281283
282284            tmp = array(0)
283285            tmp_index = index(0)
284-             find_hole: do i=1, size(array, kind=${ki}$ )-1
286+             find_hole: do i=1, size(array, kind=int_index )-1
285287                if ( array(i) >= tmp ) exit find_hole
286288                array(i-1) = array(i)
287289                index(i-1) = index(i)
@@ -313,16 +315,16 @@ contains
313315! worst-case. Consistency of the indices in `index` with the elements of
314316! `array` are maintained.
315317
316-             ${t1}$, intent(inout)             :: array(0:)
318+             ${t1}$, intent(inout) :: array(0:)
317319            ${ti}$, intent(inout) :: index(0:)
318-             ${t3}$, intent(inout)             :: buf(0:)
320+             ${t3}$, intent(inout) :: buf(0:)
319321            ${ti}$, intent(inout) :: ibuf(0:)
320322
321-             ${ti}$  :: array_size, finish, min_run, r, r_count, &
323+             integer(int_index)  :: array_size, finish, min_run, r, r_count, &
322324                start
323-             type(run_type_${namei}$ ) :: runs(0:max_merge_stack-1), left, right
325+             type(run_type ) :: runs(0:max_merge_stack-1), left, right
324326
325-             array_size = size(array, kind=${ki}$ )
327+             array_size = size(array, kind=int_index )
326328
327329! Very short runs are extended using insertion sort to span at least this
328330! many elements. Slices of up to this length are sorted using insertion sort.
@@ -333,7 +335,6 @@ contains
333335                return
334336            end if
335337
336- 
337338! Following Rust sort, natural runs in `array` are identified by traversing
338339! it backwards. By traversing it backward, merges more often go in the
339340! opposite direction (forwards). According to developers of Rust sort,
@@ -370,7 +371,7 @@ contains
370371                end do Insert
371372                if ( start == 0 .and. finish == array_size - 1 ) return
372373
373-                 runs(r_count) = run_type_${namei}$ ( base = start, &
374+                 runs(r_count) = run_type ( base = start, &
374375                                          len = finish - start + 1 )
375376                finish = start-1
376377                r_count = r_count + 1
@@ -383,12 +384,12 @@ contains
383384                    left = runs( r + 1 )
384385                    right = runs( r )
385386                    call merge( array( left % base: &
386-                                      right % base + right % len - 1 ), &
387+                                         right % base + right % len - 1 ), &
387388                                left % len, buf, &
388389                                index( left % base: &
389390                                     right % base + right % len - 1 ), ibuf )
390391
391-                     runs(r) = run_type_${namei}$ ( base = left % base, &
392+                     runs(r) = run_type ( base = left % base, &
392393                                        len = left % len + right % len )
393394                    if ( r == r_count - 3 ) runs(r+1) = runs(r+2)
394395                    r_count = r_count - 1
@@ -406,15 +407,15 @@ contains
406407! using `BUF` as temporary storage, and stores the merged runs into
407408! `ARRAY(0:)`. `MID` must be > 0, and < `SIZE(ARRAY)-1`. Buffer `BUF`
408409! must be long enough to hold the shorter of the two runs.
409-             ${t1}$, intent(inout)             :: array(0:)
410-             ${ti}$ , intent(in)     :: mid
411-             ${t3}$, intent(inout)             :: buf(0:)
410+             ${t1}$, intent(inout) :: array(0:)
411+             integer(int_index) , intent(in)  :: mid
412+             ${t3}$, intent(inout) :: buf(0:)
412413            ${ti}$, intent(inout) :: index(0:)
413414            ${ti}$, intent(inout) :: ibuf(0:)
414415
415-             ${ti}$  :: array_len, i, j, k
416+             integer(int_index)  :: array_len, i, j, k
416417
417-             array_len = size(array, kind=${ki}$ )
418+             array_len = size(array, kind=int_index )
418419
419420! Merge first copies the shorter run into `buf`. Then, depending on which
420421! run was shorter, it traces the copied run and the longer run forwards
@@ -474,11 +475,12 @@ contains
474475            ${t1}$, intent(inout) :: array(0:)
475476            ${ti}$, intent(inout) :: index(0:)
476477
477-             ${ti}$ :: itemp, lo, hi
478+             ${ti}$ :: itemp
479+             integer(int_index) :: lo, hi
478480            ${t3}$ :: temp
479481
480482            lo = 0
481-             hi = size( array, kind=${ki}$  ) - 1
483+             hi = size( array, kind=int_index  ) - 1
482484            do while( lo < hi )
483485                temp = array(lo)
484486                array(lo) = array(hi)
0 commit comments