1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
! From http://www-h.eng.cam.ac.uk/help/mjg17/f90/mergsort.f90
MODULE Sort

CONTAINS

RECURSIVE SUBROUTINE Module_merge_sort (a, ascend)

IMPLICIT NONE

INTEGER, DIMENSION(:), INTENT(INOUT) :: a
LOGICAL, INTENT(IN), OPTIONAL :: ascend
LOGICAL :: up

INTEGER low, high, mid

! If 'ascend' parameter is not specified, then default sort to ascending order
IF (PRESENT(ascend)) THEN
up = ascend
ELSE
up = .TRUE.
ENDIF

low=LBOUND(a,1)
high=UBOUND(a,1)

IF (low<high) THEN
mid=(low+high)/2
CALL Module_merge_sort(a(low:mid), up)
CALL Module_merge_sort(a(mid+1:high), up)
a(low:high) = Merge(a(low:mid), a(mid+1:high), up)
END IF

END SUBROUTINE Module_merge_sort


FUNCTION Merge (a, b, up)

INTEGER, DIMENSION(:), INTENT(INOUT) :: a, b
INTEGER, DIMENSION(SIZE(a)+SIZE(b)) :: Merge
LOGICAL, INTENT(IN) :: up

INTEGER a_ptr, a_high, a_low
INTEGER b_ptr, b_high, b_low
INTEGER c_ptr

LOGICAL condition

a_low=LBOUND(a,1)
a_high=UBOUND(a,1)
b_low=LBOUND(b,1)
b_high=UBOUND(b,1)

a_ptr=a_low
b_ptr=b_low
c_ptr=1

DO WHILE (a_ptr<=a_high .AND. b_ptr<=b_high)

IF (up) THEN
condition= (a(a_ptr) <= b(b_ptr))
ELSE
condition= (a(a_ptr) >= b(b_ptr))
END IF

IF (condition) THEN
Merge(c_ptr)=a(a_ptr)
a_ptr=a_ptr+1
ELSE
Merge(c_ptr)=b(b_ptr)
b_ptr=b_ptr+1
END IF

c_ptr = c_ptr + 1

END DO

IF (a_ptr>a_high) THEN
Merge(c_ptr:) = b(b_ptr:b_high)
ELSE
Merge(c_ptr:) = a(a_ptr:a_high)
END IF

END FUNCTION Merge

END MODULE Sort




PROGRAM Merge_sort

USE Sort
INTEGER, DIMENSION(:), ALLOCATABLE :: array
INTEGER i, n
REAL r, time

PRINT*, "Enter array size:"
READ(*,*) n

ALLOCATE( array(n) )

DO i=1, n
CALL RANDOM_NUMBER(r)
array(i)=100 * r
END DO

PRINT '(20I3)', array(1:20)
time = Second()
CALL Module_merge_sort(array)
PRINT '("[Sort time = ",F10.3," seconds ]")', Second() - time
PRINT '(20I3)', array(1:20)
time = Second()
CALL Module_merge_sort(array, .FALSE.)
PRINT '("[Sort time = ",F10.3," seconds ]")', Second() - time
PRINT '(20I3)', array(1:20)


CONTAINS

REAL FUNCTION Second()

IMPLICIT NONE

INTEGER i, timer_count_rate, timer_count_max

CALL SYSTEM_CLOCK( i, timer_count_rate, timer_count_max )
Second = REAL(i) / timer_count_rate

END FUNCTION Second


END PROGRAM Merge_sort