/** 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); } }
/** Returns a Numeric object which is the difference of this and * other */ Numeric::Ptr ATDecimalOrDerivedImpl::subtract(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 subtraction ATDecimalOrDerivedImpl* otherImpl = (ATDecimalOrDerivedImpl*)(const Numeric*)other; // if integer, return xs:integer, otherwise xs:decimal if(_isInteger) { return context->getItemFactory()->createInteger(_decimal - otherImpl->_decimal, context); } return context->getItemFactory()->createDecimal(_decimal - otherImpl->_decimal, 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))->subtract(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))->subtract(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->subtract((const Numeric::Ptr )other->castAs(AnyAtomicType::DECIMAL, getTypeURI(), 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->subtract(second, context); } }