[Groonga-commit] groonga/grnxx at 544c88b [master] Add BitwiseCompletionCursor for DoubleArray<GeoPoint>.

Back to archive index

susumu.yata null+****@clear*****
Fri Apr 19 12:58:54 JST 2013


susumu.yata	2013-04-19 12:58:54 +0900 (Fri, 19 Apr 2013)

  New Revision: 544c88b7d355b3d440e505d635004fd1a8fbcf28
  https://github.com/groonga/grnxx/commit/544c88b7d355b3d440e505d635004fd1a8fbcf28

  Message:
    Add BitwiseCompletionCursor for DoubleArray<GeoPoint>.

  Modified files:
    lib/grnxx/alpha/map/double_array-slice.cpp
    lib/grnxx/alpha/map/double_array.cpp
    lib/grnxx/alpha/map/double_array.hpp

  Modified: lib/grnxx/alpha/map/double_array-slice.cpp (+3 -3)
===================================================================
--- lib/grnxx/alpha/map/double_array-slice.cpp    2013-04-18 18:35:35 +0900 (8edcc65)
+++ lib/grnxx/alpha/map/double_array-slice.cpp    2013-04-19 12:58:54 +0900 (89a73b1)
@@ -559,7 +559,7 @@ void DoubleArrayIDCursor<Slice>::init_order_by_key(int64_t min, int64_t max) {
 }
 
 template <>
