source: branches/parallel/src/TableTraverse.cpp@ 2281

Last change on this file since 2281 was 2281, checked in by KohjiNakamura, 13 years ago

TableTraverse added

File size: 5.4 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <sys/time.h>
4#include <TableTraverse.h>
5
6#define TIMING 0
7
8using namespace casa;
9
10namespace asap {
11 class Comparator {
12 public:
13 virtual ~Comparator() {}
14 virtual int compare(const void *a, const void *b) = 0;
15 };
16
17 class CompContext: public Comparator {
18 uInt nCols;
19 void const *const *colValues;
20 const TypeManager *const* typeManagers;
21 public:
22 CompContext(uInt nCols, void const *const colValues[],
23 const TypeManager *const typeManagers[])
24 : nCols(nCols), colValues(colValues), typeManagers(typeManagers) {
25 DebugAssert(colValues != NULL, AipsError);
26 DebugAssert(typeManagers != NULL, AipsError);
27 for (uInt i = 0; i < nCols; i++) {
28 DebugAssert(colValues[i] != NULL, AipsError);
29 DebugAssert(typeManagers[i] != NULL, AipsError);
30 }
31 }
32
33 virtual int compare(const void *a, const void *b) {
34 uInt ai = *(uInt*)a;
35 uInt bi = *(uInt*)b;
36 for (size_t i = 0; i < nCols; i++) {
37 const size_t valueSize = typeManagers[i]->sizeOf();
38 const char *values = (const char *)colValues[i];
39 int diff = typeManagers[i]->getComparator()->comp(&values[ai*valueSize], &values[bi*valueSize]);
40 if (diff != 0) {
41 return diff;
42 }
43 }
44 return 0;
45 }
46 };
47}
48
49#if TIMING
50static double currenttime()
51{
52 struct timeval tv;
53 int result = gettimeofday(&tv, NULL);
54 return tv.tv_sec + ((double)tv.tv_usec) / 1000000.;
55}
56#endif
57
58static inline void swap_(char *a, char *b, size_t size)
59{
60 char tmp[size];
61 char *p = tmp;
62 do {
63 *p = *a;
64 *a++ = *b;
65 *b++ = *p++;
66 } while (--size > 0);
67}
68
69static inline void cpy(char *dest, char *src, size_t size)
70{
71 for (size_t i = 0; i < size; i++) {
72 dest[i] = src[i];
73 }
74}
75
76static void sort_(char *left, char *right, const size_t size,
77 asap::Comparator *comp, int level)
78{
79 const size_t len = (right - left) / size;
80 if (len < 2) {
81 return;
82 }
83 size_t mid = len >> 1;
84 char *l = left;
85 char *r = right - size;
86 char pivot[size] __attribute__ ((aligned (16)));
87 cpy(pivot, &left[mid*size], size);
88 while (true) {
89 while (l < r && comp->compare(l, pivot) < 0) {
90 l += size;
91 }
92 while (l < r && comp->compare(r, pivot) > 0) {
93 r -= size;
94 }
95 if (l >= r) {
96 break;
97 }
98 swap_(l, r, size);
99 l += size;
100 r -= size;
101 }
102 sort_(left, l, size, comp, level + 1);
103 sort_(l, right, size, comp, level + 1);
104}
105
106static inline void modernQSort(void *base, size_t elements, size_t size,
107 asap::Comparator *comp)
108{
109 sort_((char *)base, &((char *)base)[elements * size], size, comp, 0);
110}
111
112namespace asap {
113 class ROTableColumnBackDoor: public ROTableColumn {
114 public:
115 static BaseColumn *baseColumnPtr(const ROTableColumn *col)
116 {
117 return ((ROTableColumnBackDoor*)col)->baseColPtr();
118 }
119 };
120
121 void traverseTable(const Table &table,
122 const char *const columnNames[],
123 const TypeManager *const typeManagers[],
124 TableVisitor *visitor,
125 Bool doSort)
126 {
127#if TIMING
128 double s = currenttime();
129#endif
130 uInt colCount = 0;
131 for (; columnNames[colCount]; colCount++) {
132 AlwaysAssert(typeManagers[colCount], AipsError);
133 }
134
135 ROTableColumn *cols[colCount];
136 void *colValues[colCount];
137 for (uInt i = 0; i < colCount; i++) {
138 cols[i] = NULL;
139 colValues[i] = NULL;
140 }
141 size_t sizes[colCount];
142 const uInt nRows = table.nrow();
143 for (uInt i = 0; i < colCount; i++) {
144 cols[i] = new ROTableColumn(table, columnNames[i]);
145 colValues[i] = typeManagers[i]->allocArray(nRows);
146 sizes[i] = typeManagers[i]->sizeOf();
147 PlainColumn *col = dynamic_cast <PlainColumn *>(
148 ROTableColumnBackDoor::baseColumnPtr(cols[i]));
149 if (col) {
150 const uInt gotRows = col->dataManagerColumn()->
151 getBlockV(0, nRows, colValues[i]);
152 DebugAssert(gotRows == nRows, AipsError);
153 } else {
154 for (uInt i = 0; i < colCount; i++) {
155 typeManagers[i]->freeArray(colValues[i]);
156 delete cols[i];
157 }
158 throw AipsError("Invalid type of column specified." ) ;
159 }
160 }
161
162 uInt *idx = new uInt[nRows];
163 for (uInt i = 0; i < nRows; i++) {
164 idx[i] = i;
165 }
166
167 try {
168 if (doSort) {
169 CompContext compCtx(colCount, colValues, typeManagers);
170 modernQSort(idx, nRows, sizeof(idx[0]), &compCtx);
171 }
172
173 visitor->start();
174 Bool first = True;
175 for (uInt i = 0; i < nRows; i++) {
176 if (visitor->visit(first, idx[i], colCount, colValues) == False) {
177 break;
178 }
179 first = False;
180 }
181 visitor->finish();
182 } catch (...) {
183 delete[] idx;
184 for (uInt i = 0; i < colCount; i++) {
185 typeManagers[i]->freeArray(colValues[i]);
186 delete cols[i];
187 }
188 throw;
189 }
190
191 delete[] idx;
192 for (uInt i = 0; i < colCount; i++) {
193 typeManagers[i]->freeArray(colValues[i]);
194 delete cols[i];
195 }
196
197#if TIMING
198 double e = currenttime();
199 printf("%s took %.3f sec\n", __PRETTY_FUNCTION__, e - s);
200#endif
201 }
202}
203
204#if 0
205using namespace asap ;
206
207class MyComp: public Comparator {
208public:
209 virtual int compare(const void *a, const void *b) {
210 return (*(int*)a) - (*(int*)b);
211 }
212};
213
214int main()
215{
216 srand((int)currenttime());
217 int x[100];
218 printf("init\n");
219 for (int i = 0; i < 100; i++) {
220 x[i] = rand() % 100;
221 }
222 MyComp myComp;
223 printf("sorting\n");
224 modernQSort(x, 1, sizeof(x[0]), &myComp);
225 modernQSort(x, 2, sizeof(x[0]), &myComp);
226 modernQSort(x, 3, sizeof(x[0]), &myComp);
227 modernQSort(x, 100, sizeof(x[0]), &myComp);
228 for (int i = 0; i < 100; i++) {
229 printf("%d\n", x[i]);
230 }
231}
232#endif
Note: See TracBrowser for help on using the repository browser.