diff options
author | Katherine Wu <katherine.wu@mongodb.com> | 2020-08-27 13:33:51 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-09-22 17:14:12 +0000 |
commit | c39af144b2370be0537410d9bc79be66a1a5f3c7 (patch) | |
tree | 60e728ab0039a184650b77314e60ce38b935d2f8 /src/mongo/db/pipeline/expression_trigonometric.h | |
parent | 00e6eaf6ab5c029784ee525d77b50ed93ce2c027 (diff) | |
download | mongo-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.h | 180 |
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 |