[Groonga-commit] groonga/grnxx at d9a940c [master] Add nodes for arithmetic operators.

Back to archive index

susumu.yata null+****@clear*****
Mon Aug 11 18:49:54 JST 2014


susumu.yata	2014-08-11 18:49:54 +0900 (Mon, 11 Aug 2014)

  New Revision: d9a940c118d98d010768c1a7b515dec1d94497a9
  https://github.com/groonga/grnxx/commit/d9a940c118d98d010768c1a7b515dec1d94497a9

  Message:
    Add nodes for arithmetic operators.

  Modified files:
    include/grnxx/error.hpp
    lib/grnxx/expression2.cpp

  Modified: include/grnxx/error.hpp (+2 -0)
===================================================================
--- include/grnxx/error.hpp    2014-08-11 18:32:56 +0900 (1a07df7)
+++ include/grnxx/error.hpp    2014-08-11 18:49:54 +0900 (ebfa757)
@@ -17,6 +17,8 @@ enum ErrorCode {
   INVALID_ARGUMENT,   // Invalid argument.
   INVALID_OPERATION,  // Invalid operation.
   INVALID_OPERAND,    // Invalid operand.
+  DIVISION_BY_ZERO,   // Integer division by zero.
+  DIVISION_OVERFLOW,  // Overflow in integer division.
   NOT_SUPPORTED_YET   // The operation is not supported yet.
 };
 

  Modified: lib/grnxx/expression2.cpp (+337 -7)
===================================================================
--- lib/grnxx/expression2.cpp    2014-08-11 18:32:56 +0900 (9f7806f)
+++ lib/grnxx/expression2.cpp    2014-08-11 18:49:54 +0900 (3e86558)
@@ -1494,13 +1494,343 @@ bool BitwiseXorNode<Int>::evaluate(Error *error,
   return true;
 }
 
