Skip to content

Commit

Permalink
Revert "SERVER-18427 Adds $log, $log10, $ln, $pow, and $exp aggregati…
Browse files Browse the repository at this point in the history
…on expressions"

This reverts commit f0541cc.
  • Loading branch information
jamesfcohan committed Aug 4, 2015
1 parent cbfd06f commit 6ba08bc
Show file tree
Hide file tree
Showing 3 changed files with 0 additions and 386 deletions.
111 changes: 0 additions & 111 deletions jstests/aggregation/bugs/server18427.js

This file was deleted.

249 changes: 0 additions & 249 deletions src/mongo/db/pipeline/expression.cpp
Expand Up @@ -1154,26 +1154,6 @@ const char* ExpressionDivide::getOpName() const {
return "$divide";
}

/* ----------------------- ExpressionExp ---------------------------- */

Value ExpressionExp::evaluateInternal(Variables* vars) const {
Value expVal = vpOperand[0]->evaluateInternal(vars);
if (expVal.nullish())
return Value(BSONNULL);

uassert(28765,
str::stream() << "$exp only supports numeric types, not " << typeName(expVal.getType()),
expVal.numeric());

// exp() always returns a double since e is a double.
return Value(exp(expVal.coerceToDouble()));
}

REGISTER_EXPRESSION(exp, ExpressionExp::parse);
const char* ExpressionExp::getOpName() const {
return "$exp";
}

/* ---------------------- ExpressionObject --------------------------- */

