1
1
#:include "common.fypp"
2
2
#:set IRS_KINDS_TYPES = INT_KINDS_TYPES + REAL_KINDS_TYPES + STRING_KINDS_TYPES
3
3
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
+
4
9
!! Licensing:
5
10
!!
6
11
!! This file is subjec† both to the Fortran Standard Library license, and
@@ -57,8 +62,29 @@ submodule(stdlib_sorting) stdlib_sorting_ord_sort
57
62
contains
58
63
59
64
#: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
60
80
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
+ subroutine ${k1}$_${sname}$_ord_sort( array, work )
62
88
! A translation to Fortran 2008, of the `"Rust" sort` algorithm found in
63
89
! `slice.rs`
64
90
! https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs#L2159
@@ -92,7 +118,7 @@ contains
92
118
! Allocate a buffer to use as scratch memory.
93
119
array_size = size( array, kind=int_size )
94
120
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."
96
122
call merge_sort( array, buf )
97
123
end if
98
124
@@ -129,7 +155,7 @@ contains
129
155
do j=1, size(array, kind=int_size)-1
130
156
key = array(j)
131
157
i = j - 1
132
- do while( i >= 0 .and. array(i) > key )
158
+ do while( i >= 0 .and. array(i) ${signt}$ key )
133
159
array(i+1) = array(i)
134
160
i = i - 1
135
161
end do
@@ -204,7 +230,7 @@ contains
204
230
205
231
tmp = array(0)
206
232
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
208
234
array(i-1) = array(i)
209
235
end do find_hole
210
236
array(i-1) = tmp
@@ -263,16 +289,16 @@ contains
263
289
start = finish
264
290
if ( start > 0 ) then
265
291
start = start - 1
266
- if ( array(start+1) < array(start) ) then
292
+ if ( array(start+1) ${signoppt}$ array(start) ) then
267
293
Descending: do while ( start > 0 )
268
- if ( array(start) > = array(start-1) ) &
294
+ if ( array(start) ${signt}$ = array(start-1) ) &
269
295
exit Descending
270
296
start = start - 1
271
297
end do Descending
272
298
call reverse_segment( array(start:finish) )
273
299
else
274
300
Ascending: do while( start > 0 )
275
- if ( array(start) < array(start-1) ) exit Ascending
301
+ if ( array(start) ${signoppt}$ array(start-1) ) exit Ascending
276
302
start = start - 1
277
303
end do Ascending
278
304
end if
@@ -338,7 +364,7 @@ contains
338
364
i = 0
339
365
j = mid
340
366
merge_lower: do k = 0, array_len-1
341
- if ( buf(i) < = array(j) ) then
367
+ if ( buf(i) ${signoppt}$ = array(j) ) then
342
368
array(k) = buf(i)
343
369
i = i + 1
344
370
if ( i >= mid ) exit merge_lower
@@ -356,7 +382,7 @@ contains
356
382
i = mid - 1
357
383
j = array_len - mid -1
358
384
merge_upper: do k = array_len-1, 0, -1
359
- if ( buf(j) > = array(i) ) then
385
+ if ( buf(j) ${signt}$ = array(i) ) then
360
386
array(k) = buf(j)
361
387
j = j - 1
362
388
if ( j < 0 ) exit merge_upper
@@ -392,12 +418,32 @@ contains
392
418
393
419
end subroutine reverse_segment
394
420
395
- end subroutine ${k1}$_ord_sort
421
+ end subroutine ${k1}$_${sname}$ _ord_sort
396
422
397
423
#: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
398
435
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
399
443
400
- module subroutine char_ord_sort( array, work )
444
+
445
+ #:for sname, signt, signoppt in SIGN_NAME_TYPE
446
+ subroutine char_${sname}$_ord_sort( array, work )
401
447
! A translation to Fortran 2008, of the `"Rust" sort` algorithm found in
402
448
! `slice.rs`
403
449
! https://github.com/rust-lang/rust/blob/90eb44a5897c39e3dff9c7e48e3973671dcd9496/src/liballoc/slice.rs#L2159
@@ -432,7 +478,7 @@ contains
432
478
array_size = size( array, kind=int_size )
433
479
allocate( character(len=len(array)) :: buf(0:array_size/2-1), &
434
480
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."
436
482
call merge_sort( array, buf )
437
483
end if
438
484
@@ -469,7 +515,7 @@ contains
469
515
do j=1, size(array, kind=int_size)-1
470
516
key = array(j)
471
517
i = j - 1
472
- do while( i >= 0 .and. array(i) > key )
518
+ do while( i >= 0 .and. array(i) ${signt}$ key )
473
519
array(i+1) = array(i)
474
520
i = i - 1
475
521
end do
@@ -544,7 +590,7 @@ contains
544
590
545
591
tmp = array(0)
546
592
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
548
594
array(i-1) = array(i)
549
595
end do find_hole
550
596
array(i-1) = tmp
@@ -603,16 +649,16 @@ contains
603
649
start = finish
604
650
if ( start > 0 ) then
605
651
start = start - 1
606
- if ( array(start+1) < array(start) ) then
652
+ if ( array(start+1) ${signoppt}$ array(start) ) then
607
653
Descending: do while ( start > 0 )
608
- if ( array(start) > = array(start-1) ) &
654
+ if ( array(start) ${signt}$ = array(start-1) ) &
609
655
exit Descending
610
656
start = start - 1
611
657
end do Descending
612
658
call reverse_segment( array(start:finish) )
613
659
else
614
660
Ascending: do while( start > 0 )
615
- if ( array(start) < array(start-1) ) exit Ascending
661
+ if ( array(start) ${signoppt}$ array(start-1) ) exit Ascending
616
662
start = start - 1
617
663
end do Ascending
618
664
end if
@@ -678,7 +724,7 @@ contains
678
724
i = 0
679
725
j = mid
680
726
merge_lower: do k = 0, array_len-1
681
- if ( buf(i) < = array(j) ) then
727
+ if ( buf(i) ${signoppt}$ = array(j) ) then
682
728
array(k) = buf(i)
683
729
i = i + 1
684
730
if ( i >= mid ) exit merge_lower
@@ -696,7 +742,7 @@ contains
696
742
i = mid - 1
697
743
j = array_len - mid -1
698
744
merge_upper: do k = array_len-1, 0, -1
699
- if ( buf(j) > = array(i) ) then
745
+ if ( buf(j) ${signt}$ = array(i) ) then
700
746
array(k) = buf(j)
701
747
j = j - 1
702
748
if ( j < 0 ) exit merge_upper
@@ -732,7 +778,8 @@ contains
732
778
733
779
end subroutine reverse_segment
734
780
735
- end subroutine char_ord_sort
781
+ end subroutine char_${sname}$_ord_sort
782
+ #:endfor
736
783
737
784
end submodule stdlib_sorting_ord_sort
738
785
0 commit comments