susumu.yata
null+****@clear*****
Thu Nov 13 22:44:00 JST 2014
susumu.yata 2014-11-13 22:44:00 +0900 (Thu, 13 Nov 2014) New Revision: b7160930710bf710c3d03474cedcfd33c8f009f0 https://github.com/groonga/grnxx/commit/b7160930710bf710c3d03474cedcfd33c8f009f0 Message: Enable bitwise binary operators. (#106) Modified files: lib/grnxx/impl/expression.cpp lib/grnxx/impl/expression.hpp Modified: lib/grnxx/impl/expression.cpp (+168 -18) =================================================================== --- lib/grnxx/impl/expression.cpp 2014-11-13 22:02:36 +0900 (a89e074) +++ lib/grnxx/impl/expression.cpp 2014-11-13 22:44:00 +0900 (86bddf7) @@ -1032,6 +1032,130 @@ struct GreaterEqual { template <typename T> using GreaterEqualNode = ComparisonNode<GreaterEqual::Comparer<T>>; +// TODO: BitwiseAnd/Or/XorNode should be implemented on the same base class? + +// ---- BitwiseBinaryNode ---- + +template <typename T, typename U = typename T::Value> +class BitwiseBinaryNode : public BinaryNode<U, U, U> { + public: + using Operator = T; + using Value = U; + using Arg1 = U; + using Arg2 = U; + + BitwiseBinaryNode(std::unique_ptr<Node> &&arg1, std::unique_ptr<Node> &&arg2) + : BinaryNode<Value, Arg1, Arg2>(std::move(arg1), std::move(arg2)), + operator_() {} + + void evaluate(ArrayCRef<Record> records, ArrayRef<Value> results); + + private: + Operator operator_; +}; + +template <typename T, typename U> +void BitwiseBinaryNode<T, U>::evaluate(ArrayCRef<Record> records, + ArrayRef<Value> results) { + this->fill_arg1_values(records); + this->fill_arg2_values(records); + for (size_t i = 0; i < records.size(); ++i) { + results[i] = this->arg1_values_[i] & this->arg2_values_[i]; + } +} + +template <typename T> +class BitwiseBinaryNode<T, Bool> : public BinaryNode<Bool, Bool, Bool> { + public: + using Operator = T; + using Value = Bool; + using Arg1 = Bool; + using Arg2 = Bool; + + BitwiseBinaryNode(std::unique_ptr<Node> &&arg1, std::unique_ptr<Node> &&arg2) + : BinaryNode<Value, Arg1, Arg2>(std::move(arg1), std::move(arg2)), + operator_() {} + + void filter(ArrayCRef<Record> input_records, + ArrayRef<Record> *output_records); + void evaluate(ArrayCRef<Record> records, ArrayRef<Value> results); + + private: + Operator operator_; +}; + +template <typename T> +void BitwiseBinaryNode<T, Bool>::filter(ArrayCRef<Record> input_records, + ArrayRef<Record> *output_records) { + this->fill_arg1_values(input_records); + this->fill_arg2_values(input_records); + size_t count = 0; + for (size_t i = 0; i < input_records.size(); ++i) { + if ((this->arg1_values_[i] & this->arg2_values_[i]).is_true()) { + (*output_records)[count] = input_records[i]; + ++count; + } + } + *output_records = output_records->ref(0, count); +} + +template <typename T> +void BitwiseBinaryNode<T, Bool>::evaluate(ArrayCRef<Record> records, + ArrayRef<Value> results) { + this->fill_arg1_values(records); + this->fill_arg2_values(records); + // TODO: Should be processed per 64 bits. + // Check the 64-bit boundary and do it! + for (size_t i = 0; i < records.size(); ++i) { + results[i] = this->arg1_values_[i] & this->arg2_values_[i]; + } +} + +// ----- BitwiseAndNode ----- + +struct BitwiseAnd { + template <typename T> + struct Operator { + using Value = T; + Value operator()(Value arg1, Value arg2) const { + return arg1 & arg2; + } + }; +}; + +template <typename T> +using BitwiseAndNode = BitwiseBinaryNode<BitwiseAnd::Operator<T>>; + +// ----- BitwiseOrNode ----- + +struct BitwiseOr { + template <typename T> + struct Operator { + using Value = T; + Value operator()(Value arg1, Value arg2) const { + return arg1 | arg2; + } + }; +}; + +template <typename T> +using BitwiseOrNode = BitwiseBinaryNode<BitwiseOr::Operator<T>>; + +// ----- BitwiseXorNode ----- + +struct BitwiseXor { + template <typename T> + struct Operator { + using Value = T; + Value operator()(Value arg1, Value arg2) const { + return arg1 ^ arg2; + } + }; +}; + +template <typename T> +using BitwiseXorNode = BitwiseBinaryNode<BitwiseXor::Operator<T>>; + } // namespace expression using namespace expression; @@ -1568,24 +1692,23 @@ Node *ExpressionBuilder::create_binary_node( return create_comparison_node<GreaterEqual>( std::move(arg1), std::move(arg2)); } -// case BITWISE_AND_OPERATOR: -// case BITWISE_OR_OPERATOR: -// case BITWISE_XOR_OPERATOR: { -// switch (arg1->data_type()) { -// case BOOL_DATA: { -// return create_bitwise_node<Bool>( -// error, operator_type, std::move(arg1), std::move(arg2)); -// } -// case INT_DATA: { -// return create_bitwise_node<Int>( -// error, operator_type, std::move(arg1), std::move(arg2)); -// } -// default: { -// GRNXX_ERROR_SET(error, INVALID_OPERAND, "Invalid data type"); -// return nullptr; -// } -// } -// } + case BITWISE_AND_OPERATOR: + case BITWISE_OR_OPERATOR: + case BITWISE_XOR_OPERATOR: { + switch (arg1->data_type()) { + case BOOL_DATA: { + return create_bitwise_binary_node<Bool>( + operator_type, std::move(arg1), std::move(arg2)); + } + case INT_DATA: { + return create_bitwise_binary_node<Int>( + operator_type, std::move(arg1), std::move(arg2)); + } + default: { + throw "Invalid data type"; // TODO + } + } + } // case PLUS_OPERATOR: // case MINUS_OPERATOR: // case MULTIPLICATION_OPERATOR: @@ -1710,5 +1833,32 @@ Node *ExpressionBuilder::create_comparison_node(std::unique_ptr<Node> &&arg1, } } +template <typename T> +Node *ExpressionBuilder::create_bitwise_binary_node( + OperatorType operator_type, + std::unique_ptr<Node> &&arg1, + std::unique_ptr<Node> &&arg2) { + if (arg1->data_type() != arg2->data_type()) { + throw "Data type conflict"; // TODO + } + switch (operator_type) { + case BITWISE_AND_OPERATOR: { + return new BitwiseBinaryNode<BitwiseAnd::Operator<T>>( + std::move(arg1), std::move(arg2)); + } + case BITWISE_OR_OPERATOR: { + return new BitwiseBinaryNode<BitwiseOr::Operator<T>>( + std::move(arg1), std::move(arg2)); + } + case BITWISE_XOR_OPERATOR: { + return new BitwiseBinaryNode<BitwiseXor::Operator<T>>( + std::move(arg1), std::move(arg2)); + } + default: { + throw "Invalid operator"; // TODO + } + } +} + } // namespace impl } // namespace grnxx Modified: lib/grnxx/impl/expression.hpp (+8 -0) =================================================================== --- lib/grnxx/impl/expression.hpp 2014-11-13 22:02:36 +0900 (0fe020b) +++ lib/grnxx/impl/expression.hpp 2014-11-13 22:44:00 +0900 (af1fb80) @@ -151,6 +151,14 @@ class ExpressionBuilder : public ExpressionBuilderInterface { template <typename T> Node *create_comparison_node(std::unique_ptr<Node> &&arg1, std::unique_ptr<Node> &&arg2); + + // Create a node associated with a bitwise binary operator. + // + // On failure, throws an exception. + template <typename T> + Node *create_bitwise_binary_node(OperatorType operator_type, + std::unique_ptr<Node> &&arg1, + std::unique_ptr<Node> &&arg2); }; } // namespace impl -------------- next part -------------- HTML����������������������������... 下載