intrusive_ptr<ExpressionObject> ExpressionObject::create() {
Expand Down Expand Up @@ -2073,85 +2053,6 @@ const char* ExpressionIfNull::getOpName() const {
return "$ifNull";
}

/* ----------------------- ExpressionLn ---------------------------- */

Value ExpressionLn::evaluateInternal(Variables* vars) const {
Value argVal = vpOperand[0]->evaluateInternal(vars);
if (argVal.nullish())
return Value(BSONNULL);

uassert(28754,
str::stream() << "$ln only supports numeric types, not " << typeName(argVal.getType()),
argVal.numeric());

double argDouble = argVal.coerceToDouble();
uassert(28755,
str::stream() << "$ln's argument must be a positive number, but is " << argDouble,
argDouble > 0 || std::isnan(argDouble));
return Value(std::log(argDouble));
}

REGISTER_EXPRESSION(ln, ExpressionLn::parse);
const char* ExpressionLn::getOpName() const {
return "$ln";
}

/* ----------------------- ExpressionLog ---------------------------- */

Value ExpressionLog::evaluateInternal(Variables* vars) const {
Value argVal = vpOperand[0]->evaluateInternal(vars);
Value baseVal = vpOperand[1]->evaluateInternal(vars);
if (argVal.nullish() || baseVal.nullish())
return Value(BSONNULL);

uassert(28756,
str::stream() << "$log's argument must be numeric, not " << typeName(argVal.getType()),
argVal.numeric());
uassert(28757,
str::stream() << "$log's base must be numeric, not " << typeName(baseVal.getType()),
baseVal.numeric());

double argDouble = argVal.coerceToDouble();
double baseDouble = baseVal.coerceToDouble();
uassert(28758,
str::stream() << "$log's argument must be a positive number, but is " << argDouble,
argDouble > 0 || std::isnan(argDouble));
uassert(28759,
str::stream() << "$log's base must be a positive number not equal to 1, but is "
<< baseDouble,
(baseDouble > 0 && baseDouble != 1) || std::isnan(baseDouble));
return Value(std::log(argDouble) / std::log(baseDouble));
}

REGISTER_EXPRESSION(log, ExpressionLog::parse);
const char* ExpressionLog::getOpName() const {
return "$log";
}

/* ----------------------- ExpressionLog10 ---------------------------- */

Value ExpressionLog10::evaluateInternal(Variables* vars) const {
Value argVal = vpOperand[0]->evaluateInternal(vars);
if (argVal.nullish())
return Value(BSONNULL);

uassert(28760,
str::stream() << "$log10 only supports numeric types, not "
<< typeName(argVal.getType()),
argVal.numeric());

double argDouble = argVal.coerceToDouble();
uassert(28761,
str::stream() << "$log10's argument must be a positive number, but is " << argDouble,
argDouble > 0 || std::isnan(argDouble));
return Value(std::log10(argDouble));
}

REGISTER_EXPRESSION(log10, ExpressionLog10::parse);
const char* ExpressionLog10::getOpName() const {
return "$log10";
}

/* ------------------------ ExpressionNary ----------------------------- */

intrusive_ptr<Expression> ExpressionNary::optimize() {
Expand Down Expand Up @@ -2327,156 +2228,6 @@ const char* ExpressionOr::getOpName() const {
return "$or";
}

/* ----------------------- ExpressionPow ---------------------------- */

Value ExpressionPow::evaluateInternal(Variables* vars) const {
Value baseVal = vpOperand[0]->evaluateInternal(vars);
Value expVal = vpOperand[1]->evaluateInternal(vars);
if (baseVal.nullish() || expVal.nullish())
return Value(BSONNULL);

BSONType baseType = baseVal.getType();
BSONType expType = expVal.getType();

uassert(28762,
str::stream() << "$pow's base must be numeric, not " << typeName(baseType),
baseVal.numeric());
uassert(28763,
str::stream() << "$pow's exponent must be numeric, not " << typeName(expType),
expVal.numeric());

// pow() will cast args to doubles.
double baseNum = baseVal.coerceToDouble();
double expNum = expVal.coerceToDouble();

uassert(28764,
"$pow cannot take a base of 0 and a negative exponent",
!(baseNum == 0 && expNum < 0));

// If either number is a double, return a double.
if (baseType == NumberDouble || expType == NumberDouble) {
return Value(pow(baseNum, expNum));
}

// base and exp are both integers.

auto representableAsLong = [](long long base, long long exp) {
// If exp is greater than 63 and base is not -1, 0, or 1, the result will overflow.
// If exp is negative and the base is not -1 or 1, the result will be fractional.
if (exp < 0 || exp > 63) {
return std::abs(base) == 1 || base == 0;
}

struct MinMax {
long long min;
long long max;
};

// Array indices correspond to exponents 0 through 63. The values in each index are the min
// and max bases, respectively, that can be raised to that exponent without overflowing a
// 64-bit int. For max bases, this was computed by solving for b in
// b = (2^63-1)^(1/exp) for exp = [0, 63] and truncating b. To calculate min bases, for even
// exps the equation used was b = (2^63-1)^(1/exp), and for odd exps the equation used was
// b = (-2^63)^(1/exp). Since the magnitude of long min is greater than long max, the
// magnitude of some of the min bases raised to odd exps is greater than the corresponding
// max bases raised to the same exponents.

static const MinMax kBaseLimits[] = {
{std::numeric_limits<long long>::min(), std::numeric_limits<long long>::max()}, // 0
{std::numeric_limits<long long>::min(), std::numeric_limits<long long>::max()},
{-3037000499, 3037000499},
{-2097152, 2097151},
{-55108, 55108},
{-6208, 6208},
{-1448, 1448},
{-512, 511},
{-234, 234},
{-128, 127},
{-78, 78}, // 10
{-52, 52},
{-38, 38},
{-28, 28},
{-22, 22},
{-18, 18},
{-15, 15},
{-13, 13},
{-11, 11},
{-9, 9},
{-8, 8}, // 20
{-8, 7},
{-7, 7},
{-6, 6},
{-6, 6},
{-5, 5},
{-5, 5},
{-5, 5},
{-4, 4},
{-4, 4},
{-4, 4}, // 30
{-4, 4},
{-3, 3},
{-3, 3},
{-3, 3},
{-3, 3},
{-3, 3},
{-3, 3},
{-3, 3},
{-3, 3},
{-2, 2}, // 40
{-2, 2},
{-2, 2},
{-2, 2},
{-2, 2},
{-2, 2},
{-2, 2},
{-2, 2},
{-2, 2},
{-2, 2},
{-2, 2}, // 50
{-2, 2},
{-2, 2},
{-2, 2},
{-2, 2},
{-2, 2},
{-2, 2},
{-2, 2},
{-2, 2},
{-2, 2},
{-2, 2}, // 60
{-2, 2},
{-2, 2},
{-2, 1}};

return base >= kBaseLimits[exp].min && base <= kBaseLimits[exp].max;
};

// If the result cannot be represented as a long, return a double. Otherwise if either number
// is a long, return a long. If both numbers are ints, then return an int if the result fits or
// a long if it is too big.
if (!representableAsLong(baseNum, expNum)) {
return Value(pow(baseNum, expNum));
}

long long baseLong = baseVal.getLong();
long long expLong = expVal.getLong();
long long result = 1;
// Use repeated multiplication, since pow() casts args to doubles which could result in loss of
// precision if arguments are very large.
for (int i = 0; i < expLong; i++) {
result *= baseLong;
}

if (baseType == NumberLong || expType == NumberLong) {
return Value(result);
}
return Value::createIntOrLong(result);
}

REGISTER_EXPRESSION(pow, ExpressionPow::parse);
const char* ExpressionPow::getOpName() const {
return "$pow";
}

/* ------------------------- ExpressionSecond ----------------------------- */

Value ExpressionSecond::evaluateInternal(Variables* vars) const {
Expand Down

0 comments on commit 6ba08bc

Please sign in to comment.