2 (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
3 See the copyright notice in the ACK home directory, in the file "Copyright".
7 IMPLEMENTATION MODULE ArraySort
;
9 Module: Array sorting module.
10 Author: Ceriel J.H. Jacobs
13 FROM SYSTEM
IMPORT ADDRESS
, BYTE
; (* no generics in Modula-2, sorry *)
15 TYPE BytePtr
= POINTER TO BYTE
;
17 VAR compareproc
: CompareProc
;
19 PROCEDURE Sort(base
: ADDRESS
; (* address of array *)
20 nel
: CARDINAL; (* number of elements in array *)
21 size
: CARDINAL; (* size of each element *)
22 compar
: CompareProc
); (* the comparison procedure *)
24 compareproc
:= compar
;
25 qsort(base
, base
+(nel
-1)*size
, size
);
28 PROCEDURE qsort(a1
, a2
: ADDRESS
; size
: CARDINAL);
29 (* Implemented with quick-sort, with some extra's *)
30 VAR left
, right
, lefteq
, righteq
: ADDRESS
;
37 lefteq
:= a1
+ size
* (((a2
- a1
) + size
) DIV (2 * size
));
40 Pick an element in the middle of the array.
41 We will collect the equals around it.
42 "lefteq" and "righteq" indicate the left and right
43 bounds of the equals respectively.
44 Smaller elements end up left of it, larger elements end
49 IF left
>= lefteq
THEN EXIT END;
50 cmp
:= compareproc(left
, lefteq
);
51 IF cmp
= greater
THEN EXIT END;
55 (* equal, so exchange with the element
56 to the left of the "equal"-interval.
58 lefteq
:= lefteq
- size
;
59 exchange(left
, lefteq
, size
);
64 IF right
<= righteq
THEN EXIT END;
65 cmp
:= compareproc(right
, righteq
);
68 (* larger one at the left,
71 exchange(left
,right
,size
);
73 right
:= right
- size
;
78 no more room at the left part, so we
79 move the "equal-interval" one place to the
80 right, and the smaller element to the
82 This is best expressed as a three-way
85 righteq
:= righteq
+ size
;
86 threewayexchange(left
, righteq
, right
,
88 lefteq
:= lefteq
+ size
;
90 ELSIF cmp
= equal
THEN
91 (* equal, zo exchange with the element
92 to the right of the "equal"
95 righteq
:= righteq
+ size
;
96 exchange(right
, righteq
, size
);
98 (* leave it where it is *)
99 right
:= right
- size
;
102 IF (NOT mainloop
) THEN
103 IF left
>= lefteq
THEN
104 (* sort "smaller" part *)
105 qsort(a1
, lefteq
- size
, size
);
106 (* and now the "larger" part, saving a
107 procedure call, because of this big
110 a1
:= righteq
+ size
;
111 EXIT; (* from the LOOP *)
113 (* larger element to the left, but no more room,
114 so move the "equal-interval" one place to the
115 left, and the larger element to the right
118 lefteq
:= lefteq
- size
;
119 threewayexchange(right
, lefteq
, left
, size
);
120 righteq
:= righteq
- size
;
127 PROCEDURE exchange(a
,b
: BytePtr
; size
: CARDINAL);
140 PROCEDURE threewayexchange(p
,q
,r
: BytePtr
; size
: CARDINAL);
153 END threewayexchange
;