-// TODO: Other binary operators.
-//  // Arithmetic operators.
-//  PLUS_OPERATOR,            // For Int, Float.
-//  MINUS_OPERATOR,           // For Int, Float.
-//  MULTIPLICATION_OPERATOR,  // For Int, Float.
-//  DIVISION_OPERATOR,        // For Int, Float.
-//  MODULUS_OPERATOR,         // For Int.
+// ---- PlusOperator ----
+
+template <typename T> class PlusNode;
+
+template <>
+class PlusNode<Int> : public BinaryNode<Int, Int, Int> {
+ public:
+  using Value = Int;
+  using Arg1 = Int;
+  using Arg2 = Int;
+
+  PlusNode(unique_ptr<Node> &&arg1, unique_ptr<Node> &&arg2)
+      : BinaryNode<Value, Arg1, Arg2>(std::move(arg1), std::move(arg2)) {}
+
+  bool evaluate(Error *error,
+                ArrayCRef<Record> records,
+                ArrayRef<Value> results);
+};
+
+bool PlusNode<Int>::evaluate(Error *error,
+                             ArrayCRef<Record> records,
+                             ArrayRef<Value> results) {
+  if (!fill_arg1_values(error, records) ||
+      !fill_arg2_values(error, records)) {
+    return false;
+  }
+  for (Int i = 0; i < records.size(); ++i) {
+    results.set(i, this->arg1_values_[i] + this->arg2_values_[i]);
+  }
+  return true;
+}
+
+template <>
+class PlusNode<Float> : public BinaryNode<Float, Float, Float> {
+ public:
+  using Value = Float;
+  using Arg1 = Float;
+  using Arg2 = Float;
+
+  PlusNode(unique_ptr<Node> &&arg1, unique_ptr<Node> &&arg2)
+      : BinaryNode<Value, Arg1, Arg2>(std::move(arg1), std::move(arg2)) {}
+
+  bool adjust(Error *error, ArrayRef<Record> records);
+  bool evaluate(Error *error,
+                ArrayCRef<Record> records,
+                ArrayRef<Value> results);
+};
+
+bool PlusNode<Float>::adjust(Error *error, ArrayRef<Record> records) {
+  if (!fill_arg1_values(error, records) ||
+      !fill_arg2_values(error, records)) {
+    return false;
+  }
+  for (Int i = 0; i < records.size(); ++i) {
+    records.set_score(i, this->arg1_values_[i] + this->arg2_values_[i]);
+  }
+  return true;
+}
+
+bool PlusNode<Float>::evaluate(Error *error,
+                               ArrayCRef<Record> records,
+                               ArrayRef<Value> results) {
+  if (!fill_arg1_values(error, records) ||
+      !fill_arg2_values(error, records)) {
+    return false;
+  }
+  for (Int i = 0; i < records.size(); ++i) {
+    results.set(i, this->arg1_values_[i] + this->arg2_values_[i]);
+  }
+  return true;
+}
+
+// ---- MinusOperator ----
+
+template <typename T> class MinusNode;
+
+template <>
+class MinusNode<Int> : public BinaryNode<Int, Int, Int> {
+ public:
+  using Value = Int;
+  using Arg1 = Int;
+  using Arg2 = Int;
+
+  MinusNode(unique_ptr<Node> &&arg1, unique_ptr<Node> &&arg2)
+      : BinaryNode<Value, Arg1, Arg2>(std::move(arg1), std::move(arg2)) {}
+
+  bool evaluate(Error *error,
+                ArrayCRef<Record> records,
+                ArrayRef<Value> results);
+};
+
+bool MinusNode<Int>::evaluate(Error *error,
+                              ArrayCRef<Record> records,
+                              ArrayRef<Value> results) {
+  if (!fill_arg1_values(error, records) ||
+      !fill_arg2_values(error, records)) {
+    return false;
+  }
+  for (Int i = 0; i < records.size(); ++i) {
+    results.set(i, this->arg1_values_[i] - this->arg2_values_[i]);
+  }
+  return true;
+}
+
+template <>
+class MinusNode<Float> : public BinaryNode<Float, Float, Float> {
+ public:
+  using Value = Float;
+  using Arg1 = Float;
+  using Arg2 = Float;
+
+  MinusNode(unique_ptr<Node> &&arg1, unique_ptr<Node> &&arg2)
+      : BinaryNode<Value, Arg1, Arg2>(std::move(arg1), std::move(arg2)) {}
+
+  bool adjust(Error *error, ArrayRef<Record> records);
+  bool evaluate(Error *error,
+                ArrayCRef<Record> records,
+                ArrayRef<Value> results);
+};
+
+bool MinusNode<Float>::adjust(Error *error, ArrayRef<Record> records) {
+  if (!fill_arg1_values(error, records) ||
+      !fill_arg2_values(error, records)) {
+    return false;
+  }
+  for (Int i = 0; i < records.size(); ++i) {
+    records.set_score(i, this->arg1_values_[i] - this->arg2_values_[i]);
+  }
+  return true;
+}
+
+bool MinusNode<Float>::evaluate(Error *error,
+                                ArrayCRef<Record> records,
+                                ArrayRef<Value> results) {
+  if (!fill_arg1_values(error, records) ||
+      !fill_arg2_values(error, records)) {
+    return false;
+  }
+  for (Int i = 0; i < records.size(); ++i) {
+    results.set(i, this->arg1_values_[i] - this->arg2_values_[i]);
+  }
+  return true;
+}
+
+// ---- MultiplicationOperator ----
+
+template <typename T> class MultiplicationNode;
+
+template <>
+class MultiplicationNode<Int> : public BinaryNode<Int, Int, Int> {
+ public:
+  using Value = Int;
+  using Arg1 = Int;
+  using Arg2 = Int;
+
+  MultiplicationNode(unique_ptr<Node> &&arg1, unique_ptr<Node> &&arg2)
+      : BinaryNode<Value, Arg1, Arg2>(std::move(arg1), std::move(arg2)) {}
+
+  bool evaluate(Error *error,
+                ArrayCRef<Record> records,
+                ArrayRef<Value> results);
+};
+
+bool MultiplicationNode<Int>::evaluate(Error *error,
+                                       ArrayCRef<Record> records,
+                                       ArrayRef<Value> results) {
+  if (!fill_arg1_values(error, records) ||
+      !fill_arg2_values(error, records)) {
+    return false;
+  }
+  for (Int i = 0; i < records.size(); ++i) {
+    results.set(i, this->arg1_values_[i] * this->arg2_values_[i]);
+  }
+  return true;
+}
+
+template <>
+class MultiplicationNode<Float> : public BinaryNode<Float, Float, Float> {
+ public:
+  using Value = Float;
+  using Arg1 = Float;
+  using Arg2 = Float;
+
+  MultiplicationNode(unique_ptr<Node> &&arg1, unique_ptr<Node> &&arg2)
+      : BinaryNode<Value, Arg1, Arg2>(std::move(arg1), std::move(arg2)) {}
+
+  bool adjust(Error *error, ArrayRef<Record> records);
+  bool evaluate(Error *error,
+                ArrayCRef<Record> records,
+                ArrayRef<Value> results);
+};
+
+bool MultiplicationNode<Float>::adjust(Error *error,
+                                       ArrayRef<Record> records) {
+  if (!fill_arg1_values(error, records) ||
+      !fill_arg2_values(error, records)) {
+    return false;
+  }
+  for (Int i = 0; i < records.size(); ++i) {
+    records.set_score(i, this->arg1_values_[i] * this->arg2_values_[i]);
+  }
+  return true;
+}
+
+bool MultiplicationNode<Float>::evaluate(Error *error,
+                                         ArrayCRef<Record> records,
+                                         ArrayRef<Value> results) {
+  if (!fill_arg1_values(error, records) ||
+      !fill_arg2_values(error, records)) {
+    return false;
+  }
+  for (Int i = 0; i < records.size(); ++i) {
+    results.set(i, this->arg1_values_[i] * this->arg2_values_[i]);
+  }
+  return true;
+}
+
+// ---- DivisionOperator ----
+
+template <typename T> class DivisionNode;
+
+template <>
+class DivisionNode<Int> : public BinaryNode<Int, Int, Int> {
+ public:
+  using Value = Int;
+  using Arg1 = Int;
+  using Arg2 = Int;
+
+  DivisionNode(unique_ptr<Node> &&arg1, unique_ptr<Node> &&arg2)
+      : BinaryNode<Value, Arg1, Arg2>(std::move(arg1), std::move(arg2)) {}
+
+  bool evaluate(Error *error,
+                ArrayCRef<Record> records,
+                ArrayRef<Value> results);
+};
+
+bool DivisionNode<Int>::evaluate(Error *error,
+                                 ArrayCRef<Record> records,
+                                 ArrayRef<Value> results) {
+  if (!fill_arg1_values(error, records) ||
+      !fill_arg2_values(error, records)) {
+    return false;
+  }
+  for (Int i = 0; i < records.size(); ++i) {
+    if (this->arg2_values_[i] == 0) {
+      GRNXX_ERROR_SET(error, DIVISION_BY_ZERO, "Division by zero");
+      return false;
+    } else if ((this->arg2_values_[i] == -1) &&
+               (this->arg1_values_[i] == numeric_limits<Int>::min())) {
+      GRNXX_ERROR_SET(error, DIVISION_OVERFLOW, "Division overflow");
+      return false;
+    }
+    results.set(i, this->arg1_values_[i] / this->arg2_values_[i]);
+  }
+  return true;
+}
+
+template <>
+class DivisionNode<Float> : public BinaryNode<Float, Float, Float> {
+ public:
+  using Value = Float;
+  using Arg1 = Float;
+  using Arg2 = Float;
+
+  DivisionNode(unique_ptr<Node> &&arg1, unique_ptr<Node> &&arg2)
+      : BinaryNode<Value, Arg1, Arg2>(std::move(arg1), std::move(arg2)) {}
+
+  bool adjust(Error *error, ArrayRef<Record> records);
+  bool evaluate(Error *error,
+                ArrayCRef<Record> records,
+                ArrayRef<Value> results);
+};
+
+bool DivisionNode<Float>::adjust(Error *error,
+                                 ArrayRef<Record> records) {
+  if (!fill_arg1_values(error, records) ||
+      !fill_arg2_values(error, records)) {
+    return false;
+  }
+  for (Int i = 0; i < records.size(); ++i) {
+    records.set_score(i, this->arg1_values_[i] / this->arg2_values_[i]);
+  }
+  return true;
+}
+
+bool DivisionNode<Float>::evaluate(Error *error,
+                                   ArrayCRef<Record> records,
+                                   ArrayRef<Value> results) {
+  if (!fill_arg1_values(error, records) ||
+      !fill_arg2_values(error, records)) {
+    return false;
+  }
+  for (Int i = 0; i < records.size(); ++i) {
+    results.set(i, this->arg1_values_[i] / this->arg2_values_[i]);
+  }
+  return true;
+}
+
+// ---- ModulusOperator ----
+
+template <typename T> class ModulusNode;
+
+template <>
+class ModulusNode<Int> : public BinaryNode<Int, Int, Int> {
+ public:
+  using Value = Int;
+  using Arg1 = Int;
+  using Arg2 = Int;
+
+  ModulusNode(unique_ptr<Node> &&arg1, unique_ptr<Node> &&arg2)
+      : BinaryNode<Value, Arg1, Arg2>(std::move(arg1), std::move(arg2)) {}
+
+  bool evaluate(Error *error,
+                ArrayCRef<Record> records,
+                ArrayRef<Value> results);
+};
+
+bool ModulusNode<Int>::evaluate(Error *error,
+                                ArrayCRef<Record> records,
+                                ArrayRef<Value> results) {
+  if (!fill_arg1_values(error, records) ||
+      !fill_arg2_values(error, records)) {
+    return false;
+  }
+  for (Int i = 0; i < records.size(); ++i) {
+    if (this->arg2_values_[i] == 0) {
+      GRNXX_ERROR_SET(error, DIVISION_BY_ZERO, "Division by zero");
+      return false;
+    } else if ((this->arg2_values_[i] == -1) &&
+               (this->arg1_values_[i] == numeric_limits<Int>::min())) {
+      GRNXX_ERROR_SET(error, DIVISION_OVERFLOW, "Division overflow");
+      return false;
+    }
+    results.set(i, this->arg1_values_[i] % this->arg2_values_[i]);
+  }
+  return true;
+}
 
 }  // namespace expression
 
-------------- next part --------------
HTML����������������������������...
Descargar 



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