/****************************************************************************+ −
**+ −
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).+ −
** All rights reserved.+ −
** Contact: Nokia Corporation (qt-info@nokia.com)+ −
**+ −
** This file is part of the QtXmlPatterns module of the Qt Toolkit.+ −
**+ −
** $QT_BEGIN_LICENSE:LGPL$+ −
** No Commercial Usage+ −
** This file contains pre-release code and may not be distributed.+ −
** You may use this file in accordance with the terms and conditions+ −
** contained in the Technology Preview License Agreement accompanying+ −
** this package.+ −
**+ −
** GNU Lesser General Public License Usage+ −
** Alternatively, this file may be used under the terms of the GNU Lesser+ −
** General Public License version 2.1 as published by the Free Software+ −
** Foundation and appearing in the file LICENSE.LGPL included in the+ −
** packaging of this file. Please review the following information to+ −
** ensure the GNU Lesser General Public License version 2.1 requirements+ −
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.+ −
**+ −
** In addition, as a special exception, Nokia gives you certain additional+ −
** rights. These rights are described in the Nokia Qt LGPL Exception+ −
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.+ −
**+ −
** If you have questions regarding the use of this file, please contact+ −
** Nokia at qt-info@nokia.com.+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
**+ −
** $QT_END_LICENSE$+ −
**+ −
****************************************************************************/+ −
+ −
/**+ −
* @file+ −
* @short This file is included by qabstractfloat_p.h.+ −
* If you need includes in this file, put them in qabstractfloat_p.h, outside of the namespace.+ −
*/+ −
+ −
template <const bool isDouble>+ −
AbstractFloat<isDouble>::AbstractFloat(const xsDouble num) : m_value(num)+ −
{+ −
}+ −
+ −
template <const bool isDouble>+ −
Numeric::Ptr AbstractFloat<isDouble>::fromValue(const xsDouble num)+ −
{+ −
return Numeric::Ptr(new AbstractFloat<isDouble>(num));+ −
}+ −
+ −
template <const bool isDouble>+ −
AtomicValue::Ptr AbstractFloat<isDouble>::fromLexical(const QString &strNumeric)+ −
{+ −
/* QString::toDouble() handles the whitespace facet. */+ −
+ −
if(strNumeric == QLatin1String("NaN"))+ −
return isDouble ? CommonValues::DoubleNaN : CommonValues::FloatNaN;+ −
else if(strNumeric == QLatin1String("-INF"))+ −
return isDouble ? CommonValues::NegativeInfDouble : CommonValues::NegativeInfFloat;+ −
else if(strNumeric == QLatin1String("INF"))+ −
return isDouble ? CommonValues::InfDouble : CommonValues::InfFloat;+ −
+ −
/* QString::toDouble() supports any case as well as +INF, but we don't. */+ −
const QString toUpper(strNumeric.toUpper());+ −
if(toUpper == QLatin1String("-INF") ||+ −
toUpper == QLatin1String("INF") ||+ −
toUpper == QLatin1String("+INF") ||+ −
toUpper == QLatin1String("NAN"))+ −
{+ −
return ValidationError::createError();+ −
}+ −
+ −
bool conversionOk = false;+ −
const xsDouble num = strNumeric.toDouble(&conversionOk);+ −
+ −
if(conversionOk)+ −
return AtomicValue::Ptr(new AbstractFloat<isDouble>(num));+ −
else+ −
return ValidationError::createError();+ −
}+ −
+ −
template <const bool isDouble>+ −
int AbstractFloat<isDouble>::internalSignbit(const xsDouble num)+ −
{+ −
Q_ASSERT_X(sizeof(xsDouble) == 8 || sizeof(xsDouble) == 4, Q_FUNC_INFO,+ −
"This implementation of signbit assumes xsDouble, that is qreal, is 64 bits large.");+ −
+ −
union+ −
{+ −
xsDouble asDouble;+ −
qint64 asInt;+ −
} value;+ −
+ −
value.asDouble = num;+ −
+ −
/* The highest bit, the 64'th for those who have 64bit floats, is the sign bit. So we pull it down until that bit is the+ −
* only one left. */+ −
if(sizeof(xsDouble) == 8)+ −
return value.asInt >> 63;+ −
else+ −
return value.asInt >> 31;+ −
}+ −
+ −
template <const bool isDouble>+ −
bool AbstractFloat<isDouble>::isEqual(const xsDouble a, const xsDouble b)+ −
{+ −
if(qIsInf(a))+ −
return qIsInf(b) && internalSignbit(a) == internalSignbit(b);+ −
else if(qIsInf(b))+ −
return qIsInf(a) && internalSignbit(a) == internalSignbit(b);+ −
else+ −
{+ −
/* Preferrably, we would use std::numeric_limits<xsDouble>::espilon(), but+ −
* we cannot since we cannot depend on the STL. The small xs:double value below,+ −
* was extracted by printing the std::numeric_limits<xsDouble>::epsilon() using+ −
* gdb. */+ −
return qAbs(a - b) <= 2.2204460492503131e-16 * qAbs(a);+ −
}+ −
}+ −
+ −
template <const bool isDouble>+ −
bool AbstractFloat<isDouble>::isZero() const+ −
{+ −
return AbstractFloat<isDouble>::isEqual(m_value, 0.0);+ −
}+ −
+ −
template <const bool isDouble>+ −
bool AbstractFloat<isDouble>::evaluateEBV(const QExplicitlySharedDataPointer<DynamicContext> &) const+ −
{+ −
if(isZero() || qIsNaN(m_value))+ −
return false;+ −
else+ −
return true;+ −
}+ −
+ −
template <const bool isDouble>+ −
QString AbstractFloat<isDouble>::stringValue() const+ −
{+ −
if(qIsNaN(m_value))+ −
return QLatin1String("NaN");+ −
else if(qIsInf(m_value))+ −
return internalSignbit(m_value) == 0 ? QLatin1String("INF") : QLatin1String("-INF");+ −
/*+ −
* If SV has an absolute value that is greater than or equal to 0.000001+ −
* (one millionth) and less than 1000000 (one million),+ −
* then the value is converted to an xs:decimal and the resulting xs:decimal+ −
* is converted to an xs:string according to the rules above.+ −
*/+ −
else if(0.000001 <= qAbs(m_value) && qAbs(m_value) < 1000000.0)+ −
return Decimal::toString(toDecimal());+ −
/*+ −
* If SV has the value positive or negative zero, TV is "0" or "-0" respectively.+ −
*/+ −
else if(isZero())+ −
return internalSignbit(m_value) == 0 ? QLatin1String("0") : QLatin1String("-0");+ −
else+ −
{+ −
/*+ −
* Besides these special values, the general form of the canonical form for+ −
* xs:float and xs:double is a mantissa, which is a xs:decimal, followed by+ −
* the letter "E", followed by an exponent which is an xs:integer.+ −
*/+ −
int sign;+ −
int decimalPoint;+ −
char *result = 0;+ −
static_cast<void>(qdtoa(m_value, -1, 0, &decimalPoint, &sign, 0, &result));+ −
+ −
/* If the copy constructor is used instead of QString::operator=(),+ −
* it doesn't compile. I have no idea why. */+ −
const QString qret(QString::fromLatin1(result));+ −
+ −
/* We use free() instead of delete here, because qlocale.cpp use malloc(). Spotted+ −
* by valgrind. */+ −
free(result);+ −
+ −
QString valueAsString;+ −
+ −
if(sign)+ −
valueAsString += QLatin1Char('-');+ −
+ −
valueAsString += qret.at(0);+ −
valueAsString += QLatin1Char('.');+ −
+ −
if(1 == qret.size())+ −
valueAsString += QLatin1Char('0');+ −
else+ −
valueAsString += qret.mid(1);+ −
+ −
valueAsString += QLatin1Char('E');+ −
decimalPoint--;+ −
valueAsString += QString::number(decimalPoint);+ −
return valueAsString;+ −
}+ −
}+ −
+ −
template <const bool isDouble>+ −
xsDouble AbstractFloat<isDouble>::toDouble() const+ −
{+ −
return m_value;+ −
}+ −
+ −
template <const bool isDouble>+ −
xsInteger AbstractFloat<isDouble>::toInteger() const+ −
{+ −
return static_cast<xsInteger>(m_value);+ −
}+ −
+ −
template <const bool isDouble>+ −
xsFloat AbstractFloat<isDouble>::toFloat() const+ −
{+ −
/* No cast, since xsFloat and xsDouble are typedef'ed with the same type. */+ −
return m_value;+ −
}+ −
+ −
template <const bool isDouble>+ −
xsDecimal AbstractFloat<isDouble>::toDecimal() const+ −
{+ −
return static_cast<xsDecimal>(m_value);+ −
}+ −
+ −
template <const bool isDouble>+ −
Numeric::Ptr AbstractFloat<isDouble>::round() const+ −
{+ −
return AbstractFloat<isDouble>::fromValue(static_cast<xsDouble>(roundFloat(m_value)));+ −
}+ −
+ −
template <const bool isDouble>+ −
Numeric::Ptr AbstractFloat<isDouble>::roundHalfToEven(const xsInteger precision) const+ −
{+ −
if(isNaN() || isInf() || isZero())+ −
return Numeric::Ptr(const_cast<AbstractFloat<isDouble> *>(this));+ −
else+ −
{+ −
/* The cast to double helps finding the correct pow() version on irix-cc. */+ −
const xsDouble powered = pow(double(10), double(precision));+ −
xsDouble val = powered * m_value;+ −
bool isHalf = false;+ −
+ −
if(val - 0.5 == ::floor(val))+ −
isHalf = true;+ −
+ −
val = m_value * powered + 0.5;+ −
val = ::floor(val);+ −
+ −
if(isHalf /*&& isOdd(val) or? TODO */)+ −
val -= 1;+ −
+ −
val /= powered;+ −
+ −
return fromValue(val);+ −
}+ −
}+ −
+ −
template <const bool isDouble>+ −
Numeric::Ptr AbstractFloat<isDouble>::floor() const+ −
{+ −
return AbstractFloat<isDouble>::fromValue(static_cast<xsDouble>(::floor(m_value)));+ −
}+ −
+ −
template <const bool isDouble>+ −
Numeric::Ptr AbstractFloat<isDouble>::ceiling() const+ −
{+ −
return AbstractFloat<isDouble>::fromValue(static_cast<xsDouble>(ceil(m_value)));+ −
}+ −
+ −
template <const bool isDouble>+ −
Numeric::Ptr AbstractFloat<isDouble>::abs() const+ −
{+ −
/* We must use fabs() instead of qAbs() because qAbs()+ −
* doesn't return 0 for -0.0. */+ −
return AbstractFloat<isDouble>::fromValue(static_cast<xsDouble>(fabs(m_value)));+ −
}+ −
+ −
template <const bool isDouble>+ −
bool AbstractFloat<isDouble>::isNaN() const+ −
{+ −
return qIsNaN(m_value);+ −
}+ −
+ −
template <const bool isDouble>+ −
bool AbstractFloat<isDouble>::isInf() const+ −
{+ −
return qIsInf(m_value);+ −
}+ −
+ −
template <const bool isDouble>+ −
ItemType::Ptr AbstractFloat<isDouble>::type() const+ −
{+ −
return isDouble ? BuiltinTypes::xsDouble : BuiltinTypes::xsFloat;+ −
}+ −
+ −
template <const bool isDouble>+ −
Item AbstractFloat<isDouble>::toNegated() const+ −
{+ −
return fromValue(-m_value).data();+ −
}+ −
+ −
template <const bool isDouble>+ −
bool AbstractFloat<isDouble>::isSigned() const+ −
{+ −
Q_ASSERT_X(false, Q_FUNC_INFO,+ −
"It makes no sense to call this function, see Numeric::isSigned().");+ −
return false;+ −
}+ −
+ −
template <const bool isDouble>+ −
qulonglong AbstractFloat<isDouble>::toUnsignedInteger() const+ −
{+ −
Q_ASSERT_X(false, Q_FUNC_INFO,+ −
"It makes no sense to call this function, see Numeric::toUnsignedInteger().");+ −
return 0;+ −
}+ −
+ −