/** Rounds this Numeric to the given precision, and rounds a half to even */ Numeric::Ptr ATDecimalOrDerivedImpl::roundHalfToEven(const Numeric::Ptr &precision, const DynamicContext* context) const { ATDecimalOrDerived::Ptr decimal_precision = (const Numeric::Ptr)precision->castAs(this->getPrimitiveTypeIndex(), context); MAPM exp = MAPM(10).pow(((ATDecimalOrDerivedImpl*)(const ATDecimalOrDerived*)decimal_precision)->_decimal); MAPM value = _decimal * exp; bool halfVal = false; // check if we're rounding on a half value if((value-0.5) == (value.floor())) { halfVal = true; } value = _decimal * exp + 0.5; value = value.floor(); // if halfVal make sure what we return has the least significant digit even if (halfVal) { if(value.is_odd()) { value = value - 1; } } value = value / exp; // if integer, return xs:integer, otherwise xs:decimal if(_isInteger) { return context->getItemFactory()->createInteger(value, context); } return context->getItemFactory()->createDecimal(value, context); }
/** Rounds this Numeric to the given precision, and rounds a half to even */ Numeric::Ptr ATFloatOrDerivedImpl::roundHalfToEven(const Numeric::Ptr &precision, const DynamicContext* context) const { switch (_state) { case NaN: return notANumber(context); case INF: return infinity(context); case NEG_INF: return negInfinity(context); case NEG_NUM: case NUM: break; default: { assert(false); return 0; // should never get here } } if (isZero() && isNegative()) return this; ATFloatOrDerived::Ptr float_precision = (const Numeric::Ptr)precision->castAs(this->getPrimitiveTypeIndex(), context); MAPM exp = MAPM(10).pow(((ATFloatOrDerivedImpl*)(const ATFloatOrDerived*)float_precision)->_float); MAPM value = _float * exp; bool halfVal = false; // check if we're rounding on a half value if((value-0.5) == (value.floor())) { halfVal = true; } value = _float * exp + 0.5; value = value.floor(); // if halfVal make sure what we return has the least significant digit even if (halfVal) { if(value.is_odd()) { value = value - 1; } } value = value / exp; // the spec doesn't actually say to do this, but djf believes this is the correct way to handle rounding of -ve values which will result in 0.0E0 // if (value == 0 && isNegative()) // return negZero(context); return newFloat(value, context); }