annotate lib-src/qsort.c @ 934:c925bacdda60

[xemacs-hg @ 2002-07-29 09:21:12 by michaels] 2002-07-17 Marcus Crestani <crestani@informatik.uni-tuebingen.de> Markus Kaltenbach <makalten@informatik.uni-tuebingen.de> Mike Sperber <mike@xemacs.org> configure flag to turn these changes on: --use-kkcc First we added a dumpable flag to lrecord_implementation. It shows, if the object is dumpable and should be processed by the dumper. * lrecord.h (struct lrecord_implementation): added dumpable flag (MAKE_LRECORD_IMPLEMENTATION): fitted the different makro definitions to the new lrecord_implementation and their calls. Then we changed mark_object, that it no longer needs a mark method for those types that have pdump descritions. * alloc.c: (mark_object): If the object has a description, the new mark algorithm is called, and the object is marked according to its description. Otherwise it uses the mark method like before. These procedures mark objects according to their descriptions. They are modeled on the corresponding pdumper procedures. (mark_with_description): (get_indirect_count): (structure_size): (mark_struct_contents): These procedures still call mark_object, this is needed while there are Lisp_Objects without descriptions left. We added pdump descriptions for many Lisp_Objects: * extents.c: extent_auxiliary_description * database.c: database_description * gui.c: gui_item_description * scrollbar.c: scrollbar_instance_description * toolbar.c: toolbar_button_description * event-stream.c: command_builder_description * mule-charset.c: charset_description * device-msw.c: devmode_description * dialog-msw.c: mswindows_dialog_id_description * eldap.c: ldap_description * postgresql.c: pgconn_description pgresult_description * tooltalk.c: tooltalk_message_description tooltalk_pattern_description * ui-gtk.c: emacs_ffi_description emacs_gtk_object_description * events.c: * events.h: * event-stream.c: * event-Xt.c: * event-gtk.c: * event-tty.c: To write a pdump description for Lisp_Event, we converted every struct in the union event to a Lisp_Object. So we created nine new Lisp_Objects: Lisp_Key_Data, Lisp_Button_Data, Lisp_Motion_Data, Lisp_Process_Data, Lisp_Timeout_Data, Lisp_Eval_Data, Lisp_Misc_User_Data, Lisp_Magic_Data, Lisp_Magic_Eval_Data. We also wrote makro selectors and mutators for the fields of the new designed Lisp_Event and added everywhere these new abstractions. We implemented XD_UNION support in (mark_with_description), so we can describe exspecially console/device specific data with XD_UNION. To describe with XD_UNION, we added a field to these objects, which holds the variant type of the object. This field is initialized in the appendant constructor. The variant is an integer, it has also to be described in an description, if XD_UNION is used. XD_UNION is used in following descriptions: * console.c: console_description (get_console_variant): returns the variant (create_console): added variant initialization * console.h (console_variant): the different console types * console-impl.h (struct console): added enum console_variant contype * device.c: device_description (Fmake_device): added variant initialization * device-impl.h (struct device): added enum console_variant devtype * objects.c: image_instance_description font_instance_description (Fmake_color_instance): added variant initialization (Fmake_font_instance): added variant initialization * objects-impl.h (struct Lisp_Color_Instance): added color_instance_type * objects-impl.h (struct Lisp_Font_Instance): added font_instance_type * process.c: process_description (make_process_internal): added variant initialization * process.h (process_variant): the different process types
author michaels
date Mon, 29 Jul 2002 09:21:25 +0000
parents 576fb035e263
children 061f4f90f874
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
1 /* Plug-compatible replacement for UNIX qsort.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
2 Copyright (C) 1989 Free Software Foundation, Inc.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
3 Written by Douglas C. Schmidt (schmidt@ics.uci.edu)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
4
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
5 This file is part of GNU CC.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
6
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
7 GNU QSORT is free software; you can redistribute it and/or modify
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
8 it under the terms of the GNU General Public License as published by
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
9 the Free Software Foundation; either version 2, or (at your option)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
10 any later version.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
11
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
12 GNU QSORT is distributed in the hope that it will be useful,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
15 GNU General Public License for more details.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
16
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
18 along with GNU QSORT; see the file COPYING. If not, write to
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
19 the Free the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
20 Boston, MA 02111-1307, USA. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
21
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
22 /* Synched up with: FSF 19.28. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
23
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
24 #ifdef sparc
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
25 #include <alloca.h>
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
26 #endif
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
27
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
28 /* Invoke the comparison function, returns either 0, < 0, or > 0. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
29 #define CMP(A,B) ((*cmp)((A),(B)))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
30
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
31 /* Byte-wise swap two items of size SIZE. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
32 #define SWAP(A,B,SIZE) do {int sz = (SIZE); char *a = (A); char *b = (B); \
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
33 do { char _temp = *a;*a++ = *b;*b++ = _temp;} while (--sz);} while (0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
34
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
35 /* Copy SIZE bytes from item B to item A. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
36 #define COPY(A,B,SIZE) {int sz = (SIZE); do { *(A)++ = *(B)++; } while (--sz); }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
37
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
38 /* This should be replaced by a standard ANSI macro. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
39 #define BYTES_PER_WORD 8
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
40
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
41 /* The next 4 #defines implement a very fast in-line stack abstraction. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
42 #define STACK_SIZE (BYTES_PER_WORD * sizeof (long))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
43 #define PUSH(LOW,HIGH) do {top->lo = LOW;top++->hi = HIGH;} while (0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
44 #define POP(LOW,HIGH) do {LOW = (--top)->lo;HIGH = top->hi;} while (0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
45 #define STACK_NOT_EMPTY (stack < top)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
46
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
47 /* Discontinue quicksort algorithm when partition gets below this size.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
48 This particular magic number was chosen to work best on a Sun 4/260. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
49 #define MAX_THRESH 4
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
50
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
51 /* Stack node declarations used to store unfulfilled partition obligations. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
52 typedef struct
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
53 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
54 char *lo;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
55 char *hi;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
56 } stack_node;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
57
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
58 /* Order size using quicksort. This implementation incorporates
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
59 four optimizations discussed in Sedgewick:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
60
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
61 1. Non-recursive, using an explicit stack of pointer that store the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
62 next array partition to sort. To save time, this maximum amount
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
63 of space required to store an array of MAX_INT is allocated on the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
64 stack. Assuming a 32-bit integer, this needs only 32 *
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
65 sizeof (stack_node) == 136 bits. Pretty cheap, actually.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
66
444
576fb035e263 Import from CVS: tag r21-2-37
cvs
parents: 0
diff changeset
67 2. Choose the pivot element using a median-of-three decision tree.
0
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
68 This reduces the probability of selecting a bad pivot value and
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
69 eliminates certain extraneous comparisons.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
70
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
71 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
72 insertion sort to order the MAX_THRESH items within each partition.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
73 This is a big win, since insertion sort is faster for small, mostly
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
74 sorted array segments.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
75
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
76 4. The larger of the two sub-partitions is always pushed onto the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
77 stack first, with the algorithm then concentrating on the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
78 smaller partition. This *guarantees* no more than log (n)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
79 stack size is needed (actually O(1) in this case)! */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
80
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
81 int
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
82 qsort (base_ptr, total_elems, size, cmp)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
83 char *base_ptr;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
84 int total_elems;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
85 int size;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
86 int (*cmp)();
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
87 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
88 /* Allocating SIZE bytes for a pivot buffer facilitates a better
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
89 algorithm below since we can do comparisons directly on the pivot. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
90 char *pivot_buffer = (char *) alloca (size);
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
91 int max_thresh = MAX_THRESH * size;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
92
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
93 if (total_elems > MAX_THRESH)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
94 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
95 char *lo = base_ptr;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
96 char *hi = lo + size * (total_elems - 1);
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
97 stack_node stack[STACK_SIZE]; /* Largest size needed for 32-bit int!!! */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
98 stack_node *top = stack + 1;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
99
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
100 while (STACK_NOT_EMPTY)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
101 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
102 char *left_ptr;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
103 char *right_ptr;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
104 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
105 char *pivot = pivot_buffer;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
106 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
107 /* Select median value from among LO, MID, and HI. Rearrange
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
108 LO and HI so the three values are sorted. This lowers the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
109 probability of picking a pathological pivot value and
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
110 skips a comparison for both the LEFT_PTR and RIGHT_PTR. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
111
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
112 char *mid = lo + size * ((hi - lo) / size >> 1);
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
113
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
114 if (CMP (mid, lo) < 0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
115 SWAP (mid, lo, size);
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
116 if (CMP (hi, mid) < 0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
117 SWAP (mid, hi, size);
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
118 else
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
119 goto jump_over;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
120 if (CMP (mid, lo) < 0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
121 SWAP (mid, lo, size);
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
122 jump_over:
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
123 COPY (pivot, mid, size);
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
124 pivot = pivot_buffer;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
125 }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
126 left_ptr = lo + size;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
127 right_ptr = hi - size;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
128
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
129 /* Here's the famous ``collapse the walls'' section of quicksort.
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
130 Gotta like those tight inner loops! They are the main reason
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
131 that this algorithm runs much faster than others. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
132 do
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
133 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
134 while (CMP (left_ptr, pivot) < 0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
135 left_ptr += size;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
136
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
137 while (CMP (pivot, right_ptr) < 0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
138 right_ptr -= size;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
139
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
140 if (left_ptr < right_ptr)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
141 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
142 SWAP (left_ptr, right_ptr, size);
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
143 left_ptr += size;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
144 right_ptr -= size;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
145 }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
146 else if (left_ptr == right_ptr)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
147 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
148 left_ptr += size;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
149 right_ptr -= size;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
150 break;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
151 }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
152 }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
153 while (left_ptr <= right_ptr);
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
154
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
155 }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
156
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
157 /* Set up pointers for next iteration. First determine whether
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
158 left and right partitions are below the threshold size. If so,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
159 ignore one or both. Otherwise, push the larger partition's
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
160 bounds on the stack and continue sorting the smaller one. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
161
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
162 if ((right_ptr - lo) <= max_thresh)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
163 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
164 if ((hi - left_ptr) <= max_thresh) /* Ignore both small partitions. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
165 POP (lo, hi);
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
166 else /* Ignore small left partition. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
167 lo = left_ptr;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
168 }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
169 else if ((hi - left_ptr) <= max_thresh) /* Ignore small right partition. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
170 hi = right_ptr;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
171 else if ((right_ptr - lo) > (hi - left_ptr)) /* Push larger left partition indices. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
172 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
173 PUSH (lo, right_ptr);
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
174 lo = left_ptr;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
175 }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
176 else /* Push larger right partition indices. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
177 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
178 PUSH (left_ptr, hi);
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
179 hi = right_ptr;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
180 }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
181 }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
182 }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
183
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
184 /* Once the BASE_PTR array is partially sorted by quicksort the rest
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
185 is completely sorted using insertion sort, since this is efficient
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
186 for partitions below MAX_THRESH size. BASE_PTR points to the beginning
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
187 of the array to sort, and END_PTR points at the very last element in
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
188 the array (*not* one beyond it!). */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
189
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
190 #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
191
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
192 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
193 char *end_ptr = base_ptr + size * (total_elems - 1);
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
194 char *run_ptr;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
195 char *tmp_ptr = base_ptr;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
196 char *thresh = MIN (end_ptr, base_ptr + max_thresh);
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
197
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
198 /* Find smallest element in first threshold and place it at the
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
199 array's beginning. This is the smallest array element,
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
200 and the operation speeds up insertion sort's inner loop. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
201
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
202 for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
203 if (CMP (run_ptr, tmp_ptr) < 0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
204 tmp_ptr = run_ptr;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
205
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
206 if (tmp_ptr != base_ptr)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
207 SWAP (tmp_ptr, base_ptr, size);
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
208
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
209 /* Insertion sort, running from left-hand-side up to `right-hand-side.'
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
210 Pretty much straight out of the original GNU qsort routine. */
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
211
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
212 for (run_ptr = base_ptr + size; (tmp_ptr = run_ptr += size) <= end_ptr; )
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
213 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
214
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
215 while (CMP (run_ptr, tmp_ptr -= size) < 0)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
216 ;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
217
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
218 if ((tmp_ptr += size) != run_ptr)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
219 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
220 char *trav;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
221
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
222 for (trav = run_ptr + size; --trav >= run_ptr;)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
223 {
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
224 char c = *trav;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
225 char *hi, *lo;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
226
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
227 for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
228 *hi = *lo;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
229 *hi = c;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
230 }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
231 }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
232
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
233 }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
234 }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
235 return 1;
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
236 }
376386a54a3c Import from CVS: tag r19-14
cvs
parents:
diff changeset
237