From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from conuserg-07.nifty.com (conuserg-07.nifty.com [210.131.2.74]) by sourceware.org (Postfix) with ESMTPS id 067C7385BF9D for ; Thu, 25 Nov 2021 12:02:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 067C7385BF9D Authentication-Results: sourceware.org; dmarc=fail (p=none dis=none) header.from=nifty.ne.jp Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=nifty.ne.jp Received: from localhost.localdomain (z221123.dynamic.ppp.asahi-net.or.jp [110.4.221.123]) (authenticated) by conuserg-07.nifty.com with ESMTP id 1APC2HE1024170; Thu, 25 Nov 2021 21:02:23 +0900 DKIM-Filter: OpenDKIM Filter v2.10.3 conuserg-07.nifty.com 1APC2HE1024170 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nifty.ne.jp; s=dec2015msa; t=1637841743; bh=Ci+zf1BopqoLeTPbcijnP2uyQZ89W9Du5KflYjf7EWg=; h=From:To:Cc:Subject:Date:From; b=YuxNYjTtNrNsWdkXeYGNyAqdxGD+y0zPuC9buDQh8gnUVTzKvb4ql5rlxBmUAFsiK pZLMRcmB0am3YYFwaOr4TM64tD9eN1FbrcwgOy5t5cmUERrkNpBP0uzttUpKrrCTNY nXK1ox+RX3U11OOf1nRUFSzJgkpFT2AGtXbjdqRkwX/RrOUY4PXtOS0zBUiNCbUPaG sfhdNR7nFv5xwtO6+qY01MdM9TIcUBPCslnz6r5F2HsMWBRYia0BrW66+D25PqC6h6 3ROr013iDhGJXnpxa4I+V2aGgjIfQV3CbGV5KDxghXc/VE3+6QbbHAZLN2AYnb+PRu ciEF1fmpziqOw== X-Nifty-SrcIP: [110.4.221.123] From: Takashi Yano To: newlib@sourceware.org Subject: [PATCH] ldtoa: Fix insufficient valid output digits for "%f" format. Date: Thu, 25 Nov 2021 21:02:07 +0900 Message-Id: <20211125120207.258-1-takashi.yano@nifty.ne.jp> X-Mailer: git-send-email 2.33.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-10.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: newlib@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Newlib mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 25 Nov 2021 12:02:47 -0000 - If the number has large integer part and small fraction part is specified in output format, e.g. printf("%.3f", sqrt(2)*1e60);, valid output digits were insufficient. This patch fixes the issue. --- newlib/libc/stdlib/ldtoa.c | 41 +++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/newlib/libc/stdlib/ldtoa.c b/newlib/libc/stdlib/ldtoa.c index 1b32e801c..95347e017 100644 --- a/newlib/libc/stdlib/ldtoa.c +++ b/newlib/libc/stdlib/ldtoa.c @@ -83,7 +83,7 @@ static void eclear (register short unsigned int *x); static void einfin (register short unsigned int *x, register LDPARMS * ldp); static void efloor (short unsigned int *x, short unsigned int *y, LDPARMS * ldp); -static void etoasc (short unsigned int *x, char *string, int ndigs, +static void etoasc (short unsigned int *x, char *string, int ndec, int ndigs, int outformat, LDPARMS * ldp); union uconv @@ -217,7 +217,7 @@ static const char *const ermsg[7] = { * e24toasc( &f, str, n ) single to ASCII string, n digits after decimal * e53toasc( &d, str, n ) double to ASCII string, n digits after decimal * e64toasc( &d, str, n ) long double to ASCII string - * etoasc(e,str,n,fmt,ldp)e to ASCII string, n digits after decimal + * etoasc(e,str,ndec,n,fmt,ldp)e to ASCII string, n digits after decimal * etoe24( e, &f ) convert e type to IEEE single precision * etoe53( e, &d ) convert e type to IEEE double precision * etoe64( e, &d ) convert e type to IEEE long double precision @@ -2839,23 +2839,33 @@ _ldtoa_r (struct _reent *ptr, long double d, int mode, int ndigits, /* This sanity limit must agree with the corresponding one in etoasc, to keep straight the returned value of outexpon. Note that we use a dynamic - limit now, either NDEC or NDEC_SML, depending on ndigits. See the usage - of "my_NDEC" in etoasc. */ - if (ndigits > NDEC) - ndigits = NDEC; + limit now, either ndec (<= NDEC) or NDEC_SML, depending on ndigits. */ + int ndec; + if (mode == 3) /* %f */ + { + int expon = (e[NE - 1] & 0x7fff) - (EXONE - 1); /* exponent part */ + /* log2(10) approximately 485/146 */ + ndec = expon * 146 / 485 + ndigits; + } + else /* %g/%e */ + ndec = ndigits; + if (ndec < 0) + ndec = 0; + if (ndec > NDEC) + ndec = NDEC; /* Allocate buffer if more than NDEC_SML digits are requested. */ - if (ndigits > NDEC_SML) + if (ndec > NDEC_SML) { - outbuf = (char *) _malloc_r (ptr, NDEC + MAX_EXP_DIGITS + 10); + outbuf = (char *) _malloc_r (ptr, ndec + MAX_EXP_DIGITS + 10); if (!outbuf) { - ndigits = NDEC_SML; + ndec = NDEC_SML; outbuf = outbuf_sml; } } - etoasc (e, outbuf, ndigits, mode, ldp); + etoasc (e, outbuf, ndec, ndigits, mode, ldp); s = outbuf; if (eisinf (e) || eisnan (e)) { @@ -2992,8 +3002,8 @@ _ldcheck (long double *d) } /* _ldcheck */ static void -etoasc (short unsigned int *x, char *string, int ndigits, int outformat, - LDPARMS * ldp) +etoasc (short unsigned int *x, char *string, int ndec, int ndigits, + int outformat, LDPARMS * ldp) { long digit; unsigned short y[NI], t[NI], u[NI], w[NI]; @@ -3003,7 +3013,6 @@ etoasc (short unsigned int *x, char *string, int ndigits, int outformat, char *s, *ss; unsigned short m; unsigned short *equot = ldp->equot; - int my_NDEC = (ndigits > NDEC_SML) ? NDEC : NDEC_SML; ndigs = ndigits; rndsav = ldp->rndprc; @@ -3129,7 +3138,7 @@ tnzro: else { emovi (y, w); - for (i = 0; i < my_NDEC + 1; i++) + for (i = 0; i < ndec + 1; i++) { if ((w[NI - 1] & 0x7) != 0) break; @@ -3205,8 +3214,8 @@ isone: else if( ndigs < 0 ) ndigs = 0; */ - if (ndigs > my_NDEC) - ndigs = my_NDEC; + if (ndigs > ndec) + ndigs = ndec; if (digit == 10) { *s++ = '1'; -- 2.33.0