summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline/expression_trigonometric.h
diff options
context:
space:
mode:
authorKatherine Wu <katherine.wu@mongodb.com>2020-08-27 13:33:51 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-09-22 17:14:12 +0000
commitc39af144b2370be0537410d9bc79be66a1a5f3c7 (patch)
tree60e728ab0039a184650b77314e60ce38b935d2f8 /src/mongo/db/pipeline/expression_trigonometric.h
parent00e6eaf6ab5c029784ee525d77b50ed93ce2c027 (diff)
downloadmongo-c39af144b2370be0537410d9bc79be66a1a5f3c7.tar.gz
SERVER-48873 Implement agg trig expression operators in grammar
Diffstat (limited to 'src/mongo/db/pipeline/expression_trigonometric.h')
-rw-r--r--src/mongo/db/pipeline/expression_trigonometric.h180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/mongo/db/pipeline/expression_trigonometric.h b/src/mongo/db/pipeline/expression_trigonometric.h
index c1fa96804d1..bb6d0928fd7 100644
--- a/src/mongo/db/pipeline/expression_trigonometric.h
+++ b/src/mongo/db/pipeline/expression_trigonometric.h
@@ -105,6 +105,9 @@ class ExpressionBoundedTrigonometric : public ExpressionSingleNumericArg<Bounded
public:
explicit ExpressionBoundedTrigonometric(ExpressionContext* const expCtx)
: ExpressionSingleNumericArg<BoundedTrigType>(expCtx) {}
+ explicit ExpressionBoundedTrigonometric(ExpressionContext* const expCtx,
+ Expression::ExpressionVector&& children)
+ : ExpressionSingleNumericArg<BoundedTrigType>(expCtx, std::move(children)) {}
std::string toString(double d) const {
return str::stream() << d;
@@ -201,6 +204,9 @@ class ExpressionUnboundedTrigonometric : public ExpressionSingleNumericArg<TrigT
public:
explicit ExpressionUnboundedTrigonometric(ExpressionContext* const expCtx)
: ExpressionSingleNumericArg<TrigType>(expCtx) {}
+ explicit ExpressionUnboundedTrigonometric(ExpressionContext* const expCtx,
+ Expression::ExpressionVector&& children)
+ : ExpressionSingleNumericArg<TrigType>(expCtx, std::move(children)) {}
/**
* evaluateNumericArg evaluates the implented trig function on one numericArg.
@@ -269,4 +275,178 @@ public:
return visitor->visit(this);
}
};
+
+
+/* ----------------------- Inclusive Bounded Trigonometric Functions ---------------------------- */
+
+#define CREATE_BOUNDED_TRIGONOMETRIC_CLASS(className, funcName, boundType, lowerBound, upperBound) \
+ class Expression##className final \
+ : public ExpressionBoundedTrigonometric<Expression##className, boundType> { \
+ public: \
+ explicit Expression##className(ExpressionContext* const expCtx) \
+ : ExpressionBoundedTrigonometric(expCtx) {} \
+ explicit Expression##className(ExpressionContext* const expCtx, \
+ ExpressionVector&& children) \
+ : ExpressionBoundedTrigonometric(expCtx, std::move(children)) {} \
+ double getLowerBound() const final { \
+ return lowerBound; \
+ } \
+ \
+ double getUpperBound() const final { \
+ return upperBound; \
+ } \
+ \
+ double doubleFunc(double arg) const final { \
+ return std::funcName(arg); \
+ } \
+ \
+ Decimal128 decimalFunc(Decimal128 arg) const final { \
+ return arg.funcName(); \
+ } \
+ \
+ const char* getOpName() const final { \
+ return "$" #funcName; \
+ } \
+ \
+ void acceptVisitor(ExpressionVisitor* visitor) final { \
+ return visitor->visit(this); \
+ } \
+ };
+
+
+/**
+ * Inclusive Bounds
+ */
+CREATE_BOUNDED_TRIGONOMETRIC_CLASS(ArcCosine, acos, InclusiveBoundType, -1.0, 1.0);
+
+CREATE_BOUNDED_TRIGONOMETRIC_CLASS(ArcSine, asin, InclusiveBoundType, -1.0, 1.0);
+
+CREATE_BOUNDED_TRIGONOMETRIC_CLASS(HyperbolicArcTangent, atanh, InclusiveBoundType, -1.0, 1.0);
+
+CREATE_BOUNDED_TRIGONOMETRIC_CLASS(
+ HyperbolicArcCosine, acosh, InclusiveBoundType, 1.0, std::numeric_limits<double>::infinity());
+
+/**
+ * Exclusive Bounds
+ */
+CREATE_BOUNDED_TRIGONOMETRIC_CLASS(Cosine,
+ cos,
+ ExclusiveBoundType,
+ -std::numeric_limits<double>::infinity(),
+ std::numeric_limits<double>::infinity());
+
+CREATE_BOUNDED_TRIGONOMETRIC_CLASS(Sine,
+ sin,
+ ExclusiveBoundType,
+ -std::numeric_limits<double>::infinity(),
+ std::numeric_limits<double>::infinity());
+
+CREATE_BOUNDED_TRIGONOMETRIC_CLASS(Tangent,
+ tan,
+ ExclusiveBoundType,
+ -std::numeric_limits<double>::infinity(),
+ std::numeric_limits<double>::infinity());
+
+#undef CREATE_BOUNDED_TRIGONOMETRIC_CLASS
+
+/* ----------------------- Unbounded Trigonometric Functions ---------------------------- */
+
+
+#define CREATE_TRIGONOMETRIC_CLASS(className, funcName) \
+ class Expression##className final \
+ : public ExpressionUnboundedTrigonometric<Expression##className> { \
+ public: \
+ explicit Expression##className(ExpressionContext* const expCtx) \
+ : ExpressionUnboundedTrigonometric(expCtx) {} \
+ explicit Expression##className(ExpressionContext* const expCtx, \
+ ExpressionVector&& children) \
+ : ExpressionUnboundedTrigonometric(expCtx, std::move(children)) {} \
+ \
+ double doubleFunc(double arg) const final { \
+ return std::funcName(arg); \
+ } \
+ \
+ Decimal128 decimalFunc(Decimal128 arg) const final { \
+ return arg.funcName(); \
+ } \
+ \
+ const char* getOpName() const final { \
+ return "$" #funcName; \
+ } \
+ \
+ void acceptVisitor(ExpressionVisitor* visitor) final { \
+ return visitor->visit(this); \
+ } \
+ };
+
+CREATE_TRIGONOMETRIC_CLASS(ArcTangent, atan);
+CREATE_TRIGONOMETRIC_CLASS(HyperbolicArcSine, asinh);
+CREATE_TRIGONOMETRIC_CLASS(HyperbolicCosine, cosh);
+CREATE_TRIGONOMETRIC_CLASS(HyperbolicSine, sinh);
+CREATE_TRIGONOMETRIC_CLASS(HyperbolicTangent, tanh);
+
+#undef CREATE_TRIGONOMETRIC_CLASS
+
+/* ----------------------- ExpressionDegreesToRadians and ExpressionRadiansToDegrees ---- */
+
+static constexpr double kDoublePi = 3.141592653589793;
+static constexpr double kDoublePiOver180 = kDoublePi / 180.0;
+static constexpr double kDouble180OverPi = 180.0 / kDoublePi;
+
+static Value doDegreeRadiansConversion(const Value& numericArg,
+ Decimal128 decimalFactor,
+ double doubleFactor) {
+ switch (numericArg.getType()) {
+ case BSONType::NumberDecimal:
+ return Value(numericArg.getDecimal().multiply(decimalFactor));
+ default:
+ return Value(numericArg.coerceToDouble() * doubleFactor);
+ }
+}
+
+class ExpressionDegreesToRadians final
+ : public ExpressionSingleNumericArg<ExpressionDegreesToRadians> {
+public:
+ explicit ExpressionDegreesToRadians(ExpressionContext* const expCtx)
+ : ExpressionSingleNumericArg(expCtx) {}
+ explicit ExpressionDegreesToRadians(ExpressionContext* const expCtx,
+ ExpressionVector&& children)
+ : ExpressionSingleNumericArg(expCtx, std::move(children)) {}
+
+ Value evaluateNumericArg(const Value& numericArg) const final {
+ return doDegreeRadiansConversion(numericArg, Decimal128::kPiOver180, kDoublePiOver180);
+ }
+
+ const char* getOpName() const final {
+ return "$degreesToRadians";
+ }
+
+ void acceptVisitor(ExpressionVisitor* visitor) final {
+ return visitor->visit(this);
+ }
+};
+
+class ExpressionRadiansToDegrees final
+ : public ExpressionSingleNumericArg<ExpressionRadiansToDegrees> {
+public:
+ explicit ExpressionRadiansToDegrees(ExpressionContext* const expCtx)
+ : ExpressionSingleNumericArg(expCtx) {}
+ explicit ExpressionRadiansToDegrees(ExpressionContext* const expCtx,
+ ExpressionVector&& children)
+ : ExpressionSingleNumericArg(expCtx, std::move(children)) {}
+
+ Value evaluateNumericArg(const Value& numericArg) const final {
+ return doDegreeRadiansConversion(numericArg, Decimal128::k180OverPi, kDouble180OverPi);
+ }
+
+ const char* getOpName() const final {
+ return "$radiansToDegrees";
+ }
+
+ void acceptVisitor(ExpressionVisitor* visitor) final {
+ return visitor->visit(this);
+ }
+};
+
+
} // namespace mongo