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