[Groonga-commit] groonga/grnxx at 75f38e3 [master] Add Lhs/RhsMerger. (#66)

Back to archive index

susumu.yata null+****@clear*****
Wed Sep 24 11:05:37 JST 2014


susumu.yata	2014-09-24 11:05:37 +0900 (Wed, 24 Sep 2014)

  New Revision: 75f38e3800db21b8ef36cb6d686d636601ebbadb
  https://github.com/groonga/grnxx/commit/75f38e3800db21b8ef36cb6d686d636601ebbadb

  Message:
    Add Lhs/RhsMerger. (#66)

  Modified files:
    lib/grnxx/merger.cpp

  Modified: lib/grnxx/merger.cpp (+279 -5)
===================================================================
--- lib/grnxx/merger.cpp    2014-09-24 10:43:39 +0900 (bbb18ff)
+++ lib/grnxx/merger.cpp    2014-09-24 11:05:37 +0900 (e24e3e4)
@@ -468,11 +468,284 @@ bool MinusMerger::finish(Error *error) {
 
 // -- LhsMerger --
 
-// TODO
+class LhsMerger : public Merger {
+ public:
+  ~LhsMerger() {}
+
+  static unique_ptr<Merger> create(Error *error, const MergerOptions &options);
+
+  bool reset(Error *error,
+             Array<Record> *input_records_1,
+             Array<Record> *input_records_2,
+             Array<Record> *output_records);
+
+  bool finish(Error *error);
+
+ private:
+  Array<Record> *input_records_1_;
+  Array<Record> *input_records_2_;
+  Array<Record> *output_records_;
+  MergerOperatorType operator_type_;
+  Int offset_;
+  Int limit_;
+
+  LhsMerger(MergerOperatorType operator_type, Int offset, Int limit)
+      : Merger(),
+        input_records_1_(nullptr),
+        input_records_2_(nullptr),
+        output_records_(nullptr),
+        operator_type_(operator_type),
+        offset_(offset),
+        limit_(limit) {}
+};
+
+unique_ptr<Merger> LhsMerger::create(Error *error,
+                                     const MergerOptions &options) {
+  unique_ptr<Merger> merger(
+      new (nothrow) LhsMerger(options.operator_type,
+                              options.offset,
+                              options.limit));
+  if (!merger) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return nullptr;
+  }
+  return merger;
+}
+
+bool LhsMerger::reset(Error *,
+                      Array<Record> *input_records_1,
+                      Array<Record> *input_records_2,
+                      Array<Record> *output_records) {
+  input_records_1_ = input_records_1;
+  input_records_2_ = input_records_2;
+  output_records_ = output_records;
+  return true;
+}
+
+bool LhsMerger::finish(Error *error) {
+  // Create a hash table from the second input.
+  std::unordered_map<Int, Float> filter;
+  for (Int i = 0; i < input_records_2_->size(); ++i) {
+    filter[input_records_2_->get_row_id(i)] = input_records_2_->get_score(i);
+  }
+
+  // Adjust score of the first input.
+  const MergerOperatorType operator_type = operator_type_;
+  for (Int i = 0; i < input_records_1_->size(); ++i) {
+    Record record = input_records_1_->get(i);
+    auto it = filter.find(record.row_id);
+    if (it != filter.end()) {
+      switch (operator_type) {
+        case PLUS_MERGER_OPERATOR: {
+          record.score += it->second;
+          break;
+        }
+        case MINUS_MERGER_OPERATOR: {
+          record.score -= it->second;
+          break;
+        }
+        case MULTIPLICATION_MERGER_OPERATOR: {
+          record.score *= it->second;
+          break;
+        }
+        case LHS_MERGER_OPERATOR: {
+          break;
+        }
+        case RHS_MERGER_OPERATOR: {
+          record.score = it->second;
+          break;
+        }
+        case ZERO_MERGER_OPERATOR: {
+          record.score = 0.0;
+          break;
+        }
+      }
+    } else {
+      switch (operator_type) {
+        case PLUS_MERGER_OPERATOR:
+        case MINUS_MERGER_OPERATOR: {
+          break;
+        }
+        case MULTIPLICATION_MERGER_OPERATOR: {
+          // TODO: I'm not sure if it->second should be used?
+          record.score = 0.0;
+          break;
+        }
+        case LHS_MERGER_OPERATOR: {
+          break;
+        }
+        case RHS_MERGER_OPERATOR:
+        case ZERO_MERGER_OPERATOR: {
+          record.score = 0.0;
+          break;
+        }
+      }
+    }
+    if (!output_records_->push_back(error, record)) {
+      return false;
+    }
+  }
+
+  // Remove out-of-range records.
+  if (offset_ > 0) {
+    for (Int i = offset_; i < output_records_->size(); ++i) {
+      output_records_->set(i - offset_, output_records_->get(i));
+    }
+    output_records_->resize(nullptr, output_records_->size() - offset_);
+  }
+  if (limit_ < output_records_->size()) {
+    output_records_->resize(nullptr, limit_);
+  }
+  input_records_1_->clear();
+  input_records_2_->clear();
+  return true;
+}
 
 // -- RhsMerger --
 
-// TODO
+
+class RhsMerger : public Merger {
+ public:
+  ~RhsMerger() {}
+
+  static unique_ptr<Merger> create(Error *error, const MergerOptions &options);
+
+  bool reset(Error *error,
+             Array<Record> *input_records_1,
+             Array<Record> *input_records_2,
+             Array<Record> *output_records);
+
+  bool finish(Error *error);
+
+ private:
+  Array<Record> *input_records_1_;
+  Array<Record> *input_records_2_;
+  Array<Record> *output_records_;
+  MergerOperatorType operator_type_;
+  Int offset_;
+  Int limit_;
+
+  RhsMerger(MergerOperatorType operator_type, Int offset, Int limit)
+      : Merger(),
+        input_records_1_(nullptr),
+        input_records_2_(nullptr),
+        output_records_(nullptr),
+        operator_type_(operator_type),
+        offset_(offset),
+        limit_(limit) {}
+};
+
+unique_ptr<Merger> RhsMerger::create(Error *error,
+                                     const MergerOptions &options) {
+  unique_ptr<Merger> merger(
+      new (nothrow) RhsMerger(options.operator_type,
+                              options.offset,
+                              options.limit));
+  if (!merger) {
+    GRNXX_ERROR_SET(error, NO_MEMORY, "Memory allocation failed");
+    return nullptr;
+  }
+  return merger;
+}
+
+bool RhsMerger::reset(Error *,
+                      Array<Record> *input_records_1,
+                      Array<Record> *input_records_2,
+                      Array<Record> *output_records) {
+  input_records_1_ = input_records_1;
+  input_records_2_ = input_records_2;
+  output_records_ = output_records;
+  return true;
+}
+
+bool RhsMerger::finish(Error *error) {
+  // Create a hash table from the first input.
+  std::unordered_map<Int, Float> filter;
+  for (Int i = 0; i < input_records_1_->size(); ++i) {
+    filter[input_records_1_->get_row_id(i)] = input_records_1_->get_score(i);
+  }
+
+  // Adjust score of the first input.
+  const MergerOperatorType operator_type = operator_type_;
+  for (Int i = 0; i < input_records_2_->size(); ++i) {
+    Record record;
+    record.row_id = input_records_2_->get_row_id(i);
+    auto it = filter.find(record.row_id);
+    if (it != filter.end()) {
+      switch (operator_type) {
+        case PLUS_MERGER_OPERATOR: {
+          record.score = it->second + input_records_2_->get_score(i);
+          break;
+        }
+        case MINUS_MERGER_OPERATOR: {
+          record.score = it->second - input_records_2_->get_score(i);
+          break;
+        }
+        case MULTIPLICATION_MERGER_OPERATOR: {
+          record.score = it->second * input_records_2_->get_score(i);
+          break;
+        }
+        case LHS_MERGER_OPERATOR: {
+          record.score = it->second;
+          break;
+        }
+        case RHS_MERGER_OPERATOR: {
+          record.score = input_records_2_->get_score(i);
+          break;
+        }
+        case ZERO_MERGER_OPERATOR: {
+          record.score = 0.0;
+          break;
+        }
+      }
+    } else {
+      switch (operator_type) {
+        case PLUS_MERGER_OPERATOR: {
+          record.score = input_records_2_->get_score(i);
+          break;
+        }
+        case MINUS_MERGER_OPERATOR: {
+          record.score = -input_records_2_->get_score(i);
+          break;
+        }
+        case MULTIPLICATION_MERGER_OPERATOR: {
+          // TODO: I'm not sure if input_records_2_->get_score(i) should be used?
+          record.score = 0.0;
+          break;
+        }
+        case LHS_MERGER_OPERATOR: {
+          record.score = 0.0;
+          break;
+        }
+        case RHS_MERGER_OPERATOR: {
+          record.score = input_records_2_->get_score(i);
+          break;
+        }
+        case ZERO_MERGER_OPERATOR: {
+          record.score = 0.0;
+          break;
+        }
+      }
+    }
+    if (!output_records_->push_back(error, record)) {
+      return false;
+    }
+  }
+
+  // Remove out-of-range records.
+  if (offset_ > 0) {
+    for (Int i = offset_; i < output_records_->size(); ++i) {
+      output_records_->set(i - offset_, output_records_->get(i));
+    }
+    output_records_->resize(nullptr, output_records_->size() - offset_);
+  }
+  if (limit_ < output_records_->size()) {
+    output_records_->resize(nullptr, limit_);
+  }
+  input_records_1_->clear();
+  input_records_2_->clear();
+  return true;
+}
 
 // -- Merger --
 
@@ -495,10 +768,11 @@ unique_ptr<Merger> Merger::create(Error *error, const MergerOptions &options) {
     case MINUS_MERGER: {
       return MinusMerger::create(error, options);
     }
-    case LHS_MERGER:
+    case LHS_MERGER: {
+      return LhsMerger::create(error, options);
+    }
     case RHS_MERGER: {
-      GRNXX_ERROR_SET(error, NOT_SUPPORTED_YET, "Not supported yet");
-      return nullptr;
+      return RhsMerger::create(error, options);
     }
   }
 }
-------------- next part --------------
HTML����������������������������...
Download 



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