aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/generic
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2012-03-10 08:55:53 -0800
committerRichard Henderson <rth@twiddle.net>2012-03-19 06:49:44 -0700
commiteb92c487b35e26aa1e08815c4480d0bc5cc9f370 (patch)
tree99b3d94fcac1b61ea4c23f5575c109508db5e590 /sysdeps/generic
parent7d2e8012cfb4fa30086ef330ef1b993cfcc3dd99 (diff)
downloadglibc-eb92c487b35e26aa1e08815c4480d0bc5cc9f370.zip
glibc-eb92c487b35e26aa1e08815c4480d0bc5cc9f370.tar.gz
glibc-eb92c487b35e26aa1e08815c4480d0bc5cc9f370.tar.bz2
Create and use SET_RESTORE_ROUND{,_NOEX,_53BIT}{,F,L}.
Diffstat (limited to 'sysdeps/generic')
-rw-r--r--sysdeps/generic/math_private.h69
1 files changed, 69 insertions, 0 deletions
diff --git a/sysdeps/generic/math_private.h b/sysdeps/generic/math_private.h
index ab4b47b..0b945f9 100644
--- a/sysdeps/generic/math_private.h
+++ b/sysdeps/generic/math_private.h
@@ -457,6 +457,75 @@ default_libc_feupdateenv (fenv_t *e)
# define libc_feupdateenv_53bit libc_feupdateenv
#endif
+/* Save and set the rounding mode. The use of fenv_t to store the old mode
+ allows a target-specific version of this function to avoid converting the
+ rounding mode from the fpu format. By default we have no choice but to
+ manipulate the entire env. */
+
+#ifndef libc_feholdsetround
+# define libc_feholdsetround libc_feholdexcept_setround
+#endif
+#ifndef libc_feholdsetroundf
+# define libc_feholdsetroundf libc_feholdexcept_setroundf
+#endif
+#ifndef libc_feholdsetroundl
+# define libc_feholdsetroundl libc_feholdexcept_setroundl
+#endif
+
+/* ... and the reverse. */
+
+#ifndef libc_feresetround
+# define libc_feresetround libc_feupdateenv
+#endif
+#ifndef libc_feresetroundf
+# define libc_feresetroundf libc_feupdateenvf
+#endif
+#ifndef libc_feresetroundl
+# define libc_feresetroundl libc_feupdateenvl
+#endif
+
+/* ... and a version that may also discard exceptions. */
+
+#ifndef libc_feresetround_noex
+# define libc_feresetround_noex libc_fesetenv
+#endif
+#ifndef libc_feresetround_noexf
+# define libc_feresetround_noexf libc_fesetenvf
+#endif
+#ifndef libc_feresetround_noexl
+# define libc_feresetround_noexl libc_fesetenvl
+#endif
+
+/* Save and restore the rounding mode within a lexical block. */
+
+#define SET_RESTORE_ROUND(RM) \
+ fenv_t __libc_save_rm __attribute__((cleanup(libc_feresetround))); \
+ libc_feholdsetround (&__libc_save_rm, (RM))
+#define SET_RESTORE_ROUNDF(RM) \
+ fenv_t __libc_save_rm __attribute__((cleanup(libc_feresetroundf))); \
+ libc_feholdsetroundf (&__libc_save_rm, (RM))
+#define SET_RESTORE_ROUNDL(RM) \
+ fenv_t __libc_save_rm __attribute__((cleanup(libc_feresetroundl))); \
+ libc_feholdsetroundl (&__libc_save_rm, (RM))
+
+/* Save and restore the rounding mode within a lexical block, and also
+ the set of exceptions raised within the block may be discarded. */
+
+#define SET_RESTORE_ROUND_NOEX(RM) \
+ fenv_t __libc_save_rm __attribute__((cleanup(libc_feresetround_noex))); \
+ libc_feholdsetround (&__libc_save_rm, (RM))
+#define SET_RESTORE_ROUND_NOEXF(RM) \
+ fenv_t __libc_save_rm __attribute__((cleanup(libc_feresetround_noexf))); \
+ libc_feholdsetroundf (&__libc_save_rm, (RM))
+#define SET_RESTORE_ROUND_NOEXL(RM) \
+ fenv_t __libc_save_rm __attribute__((cleanup(libc_feresetround_noexl))); \
+ libc_feholdsetroundl (&__libc_save_rm, (RM))
+
+/* Like SET_RESTORE_ROUND, but also set rounding precision to 53 bits. */
+#define SET_RESTORE_ROUND_53BIT(RM) \
+ fenv_t __libc_save_rm __attribute__((cleanup(libc_feupdateenv_53bit))); \
+ libc_feholdexcept_setround_53bit (&__libc_save_rm, (RM))
+
#define __nan(str) \
(__builtin_constant_p (str) && str[0] == '\0' ? NAN : __nan (str))
#define __nanf(str) \