Skip to content

Commit 4931ecb

Browse files
committed
add specs file for radix_sort
1 parent d49178a commit 4931ecb

File tree

3 files changed

+187
-104
lines changed

3 files changed

+187
-104
lines changed

doc/specs/stdlib_sorting.md

Lines changed: 185 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ module's `string_type` type.
2525
## Overview of the module
2626

2727
The module `stdlib_sorting` defines several public entities, one
28-
default integer parameter, `int_size`, and three overloaded
29-
subroutines: `ORD_SORT`, `SORT`, and `SORT_INDEX`. The
30-
overloaded subroutines also each have seven specific names for
28+
default integer parameter, `int_size`, and four overloaded
29+
subroutines: `ORD_SORT`, `SORT`, `RADIX_SORT` and `SORT_INDEX`. The
30+
overloaded subroutines also each have several specific names for
3131
versions corresponding to different types of array arguments.
3232

3333
### The `int_size` parameter
@@ -47,9 +47,11 @@ data:
4747
* `SORT_INDEX` is based on `ORD_SORT`, but in addition to sorting the
4848
input array, it returns indices that map the original array to its
4949
sorted version. This enables related arrays to be re-ordered in the
50-
same way; and
50+
same way;
5151
* `SORT` is intended to sort simple arrays of intrinsic data
52-
that are effectively unordered before the sort.
52+
that are effectively unordered before the sort;
53+
* `RADIX_SORT` is intended to sort fixed width intrinsic data
54+
types (integers and reals).
5355

5456
#### Licensing
5557

@@ -196,6 +198,18 @@ magnitude slower than `ORD_SORT`. Its memory requirements are also
196198
low, being of order O(Ln(N)), while the memory requirements of
197199
`ORD_SORT` and `SORT_INDEX` are of order O(N).
198200

