public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-3202] libstdc++: Avoid problematic use of log10 in std::format [PR110860]
@ 2023-08-14 17:10 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2023-08-14 17:10 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:2d2b05f0691799f03062bf5c436462f14cad3e7c

commit r14-3202-g2d2b05f0691799f03062bf5c436462f14cad3e7c
Author: Paul Dreik <gccpatches@pauldreik.se>
Date:   Mon Aug 14 15:42:33 2023 +0100

    libstdc++: Avoid problematic use of log10 in std::format [PR110860]
    
    If abs(__v) is smaller than one, the result will be of the
    form 0.xxxxx. It is only if the magnitude is large that more digits
    are needed before the decimal dot.
    
    This uses frexp instead of log10 which should be less expensive
    and have sufficient precision for the desired purpose.
    
    It removes the problematic cases where log10 will be negative or not
    fit in an int.
    
    Signed-off-by: Paul Dreik <gccpatches@pauldreik.se>
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/110860
            * include/std/format (__formatter_fp::format): Use frexp instead
            of log10.

Diff:
---
 libstdc++-v3/include/std/format | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index f4520ff3f746..7ea0377ec715 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -1490,14 +1490,23 @@ namespace __format
 	      // If the buffer is too small it's probably because of a large
 	      // precision, or a very large value in fixed format.
 	      size_t __guess = 8 + __prec;
-	      if (__fmt == chars_format::fixed && __v != 0) // +ddd.prec
+	      if (__fmt == chars_format::fixed) // +ddd.prec
 		{
-		  if constexpr (is_same_v<_Fp, float>)
-		    __guess += __builtin_log10f(__v < 0.0f ? -__v : __v);
-		  else if constexpr (is_same_v<_Fp, double>)
-		    __guess += __builtin_log10(__v < 0.0 ? -__v : __v);
-		  else if constexpr (is_same_v<_Fp, long double>)
-		    __guess += __builtin_log10l(__v < 0.0l ? -__v : __v);
+		  if constexpr (is_same_v<_Fp, float> || is_same_v<_Fp, double>
+				  || is_same_v<_Fp, long double>)
+		    {
+		      // The number of digits to the left of the decimal point
+		      // is floor(log10(max(abs(__v),1)))+1
+		      int __exp{};
+		      if constexpr (is_same_v<_Fp, float>)
+			__builtin_frexpf(__v, &__exp);
+		      else if constexpr (is_same_v<_Fp, double>)
+			__builtin_frexp(__v, &__exp);
+		      else if constexpr (is_same_v<_Fp, long double>)
+			__builtin_frexpl(__v, &__exp);
+		      if (__exp > 0)
+			__guess += 1U + __exp * 4004U / 13301U; // log10(2) approx.
+		    }
 		  else
 		    __guess += numeric_limits<_Fp>::max_exponent10;
 		}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-08-14 17:10 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-14 17:10 [gcc r14-3202] libstdc++: Avoid problematic use of log10 in std::format [PR110860] Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).