コード例 #1
0
Value GranularityRounderPowersOfTwo::roundDown(Value value) {
    uassertNonNegativeNumber(value);

    if (value.coerceToDouble() == 0.0) {
        return value;
    }

    Value exp;
    if (value.getType() == BSONType::NumberDouble) {
        exp = Value(static_cast<int>(std::ceil(std::log2(value.getDouble())) - 1.0));
    } else if (value.getType() == BSONType::NumberDecimal) {
        Decimal128 input = value.getDecimal();
        exp = Value(Decimal128(
            static_cast<int>((std::ceil(input.logarithm(Decimal128(2)).toDouble()) - 1.0))));
    } else {
        long long number = value.getLong();

        int leadingZeros = countLeadingZeros64(number);
        int trailingZeros = countTrailingZeros64(number);

        if (leadingZeros + trailingZeros == 63) {
            // If number is a power of 2, then we need to subtract an extra 1 so we round down to
            // the next power of 2.
            exp = Value(63 - leadingZeros - 1);
        } else {
            exp = Value(63 - leadingZeros);
        }
    }

    return ExpressionPow::create(getExpCtx(), Value(2), exp)->evaluate(Document());
}
コード例 #2
0
Value GranularityRounderPowersOfTwo::roundUp(Value value) {
    uassertNonNegativeNumber(value);

    if (value.coerceToDouble() == 0.0) {
        return value;
    }

    Value exp;
    if (value.getType() == BSONType::NumberDouble) {
        exp = Value(static_cast<int>(std::floor(std::log2(value.getDouble())) + 1.0));
    } else if (value.getType() == BSONType::NumberDecimal) {
        Decimal128 input = value.getDecimal();
        exp = Value(Decimal128(
            static_cast<int>((std::floor(input.logarithm(Decimal128(2)).toDouble()) + 1.0))));
    } else {
        long long number = value.getLong();

        // We can find the log_2 of 'number' by counting the number of leading zeros to find its
        // first bit set. This is safe to do because we are working with positive values.
        exp = Value(63 - countLeadingZeros64(number) + 1);
    }

    return ExpressionPow::create(getExpCtx(), Value(2), exp)->evaluate(Document());
}