sc/source/core/tool/interpr2.cxx |  144 ++++++++++++++++-----------------------
 1 file changed, 61 insertions(+), 83 deletions(-)

New commits:
commit 6badee44a10ebb8e9b5b821bd15a12a3bf6b2f22
Author:     Mike Kaganski <[email protected]>
AuthorDate: Mon Nov 3 16:11:28 2025 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Sat Nov 8 13:22:31 2025 +0100

    Simplify ScBahtText using rtl::math::doubleToString
    
    Instead of rounding and converting the number, create a string with
    all the digits and proper rounding, and parse it from start to end.
    Avoids insertion to beginning of the buffer; matches the rounding
    used everywhere (up to 15 significands).
    
    Change-Id: I3cdbae0d4fda704edd282c86e85c715c5336e81e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193612
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/sc/source/core/tool/interpr2.cxx b/sc/source/core/tool/interpr2.cxx
index 36375d4cc15c..797d863abefb 100644
--- a/sc/source/core/tool/interpr2.cxx
+++ b/sc/source/core/tool/interpr2.cxx
@@ -3401,22 +3401,21 @@ constexpr std::u16string_view TH_BAHT   = u"บาท";
 constexpr std::u16string_view TH_SATANG = u"สตางค์";
 constexpr std::u16string_view TH_MINUS  = u"ลบ";
 
-/** Appends a digit (0 to 9) to the passed string. */
-void lclAppendDigit( OUStringBuffer& rText, sal_Int32 nDigit )
+/** Appends a digit (1 to 9) to the passed string. */
+void lclAppendDigit( OUStringBuffer& rText, char nDigit )
 {
+    assert(nDigit >= '1' && nDigit <= '9');
     switch( nDigit )
     {
-        case 0: rText.append( TH_0 ); break;
-        case 1: rText.append( TH_1 ); break;
-        case 2: rText.append( TH_2 ); break;
-        case 3: rText.append( TH_3 ); break;
-        case 4: rText.append( TH_4 ); break;
-        case 5: rText.append( TH_5 ); break;
-        case 6: rText.append( TH_6 ); break;
-        case 7: rText.append( TH_7 ); break;
-        case 8: rText.append( TH_8 ); break;
-        case 9: rText.append( TH_9 ); break;
-        default:    OSL_FAIL( "lclAppendDigit - illegal digit" );
+        case '1': rText.append( TH_1 ); break;
+        case '2': rText.append( TH_2 ); break;
+        case '3': rText.append( TH_3 ); break;
+        case '4': rText.append( TH_4 ); break;
+        case '5': rText.append( TH_5 ); break;
+        case '6': rText.append( TH_6 ); break;
+        case '7': rText.append( TH_7 ); break;
+        case '8': rText.append( TH_8 ); break;
+        case '9': rText.append( TH_9 ); break;
     }
 }
 
@@ -3424,9 +3423,9 @@ void lclAppendDigit( OUStringBuffer& rText, sal_Int32 
nDigit )
     @param nDigit  A digit in the range from 1 to 9.
     @param nPow10  A value in the range from 2 to 5.
  */
