diff options
author | CoprDistGit <infra@openeuler.org> | 2024-08-03 06:28:41 +0000 |
---|---|---|
committer | CoprDistGit <infra@openeuler.org> | 2024-08-03 06:28:41 +0000 |
commit | d20db0561a6a36f914fde030512503b114ef9a0c (patch) | |
tree | d4e5e3494d95c269a1cee6195f11bf3201bcadbf /stdlib-strfrom-Add-copysign-to-fix-NAN-issue-on-risc.patch | |
parent | 016343d99b1b269d7246ef1e143d4b54914433d4 (diff) |
automatic import of glibcopeneuler22.03_LTS_SP4openeuler22.03_LTS_SP3openeuler20.03
Diffstat (limited to 'stdlib-strfrom-Add-copysign-to-fix-NAN-issue-on-risc.patch')
-rw-r--r-- | stdlib-strfrom-Add-copysign-to-fix-NAN-issue-on-risc.patch | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/stdlib-strfrom-Add-copysign-to-fix-NAN-issue-on-risc.patch b/stdlib-strfrom-Add-copysign-to-fix-NAN-issue-on-risc.patch new file mode 100644 index 0000000..baaeb5e --- /dev/null +++ b/stdlib-strfrom-Add-copysign-to-fix-NAN-issue-on-risc.patch @@ -0,0 +1,176 @@ +From 0cc0033ef19bd3378445c2b851e53d7255cb1b1e Mon Sep 17 00:00:00 2001 +From: Letu Ren <fantasquex@gmail.com> +Date: Fri, 21 Oct 2022 22:54:50 +0800 +Subject: [PATCH] stdlib/strfrom: Add copysign to fix NAN issue on riscv (BZ + #29501) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +According to the specification of ISO/IEC TS 18661-1:2014, + +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. +v4: Fix wrong commit message header. +v5: Fix style: add space before parentheses. +v6: Add copyright. +Signed-off-by: Letu Ren <fantasquex@gmail.com> +Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> +--- + stdlib/strfrom-skeleton.c | 3 +- + .../generic/fix-float-double-convert-nan.h | 31 ++++++++++++++++ + .../riscv/rvd/fix-float-double-convert-nan.h | 37 +++++++++++++++++++ + 3 files changed, 70 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..36e9adcad5 100644 +--- a/stdlib/strfrom-skeleton.c ++++ b/stdlib/strfrom-skeleton.c +@@ -27,6 +27,7 @@ + #include <printf.h> + #include <string.h> + #include <locale/localeinfo.h> ++#include <fix-float-double-convert-nan.h> + + #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..66692262fc +--- /dev/null ++++ b/sysdeps/generic/fix-float-double-convert-nan.h +@@ -0,0 +1,31 @@ ++/* Fix for conversion of float NAN to double. Generic version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ <https://www.gnu.org/licenses/>. */ ++ ++#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..cab003f3c1 +--- /dev/null ++++ b/sysdeps/riscv/rvd/fix-float-double-convert-nan.h +@@ -0,0 +1,37 @@ ++/* Fix for conversion of float NAN to double. RISC-V version.. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ <https://www.gnu.org/licenses/>. */ ++ ++#ifndef FIX_FLOAT_DOUBLE_CONVERT_NAN_H ++#define FIX_FLOAT_DOUBLE_CONVERT_NAN_H ++ ++#include <math.h> ++ ++/* 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 +-- +2.39.2 + |