/** 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; } }
MAPM XQNumericLiteral::getValue() const { // Use the C API to copy our fake MAPM MAPM copy; m_apm_copy(const_cast<M_APM>(copy.c_struct()), const_cast<M_APM>(&value_)); return copy; }
/** 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); }
MAPM MAPM::operator--() { // m_apm_enter(); MAPM ret; m_apm_subtract_mt(ret.val(),cval(),MM_One); *this = ret; // m_apm_leave(); return *this; }
MAPM MAPM::operator++() { // m_apm_enter(); MAPM ret; m_apm_add_mt(ret.val(),cval(),MM_One); *this = ret; // m_apm_leave(); return *this; }
/** 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); }
ATDecimalOrDerived::Ptr ItemFactoryImpl::createNonNegativeInteger(const MAPM value, const DynamicContext* context) { if(value.is_integer() && value.sign() >= 0) { return new ATDecimalOrDerivedImpl(SchemaSymbols::fgURI_SCHEMAFORSCHEMA, SchemaSymbols::fgDT_NONNEGATIVEINTEGER, value, context); } return createDecimalOrDerived( SchemaSymbols::fgURI_SCHEMAFORSCHEMA, SchemaSymbols::fgDT_NONNEGATIVEINTEGER, value, context); }
/** Returns the arithmetic product of its operands as a Numeric */ Numeric::Ptr ATDecimalOrDerivedImpl::mod(const Numeric::Ptr &other, const DynamicContext* context) const { if(this->isOfType(other->getTypeURI(), other->getTypeName(), context)) { // if both are of the same type exactly, we can perform the modulo const ATDecimalOrDerivedImpl* otherImpl = (ATDecimalOrDerivedImpl*)(const Numeric*)other; if(otherImpl->isZero()) { XQThrow2(::IllegalArgumentException, X("ATDecimalOrDerivedImpl::mod"), X("Division by zero [err:FOAR0001]")); } MAPM result = _decimal; MAPM r; r = result.integer_divide(otherImpl->_decimal); result -= r * otherImpl->_decimal; // if integer, return xs:integer, otherwise xs:decimal if(_isInteger) { return context->getItemFactory()->createInteger(result, context); } return context->getItemFactory()->createDecimal(result, context); } else if(this->getPrimitiveTypeIndex() != other->getPrimitiveTypeIndex()) { // if other is not a decimal, then we need to promote this to a float or double return ((const Numeric::Ptr )this->castAs(other->getPrimitiveTypeIndex(), context))->mod(other, context); } else if (this->isInstanceOfType(other->getTypeURI(), other->getTypeName(), context)) { // here we know we have two decimals, and this is 'lower' in the hierarchy than other // so cast this to other's type return ((const Numeric::Ptr )this->castAs(AnyAtomicType::DECIMAL, other->getTypeURI(), other->getTypeName(), context))->mod(other, context); } else if (other->isInstanceOfType(this->getTypeURI(), this->getTypeName(), context)) { // here we have two decimals, and this is 'higher' in the hierarchy than other // so cast other to this' type return this->mod((const Numeric::Ptr )other->castAs(AnyAtomicType::DECIMAL, this->getTypeURI(), this->getTypeName(), context), context); } else { // we have two separate branches. if either is instance of integer, cast it to integer, otherwise, cast to decimal // revisit: this is not the prettiest way to do it. You would want to go up the tree one by one instead of // jumping to integer and decimal ATDecimalOrDerived::Ptr first; ATDecimalOrDerived::Ptr second; if(this->_isInteger) { first = (const ATDecimalOrDerived::Ptr )this->castAs(AnyAtomicType::DECIMAL, SchemaSymbols::fgURI_SCHEMAFORSCHEMA, SchemaSymbols::fgDT_INTEGER, context); } else { first = (const ATDecimalOrDerived::Ptr )this->castAs(AnyAtomicType::DECIMAL, context); } if(((ATDecimalOrDerivedImpl*)(const Numeric*)other)->_isInteger) { second = (const ATDecimalOrDerived::Ptr )other->castAs(AnyAtomicType::DECIMAL, SchemaSymbols::fgURI_SCHEMAFORSCHEMA, SchemaSymbols::fgDT_INTEGER, context); } else { second = (const ATDecimalOrDerived::Ptr )other->castAs(AnyAtomicType::DECIMAL, context); } return first->mod(second, context); } }
MAPM DateUtils::convertDMY2Absolute(MAPM day, MAPM month, MAPM year) { MAPM prevYear = year - 1; if(year.sign() < 0) ++prevYear; MAPM absolute = ( prevYear * 365 ) + prevYear.integer_divide(4) - prevYear.integer_divide(100) + prevYear.integer_divide(400); if(isLeapYear(year)) absolute+=days_before_month_leap[asInt(month)-1]; else absolute+=days_before_month[asInt(month)-1]; absolute+= day; return absolute - 1; }
int MAPM::digits(const MAPM &otherVal) const { int maxd=myDigits(); int his=m_apm_significant_digits_mt(otherVal.cval()); if (maxd<his) maxd=his; return maxd; }
/** 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 } } }
int DateUtils::asInt(MAPM num) { if(num < INT_MIN || num > INT_MAX) { XQThrow2(XPath2TypeCastException, X("DateUtils::asInt"), X("Invalid representation of an int [err:FORG0001]")); } else { return (int)num.toDouble(); } }
/** 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); }
void DateUtils::formatNumber(const MAPM &value, int minDigits, XMLBuffer &buffer) { char obuf[1024]; value.toIntegerString(obuf); char *str = obuf; if(value.sign() < 0) { ++str; buffer.append(chDash); } size_t length = strlen(str); for(int i = (int)length; i < minDigits; ++i) { buffer.append(chDigit_0); } buffer.append(X(str)); }
ATDecimalOrDerived::Ptr ItemFactoryImpl::createInteger(const MAPM value, const DynamicContext* context) { if(value.is_integer()) { return new ATDecimalOrDerivedImpl(SchemaSymbols::fgURI_SCHEMAFORSCHEMA, SchemaSymbols::fgDT_INTEGER, value, context); } return createDecimalOrDerived( SchemaSymbols::fgURI_SCHEMAFORSCHEMA, SchemaSymbols::fgDT_INTEGER, value, context); }
ATFloatOrDerivedImpl:: ATFloatOrDerivedImpl(const XMLCh* typeURI, const XMLCh* typeName, const MAPM value, const StaticContext* context): ATFloatOrDerived(), _typeName(typeName), _typeURI(typeURI) { _float = value; _state = NUM; if (value.sign() < 0) _state = NEG_NUM; checkFloatLimits(_state, _float); }
wxString pgsDateTimeGen::random() { // Get a random number representing seconds MAPM result = pgsMapm::pgs_str_mapm(m_randomizer->random()), quot, rem; // Use hours and seconds for avoiding overflows of seconds result.integer_div_rem(3600, quot, rem); long hours, seconds; pgsMapm::pgs_mapm_str(quot, true).ToLong(&hours); pgsMapm::pgs_mapm_str(rem, true).ToLong(&seconds); wxTimeSpan time_span(hours, 0, seconds, 0); // Add the TimeSpan to the MinDate wxDateTime aux_min(m_min); aux_min.Add(time_span); // Post conditions wxASSERT(aux_min.IsLaterThan(m_min) || aux_min.IsEqualTo(m_min)); wxASSERT(aux_min.IsEarlierThan(m_max) || aux_min.IsEqualTo(m_max)); return aux_min.Format(wxT("%Y-%m-%d %H:%M:%S")); }
XQNumericLiteral::XQNumericLiteral(const XMLCh* typeURI, const XMLCh* typeName, const MAPM &value, AnyAtomicType::AtomicObjectType primitiveType, XPath2MemoryManager* memMgr) : ASTNodeImpl(NUMERIC_LITERAL, memMgr), typeURI_(typeURI), typeName_(typeName), primitiveType_(primitiveType) { _src.getStaticType() = StaticType::create(primitiveType_); memset(&value_, 0, sizeof(value_)); const M_APM cval = value.c_struct(); value_.m_apm_datalength = cval->m_apm_datalength; value_.m_apm_exponent = cval->m_apm_exponent; value_.m_apm_sign = cval->m_apm_sign; int len = (cval->m_apm_datalength + 1) >> 1; value_.m_apm_data = (UCHAR*)memMgr->allocate(len); memcpy(value_.m_apm_data, cval->m_apm_data, len); }
MAPM::MAPM(const MAPM &m) { myVal=(M_APM)m.cval(); ref(myVal); }
MAPM MAPM::gcd(const MAPM &m) const { MAPM ret; m_apm_gcd_mt(ret.val(),cval(),m.cval()); return ret; }
void DateUtils::convertAbsolute2DMY(MAPM absolute, MAPM& day, MAPM& month, MAPM& year) { absolute += 1; bool bc = absolute.sign() <= 0; bool fix = false; MAPM div, rem; absolute.integer_div_rem(days_in_400_years, div, rem); year = div * 400; absolute = rem; absolute.integer_div_rem(days_in_100_years, div, rem); if(div <= -4) fix = true; if(div >= 4) { div -= 1; rem += days_in_100_years; } year += div * 100; absolute = rem; absolute.integer_div_rem(days_in_4_years, div, rem); year += div * 4; absolute = rem; absolute.integer_div_rem(days_in_1_years, div, rem); if(div <= -4) fix = true; if(div >= 4) { div -= 1; rem += days_in_1_years; } year += div; absolute = rem; if(bc) { if(fix && absolute.sign() == 0) { // Correct off by one error in year calculations // due to negative leap years absolute += 1; } else { --year; absolute += daysInYear(year); } } else { if(absolute.sign() != 0) { ++year; } } month = 12; day = 31; int *days = isLeapYear(year) ? days_before_month_leap : days_before_month; for(int i = 11; i >= 0; --i) { if(absolute > days[i]) { month = i + 1; day = absolute - days[i]; break; } } }
MAPM MAPM::lcm(const MAPM &m) const { MAPM ret; m_apm_lcm_mt(ret.val(),cval(),m.cval()); return ret; }
MAPM MAPM::ceil(void) const { MAPM ret; m_apm_ceil_mt(ret.val(),cval()); return ret; }
MAPM MAPM::random(void) { MAPM ret; m_apm_get_random_mt(ret.val()); return ret; }
void MAPM::integer_div_rem(const MAPM &denom,MAPM ",MAPM &rem) const { m_apm_integer_div_rem_mt(quot.val(),rem.val(),cval(),denom.cval()); }
MAPM MAPM::integer_divide(const MAPM &denom) const { MAPM ret; m_apm_integer_divide_mt(ret.val(),cval(),denom.cval()); return ret; }
MAPM MAPM::ipow_nr(int p) const { MAPM ret; m_apm_integer_pow_nr_mt(ret.val(),cval(),p); return ret; }
MAPM MAPM::factorial(void) const { MAPM ret; m_apm_factorial_mt(ret.val(),cval()); return ret; }
MAPM MAPM::ipow(int p,int toDigits) const { MAPM ret; m_apm_integer_pow_mt(ret.val(),toDigits,cval(),p); return ret; }
MAPM MAPM::floor(void) const { MAPM ret; m_apm_floor_mt(ret.val(),cval()); return ret; }