11#:include "common.fypp"
22#:set IRS_KINDS_TYPES = INT_KINDS_TYPES + REAL_KINDS_TYPES + STRING_KINDS_TYPES
33
4+ #:set SIGN_NAME = ["increase", "decrease"]
5+ #:set SIGN_TYPE = [">", "<"]
6+ #:set SIGN_OPP_TYPE = ["<", ">"]
7+ #:set SIGN_NAME_TYPE = list(zip(SIGN_NAME, SIGN_TYPE, SIGN_OPP_TYPE))
8+
49!! Licensing:
510!!
611!! This file is subjec† both to the Fortran Standard Library license, and
@@ -57,8 +62,29 @@ submodule(stdlib_sorting) stdlib_sorting_ord_sort
5762contains
5863
5964#:for k1, t1 in IRS_KINDS_TYPES
65+ module subroutine ${k1}$_ord_sort( array, work, reverse )
66+ ${t1}$, intent(inout) :: array(0:)
67+ ${t1}$, intent(out), optional :: work(0:)
68+ logical, intent(in), optional :: reverse
69+
70+ logical :: reverse_
71+
72+ reverse_ = .false.
73+ if(present(reverse)) reverse_ = reverse
74+
75+ if (reverse_) then
76+ call ${k1}$_decrease_ord_sort(array, work)
77+ else
78+ call ${k1}$_increase_ord_sort(array, work)
79+ endif
6080
61- module subroutine ${k1}$_ord_sort( array, work )
81+ end subroutine ${k1}$_ord_sort
82+ #:endfor
83+
84+ #:for sname, signt, signoppt in SIGN_NAME_TYPE
85+ #:for k1, t1 in IRS_KINDS_TYPES
86+
87+ module subroutine ${k1}$_${sname}$_ord_sort( array, work )
6288! A translation to Fortran 2008, of the `"Rust" sort` algorithm found in
6389! `slice.rs`
6490! https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs#L2159
@@ -92,7 +118,7 @@ contains
92118! Allocate a buffer to use as scratch memory.
93119 array_size = size( array, kind=int_size )
94120 allocate( buf(0:array_size/2-1), stat=stat )
95- if ( stat /= 0 ) error stop "${k1}$_ord_sort: Allocation of buffer failed."
121+ if ( stat /= 0 ) error stop "${k1}$_${sname}$ _ord_sort: Allocation of buffer failed."
96122 call merge_sort( array, buf )
97123 end if
98124
@@ -129,7 +155,7 @@ contains
129155 do j=1, size(array, kind=int_size)-1
130156 key = array(j)
131157 i = j - 1
132- do while( i >= 0 .and. array(i) > key )
158+ do while( i >= 0 .and. array(i) ${signt}$ key )
133159 array(i+1) = array(i)
134160 i = i - 1
135161 end do
@@ -204,7 +230,7 @@ contains
204230
205231 tmp = array(0)
206232 find_hole: do i=1, size(array, kind=int_size)-1
207- if ( array(i) > = tmp ) exit find_hole
233+ if ( array(i) ${signt}$ = tmp ) exit find_hole
208234 array(i-1) = array(i)
209235 end do find_hole
210236 array(i-1) = tmp
@@ -263,16 +289,16 @@ contains
263289 start = finish
264290 if ( start > 0 ) then
265291 start = start - 1
266- if ( array(start+1) < array(start) ) then
292+ if ( array(start+1) ${signoppt}$ array(start) ) then
267293 Descending: do while ( start > 0 )
268- if ( array(start) > = array(start-1) ) &
294+ if ( array(start) ${signt}$ = array(start-1) ) &
269295 exit Descending
270296 start = start - 1
271297 end do Descending
272298 call reverse_segment( array(start:finish) )
273299 else
274300 Ascending: do while( start > 0 )
275- if ( array(start) < array(start-1) ) exit Ascending
301+ if ( array(start) ${signoppt}$ array(start-1) ) exit Ascending
276302 start = start - 1
277303 end do Ascending
278304 end if
@@ -338,7 +364,7 @@ contains
338364 i = 0
339365 j = mid
340366 merge_lower: do k = 0, array_len-1
341- if ( buf(i) < = array(j) ) then
367+ if ( buf(i) ${signoppt}$ = array(j) ) then
342368 array(k) = buf(i)
343369 i = i + 1
344370 if ( i >= mid ) exit merge_lower
@@ -356,7 +382,7 @@ contains
356382 i = mid - 1
357383 j = array_len - mid -1
358384 merge_upper: do k = array_len-1, 0, -1
359- if ( buf(j) > = array(i) ) then
385+ if ( buf(j) ${signt}$ = array(i) ) then
360386 array(k) = buf(j)
361387 j = j - 1
362388 if ( j < 0 ) exit merge_upper
@@ -392,12 +418,32 @@ contains
392418
393419 end subroutine reverse_segment
394420
395- end subroutine ${k1}$_ord_sort
421+ end subroutine ${k1}$_${sname}$ _ord_sort
396422
397423#:endfor
424+ #:endfor
425+
426+ module subroutine char_ord_sort( array, work, reverse )
427+ character(len=*), intent(inout) :: array(0:)
428+ character(len=len(array)), intent(out), optional :: work(0:)
429+ logical, intent(in), optional :: reverse
430+
431+ logical :: reverse_
432+
433+ reverse_ = .false.
434+ if(present(reverse)) reverse_ = reverse
398435
436+ if (reverse_) then
437+ call char_decrease_ord_sort(array, work)
438+ else
439+ call char_increase_ord_sort(array, work)
440+ endif
441+
442+ end subroutine char_ord_sort
399443
400- module subroutine char_ord_sort( array, work )
444+
445+ #:for sname, signt, signoppt in SIGN_NAME_TYPE
446+ module subroutine char_${sname}$_ord_sort( array, work )
401447! A translation to Fortran 2008, of the `"Rust" sort` algorithm found in
402448! `slice.rs`
403449! https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs#L2159
@@ -432,7 +478,7 @@ contains
432478 array_size = size( array, kind=int_size )
433479 allocate( character(len=len(array)) :: buf(0:array_size/2-1), &
434480 stat=stat )
435- if ( stat /= 0 ) error stop "${k1}$_ord_sort: Allocation of buffer failed."
481+ if ( stat /= 0 ) error stop "${k1}$_${sname}$ _ord_sort: Allocation of buffer failed."
436482 call merge_sort( array, buf )
437483 end if
438484
@@ -469,7 +515,7 @@ contains
469515 do j=1, size(array, kind=int_size)-1
470516 key = array(j)
471517 i = j - 1
472- do while( i >= 0 .and. array(i) > key )
518+ do while( i >= 0 .and. array(i) ${signt}$ key )
473519 array(i+1) = array(i)
474520 i = i - 1
475521 end do
@@ -544,7 +590,7 @@ contains
544590
545591 tmp = array(0)
546592 find_hole: do i=1, size(array, kind=int_size)-1
547- if ( array(i) > = tmp ) exit find_hole
593+ if ( array(i) ${signt}$ = tmp ) exit find_hole
548594 array(i-1) = array(i)
549595 end do find_hole
550596 array(i-1) = tmp
@@ -603,16 +649,16 @@ contains
603649 start = finish
604650 if ( start > 0 ) then
605651 start = start - 1
606- if ( array(start+1) < array(start) ) then
652+ if ( array(start+1) ${signoppt}$ array(start) ) then
607653 Descending: do while ( start > 0 )
608- if ( array(start) > = array(start-1) ) &
654+ if ( array(start) ${signt}$ = array(start-1) ) &
609655 exit Descending
610656 start = start - 1
611657 end do Descending
612658 call reverse_segment( array(start:finish) )
613659 else
614660 Ascending: do while( start > 0 )
615- if ( array(start) < array(start-1) ) exit Ascending
661+ if ( array(start) ${signoppt}$ array(start-1) ) exit Ascending
616662 start = start - 1
617663 end do Ascending
618664 end if
@@ -678,7 +724,7 @@ contains
678724 i = 0
679725 j = mid
680726 merge_lower: do k = 0, array_len-1
681- if ( buf(i) < = array(j) ) then
727+ if ( buf(i) ${signoppt}$ = array(j) ) then
682728 array(k) = buf(i)
683729 i = i + 1
684730 if ( i >= mid ) exit merge_lower
@@ -696,7 +742,7 @@ contains
696742 i = mid - 1
697743 j = array_len - mid -1
698744 merge_upper: do k = array_len-1, 0, -1
699- if ( buf(j) > = array(i) ) then
745+ if ( buf(j) ${signt}$ = array(i) ) then
700746 array(k) = buf(j)
701747 j = j - 1
702748 if ( j < 0 ) exit merge_upper
@@ -732,7 +778,8 @@ contains
732778
733779 end subroutine reverse_segment
734780
735- end subroutine char_ord_sort
781+ end subroutine char_${sname}$_ord_sort
782+ #:endfor
736783
737784end submodule stdlib_sorting_ord_sort
738785
0 commit comments