int c4_GroupByViewer::ScanTransitions(int lo_, int hi_, t4_byte *flags_, const
  c4_View &match_)const {
  d4_assert(lo_ > 0);

  int m = hi_ - lo_;
  d4_assert(m >= 0);

  // done if nothing left or if entire range is identical
  if (m == 0 || match_[lo_ - 1] == match_[hi_ - 1])
    return 0;

  // range has a transition, done if it is exactly of size one
  if (m == 1) {
    ++(flags_[lo_]);
    return 1;
  }

  // use binary splitting if the range has enough entries
  if (m >= 5)
    return ScanTransitions(lo_, lo_ + m / 2, flags_, match_) + ScanTransitions
      (lo_ + m / 2, hi_, flags_, match_);

  // else use a normal linear scan
  int n = 0;

  for (int i = lo_; i < hi_; ++i)
  if (match_[i] != match_[i - 1]) {
    ++(flags_[i]);
    ++n;
  }

  return n;
}
示例#2
0
文件: custom.cpp 项目: SASfit/SASfit
c4_GroupByViewer::c4_GroupByViewer (c4_Sequence& seq_, const c4_View& keys_,
                           const c4_Property& result_)
  : _parent (&seq_), _keys (keys_), _result (result_)
{
  _sorted = _parent.SortOn(_keys);
  int n = _sorted.GetSize();

  c4_Bytes temp;
  t4_byte* buf = temp.SetBufferClear(n);

  int groups = 0;
  if (n > 0)
  {
    ++buf[0]; // the first entry is always a transition
    groups = 1 + ScanTransitions(1, n, buf, _sorted.Project(_keys));
  }

    // set up a map pointing to each transition
  _map.SetSize(groups + 1);
  int j = 0;

  for (int i = 0; i < n; ++i)
    if (buf[i])
      _map.SetAt(j++, i);

    // also append an entry to point just past the end
  _map.SetAt(j, n);

  d4_assert(_map.GetAt(0) == 0);
  d4_assert(j == groups);
}