source: trunk/src/STIdxIter.cpp @ 2913

Last change on this file since 2913 was 2913, checked in by Takeshi Nakazato, 10 years ago

New Development: No

JIRA Issue: No

Ready for Test: Yes

Interface Changes: Yes/No?

What Interface Changed: Please list interface changes

Test Programs: List test programs

Put in Release Notes: Yes/No?

Module(s): Module Names change impacts.

Description: Describe your changes here...

Inlude assert.h


File size: 16.4 KB
Line 
1#include <assert.h>
2#include <iostream>
3#include <casa/Utilities/GenSort.h>
4#include <casa/Arrays/Vector.h>
5#include <casa/Arrays/Matrix.h>
6#include <casa/Arrays/ArrayMath.h>
7#include <casa/Arrays/ArrayIO.h>
8#include <casa/Utilities/DataType.h>
9#include <tables/Tables/ScalarColumn.h>
10#include <tables/Tables/TableRow.h>
11#include <tables/Tables/TableRecord.h>
12#include "STIdxIter.h"
13
14namespace asap {
15
16IndexIterator::IndexIterator( IPosition &shape )
17  : niter_m( 0 )
18{
19  nfield_m = shape.nelements() ;
20  prod_m.resize( nfield_m ) ;
21  idx_m.resize( nfield_m ) ;
22  prod_m[nfield_m-1] = 1 ;
23  idx_m[nfield_m-1] = 0 ;
24  for ( Int i = nfield_m-2 ; i >= 0 ; i-- ) {
25    prod_m[i] = shape[i+1] * prod_m[i+1] ;
26    idx_m[i] = 0 ;
27  }
28  maxiter_m = prod_m[0] * shape[0] ;
29//   cout << "maxiter_m=" << maxiter_m << endl ;
30}
31
32Bool IndexIterator::pastEnd()
33{
34  return niter_m >= maxiter_m ;
35}
36
37void IndexIterator::next()
38{
39  niter_m++ ;
40  uInt x = niter_m ;
41  for ( Int i = 0 ; i < nfield_m ; i++ ) {
42    idx_m[i] = x / prod_m[i] ;
43    //cout << "i=" << i << ": prod=" << prod_m[i]
44    //     << ", idx=" << idx_m[i] << endl ;
45    x %= prod_m[i] ;
46  }
47}
48
49ArrayIndexIterator::ArrayIndexIterator( Matrix<uInt> &arr,
50                                        vector< vector<uInt> > idlist )
51  : arr_m( arr ),
52    pos_m( 1 )
53{
54  ncol_m = arr_m.ncolumn() ;
55  nrow_m = arr_m.nrow() ;
56  vector< vector<uInt> > l = idlist ;
57  if ( l.size() != ncol_m ) {
58    l.resize( ncol_m ) ;
59    for ( uInt i = 0 ; i < ncol_m ; i++ ) {
60      Vector<uInt> a( arr_m.column( i ).copy() ) ;
61      uInt n = genSort( a, Sort::Ascending, Sort::QuickSort|Sort::NoDuplicates ) ;
62      a.resize(n,True) ;
63      a.tovector( l[i] ) ;
64    }
65  }
66  idxlist_m = l ;
67  IPosition shape( ncol_m ) ;
68  for ( uInt i = 0 ; i < ncol_m ; i++ ) {
69    shape[i] = idxlist_m[i].size() ;
70  }
71//   cout << "shape=" << shape << endl ;
72  iter_m = new IndexIterator( shape ) ;
73  current_m.resize( ncol_m ) ;
74}
75
76ArrayIndexIterator::~ArrayIndexIterator()
77{
78  delete iter_m ;
79}
80
81Vector<uInt> ArrayIndexIterator::current()
82{
83  Block<uInt> idx = iter_m->current() ;
84  for ( uInt i = 0 ; i < ncol_m ; i++ )
85    current_m[i] = idxlist_m[i][idx[i]] ;
86  return current_m ;
87}
88
89Bool ArrayIndexIterator::pastEnd()
90{
91  return iter_m->pastEnd() ;
92}
93
94ArrayIndexIteratorNormal::ArrayIndexIteratorNormal( Matrix<uInt> &arr,
95                                                    vector< vector<uInt> > idlist )
96  : ArrayIndexIterator( arr, idlist )
97{
98  storage_m.resize( nrow_m ) ;
99}
100
101void ArrayIndexIteratorNormal::next()
102{
103  iter_m->next() ;
104}
105
106Vector<uInt> ArrayIndexIteratorNormal::getRows( StorageInitPolicy policy )
107{
108  Vector<uInt> v = current() ;
109  uInt len = 0 ;
110  uInt *p = storage_m.storage() ;
111  for ( uInt i = 0 ; i < nrow_m ; i++ ) {
112    if ( allEQ( v, arr_m.row( i ) ) ) {
113      *p = i ;
114      len++ ;
115      p++ ;
116    }
117  }
118  pos_m[0] = len ;
119  p = storage_m.storage() ;
120  return Vector<uInt>( pos_m, p, policy ) ;
121}
122
123ArrayIndexIteratorAcc::ArrayIndexIteratorAcc( Matrix<uInt> &arr,
124                                              vector< vector<uInt> > idlist )
125  : ArrayIndexIterator( arr, idlist )
126{
127  // storage_m layout
128  // length: ncol_m * (nrow_m + 1)
129  // 0~nrow_m-1: constant temporary storage that indicates whole rows
130  // nrow_m~2*nrow_m-1: temporary storage for column 0
131  // 2*nrow_m~3*nrow_m-1: temporary storage for column 1
132  // ...
133  storage_m.resize( arr_m.nelements()+nrow_m ) ;
134  // initialize constant temporary storage
135  uInt *p = storage_m.storage() ;
136  for ( uInt i = 0 ; i < nrow_m ; i++ ) {
137    *p = i ;
138    p++ ;
139  }
140  // len_m layout
141  // len[0]: length of temporary storage that incidates whole rows (constant)
142  // len[1]: number of matched row for column 0 selection
143  // len[2]: number of matched row for column 1 selection
144  // ...
145  len_m.resize( ncol_m+1 ) ;
146  p = len_m.storage() ;
147  for ( uInt i = 0 ; i < ncol_m+1 ; i++ ) {
148    *p = nrow_m ;
149    p++ ;
150//     cout << "len[" << i << "]=" << len_m[i] << endl ;
151  }
152  // skip_m layout
153  // skip_m[0]: True if column 0 is filled by unique value
154  // skip_m[1]: True if column 1 is filled by unique value
155  // ...
156  skip_m.resize( ncol_m ) ;
157  for ( uInt i = 0 ; i < ncol_m ; i++ ) {
158    skip_m[i] = (Bool)(idxlist_m[i].size()==1) ;
159//     cout << "skip_m[" << i << "]=" << skip_m[i] << endl ;
160  }
161  prev_m = iter_m->current() ;
162  p = prev_m.storage() ;
163  for ( uInt i = 0 ; i < ncol_m ; i++ ) {
164    *p = *p - 1 ;
165    p++ ;
166  }
167//   cout << "prev_m=" << Vector<uInt>(IPosition(1,ncol_m),prev_m.storage()) << endl ;
168}
169
170void ArrayIndexIteratorAcc::next()
171{
172  prev_m = iter_m->current() ;
173  iter_m->next() ;
174}
175
176Vector<uInt> ArrayIndexIteratorAcc::getRows( StorageInitPolicy policy )
177{
178  Block<uInt> v = iter_m->current() ;
179  Int c = isChanged( v ) ;
180//   cout << "v=" << Vector<uInt>(IPosition(1,v.nelements()),v.storage(),SHARE) << endl ;
181//   cout << "c=" << c << endl ;
182  if ( c > ncol_m-1 ) {
183    pos_m[0] = len_m[ncol_m] ;
184    Int offset = ncol_m - 1 ;
185    while( offset >= 0 && skip_m[offset] )
186      offset-- ;
187    offset++ ;
188//     cout << "offset=" << offset << endl ;
189    return Vector<uInt>( pos_m, storage_m.storage()+offset*nrow_m, policy ) ;
190  }
191  Int offset = c - 1 ;
192  while( offset >= 0 && skip_m[offset] )
193    offset-- ;
194  offset++ ;
195//   cout << "offset = " << offset << endl ;
196  uInt *base = storage_m.storage() + offset * nrow_m ;
197//   cout << "len_m[c+1]=" << len_m[c+1] << endl ;
198//   cout << "base=" << Vector<uInt>(IPosition(1,len_m[c+1]),base,SHARE) << endl ;
199  for ( Int i = c ; i < ncol_m ; i++ ) {
200    base = updateStorage( i, base, idxlist_m[i][v[i]] ) ;
201//     cout << "len_m[" << i << "]=" << len_m[i] << endl ;
202//     cout << "base=" << Vector<uInt>(IPosition(1,len_m[i]),base,SHARE) << endl ;
203  }
204  pos_m[0] = len_m[ncol_m] ;
205//   cout << "pos_m=" << pos_m << endl ;
206//   cout << "ret=" << Vector<uInt>( pos_m, base, policy ) << endl ;
207  return Vector<uInt>( pos_m, base, policy ) ;
208}
209
210Int ArrayIndexIteratorAcc::isChanged( Block<uInt> &idx )
211{
212  Int i = 0 ;
213  while( i < ncol_m && idx[i] == prev_m[i] )
214    i++ ;
215  return i ;
216}
217
218uInt *ArrayIndexIteratorAcc::updateStorage( Int &icol,
219                                            uInt *base,
220                                            uInt &v )
221{
222  // CAUTION:
223  // indexes for storage_m and len_m differ from index for skip_m by 1
224  // (skip_m[0] corresponds to storage_m[1] and len_m[1]) since there
225  // is additional temporary storage at first segment in storage_m
226  uInt *p ;
227  if ( skip_m[icol] ) {
228    // skip update, just update len_m[icol] and pass appropriate pointer
229//     cout << "skip " << icol << endl ;
230    p = base ;
231    len_m[icol+1] = len_m[icol] ;
232  }
233  else {
234//     cout << "update " << icol << endl ;
235    uInt len = 0 ;
236    p = storage_m.storage() + (icol+1) * nrow_m ;
237    uInt *work = p ;
238    Bool b ;
239    const uInt *arr_p = arr_m.getStorage( b ) ;
240    long offset = 0 ;
241    // warr_p points a first element of (icol)-th column
242    const uInt *warr_p = arr_p + icol * nrow_m ;
243    for ( uInt i = 0 ; i < len_m[icol] ; i++ ) {
244      // increment warr_p by (*(base)-*(base-1))
245      warr_p += *base - offset ;
246      // check if target element is equal to value specified
247      if ( *warr_p == v ) {
248        // then, add current index to storage_m
249        //       cout << "add " << *base << endl ;
250        *work = *base ;
251        len++ ;
252        work++ ;
253      }
254      // update offset
255      offset = *base ;
256      // next index
257      base++ ;
258    }
259    arr_m.freeStorage( arr_p, b ) ;
260    len_m[icol+1] = len ;
261  }
262  return p ;
263}
264
265STIdxIter::STIdxIter()
266{
267  iter_m = 0 ;
268}
269
270STIdxIter::STIdxIter( const string &name,
271                      const vector<string> &cols )
272{
273}
274
275STIdxIter::STIdxIter( const CountedPtr<Scantable> &s,
276                      const vector<string> &cols )
277{
278}
279
280STIdxIter::~STIdxIter()
281{
282  if ( iter_m != 0 )
283    delete iter_m ;
284}
285
286vector<uInt> STIdxIter::tovector( Vector<uInt> v )
287{
288  vector<uInt> ret ;
289  v.tovector( ret ) ;
290  return ret ;
291}
292
293Vector<uInt> STIdxIter::getRows( StorageInitPolicy policy )
294{
295  return iter_m->getRows( policy ) ;
296}
297
298STIdxIterNormal::STIdxIterNormal()
299  : STIdxIter()
300{
301}
302
303STIdxIterNormal::STIdxIterNormal( const string &name,
304                                  const vector<string> &cols )
305  : STIdxIter( name, cols )
306{
307  Table t( name, Table::Old ) ;
308  init( t, cols ) ;
309}
310
311STIdxIterNormal::STIdxIterNormal( const CountedPtr<Scantable> &s,
312                                  const vector<string> &cols )
313  : STIdxIter( s, cols )
314{
315  init( s->table(), cols ) ;
316}
317
318STIdxIterNormal::~STIdxIterNormal()
319{
320}
321
322void STIdxIterNormal::init( Table &t,
323                            const vector<string> &cols )
324{
325  uInt ncol = cols.size() ;
326  uInt nrow = t.nrow() ;
327  Matrix<uInt> arr( nrow, ncol ) ;
328  ROScalarColumn<uInt> col ;
329  Vector<uInt> v ;
330  for ( uInt i = 0 ; i < ncol ; i++ ) {
331    col.attach( t, cols[i] ) ;
332    v.reference( arr.column( i ) ) ;
333    col.getColumn( v ) ;
334  }
335  iter_m = new ArrayIndexIteratorNormal( arr ) ;
336}
337
338STIdxIterAcc::STIdxIterAcc()
339  : STIdxIter()
340{
341}
342
343STIdxIterAcc::STIdxIterAcc( const string &name,
344                            const vector<string> &cols )
345  : STIdxIter( name, cols )
346{
347  Table t( name, Table::Old ) ;
348  init( t, cols ) ;
349}
350
351STIdxIterAcc::STIdxIterAcc( const CountedPtr<Scantable> &s,
352                            const vector<string> &cols )
353  : STIdxIter( s, cols )
354{
355  init( s->table(), cols ) ;
356}
357
358STIdxIterAcc::~STIdxIterAcc()
359{
360}
361
362void STIdxIterAcc::init( Table &t,
363                         const vector<string> &cols )
364{
365  uInt ncol = cols.size() ;
366  uInt nrow = t.nrow() ;
367  // array shape here is as follows if cols=["BEAMNO","POLNO","IFNO"]:
368  // [[B0,B1,B2,...,BN],
369  //  [P0,P1,P2,...,PN],
370  //  [I0,I1,I2,...,IN]]
371  // order of internal storage is
372  // [B0,B1,B2,..,BN,P0,P1,P2,...,PN,I0,I1,I2,...,IN]
373  Matrix<uInt> arr( nrow, ncol ) ;
374  Vector<uInt> v ;
375  ROScalarColumn<uInt> col ;
376  for ( uInt i = 0 ; i < ncol ; i++ ) {
377    col.attach( t, cols[i] ) ;
378    v.reference( arr.column( i ) ) ;
379    col.getColumn( v ) ;
380  }
381  iter_m = new ArrayIndexIteratorAcc( arr ) ;
382}
383
384STIdxIterExAcc::STIdxIterExAcc()
385  : STIdxIter(),
386    srctypeid_m( -1 ),
387    srcnameid_m( -1 )
388{
389}
390
391STIdxIterExAcc::STIdxIterExAcc( const string &name,
392                                const vector<string> &cols )
393  : STIdxIter( name, cols ),
394    srctypeid_m( -1 ),
395    srcnameid_m( -1 )
396{
397  Table t( name, Table::Old ) ;
398  init( t, cols ) ;
399}
400
401STIdxIterExAcc::STIdxIterExAcc( const CountedPtr<Scantable> &s,
402                                const vector<string> &cols )
403  : STIdxIter( s, cols ),
404    srctypeid_m( -1 ),
405    srcnameid_m( -1 )
406{
407  init( s->table(), cols ) ;
408}
409
410STIdxIterExAcc::~STIdxIterExAcc()
411{
412}
413
414void STIdxIterExAcc::init( Table &t,
415                         const vector<string> &cols )
416{
417  uInt ncol = cols.size() ;
418  uInt nrow = t.nrow() ;
419  // array shape here is as follows if cols=["BEAMNO","POLNO","IFNO"]:
420  // [[B0,B1,B2,...,BN],
421  //  [P0,P1,P2,...,PN],
422  //  [I0,I1,I2,...,IN]]
423  // order of internal storage is
424  // [B0,B1,B2,..,BN,P0,P1,P2,...,PN,I0,I1,I2,...,IN]
425  Matrix<uInt> arr( nrow, ncol ) ;
426  Vector<uInt> v ;
427  ROScalarColumn<uInt> col ;
428  ROScalarColumn<String> strCol ;
429  ROScalarColumn<Int> intCol ;
430  for ( uInt i = 0 ; i < ncol ; i++ ) {
431    v.reference( arr.column( i ) ) ;
432    if ( cols[i] == "SRCTYPE" ) {
433      intCol.attach( t, cols[i] ) ;
434      Vector<Int> srctype = intCol.getColumn() ;
435      processIntCol( srctype, v, srctype_m ) ;
436      srctypeid_m = i ;
437    }
438    else if ( cols[i] == "SRCNAME" ) {
439      strCol.attach( t, cols[i] ) ;
440      Vector<String> srcname = strCol.getColumn() ;
441      processStrCol( srcname, v, srcname_m ) ;
442      srcnameid_m = i ;
443    }
444    else {
445      col.attach( t, cols[i] ) ;
446      col.getColumn( v ) ;
447    }
448  }
449  iter_m = new ArrayIndexIteratorAcc( arr ) ;
450}
451
452void STIdxIterExAcc::processIntCol( Vector<Int> &in,
453                                    Vector<uInt> &out,
454                                    Block<Int> &val )
455{
456  convertArray( out, in ) ;
457}
458
459void STIdxIterExAcc::processStrCol( Vector<String> &in,
460                                    Vector<uInt> &out,
461                                    Block<String> &val )
462{
463  uInt len = in.nelements() ;
464  Vector<String> tmp = in.copy() ;
465  uInt n = genSort( tmp, Sort::Ascending, Sort::QuickSort|Sort::NoDuplicates ) ;
466  val.resize( n ) ;
467  for ( uInt i = 0 ; i < n ; i++ ) {
468    val[i] = tmp[i] ;
469//     cout << "val[" << i << "]=" << val[i] << endl ;
470  }
471  if ( n == 1 ) {
472    //cout << "n=1" << endl ;
473    out = 0 ;
474  }
475  else if ( n == 2 ) {
476    //cout << "n=2" << endl ;
477    for ( uInt i = 0 ; i < len ; i++ ) {
478      out[i] = (in[i] == val[0]) ? 0 : 1 ;
479    }
480  }
481  else {
482    //cout << "n=" << n << endl ;
483    map<String,uInt> m ;
484    for ( uInt i = 0 ; i < n ; i++ )
485      m[val[i]] = i ;
486    for ( uInt i = 0 ; i < len ; i++ ) {
487      out[i] = m[in[i]] ;
488    }
489  }
490}
491
492Int STIdxIterExAcc::getSrcType()
493{
494  if ( srctypeid_m >= 0 )
495    return (Int)(iter_m->current()[srctypeid_m]) ;
496  else
497    return -999 ;
498}
499
500String STIdxIterExAcc::getSrcName()
501{
502  if ( srcname_m.nelements() > 0 )
503    return srcname_m[iter_m->current()[srcnameid_m]] ;
504  else
505    return "" ;
506}
507
508STIdxIter2::STIdxIter2()
509  : cols_(),
510    table_(),
511    counter_(0),
512    num_iter_(0),
513    num_row_(0),
514    sorter_(),
515    index_(),
516    unique_(),
517    pointer_()
518{
519}
520
521STIdxIter2::STIdxIter2( const string &name,
522                      const vector<string> &cols )
523  : cols_(cols),
524    table_(name, Table::Old),
525    counter_(0),
526    num_iter_(0),
527    num_row_(0),
528    sorter_(),
529    index_(),
530    unique_(),
531    pointer_()
532{
533  init();
534}
535
536STIdxIter2::STIdxIter2( const CountedPtr<Scantable> &s,
537                      const vector<string> &cols )
538  : cols_(cols),
539    table_(s->table()),
540    counter_(0),
541    num_iter_(0),
542    num_row_(0),
543    sorter_(),
544    index_(),
545    unique_(),
546    pointer_()
547{
548  init();
549}
550
551STIdxIter2::~STIdxIter2()
552{
553  deallocate();
554}
555
556void STIdxIter2::deallocate()
557{
558  for (vector<void*>::iterator i = pointer_.begin(); i != pointer_.end(); ++i) {
559    free(*i);
560  }
561}
562
563Record STIdxIter2::currentValue() {
564  assert(counter_ < num_iter_);
565  Vector<String> cols(cols_.size());
566  for (uInt i = 0; i < cols.nelements(); ++i) {
567    cols[i] = cols_[i];
568  }
569  const ROTableRow row(table_, cols);
570  const TableRecord rec = row.get(index_[unique_[counter_]]);
571  return Record(rec);
572}
573
574Bool STIdxIter2::pastEnd() {
575  return counter_ >= num_iter_;
576}
577
578void STIdxIter2::next() {
579  counter_++;
580}
581
582vector<uInt> STIdxIter2::tovector( Vector<uInt> v )
583{
584  vector<uInt> ret ;
585  v.tovector( ret ) ;
586  return ret ;
587}
588
589Vector<uInt> STIdxIter2::getRows( StorageInitPolicy policy )
590{
591  assert(num_iter_ > 1);
592  assert(counter_ < num_iter_);
593  if (counter_ == num_iter_ - 1) {
594    uInt start = unique_[counter_];
595    uInt num_row = num_row_ - start;
596    Vector<uInt> rows(IPosition(1, num_row), &(index_.data()[start]), policy);
597    return rows;
598  }
599  else {
600    uInt start = unique_[counter_];
601    uInt end = unique_[counter_ + 1];
602    uInt num_row = end - start;
603    Vector<uInt> rows(IPosition(1, num_row), &(index_.data()[start]), policy);
604    return rows;
605  }
606}
607
608void STIdxIter2::init()
609{
610  num_row_ = table_.nrow();
611  for (uInt i = 0; i < cols_.size(); ++i) {
612    addSortKey(cols_[i]);
613  }
614  sorter_.sort(index_, num_row_);
615  num_iter_ = sorter_.unique(unique_, index_);
616  // cout << "num_row_ = " << num_row_ << endl
617  //      << "num_iter_ = " << num_iter_ << endl;
618  // cout << "unique_ = " << unique_ << endl;
619  // cout << "index_ = " << index_ << endl;
620}
621
622void STIdxIter2::addSortKey(const string &name)
623{
624  const ColumnDesc &desc = table_.tableDesc().columnDesc(name);
625  const DataType dtype = desc.trueDataType();
626  switch (dtype) {
627  case TpUInt:
628    addColumnToKey<uInt, TpUInt>(name);
629    break;
630  case TpInt:
631    addColumnToKey<Int, TpInt>(name);
632    break;
633  case TpFloat:
634    addColumnToKey<Float, TpFloat>(name);
635    break;
636  case TpDouble:
637    addColumnToKey<Double, TpDouble>(name);
638    break;
639  case TpComplex:
640    addColumnToKey<Complex, TpComplex>(name);
641    break;
642  // case TpString:
643  //   addColumnToKey<String, TpString>(name);
644  //   break;
645  default:
646    deallocate();
647    stringstream oss;
648    oss << name << ": data type is not supported" << endl;
649    throw(AipsError(oss.str()));
650  }
651}
652
653template<class T, DataType U>
654void STIdxIter2::addColumnToKey(const string &name)
655{
656  void *raw_storage = malloc(sizeof(T) * num_row_);
657  T *storage = reinterpret_cast<T*>(raw_storage);
658  Vector<T> array(IPosition(1, num_row_), storage, SHARE);
659  ROScalarColumn<T> col(table_, name);
660  col.getColumn(array);
661  sorter_.sortKey(storage, U, 0, Sort::Ascending);
662  pointer_.push_back(raw_storage);
663}
664} // namespace
665
Note: See TracBrowser for help on using the repository browser.