From patchwork Thu Oct 6 13:15:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Letu Ren X-Patchwork-Id: 58471 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 096413938C3F for ; Thu, 6 Oct 2022 13:16:45 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 096413938C3F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1665062205; bh=MzJLYS6iSGdyxsr5YMK2rmVdq71Qyx4VHQdZGnoQS+A=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=ulhs0bG3A+RofryqT74eQKXFfDtbcAid/AtEbIx/LkCvdJAn2OtURJj526FTzhsVO 9dtT2WVfhyhEW3/mFT9oX3FCxVdWR/FtdPoABe0oF/Wnnhse9kep1M7BosTn2F7SH9 pDJDsdncvBR6Z/wDM4FIbU1FHnOqWGLEew0To/qo= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pj1-x102e.google.com (mail-pj1-x102e.google.com [IPv6:2607:f8b0:4864:20::102e]) by sourceware.org (Postfix) with ESMTPS id 3BA15392AC2D for ; Thu, 6 Oct 2022 13:16:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3BA15392AC2D Received: by mail-pj1-x102e.google.com with SMTP id x1-20020a17090ab00100b001fda21bbc90so4297630pjq.3 for ; Thu, 06 Oct 2022 06:16:02 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date; bh=MzJLYS6iSGdyxsr5YMK2rmVdq71Qyx4VHQdZGnoQS+A=; b=031i7//a7YKLUtpJV5MfBcJ02amVLdnbIh1gJ3GwxqJ5qHZTUWtAtnr+RT2Ppa98cr GQCWNZcly0rwTcGX5syT44xLPh0nipEWaDzU4BI2oFFEjYdg2JwKjXcWLylk6hZyUJVX 8R7GMi/rVlLI59E6JDIXRw4nnwbYdjeVKjpJprwLiAnRQjrTqIHnCe+8s0BFhj62Wyz5 kZ53gvGJBza1wa+Z6cVMPyTCdsahp3DK4ALHKcULFOQ36ARXOHgMMeAAw2KmfbA0psSu rMJ/xw4vLbELS9NU1+L6jqbxEK9sVG2z713kMNBjMIccTX9sZqRvg5L6pSB1dGavC/1H VXhA== X-Gm-Message-State: ACrzQf2vWMPAOM9sOxk2Y5gcjBWXS8+Uxe/yPtD7zvaDFs9wEGBs171S EhMoE0dEOc4axeHdjcCnq9GveF8yvPY8vOqg X-Google-Smtp-Source: AMsMyM6u6gZ0OWytr35luYzRpiL8iEYl72motGpQvj6EIWF4wR5reo7Cu79TTptj7h7W+C2LHnG6UQ== X-Received: by 2002:a17:90b:1943:b0:20a:85e9:f089 with SMTP id nk3-20020a17090b194300b0020a85e9f089mr5361000pjb.47.1665062161066; Thu, 06 Oct 2022 06:16:01 -0700 (PDT) Received: from fanta-arch.tsinghua.edu.cn (ec2-18-162-45-232.ap-east-1.compute.amazonaws.com. [18.162.45.232]) by smtp.gmail.com with ESMTPSA id cc4-20020a17090af10400b001fe2ab750bbsm2882817pjb.29.2022.10.06.06.15.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Oct 2022 06:16:00 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v3] According to the specification of ISO/IEC TS 18661-1:2014, Date: Thu, 6 Oct 2022 21:15:45 +0800 Message-Id: <20221006131545.13518-1-fantasquex@gmail.com> X-Mailer: git-send-email 2.38.0 MIME-Version: 1.0 X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Letu Ren via Libc-alpha From: Letu Ren Reply-To: Letu Ren Cc: fweimer@redhat.com, Letu Ren , joseph@codesourcery.com Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" The strfromd, strfromf, and strfroml functions are equivalent to snprintf(s, n, format, fp) (7.21.6.5), except the format string contains only the character %, an optional precision that does not contain an asterisk *, and one of the conversion specifiers a, A, e, E, f, F, g, or G, which applies to the type (double, float, or long double) indicated by the function suffix (rather than by a length modifier). Use of these functions with any other 20 format string results in undefined behavior. strfromf will convert the arguement with type float to double first. According to the latest version of IEEE754 which is published in 2019, Conversion of a quiet NaN from a narrower format to a wider format in the same radix, and then back to the same narrower format, should not change the quiet NaN payload in any way except to make it canonical. When either an input or result is a NaN, this standard does not interpret the sign of a NaN. However, operations on bit strings—copy, negate, abs, copySign—specify the sign bit of a NaN result, sometimes based upon the sign bit of a NaN operand. The logical predicates totalOrder and isSignMinus are also affected by the sign bit of a NaN operand. For all other operations, this standard does not specify the sign bit of a NaN result, even when there is only one input NaN, or when the NaN is produced from an invalid operation. converting NAN or -NAN with type float to double doesn't need to keep the signbit. As a result, this test case isn't mandatory. The problem is that according to RISC-V ISA manual in chapter 11.3 of riscv-isa-20191213, Except when otherwise stated, if the result of a floating-point operation is NaN, it is the canonical NaN. The canonical NaN has a positive sign and all significand bits clear except the MSB, a.k.a. the quiet bit. For single-precision floating-point, this corresponds to the pattern 0x7fc00000. which means that conversion -NAN from float to double won't keep the signbit. Since glibc ought to be consistent here between types and architectures, this patch adds copysign to fix this problem if the string is NAN. This patch adds two different functions under sysdeps directory to work around the issue. This patch has been tested on x86_64 and riscv64. Resolves: BZ #29501 v2: Change from macros to different inline functions. v3: Add unlikely check to isnan. --- I'm not sure about copyright of the new file I created and the name of the new function. Please give me some advice. Thanks. stdlib/strfrom-skeleton.c | 3 ++- .../generic/fix-float-double-convert-nan.h | 15 +++++++++++++ .../riscv/rvd/fix-float-double-convert-nan.h | 21 +++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 sysdeps/generic/fix-float-double-convert-nan.h create mode 100644 sysdeps/riscv/rvd/fix-float-double-convert-nan.h diff --git a/stdlib/strfrom-skeleton.c b/stdlib/strfrom-skeleton.c index 1fba04bf6a..a14df8d424 100644 --- a/stdlib/strfrom-skeleton.c +++ b/stdlib/strfrom-skeleton.c @@ -27,6 +27,7 @@ #include #include #include +#include #define UCHAR_T char #define L_(Str) Str @@ -61,7 +62,7 @@ STRFROM (char *dest, size_t size, const char *format, FLOAT f) because __printf_fp and __printf_fphex only accept double and long double as the floating-point argument. */ if (__builtin_types_compatible_p (FLOAT, float)) - fpnum.flt = f; + fpnum.flt = keep_sign_conversion(f); else fpnum.value = f; diff --git a/sysdeps/generic/fix-float-double-convert-nan.h b/sysdeps/generic/fix-float-double-convert-nan.h new file mode 100644 index 0000000000..0949dda102 --- /dev/null +++ b/sysdeps/generic/fix-float-double-convert-nan.h @@ -0,0 +1,15 @@ +/* Fix for conversion of float NAN to double. Generic version. */ + +#ifndef FIX_FLOAT_DOUBLE_CONVERT_NAN_H +#define FIX_FLOAT_DOUBLE_CONVERT_NAN_H + +/* This function aims to work around conversions of float -NAN + to double returning NAN instead of the correct -NAN in some + architectures. */ +static inline double __attribute__ ((always_inline)) +keep_sign_conversion (float flt) +{ + return flt; +} + +#endif diff --git a/sysdeps/riscv/rvd/fix-float-double-convert-nan.h b/sysdeps/riscv/rvd/fix-float-double-convert-nan.h new file mode 100644 index 0000000000..59806052a8 --- /dev/null +++ b/sysdeps/riscv/rvd/fix-float-double-convert-nan.h @@ -0,0 +1,21 @@ +/* Fix for conversion of float NAN to double. RISC-V version. */ + +#ifndef FIX_FLOAT_DOUBLE_CONVERT_NAN_H +#define FIX_FLOAT_DOUBLE_CONVERT_NAN_H + +#include + +/* RISC-V rvd instructions do not preserve the signbit of NAN + when converting from float to double. */ +static inline double +keep_sign_conversion (float flt) +{ + if (__glibc_unlikely (isnan (flt))) + { + float x = copysignf (1.f, flt); + return copysign ((double) flt, (double) x); + } + return flt; +} + +#endif