-void lclAppendPow10( OUStringBuffer& rText, sal_Int32 nDigit, sal_Int32 nPow10 
)
+void lclAppendPow10( OUStringBuffer& rText, char nDigit, sal_Int32 nPow10 )
 {
-    OSL_ENSURE( (1 <= nDigit) && (nDigit <= 9), "lclAppendPow10 - illegal 
digit" );
+    assert(nPow10 >= 2 && nPow10 <= 5);
     lclAppendDigit( rText, nDigit );
     switch( nPow10 )
     {
@@ -3434,51 +3433,33 @@ void lclAppendPow10( OUStringBuffer& rText, sal_Int32 
nDigit, sal_Int32 nPow10 )
         case 3: rText.append( TH_1E3 );   break;
         case 4: rText.append( TH_1E4 );   break;
         case 5: rText.append( TH_1E5 );   break;
-        default:    OSL_FAIL( "lclAppendPow10 - illegal power" );
     }
 }
 
 /** Appends a block of 6 digits (value from 1 to 999,999) to the passed 
string. */
-void lclAppendBlock( OUStringBuffer& rText, sal_Int32 nValue )
-{
-    OSL_ENSURE( (1 <= nValue) && (nValue <= 999999), "lclAppendBlock - illegal 
value" );
-    if( nValue >= 100000 )
-    {
-        lclAppendPow10( rText, nValue / 100000, 5 );
-        nValue %= 100000;
-    }
-    if( nValue >= 10000 )
-    {
-        lclAppendPow10( rText, nValue / 10000, 4 );
-        nValue %= 10000;
-    }
-    if( nValue >= 1000 )
-    {
-        lclAppendPow10( rText, nValue / 1000, 3 );
-        nValue %= 1000;
-    }
-    if( nValue >= 100 )
-    {
-        lclAppendPow10( rText, nValue / 100, 2 );
-        nValue %= 100;
-    }
-    if( nValue <= 0 )
-        return;
-
-    sal_Int32 nTen = nValue / 10;
-    sal_Int32 nOne = nValue % 10;
-    if( nTen >= 1 )
-    {
-        if( nTen >= 3 )
-            lclAppendDigit( rText, nTen );
-        else if( nTen == 2 )
+void lclAppendBlock( OUStringBuffer& rText, std::string_view block )
+{
+    assert(block.size() > 0 && block.size() <= 6);
+    auto it = block.begin();
+    for (size_t pow = block.size() - 1; pow >= 2; --pow)
+        if (char ch = *it++; ch != '0')
+            lclAppendPow10(rText, ch, pow);
+
+    // Two last characters
+    char ten = block.size() > 1 ? *it++ : '0';
+    char one = *it;
+    if (ten >= '1')
+    {
+        if (ten >= '3')
+            lclAppendDigit(rText, ten);
+        else if (ten == '2')
             rText.append( TH_20 );
         rText.append( TH_10 );
     }
-    if( (nTen > 0) && (nOne == 1) )
+    if ((ten > '0') && (one == '1'))
         rText.append( TH_11 );
-    else if( nOne > 0 )
-        lclAppendDigit( rText, nOne );
+    else if( one > '0' )
+        lclAppendDigit(rText, one);
 }
 
 } // namespace
@@ -3496,56 +3477,53 @@ void ScInterpreter::ScBahtText()
         return;
     }
 
-    // sign
-    bool bMinus = fValue < 0.0;
-    fValue = std::abs( fValue );
-
+    OString number = rtl::math::doubleToString(std::abs(fValue), 
rtl_math_StringFormat_F, 2, '.');
+    assert(number.getLength() > 3); // At least "0.00"
+    const sal_Int32 dotPos = number.getLength() - 3;
+    assert(number[dotPos] == '.');
     // split Baht and Satang
-    double fBaht = 0.0;
-    sal_Int32 nSatang = std::round(modf(fValue, &fBaht) * 100);
-    if (nSatang > 99)
+    std::string_view sBaht(number.subView(0, dotPos)), 
sSatang(number.subView(dotPos + 1));
+    bool noBaht = sBaht == "0", noSatang = sSatang == "00";
+    if (noBaht && noSatang)
     {
-        nSatang -= 100;
-        fBaht += 1;
+        return PushString(OUString::Concat(TH_0) + TH_BAHT + TH_DOT0);
     }
 
     OUStringBuffer aText;
+    // sign
+    if (fValue < 0.0)
+        aText.append(TH_MINUS);
 
     // generate text for Baht value
-    if( fBaht == 0.0 )
-    {
-        if( nSatang == 0 )
-            aText.append( TH_0 );
-    }
-    else while( fBaht > 0.0 )
+    if (!noBaht)
     {
-        OUStringBuffer aBlock;
-        if (sal_Int32 nBlock = std::round(modf(fBaht / 1.0e6, &fBaht) * 1.0e6))
-            lclAppendBlock( aBlock, nBlock );
-        // add leading "million", if there will come more blocks
-        if( fBaht > 0.0 )
-            aBlock.insert( 0, TH_1E6 );
-
-        aText.insert(0, aBlock);
+        size_t blocksize = sBaht.size() % 6;
+        if (blocksize == 0)
+            blocksize = 6;
+        while (!sBaht.empty())
+        {
+            assert(blocksize <= sBaht.size());
+            lclAppendBlock(aText, sBaht.substr(0, blocksize));
+            sBaht.remove_prefix(blocksize);
+            blocksize = 6;
+            // add "million", if there will come more blocks
+            if (!sBaht.empty())
+                aText.append(TH_1E6);
+        }
+        aText.append(TH_BAHT);
     }
-    if (!aText.isEmpty())
-        aText.append( TH_BAHT );
 
     // generate text for Satang value
-    if( nSatang == 0 )
+    if (noSatang)
     {
         aText.append( TH_DOT0 );
     }
     else
     {
-        lclAppendBlock( aText, nSatang );
+        lclAppendBlock(aText, sSatang);
         aText.append( TH_SATANG );
     }
 
-    // add the minus sign
-    if( bMinus )
-        aText.insert( 0, TH_MINUS );
-
     PushString(aText.makeStringAndClear());
 }
 

Reply via email to