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

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