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

Last change on this file since 2284 was 2284, checked in by KohjiNakamura, 13 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.