486b8fc81df31ce429ebcde4fd7712518930b96b
[riscv-tests.git] / benchmarks / qsort / qsort_main.c
1 //**************************************************************************
2 // Quicksort benchmark
3 //--------------------------------------------------------------------------
4 //
5 // This benchmark uses quicksort to sort an array of integers. The
6 // implementation is largely adapted from Numerical Recipes for C. The
7 // input data (and reference data) should be generated using the
8 // qsort_gendata.pl perl script and dumped to a file named
9 // dataset1.h The smips-gcc toolchain does not support system calls
10 // so printf's can only be used on a host system, not on the smips
11 // processor simulator itself. You should not change anything except
12 // the HOST_DEBUG and PREALLOCATE macros for your timing run.
13
14 //--------------------------------------------------------------------------
15 // Macros
16
17 // Set HOST_DEBUG to 1 if you are going to compile this for a host
18 // machine (ie Athena/Linux) for debug purposes and set HOST_DEBUG
19 // to 0 if you are compiling with the smips-gcc toolchain.
20
21 #ifndef HOST_DEBUG
22 #define HOST_DEBUG 0
23 #endif
24
25 // Set PREALLOCATE to 1 if you want to preallocate the benchmark
26 // function before starting stats. If you have instruction/data
27 // caches and you don't want to count the overhead of misses, then
28 // you will need to use preallocation.
29
30 #ifndef PREALLOCATE
31 #define PREALLOCATE 0
32 #endif
33
34 // Set SET_STATS to 1 if you want to carve out the piece that actually
35 // does the computation.
36
37 #ifndef SET_STATS
38 #define SET_STATS 0
39 #endif
40
41 // The INSERTION_THRESHOLD is the size of the subarray when the
42 // algorithm switches to using an insertion sort instead of
43 // quick sort.
44
45 #define INSERTION_THRESHOLD 7
46
47 // NSTACK is the required auxiliary storage.
48 // It must be at least 2*lg(DATA_SIZE)
49
50 #define NSTACK 50
51
52 // Swap macro for swapping two values.
53
54 #define SWAP(a,b) temp=(a);(a)=(b);(b)=temp;
55
56 //--------------------------------------------------------------------------
57 // Input/Reference Data
58
59 #include "dataset1.h"
60
61 //--------------------------------------------------------------------------
62 // Helper functions
63
64 int verify( int n, int test[], int correct[] )
65 {
66 int i;
67 for ( i = 0; i < n; i++ ) {
68 if ( test[i] != correct[i] ) {
69 return 2;
70 }
71 }
72 return 1;
73 }
74
75 #if HOST_DEBUG
76 void printArray( char name[], int n, int arr[] )
77 {
78 int i;
79 printf( " %10s :", name );
80 for ( i = 0; i < n; i++ )
81 printf( " %3d ", arr[i] );
82 printf( "\n" );
83 }
84 #endif
85
86 void finishTest( int toHostValue )
87 {
88 #if HOST_DEBUG
89 if ( toHostValue == 1 )
90 printf( "*** PASSED ***\n" );
91 else
92 printf( "*** FAILED *** (tohost = %d)\n", toHostValue );
93 exit(0);
94 #else
95 asm( "mtpcr %0, tohost" : : "r" (toHostValue) );
96 while ( 1 ) { }
97 #endif
98 }
99
100 void setStats( int enable )
101 {
102 #if ( !HOST_DEBUG && SET_STATS )
103 asm( "mtpcr %0, cr10" : : "r" (enable) );
104 #endif
105 }
106
107 //--------------------------------------------------------------------------
108 // Quicksort function
109
110 void sort( int n, int arr[] )
111 {
112 int i,j,k;
113 int ir = n;
114 int l = 1;
115 int jstack = 0;
116 int a, temp;
117
118 int istack[NSTACK];
119
120 for (;;) {
121
122 #if HOST_DEBUG
123 printArray( "", n, arr );
124 #endif
125
126 // Insertion sort when subarray small enough.
127 if ( ir-l < INSERTION_THRESHOLD ) {
128
129 for ( j = l+1; j <= ir; j++ ) {
130 a = arr[j-1];
131 for ( i = j-1; i >= l; i-- ) {
132 if ( arr[i-1] <= a ) break;
133 arr[i] = arr[i-1];
134 }
135 arr[i] = a;
136 }
137
138 if ( jstack == 0 ) break;
139
140 // Pop stack and begin a new round of partitioning.
141 ir = istack[jstack--];
142 l = istack[jstack--];
143
144 }
145 else {
146
147 // Choose median of left, center, and right elements as
148 // partitioning element a. Also rearrange so that a[l-1] <= a[l] <= a[ir-].
149
150 k = (l+ir) >> 1;
151 SWAP(arr[k-1],arr[l])
152 if ( arr[l-1] > arr[ir-1] ) {
153 SWAP(arr[l-1],arr[ir-1])
154 }
155 if ( arr[l] > arr[ir-1] ) {
156 SWAP(arr[l],arr[ir-1])
157 }
158 if ( arr[l-1] > arr[l] ) {
159 SWAP(arr[l-1],arr[l])
160 }
161
162 // Initialize pointers for partitioning.
163 i = l+1;
164 j = ir;
165
166 // Partitioning element.
167 a = arr[l];
168
169 for (;;) { // Beginning of innermost loop.
170 do i++; while (arr[i-1] < a); // Scan up to find element > a.
171 do j--; while (arr[j-1] > a); // Scan down to find element < a.
172 if (j < i) break; // Pointers crossed. Partitioning complete.
173 SWAP(arr[i-1],arr[j-1]); // Exchange elements.
174 } // End of innermost loop.
175
176 // Insert partitioning element.
177 arr[l] = arr[j-1];
178 arr[j-1] = a;
179 jstack += 2;
180
181 // Push pointers to larger subarray on stack,
182 // process smaller subarray immediately.
183
184 #if HOST_DEBUG
185 if ( jstack > NSTACK ) { printf("NSTACK too small in sort.\n"); exit(1); }
186 #endif
187
188 if ( ir-i+1 >= j-l ) {
189 istack[jstack] = ir;
190 istack[jstack-1] = i;
191 ir = j-1;
192 }
193 else {
194 istack[jstack] = j-1;
195 istack[jstack-1] = l;
196 l = i;
197 }
198 }
199
200 }
201
202 }
203
204 //--------------------------------------------------------------------------
205 // Main
206
207 int main( int argc, char* argv[] )
208 {
209
210 // Output the input array
211
212 #if HOST_DEBUG
213 printArray( "input", DATA_SIZE, input_data );
214 printArray( "verify", DATA_SIZE, verify_data );
215 #endif
216
217 // If needed we preallocate everything in the caches
218
219 #if PREALLOCATE
220 sort( DATA_SIZE, input_data );
221 #endif
222
223 // Do the sort
224
225 setStats(1);
226 sort( DATA_SIZE, input_data );
227 setStats(0);
228
229 // Print out the results
230
231 #if HOST_DEBUG
232 printArray( "test", DATA_SIZE, input_data );
233 #endif
234
235 // Check the results
236
237 finishTest(verify( DATA_SIZE, input_data, verify_data ));
238
239 }