-class DoubleArrayKeyCursor<Slice> : public MapCursor<Slice>{
+class DoubleArrayKeyCursor<Slice> : public MapCursor<Slice> {
  public:
   DoubleArrayKeyCursor(DoubleArray<Slice> *double_array,
                        Slice min, Slice max,
@@ -872,7 +872,7 @@ bool DoubleArrayKeyCursor<Slice>::next_reverse_order_by_key() {
 }
 
 template <>
-class DoubleArrayPrefixCursor<Slice> : public MapCursor<Slice>{
+class DoubleArrayPrefixCursor<Slice> : public MapCursor<Slice> {
  public:
   DoubleArrayPrefixCursor(DoubleArray<Slice> *double_array,
                           Slice query, size_t min_size,
@@ -996,7 +996,7 @@ void DoubleArrayPrefixCursor<Slice>::init_order_by_key(
 }
 
 template <>
-class DoubleArrayCompletionCursor<Slice> : public MapCursor<Slice>{
+class DoubleArrayCompletionCursor<Slice> : public MapCursor<Slice> {
  public:
   DoubleArrayCompletionCursor(DoubleArray<Slice> *double_array,
                               Slice query,

  Modified: lib/grnxx/alpha/map/double_array.cpp (+240 -2)
===================================================================
--- lib/grnxx/alpha/map/double_array.cpp    2013-04-18 18:35:35 +0900 (2750357)
+++ lib/grnxx/alpha/map/double_array.cpp    2013-04-19 12:58:54 +0900 (cd9de63)
@@ -507,6 +507,7 @@ class DoubleArrayIDCursor : public MapCursor<T> {
   void init_order_by_key(int64_t min, int64_t max);
 };
 
+constexpr uint64_t IS_ROOT_FLAG    = uint64_t(1) << 62;
 constexpr uint64_t POST_ORDER_FLAG = uint64_t(1) << 63;
 
 template <typename T>
@@ -626,7 +627,7 @@ void DoubleArrayIDCursor<GeoPoint>::init_order_by_key(int64_t, int64_t) {
 }
 
 template <typename T>
-class DoubleArrayKeyCursor : public MapCursor<T>{
+class DoubleArrayKeyCursor : public MapCursor<T> {
  public:
   DoubleArrayKeyCursor(DoubleArray<T> *double_array, T min, T max,
                        const MapCursorOptions &options);
@@ -922,6 +923,230 @@ bool DoubleArrayKeyCursor<T>::next_reverse_order_by_key() {
   return false;
 }
 
+class DoubleArrayBitwiseCompletionCursor : public MapCursor<GeoPoint> {
+ public:
+  DoubleArrayBitwiseCompletionCursor(DoubleArray<GeoPoint> *double_array,
+                                     GeoPoint query, size_t bit_size,
+                                     const MapCursorOptions &options);
+  ~DoubleArrayBitwiseCompletionCursor();
+
+  bool next();
+  bool remove();
+
+ private:
+  DoubleArray<GeoPoint> *double_array_;
+  uint64_t cur_;
+  uint64_t count_;
+  GeoPoint query_;
+  size_t bit_size_;
+  uint64_t mask_;
+  MapCursorOptions options_;
+  std::vector<uint64_t> node_ids_;
+  std::vector<std::pair<int64_t, GeoPoint>> keys_;
+
+  void init_order_by_id();
+  void init_order_by_key();
+
+  bool next_order_by_id();
+  bool next_order_by_key();
+  bool next_reverse_order_by_key();
+};
+
+DoubleArrayBitwiseCompletionCursor::DoubleArrayBitwiseCompletionCursor(
+    DoubleArray<GeoPoint> *double_array, GeoPoint query, size_t bit_size,
+    const MapCursorOptions &options)
+  : MapCursor<GeoPoint>(), double_array_(double_array), cur_(), count_(0),
+    query_(query), bit_size_(bit_size), mask_(), options_(options),
+    node_ids_(), keys_() {
+  if ((~options_.flags & MAP_CURSOR_ORDER_BY_ID) ||
+      (options_.flags & MAP_CURSOR_ORDER_BY_KEY)) {
+    init_order_by_id();
+  } else {
+    init_order_by_key();
+  }
+}
+
+DoubleArrayBitwiseCompletionCursor::~DoubleArrayBitwiseCompletionCursor() {}
+
+bool DoubleArrayBitwiseCompletionCursor::next() {
+  if (count_ >= options_.limit) {
+    return false;
+  }
+  if ((options_.flags & MAP_CURSOR_ORDER_BY_ID) &&
+      (~options_.flags & MAP_CURSOR_ORDER_BY_KEY)) {
+    return next_order_by_id();
+  } else if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
+    return next_order_by_key();
+  } else {
+    return next_reverse_order_by_key();
+  }
+}
+
+bool DoubleArrayBitwiseCompletionCursor::remove() {
+  return double_array_->unset(this->key_id_);
+}
+
+void DoubleArrayBitwiseCompletionCursor::init_order_by_id() {
+  init_order_by_key();
+
+  while (!node_ids_.empty()) {
+    const bool is_root = node_ids_.back() & IS_ROOT_FLAG;
+    const uint64_t node_id = node_ids_.back() & ~IS_ROOT_FLAG;
+    node_ids_.pop_back();
+
+    const DoubleArrayNodeForOthers node = double_array_->nodes_[node_id];
+    if (!is_root && (node.sibling() != INVALID_LABEL)) {
+      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
+    }
+
+    if (node.is_leaf()) {
+      const GeoPoint key = double_array_->keys_[node.key_id()];
+      if (((key.value() ^ query_.value()) & mask_) != 0) {
+        keys_.push_back(std::make_pair(node.key_id(), key));
+      }
+    } else if (node.child() != INVALID_LABEL) {
+      node_ids_.push_back(node.offset() ^ node.child());
+    }
+  }
+
+  std::sort(keys_.begin(), keys_.end(),
+            [](const std::pair<int64_t, GeoPoint> &lhs,
+               const std::pair<int64_t, GeoPoint> &rhs) {
+              return lhs.first < rhs.first;
+            });
+  if (options_.flags & MAP_CURSOR_REVERSE_ORDER) {
+    std::reverse(keys_.begin(), keys_.end());
+  }
+  cur_ = options_.offset;
+}
+
+void DoubleArrayBitwiseCompletionCursor::init_order_by_key() {
+  if (bit_size_ >= 64) {
+    bit_size_ = 64;
+  }
+  switch (bit_size_) {
+    case 0: {
+      mask_ = 0;
+      break;
+    }
+    case 1: {
+      mask_ = GeoPoint(1 << 31, 0).value();
+      break;
+    }
+    default: {
+      mask_ = GeoPoint(0xFFFFFFFFU << (32 - (bit_size_ / 2) - (bit_size_ % 2)),
+                       0xFFFFFFFFU << (32 - (bit_size_ / 2))).value();
+      break;
+    }
+  }
+
+  // Note: MAP_CURSOR_EXCEPT_QUERY does not make sense.
+
+  uint8_t query_buf[sizeof(GeoPoint)];
+  convert_key(query_, query_buf);
+
+  size_t min_size = bit_size_ / 8;
+
+  uint64_t node_id = ROOT_NODE_ID;
+  for (size_t i = 0; i < min_size; ++i) {
+    const DoubleArrayNodeForOthers node = double_array_->nodes_[node_id];
+    if (node.is_leaf()) {
+      const GeoPoint key = double_array_->keys_[node.key_id()];
+      if (((key.value() ^ query_.value()) ^ mask_) != 0) {
+        if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
+          node_id |= IS_ROOT_FLAG;
+        }
+        node_ids_.push_back(node_id);
+      }
+      return;
+    }
+
+    node_id = node.offset() ^ query_buf[i];
+    if (double_array_->nodes_[node_id].label() != query_buf[i]) {
+      return;
+    }
+  }
+
+  if (~options_.flags & MAP_CURSOR_REVERSE_ORDER) {
+    node_id |= IS_ROOT_FLAG;
+  }
+  node_ids_.push_back(node_id);
+}
+
+bool DoubleArrayBitwiseCompletionCursor::next_order_by_id() {
+  if (cur_ < keys_.size()) {
+    this->key_id_ = keys_[cur_].first;
+    this->key_ = keys_[cur_].second;
+    ++cur_;
+    ++count_;
+    return true;
+  }
+  return false;
+}
+
+bool DoubleArrayBitwiseCompletionCursor::next_order_by_key() {
+  while (!node_ids_.empty()) {
+    const bool is_root = node_ids_.back() & IS_ROOT_FLAG;
+    const uint64_t node_id = node_ids_.back() & ~IS_ROOT_FLAG;
+    node_ids_.pop_back();
+
+    const DoubleArrayNodeForOthers node = double_array_->nodes_[node_id];
+    if (!is_root && (node.sibling() != INVALID_LABEL)) {
+      node_ids_.push_back(node_id ^ node.label() ^ node.sibling());
+    }
+
+    if (node.is_leaf()) {
+      const GeoPoint key = double_array_->keys_[node.key_id()];
+      if (((key.value() ^ query_.value()) ^ mask_) != 0) {
+        if (options_.offset > 0) {
+          --options_.offset;
+        } else {
+          this->key_id_ = node.key_id();
+          this->key_ = key;
+          ++count_;
+          return true;
+        }
+      }
+    } else if (node.child() != INVALID_LABEL) {
+      node_ids_.push_back(node.offset() ^ node.child());
+    }
+  }
+  return false;
+}
+
+bool DoubleArrayBitwiseCompletionCursor::next_reverse_order_by_key() {
+  while (!node_ids_.empty()) {
+    const bool post_order = node_ids_.back() & POST_ORDER_FLAG;
+    const uint64_t node_id = node_ids_.back() & ~POST_ORDER_FLAG;
+
+    const DoubleArrayNodeForOthers node = double_array_->nodes_[node_id];
+    if (post_order) {
+      node_ids_.pop_back();
+      if (node.is_leaf()) {
+        const GeoPoint key = double_array_->keys_[node.key_id()];
+        if (((key.value() ^ query_.value()) ^ mask_) != 0) {
+          if (options_.offset > 0) {
+            --options_.offset;
+          } else {
+            this->key_id_ = node.key_id();
+            this->key_ = key;
+            ++count_;
+            return true;
+          }
+        }
+      }
+    } else {
+      node_ids_.back() |= POST_ORDER_FLAG;
+      uint16_t label = double_array_->nodes_[node_id].child();
+      while (label != INVALID_LABEL) {
+        node_ids_.push_back(node.offset() ^ label);
+        label = double_array_->nodes_[node.offset() ^ label].sibling();
+      }
+    }
+  }
+  return false;
+}
+
 template <typename T>
 DoubleArray<T>::~DoubleArray() {
   if (!initialized_) try {
@@ -1096,7 +1321,6 @@ bool DoubleArray<T>::find(T key, int64_t *key_id) {
     return false;
   }
 
-  // TODO: NaN.
   const int32_t found_key_id = node.key_id();
   if (Helper<T>::equal_to(keys_[found_key_id], key)) {
     if (key_id) {
@@ -1223,6 +1447,20 @@ MapCursor<GeoPoint> *DoubleArray<GeoPoint>::open_key_cursor(
 }
 
 template <typename T>
+MapCursor<T> *DoubleArray<T>::open_bitwise_completion_cursor(
+    T, size_t, const MapCursorOptions &) {
+  // Not supported.
+  return nullptr;
+}
+
+template <>
+MapCursor<GeoPoint> *DoubleArray<GeoPoint>::open_bitwise_completion_cursor(
+    GeoPoint query, size_t bit_size, const MapCursorOptions &options) {
+  return new (std::nothrow) DoubleArrayBitwiseCompletionCursor(
+      this, query, bit_size, options);
+}
+
+template <typename T>
 DoubleArray<T>::DoubleArray()
   : pool_(),
     block_info_(nullptr),

  Modified: lib/grnxx/alpha/map/double_array.hpp (+5 -4)
===================================================================
--- lib/grnxx/alpha/map/double_array.hpp    2013-04-18 18:35:35 +0900 (0f7448e)
+++ lib/grnxx/alpha/map/double_array.hpp    2013-04-19 12:58:54 +0900 (390011b)
@@ -29,6 +29,7 @@ template <typename T> class DoubleArrayIDCursor;
 template <typename T> class DoubleArrayKeyCursor;
 template <typename T> class DoubleArrayPrefixCursor;
 template <typename T> class DoubleArrayCompletionCursor;
+class DoubleArrayBitwiseCompletionCursor;
 
 // Forward declarations.
 struct DoubleArrayHeaderForOthers;
@@ -62,6 +63,7 @@ template <typename T>
 class DoubleArray : public Map<T> {
   friend class DoubleArrayIDCursor<T>;
   friend class DoubleArrayKeyCursor<T>;
+  friend class DoubleArrayBitwiseCompletionCursor;
 
  public:
   typedef DoubleArrayHeaderForOthers DoubleArrayHeader;
@@ -104,10 +106,9 @@ class DoubleArray : public Map<T> {
   MapCursor<T> *open_key_cursor(T min, T max,
       const MapCursorOptions &options = MapCursorOptions());
 
-  // TODO
-//  MapCursor<T> *open_bitwise_completion_cursor(
-//      T query, size_t bit_size,
-//      const MapCursorOptions &options = MapCursorOptions());
+  MapCursor<T> *open_bitwise_completion_cursor(
+      T query, size_t bit_size,
+      const MapCursorOptions &options = MapCursorOptions());
 
  private:
   io::Pool pool_;
-------------- next part --------------
HTML����������������������������...
Download 



More information about the Groonga-commit mailing list
Back to archive index