201+
#### The `RADIX_SORT` subroutine
202+
203+
`RADIX_SORT` is a implementation of LSD [radix sort](https://en.wikipedia.org/wiki/Radix_sort),
204+
using `256` (one byte) as the radix. It only works for fixed width data,
205+
thus integers and reals. `RADIX_SORT` is always of O(N) runtime performance
206+
for any input data. For large and random data, it is about five (or more)
207+
times faster than other sort subroutines.
208+
209+
The `RADIX_SORT` needs a buffer that have same size of the input data.
210+
Your can provide it using `work` arguement, if not the subroutine will
211+
allocate the buffer and deallocate before return.
212+
199213
### Specifications of the `stdlib_sorting` procedures
200214

201215
#### `ord_sort` - sorts an input array
@@ -318,6 +332,55 @@ element of `array` is a `NaN`. Sorting of `CHARACTER(*)` and
318332
{!example/sorting/example_sort.f90!}
319333
```
320334

335+
#### `radix_sort` - sorts an input array
336+
337+
##### Status
338+
339+
Experimental
340+
341+
##### Description
342+
343+
Returns an input array with the elements sorted in order of increasing, or
344+
decreasing, value.
345+
346+
##### Syntax
347+
348+
`call [[stdlib_sorting(module):radix_sort(interface)]]( array[, work, reverse] )`
349+
350+
##### Class
351+
352+
Generic subroutine.
353+
354+
##### Arguments
355+
356+
`array` : shall be a rank one array of any of the types:
357+
`integer(int8)`, `integer(int16)`, `integer(int32)`, `integer(int64)`,
358+
`real(sp)`, `real(dp)`. It is an `intent(inout)` argument. On return its
359+
input elements will be sorted in order of non-decreasing value.
360+
361+
`work` (optional): shall be a rank one array of the same type as
362+
array, and shall have at least `size(array)` elements. It is an
363+
`intent(inout)` argument, and its contents on return are undefined.
364+
365+
`reverse` (optional): shall be a scalar of type default logical. It
366+
is an `intent(in)` argument. If present with a value of `.true.` then
367+
`array` will be sorted in order of non-increasing values in unstable
368+
order. Otherwise index will sort `array` in order of non-decreasing
369+
values in unstable order.
370+
371+
##### Notes
372+
373+
`SORT` implements a LSD radix sort algorithm with a `256` radix. For any
374+
input data it provides `O(N)` run time performance. If `array` is of
375+
any type `REAL` the order of its elements on return undefined if any
376+
element of `array` is a `NaN`.
377+
378+
##### Example
379+
380+
```fortran
381+
{!example/sorting/example_radix_sort.f90!}
382+
```
383+
321384
#### `sort_index` - creates an array of sorting indices for an input array, while also sorting the array.
322385

323386
##### Status
@@ -496,107 +559,126 @@ of size `16**3`, with characters drawn from the set "a"-"p":
496559
random order.
497560

498561
These benchmarks have been performed on two different compilers, both
499-
on a MacBook Pro, featuring a 2.3 GHz Quad-Core Intel Core i5, with 8
500-
GB 2133 MHz LPDDR3 memory. The first compiler was GNU Fortran
501-
(GCC) 10.2.0, with the following results:
562+
on WSL with Ubuntu-20.04, Intel(R) Core(TM) i7-10700 CPU @ 2.9GHz, with
563+
32 GB DDR4 memory. The first compiler is GNU Fortran (GCC) 9.4.0, with
564+
the following results.
502565

503566
| Type | Elements | Array Name | Method | Time (s) |
504567
|-------------|----------|-----------------|-------------|-----------|
505-
| Integer | 65536 | Blocks | Ord_Sort | 0.000579 |
506-
| Integer | 65536 | Decreasing | Ord_Sort | 0.000212 |
507-
| Integer | 65536 | Identical | Ord_Sort | 0.000165 |
508-
| Integer | 65536 | Increasing | Ord_Sort | 0.000131 |
509-
| Integer | 65536 | Random dense | Ord_Sort | 0.009991 |
510-
| Integer | 65536 | Random order | Ord_Sort | 0.008574 |
511-
| Integer | 65536 | Random sparse | Ord_Sort | 0.010504 |
512-
| Integer | 65536 | Random 3 | Ord_Sort | 0.000532 |
513-
| Integer | 65536 | Random 10 | Ord_Sort | 0.000315 |
514-
| Character | 65536 | Char. Decrease | Ord_Sort | 0.001041 |
515-
| Character | 65536 | Char. Increase | Ord_Sort | 0.000584 |
516-
| Character | 65536 | Char. Random | Ord_Sort | 0.026273 |
517-
| String_type | 4096 | String Decrease | Ord_Sort | 0.001202 |
518-
| String_type | 4096 | String Increase | Ord_Sort | 0.000758 |
519-
| String_type | 4096 | String Random | Ord_Sort | 0.018180 |
520-
| Integer | 65536 | Blocks | Sort | 0.005073 |
521-
| Integer | 65536 | Decreasing | Sort | 0.005830 |
522-
| Integer | 65536 | Identical | Sort | 0.007372 |
523-
| Integer | 65536 | Increasing | Sort | 0.002421 |
524-
| Integer | 65536 | Random dense | Sort | 0.007006 |
525-
| Integer | 65536 | Random order | Sort | 0.007211 |
526-
| Integer | 65536 | Random sparse | Sort | 0.007109 |
527-
| Integer | 65536 | Random 3 | Sort | 0.012232 |
528-
| Integer | 65536 | Random 10 | Sort | 0.017345 |
529-
| Character | 65536 | Char. Decrease | Sort | 0.031350 |
530-
| Character | 65536 | Char. Increase | Sort | 0.011606 |
531-
| Character | 65536 | Char. Random | Sort | 0.022440 |
532-
| String_type | 4096 | String Decrease | Sort | 0.026539 |
533-
| String_type | 4096 | String Increase | Sort | 0.009755 |
534-
| String_type | 4096 | String Random | Sort | 0.016218 |
535-
| Integer | 65536 | Blocks | Sort_Index | 0.000953 |
536-
| Integer | 65536 | Decreasing | Sort_Index | 0.000418 |
537-
| Integer | 65536 | Identical | Sort_Index | 0.000264 |
538-
| Integer | 65536 | Increasing | Sort_Index | 0.000262 |
539-
| Integer | 65536 | Random dense | Sort_Index | 0.009563 |
540-
| Integer | 65536 | Random order | Sort_Index | 0.009592 |
541-
| Integer | 65536 | Random sparse | Sort_Index | 0.009691 |
542-
| Integer | 65536 | Random 3 | Sort_Index | 0.000781 |
543-
| Integer | 65536 | Random 10 | Sort_Index | 0.000455 |
544-
| Character | 65536 | Char. Decrease | Sort_Index | 0.001189 |
545-
| Character | 65536 | Char. Increase | Sort_Index | 0.000752 |
546-
| Character | 65536 | Char. Random | Sort_Index | 0.025767 |
547-
| String_type | 4096 | String Decrease | Sort_Index | 0.001411 |
548-
| String_type | 4096 | String Increase | Sort_Index | 0.000761 |
549-
| String_type | 4096 | String Random | Sort_Index | 0.018202 |
550-
551-
The second compiler was Intel(R) Fortran Intel(R) 64 Compiler Classic
552-
for applications running on Intel(R) 64, Version 2021.2.0 Build
553-
20210228_000000, with the following results:
568+
| Integer | 65536 | Blocks | Ord_Sort | 0.001048 |
569+
| Integer | 65536 | Decreasing | Ord_Sort | 0.000204 |
570+
| Integer | 65536 | Identical | Ord_Sort | 0.000097 |
571+
| Integer | 65536 | Increasing | Ord_Sort | 0.000096 |
572+
| Integer | 65536 | Random dense | Ord_Sort | 0.006580 |
573+
| Integer | 65536 | Random order | Ord_Sort | 0.006886 |
574+
| Integer | 65536 | Random sparse | Ord_Sort | 0.006821 |
575+
| Integer | 65536 | Random 3 | Ord_Sort | 0.000461 |
576+
| Integer | 65536 | Random 10 | Ord_Sort | 0.000226 |
577+
| Character | 65536 | Char. Decrease | Ord_Sort | 0.000824 |
578+
| Character | 65536 | Char. Increase | Ord_Sort | 0.000370 |
579+
| Character | 65536 | Char. Random | Ord_Sort | 0.016020 |
580+
| String_type | 4096 | String Decrease | Ord_Sort | 0.000465 |
581+
| String_type | 4096 | String Increase | Ord_Sort | 0.000169 |
582+
| String_type | 4096 | String Random | Ord_Sort | 0.004194 |
583+
| Integer | 65536 | Blocks | Radix_Sort | 0.001610 |
584+
| Integer | 65536 | Decreasing | Radix_Sort | 0.001076 |
585+
| Integer | 65536 | Identical | Radix_Sort | 0.001074 |
586+
| Integer | 65536 | Increasing | Radix_Sort | 0.001060 |
587+
| Integer | 65536 | Random dense | Radix_Sort | 0.001161 |
588+
| Integer | 65536 | Random order | Radix_Sort | 0.001069 |
589+
| Integer | 65536 | Random sparse | Radix_Sort | 0.001005 |
590+
| Integer | 65536 | Random 3 | Radix_Sort | 0.001057 |
591+
| Integer | 65536 | Random 10 | Radix_Sort | 0.001046 |
592+
| Integer | 65536 | rand-real32 | Radix_Sort | 0.001429 |
593+
| Integer | 65536 | Blocks | Sort | 0.004269 |
594+
| Integer | 65536 | Decreasing | Sort | 0.005108 |
595+
| Integer | 65536 | Identical | Sort | 0.006257 |
596+
| Integer | 65536 | Increasing | Sort | 0.002093 |
597+
| Integer | 65536 | Random dense | Sort | 0.006032 |
598+
| Integer | 65536 | Random order | Sort | 0.006030 |
599+
| Integer | 65536 | Random sparse | Sort | 0.006126 |
600+
| Integer | 65536 | Random 3 | Sort | 0.007930 |
601+
| Integer | 65536 | Random 10 | Sort | 0.014729 |
602+
| Character | 65536 | Char. Decrease | Sort | 0.020623 |
603+
| Character | 65536 | Char. Increase | Sort | 0.008028 |
604+
| Character | 65536 | Char. Random | Sort | 0.014258 |
605+
| String_type | 4096 | String Decrease | Sort | 0.005542 |
606+
| String_type | 4096 | String Increase | Sort | 0.001987 |
607+
| String_type | 4096 | String Random | Sort | 0.003267 |
608+
| Integer | 65536 | Blocks | Sort_Index | 0.000686 |
609+
| Integer | 65536 | Decreasing | Sort_Index | 0.000529 |
610+
| Integer | 65536 | Identical | Sort_Index | 0.000218 |
611+
| Integer | 65536 | Increasing | Sort_Index | 0.000214 |
612+
| Integer | 65536 | Random dense | Sort_Index | 0.008044 |
613+
| Integer | 65536 | Random order | Sort_Index | 0.008042 |
614+
| Integer | 65536 | Random sparse | Sort_Index | 0.008148 |
615+
| Integer | 65536 | Random 3 | Sort_Index | 0.000677 |
616+
| Integer | 65536 | Random 10 | Sort_Index | 0.000387 |
617+
| Character | 65536 | Char. Decrease | Sort_Index | 0.000932 |
618+
| Character | 65536 | Char. Increase | Sort_Index | 0.000487 |
619+
| Character | 65536 | Char. Random | Sort_Index | 0.017231 |
620+
| String_type | 4096 | String Decrease | Sort_Index | 0.000489 |
621+
| String_type | 4096 | String Increase | Sort_Index | 0.000183 |
622+
| String_type | 4096 | String Random | Sort_Index | 0.004102 |
623+
624+
The second compiler is Intel(R) Fortran Intel(R) 64 Compiler Classic
625+
for applications running on Intel(R) 64, Version 2021.7.0 Build
626+
20220726_000000, with the following results:
554627

555628
| Type | Elements | Array Name | Method | Time (s) |
556629
|-------------|----------|-----------------|-------------|-----------|
557-
| Integer | 65536 | Blocks | Ord_Sort | 0.000267 |
558-
| Integer | 65536 | Decreasing | Ord_Sort | 0.000068 |
559-
| Integer | 65536 | Identical | Ord_Sort | 0.000056 |
560-
| Integer | 65536 | Increasing | Ord_Sort | 0.000056 |
561-
| Integer | 65536 | Random dense | Ord_Sort | 0.004615 |
562-
| Integer | 65536 | Random order | Ord_Sort | 0.006325 |
563-
| Integer | 65536 | Random sparse | Ord_Sort | 0.004601 |
564-
| Integer | 65536 | Random 3 | Ord_Sort | 0.000193 |
565-
| Integer | 65536 | Random 10 | Ord_Sort | 0.000101 |
566-
| Character | 65536 | Char. Decrease | Ord_Sort | 0.001009 |
567-
| Character | 65536 | Char. Increase | Ord_Sort | 0.000529 |
568-
| Character | 65536 | Char. Random | Ord_Sort | 0.024547 |
569-
| String_type | 4096 | String Decrease | Ord_Sort | 0.003381 |
570-
| String_type | 4096 | String Increase | Ord_Sort | 0.000133 |
571-
| String_type | 4096 | String Random | Ord_Sort | 0.051985 |
572-
| Integer | 65536 | Blocks | Sort | 0.001614 |
573-
| Integer | 65536 | Decreasing | Sort | 0.001783 |
574-
| Integer | 65536 | Identical | Sort | 0.002111 |
575-
| Integer | 65536 | Increasing | Sort | 0.000674 |
576-
| Integer | 65536 | Random dense | Sort | 0.003574 |
577-
| Integer | 65536 | Random order | Sort | 0.003296 |
578-
| Integer | 65536 | Random sparse | Sort | 0.003380 |
579-
| Integer | 65536 | Random 3 | Sort | 0.003623 |
580-
| Integer | 65536 | Random 10 | Sort | 0.006839 |
581-
| Character | 65536 | Char. Decrease | Sort | 0.032564 |
582-
| Character | 65536 | Char. Increase | Sort | 0.012346 |
583-
| Character | 65536 | Char. Random | Sort | 0.022932 |
584-
| String_type | 4096 | String Decrease | Sort | 0.082140 |
585-
| String_type | 4096 | String Increase | Sort | 0.029591 |
586-
| String_type | 4096 | String Random | Sort | 0.043078 |
587-
| Integer | 65536 | Blocks | Sort_Index | 0.000848 |
588-
| Integer | 65536 | Decreasing | Sort_Index | 0.000103 |
589-
| Integer | 65536 | Identical | Sort_Index | 0.000102 |
590-
| Integer | 65536 | Increasing | Sort_Index | 0.000066 |
591-
| Integer | 65536 | Random dense | Sort_Index | 0.006434 |
592-
| Integer | 65536 | Random order | Sort_Index | 0.005941 |
593-
| Integer | 65536 | Random sparse | Sort_Index | 0.005957 |
594-
| Integer | 65536 | Random 3 | Sort_Index | 0.000326 |
595-
| Integer | 65536 | Random 10 | Sort_Index | 0.000175 |
596-
| Character | 65536 | Char. Decrease | Sort_Index | 0.001082 |
597-
| Character | 65536 | Char. Increase | Sort_Index | 0.000468 |
598-
| Character | 65536 | Char. Random | Sort_Index | 0.023100 |
599-
| String_type | 4096 | String Decrease | Sort_Index | 0.003292 |
600-
| String_type | 4096 | String Increase | Sort_Index | 0.000122 |
601-
| String_type | 4096 | String Random | Sort_Index | 0.049155 |
602-
630+
| Integer | 65536 | Blocks | Ord_Sort | 0.000135 |
631+
| Integer | 65536 | Decreasing | Ord_Sort | 0.000053 |
632+
| Integer | 65536 | Identical | Ord_Sort | 0.000033 |
633+
| Integer | 65536 | Increasing | Ord_Sort | 0.000034 |
634+
| Integer | 65536 | Random dense | Ord_Sort | 0.003291 |
635+
| Integer | 65536 | Random order | Ord_Sort | 0.003546 |
636+
| Integer | 65536 | Random sparse | Ord_Sort | 0.003313 |
637+
| Integer | 65536 | Random 3 | Ord_Sort | 0.000145 |
638+
| Integer | 65536 | Random 10 | Ord_Sort | 0.000070 |
639+
| Character | 65536 | Char. Decrease | Ord_Sort | 0.000696 |
640+
| Character | 65536 | Char. Increase | Ord_Sort | 0.000338 |
641+
| Character | 65536 | Char. Random | Ord_Sort | 0.015255 |
642+
| String_type | 4096 | String Decrease | Ord_Sort | 0.001276 |
643+
| String_type | 4096 | String Increase | Ord_Sort | 0.000153 |
644+
| String_type | 4096 | String Random | Ord_Sort | 0.024705 |
645+
| Integer | 65536 | Blocks | Radix_Sort | 0.001038 |
646+
| Integer | 65536 | Decreasing | Radix_Sort | 0.000910 |
647+
| Integer | 65536 | Identical | Radix_Sort | 0.000441 |
648+
| Integer | 65536 | Increasing | Radix_Sort | 0.000803 |
649+
| Integer | 65536 | Random dense | Radix_Sort | 0.000363 |
650+
| Integer | 65536 | Random order | Radix_Sort | 0.000741 |
651+
| Integer | 65536 | Random sparse | Radix_Sort | 0.000384 |
652+
| Integer | 65536 | Random 3 | Radix_Sort | 0.000877 |
653+
| Integer | 65536 | Random 10 | Radix_Sort | 0.000801 |
654+
| Integer | 65536 | rand-real32 | Radix_Sort | 0.000604 |
655+
| Integer | 65536 | Blocks | Sort | 0.001342 |
656+
| Integer | 65536 | Decreasing | Sort | 0.001391 |
657+
| Integer | 65536 | Identical | Sort | 0.001485 |
658+
| Integer | 65536 | Increasing | Sort | 0.000447 |
659+
| Integer | 65536 | Random dense | Sort | 0.002778 |
660+
| Integer | 65536 | Random order | Sort | 0.002896 |
661+
| Integer | 65536 | Random sparse | Sort | 0.003136 |
662+
| Integer | 65536 | Random 3 | Sort | 0.002996 |
663+
| Integer | 65536 | Random 10 | Sort | 0.005752 |
664+
| Character | 65536 | Char. Decrease | Sort | 0.021973 |
665+
| Character | 65536 | Char. Increase | Sort | 0.008391 |
666+
| Character | 65536 | Char. Random | Sort | 0.015155 |
667+
| String_type | 4096 | String Decrease | Sort | 0.034014 |
668+
| String_type | 4096 | String Increase | Sort | 0.010464 |
669+
| String_type | 4096 | String Random | Sort | 0.015748 |
670+
| Integer | 65536 | Blocks | Sort_Index | 0.000381 |
671+
| Integer | 65536 | Decreasing | Sort_Index | 0.000085 |
672+
| Integer | 65536 | Identical | Sort_Index | 0.000046 |
673+
| Integer | 65536 | Increasing | Sort_Index | 0.000046 |
674+
| Integer | 65536 | Random dense | Sort_Index | 0.004020 |
675+
| Integer | 65536 | Random order | Sort_Index | 0.004059 |
676+
| Integer | 65536 | Random sparse | Sort_Index | 0.004073 |
677+
| Integer | 65536 | Random 3 | Sort_Index | 0.000215 |
678+
| Integer | 65536 | Random 10 | Sort_Index | 0.000101 |
679+
| Character | 65536 | Char. Decrease | Sort_Index | 0.000680 |
680+
| Character | 65536 | Char. Increase | Sort_Index | 0.000356 |
681+
| Character | 65536 | Char. Random | Sort_Index | 0.016231 |
682+
| String_type | 4096 | String Decrease | Sort_Index | 0.001219 |
683+
| String_type | 4096 | String Increase | Sort_Index | 0.000125 |
684+
| String_type | 4096 | String Random | Sort_Index | 0.018631 |

src/stdlib_sorting.fypp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ module stdlib_sorting
430430
!! The generic subroutine interface implementing the LSD radix sort algorithm,
431431
!! see https://en.wikipedia.org/wiki/Radix_sort for more details.
432432
!! It is always O(N) in sorting random data, but need a O(N) buffer.
433+
!! ([Specification](../page/specs/stdlib_sorting.html#radix_sort-sorts-an-input-array))
433434
!!
434435

435436
pure module subroutine int8_radix_sort(array, reverse)

test/sorting/test_sorting.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ module test_sorting
3838
string_rand(0:string_size-1)
3939

4040
integer(int32) :: dummy(0:test_size-1)
41-
real(sp) :: real_dummy(0:test_size-1)
41+
real(sp) :: real_dummy(0:test_size-1)
4242
character(len=4) :: char_dummy(0:char_size-1)
4343
type(string_type) :: string_dummy(0:string_size-1)
4444
integer(int_size) :: index(0:max(test_size, char_size, string_size)-1)

0 commit comments

Comments
 (0)