/** 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
    }
  } 
}
Exemple #5
0
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() );
}