svl/qa/unit/svl.cxx | 5 +++++ svl/source/numbers/zformat.cxx | 12 ++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-)
New commits: commit 51df96790ec1ab24bd98a9d186e78164a401fddd Author: Xisco Fauli <[email protected]> AuthorDate: Tue Jan 27 10:57:03 2026 +0100 Commit: Xisco Fauli <[email protected]> CommitDate: Tue Jan 27 14:40:03 2026 +0100 tdf#167892: svl_qa_cppunit: Add test Change-Id: I56925b648518c8e3399e534e3c82eb9bc0bfa335 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198192 Tested-by: Jenkins Reviewed-by: Xisco Fauli <[email protected]> Signed-off-by: Xisco Fauli <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198200 diff --git a/svl/qa/unit/svl.cxx b/svl/qa/unit/svl.cxx index 4b482e0c1d9b..a98a253831ea 100644 --- a/svl/qa/unit/svl.cxx +++ b/svl/qa/unit/svl.cxx @@ -1437,6 +1437,11 @@ void Test::testUserDefinedNumberFormats() sExpected = "-1/2"; checkPreviewString(aFormatter, sCode, -0.5, eLang, sExpected); } + { // tdf#167892: hang formatting as fraction + sCode = "#/?"; + sExpected = "0/1"; + checkPreviewString(aFormatter, sCode, 0.0000000000000000001, eLang, sExpected); + } { // tdf#52510 sCode = "_($* #,##0.00_);_($* (#,##0.00);"; sExpected = ""; diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx index 89968ba942c5..0c33ade1f94c 100644 --- a/svl/source/numbers/zformat.cxx +++ b/svl/source/numbers/zformat.cxx @@ -2884,14 +2884,14 @@ void SvNumberformat::ImpGetFractionElements ( double& fNumber, sal_uInt16 nIx, { double fTemp = 1.0 / fRemainder; // 64bits precision required when fRemainder is very weak nPartialDenom = static_cast<sal_Int64>(floor(fTemp)); // due to floating point notation with double precision -#ifdef _WIN32 // The fTemp value may be out of range for sal_Int64 (e.g. 1e+19), and the result of - // casting that is undefined. In practice, gcc/llvm gives us a large positive number, but MSVC may create - // a large negative number, which will make this algorithm oscillate, so apply a correction that makes - // MSVC end up with the same thing. There is probably a better algorithm to be used here. + // casting that is undefined. In practice, gcc/llvm gives us a large positive number, + // but depending on the compiler, we have either a large positive number (which works fine) + // or a a large negative number, which will make this algorithm oscillate. + // So apply a correction that makes all the compilers work reasonbly. + // There is probably a better algorithm to be used here for this whole function. if (nPartialDenom < 0) nPartialDenom = -(nPartialDenom+1); -#endif fRemainder = fTemp - static_cast<double>(nPartialDenom); nDivNext = nPartialDenom * nDiv + nDivPrev; if (nDivNext <= nBasis) // continue loop commit aee02120d8252ece180dc7a601d572923606f4dc Author: Noel Grandin <[email protected]> AuthorDate: Mon Jan 26 20:12:37 2026 +0200 Commit: Xisco Fauli <[email protected]> CommitDate: Tue Jan 27 14:39:57 2026 +0100 tdf#167892 fix hang formatting very small number on windows Workaround undefined behaviour where llvm/gcc produces different code from MSVC, resulting in oscillation in this algorithm. regression from commit 44d17f8feca372acd41142d1b607d3360282bf30 Author: Eike Rathke <[email protected]> Date: Tue Oct 13 21:41:45 2020 +0200 Resolves: tdf#137453 Implicit conversion from sal_uInt64 to sal_Int32 is bad.. Change-Id: I486e8caabcbf582cf94b47547efc89d1b206503e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198163 Reviewed-by: Noel Grandin <[email protected]> Tested-by: Jenkins Signed-off-by: Xisco Fauli <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198199 diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx index 65855709854a..89968ba942c5 100644 --- a/svl/source/numbers/zformat.cxx +++ b/svl/source/numbers/zformat.cxx @@ -2853,7 +2853,7 @@ double SvNumberformat::GetRoundFractionValue ( double fNumber ) const void SvNumberformat::ImpGetFractionElements ( double& fNumber, sal_uInt16 nIx, double& fIntPart, sal_Int64& nFrac, sal_Int64& nDiv ) const { - if ( fNumber < 0.0 ) + if (fNumber < 0.0) fNumber = -fNumber; fIntPart = floor(fNumber); // Integral part fNumber -= fIntPart; // Fractional part @@ -2884,9 +2884,17 @@ void SvNumberformat::ImpGetFractionElements ( double& fNumber, sal_uInt16 nIx, { double fTemp = 1.0 / fRemainder; // 64bits precision required when fRemainder is very weak nPartialDenom = static_cast<sal_Int64>(floor(fTemp)); // due to floating point notation with double precision +#ifdef _WIN32 + // The fTemp value may be out of range for sal_Int64 (e.g. 1e+19), and the result of + // casting that is undefined. In practice, gcc/llvm gives us a large positive number, but MSVC may create + // a large negative number, which will make this algorithm oscillate, so apply a correction that makes + // MSVC end up with the same thing. There is probably a better algorithm to be used here. + if (nPartialDenom < 0) + nPartialDenom = -(nPartialDenom+1); +#endif fRemainder = fTemp - static_cast<double>(nPartialDenom); nDivNext = nPartialDenom * nDiv + nDivPrev; - if ( nDivNext <= nBasis ) // continue loop + if (nDivNext <= nBasis) // continue loop { nFracNext = nPartialDenom * nFrac + nFracPrev; nFracPrev = nFrac;
