/** 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); }
/** Rounds this Numeric */ Numeric::Ptr ATDecimalOrDerivedImpl::round(const DynamicContext* context) const { // if integer, return xs:integer, otherwise xs:decimal if(_isInteger) { return (const Numeric::Ptr )this->castAs(AnyAtomicType::DECIMAL, SchemaSymbols::fgURI_SCHEMAFORSCHEMA, SchemaSymbols::fgDT_INTEGER, context); } MAPM value = _decimal + 0.5; return context->getItemFactory()->createDecimal(value.floor(), context); }
/** Rounds this Numeric */ Numeric::Ptr ATFloatOrDerivedImpl::round(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: { if (isNegative() &&_float >= -0.5) { return negZero(context); } MAPM value = _float + 0.5; return newFloat(value.floor(), context); } default: { assert(false); return 0; // should never get here } } }
typename IntegerImpl<T>::value_type IntegerImpl<T>::ftoi( MAPM const &d ) { MAPM const temp( d.sign() >= 0 ? d.floor() : d.ceil() ); unique_ptr<char[]> const buf( new char[ temp.exponent() + 3 ] ); temp.toIntegerString( buf.get() ); return ztd::aton<value_type>( buf.get() ); }