SURFEX v8.1
General documentation of Surfex
gnomesort.c
Go to the documentation of this file.
1 #include <stdio.h>
2 
3 /*
4  gnomesort.c : The easiest sort on Earth ? Yes, it is.
5 
6  This is how a Dutch Garden Gnome sorts a line of flower pots. Basically,
7  he looks at the flower pot next to him and the previous one;
8  if they are in the right order he steps one pot forward, otherwise
9  he swaps them and steps one pot backwards.
10  Boundary conditions: if there is no previous pot, he steps forwards;
11  if there is no pot next to him, he is done.
12 
13  See more Wikipedia & http://www.cs.vu.nl/~dick/gnomesort.html
14 
15  Author: Sami Saarinen, ECMWF, 12-Nov-2007
16 */
17 
18 /* Fortran callable: ecgnomesort_() */
19 
20 /*
21  Methods:
22 
23  0 : Unsigned 32-bit ints
24  1 : Signed 32-bit ints
25  2 : 64-bit doubles (IEEE) : signbit + 11-bit exp + 52-bits mantissa
26  3 : 32-bit floats (IEEE) : signbit + 8-bit exp + 23-bits mantissa
27  4 : Signed 64-bit ints
28  5 : Unsigned 64-bit ints
29 
30 */
31 
32 
33 typedef unsigned long long int Uint64;
34 typedef long long int Sint64;
35 typedef unsigned int Uint32;
36 typedef int Sint32;
37 
38 #define GnomeSort(T) \
39 static void GnomeSort_##T(T a[], const int n, const int inc) \
40 { \
41  int i = 0; \
42  if (inc == 1) { \
43  while (i < n) { \
44  if (i == 0 || a[i-1] <= a[i]) ++i; \
45  else {T tmp = a[i]; a[i] = a[i-1]; a[--i] = tmp;} \
46  } \
47  } else { \
48  while (i < n) { \
49  if (i == 0 || a[(i-1)*inc] <= a[i*inc]) ++i; \
50  else {T tmp = a[i*inc]; a[i*inc] = a[(i-1)*inc]; a[(--i)*inc] = tmp;} \
51  } \
52  } \
53 } \
54 static void GnomeSortIdx_##T(const T a[], const int n, const int inc, int index[], const int index_adj) \
55 { \
56  int i = 0; \
57  if (inc == 1) { \
58  if (index_adj) { \
59  while (i < n) { \
60  if (i == 0 || a[index[i-1]-index_adj] <= a[index[i]-index_adj]) ++i; \
61  else {int tmp = index[i]; index[i] = index[i-1]; index[--i] = tmp;} \
62  } \
63  } else { /* index_adj == 0 */ \
64  while (i < n) { \
65  if (i == 0 || a[index[i-1]] <= a[index[i]]) i++; \
66  else {int tmp = index[i]; index[i] = index[i-1]; index[--i] = tmp;} \
67  } \
68  } \
69  } else { /* inc != 1 */ \
70  if (index_adj) { \
71  while (i < n) { \
72  if (i == 0 || a[(index[i-1]-index_adj)*inc] <= a[(index[i]-index_adj)*inc]) ++i; \
73  else {int tmp = index[i]; index[i] = index[i-1]; index[--i] = tmp;} \
74  } \
75  } else { /* index_adj == 0 */ \
76  while (i < n) { \
77  if (i == 0 || a[index[i-1]*inc] <= a[index[i]*inc]) ++i; \
78  else {int tmp = index[i]; index[i] = index[i-1]; index[--i] = tmp;} \
79  } \
80  } \
81  } \
82 }
83 
84 #define DoSort(T) { \
85  T *data = Data; \
86  if (index && nidx >= n) { \
87  GnomeSortIdx_##T(&data[addr], n, inc, index, index_adj); \
88  } else { \
89  GnomeSort_##T(&data[addr], n, inc); \
90  } \
91 }
92 
93 #define SORT_UINT 0
95 
96 #define SORT_INT 1
98 
99 #define SORT_R64 2
100 GnomeSort(double)
101 
102 #define SORT_R32 3
103 GnomeSort(float)
104 
105 #define SORT_I64 4
107 
108 #define SORT_U64 5
110 
111 void
112 ecgnomesort_(const int *Mode,
113  const int *N,
114  const int *Inc,
115  const int *Start_addr,
116  void *Data,
117  int *index,
118  const int *Nindex,
119  const int *Index_adj,
120  int *retc)
121 {
122  int mode = *Mode;
123  int method = mode%10;
124  int n = *N;
125  int rc = n;
126  int inc = *Inc;
127  int nidx = *Nindex; /* Must be >= n or otherwise the index[] is disregarded */
128  int index_adj = *Index_adj;
129  int addr = (*Start_addr) - 1; /* Fortran to C */
130 
131  if (method != SORT_UINT &&
132  method != SORT_INT &&
133  method != SORT_R64 &&
134  method != SORT_R32 &&
135  method != SORT_I64 &&
136  method != SORT_U64 ) {
137  rc = -1;
138  goto finish;
139  }
140 
141  if (n <= 0) {
142  if (n < 0) rc = -2;
143  goto finish;
144  }
145 
146  if (inc < 1) {
147  rc = -3;
148  goto finish;
149  }
150 
151  switch (method) {
152  case SORT_UINT:
153  DoSort(Uint32);
154  break;
155  case SORT_INT:
156  DoSort(Sint32);
157  break;
158  case SORT_R64:
159  DoSort(double);
160  break;
161  case SORT_R32:
162  DoSort(float);
163  break;
164  case SORT_I64:
165  DoSort(Sint64);
166  break;
167  case SORT_U64:
168  DoSort(Uint64);
169  break;
170  }
171 
172  finish:
173 
174  *retc = rc;
175 }
int Sint32
Definition: gnomesort.c:36
ERROR in method
Definition: ecsort_shared.h:90
long long int Sint64
Definition: countingsort.c:42
unsigned long long int Uint64
Definition: countingsort.c:41
unsigned long long int Uint64
Definition: gnomesort.c:33
GnomeSort(Uint32)
Definition: gnomesort.c:94
long long int Sint64
Definition: gnomesort.c:34
integer(kind=kindofint) nidx
int Sint32
Definition: countingsort.c:44
ERROR in n
Definition: ecsort_shared.h:90
unsigned int Uint32
Definition: countingsort.c:43
unsigned int Uint32
Definition: gnomesort.c:35
ERROR in index
Definition: ecsort_shared.h:90