summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.fetch1
-rw-r--r--RepositoryExternal.mk9
-rw-r--r--download.lst2
-rw-r--r--external/Module_external.mk1
-rw-r--r--external/dragonbox/Module_dragonbox.mk16
-rw-r--r--external/dragonbox/README4
-rw-r--r--external/dragonbox/UnpackedTarball_dragonbox.mk14
-rw-r--r--readlicense_oo/license/license.xml21
-rw-r--r--sal/Library_sal.mk1
-rw-r--r--sal/qa/rtl/math/test-rtl-math.cxx13
-rw-r--r--sal/rtl/math.cxx288
-rw-r--r--sd/qa/unit/export-tests-ooxml2.cxx2
12 files changed, 146 insertions, 226 deletions
diff --git a/Makefile.fetch b/Makefile.fetch
index 78ff78b9e312..af6f0ce7aa5f 100644
--- a/Makefile.fetch
+++ b/Makefile.fetch
@@ -110,6 +110,7 @@ $(WORKDIR)/download: $(BUILDDIR)/config_$(gb_Side).mk $(SRCDIR)/download.lst $(S
$(call fetch_Optional,CAIRO,PIXMAN_TARBALL) \
$(call fetch_Optional,CDR,CDR_TARBALL) \
$(call fetch_Optional,CLUCENE,CLUCENE_TARBALL) \
+ DRAGONBOX_TARBALL \
DTOA_TARBALL \
$(call fetch_Optional,LIBCMIS,LIBCMIS_TARBALL) \
$(call fetch_Optional,COINMP,COINMP_TARBALL) \
diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index 2e7e86266e34..779e318ebc49 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -4132,6 +4132,15 @@ $(eval $(call gb_Helper_register_libraries_for_install,OOOLIBS,ooo,\
))
endif
+define gb_LinkTarget__use_dragonbox
+$(call gb_LinkTarget_use_unpacked,$(1),dragonbox)
+$(call gb_LinkTarget_set_include,$(1),\
+ -I$(call gb_UnpackedTarball_get_dir,dragonbox/include/)\
+ $$(INCLUDE) \
+)
+
+endef
+
define gb_LinkTarget__use_dtoa
$(call gb_LinkTarget_use_unpacked,$(1),dtoa)
$(call gb_LinkTarget_set_include,$(1),\
diff --git a/download.lst b/download.lst
index 33842d7282ee..bb4d12649d8f 100644
--- a/download.lst
+++ b/download.lst
@@ -23,6 +23,8 @@ export CDR_SHA256SUM := 5666249d613466b9aa1e987ea4109c04365866e9277d80f6cd9663e8
export CDR_TARBALL := libcdr-0.1.7.tar.xz
export CLUCENE_SHA256SUM := ddfdc433dd8ad31b5c5819cc4404a8d2127472a3b720d3e744e8c51d79732eab
export CLUCENE_TARBALL := 48d647fbd8ef8889e5a7f422c1bfda94-clucene-core-2.3.3.4.tar.gz
+export DRAGONBOX_SHA256SUM := 293247ccba995ec47ae3abb52c3e83904a7d71efb7093d4c0d2c6367c1cc1e20
+export DRAGONBOX_TARBALL := dragonbox-1.1.0.tar.gz
export DTOA_SHA256SUM := 0082d0684f7db6f62361b76c4b7faba19e0c7ce5cb8e36c4b65fea8281e711b4
export DTOA_TARBALL := dtoa-20180411.tgz
export LIBCMIS_SHA256SUM := d7b18d9602190e10d437f8a964a32e983afd57e2db316a07d87477a79f5000a2
diff --git a/external/Module_external.mk b/external/Module_external.mk
index 946b9dd16ed7..5420092797a1 100644
--- a/external/Module_external.mk
+++ b/external/Module_external.mk
@@ -30,6 +30,7 @@ $(eval $(call gb_Module_add_moduledirs,external,\
$(call gb_Helper_optional,CPPUNIT,cppunit) \
$(call gb_Helper_optional,CT2N,ct2n) \
$(call gb_Helper_optional,CURL,curl) \
+ dragonbox \
dtoa \
$(call gb_Helper_optional,EBOOK,libebook) \
$(call gb_Helper_optional,EPM,epm) \
diff --git a/external/dragonbox/Module_dragonbox.mk b/external/dragonbox/Module_dragonbox.mk
new file mode 100644
index 000000000000..2ed608f1e5e8
--- /dev/null
+++ b/external/dragonbox/Module_dragonbox.mk
@@ -0,0 +1,16 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Module_Module,dragonbox))
+
+$(eval $(call gb_Module_add_targets,dragonbox,\
+ UnpackedTarball_dragonbox \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/dragonbox/README b/external/dragonbox/README
new file mode 100644
index 000000000000..28db2711b9e4
--- /dev/null
+++ b/external/dragonbox/README
@@ -0,0 +1,4 @@
+Dragonbox is available from [ https://github.com/jk-jeon/dragonbox ].
+
+Used to convert a double to a decimal string, providing breakout of significand and exponent
+as integers, allowing to create custom number representation (e.g., locale-specific).
diff --git a/external/dragonbox/UnpackedTarball_dragonbox.mk b/external/dragonbox/UnpackedTarball_dragonbox.mk
new file mode 100644
index 000000000000..c483f19a3c56
--- /dev/null
+++ b/external/dragonbox/UnpackedTarball_dragonbox.mk
@@ -0,0 +1,14 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_UnpackedTarball_UnpackedTarball,dragonbox))
+
+$(eval $(call gb_UnpackedTarball_set_tarball,dragonbox,$(DRAGONBOX_TARBALL)))
+
+# vim: set noet sw=4 ts=4:
diff --git a/readlicense_oo/license/license.xml b/readlicense_oo/license/license.xml
index 56b36c71fa02..f0a2484b8acb 100644
--- a/readlicense_oo/license/license.xml
+++ b/readlicense_oo/license/license.xml
@@ -1844,6 +1844,27 @@
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.</p>
</div>
+ <h2>Dragonbox</h2>
+ <p>The following software may be included in this product: Dragonbox.</p>
+ <p>Dragonbox code is covered by the following license:</p>
+ <p><a href="#a__Apache_License_version_2_0">Jump to Apache License Version 2.0</a></p>
+ <blockquote>
+ <p>--- LLVM Exceptions to the Apache 2.0 License ----</p>
+
+ <p>As an exception, if, as a result of your compiling your source code, portions
+ of this Software are embedded into an Object form of such source code, you
+ may redistribute such embedded portions in such Object form without complying
+ with the conditions of Sections 4(a), 4(b) and 4(d) of the License.</p>
+
+ <p>In addition, if you combine or link compiled forms of this Software with
+ software that is licensed under the GPLv2 ("Combined Software") and if a
+ court of competent jurisdiction determines that the patent provision (Section
+ 3), the indemnity provision (Section 9) or other Section of the License
+ conflicts with the conditions of the GPLv2, you may retroactively and
+ prospectively choose to deem waived or otherwise exclude such Section(s) of
+ the License, but only in their entirety and only with respect to the Combined
+ Software.</p>
+ </blockquote>
<h2>dtoa</h2>
<p>The following software may be included in this product: dtoa.</p>
<p>dtoa code is covered by the MIT license:</p>
diff --git a/sal/Library_sal.mk b/sal/Library_sal.mk
index d8d409195a39..aae7c97f0310 100644
--- a/sal/Library_sal.mk
+++ b/sal/Library_sal.mk
@@ -43,6 +43,7 @@ $(eval $(call gb_Library_use_libraries,sal,\
))
$(eval $(call gb_Library_use_externals,sal,\
+ dragonbox \
dtoa \
valgrind \
zlib \
diff --git a/sal/qa/rtl/math/test-rtl-math.cxx b/sal/qa/rtl/math/test-rtl-math.cxx
index aaadccc8e97c..94840dbdb7e8 100644
--- a/sal/qa/rtl/math/test-rtl-math.cxx
+++ b/sal/qa/rtl/math/test-rtl-math.cxx
@@ -432,7 +432,8 @@ public:
fVal = std::nextafter( fVal, 0);
aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic,
rtl_math_DecimalPlaces_Max, '.', true);
- CPPUNIT_ASSERT_EQUAL( OUString("1.7976931348623149E+308"), aRes);
+ CPPUNIT_ASSERT_EQUAL( OUString("1.797693134862315E+308"), aRes);
+ CPPUNIT_ASSERT_EQUAL(fVal, rtl::math::stringToDouble(aRes, '.', ',')); // Test roundtrip
// DBL_MAX and 4 nextafters rounded to 15 decimals
fVal = DBL_MAX;
@@ -463,24 +464,20 @@ public:
// DBL_MAX rounded to 2 decimals
fVal = DBL_MAX;
aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic, 2, '.', true);
- CPPUNIT_ASSERT_EQUAL( OUString("1.80E+308"), aRes);
+ CPPUNIT_ASSERT_EQUAL( OUString("1.8E+308"), aRes);
// Crashed after commit eae24a9488814e77254d175c11fc4a138c1dbd30
fVal = 123456.789;
aRes = rtl::math::doubleToUString(fVal, rtl_math_StringFormat_E, 2, '.', false);
CPPUNIT_ASSERT_EQUAL(OUString("1.23E+005"), aRes);
- // Testing "after-treatment of up-rounding to the next decade" branch
- // See void doubleToString in sal/rtl/math.cxx
- // 1. Yet empty buffer
fVal = 9.9999999999999929;
aRes = rtl::math::doubleToUString(fVal, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
- CPPUNIT_ASSERT_EQUAL(OUString("10"), aRes);
+ CPPUNIT_ASSERT_EQUAL(OUString("9.99999999999999"), aRes);
- // 2. Buffer with some content
fVal = 0.99999999999999933;
aRes = rtl::math::doubleToUString(fVal, rtl_math_StringFormat_F, rtl_math_DecimalPlaces_Max, '.', true);
- CPPUNIT_ASSERT_EQUAL(OUString("1"), aRes);
+ CPPUNIT_ASSERT_EQUAL(OUString("0.999999999999999"), aRes);
}
void test_approx() {
diff --git a/sal/rtl/math.cxx b/sal/rtl/math.cxx
index bec83c380b32..edb894cb7820 100644
--- a/sal/rtl/math.cxx
+++ b/sal/rtl/math.cxx
@@ -19,6 +19,7 @@
#include <rtl/math.h>
+#include <o3tl/safeint.hxx>
#include <osl/diagnose.h>
#include <rtl/character.hxx>
#include <rtl/math.hxx>
@@ -34,6 +35,7 @@
#include <memory>
#include <stdlib.h>
+#include <dragonbox/dragonbox.h>
#include <dtoa.h>
constexpr int minExp = -323, maxExp = 308;
@@ -104,11 +106,6 @@ static double getN10Exp(int nExp)
namespace {
-double const nCorrVal[] = {
- 0, 9e-1, 9e-2, 9e-3, 9e-4, 9e-5, 9e-6, 9e-7, 9e-8,
- 9e-9, 9e-10, 9e-11, 9e-12, 9e-13, 9e-14, 9e-15
-};
-
struct StringTraits
{
typedef char Char;
@@ -245,6 +242,38 @@ int getBitsInFracPart(double fAbsValue)
return std::max(nBitsInFracPart, 0);
}
+constexpr sal_uInt64 eX[] = { 10ull,
+ 100ull,
+ 1000ull,
+ 10000ull,
+ 100000ull,
+ 1000000ull,
+ 10000000ull,
+ 100000000ull,
+ 1000000000ull,
+ 10000000000ull,
+ 100000000000ull,
+ 1000000000000ull,
+ 10000000000000ull,
+ 100000000000000ull,
+ 1000000000000000ull,
+ 10000000000000000ull,
+ 100000000000000000ull,
+ 1000000000000000000ull,
+ 10000000000000000000ull };
+
+int decimalDigits(sal_uInt64 n)
+{
+ return std::distance(std::begin(eX), std::upper_bound(std::begin(eX), std::end(eX), n)) + 1;
+}
+
+sal_uInt64 roundToPow10(sal_uInt64 n, int e)
+{
+ assert(e > 0 && o3tl::make_unsigned(e) <= std::size(eX));
+ const sal_uInt64 d = eX[e - 1];
+ return (n + d / 2) / d * d;
+}
+
template< typename T >
void doubleToString(typename T::String ** pResult,
sal_Int32 * pResultCapacity, sal_Int32 nResultOffset,
@@ -254,18 +283,6 @@ void doubleToString(typename T::String ** pResult,
typename T::Char cGroupSeparator,
bool bEraseTrailingDecZeros)
{
- static double const nRoundVal[] = {
- 5.0e+0, 0.5e+0, 0.5e-1, 0.5e-2, 0.5e-3, 0.5e-4, 0.5e-5, 0.5e-6,
- 0.5e-7, 0.5e-8, 0.5e-9, 0.5e-10,0.5e-11,0.5e-12,0.5e-13,0.5e-14
- };
-
- // sign adjustment, instead of testing for fValue<0.0 this will also fetch
- // -0.0
- bool bSign = std::signbit(fValue);
-
- if (bSign)
- fValue = -fValue;
-
if (std::isnan(fValue))
{
// #i112652# XMLSchema-2
@@ -283,8 +300,7 @@ void doubleToString(typename T::String ** pResult,
return;
}
- bool bHuge = fValue == HUGE_VAL; // g++ 3.0.1 requires it this way...
- if (bHuge || std::isinf(fValue))
+ if (std::isinf(fValue))
{
// #i112652# XMLSchema-2
sal_Int32 nCapacity = RTL_CONSTASCII_LENGTH("-INF");
@@ -295,7 +311,7 @@ void doubleToString(typename T::String ** pResult,
nResultOffset = 0;
}
- if ( bSign )
+ if (std::signbit(fValue))
T::appendAscii(pResult, pResultCapacity, &nResultOffset,
RTL_CONSTASCII_STRINGPARAM("-"));
@@ -305,6 +321,18 @@ void doubleToString(typename T::String ** pResult,
return;
}
+ decltype(jkj::dragonbox::to_decimal(fValue)) aParts{};
+ if (fValue) // to_decimal is documented to only handle non-zero finite numbers
+ aParts = jkj::dragonbox::to_decimal(fValue);
+ else
+ aParts.is_negative = std::signbit(fValue); // Handle -0.0
+
+ int nOrigDigits = decimalDigits(aParts.significand);
+ int nExp = nOrigDigits + aParts.exponent - 1;
+ int nRoundDigits = 15;
+ if (aParts.is_negative)
+ fValue = -fValue;
+
// Unfortunately the old rounding below writes 1.79769313486232e+308 for
// DBL_MAX and 4 subsequent nextafter(...,0).
static const double fB1 = std::nextafter( DBL_MAX, 0);
@@ -318,77 +346,17 @@ void doubleToString(typename T::String ** pResult,
// they exceed range they should not be written to exchange strings or
// file formats.
- // Writing pDig up to decimals(-1,-2) then appending one digit from
- // pRou xor one or two digits from pSlot[].
- constexpr char pDig[] = "7976931348623157";
- constexpr char pRou[] = "8087931359623267"; // the only up-carry is 80
- static_assert(SAL_N_ELEMENTS(pDig) == SAL_N_ELEMENTS(pRou), "digit count mismatch");
- constexpr sal_Int32 nDig2 = RTL_CONSTASCII_LENGTH(pRou) - 2;
- sal_Int32 nCapacity = RTL_CONSTASCII_LENGTH(pRou) + 8; // + "-1.E+308"
- const char pSlot[5][2][3] =
- { // rounded, not
- "67", "57", // DBL_MAX
- "65", "55",
- "53", "53",
- "51", "51",
- "59", "49",
- };
-
- if (!pResultCapacity)
- {
- pResultCapacity = &nCapacity;
- T::createBuffer(pResult, pResultCapacity);
- nResultOffset = 0;
- }
-
- if (bSign)
- T::appendAscii(pResult, pResultCapacity, &nResultOffset,
- RTL_CONSTASCII_STRINGPARAM("-"));
-
- nDecPlaces = std::clamp<sal_Int32>( nDecPlaces, 0, RTL_CONSTASCII_LENGTH(pRou));
- if (nDecPlaces == 0)
- {
- T::appendAscii(pResult, pResultCapacity, &nResultOffset,
- RTL_CONSTASCII_STRINGPARAM("2"));
- }
- else
- {
- T::appendAscii(pResult, pResultCapacity, &nResultOffset,
- RTL_CONSTASCII_STRINGPARAM("1"));
- T::appendChars(pResult, pResultCapacity, &nResultOffset, &cDecSeparator, 1);
- if (nDecPlaces <= 2)
- {
- T::appendAscii(pResult, pResultCapacity, &nResultOffset, pRou, nDecPlaces);
- }
- else if (nDecPlaces <= nDig2)
- {
- T::appendAscii(pResult, pResultCapacity, &nResultOffset, pDig, nDecPlaces - 1);
- T::appendAscii(pResult, pResultCapacity, &nResultOffset, pRou + nDecPlaces - 1, 1);
- }
- else
- {
- const sal_Int32 nDec = nDecPlaces - nDig2;
- nDecPlaces -= nDec;
- // nDec-1 is also offset into slot, rounded(1-1=0) or not(2-1=1)
- const size_t nSlot = ((fValue < fB3) ? 4 : ((fValue < fB2) ? 3
- : ((fValue < fB1) ? 2 : ((fValue < DBL_MAX) ? 1 : 0))));
-
- T::appendAscii(pResult, pResultCapacity, &nResultOffset, pDig, nDecPlaces);
- T::appendAscii(pResult, pResultCapacity, &nResultOffset, pSlot[nSlot][nDec-1], nDec);
- }
- }
- T::appendAscii(pResult, pResultCapacity, &nResultOffset,
- RTL_CONSTASCII_STRINGPARAM("E+308"));
-
- return;
+ eFormat = rtl_math_StringFormat_E;
+ nDecPlaces = std::clamp<sal_Int32>( nDecPlaces, 0, 16);
+ nRoundDigits = 17;
}
// Use integer representation for integer values that fit into the
// mantissa (1.((2^53)-1)) with a precision of 1 for highest accuracy.
if ((eFormat == rtl_math_StringFormat_Automatic ||
- eFormat == rtl_math_StringFormat_F) && isRepresentableInteger(fValue))
+ eFormat == rtl_math_StringFormat_F) && aParts.exponent >= 0 && fValue < 0x1p53)
{
- sal_Int64 nInt = static_cast< sal_Int64 >(fValue);
+ eFormat = rtl_math_StringFormat_F;
if (nDecPlaces == rtl_math_DecimalPlaces_Max)
nDecPlaces = 0;
else
@@ -397,68 +365,7 @@ void doubleToString(typename T::String ** pResult,
if (bEraseTrailingDecZeros && nDecPlaces > 0)
nDecPlaces = 0;
- // Round before decimal position.
- if (nDecPlaces < 0)
- {
- sal_Int64 nRounding = static_cast< sal_Int64 >(getN10Exp(-nDecPlaces - 1));
- const sal_Int64 nTemp = (nInt / nRounding + 5) / 10;
- nInt = nTemp * 10 * nRounding;
- }
-
- // Max 1 sign, 16 integer digits, 15 group separators, 1 decimal
- // separator, 15 decimals digits.
- typename T::Char aBuf[64];
- typename T::Char* pEnd = aBuf + 40;
- typename T::Char* pStart = pEnd;
-
- // Backward fill.
- sal_Int32 nGrouping = cGroupSeparator && pGroups ? *pGroups : 0;
- sal_Int32 nGroupDigits = 0;
- do
- {
- typename T::Char nDigit = nInt % 10;
- nInt /= 10;
- *--pStart = nDigit + '0';
- if (nGrouping && nGrouping == ++nGroupDigits && nInt)
- {
- *--pStart = cGroupSeparator;
- if (*(pGroups + 1))
- nGrouping = *++pGroups;
- nGroupDigits = 0;
- }
- }
- while (nInt);
- if (bSign)
- *--pStart = '-';
-
- // Append decimals.
- if (nDecPlaces > 0)
- {
- *pEnd++ = cDecSeparator;
- pEnd = std::fill_n(pEnd, nDecPlaces, '0');
- }
-
- if (!pResultCapacity)
- T::createString(pResult, pStart, pEnd - pStart);
- else
- T::appendChars(pResult, pResultCapacity, &nResultOffset, pStart, pEnd - pStart);
-
- return;
- }
-
- // find the exponent
- int nExp = 0;
- if ( fValue > 0.0 )
- {
- // Cap nExp at a small value beyond which "fValue /= N10Exp" would lose precision (or N10Exp
- // might even be zero); that will produce output with the decimal point in a non-normalized
- // position, but the current quality of output for such small values is probably abysmal,
- // anyway:
- nExp = std::max(
- static_cast< int >(floor(log10(fValue))), std::numeric_limits<double>::min_exponent10);
- double const N10Exp = getN10Exp(nExp);
- assert(N10Exp != 0);
- fValue /= N10Exp;
+ nRoundDigits = nOrigDigits; // no rounding
}
switch (eFormat)
@@ -531,12 +438,14 @@ void doubleToString(typename T::String ** pResult,
nDigits += nExp;
// Round the number
- if(nDigits >= 0)
+ nRoundDigits = std::min<int>(nDigits, nRoundDigits);
+ if(nDigits >= 0 && nOrigDigits > nRoundDigits)
{
- fValue += nRoundVal[std::min<sal_Int32>(nDigits, 15)];
- if (fValue >= 10)
+ aParts.significand = roundToPow10(aParts.significand, nOrigDigits - nRoundDigits);
+ assert(aParts.significand <= eX[nOrigDigits - 1]);
+ if (aParts.significand == eX[nOrigDigits - 1]) // up-rounding to the next decade
{
- fValue = 1.0;
+ nOrigDigits++;
nExp++;
if (eFormat == rtl_math_StringFormat_F)
@@ -552,7 +461,7 @@ void doubleToString(typename T::String ** pResult,
assert(nBuf <= 1024);
typename T::Char* pBuf = static_cast<typename T::Char*>(alloca(nBuf * sizeof(typename T::Char)));
typename T::Char * p = pBuf;
- if ( bSign )
+ if (aParts.is_negative)
*p++ = '-';
bool bHasDec = false;
@@ -612,77 +521,22 @@ void doubleToString(typename T::String ** pResult,
// print the number
if (nDigits > 0)
{
- for (int i = 0; ; i++)
+ for (int nCurExp = nOrigDigits - 1;;)
{
- if (i < 15) // was 16 in ancient versions, which leads to inaccuracies
+ int nDigit;
+ if (aParts.significand > 0 && nCurExp > 0)
{
- int nDigit;
- if (nDigits-1 == 0 && i > 0 && i < 14)
- nDigit = floor( fValue + nCorrVal[15-i]);
- else
- nDigit = fValue + 1E-15;
-
- if (nDigit >= 10)
- { // after-treatment of up-rounding to the next decade
- typename T::Char* p1 = pBuf;
- // Assert that no one changed the logic we rely on.
- assert(!bSign || *p1 == '-');
- // Do not touch leading minus sign put earlier.
- if (bSign)
- ++p1;
- assert(p1 <= p);
- if (p1 == p)
- {
- *p++ = '1';
- if (eFormat != rtl_math_StringFormat_F)
- {
- *p++ = cDecSeparator;
- nExp++;
- bHasDec = true;
- }
- *p++ = '0';
- }
- else
- {
- for (typename T::Char* p2 = p - 1; p2 >= p1; --p2)
- {
- typename T::Char cS = *p2;
- if (cS == cDecSeparator)
- continue;
- if (cS != '9')
- {
- ++*p2;
- break;
- }
- *p2 = '0';
- if (p2 == p1) // The number consisted of all 9s replaced to all 0s
- {
- if (eFormat == rtl_math_StringFormat_F)
- { // move everything to the right before inserting '1'
- std::memmove(p2 + 1, p2, (p++ - p2) * sizeof(*p));
- }
- else
- {
- nExp++;
- }
- *p2 = '1';
- }
- }
-
- *p++ = '0';
- }
- fValue = 0.0;
- }
- else
- {
- *p++ = nDigit + '0';
- fValue = (fValue - nDigit) * 10.0;
- }
+ --nCurExp;
+ nDigit = aParts.significand / eX[nCurExp];
+ aParts.significand %= eX[nCurExp];
}
else
{
- *p++ = '0';
+ nDigit = aParts.significand;
+ aParts.significand = 0;
}
+ assert(nDigit >= 0 && nDigit < 10);
+ *p++ = nDigit + '0';
if (!--nDigits)
break; // for
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx
index 4777845308c5..08326f923c0d 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -1632,7 +1632,7 @@ void SdOOXMLExportTest2::testTdf118825()
xmlDocUniquePtr pXmlDocContent = parseExport(tempFile, "ppt/slides/slide1.xml");
- CPPUNIT_ASSERT_MOTIONPATH("M 0.0449285714285714 0.00368253968253968 C 0.0575714285714285 -0.00095238095238096 0.0704264795523803 -0.00370117418637049 0.0831071428571428 -0.00819047619047622 C 0.0953550597998766 -0.0125265741339082 0.107821870086751 -0.010397536991717 0.120321428571429 -0.0115555555555556 C 0.133179018681433 -0.0127467438724762 0.151318627483861 -0.0158700272533852 0.1585 0.00539682539682542 C 0.16478291361998 0.0240029898688431 0.15828642886492 0.0483806254341085 0.161392857142857 0.0698412698412698 C 0.165179286017685 0.0959996731216037 0.17453898927982 0.119735912694626 0.187142857142857 0.132634920634921 C 0.199788991845377 0.145577185161529 0.215607110490848 0.142889773028431 0.230107142857143 0.142857142857143 C 0.243821417584191 0.142826280916829 0.257716514999779 0.142685979556724 0.271142857142857 0.137777777777778 C 0.286895094567923 0.132019309914514 0.302318190711873 0.122962218306185 0.317928571428571 0.11568253968254 C 0.333496771884547 0.108422531222479 0.348787823719556 0.0990570571890929 0.363714285714286 0.0885079365079364 C 0.374930683062651 0.080580865157908 0.385357142857143 0.0693333333333332 0.396178571428571 0.0596825396825396 L 0.404785714285714 0.0410158730158729 L 0.401892857142857 0.0342222222222221 E", getXPath(pXmlDocContent, "(//p:animMotion)[1]", "path"));
+ CPPUNIT_ASSERT_MOTIONPATH("M 0.0449285714285714 0.00368253968253968 C 0.0575714285714285 -0.00095238095238096 0.0704264795523803 -0.00370117418637049 0.0831071428571428 -0.00819047619047622 C 0.0953550597998766 -0.0125265741339082 0.107821870086751 -0.010397536991717 0.120321428571429 -0.0115555555555556 C 0.133179018681433 -0.0127467438724762 0.151318627483861 -0.0158700272533852 0.1585 0.00539682539682542 C 0.16478291361998 0.0240029898688431 0.15828642886492 0.0483806254341085 0.161392857142857 0.0698412698412698 C 0.165179286017685 0.0959996731216037 0.17453898927982 0.119735912694626 0.187142857142857 0.132634920634921 C 0.199788991845377 0.145577185161529 0.215607110490848 0.142889773028431 0.230107142857143 0.142857142857143 C 0.243821417584191 0.142826280916829 0.257716514999779 0.142685979556724 0.271142857142857 0.137777777777778 C 0.286895094567923 0.132019309914514 0.302318190711873 0.122962218306185 0.317928571428571 0.11568253968254 C 0.333496771884548 0.108422531222479 0.348787823719556 0.0990570571890929 0.363714285714286 0.0885079365079364 C 0.374930683062651 0.080580865157908 0.385357142857143 0.0693333333333332 0.396178571428571 0.0596825396825396 L 0.404785714285714 0.0410158730158729 L 0.401892857142857 0.0342222222222221 E", getXPath(pXmlDocContent, "(//p:animMotion)[1]", "path"));
CPPUNIT_ASSERT_MOTIONPATH("M 0.025 0.0571428571428571 L 0.0821428571428571 0.184126984126984 L -0.175 0.234920634920635 L -0.246428571428571 -0.0190476190476191 L -0.0821428571428573 -0.133333333333333 E", getXPath(pXmlDocContent, "(//p:animMotion)[2]", "path"));
CPPUNIT_ASSERT_MOTIONPATH("M -0.0107142857142857 0.00634920634920635 C -0.110714285714286 0.501587301587301 -0.153571428571429 -0.00634920634920635 -0.246428571428572 0.184126984126984 C -0.339285714285715 0.374603174603175 -0.296428571428572 0.514285714285714 -0.267857142857143 0.603174603174603 C -0.239285714285715 0.692063492063492 0.0607142857142858 0.590476190476191 0.0607142857142858 0.590476190476191 E", getXPath(pXmlDocContent, "(//p:animMotion)[3]", "path"));
CPPUNIT_ASSERT_MOTIONPATH("M 0.0535714285714286 -0.0444444444444444 L 0.132142857142857 -0.0444444444444444 L 0.132142857142857 -0.146031746031746 L 0.0964285714285715 -0.146031746031746 E", getXPath(pXmlDocContent, "(//p:animMotion)[4]", "path"));