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.