Esempio n. 1
0
/** Returns the mod of its operands as a Numeric */
Numeric::Ptr ATFloatOrDerivedImpl::mod(const Numeric::Ptr &other, const DynamicContext* context) const {
    if(other->getPrimitiveTypeIndex() == AnyAtomicType::DECIMAL) {
        // if other is a decimal, promote it to xs:float
        return this->mod((const Numeric::Ptr )other->castAs(this->getPrimitiveTypeIndex(), context), context);
    } else if (other->getPrimitiveTypeIndex() == AnyAtomicType::DOUBLE) {
        // if other is a double, promote this to xs:double
        return ((const Numeric::Ptr )this->castAs(other->getPrimitiveTypeIndex(), context))->mod(other, context);
    } else if (other->getPrimitiveTypeIndex() == AnyAtomicType::FLOAT) {
        // same primitive type, can make comparison
        const ATFloatOrDerivedImpl* otherImpl = (ATFloatOrDerivedImpl*)(const Numeric*)other;
        if(this->isNaN() || otherImpl->isNaN() || this->isInfinite() || otherImpl->isZero()) {
            return notANumber(context);
        } else if(otherImpl->isInfinite() || this->isZero()) {
            return (const Numeric::Ptr )this->castAs(AnyAtomicType::FLOAT, context);
        } else {
            MAPM result = _float;
            MAPM r;
            r = result.integer_divide(otherImpl->_float);
            result -= r * otherImpl->_float;
            if (result == 0 && isNegative())
                return negZero(context);
            return newFloat(result, context);
        }
    } else {
        assert(false); // should never get here, numeric types are xs:decimal, xs:float, xs:integer and xs:double
        return 0;
    }
}
Esempio n. 2
0
Numeric::Ptr ATFloatOrDerivedImpl::tan(const DynamicContext* context) const {
    switch (_state) {
    case NaN:
        return this;
    case INF:
        return notANumber(context);
    case NEG_INF:
        return notANumber(context);
    case NEG_NUM:
    case NUM:
        return newFloat(_float.tan(), context);
    default:
        assert(false);
        return 0;  // should never get here
    }
}
Esempio n. 3
0
/** Returns a Numeric object which is the difference of this and
   * other */
