bool SafeNum::isEquivalent(const SafeNum& rhs) const { if (!isValid() && !rhs.isValid()) { return true; } // EOO is not equivalent to anything else. if (!isValid() || !rhs.isValid()) { return false; } // If the types of either side are mixed, we'll try to find the shortest type we // can upconvert to that would not sacrifice the accuracy in the process. // If none of the sides is a double, compare them as long's. if (_type != NumberDouble && rhs._type != NumberDouble) { return getLongLong(*this) == getLongLong(rhs); } // If both sides are doubles, compare them as so. if (_type == NumberDouble && rhs._type == NumberDouble) { return _value.doubleVal == rhs._value.doubleVal; } // If we're mixing integers and doubles, we should be careful. Some integers are // too big to be accuratelly represented in a double. If we're within a safe range // we compare both sides as doubles. const double lhsDouble = getDouble(*this); const double rhsDouble = getDouble(rhs); if (lhsDouble > -maxIntInDouble && lhsDouble < maxIntInDouble && rhsDouble > -maxIntInDouble && rhsDouble < maxIntInDouble) { return lhsDouble == rhsDouble; } return false; }
SafeNum BitNode::applyOpList(SafeNum value) const { for (const auto& op : _opList) { value = (value.*(op.bitOperator))(op.operand); if (!value.isValid()) { uasserted(ErrorCodes::BadValue, str::stream() << "Failed to apply $bit operations to current value: " << value.debugString()); } } return value; }