PATCH: Add __float128 I/O support
H. J. Lu
hjl@lucon.org
Thu May 6 19:36:00 GMT 2004
__float128 is added to gcc 3.4.0. This patch adds the __float128 I/0
support to glibc with a new length modifier "lL" for fprintf and a new
conversion flag "lL" for fscanf. I tested it on ia64 and x86_64 with
gcc 3.4.0. I also tested it on ia32, ia64 and x86_64 with gcc 3.2.
Everything looks OK.
H.J.
-------------- next part --------------
2004-05-06 H.J. Lu <hongjiu.lu@intel.com>
* config.h.in: Add HAVE_FLOAT128.
* configure.in: Test __float128. Add sysdeps/ieee754/quad to
directory list and set HAVE_FLOAT128 if __float128 is supported.
* configure: Regenerated.
* include/gmp.h (__mpn_extract_float128): Add if HAVE_FLOAT128
is defined.
(__mpn_construct_float128): Likewise.
* include/math.h (__isinfq): Likewise.
* include/math.h (__isnanq): Likewise.
* include/math.h (__signbitq): Likewise.
* include/stdlib.h (__strtoqd_internal): Likewise.
* include/stdlib.h (strtoqd): Likewise.
* include/stdlib.h (strtoqd_l): Likewise.
* include/stdlib.h (__strtoqd_l): Likewise.
* include/stdlib.h (__strtoqd_internal): Likewise.
* include/stdlib.h (____strtoqd_l_internal): Likewise.
* include/wchar.h (wcstoqd): Likewise.
* include/wchar.h (__wcstoqd_internal): Likewise.
* include/wchar.h (wcstoqd_l): Likewise.
* include/wchar.h (__wcstoqd_l): Likewise.
* include/wchar.h (____wcstoqd_l_internal): Likewise.
* include/printf.h: Include next <printf.h> instead of
<stdio-common/printf.h>.
* math/math_private.h: Include <math_quad.h> if HAVE_FLOAT128
is defined.
* stdio-common/printf-parse.h (printf_arg): Add pa_float128
if HAVE_FLOAT128 is defined.
* stdio-common/printf-parsemb.c (__parse_one_specmb): Support
__float128 if HAVE_FLOAT128 is defined.
* stdio-common/printf_fp.c (__printf_fp): Likewise.
* stdio-common/printf_size.c (printf_size): Likewise.
* stdio-common/printf_size.c (printf_size_info): Likewise.
* stdio-common/vfprintf.c (vfprintf): Likewise.
* stdio-common/vfscanf.c (_IO_vfscanf): Likewise.
* stdlib/strfmon_l.c (__vstrfmon_l): Likewise.
* sysdeps/generic/printf_fphex.c (__printf_fphex): Likewise.
* stdio-common/printf_size.c: Include <ieee754-quad.h> if
HAVE_FLOAT128 is defined.
* stdio-common/vfscanf.c: Likewise.
* sysdeps/generic/printf_fphex.c: Likewise.
* stdio-common/printf_fp.c (__mpn_extract_double): Removed.
(__mpn_extract_long_double): Likewise.
* stdio-common/printf.h: Moved to ...
* sysdeps/generic/printf.h: Here.
* sysdeps/ieee754/quad/Makefile: New file.
* sysdeps/ieee754/quad/bits/huge_valq.h: Likewise.
* sysdeps/ieee754/quad/float.h: Likewise.
* sysdeps/ieee754/quad/ieee754-quad.h: Likewise.
* sysdeps/ieee754/quad/math_quad.h: Likewise.
* sysdeps/ieee754/quad/mpn2quad.c: Likewise.
* sysdeps/ieee754/quad/printf.h: Likewise.
* sysdeps/ieee754/quad/printf_quadfphex.h: Likewise.
* sysdeps/ieee754/quad/quad2mpn.c: Likewise.
* sysdeps/ieee754/quad/s_isinfq.c: Likewise.
* sysdeps/ieee754/quad/s_isnanq.c: Likewise.
* sysdeps/ieee754/quad/s_signbitq.c: Likewise.
* sysdeps/ieee754/quad/strtoqd.c: Likewise.
* sysdeps/ieee754/quad/strtoqd_l.c: Likewise.
* sysdeps/ieee754/quad/wcstoqd.c: Likewise.
* sysdeps/ieee754/quad/wcstoqd_l.c: Likewise.
--- libc/config.h.in.float128 2004-05-05 14:48:53.000000000 -0700
+++ libc/config.h.in 2004-05-05 14:48:54.000000000 -0700
@@ -211,6 +211,9 @@
/* Defined of libidn is available. */
#undef HAVE_LIBIDN
+/* Defined of __float128 is supported. */
+#undef HAVE_FLOAT128
+
/*
*/
--- libc/configure.in.float128 2004-05-05 14:48:53.000000000 -0700
+++ libc/configure.in 2004-05-05 14:48:54.000000000 -0700
@@ -448,6 +448,20 @@ if test "$base_machine" = "i386"; then
AC_DEFINE(USE_REGPARMS)
fi
+# We need to deal with __float here to include sysdeps/ieee754/quad
+# if __float128 is supported.
+AC_CACHE_CHECK(__float128 is supported,
+ libc_cv_float128,
+ [cat > conftest.c <<EOF
+ __float128 x = 1;
+EOF
+ libc_cv_float128=no
+ if AC_TRY_COMMAND(${CC-cc} -Werror -S conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then
+ libc_cv_float128=yes
+ fi
+ rm -f conftest.[cs]
+ ])
+
# Compute the list of sysdep directories for this configuration.
# This can take a while to compute.
sysdep_dir=$srcdir/sysdeps
@@ -585,10 +599,23 @@ fi
# from each element's parent name and Implies file (if present).
set $sysnames
names=
+have_float128=no
while test $# -gt 0; do
name=$1
shift
+ if test $libc_cv_float128 = yes; then
+ if test "$name" = "sysdeps/ieee754/ldbl-96"; then
+ case " $names " in *" sysdeps/ieee754/quad "*)
+ # Already in the list.
+ continue
+ esac
+ echo $ECHO_N "sysdeps/ieee754/quad $ECHO_C" >&AS_MESSAGE_FD
+ names="$names sysdeps/ieee754/quad"
+ have_float128=yes
+ fi
+ fi
+
case " $names " in *" $name "*)
# Already in the list.
continue
@@ -667,6 +694,9 @@ AC_SUBST(sysnames)
# The other names were emitted during the scan.
AC_MSG_RESULT($default_sysnames)
+if test $have_float128 = yes; then
+ AC_DEFINE(HAVE_FLOAT128)
+fi
### Locate tools.
--- libc/include/gmp.h.float128 2003-03-19 08:15:40.000000000 -0800
+++ libc/include/gmp.h 2004-05-05 14:48:54.000000000 -0700
@@ -23,5 +23,13 @@ extern double __mpn_construct_double (mp
extern long double __mpn_construct_long_double (mp_srcptr frac_ptr, int expt,
int sign);
+#ifdef HAVE_FLOAT128
+extern mp_size_t __mpn_extract_float128 (mp_ptr res_ptr, mp_size_t size,
+ int *expt, int *is_neg,
+ __float128 value);
+
+extern __float128 __mpn_construct_float128 (mp_srcptr frac_ptr,
+ int expt, int negative);
+#endif
#endif
--- libc/include/math.h.float128 2002-09-09 17:41:44.000000000 -0700
+++ libc/include/math.h 2004-05-05 14:48:54.000000000 -0700
@@ -28,4 +28,13 @@ libm_hidden_proto (__fpclassifyl)
libm_hidden_proto (__expm1l)
# endif
+# ifdef HAVE_FLOAT128
+extern int __isinfq (__float128);
+extern int __isnanq (__float128);
+extern int __signbitq (__float128);
+
+hidden_proto (__isinfq)
+hidden_proto (__isnanq)
+# endif
+
#endif
--- libc/include/printf.h.float128 2002-08-02 23:15:15.000000000 -0700
+++ libc/include/printf.h 2004-05-06 11:54:43.000000000 -0700
@@ -1,6 +1,6 @@
#ifndef _PRINTF_H
-#include <stdio-common/printf.h>
+#include_next <printf.h>
/* Now define the internal interfaces. */
extern int __printf_fphex (FILE *, const struct printf_info *,
--- libc/include/stdlib.h.float128 2004-02-06 12:36:00.000000000 -0800
+++ libc/include/stdlib.h 2004-05-05 14:48:54.000000000 -0700
@@ -194,6 +194,37 @@ __strtoull_l (__const char * __restrict
# define __cxa_atexit(func, arg, d) INTUSE(__cxa_atexit) (func, arg, d)
# endif
+#ifdef HAVE_FLOAT128
+extern __float128 __strtoqd_internal (__const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __group) __THROW;
+
+extern __float128 strtoqd (__const char *__restrict __nptr,
+ char **__restrict __endptr) __THROW;
+
+extern __float128 strtoqd_l (__const char *__restrict __nptr,
+ char **__restrict __endptr,
+ __locale_t __loc) __THROW;
+
+extern __typeof (strtoqd_l) __strtoqd_l;
+
+libc_hidden_proto (__strtoqd_internal)
+
+extern __float128 ____strtoqd_l_internal (__const char *__restrict __nptr,
+ char **__restrict __endptr,
+ int __group, __locale_t __loc)
+ __THROW;
+
+libc_hidden_proto (____strtoqd_l_internal)
+
+extern __inline __float128
+__strtoqd_l (__const char *__restrict __nptr, char **__restrict __endptr,
+ __locale_t __loc) __THROW
+{
+ return ____strtoqd_l_internal (__nptr, __endptr, 0, __loc);
+}
+#endif
+
#endif
extern void * __default_morecore (ptrdiff_t);
--- libc/include/wchar.h.float128 2004-03-15 12:43:44.000000000 -0800
+++ libc/include/wchar.h 2004-05-05 14:48:54.000000000 -0700
@@ -123,5 +123,28 @@ extern size_t __mbsrtowcs_l (wchar_t *ds
# define mbsinit(state) ((state)->__count == 0)
# define __mbsinit(state) ((state)->__count == 0)
+# ifdef HAVE_FLOAT128
+extern __float128 wcstoqd (__const wchar_t *__restrict __nptr,
+ wchar_t **__restrict __endptr) __THROW;
+extern __float128 __wcstoqd_internal (__const wchar_t *__restrict __nptr,
+ wchar_t **__restrict __endptr,
+ int __group) __THROW;
+
+
+extern __float128 wcstoqd_l (__const wchar_t *__restrict __nptr,
+ wchar_t **__restrict __endptr,
+ __locale_t __loc) __THROW;
+extern __typeof (wcstoqd_l) __wcstoqd_l;
+
+extern __float128 ____wcstoqd_l_internal (__const wchar_t *__restrict __nptr,
+ wchar_t **__restrict __endptr,
+ int __group,
+ __locale_t __loc) __THROW;
+
+libc_hidden_proto (__wcstoqd_internal)
+libc_hidden_proto (____wcstoqd_l_internal)
+
+# endif
+
# endif
#endif
--- libc/math/math_private.h.float128 2003-09-04 09:10:31.000000000 -0700
+++ libc/math/math_private.h 2004-05-05 14:48:54.000000000 -0700
@@ -20,6 +20,10 @@
#include <endian.h>
#include <sys/types.h>
+#ifdef HAVE_FLOAT128
+#include <math_quad.h>
+#endif
+
/* The original fdlibm code used statements like:
n0 = ((*(int*)&one)>>29)^1; * index of high word *
ix0 = *(n0+(int*)&x); * high word of x *
--- libc/stdio-common/printf-parse.h.float128 2003-06-12 07:53:10.000000000 -0700
+++ libc/stdio-common/printf-parse.h 2004-05-05 14:48:54.000000000 -0700
@@ -57,6 +57,9 @@ union printf_arg
const char *pa_string;
const wchar_t *pa_wstring;
void *pa_pointer;
+#ifdef HAVE_FLOAT128
+ __float128 pa_float128;
+#endif
};
--- libc/stdio-common/printf-parsemb.c.float128 2003-06-12 08:17:00.000000000 -0700
+++ libc/stdio-common/printf-parsemb.c 2004-05-06 11:02:58.000000000 -0700
@@ -351,6 +351,11 @@ __parse_one_specmb (const UCHAR_T *forma
case L'G':
case L'a':
case L'A':
+#ifdef HAVE_FLOAT128
+ if (spec->info.is_float128)
+ spec->data_arg_type = PA_DOUBLE|PA_FLAG_FLOAT128;
+ else
+#endif
if (spec->info.is_long_double)
spec->data_arg_type = PA_DOUBLE|PA_FLAG_LONG_DOUBLE;
else
--- libc/stdio-common/printf.h.float128 2001-07-23 16:42:48.000000000 -0700
+++ libc/stdio-common/printf.h 2004-05-06 11:55:03.000000000 -0700
@@ -1,145 +0,0 @@
-/* Copyright (C) 1991-1993,1995-1999,2000,2001 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, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#ifndef _PRINTF_H
-
-#define _PRINTF_H 1
-#include <features.h>
-
-__BEGIN_DECLS
-
-#define __need_FILE
-#include <stdio.h>
-#define __need_size_t
-#define __need_wchar_t
-#include <stddef.h>
-
-
-struct printf_info
-{
- int prec; /* Precision. */
- int width; /* Width. */
- wchar_t spec; /* Format letter. */
- unsigned int is_long_double:1;/* L flag. */
- unsigned int is_short:1; /* h flag. */
- unsigned int is_long:1; /* l flag. */
- unsigned int alt:1; /* # flag. */
- unsigned int space:1; /* Space flag. */
- unsigned int left:1; /* - flag. */
- unsigned int showsign:1; /* + flag. */
- unsigned int group:1; /* ' flag. */
- unsigned int extra:1; /* For special use. */
- unsigned int is_char:1; /* hh flag. */
- unsigned int wide:1; /* Nonzero for wide character streams. */
- unsigned int i18n:1; /* I flag. */
- wchar_t pad; /* Padding character. */
-};
-
-
-/* Type of a printf specifier-handler function.
- STREAM is the FILE on which to write output.
- INFO gives information about the format specification.
- ARGS is a vector of pointers to the argument data;
- the number of pointers will be the number returned
- by the associated arginfo function for the same INFO.
-
- The function should return the number of characters written,
- or -1 for errors. */
-
-typedef int printf_function (FILE *__stream,
- __const struct printf_info *__info,
- __const void *__const *__args);
-
-/* Type of a printf specifier-arginfo function.
- INFO gives information about the format specification.
- N, ARGTYPES, and return value are as for parse_printf_format. */
-
-typedef int printf_arginfo_function (__const struct printf_info *__info,
- size_t __n, int *__argtypes);
-
-
-/* Register FUNC to be called to format SPEC specifiers; ARGINFO must be
- specified to determine how many arguments a SPEC conversion requires and
- what their types are. */
-
-extern int register_printf_function (int __spec, printf_function __func,
- printf_arginfo_function __arginfo);
-
-
-/* Parse FMT, and fill in N elements of ARGTYPES with the
- types needed for the conversions FMT specifies. Returns
- the number of arguments required by FMT.
-
- The ARGINFO function registered with a user-defined format is passed a
- `struct printf_info' describing the format spec being parsed. A width
- or precision of INT_MIN means a `*' was used to indicate that the
- width/precision will come from an arg. The function should fill in the
- array it is passed with the types of the arguments it wants, and return
- the number of arguments it wants. */
-
-extern size_t parse_printf_format (__const char *__restrict __fmt, size_t __n,
- int *__restrict __argtypes) __THROW;
-
-
-/* Codes returned by `parse_printf_format' for basic types.
-
- These values cover all the standard format specifications.
- Users can add new values after PA_LAST for their own types. */
-
-enum
-{ /* C type: */
- PA_INT, /* int */
- PA_CHAR, /* int, cast to char */
- PA_WCHAR, /* wide char */
- PA_STRING, /* const char *, a '\0'-terminated string */
- PA_WSTRING, /* const wchar_t *, wide character string */
- PA_POINTER, /* void * */
- PA_FLOAT, /* float */
- PA_DOUBLE, /* double */
- PA_LAST
-};
-
-/* Flag bits that can be set in a type returned by `parse_printf_format'. */
-#define PA_FLAG_MASK 0xff00
-#define PA_FLAG_LONG_LONG (1 << 8)
-#define PA_FLAG_LONG_DOUBLE PA_FLAG_LONG_LONG
-#define PA_FLAG_LONG (1 << 9)
-#define PA_FLAG_SHORT (1 << 10)
-#define PA_FLAG_PTR (1 << 11)
-
-
-
-/* Function which can be registered as `printf'-handlers. */
-
-/* Print floating point value using using abbreviations for the orders
- of magnitude used for numbers ('k' for kilo, 'm' for mega etc). If
- the format specifier is a uppercase character powers of 1000 are
- used. Otherwise powers of 1024. */
-extern int printf_size (FILE *__restrict __fp,
- __const struct printf_info *__info,
- __const void *__const *__restrict __args) __THROW;
-
-/* This is the appropriate argument information function for `printf_size'. */
-extern int printf_size_info (__const struct printf_info *__restrict
- __info, size_t __n, int *__restrict __argtypes)
- __THROW;
-
-
-__END_DECLS
-
-#endif /* printf.h */
--- libc/stdio-common/printf_fp.c.float128 2004-03-26 10:57:38.000000000 -0800
+++ libc/stdio-common/printf_fp.c 2004-05-06 11:31:17.000000000 -0700
@@ -45,6 +45,14 @@
# define CHAR_T char
#endif
+#ifdef HAVE_FLOAT128
+#define FLOAT_MANT_DIG QUAD_MANT_DIG
+#define FLOAT_MAX_10_EXP_LOG QUAD_MAX_10_EXP_LOG
+#else
+#define FLOAT_MANT_DIG LDBL_MANT_DIG
+#define FLOAT_MAX_10_EXP_LOG LDBL_MAX_10_EXP_LOG
+#endif
+
#include "_i18n_number.h"
#ifndef NDEBUG
@@ -121,12 +129,6 @@
extern int __isinfl_internal (long double) attribute_hidden;
extern int __isnanl_internal (long double) attribute_hidden;
-extern mp_size_t __mpn_extract_double (mp_ptr res_ptr, mp_size_t size,
- int *expt, int *is_neg,
- double value);
-extern mp_size_t __mpn_extract_long_double (mp_ptr res_ptr, mp_size_t size,
- int *expt, int *is_neg,
- long double value);
extern unsigned int __guess_grouping (unsigned int intdig_max,
const char *grouping);
@@ -147,6 +149,9 @@ __printf_fp (FILE *fp,
{
double dbl;
__long_double_t ldbl;
+#ifdef HAVE_FLOAT128
+ __float128 flt128;
+#endif
}
fpnum;
@@ -165,7 +170,7 @@ __printf_fp (FILE *fp,
/* We need just a few limbs for the input before shifting to the right
position. */
- mp_limb_t fp_input[(LDBL_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB];
+ mp_limb_t fp_input[(FLOAT_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB];
/* We need to shift the contents of fp_input by this amount of bits. */
int to_shift = 0;
@@ -309,6 +314,52 @@ __printf_fp (FILE *fp,
grouping = NULL;
/* Fetch the argument value. */
+#ifdef HAVE_FLOAT128
+ if (info->is_float128)
+ {
+ fpnum.flt128 = *(const __float128 *) args[0];
+
+ /* Check for special values: not a number or infinity. */
+ if (__isnanq (fpnum.flt128))
+ {
+ if (isupper (info->spec))
+ {
+ special = "NAN";
+ wspecial = L"NAN";
+ }
+ else
+ {
+ special = "nan";
+ wspecial = L"nan";
+ }
+ is_neg = 0;
+ }
+ else if (__isinfq (fpnum.flt128))
+ {
+ if (isupper (info->spec))
+ {
+ special = "INF";
+ wspecial = L"INF";
+ }
+ else
+ {
+ special = "inf";
+ wspecial = L"inf";
+ }
+ is_neg = __signbitq (fpnum.flt128);
+ }
+ else
+ {
+ fracsize = __mpn_extract_float128 (fp_input,
+ (sizeof (fp_input) /
+ sizeof (fp_input[0])),
+ &exponent, &is_neg,
+ fpnum.flt128);
+ to_shift = 1 + fracsize * BITS_PER_MP_LIMB - QUAD_MANT_DIG;
+ }
+ }
+ else
+#endif
#ifndef __NO_LONG_DOUBLE_MATH
if (info->is_long_double && sizeof (long double) > sizeof (double))
{
@@ -446,7 +497,7 @@ __printf_fp (FILE *fp,
{
/* |FP| >= 8.0. */
int scaleexpo = 0;
- int explog = LDBL_MAX_10_EXP_LOG;
+ int explog = FLOAT_MAX_10_EXP_LOG;
int exp10 = 0;
const struct mp_power *powers = &_fpioconst_pow10[explog + 1];
int cnt_h, cnt_l, i;
@@ -479,10 +530,31 @@ __printf_fp (FILE *fp,
{
if (scalesize == 0)
{
+#ifdef HAVE_FLOAT128
+ if (QUAD_MANT_DIG > _FPIO_CONST_OFFSET * BITS_PER_MP_LIMB
+ && info->is_float128)
+ {
+#define _FPIO_CONST_SHIFT \
+ (((QUAD_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB) \
+ - _FPIO_CONST_OFFSET)
+ /* 64bit const offset is not enough for
+ IEEE quad long double. */
+ tmpsize = powers->arraysize + _FPIO_CONST_SHIFT;
+ memcpy (tmp + _FPIO_CONST_SHIFT,
+ &__tens[powers->arrayoff],
+ tmpsize * sizeof (mp_limb_t));
+ MPN_ZERO (tmp, _FPIO_CONST_SHIFT);
+ /* Adjust exponent, as scaleexpo will be this much
+ bigger too. */
+ exponent += _FPIO_CONST_SHIFT * BITS_PER_MP_LIMB;
+ }
+ else
+#endif
#ifndef __NO_LONG_DOUBLE_MATH
if (LDBL_MANT_DIG > _FPIO_CONST_OFFSET * BITS_PER_MP_LIMB
&& info->is_long_double)
{
+#undef _FPIO_CONST_SHIFT
#define _FPIO_CONST_SHIFT \
(((LDBL_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB) \
- _FPIO_CONST_OFFSET)
@@ -617,7 +689,7 @@ __printf_fp (FILE *fp,
{
/* |FP| < 1.0. */
int exp10 = 0;
- int explog = LDBL_MAX_10_EXP_LOG;
+ int explog = FLOAT_MAX_10_EXP_LOG;
const struct mp_power *powers = &_fpioconst_pow10[explog + 1];
mp_size_t used_limbs = fracsize - 1;
--- libc/stdio-common/printf_size.c.float128 2004-03-19 11:19:06.000000000 -0800
+++ libc/stdio-common/printf_size.c 2004-05-06 10:57:30.000000000 -0700
@@ -25,6 +25,9 @@
#include <printf.h>
#include <libioP.h>
+#ifdef HAVE_FLOAT128
+#include <ieee754-quad.h>
+#endif
/* This defines make it possible to use the same code for GNU C library and
the GNU I/O library. */
@@ -104,6 +107,9 @@ printf_size (FILE *fp, const struct prin
{
union ieee754_double dbl;
union ieee854_long_double ldbl;
+#ifdef HAVE_FLOAT128
+ union ieee854_float128 flt128;
+#endif
}
fpnum;
const void *ptr = &fpnum;
@@ -120,6 +126,39 @@ printf_size (FILE *fp, const struct prin
/* Fetch the argument value. */
+#ifdef HAVE_FLOAT128
+ if (info->is_float128)
+ {
+ fpnum.flt128.d = *(const __float128 *) args[0];
+
+ /* Check for special values: not a number or infinity. */
+ if (__isnanq (fpnum.flt128.d))
+ {
+ special = "nan";
+ wspecial = L"nan";
+ negative = 0;
+ }
+ else if (__isinfq (fpnum.flt128.d))
+ {
+ special = "inf";
+ wspecial = L"inf";
+
+ negative = __signbitq (fpnum.flt128.d);
+ }
+ else
+#if 1
+ /* FIXME: The __float128 algorithm doesn't work yet. */
+ abort ();
+#else
+ while (fpnum.flt128.d >= divisor && tag[1] != '\0')
+ {
+ fpnum.flt128.d /= divisor;
+ ++tag;
+ }
+#endif
+ }
+ else
+#endif
#ifndef __NO_LONG_DOUBLE_MATH
if (info->is_long_double && sizeof (long double) > sizeof (double))
{
@@ -204,6 +243,9 @@ printf_size (FILE *fp, const struct prin
fp_info.spec = 'f';
fp_info.prec = info->prec < 0 ? 3 : info->prec;
fp_info.is_long_double = info->is_long_double;
+#ifdef HAVE_FLOAT128
+ fp_info.is_float128 = info->is_float128;
+#endif
fp_info.is_short = info->is_short;
fp_info.is_long = info->is_long;
fp_info.alt = info->alt;
@@ -250,7 +292,14 @@ printf_size_info (const struct printf_in
{
/* We need only one double or long double argument. */
if (n >= 1)
+#ifdef HAVE_FLOAT128
+ argtypes[0] = (PA_DOUBLE
+ | ((info->is_long_double
+ ? PA_FLAG_LONG_DOUBLE
+ : (info->is_float128 ? PA_FLAG_FLOAT128 : 0))));
+#else
argtypes[0] = PA_DOUBLE | (info->is_long_double ? PA_FLAG_LONG_DOUBLE : 0);
+#endif
return 1;
}
--- libc/stdio-common/vfprintf.c.float128 2004-03-19 11:19:06.000000000 -0800
+++ libc/stdio-common/vfprintf.c 2004-05-06 11:41:41.000000000 -0700
@@ -433,7 +433,7 @@ vfprintf (FILE *s, const CHAR_T *format,
REF (form_unknown), /* for '.' */ \
REF (form_unknown), /* for 'h' */ \
REF (mod_longlong), /* for 'l' */ \
- REF (form_unknown), /* for 'L', 'q' */ \
+ REF (mod_float128), /* for 'L', 'q' */ \
REF (form_unknown), /* for 'z', 'Z' */ \
REF (form_percent), /* for '%' */ \
REF (form_integer), /* for 'd', 'i' */ \
@@ -490,6 +490,16 @@ vfprintf (FILE *s, const CHAR_T *format,
}
+#ifdef HAVE_FLOAT128
+#define INIT_FLOAT128 .is_float128 = is_float128,
+#define CHECK_FLOAT128 if (is_float128) \
+ the_arg.pa_float128 = va_arg (ap, __float128); \
+ else
+#else
+#define INIT_FLOAT128
+#define CHECK_FLOAT128
+#endif
+
#define process_arg(fspec) \
/* Start real work. We know about all flags and modifiers and \
now process the wanted format specifier. */ \
@@ -767,8 +777,10 @@ vfprintf (FILE *s, const CHAR_T *format,
.pad = pad, \
.extra = 0, \
.i18n = use_outdigits, \
+ INIT_FLOAT128 \
.wide = sizeof (CHAR_T) != 1 }; \
\
+ CHECK_FLOAT128 \
if (is_long_double) \
the_arg.pa_long_double = va_arg (ap, long double); \
else \
@@ -809,6 +821,7 @@ vfprintf (FILE *s, const CHAR_T *format,
.is_long_double = is_long_double, \
.is_short = is_short, \
.is_long = is_long, \
+ INIT_FLOAT128 \
.alt = alt, \
.space = space, \
.left = left, \
@@ -818,6 +831,7 @@ vfprintf (FILE *s, const CHAR_T *format,
.extra = 0, \
.wide = sizeof (CHAR_T) != 1 }; \
\
+ CHECK_FLOAT128 \
if (is_long_double) \
the_arg.pa_long_double = va_arg (ap, long double); \
else \
@@ -1293,6 +1307,9 @@ vfprintf (FILE *s, const CHAR_T *format,
int is_short = 0; /* Argument is short int. */
int is_long = 0; /* Argument is long int. */
int is_char = 0; /* Argument is promoted (unsigned) char. */
+#ifdef HAVE_FLOAT128
+ int is_float128 = 0; /* Argument is float128. */
+#endif
int width = 0; /* Width of output; 0 means none specified. */
int prec = -1; /* Precision of output; -1 means none specified. */
/* This flag is set by the 'I' modifier and selects the use of the
@@ -1495,6 +1512,16 @@ vfprintf (FILE *s, const CHAR_T *format,
is_long = 1;
JUMP (*++f, step4_jumps);
+ LABEL (mod_float128):
+#ifdef HAVE_FLOAT128
+ if (*f != 'L')
+ goto LABEL (form_unknown);
+ is_float128 = 1;
+ JUMP (*++f, step4_jumps);
+#else
+ goto LABEL (form_unknown);
+#endif
+
LABEL (mod_size_t):
is_long_double = sizeof (size_t) > sizeof (unsigned long int);
is_long = sizeof (size_t) > sizeof (unsigned int);
@@ -1686,6 +1713,9 @@ do_positional:
T (PA_FLOAT, pa_double, double); /* Promoted. */
T (PA_DOUBLE, pa_double, double);
T (PA_DOUBLE|PA_FLAG_LONG_DOUBLE, pa_long_double, long double);
+#ifdef HAVE_FLOAT128
+ T (PA_DOUBLE|PA_FLAG_FLOAT128, pa_float128, __float128);
+#endif
T (PA_STRING, pa_string, const char *);
T (PA_WSTRING, pa_wstring, const wchar_t *);
T (PA_POINTER, pa_pointer, void *);
@@ -1728,6 +1758,9 @@ do_positional:
int showsign = specs[nspecs_done].info.showsign;
int group = specs[nspecs_done].info.group;
int is_long_double = specs[nspecs_done].info.is_long_double;
+#ifdef HAVE_FLOAT128
+ int is_float128 = specs[nspecs_done].info.is_float128;
+#endif
int is_short = specs[nspecs_done].info.is_short;
int is_char = specs[nspecs_done].info.is_char;
int is_long = specs[nspecs_done].info.is_long;
--- libc/stdio-common/vfscanf.c.float128 2004-04-21 09:36:18.000000000 -0700
+++ libc/stdio-common/vfscanf.c 2004-05-05 14:48:54.000000000 -0700
@@ -30,6 +30,10 @@
#include <bits/libc-lock.h>
#include <locale/localeinfo.h>
+#ifdef HAVE_FLOAT128
+#include <ieee754-quad.h>
+#endif
+
#ifdef __GNUC__
# define HAVE_LONGLONG
# define LONGLONG long long
@@ -63,6 +67,7 @@
#define MALLOC 0x100 /* a: malloc strings */
#define CHAR 0x200 /* hh: char */
#define I18N 0x400 /* I: use locale's digits */
+#define FLOAT128 0x800 /* lL: IEEE Quda */
#include <locale/localeinfo.h>
@@ -95,6 +100,7 @@
# define __strtol_internal __wcstol_internal
# define __strtoul_internal __wcstoul_internal
# define __strtold_internal __wcstold_internal
+# define __strtoqd_internal __wcstoqd_internal
# define __strtod_internal __wcstod_internal
# define __strtof_internal __wcstof_internal
@@ -491,6 +497,13 @@ _IO_vfscanf (s, format, argptr, errp)
++f;
flags |= LONGDBL | LONG;
}
+#ifdef HAVE_FLOAT128
+ else if (*f == L_('L'))
+ {
+ ++f;
+ flags |= FLOAT128;
+ }
+#endif
else
/* ints are long ints. */
flags |= LONG;
@@ -1808,6 +1821,15 @@ _IO_vfscanf (s, format, argptr, errp)
scan_float:
/* Convert the number. */
ADDW (L_('\0'));
+#ifdef HAVE_FLOAT128
+ if (flags & FLOAT128)
+ {
+ __float128 d = __strtoqd_internal (wp, &tw, flags & GROUP);
+ if (!(flags & SUPPRESS) && tw != wp)
+ *ARG (__float128 *) = negative ? -d : d;
+ }
+ else
+#endif
if (flags & LONGDBL)
{
long double d = __strtold_internal (wp, &tw, flags & GROUP);
--- libc/stdlib/strfmon_l.c.float128 2004-03-15 12:43:46.000000000 -0800
+++ libc/stdlib/strfmon_l.c 2004-05-06 11:31:45.000000000 -0700
@@ -114,6 +114,9 @@ __vstrfmon_l (char *s, size_t maxsize, _
{
double dbl;
__long_double_t ldbl;
+#ifdef HAVE_FLOAT128
+ __float128 flt128;
+#endif
}
fpnum;
int int_format;
@@ -124,6 +127,9 @@ __vstrfmon_l (char *s, size_t maxsize, _
int group;
char pad;
int is_long_double;
+#ifdef HAVE_FLOAT128
+ int is_float128;
+#endif
int p_sign_posn;
int n_sign_posn;
int sign_posn;
@@ -168,6 +174,9 @@ __vstrfmon_l (char *s, size_t maxsize, _
group = 1; /* Print digits grouped. */
pad = ' '; /* Fill character is <SP>. */
is_long_double = 0; /* Double argument by default. */
+#ifdef HAVE_FLOAT128
+ is_float128 = 0;
+#endif
p_sign_posn = -1; /* This indicates whether the */
n_sign_posn = -1; /* '(' flag is given. */
width = -1; /* No width specified so far. */
@@ -280,6 +289,13 @@ __vstrfmon_l (char *s, size_t maxsize, _
++fmt;
is_long_double = 1;
}
+#ifdef HAVE_FLOAT128
+ else if (*fmt == 'Q')
+ {
+ ++fmt;
+ is_float128 = 1;
+ }
+#endif
/* Handle format specifier. */
char int_symbol[4];
@@ -333,6 +349,16 @@ __vstrfmon_l (char *s, size_t maxsize, _
MON_THOUSANDS_SEP));
/* Now it's time to get the value. */
+#ifdef HAVE_FLOAT128
+ if (is_float128 == 1)
+ {
+ fpnum.flt128 = va_arg (ap, __float128);
+ is_negative = __signbitq (fpnum.flt128);
+ if (is_negative)
+ fpnum.flt128 = -fpnum.flt128;
+ }
+ else
+#endif
if (is_long_double == 1)
{
fpnum.ldbl = va_arg (ap, long double);
@@ -547,6 +573,9 @@ __vstrfmon_l (char *s, size_t maxsize, _
info.width = left_prec + (right_prec ? (right_prec + 1) : 0);
info.spec = 'f';
info.is_long_double = is_long_double;
+#ifdef HAVE_FLOAT128
+ info.is_float128 = is_float128;
+#endif
info.is_short = 0;
info.is_long = 0;
info.alt = 0;
--- libc/sysdeps/generic/printf.h.float128 2004-05-06 11:51:39.000000000 -0700
+++ libc/sysdeps/generic/printf.h 2001-07-23 16:42:48.000000000 -0700
@@ -0,0 +1,145 @@
+/* Copyright (C) 1991-1993,1995-1999,2000,2001 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _PRINTF_H
+
+#define _PRINTF_H 1
+#include <features.h>
+
+__BEGIN_DECLS
+
+#define __need_FILE
+#include <stdio.h>
+#define __need_size_t
+#define __need_wchar_t
+#include <stddef.h>
+
+
+struct printf_info
+{
+ int prec; /* Precision. */
+ int width; /* Width. */
+ wchar_t spec; /* Format letter. */
+ unsigned int is_long_double:1;/* L flag. */
+ unsigned int is_short:1; /* h flag. */
+ unsigned int is_long:1; /* l flag. */
+ unsigned int alt:1; /* # flag. */
+ unsigned int space:1; /* Space flag. */
+ unsigned int left:1; /* - flag. */
+ unsigned int showsign:1; /* + flag. */
+ unsigned int group:1; /* ' flag. */
+ unsigned int extra:1; /* For special use. */
+ unsigned int is_char:1; /* hh flag. */
+ unsigned int wide:1; /* Nonzero for wide character streams. */
+ unsigned int i18n:1; /* I flag. */
+ wchar_t pad; /* Padding character. */
+};
+
+
+/* Type of a printf specifier-handler function.
+ STREAM is the FILE on which to write output.
+ INFO gives information about the format specification.
+ ARGS is a vector of pointers to the argument data;
+ the number of pointers will be the number returned
+ by the associated arginfo function for the same INFO.
+
+ The function should return the number of characters written,
+ or -1 for errors. */
+
+typedef int printf_function (FILE *__stream,
+ __const struct printf_info *__info,
+ __const void *__const *__args);
+
+/* Type of a printf specifier-arginfo function.
+ INFO gives information about the format specification.
+ N, ARGTYPES, and return value are as for parse_printf_format. */
+
+typedef int printf_arginfo_function (__const struct printf_info *__info,
+ size_t __n, int *__argtypes);
+
+
+/* Register FUNC to be called to format SPEC specifiers; ARGINFO must be
+ specified to determine how many arguments a SPEC conversion requires and
+ what their types are. */
+
+extern int register_printf_function (int __spec, printf_function __func,
+ printf_arginfo_function __arginfo);
+
+
+/* Parse FMT, and fill in N elements of ARGTYPES with the
+ types needed for the conversions FMT specifies. Returns
+ the number of arguments required by FMT.
+
+ The ARGINFO function registered with a user-defined format is passed a
+ `struct printf_info' describing the format spec being parsed. A width
+ or precision of INT_MIN means a `*' was used to indicate that the
+ width/precision will come from an arg. The function should fill in the
+ array it is passed with the types of the arguments it wants, and return
+ the number of arguments it wants. */
+
+extern size_t parse_printf_format (__const char *__restrict __fmt, size_t __n,
+ int *__restrict __argtypes) __THROW;
+
+
+/* Codes returned by `parse_printf_format' for basic types.
+
+ These values cover all the standard format specifications.
+ Users can add new values after PA_LAST for their own types. */
+
+enum
+{ /* C type: */
+ PA_INT, /* int */
+ PA_CHAR, /* int, cast to char */
+ PA_WCHAR, /* wide char */
+ PA_STRING, /* const char *, a '\0'-terminated string */
+ PA_WSTRING, /* const wchar_t *, wide character string */
+ PA_POINTER, /* void * */
+ PA_FLOAT, /* float */
+ PA_DOUBLE, /* double */
+ PA_LAST
+};
+
+/* Flag bits that can be set in a type returned by `parse_printf_format'. */
+#define PA_FLAG_MASK 0xff00
+#define PA_FLAG_LONG_LONG (1 << 8)
+#define PA_FLAG_LONG_DOUBLE PA_FLAG_LONG_LONG
+#define PA_FLAG_LONG (1 << 9)
+#define PA_FLAG_SHORT (1 << 10)
+#define PA_FLAG_PTR (1 << 11)
+
+
+
+/* Function which can be registered as `printf'-handlers. */
+
+/* Print floating point value using using abbreviations for the orders
+ of magnitude used for numbers ('k' for kilo, 'm' for mega etc). If
+ the format specifier is a uppercase character powers of 1000 are
+ used. Otherwise powers of 1024. */
+extern int printf_size (FILE *__restrict __fp,
+ __const struct printf_info *__info,
+ __const void *__const *__restrict __args) __THROW;
+
+/* This is the appropriate argument information function for `printf_size'. */
+extern int printf_size_info (__const struct printf_info *__restrict
+ __info, size_t __n, int *__restrict __argtypes)
+ __THROW;
+
+
+__END_DECLS
+
+#endif /* printf.h */
--- libc/sysdeps/generic/printf_fphex.c.float128 2002-10-23 18:15:31.000000000 -0700
+++ libc/sysdeps/generic/printf_fphex.c 2004-05-05 14:48:55.000000000 -0700
@@ -30,6 +30,10 @@
#include "_itowa.h"
#include <locale/localeinfo.h>
+#ifdef HAVE_FLOAT128
+#include <ieee754-quad.h>
+#endif
+
/* #define NDEBUG 1*/ /* Undefine this for debugging assertions. */
#include <assert.h>
@@ -99,6 +103,9 @@ __printf_fphex (FILE *fp,
{
union ieee754_double dbl;
union ieee854_long_double ldbl;
+#ifdef HAVE_FLOAT128
+ union ieee854_float128 flt128;
+#endif
}
fpnum;
@@ -164,6 +171,47 @@ __printf_fphex (FILE *fp,
/* Fetch the argument value. */
+#ifdef HAVE_FLOAT128
+ if (info->is_float128)
+ {
+ fpnum.flt128.d = *(const __float128 *) args[0];
+
+ /* Check for special values: not a number or infinity. */
+ if (__isnanq (fpnum.flt128.d))
+ {
+ if (isupper (info->spec))
+ {
+ special = "NAN";
+ wspecial = L"NAN";
+ }
+ else
+ {
+ special = "nan";
+ wspecial = L"nan";
+ }
+ negative = 0;
+ }
+ else
+ {
+ if (__isinfq (fpnum.flt128.d))
+ {
+ if (isupper (info->spec))
+ {
+ special = "INF";
+ wspecial = L"INF";
+ }
+ else
+ {
+ special = "inf";
+ wspecial = L"inf";
+ }
+ }
+
+ negative = __signbitq (fpnum.flt128.d);
+ }
+ }
+ else
+#endif
#ifndef __NO_LONG_DOUBLE_MATH
if (info->is_long_double && sizeof (long double) > sizeof (double))
{
@@ -269,7 +317,12 @@ __printf_fphex (FILE *fp,
return done;
}
- if (info->is_long_double == 0 || sizeof (double) == sizeof (long double))
+ if ((info->is_long_double == 0
+#ifdef HAVE_FLOAT128
+ && info->is_float128 == 0
+#endif
+ )
+ || sizeof (double) == sizeof (long double))
{
/* We have 52 bits of mantissa plus one implicit digit. Since
52 bits are representable without rest using hexadecimal
@@ -330,6 +383,11 @@ __printf_fphex (FILE *fp,
exponent = -(exponent - IEEE754_DOUBLE_BIAS);
}
}
+#ifdef HAVE_FLOAT128
+# include <printf_quadfphex.h>
+ else if (info->is_float128)
+ PRINT_FPHEX_FLOAT128;
+#endif
#ifdef PRINT_FPHEX_LONG_DOUBLE
else
PRINT_FPHEX_LONG_DOUBLE;
--- libc/sysdeps/ieee754/quad/Makefile.float128 2004-05-05 14:48:55.000000000 -0700
+++ libc/sysdeps/ieee754/quad/Makefile 2004-05-05 14:48:55.000000000 -0700
@@ -0,0 +1,14 @@
+ifeq ($(subdir),stdlib)
+routines += mpn2quad quad2mpn strtoqd strtoqd_l
+endif
+
+ifeq ($(subdir),math)
+routines += s_isinfq s_isnanq s_signbitq
+endif
+
+ifeq ($(subdir),wcsmbs)
+routines += wcstoqd wcstoqd_l
+
+CFLAGS-wcstoqd.c = $(strtox-CFLAGS)
+CFLAGS-wcstoqd_l.c = $(strtox-CFLAGS)
+endif
--- libc/sysdeps/ieee754/quad/bits/huge_valq.h.float128 2004-05-05 14:48:55.000000000 -0700
+++ libc/sysdeps/ieee754/quad/bits/huge_valq.h 2004-05-05 14:48:55.000000000 -0700
@@ -0,0 +1,45 @@
+/* `HUGE_VALQ' constant for IEEE 754 machines (where it is infinity).
+ Used by <stdlib.h> and <math.h> functions for overflow.
+ Copyright (C) 2004
+ 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _MATH_H
+# error "Never use <bits/huge_valq.h> directly; include <math.h> instead."
+#endif
+
+/* IEEE positive infinity (-HUGE_VAL is negative infinity). */
+
+#include <endian.h>
+
+typedef union { unsigned char __c[16]; __float128 __qd; } __huge_valq_t;
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+# define __HUGE_VALQ_bytes { 0x7f, 0xff, 0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
+#endif
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define __HUGE_VALQ_bytes { 0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0xff, 0x7f }
+#endif
+
+#ifdef __GNUC__
+# define HUGE_VALQ (__extension__ \
+ ((__huge_valq_t) { __c : __HUGE_VALQ_bytes }).__qd)
+#else
+static __huge_valq_t __huge_valq = { __HUGE_VALQ_bytes };
+# define HUGE_VALQ (__huge_valq.__qd)
+#endif
--- libc/sysdeps/ieee754/quad/float.h.float128 2004-05-05 14:48:55.000000000 -0700
+++ libc/sysdeps/ieee754/quad/float.h 2004-05-05 14:48:55.000000000 -0700
@@ -0,0 +1,47 @@
+/* Copyright (C) 2004 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include_next <float.h>
+
+#ifndef QUAD_MANT_DIG
+#define QUAD_MANT_DIG 113
+#endif
+
+#ifndef QUAD_DIG
+#define QUAD_DIG 33
+#endif
+
+#ifndef QUAD_MIN_EXP
+#define QUAD_MIN_EXP (-16381)
+#endif
+
+#ifndef QUAD_MIN_10_EXP
+#define QUAD_MIN_10_EXP (-4931)
+#endif
+
+#ifndef QUAD_MAX_EXP
+#define QUAD_MAX_EXP 16384
+#endif
+
+#ifndef QUAD_MAX_10_EXP
+#define QUAD_MAX_10_EXP 4932
+#endif
+
+#ifndef QUAD_MAX_10_EXP_LOG
+#define QUAD_MAX_10_EXP_LOG 12
+#endif
--- libc/sysdeps/ieee754/quad/ieee754-quad.h.float128 2004-05-05 14:48:55.000000000 -0700
+++ libc/sysdeps/ieee754/quad/ieee754-quad.h 2004-05-05 14:48:55.000000000 -0700
@@ -0,0 +1,84 @@
+/* Copyright (C) 2004 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _IEEE754_QUAD_H
+
+#define _IEEE754_QUAD_H 1
+#include <features.h>
+
+#include <endian.h>
+
+__BEGIN_DECLS
+
+union ieee854_float128
+ {
+ __float128 d;
+
+ /* This is the IEEE 854 quad-precision format. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:16;
+ unsigned int mantissa1:32;
+ unsigned int mantissa2:32;
+ unsigned int mantissa3:32;
+#endif /* Big endian. */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa3:32;
+ unsigned int mantissa2:32;
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:16;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+#endif /* Little endian. */
+ } ieee;
+
+ /* This format makes it easier to see if a NaN is a signalling NaN. */
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned int negative:1;
+ unsigned int exponent:15;
+ unsigned int quiet_nan:1;
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa0:15;
+ unsigned int mantissa1:32;
+ unsigned int mantissa2:32;
+ unsigned int mantissa3:32;
+#else
+ /* Together these comprise the mantissa. */
+ unsigned int mantissa3:32;
+ unsigned int mantissa2:32;
+ unsigned int mantissa1:32;
+ unsigned int mantissa0:15;
+ unsigned int quiet_nan:1;
+ unsigned int exponent:15;
+ unsigned int negative:1;
+#endif
+ } ieee_nan;
+ };
+
+#define IEEE854_FLOAT128_BIAS 0x3fff /* Added to exponent. */
+
+__END_DECLS
+
+#endif /* ieee754-quad.h */
--- libc/sysdeps/ieee754/quad/math_quad.h.float128 2004-05-05 14:48:55.000000000 -0700
+++ libc/sysdeps/ieee754/quad/math_quad.h 2004-05-05 14:48:55.000000000 -0700
@@ -0,0 +1,90 @@
+#ifndef _MATH_PRIVATE_H_
+#error "Never use <math_quad.h> directly; include <math_private.h> instead."
+#endif
+
+/* A union which permits us to convert between a long double and
+ four 32 bit ints or two 64 bit ints. */
+
+#if __FLOAT_WORD_ORDER == BIG_ENDIAN
+
+typedef union
+{
+ __float128 value;
+ struct
+ {
+ u_int64_t msw;
+ u_int64_t lsw;
+ } parts64;
+ struct
+ {
+ u_int32_t w0, w1, w2, w3;
+ } parts32;
+} ieee854_long_double_shape_type;
+
+#endif
+
+#if __FLOAT_WORD_ORDER == LITTLE_ENDIAN
+
+typedef union
+{
+ __float128 value;
+ struct
+ {
+ u_int64_t lsw;
+ u_int64_t msw;
+ } parts64;
+ struct
+ {
+ u_int32_t w3, w2, w1, w0;
+ } parts32;
+} ieee854_long_double_shape_type;
+
+#endif
+
+/* Get two 64 bit ints from a long double. */
+
+#define GET_LDOUBLE_WORDS64(ix0,ix1,d) \
+do { \
+ ieee854_long_double_shape_type qw_u; \
+ qw_u.value = (d); \
+ (ix0) = qw_u.parts64.msw; \
+ (ix1) = qw_u.parts64.lsw; \
+} while (0)
+
+/* Set a long double from two 64 bit ints. */
+
+#define SET_LDOUBLE_WORDS64(d,ix0,ix1) \
+do { \
+ ieee854_long_double_shape_type qw_u; \
+ qw_u.parts64.msw = (ix0); \
+ qw_u.parts64.lsw = (ix1); \
+ (d) = qw_u.value; \
+} while (0)
+
+/* Get the more significant 64 bits of a long double mantissa. */
+
+#define GET_LDOUBLE_MSW64(v,d) \
+do { \
+ ieee854_long_double_shape_type sh_u; \
+ sh_u.value = (d); \
+ (v) = sh_u.parts64.msw; \
+} while (0)
+
+/* Set the more significant 64 bits of a long double mantissa from an int. */
+
+#define SET_LDOUBLE_MSW64(d,v) \
+do { \
+ ieee854_long_double_shape_type sh_u; \
+ sh_u.value = (d); \
+ sh_u.parts64.msw = (v); \
+ (d) = sh_u.value; \
+} while (0)
+
+/* Get the least significant 64 bits of a long double mantissa. */
+
+#define GET_LDOUBLE_LSW64(v,d) \
+do { \
+ ieee854_long_double_shape_type sh_u; \
+ sh_u.value = (d); \
+ (v) = sh_u.parts64.lsw; \
+} while (0)
--- libc/sysdeps/ieee754/quad/mpn2quad.c.float128 2004-05-05 14:48:55.000000000 -0700
+++ libc/sysdeps/ieee754/quad/mpn2quad.c 2004-05-05 14:48:55.000000000 -0700
@@ -0,0 +1,54 @@
+/* Copyright (C) 2004
+ 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include <ieee754-quad.h>
+#include <float.h>
+#include <math.h>
+
+/* Convert a multi-precision integer of the needed number of bits (113 for
+ long double) and an integral power of two to a `long double' in IEEE854
+ quad-precision format. */
+
+__float128
+__mpn_construct_float128 (mp_srcptr frac_ptr, int expt, int sign)
+{
+ union ieee854_float128 u;
+
+ u.ieee.negative = sign;
+ u.ieee.exponent = expt + IEEE854_FLOAT128_BIAS;
+#if BITS_PER_MP_LIMB == 32
+ u.ieee.mantissa3 = frac_ptr[0];
+ u.ieee.mantissa2 = frac_ptr[1];
+ u.ieee.mantissa1 = frac_ptr[2];
+ u.ieee.mantissa0 = frac_ptr[3] & (((mp_limb_t) 1
+ << (QUAD_MANT_DIG - 96)) - 1);
+#elif BITS_PER_MP_LIMB == 64
+ u.ieee.mantissa3 = frac_ptr[0] & (((mp_limb_t) 1 << 32) - 1);
+ u.ieee.mantissa2 = frac_ptr[0] >> 32;
+ u.ieee.mantissa1 = frac_ptr[1] & (((mp_limb_t) 1 << 32) - 1);
+ u.ieee.mantissa0 = (frac_ptr[1] >> 32) & (((mp_limb_t) 1
+ << (QUAD_MANT_DIG - 96)) - 1);
+#else
+ #error "mp_limb size " BITS_PER_MP_LIMB "not accounted for"
+#endif
+
+ return u.d;
+}
--- libc/sysdeps/ieee754/quad/printf.h.float128 2004-05-06 11:37:41.000000000 -0700
+++ libc/sysdeps/ieee754/quad/printf.h 2004-05-06 11:38:00.000000000 -0700
@@ -0,0 +1,147 @@
+/* Copyright (C) 2004 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _PRINTF_H
+
+#define _PRINTF_H 1
+#include <features.h>
+
+__BEGIN_DECLS
+
+#define __need_FILE
+#include <stdio.h>
+#define __need_size_t
+#define __need_wchar_t
+#include <stddef.h>
+
+
+struct printf_info
+{
+ int prec; /* Precision. */
+ int width; /* Width. */
+ wchar_t spec; /* Format letter. */
+ unsigned int is_long_double:1;/* L flag. */
+ unsigned int is_short:1; /* h flag. */
+ unsigned int is_long:1; /* l flag. */
+ unsigned int alt:1; /* # flag. */
+ unsigned int space:1; /* Space flag. */
+ unsigned int left:1; /* - flag. */
+ unsigned int showsign:1; /* + flag. */
+ unsigned int group:1; /* ' flag. */
+ unsigned int extra:1; /* For special use. */
+ unsigned int is_char:1; /* hh flag. */
+ unsigned int wide:1; /* Nonzero for wide character streams. */
+ unsigned int i18n:1; /* I flag. */
+ unsigned int is_float128:1; /* lL flag. */
+ wchar_t pad; /* Padding character. */
+};
+
+
+/* Type of a printf specifier-handler function.
+ STREAM is the FILE on which to write output.
+ INFO gives information about the format specification.
+ ARGS is a vector of pointers to the argument data;
+ the number of pointers will be the number returned
+ by the associated arginfo function for the same INFO.
+
+ The function should return the number of characters written,
+ or -1 for errors. */
+
+typedef int printf_function (FILE *__stream,
+ __const struct printf_info *__info,
+ __const void *__const *__args);
+
+/* Type of a printf specifier-arginfo function.
+ INFO gives information about the format specification.
+ N, ARGTYPES, and return value are as for parse_printf_format. */
+
+typedef int printf_arginfo_function (__const struct printf_info *__info,
+ size_t __n, int *__argtypes);
+
+
+/* Register FUNC to be called to format SPEC specifiers; ARGINFO must be
+ specified to determine how many arguments a SPEC conversion requires and
+ what their types are. */
+
+extern int register_printf_function (int __spec, printf_function __func,
+ printf_arginfo_function __arginfo);
+
+
+/* Parse FMT, and fill in N elements of ARGTYPES with the
+ types needed for the conversions FMT specifies. Returns
+ the number of arguments required by FMT.
+
+ The ARGINFO function registered with a user-defined format is passed a
+ `struct printf_info' describing the format spec being parsed. A width
+ or precision of INT_MIN means a `*' was used to indicate that the
+ width/precision will come from an arg. The function should fill in the
+ array it is passed with the types of the arguments it wants, and return
+ the number of arguments it wants. */
+
+extern size_t parse_printf_format (__const char *__restrict __fmt, size_t __n,
+ int *__restrict __argtypes) __THROW;
+
+
+/* Codes returned by `parse_printf_format' for basic types.
+
+ These values cover all the standard format specifications.
+ Users can add new values after PA_LAST for their own types. */
+
+enum
+{ /* C type: */
+ PA_INT, /* int */
+ PA_CHAR, /* int, cast to char */
+ PA_WCHAR, /* wide char */
+ PA_STRING, /* const char *, a '\0'-terminated string */
+ PA_WSTRING, /* const wchar_t *, wide character string */
+ PA_POINTER, /* void * */
+ PA_FLOAT, /* float */
+ PA_DOUBLE, /* double */
+ PA_LAST
+};
+
+/* Flag bits that can be set in a type returned by `parse_printf_format'. */
+#define PA_FLAG_MASK 0xff00
+#define PA_FLAG_LONG_LONG (1 << 8)
+#define PA_FLAG_LONG_DOUBLE PA_FLAG_LONG_LONG
+#define PA_FLAG_LONG (1 << 9)
+#define PA_FLAG_SHORT (1 << 10)
+#define PA_FLAG_PTR (1 << 11)
+#define PA_FLAG_FLOAT128 (1 << 12)
+
+
+
+/* Function which can be registered as `printf'-handlers. */
+
+/* Print floating point value using using abbreviations for the orders
+ of magnitude used for numbers ('k' for kilo, 'm' for mega etc). If
+ the format specifier is a uppercase character powers of 1000 are
+ used. Otherwise powers of 1024. */
+extern int printf_size (FILE *__restrict __fp,
+ __const struct printf_info *__info,
+ __const void *__const *__restrict __args) __THROW;
+
+/* This is the appropriate argument information function for `printf_size'. */
+extern int printf_size_info (__const struct printf_info *__restrict
+ __info, size_t __n, int *__restrict __argtypes)
+ __THROW;
+
+
+__END_DECLS
+
+#endif /* printf.h */
--- libc/sysdeps/ieee754/quad/printf_quadfphex.h.float128 2004-05-05 14:48:55.000000000 -0700
+++ libc/sysdeps/ieee754/quad/printf_quadfphex.h 2004-05-05 14:48:55.000000000 -0700
@@ -0,0 +1,102 @@
+/* Print floating point number in hexadecimal notation according to
+ ISO C99.
+ Copyright (C) 2004 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#define PRINT_FPHEX_FLOAT128 \
+do { \
+ /* We have 112 bits of mantissa plus one implicit digit. Since \
+ 112 bits are representable without rest using hexadecimal \
+ digits we use only the implicit digits for the number before \
+ the decimal point. */ \
+ unsigned long long int num0, num1; \
+ \
+ num0 = (((unsigned long long int) fpnum.flt128.ieee.mantissa0) << 32 \
+ | fpnum.flt128.ieee.mantissa1); \
+ num1 = (((unsigned long long int) fpnum.flt128.ieee.mantissa2) << 32 \
+ | fpnum.flt128.ieee.mantissa3); \
+ \
+ zero_mantissa = (num0|num1) == 0; \
+ \
+ if (sizeof (unsigned long int) > 6) \
+ { \
+ numstr = _itoa_word (num1, numbuf + sizeof numbuf, 16, \
+ info->spec == 'A'); \
+ wnumstr = _itowa_word (num1, \
+ wnumbuf + sizeof (wnumbuf) / sizeof (wchar_t),\
+ 16, info->spec == 'A'); \
+ } \
+ else \
+ { \
+ numstr = _itoa (num1, numbuf + sizeof numbuf, 16, \
+ info->spec == 'A'); \
+ wnumstr = _itowa (num1, \
+ wnumbuf + sizeof (wnumbuf) / sizeof (wchar_t), \
+ 16, info->spec == 'A'); \
+ } \
+ \
+ while (numstr > numbuf + (sizeof numbuf - 64 / 4)) \
+ { \
+ *--numstr = '0'; \
+ *--wnumstr = L'0'; \
+ } \
+ \
+ if (sizeof (unsigned long int) > 6) \
+ { \
+ numstr = _itoa_word (num0, numstr, 16, info->spec == 'A'); \
+ wnumstr = _itowa_word (num0, wnumstr, 16, info->spec == 'A'); \
+ } \
+ else \
+ { \
+ numstr = _itoa (num0, numstr, 16, info->spec == 'A'); \
+ wnumstr = _itowa (num0, wnumstr, 16, info->spec == 'A'); \
+ } \
+ \
+ /* Fill with zeroes. */ \
+ while (numstr > numbuf + (sizeof numbuf - 112 / 4)) \
+ { \
+ *--numstr = '0'; \
+ *--wnumstr = L'0'; \
+ } \
+ \
+ leading = fpnum.flt128.ieee.exponent == 0 ? '0' : '1'; \
+ \
+ exponent = fpnum.flt128.ieee.exponent; \
+ \
+ if (exponent == 0) \
+ { \
+ if (zero_mantissa) \
+ expnegative = 0; \
+ else \
+ { \
+ /* This is a denormalized number. */ \
+ expnegative = 1; \
+ exponent = IEEE854_FLOAT128_BIAS - 1; \
+ } \
+ } \
+ else if (exponent >= IEEE854_FLOAT128_BIAS) \
+ { \
+ expnegative = 0; \
+ exponent -= IEEE854_FLOAT128_BIAS; \
+ } \
+ else \
+ { \
+ expnegative = 1; \
+ exponent = -(exponent - IEEE854_FLOAT128_BIAS); \
+ } \
+} while (0)
--- libc/sysdeps/ieee754/quad/quad2mpn.c.float128 2004-05-05 14:48:55.000000000 -0700
+++ libc/sysdeps/ieee754/quad/quad2mpn.c 2004-05-05 14:48:55.000000000 -0700
@@ -0,0 +1,141 @@
+/* Copyright (C) 2004
+ 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include "gmp.h"
+#include "gmp-impl.h"
+#include "longlong.h"
+#include <ieee754-quad.h>
+#include <float.h>
+#include <math.h>
+#include <stdlib.h>
+
+/* Convert a `long double' in IEEE854 quad-precision format to a
+ multi-precision integer representing the significand scaled up by its
+ number of bits (113 for long double) and an integral power of two
+ (MPN frexpl). */
+
+mp_size_t
+__mpn_extract_float128 (mp_ptr res_ptr, mp_size_t size,
+ int *expt, int *is_neg,
+ __float128 value)
+{
+ union ieee854_float128 u;
+ u.d = value;
+
+ *is_neg = u.ieee.negative;
+ *expt = (int) u.ieee.exponent - IEEE854_FLOAT128_BIAS;
+
+#if BITS_PER_MP_LIMB == 32
+ res_ptr[0] = u.ieee.mantissa3; /* Low-order 32 bits of fraction. */
+ res_ptr[1] = u.ieee.mantissa2;
+ res_ptr[2] = u.ieee.mantissa1;
+ res_ptr[3] = u.ieee.mantissa0; /* High-order 32 bits. */
+ #define N 4
+#elif BITS_PER_MP_LIMB == 64
+ /* Hopefully the compiler will combine the two bitfield extracts
+ and this composition into just the original quadword extract. */
+ res_ptr[0] = ((mp_limb_t) u.ieee.mantissa2 << 32) | u.ieee.mantissa3;
+ res_ptr[1] = ((mp_limb_t) u.ieee.mantissa0 << 32) | u.ieee.mantissa1;
+ #define N 2
+#else
+ #error "mp_limb size " BITS_PER_MP_LIMB "not accounted for"
+#endif
+/* The format does not fill the last limb. There are some zeros. */
+#define NUM_LEADING_ZEROS (BITS_PER_MP_LIMB \
+ - (QUAD_MANT_DIG - ((N - 1) * BITS_PER_MP_LIMB)))
+
+ if (u.ieee.exponent == 0)
+ {
+ /* A biased exponent of zero is a special case.
+ Either it is a zero or it is a denormal number. */
+ if (res_ptr[0] == 0 && res_ptr[1] == 0
+ && res_ptr[N - 2] == 0 && res_ptr[N - 1] == 0) /* Assumes N<=4. */
+ /* It's zero. */
+ *expt = 0;
+ else
+ {
+ /* It is a denormal number, meaning it has no implicit leading
+ one bit, and its exponent is in fact the format minimum. */
+ int cnt;
+
+#if N == 2
+ if (res_ptr[N - 1] != 0)
+ {
+ count_leading_zeros (cnt, res_ptr[N - 1]);
+ cnt -= NUM_LEADING_ZEROS;
+ res_ptr[N - 1] = res_ptr[N - 1] << cnt
+ | (res_ptr[0] >> (BITS_PER_MP_LIMB - cnt));
+ res_ptr[0] <<= cnt;
+ *expt = QUAD_MIN_EXP - 1 - cnt;
+ }
+ else
+ {
+ count_leading_zeros (cnt, res_ptr[0]);
+ if (cnt >= NUM_LEADING_ZEROS)
+ {
+ res_ptr[N - 1] = res_ptr[0] << (cnt - NUM_LEADING_ZEROS);
+ res_ptr[0] = 0;
+ }
+ else
+ {
+ res_ptr[N - 1] = res_ptr[0] >> (NUM_LEADING_ZEROS - cnt);
+ res_ptr[0] <<= BITS_PER_MP_LIMB - (NUM_LEADING_ZEROS - cnt);
+ }
+ *expt = QUAD_MIN_EXP - 1
+ - (BITS_PER_MP_LIMB - NUM_LEADING_ZEROS) - cnt;
+ }
+#else
+ int j, k, l;
+
+ for (j = N - 1; j > 0; j--)
+ if (res_ptr[j] != 0)
+ break;
+
+ count_leading_zeros (cnt, res_ptr[j]);
+ cnt -= NUM_LEADING_ZEROS;
+ l = N - 1 - j;
+ if (cnt < 0)
+ {
+ cnt += BITS_PER_MP_LIMB;
+ l--;
+ }
+ if (!cnt)
+ for (k = N - 1; k >= l; k--)
+ res_ptr[k] = res_ptr[k-l];
+ else
+ {
+ for (k = N - 1; k > l; k--)
+ res_ptr[k] = res_ptr[k-l] << cnt
+ | res_ptr[k-l-1] >> (BITS_PER_MP_LIMB - cnt);
+ res_ptr[k--] = res_ptr[0] << cnt;
+ }
+
+ for (; k >= 0; k--)
+ res_ptr[k] = 0;
+ *expt = QUAD_MIN_EXP - 1 - l * BITS_PER_MP_LIMB - cnt;
+#endif
+ }
+ }
+ else
+ /* Add the implicit leading one bit for a normalized number. */
+ res_ptr[N - 1] |= (mp_limb_t) 1 << (QUAD_MANT_DIG - 1
+ - ((N - 1) * BITS_PER_MP_LIMB));
+
+ return N;
+}
--- libc/sysdeps/ieee754/quad/s_isinfq.c.float128 2004-05-05 14:48:55.000000000 -0700
+++ libc/sysdeps/ieee754/quad/s_isinfq.c 2004-05-05 14:48:55.000000000 -0700
@@ -0,0 +1,29 @@
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Change for long double by Jakub Jelinek <jj@ultra.linux.cz>
+ * Public domain.
+ */
+
+#if defined(LIBM_SCCS) && !defined(lint)
+static char rcsid[] = "$NetBSD: $";
+#endif
+
+/*
+ * isinfq(x) returns 1 if x is inf, -1 if x is -inf, else 0;
+ * no branching!
+ */
+
+#include <math.h>
+#include <math_private.h>
+
+int
+__isinfq (__float128 x)
+{
+ int64_t hx,lx;
+ GET_LDOUBLE_WORDS64(hx,lx,x);
+ lx |= (hx & 0x7fffffffffffffffLL) ^ 0x7fff000000000000LL;
+ lx |= -lx;
+ return ~(lx >> 63) & (hx >> 62);
+}
+hidden_def (__isinfq)
+weak_alias (__isinfq, isinfq)
--- libc/sysdeps/ieee754/quad/s_isnanq.c.float128 2004-05-05 14:48:55.000000000 -0700
+++ libc/sysdeps/ieee754/quad/s_isnanq.c 2004-05-05 14:48:55.000000000 -0700
@@ -0,0 +1,39 @@
+/* s_isnanl.c -- long double version of s_isnan.c.
+ * Conversion to long double by Jakub Jelinek, jj@ultra.linux.cz.
+ */
+
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#if defined(LIBM_SCCS) && !defined(lint)
+static char rcsid[] = "$NetBSD: $";
+#endif
+
+/*
+ * isnanl(x) returns 1 is x is nan, else 0;
+ * no branching!
+ */
+
+#include <math.h>
+#include <math_private.h>
+
+int
+__isnanq (__float128 x)
+{
+ int64_t hx,lx;
+ GET_LDOUBLE_WORDS64(hx,lx,x);
+ hx &= 0x7fffffffffffffffLL;
+ hx |= (u_int64_t)(lx|(-lx))>>63;
+ hx = 0x7fff000000000000LL - hx;
+ return (int)((u_int64_t)hx>>63);
+}
+hidden_def (__isnanq)
+weak_alias (__isnanq, isnanq)
--- libc/sysdeps/ieee754/quad/s_signbitq.c.float128 2004-05-05 14:48:55.000000000 -0700
+++ libc/sysdeps/ieee754/quad/s_signbitq.c 2004-05-05 14:48:55.000000000 -0700
@@ -0,0 +1,30 @@
+/* Return nonzero value if number is negative.
+ Copyright (C) 2004 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <math.h>
+#include <math_private.h>
+
+int
+__signbitq (__float128 x)
+{
+ int64_t e;
+
+ GET_LDOUBLE_MSW64 (e, x);
+ return e < 0;
+}
--- libc/sysdeps/ieee754/quad/strtoqd.c.float128 2004-05-05 14:48:55.000000000 -0700
+++ libc/sysdeps/ieee754/quad/strtoqd.c 2004-05-05 14:48:55.000000000 -0700
@@ -0,0 +1,28 @@
+/* Copyright (C) 2004 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#define FLOAT __float128
+#ifdef USE_WIDE_CHAR
+# define STRTOF wcstoqd
+# define STRTOF_L __wcstoqd_l
+#else
+# define STRTOF strtoqd
+# define STRTOF_L __strtoqd_l
+#endif
+
+#include <strtod.c>
--- libc/sysdeps/ieee754/quad/strtoqd_l.c.float128 2004-05-05 14:48:55.000000000 -0700
+++ libc/sysdeps/ieee754/quad/strtoqd_l.c 2004-05-05 14:48:55.000000000 -0700
@@ -0,0 +1,53 @@
+/* Copyright (C) 2004 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <math.h>
+#ifdef USE_WIDE_CHAR
+# include <wchar.h>
+#endif
+#include <endian.h>
+#include <ieee754-quad.h>
+#include <bits/huge_valq.h>
+
+/* The actual implementation for all floating point sizes is in strtod.c.
+ These macros tell it to produce the `IEEE quad' version, `strtoq'. */
+
+#define FLOAT __float128
+#define FLT QUAD
+#ifdef USE_WIDE_CHAR
+# define STRTOF wcstoqd_l
+# define __STRTOF __wcstoqd_l
+#else
+# define STRTOF strtoqd_l
+# define __STRTOF __strtoqd_l
+#endif
+#define MPN2FLOAT __mpn_construct_float128
+#ifndef FLOAT_HUGE_VAL
+# define FLOAT_HUGE_VAL HUGE_VALQ
+#endif
+#define SET_MANTISSA(flt, mant) \
+ do { union ieee854_float128 u; \
+ u.d = (flt); \
+ u.ieee.mantissa0 = 0x8000; \
+ u.ieee.mantissa1 = 0; \
+ u.ieee.mantissa2 = ((mant) >> 32); \
+ u.ieee.mantissa3 = (mant) & 0xffffffff; \
+ (flt) = u.d; \
+ } while (0)
+
+#include <stdlib/strtod_l.c>
--- libc/sysdeps/ieee754/quad/wcstoqd.c.float128 2004-05-05 14:48:55.000000000 -0700
+++ libc/sysdeps/ieee754/quad/wcstoqd.c 2004-05-05 14:48:55.000000000 -0700
@@ -0,0 +1,2 @@
+#define USE_WIDE_CHAR 1
+#include <strtoqd.c>
--- libc/sysdeps/ieee754/quad/wcstoqd_l.c.float128 2004-05-05 14:48:55.000000000 -0700
+++ libc/sysdeps/ieee754/quad/wcstoqd_l.c 2004-05-05 14:48:55.000000000 -0700
@@ -0,0 +1,11 @@
+#include <stddef.h>
+#include <xlocale.h>
+
+#define USE_WIDE_CHAR 1
+
+extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
+ wchar_t **,
+ int, int,
+ __locale_t);
+
+#include <strtoqd_l.c>
More information about the Libc-alpha
mailing list