Numeric::Ptr ATFloatOrDerivedImpl::subtract(const Numeric::Ptr &other, const DynamicContext* context) const {
  if(other->getPrimitiveTypeIndex() == AnyAtomicType::DECIMAL) {
    // if other is a decimal, promote it to xs:float
    return this->subtract((const Numeric::Ptr )other->castAs(this->getPrimitiveTypeIndex(), context), context);
  } else if (other->getPrimitiveTypeIndex() == AnyAtomicType::DOUBLE) {
    // if other is a double, promote this to xs:double
    return ((const Numeric::Ptr )this->castAs(other->getPrimitiveTypeIndex(), context))->subtract(other, context);
  } else if (other->getPrimitiveTypeIndex() == AnyAtomicType::FLOAT) {
    // same primitive type, can make comparison
    ATFloatOrDerivedImpl* otherImpl = (ATFloatOrDerivedImpl*)(const Numeric*)other;
    if(otherImpl->_state == NaN) return notANumber(context);

    switch (_state) {
      case NaN: return notANumber(context);
      case INF: {
        switch(otherImpl->_state) {
          case NaN: return notANumber(context);   // case taken care of above
          case NEG_NUM:
          case NUM: return infinity(context);     // INF - NUM = INF
          case INF: return notANumber(context);   // INF - INF = NaN
          case NEG_INF: return infinity(context); // INF - (-INF) = INF
          default: assert(false); return 0; // should never get here
        }
      }
      case NEG_INF: {
        switch(otherImpl->_state) {
          case NaN: return notANumber(context);          //case taken care of above
          case NEG_NUM:
          case NUM: return negInfinity(context);         // -INF - NUM = -INF
          case INF: return negInfinity(context);         // -INF - INF = -INF
          case NEG_INF: return notANumber(context);      // -INF - (-INF) = NaN
          default: assert(false); return 0; // should never get here
        }
      }                
      case NEG_NUM:
      case NUM: {
        switch(otherImpl->_state) {
          case NaN: return notANumber(context);          // case taken care of above
          case INF: return negInfinity(context);         // NUM - INF = -INF
          case NEG_INF: return infinity(context);        // NUM - (-INF) = INF
          case NEG_NUM:
          case NUM: return newFloat(_float - otherImpl->_float, context);
          default: assert(false); return 0;  // should never get here
        }
      }
      default: assert(false); return 0;  // should never get here
    } 
  } else {
    assert(false); // should never get here, numeric types are xs:decimal, xs:float, xs:integer and xs:double
    return 0;
  }
}
Esempio n. 4
0
/** Returns the floor of this Numeric */
Numeric::Ptr ATFloatOrDerivedImpl::floor(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 (isZero() && isNegative())
        return negZero(context);
      return newFloat(_float.floor(), context); 
    }
    default: { assert(false); return 0; // should never get here 
    }
  }
}
Esempio n. 5
0
/** 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);
}
Esempio n. 6
0
/** Returns a Numeric object which is the quotient of this and other */
Numeric::Ptr ATFloatOrDerivedImpl::divide(const Numeric::Ptr &other, const DynamicContext* context) const {
    if(other->getPrimitiveTypeIndex() == AnyAtomicType::DECIMAL) {
        // if other is a decimal, promote it to xs:float
        return this->divide((const Numeric::Ptr )other->castAs(this->getPrimitiveTypeIndex(), context), context);
    } else if (other->getPrimitiveTypeIndex() == AnyAtomicType::DOUBLE) {
        // if other is a double, promote this to xs:double
        return ((const Numeric::Ptr )this->castAs(other->getPrimitiveTypeIndex(), context))->divide(other, context);
    } else if (other->getPrimitiveTypeIndex() == AnyAtomicType::FLOAT) {
        // same primitive type, can make comparison
        ATFloatOrDerivedImpl* otherImpl = (ATFloatOrDerivedImpl*)(const Numeric*)other;
        if(otherImpl->_state == NaN) return notANumber(context);

        switch (_state) {
        case NaN:
            return notANumber(context);
        case INF: {
            switch(otherImpl->_state) {
            case NaN:
                return notANumber(context);      // case taken care of above
            case NEG_NUM:
            case NUM:
                return other->isPositive() ? infinity(context) : negInfinity(context);        // INF / NUM = +/-INF
            case INF:
                return notANumber(context);      // INF / INF = NaN
            case NEG_INF:
                return notANumber(context);  // INF / (-INF) = NaN
            default:
                assert(false);
                return 0; // should never get here
            } // switch
        }// case
        case NEG_INF: {
            switch(otherImpl->_state) {
            case NaN:
                return notANumber(context);          //case taken care of above
            case NEG_NUM:
            case NUM:
                return other->isPositive() ? negInfinity(context) : infinity(context);         // -INF / NUM = -INF
            case INF:
                return notANumber(context);          // -INF / INF = NaN
            case NEG_INF:
                return notANumber(context);      // -INF / (-INF) = NaN
            default:
                assert(false);
                return 0; // should never get here
            } // switch
        } // case
        case NEG_NUM:
        case NUM: {
            switch(otherImpl->_state) {
            case NaN:
                return notANumber(context);          // case taken care of above
            case INF: {                                    // NUM / INF = +/-0
                if(this->isNegative()) {
                    return negZero(context);
                } else {
                    return newFloat(0, context);
                }
            }// case
            case NEG_INF: {                               // NUM / -INF = +/-0
                if(this->isPositive()) {
                    return negZero(context);
                } else {
                    return newFloat(0, context);
                }
            }// case
            case NEG_NUM:
            case NUM: {
                if(other->isZero()) {
                    if(this->isZero()) return notANumber(context);
                    if((this->isNegative() && other->isPositive()) ||
                            (this->isPositive() && other->isNegative())) {
                        return negInfinity(context);            // NUM / (-0) or (-NUM) / 0 = -INF
                    } else {
                        return infinity(context);               // NUM / 0 or (-NUM) / (-0) = INF
                    }
                }
                else if(this->isZero())
                {
                    if((this->isNegative() && other->isPositive()) ||
                            (this->isPositive() && other->isNegative())) {
                        return negZero(context);                // 0 / (-NUM) or (-0) / NUM = -0
                    } else {
                        return newFloat(0, context);            // 0 / NUM or (-0) / (-NUM) = 0
                    }
                }
                return newFloat(_float / otherImpl->_float, context);
            }// case
            default:
                assert(false);
                return 0;  // should never get here
            }// switch
        }// case
        default:
            assert(false);
            return 0;  // should never get here
        }// switch
    } else {
        assert(false); // should never get here, numeric types are xs:decimal, xs:float, xs:integer and xs:double
        return 0;
    }
}
Esempio n. 7
0
/** Returns a Numeric object which is the sum of this and other */
Numeric::Ptr ATFloatOrDerivedImpl::add(const Numeric::Ptr &other, const DynamicContext* context) const {
    if(other->getPrimitiveTypeIndex() == AnyAtomicType::DECIMAL) {
        // if other is a decimal, promote it to xs:float
        return this->add((const Numeric::Ptr )other->castAs(this->getPrimitiveTypeIndex(), context), context);
    } else if (other->getPrimitiveTypeIndex() == AnyAtomicType::DOUBLE) {
        // if other is a double, promote this to xs:double
        return ((const Numeric::Ptr )this->castAs(other->getPrimitiveTypeIndex(), context))->add(other, context);
    } else if (other->getPrimitiveTypeIndex() == AnyAtomicType::FLOAT) {
        // same primitive type, can make comparison
        ATFloatOrDerivedImpl* otherImpl = (ATFloatOrDerivedImpl*)(const Numeric*)other;
        if(otherImpl->_state == NaN) return notANumber(context);

        switch (_state) {
        case NaN:
            return notANumber(context);
        case INF: {
            switch(otherImpl->_state) {
            case NaN:
                return notANumber(context);       // case taken care of above
            case NEG_NUM:
            case NUM:
                return infinity(context);         // INF + NUM = INF
            case INF:
                return infinity(context);         // INF + INF = INF
            case NEG_INF:
                return notANumber(context);   // INF + (-INF) = NaN
            default:
                assert(false);
                return 0; // should never get here
            }
        }
        case NEG_INF: {
            switch(otherImpl->_state) {
            case NaN:
                return notANumber(context);          //case taken care of above
            case NEG_NUM:
            case NUM:
                return negInfinity(context);         // -INF + NUM = -INF
            case INF:
                return notANumber(context);          // -INF + INF = NaN
            case NEG_INF:
                return negInfinity(context);     // -INF + (-INF) = -INF
            default:
                assert(false);
                return 0; // should never get here
            }
        }
        case NEG_NUM:
        case NUM: {
            switch(otherImpl->_state) {
            case NaN:
                return notANumber(context); // case taken care of above
            case INF:
                return infinity(context);
            case NEG_INF:
                return negInfinity(context);
            case NEG_NUM:
            case NUM:
            {
                // Handle positive and negative zero
                if(_float.sign()==0 && otherImpl->_float!=0)
                    return other;
                else if(_float.sign()!=0 && otherImpl->_float==0)
                    return this;
                else if(_float.sign()==0 && otherImpl->_float==0)
                {
                    if(_state==otherImpl->_state)
                        // sum of two zero of the same sign -> result is equal to any of the two items
                        return this;
                    else
                        // sum of two zero of different sign -> result is equal to +0
                        return newFloat(0, context);
                }
                return newFloat(_float + otherImpl->_float, context);
            }
            default:
                assert(false);
                return 0; // should never get here
            }
        }
        default:
            assert(false);
            return 0; // should never get here
        }
    } else {
        assert(false); // should never get here, numeric types are xs:decimal, xs:float, xs:integer and xs:double
        return 0;
    }
}