diff --git a/Makefile.in b/Makefile.in index 148f481e..769b4674 100644 --- a/Makefile.in +++ b/Makefile.in @@ -86,6 +86,16 @@ cflags-cpu = $(libdfp_cv_submachine_opt) asflags-cpu = $(libdfp_cv_submachine_opt) endif +# Only try building TImode files if it is support. +dfp_ti_abi = @dfp_ti_abi@ + +# Need to check a different PLT file for int128 +ifeq ($(dfp_ti_abi),yes) +dfp_abi_extn = +else +dfp_abi_extn = -no-ti +endif + picflag = @picflag@ # Yes this is a bit of a hack, but gcc/libdecnumber/Makefile won't allow @@ -182,6 +192,12 @@ libdfp_files := dfptypeconv mapround decode fmt_d32 fmt_d64 fmt_d128 fe_decround # they can add files to the libdfp_files list. include $(foreach dir,$(makefile_dirs), $(dir)/Makefile ) +# Build the TImode files if we support them. +# Note that this does change the ABI. +ifeq ($(dfp_ti_abi),yes) +libdfp_files += $(libdfp_ti_files) +endif + # Libdfp has a dependency on the backend so build that first. all: first $(dfp_backend)/$(dfp_backend_lib) libdfp @@ -220,16 +236,16 @@ CXX_WARNS := -W -Wall -Wwrite-strings -Wmissing-format-attribute -Wno-long-long # Build the static object files. .c.o: - $(CC) $(CFLAGS) $(CPPFLAGS) $(mzarch) -c $< $(C_DEFINES) $(WARNS) -include $(top_srcdir)/include/libdfp-symbols.h -include $(top_builddir)/config.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@ + $(CC) $(CFLAGS) $(CPPFLAGS) $(mzarch) -c $< $(C_DEFINES) $(WARNS) -include $(top_builddir)/config.h -include $(top_srcdir)/include/libdfp-symbols.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@ .S.o: - $(CC) $(CFLAGS) $(ASFLAGS) $(mzarch) -c $< $(ASM_DEFINES) $(WARNS) -include $(top_srcdir)/include/libdfp-symbols.h -include $(top_builddir)/config.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@ + $(CC) $(CFLAGS) $(ASFLAGS) $(mzarch) -c $< $(ASM_DEFINES) $(WARNS) -include $(top_builddir)/config.h -include $(top_srcdir)/include/libdfp-symbols.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@ # Build the shared object files. .c.os: - $(CC) $(CFLAGS) $(CPPFLAGS) $(mzarch) -c $< $(C_DEFINES) $(WARNS) -include $(top_srcdir)/include/libdfp-symbols.h -include $(top_builddir)/config.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@ + $(CC) $(CFLAGS) $(CPPFLAGS) $(mzarch) -c $< $(C_DEFINES) $(WARNS) -include $(top_builddir)/config.h -include $(top_srcdir)/include/libdfp-symbols.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@ .S.os: - $(CC) $(CFLAGS) $(ASFLAGS) $(mzarch) -c $< $(ASM_DEFINES) $(WARNS) -include $(top_srcdir)/include/libdfp-symbols.h -include $(top_builddir)/config.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@ + $(CC) $(CFLAGS) $(ASFLAGS) $(mzarch) -c $< $(ASM_DEFINES) $(WARNS) -include $(top_builddir)/config.h -include $(top_srcdir)/include/libdfp-symbols.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@ # C++ compatibility test cases. .cpp.os: @@ -338,6 +354,10 @@ libdfp_c_tests = test-printf test-amort test-decode \ test-isless-d32 test-isless-d64 test-isless-d128 \ test-islessequal-d32 test-islessequal-d64 test-islessequal-d128 +ifeq ($(dfp_ti_abi),yes) +libdfp_c_tests += test-fix test-float +endif + # Only enable C++ tests if compiler supports std::decimal (GCC 4.5+), # otherwise just skip them. ifeq ($(cxxdecimal), yes) @@ -400,7 +420,7 @@ vpath %.abilist $(+sysdeps_dirs) check-abi: check-abi-libdfp.out $(warning $@) -check-abi-libdfp.out: libdfp.abilist libdfp.symlist +check-abi-libdfp.out: libdfp$(dfp_abi_extn).abilist libdfp.symlist diff -p -U 0 $(filter %.abilist,$^) $(filter %.symlist,$^) > $@ %.symlist: $(top_srcdir)/scripts/abilist.awk %.dynsym diff --git a/Versions.def b/Versions.def index de073213..bac3acc8 100644 --- a/Versions.def +++ b/Versions.def @@ -9,5 +9,6 @@ libdfp { LIBDFP_1.0.8 LIBDFP_1.0.9 LIBDFP_1.0.10 + LIBDFP_1.0.13 LIBDFP_PRIVATE } diff --git a/base-math/Makefile b/base-math/Makefile index 8a440065..d547c22e 100644 --- a/base-math/Makefile +++ b/base-math/Makefile @@ -6,8 +6,7 @@ # redistribute it and/or modify it under the terms of the GNU Lesser # General Public License version 2.1. # -# The Decimal Floating Point C Library is distributed in the hope that -# it will be useful, but WITHOUT ANY WARRANTY; without even the implied +# The Decimal Floating Point 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 version 2.1 for more details. # @@ -46,3 +45,7 @@ libdfp_files += addsd3 adddd3 addtd3 \ trunctdsf trunctddf trunctdtf \ unordsd2 unorddd2 unordtd2 \ classify + +libdfp_ti_files += fixsdti fixddti \ + fixunssdti fixunsddti \ + floattitd floatunstitd diff --git a/base-math/fixddti.c b/base-math/fixddti.c new file mode 100644 index 00000000..ff1c1d73 --- /dev/null +++ b/base-math/fixddti.c @@ -0,0 +1,31 @@ +/* fixddti implementation. + + Copyright (C) 2015 Free Software Foundation, Inc. + + This file is part of the Decimal Floating Point C Library. + + Author(s): Paul E. Murphy + + The Decimal Floating Point C Library is free software; you can + redistribute it and/or modify it under the terms of the GNU Lesser + General Public License version 2.1. + + The Decimal Floating Point 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 version 2.1 for more details. + + You should have received a copy of the GNU Lesser General Public + License version 2.1 along with the Decimal Floating Point C Library; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA. + + Please see libdfp/COPYING.txt for more information. */ + +#define SRC_SIZE 64 +#define FUNC fixddti +#define SHIFT_EXP 16 +#define DSUFF DD +#define SIGNED 1 + +#include "fixsdti.c" diff --git a/base-math/fixsdti.c b/base-math/fixsdti.c new file mode 100644 index 00000000..06288db2 --- /dev/null +++ b/base-math/fixsdti.c @@ -0,0 +1,150 @@ +/* Common fix*ti and fixsdti implementation. + + Copyright (C) 2015 Free Software Foundation, Inc. + + This file is part of the Decimal Floating Point C Library. + + Author(s): Paul E. Murphy + + The Decimal Floating Point C Library is free software; you can + redistribute it and/or modify it under the terms of the GNU Lesser + General Public License version 2.1. + + The Decimal Floating Point 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 version 2.1 for more details. + + You should have received a copy of the GNU Lesser General Public + License version 2.1 along with the Decimal Floating Point C Library; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA. + + Please see libdfp/COPYING.txt for more information. */ + +#ifndef SRC_SIZE +# define SRC_SIZE 32 +# define FUNC fixsdti +# define SHIFT_EXP 7 +# define DSUFF DF +# define SIGNED 1 +#endif + +#define _DECIMAL_SIZE SRC_SIZE + +#include +#include +#include +#include +#include + +#if SIGNED == 1 +# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define MAX_RET_VAL {.di = {0x7FFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFFFLL}} +# define MIN_RET_VAL {.di = {0x8000000000000000LL, 0LL}} +# else +# define MAX_RET_VAL {.di = {0xFFFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL}} +# define MIN_RET_VAL {.di = { 0LL, 0x8000000000000000LL}} +# endif +# if SRC_SIZE == 32 +# define MIN_VAL (-170141100000000000000000000000000000000.DF) +# define MAX_VAL ( 170141100000000000000000000000000000000.DF) +# elif SRC_SIZE == 64 +# define MIN_VAL (-170141183460469200000000000000000000000.DD) +# define MAX_VAL ( 170141183460469200000000000000000000000.DD) +# else +# define MIN_VAL (-170141183460469231731687303715884100000.DL) +# define MAX_VAL ( 170141183460469231731687303715884100000.DL) +# endif +# define RET_TYPE __int128 +# define QUICK_CONVERT(_x) ({ long long int _a_di = _x; _a_di;}) +#else +# define MAX_RET_VAL {.di = {0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFFFLL}} +# define MIN_RET_VAL {.di = {0LL, 0LL}} +# define MIN_VAL PASTE(0., DSUFF) +# if SRC_SIZE == 32 +# define MAX_VAL (340282300000000000000000000000000000000.DF) +# elif SRC_SIZE == 64 +# define MAX_VAL (340282366920938400000000000000000000000.DD) +# else +# define MAX_VAL (340282366920938463463374607431768200000.DL) +# endif +# define RET_TYPE unsigned __int128 +# define QUICK_CONVERT(_x) ({ unsigned long long int _a_di = _x; _a_di;}) +#endif + +#define TRUNC(_x) (PASTE(__truncd, SRC_SIZE)(_x)) +#define FREXP(_x,_y) (PASTE(__frexpd,SRC_SIZE)(_x,_y)) +#define CLASSIFY(_x) (PASTE(__fpclassifyd,SRC_SIZE)(_x)) +#define SHIFT_EXP_VAL PASTE(PASTE(1e,SHIFT_EXP),PASTE(DSUFF,)) +#define SIGNBIT(_x) (PASTE(__signbitd,SRC_SIZE)(_x)) + +#if SIGNED == 1 +# define FABS(_x) (PASTE(__fabsd,SRC_SIZE)(_x)) +#else +# define FABS(_x) _x +#endif + +extern const __int128 exp10_ti[39]; + +RET_TYPE __BACKEND_(FUNC) (DEC_TYPE a) +{ + union ret_type + { + RET_TYPE ti; + uint64_t di[2]; + }; + union ret_type min = MIN_RET_VAL; + union ret_type max = MAX_RET_VAL; + + switch (CLASSIFY (a)) + { + case FP_ZERO: + return 0; + + case FP_INFINITE: + DFP_EXCEPT (FE_INVALID); + return SIGNBIT(a) ? min.ti : max.ti; + + case FP_NAN: + DFP_EXCEPT (FE_INVALID); + return min.ti; + } + + if(a < MIN_VAL || a > MAX_VAL) + { + DFP_EXCEPT (FE_INVALID); + return (a < MIN_VAL) ? min.ti : max.ti; + } + + /* A 64 bit mantissa is sufficient for dd/sd conversions. */ +#if SRC_SIZE <= 64 + RET_TYPE result; + int e; + + if (FABS(a) < SHIFT_EXP_VAL) + { + return (RET_TYPE) QUICK_CONVERT (a); + } + + DEC_TYPE a_int = TRUNC (a); + DEC_TYPE a_norm = FREXP (a_int, &e); + + + a_norm *= SHIFT_EXP_VAL; + e -= SHIFT_EXP; + /* Force a 64b conversion of the mantissa */ + result = ((int64_t) a_norm); + if (e > 0) + return result * (RET_TYPE) exp10_ti[e]; + else if (e < 0) + return result / (RET_TYPE) exp10_ti[-e]; + else + return result; +#else + /* This requires specific knowledge of the encoding. Punt it. */ + return D128_CONVERSION(a); +#endif +} + +hidden_def (__BACKEND_(FUNC)) diff --git a/base-math/fixunsddti.c b/base-math/fixunsddti.c new file mode 100644 index 00000000..d4cca2bb --- /dev/null +++ b/base-math/fixunsddti.c @@ -0,0 +1,31 @@ +/* fixunsddti implementation. + + Copyright (C) 2015 Free Software Foundation, Inc. + + This file is part of the Decimal Floating Point C Library. + + Author(s): Paul E. Murphy + + The Decimal Floating Point C Library is free software; you can + redistribute it and/or modify it under the terms of the GNU Lesser + General Public License version 2.1. + + The Decimal Floating Point 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 version 2.1 for more details. + + You should have received a copy of the GNU Lesser General Public + License version 2.1 along with the Decimal Floating Point C Library; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA. + + Please see libdfp/COPYING.txt for more information. */ + +#define SRC_SIZE 64 +#define FUNC fixunsddti +#define SHIFT_EXP 16 +#define DSUFF DD +#define SIGNED 0 + +#include "fixsdti.c" diff --git a/base-math/fixunssdti.c b/base-math/fixunssdti.c new file mode 100644 index 00000000..167fac60 --- /dev/null +++ b/base-math/fixunssdti.c @@ -0,0 +1,31 @@ +/* fixunssdti implementation. + + Copyright (C) 2015 Free Software Foundation, Inc. + + This file is part of the Decimal Floating Point C Library. + + Author(s): Paul E. Murphy + + The Decimal Floating Point C Library is free software; you can + redistribute it and/or modify it under the terms of the GNU Lesser + General Public License version 2.1. + + The Decimal Floating Point 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 version 2.1 for more details. + + You should have received a copy of the GNU Lesser General Public + License version 2.1 along with the Decimal Floating Point C Library; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA. + + Please see libdfp/COPYING.txt for more information. */ + +#define SRC_SIZE 32 +#define FUNC fixunssdti +#define SHIFT_EXP 7 +#define DSUFF DF +#define SIGNED 0 + +#include "fixsdti.c" diff --git a/base-math/floattitd.c b/base-math/floattitd.c new file mode 100644 index 00000000..4e7d4575 --- /dev/null +++ b/base-math/floattitd.c @@ -0,0 +1,135 @@ +/* Convert a signed 128-bit binary integer into nearest representable + IEEE754R 128-bit Densely Packed Decimal Floating-point (DFP). + + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the Decimal Floating Point C Library. + + Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com) + + The Decimal Floating Point C Library is free software; you can + redistribute it and/or modify it under the terms of the GNU Lesser + General Public License version 2.1. + + The Decimal Floating Point 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 version 2.1 for more details. + + You should have received a copy of the GNU Lesser General Public + License version 2.1 along with the Decimal Floating Point C Library; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA. + + Please see dfp/COPYING.txt for more information. */ + +#include + +/* + * Convert a signed 128-bit binary integer into nearest representable + * IEEE754R 128-bit Densely Packed Decimal Floating-point (DFP). + * + * Care must be taken, as the signed __int128 type has a maximum + * value of ~1.701411835e+38 (or 39 decimal digits), while the + * _Decimal128 type carries only 34 significant digits, so inexact + * (truncated or rounded) results are possible. + * + * Also the PowerISA-2.05 and later provides hardware instructions to + * convert between signed 64-bit integer values to and from 64-/128-bit + * DFP, but does not provide for direct conversion of 128-bit + * integers. So efficiency dictates that the conversion be broken into + * chunks, that the hardware conversion can handle, then can be + * combined into the final decimal result. + * + * However conversion and scaling of arbitrary binary values to decimal + * can create large decimal ranges that can result in inexact + * intermediate results after conversion or rounding during the + * combine phase. + * + * We can avoid this by factoring (divide and modulo) the binary value + * into power of 10 chunks that can be converted exactly to decimal + * and combined without rounding in the decimal form. _Decimal128 + * has 34-digits of significance and half of that is 17-digits. + * 17-digits fit nicely with in signed 64-bit integer for conversion). + * So we choose 10^17 as the chunk size for factoring and conversion. + * + * First we check if input value is less then 2^63, which we can handle + * directly as a long to _Decimal conversion. Otherwise + * the algorithm factors the 128-bit binary values into three chunks; + * low 17-digits, middle 17-digits, and highest 5-digits. The middle + * and low factors can be converted and combined for an exact result + * of up to 34-digits via digit shift and add. Values greater than + * 34-digits may become inexact after the final combine stage, while + * preserving the most significant 34-digits in the result. + */ + +_Decimal128 +__BACKEND_ (floattitd) (__int128 a) +{ + __int128 zero = (__int128) 0L; + unsigned __int128 ten_17 = (unsigned __int128) 100000000000000000UL; + unsigned __int128 two_63 = (unsigned __int128) 0x8000000000000000UL; + unsigned __int128 u, x, y, z; + unsigned long long t_low, t_mid, t_high; + _Decimal128 result = 0.DL; + _Decimal128 d_low, d_mid, d_high; + int negative = 0; + + /* take the absolute value and record the sign. */ + if (a < zero) + { + /* This is necessary because __builtin_abs() does not handle + * the __int128 and we need to record the sign bit separately. + * Can't just use copysign later because we are dealing with + * different register sets and copysign instructions only + * within a specific register set. */ + u = (unsigned __int128) -a; + negative = 1; + } + else + { + u = (unsigned __int128) a; + } + + + if (u < two_63) + { + /* If abs(a) is less than 63-bits we can convert the signed + * value directly. */ + result = (long long) a; + } + else + { + /* Else convert the absolute (unsigned) value to Decimal and + * correct the sign later if needed. */ + y = u / ten_17; + z = u % ten_17; + t_low = (unsigned long long) z; + if (y < ten_17) + { + t_mid = (unsigned long long) y; + d_mid = t_mid; + d_low = t_low; + result = (d_mid * 100000000000000000.DL) + d_low; + } + else + { + x = y / ten_17; + z = y % ten_17; + t_mid = (unsigned long long) z; + t_high = (unsigned long long) x; + d_low = t_low; + d_mid = t_mid; + d_high = t_high; + result = (d_high * 100000000000000000.DL) + d_mid; + result = (result * 100000000000000000.DL) + d_low; + } + /* Converted the absolute 127-bit value of "a" to Decimal128. + * Now correct the decimal sign if the original value + * was negative. */ + if (negative) + result = -result; + } + + return (result); +} +hidden_def (__BACKEND_ (floattitd)) diff --git a/base-math/floatunstitd.c b/base-math/floatunstitd.c new file mode 100644 index 00000000..cf6b63a7 --- /dev/null +++ b/base-math/floatunstitd.c @@ -0,0 +1,108 @@ +/* Convert a unsigned 128-bit binary integer into nearest representable + IEEE754R 128-bit Densely Packed Decimal Floating-point (DFP). + + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the Decimal Floating Point C Library. + + Contributed by Steven Munroe (munroesj@linux.vnet.ibm.com) + + The Decimal Floating Point C Library is free software; you can + redistribute it and/or modify it under the terms of the GNU Lesser + General Public License version 2.1. + + The Decimal Floating Point 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 version 2.1 for more details. + + You should have received a copy of the GNU Lesser General Public + License version 2.1 along with the Decimal Floating Point C Library; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA. + + Please see dfp/COPYING.txt for more information. */ + +#include + +/* + * Convert a unsigned 128-bit binary integer into nearest representable + * IEEE754R 128-bit Densely Packed Decimal Floating-point (DFP). + * + * Care must be taken, as the unsigned __int128 type has a maximum + * value of ~340.282366921e+36 (or 39 decimal digits), while the + * _Decimal128 type carries only 34 significant digits, so inexact + * (truncated or rounded) results are possible. + * + * Also the PowerISA-2.05 and later provides hardware instructions to + * convert between signed 64-bit integer values to and from 64-/128-bit + * DFP, but does not provide for direct conversion of 128-bit + * integers. So efficiency dictates that the conversion be broken into + * chunks, that the hardware conversion can handle, then can be + * combined into the final decimal result. + * + * However conversion and scaling of arbitrary binary values to decimal + * can create large decimal ranges that can result in inexact + * intermediate results after conversion or rounding during the + * combine phase. + * + * We can avoid this by factoring (divide and modulo) the binary value + * into power of 10 chunks that can be converted exactly to decimal + * and combined without rounding in the decimal form. _Decimal128 + * has 34-digits of significance and half of that is 17-digits. + * 17-digits fit nicely with in signed 64-bit integer for conversion). + * So we choose 10^17 as the chunk size for factoring and conversion. + * + * First we check if input value is less then 2^63, which we can handle + * directly as a long to _Decimal conversion. Otherwise + * the algorithm factors the 128-bit binary values into three chunks; + * low 17-digits, middle 17-digits, and highest 5-digits. The middle + * and low factors can be converted and combined for an exact result + * of up to 34-digits via digit shift and add. Values greater than + * 34-digits may become inexact after the final combine stage, while + * preserving the most significant 34-digits in the result. + */ + +_Decimal128 +__BACKEND_ (floatunstitd) (unsigned __int128 a) +{ + unsigned __int128 ten_17 = (unsigned __int128) 100000000000000000UL; + unsigned __int128 two_63 = (unsigned __int128) 0x8000000000000000UL; + unsigned __int128 x, y, z; + unsigned long long t_low, t_mid, t_high; + _Decimal128 result = 0.DL; + _Decimal128 d_low, d_mid, d_high; + + if (a < two_63) + { + t_low = (unsigned long long) a; + result = t_low; + } + else + { + y = a / ten_17; + z = a % ten_17; + t_low = (unsigned long long) z; + if (y < ten_17) + { + t_mid = (unsigned long long) y; + d_mid = t_mid; + d_low = t_low; + result = (d_mid * 100000000000000000.DL) + d_low; + } + else + { + x = y / ten_17; + z = y % ten_17; + t_mid = (unsigned long long) z; + t_high = (unsigned long long) x; + d_low = t_low; + d_mid = t_mid; + d_high = t_high; + result = (d_high * 100000000000000000.DL) + d_mid; + result = (result * 100000000000000000.DL) + d_low; + } + } + + return (result); +} +hidden_def (__BACKEND_ (floatunstitd)) diff --git a/config.h.in b/config.h.in index 5bfdc6da..e5dd4cd9 100644 --- a/config.h.in +++ b/config.h.in @@ -172,6 +172,10 @@ such a type exists and the standard includes do not define it. */ #undef int32_t +/* Define to the type of a signed integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef int64_t + /* Define to rpl_malloc if the replacement function should be used. */ #undef malloc diff --git a/configure b/configure index 1d70a7f5..6eccc8ad 100755 --- a/configure +++ b/configure @@ -637,6 +637,7 @@ picflag enable_shared enable_static cxxdecimal +dfp_ti_abi libdfp_cv_cc_with_decimal_float machine base_machine @@ -4443,6 +4444,9 @@ _ACEOF fi +# Enable TImode abi if compiler supports 128b integer. +dfp_ti_abi=$libdfp_cv_uint128_t + # Check for std::decimal compiler support @@ -5597,6 +5601,17 @@ _ACEOF ;; esac +ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t" +case $ac_cv_c_int64_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int64_t $ac_cv_c_int64_t +_ACEOF +;; +esac + # Checks for library functions. for ac_header in stdlib.h diff --git a/configure.ac b/configure.ac index cd54c791..c848725c 100644 --- a/configure.ac +++ b/configure.ac @@ -375,6 +375,9 @@ if test x$libdfp_cv_uint128_t = xyes; then AC_DEFINE_UNQUOTED([HAVE_UINT128_T], [1], ["Have __uint128_t type"]) fi +# Enable TImode abi if compiler supports 128b integer. +dfp_ti_abi=$libdfp_cv_uint128_t +AC_SUBST(dfp_ti_abi) # Check for std::decimal compiler support AC_CACHE_CHECK(for std::decimal, libdfp_cv_cxxdecimal, @@ -677,6 +680,7 @@ AC_TYPE_INT32_T AC_TYPE_SIZE_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T +AC_TYPE_INT64_T # Checks for library functions. AC_FUNC_MALLOC diff --git a/include/dfpacc.h b/include/dfpacc.h index 0e868db0..cf835503 100644 --- a/include/dfpacc.h +++ b/include/dfpacc.h @@ -127,6 +127,22 @@ hidden_proto_enc (fixunsdddi) unsigned long long __BACKEND_(fixunstddi) (_Decimal128); hidden_proto_enc (fixunstddi) +#ifdef HAVE_UINT128_T /* Only available for compilers with TI moode */ +unsigned __int128 __BACKEND_(fixunssdti) (_Decimal32); +hidden_proto_enc (fixunssdti) +unsigned __int128 __BACKEND_(fixunsddti) (_Decimal64); +hidden_proto_enc (fixunsddti) +unsigned __int128 __BACKEND_(fixunstdti) (_Decimal128); +hidden_proto_enc (fixunstdti) + +__int128 __BACKEND_(fixsdti) (_Decimal32); +hidden_proto_enc (fixsdti) +__int128 __BACKEND_(fixddti) (_Decimal64); +hidden_proto_enc (fixddti) +__int128 __BACKEND_(fixtdti) (_Decimal128); +hidden_proto_enc (fixtdti) +#endif + _Decimal64 __BACKEND_(floatdidd) (long long); hidden_proto_enc (floatdidd) _Decimal32 __BACKEND_(floatdisd) (long long); @@ -155,6 +171,22 @@ hidden_proto_enc (floatunssisd) _Decimal128 __BACKEND_(floatunssitd) (unsigned int); hidden_proto_enc (floatunssitd) +#ifdef HAVE_UINT128_T /* Only available for compilers with TI moode */ +_Decimal64 __BACKEND_(floatunstidd) (unsigned __int128); +hidden_proto_enc (floatunstidd) +_Decimal32 __BACKEND_(floatunstisd) (unsigned __int128); +hidden_proto_enc (floatunstisd) +_Decimal128 __BACKEND_(floatunstitd) (unsigned __int128); +hidden_proto_enc (floatunstitd) + +_Decimal128 __BACKEND_(floattisd) (__int128); +hidden_proto_enc (floattisd) +_Decimal128 __BACKEND_(floattidd) (__int128); +hidden_proto_enc (floattidd) +_Decimal128 __BACKEND_(floattitd) (__int128); +hidden_proto_enc (floattitd) +#endif + int __BACKEND_(gesd2) (_Decimal32,_Decimal32); hidden_proto_enc (gesd2) int __BACKEND_(gedd2) (_Decimal64,_Decimal64); diff --git a/sysdeps/bid/Makefile b/sysdeps/bid/Makefile index edda9b94..9c0f4e9e 100644 --- a/sysdeps/bid/Makefile +++ b/sysdeps/bid/Makefile @@ -19,3 +19,5 @@ # Please see libdfp/COPYING.txt for more information. */ libdfp_files += bid-private binpowof10 decpowof2 + +libdfp_ti_files += ticonstants diff --git a/sysdeps/bid/Versions b/sysdeps/bid/Versions index fd7aa18c..03750214 100644 --- a/sysdeps/bid/Versions +++ b/sysdeps/bid/Versions @@ -21,4 +21,13 @@ libdfp { __bid_floatunssisd; __bid_floatunssidd; __bid_floatunssitd; __bid_floatunsdisd; __bid_floatunsdidd; __bid_floatunsditd; } + + LIBDFP_1.0.13 { + __bid_floattitd; + __bid_floatunstitd; + __bid_fixunssdti; + __bid_fixunsddti; + __bid_fixsdti; + __bid_fixddti; + } } diff --git a/sysdeps/bid/libdfp-no-ti.abilist b/sysdeps/bid/libdfp-no-ti.abilist new file mode 100644 index 00000000..c46bfcb7 --- /dev/null +++ b/sysdeps/bid/libdfp-no-ti.abilist @@ -0,0 +1,367 @@ +LIBDFP_1.0.0 + LIBDFP_1.0.0 A + __bid_adddd3 F + __bid_addsd3 F + __bid_addtd3 F + __bid_divdd3 F + __bid_divsd3 F + __bid_divtd3 F + __bid_eqdd2 F + __bid_eqsd2 F + __bid_eqtd2 F + __bid_extendddtd2 F + __bid_extendddtf F + __bid_extenddfdd F + __bid_extenddftd F + __bid_extendsddd2 F + __bid_extendsddf F + __bid_extendsdtd2 F + __bid_extendsdtf F + __bid_extendsfdd F + __bid_extendsfsd F + __bid_extendsftd F + __bid_extendtftd F + __bid_fixdddi F + __bid_fixddsi F + __bid_fixsddi F + __bid_fixsdsi F + __bid_fixtddi F + __bid_fixtdsi F + __bid_fixunsdddi F + __bid_fixunsddsi F + __bid_fixunssddi F + __bid_fixunssdsi F + __bid_fixunstddi F + __bid_fixunstdsi F + __bid_floatdidd F + __bid_floatdisd F + __bid_floatditd F + __bid_floatsidd F + __bid_floatsisd F + __bid_floatsitd F + __bid_floatunsdidd F + __bid_floatunsdisd F + __bid_floatunsditd F + __bid_floatunssidd F + __bid_floatunssisd F + __bid_floatunssitd F + __bid_gedd2 F + __bid_gesd2 F + __bid_getd2 F + __bid_gtdd2 F + __bid_gtsd2 F + __bid_gttd2 F + __bid_ledd2 F + __bid_lesd2 F + __bid_letd2 F + __bid_ltdd2 F + __bid_ltsd2 F + __bid_lttd2 F + __bid_muldd3 F + __bid_mulsd3 F + __bid_multd3 F + __bid_nedd2 F + __bid_nesd2 F + __bid_netd2 F + __bid_subdd3 F + __bid_subsd3 F + __bid_subtd3 F + __bid_truncdddf F + __bid_truncddsd2 F + __bid_truncddsf F + __bid_truncdfsd F + __bid_truncsdsf F + __bid_trunctddd2 F + __bid_trunctddf F + __bid_trunctdsd2 F + __bid_trunctdsf F + __bid_trunctdtf F + __bid_trunctfdd F + __bid_trunctfsd F + __bid_unorddd2 F + __bid_unordsd2 F + __bid_unordtd2 F + acosd128 F + acosd32 F + acosd64 F + acoshd128 F + acoshd32 F + acoshd64 F + asind128 F + asind32 F + asind64 F + asinhd128 F + asinhd32 F + asinhd64 F + atan2d128 F + atan2d32 F + atan2d64 F + atand128 F + atand32 F + atand64 F + atanhd128 F + atanhd32 F + atanhd64 F + cbrtd128 F + cbrtd32 F + cbrtd64 F + ceild128 F + ceild32 F + ceild64 F + copysignd128 F + copysignd32 F + copysignd64 F + cosd128 F + cosd32 F + cosd64 F + coshd128 F + coshd32 F + coshd64 F + decoded128 F + decoded32 F + decoded64 F + erfcd128 F + erfcd32 F + erfcd64 F + erfd128 F + erfd32 F + erfd64 F + exp2d128 F + exp2d32 F + exp2d64 F + expd128 F + expd32 F + expd64 F + expm1d128 F + expm1d32 F + expm1d64 F + fabsd128 F + fabsd32 F + fabsd64 F + fdimd128 F + fdimd32 F + fdimd64 F + fe_dec_getround F + fe_dec_setround F + finited128 F + finited32 F + finited64 F + floord128 F + floord32 F + floord64 F + fmad128 F + fmad32 F + fmad64 F + fmaxd128 F + fmaxd32 F + fmaxd64 F + fmind128 F + fmind32 F + fmind64 F + fmodd128 F + fmodd32 F + fmodd64 F + fpclassifyd128 F + fpclassifyd32 F + fpclassifyd64 F + frexpd128 F + frexpd32 F + frexpd64 F + hypotd128 F + hypotd32 F + hypotd64 F + ilogbd128 F + ilogbd32 F + ilogbd64 F + isgreaterd128 F + isgreaterd32 F + isgreaterd64 F + isgreaterequald128 F + isgreaterequald32 F + isgreaterequald64 F + isinfd128 F + isinfd32 F + isinfd64 F + islessd128 F + islessd32 F + islessd64 F + islessequald128 F + islessequald32 F + islessequald64 F + islessgreaterd128 F + islessgreaterd32 F + islessgreaterd64 F + isnand128 F + isnand32 F + isnand64 F + isnormald128 F + isnormald32 F + isnormald64 F + isunorderedd128 F + isunorderedd32 F + isunorderedd64 F + ldexpd128 F + ldexpd32 F + ldexpd64 F + lgammad128 F + lgammad32 F + lgammad64 F + llrintd128 F + llrintd32 F + llrintd64 F + llroundd128 F + llroundd32 F + llroundd64 F + log10d128 F + log10d32 F + log10d64 F + log1pd128 F + log1pd32 F + log1pd64 F + log2d128 F + log2d32 F + log2d64 F + logbd128 F + logbd32 F + logbd64 F + logd128 F + logd32 F + logd64 F + lrintd128 F + lrintd32 F + lrintd64 F + lroundd128 F + lroundd32 F + lroundd64 F + modfd128 F + modfd32 F + modfd64 F + nand128 F + nand32 F + nand64 F + nearbyintd128 F + nearbyintd32 F + nearbyintd64 F + nextafterd128 F + nextafterd32 F + nextafterd64 F + nexttowardd128 F + nexttowardd32 F + nexttowardd64 F + powd128 F + powd32 F + powd64 F + printf_dfp F + quantized128 F + quantized32 F + quantized64 F + register_printf_dfp F + remainderd128 F + remainderd32 F + remainderd64 F + rintd128 F + rintd32 F + rintd64 F + roundd128 F + roundd32 F + roundd64 F + samequantumd128 F + samequantumd32 F + samequantumd64 F + scalblnd128 F + scalblnd32 F + scalblnd64 F + scalbnd128 F + scalbnd32 F + scalbnd64 F + signbitd128 F + signbitd32 F + signbitd64 F + sind128 F + sind32 F + sind64 F + sinhd128 F + sinhd32 F + sinhd64 F + sqrtd128 F + sqrtd32 F + sqrtd64 F + strtod128 F + strtod32 F + strtod64 F + tand128 F + tand32 F + tand64 F + tanhd128 F + tanhd32 F + tanhd64 F + tgammad128 F + tgammad32 F + tgammad64 F + truncd128 F + truncd32 F + truncd64 F + wcstod128 F + wcstod32 F + wcstod64 F +LIBDFP_1.0.13 + LIBDFP_1.0.13 A +LIBDFP_1.0.2 + LIBDFP_1.0.2 A + __isinfd128 F + __isinfd32 F + __isinfd64 F + __isnand128 F + __isnand32 F + __isnand64 F +LIBDFP_1.0.3 + LIBDFP_1.0.3 A + __fabsd128 F + __fabsd32 F + __fabsd64 F + __finited128 F + __finited32 F + __finited64 F + __fpclassifyd128 F + __fpclassifyd32 F + __fpclassifyd64 F + __isfinited128 F + __isfinited32 F + __isfinited64 F + __signbitd128 F + __signbitd32 F + __signbitd64 F + isfinited128 F + isfinited32 F + isfinited64 F +LIBDFP_1.0.9 + LIBDFP_1.0.9 A + __issignalingd128 F + __issignalingd32 F + __issignalingd64 F + issignalingd128 F + issignalingd32 F + issignalingd64 F + llogbd128 F + llogbd32 F + llogbd64 F + llquantexpd128 F + llquantexpd32 F + llquantexpd64 F + quantumd128 F + quantumd32 F + quantumd64 F + roundevend128 F + roundevend32 F + roundevend64 F +LIBDFP_PRIVATE + LIBDFP_PRIVATE A + __decoded128 F + __decoded32 F + __decoded64 F + __decrm_location F + __fe_dec_getround F + __fe_dec_setround F + __fmt_d128 F + __fmt_d32 F + __fmt_d64 F diff --git a/sysdeps/bid/libdfp.abilist b/sysdeps/bid/libdfp.abilist index c5d28a33..e4b28d71 100644 --- a/sysdeps/bid/libdfp.abilist +++ b/sysdeps/bid/libdfp.abilist @@ -304,6 +304,14 @@ LIBDFP_1.0.0 wcstod128 F wcstod32 F wcstod64 F +LIBDFP_1.0.13 + LIBDFP_1.0.13 A + __bid_fixddti F + __bid_fixsdti F + __bid_fixunsddti F + __bid_fixunssdti F + __bid_floattitd F + __bid_floatunstitd F LIBDFP_1.0.2 LIBDFP_1.0.2 A __isinfd128 F diff --git a/sysdeps/bid/symbol-hacks.h b/sysdeps/bid/symbol-hacks.h index c06e9105..8de93ce0 100644 --- a/sysdeps/bid/symbol-hacks.h +++ b/sysdeps/bid/symbol-hacks.h @@ -32,6 +32,11 @@ asm ("__bid_floatsitd = __GI___bid_floatsitd"); asm ("__bid_floatdidd = __GI___bid_floatdidd"); asm ("__bid_floatsisd = __GI___bid_floatsisd"); +#if HAVE_UINT128_T +asm ("__bid_floattitd = __GI___bid_floattitd"); +asm ("__bid_floatunsditd = __GI___bid_floatunsditd"); +#endif + asm ("__bid_truncdddf = __GI___bid_truncdddf"); asm ("__bid_trunctddf = __GI___bid_trunctddf"); asm ("__bid_trunctddd2 = __GI___bid_trunctddd2"); @@ -52,6 +57,9 @@ asm ("__bid_fixsddi = __GI___bid_fixsddi"); asm ("__bid_fixtddi = __GI___bid_fixtddi"); asm ("__bid_fixtdsi = __GI___bid_fixtdsi"); +asm ("__bid_fixunsdddi = __GI___bid_fixunsdddi"); +asm ("__bid_fixunssddi = __GI___bid_fixunssddi"); + asm ("__bid_addsd3 = __GI___bid_addsd3"); asm ("__bid_addtd3 = __GI___bid_addtd3"); asm ("__bid_adddd3 = __GI___bid_adddd3"); diff --git a/sysdeps/dpd/Makefile b/sysdeps/dpd/Makefile index 69d5c743..be7012a8 100644 --- a/sysdeps/dpd/Makefile +++ b/sysdeps/dpd/Makefile @@ -1 +1,3 @@ libdfp_files += dpd-private binpowof10 decpowof2 + +libdfp_ti_files += fixtdti fixunstdti ticonstants diff --git a/sysdeps/dpd/Versions b/sysdeps/dpd/Versions index 905b9e2c..7a32be45 100644 --- a/sysdeps/dpd/Versions +++ b/sysdeps/dpd/Versions @@ -32,4 +32,16 @@ libdfp { __dpd_trunctdsf; __dpd_trunctddf; __dpd_trunctdtf; } + + LIBDFP_1.0.13 { + __dpd_fixtdti; + __dpd_fixddti; + __dpd_fixsdti; + __dpd_fixunstdti; + __dpd_fixunsddti; + __dpd_fixunssdti; + __dpd_floattitd; + __dpd_floatunstitd; + } + } diff --git a/sysdeps/dpd/fixtdti.c b/sysdeps/dpd/fixtdti.c new file mode 100644 index 00000000..4bff8deb --- /dev/null +++ b/sysdeps/dpd/fixtdti.c @@ -0,0 +1,116 @@ +/* DPD encoded Decimal128 to uint128 conversion routine. + + Copyright (C) 2015 Free Software Foundation, Inc. + + This file is part of the Decimal Floating Point C Library. + + Author(s): Paul E. Murphy + + The Decimal Floating Point C Library is free software; you can + redistribute it and/or modify it under the terms of the GNU Lesser + General Public License version 2.1. + + The Decimal Floating Point 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 version 2.1 for more details. + + You should have received a copy of the GNU Lesser General Public + License version 2.1 along with the Decimal Floating Point C Library; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA. + + Please see dfp/COPYING.txt for more information. */ + +#define SRC_SIZE 128 +#define DSUFF DL + +#ifndef SIGNED +# define SIGNED 1 +# define FUNC fixtdti +# define QTYPE +#endif + +static inline QTYPE __int128 convert_td_ti(_Decimal128 d); + +#define D128_CONVERSION(a) convert_td_ti(a) +#include "fixsdti.c" + +#include "numdigits.h" +#include "tidpdcommon.h" + +static RET_TYPE +convert_td_ti(_Decimal128 a) +{ + /* Ensure number is rounded to an integral value. */ + _Decimal128 a_abs = __truncd128 (a); + +#if SIGNED + long neg = 0; + if (a_abs < 0) + { + a_abs = -a_abs; + neg = 1; + } +#else + a_abs = a; +#endif + + /* Do a quick conversion if possible. */ + if (a_abs < 1e16DL) + return (RET_TYPE) QUICK_CONVERT (a); + + /* The general idea: + + Extract number into three parts: + High 16 decimal digits: a_high + Middle 2 decimal digits: a_mid + Low 16 decimal digits: a_low + + 0 <= exp <= 38. + + return = (a_high * 1e18 + a_mid * 1e16 + a_low) * exp + + TODO: + + Note, any exp > 7 can be done in two + halves, and likewise, exp > 23 can be + done in one with a big multiply. That + work waits for another day. + */ + _Decimal128 a_high, a_low; + long digs; + uint64_t a_low_di, a_high_di; + RET_TYPE a_low_ti, a_high_ti, result; + RET_TYPE ten_16_ti = 10000000000000000LL; + int exp; + + exp = getexpd128 (a_abs); + digs = split_td (a_abs, &a_high, &a_low); + + /* Now we have + a_high = top 16 decimal digits + a_low = bottom 16 decimal digits + digs = middle 2 digits * 16 in BCD + + Now... shift a_high right 18 digits, and convert + as a uint64, compute digs, and convert a_low as + a uint64 + */ + a_low_di = ((_Decimal64) setexpd128 (a_low, 0)); + a_high_di = ((_Decimal64) setexpd128 (a_high, -18)); + + /* Convert into appropriate parts and minimize 128b multiplies. */ + a_low_ti = a_low_di; + a_high_di = a_high_di * 100LL + digs; + a_high_ti = (RET_TYPE) a_high_di * ten_16_ti; + result = (a_low_ti + a_high_ti) * (RET_TYPE) exp10_ti[exp]; + + /* No need to worry about overflow with __int128 */ +#if SIGNED + if (neg) + result = -result; +#endif + + return result; +} diff --git a/sysdeps/dpd/fixunstdti.c b/sysdeps/dpd/fixunstdti.c new file mode 100644 index 00000000..9b020a8e --- /dev/null +++ b/sysdeps/dpd/fixunstdti.c @@ -0,0 +1,28 @@ +/* DPD encoded Decimal128 to uint128 conversion routine. + + Copyright (C) 2015 Free Software Foundation, Inc. + + This file is part of the Decimal Floating Point C Library. + + Author(s): Paul E. Murphy + + The Decimal Floating Point C Library is free software; you can + redistribute it and/or modify it under the terms of the GNU Lesser + General Public License version 2.1. + + The Decimal Floating Point 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 version 2.1 for more details. + + You should have received a copy of the GNU Lesser General Public + License version 2.1 along with the Decimal Floating Point C Library; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA. + + Please see dfp/COPYING.txt for more information. */ + +#define SIGNED 0 +#define FUNC fixunstdti +#define QTYPE unsigned +#include "fixtdti.c" diff --git a/sysdeps/dpd/symbol-hacks.h b/sysdeps/dpd/symbol-hacks.h index 86d0635a..4fcef4db 100644 --- a/sysdeps/dpd/symbol-hacks.h +++ b/sysdeps/dpd/symbol-hacks.h @@ -31,6 +31,14 @@ asm ("__dpd_floatsitd = __GI___dpd_floatsitd"); asm ("__dpd_floatdidd = __GI___dpd_floatdidd"); asm ("__dpd_floatsisd = __GI___dpd_floatsisd"); +asm ("__dpd_floatunsditd = __GI___dpd_floatditd"); + +#ifdef HAVE_UINT128_T +asm ("__dpd_floattitd = __GI___dpd_floattitd"); + +asm ("__dpd_floatunstitd = __GI___dpd_floatunstitd"); +#endif + asm ("__dpd_trunctddd2 = __GI___dpd_trunctddd2"); asm ("__dpd_truncddsd2 = __GI___dpd_truncddsd2"); @@ -53,6 +61,17 @@ asm ("__dpd_fixtdsi = __GI___dpd_fixtdsi"); asm ("__dpd_fixsddi = __GI___dpd_fixsddi"); asm ("__dpd_fixtddi = __GI___dpd_fixtddi"); +asm ("__dpd_fixunssddi = __GI___dpd_fixunssddi"); +asm ("__dpd_fixunsdddi = __GI___dpd_fixunsdddi"); +asm ("__dpd_fixunstddi = __GI___dpd_fixunstddi"); + +#ifdef HAVE_UINT128_T +asm ("__dpd_fixtdti = __GI___dpd_fixtdti"); + +asm ("__dpd_fixunstdti = __GI___dpd_fixunstdti"); +#endif + + asm ("__dpd_addsd3 = __GI___dpd_addsd3"); asm ("__dpd_addtd3 = __GI___dpd_addtd3"); asm ("__dpd_adddd3 = __GI___dpd_adddd3"); diff --git a/sysdeps/dpd/tidpdcommon.h b/sysdeps/dpd/tidpdcommon.h new file mode 100644 index 00000000..8adbe707 --- /dev/null +++ b/sysdeps/dpd/tidpdcommon.h @@ -0,0 +1,65 @@ +/* Helpers for td -> ti conversions in DPD format. + + Copyright (C) 2015 Free Software Foundation, Inc. + + This file is part of the Decimal Floating Point C Library. + + Author(s): Paul E. Murphy + + The Decimal Floating Point C Library is free software; you can + redistribute it and/or modify it under the terms of the GNU Lesser + General Public License version 2.1. + + The Decimal Floating Point 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 version 2.1 for more details. + + You should have received a copy of the GNU Lesser General Public + License version 2.1 along with the Decimal Floating Point C Library; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA. + + Please see dfp/COPYING.txt for more information. */ + +#ifndef _TIDPDCOMMON_H_ +#define _TIDPDCOMMON_H_ + +/* + Split and extract components of a large _Decimal 128 number. + + This splits the number a into three components: + + a_high: Upper 16 digits + a_low: Lower 16 digits + return value: Middle 2 digits + */ +static inline long +split_td (_Decimal128 a, _Decimal128 * a_high, _Decimal128 * a_low) +{ + _Decimal128 a_high_18; + union ieee754r_Decimal128 dunion; + long digs; + + dunion.td = a; + digs = dunion.ieee.cc5; + dunion.ieee.cc5 = 0; /* Set lower 18 digits to 0 */ + dunion.ieee.cc6 = 0; + dunion.ieee.cc7H8 = 0; + dunion.ieee.cc7L2 = 0; + dunion.ieee.cc8 = 0; + dunion.ieee.cc9 = 0; + dunion.ieee.cc10 = 0; + *a_high = dunion.td; /* a_high should now have only 16 leading dec sig figs */ + digs = dpd_to_bcd[digs]; + digs &= 0xff0; + dunion.ieee.cc5 = bcd_to_dpd[digs]; /* Replace d15 in mantissa */ + a_high_18 = dunion.td; /* a_high_18 contains 18 leading dec sig figs */ + *a_low = a - a_high_18; /* a_low contains trailing 16 sig figs */ + + /* Turn two BCD digits into binary. */ + digs >>= 4; + return (digs & 0xf) + ((digs >> 4) & 0xf) * 10; +} + +#endif /* _TIDPDCOMMON_H_ */ diff --git a/sysdeps/generic/ticonstants.c b/sysdeps/generic/ticonstants.c new file mode 100644 index 00000000..b437f324 --- /dev/null +++ b/sysdeps/generic/ticonstants.c @@ -0,0 +1,69 @@ +/* 128b integer constants used for conversions. + + Copyright (C) 2015 Free Software Foundation, Inc. + + This file is part of the Decimal Floating Point C Library. + + Author(s): Paul E. Murphy + + The Decimal Floating Point C Library is free software; you can + redistribute it and/or modify it under the terms of the GNU Lesser + General Public License version 2.1. + + The Decimal Floating Point 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 version 2.1 for more details. + + You should have received a copy of the GNU Lesser General Public + License version 2.1 along with the Decimal Floating Point C Library; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA. + + Please see dfp/COPYING.txt for more information. */ + +#define QI(_x) ((__int128)(_x##ULL)) +#define ONEe19QI QI(10000000000000000000) + +__int128 const exp10_ti[] = { + 1ULL, /* 1e0 */ + 10ULL, + 100ULL, + 1000ULL, + 10000ULL, + 100000ULL, /* 1e5 */ + 1000000ULL, + 10000000ULL, + 100000000ULL, + 1000000000ULL, + 10000000000ULL, /* 1e10 */ + 100000000000ULL, + 1000000000000ULL, + 10000000000000ULL, + 100000000000000ULL, + 1000000000000000ULL, /* 1e15 */ + 10000000000000000ULL, + 100000000000000000ULL, + 1000000000000000000ULL, + 10000000000000000000ULL, + /* Use the compiler to precompute bigger numbers. */ + QI (10) * ONEe19QI, /* 1e20 */ + QI (100) * ONEe19QI, + QI (1000) * ONEe19QI, + QI (10000) * ONEe19QI, + QI (100000) * ONEe19QI, + QI (1000000) * ONEe19QI, + QI (10000000) * ONEe19QI, + QI (100000000) * ONEe19QI, + QI (1000000000) * ONEe19QI, + QI (10000000000) * ONEe19QI, + QI (100000000000) * ONEe19QI, /* 1e30 */ + QI (1000000000000) * ONEe19QI, + QI (10000000000000) * ONEe19QI, + QI (100000000000000) * ONEe19QI, + QI (1000000000000000) * ONEe19QI, + QI (10000000000000000) * ONEe19QI, /* 1e35 */ + QI (100000000000000000) * ONEe19QI, + QI (1000000000000000000) * ONEe19QI, + QI (10000000000000000000) * ONEe19QI, /* 1e38 */ +}; diff --git a/sysdeps/powerpc/dfpu/libdfp-no-ti.abilist b/sysdeps/powerpc/dfpu/libdfp-no-ti.abilist new file mode 100644 index 00000000..24ea626e --- /dev/null +++ b/sysdeps/powerpc/dfpu/libdfp-no-ti.abilist @@ -0,0 +1,366 @@ +LIBDFP_1.0.0 + LIBDFP_1.0.0 A + __dpd_adddd3 F + __dpd_addsd3 F + __dpd_addtd3 F + __dpd_divdd3 F + __dpd_divsd3 F + __dpd_divtd3 F + __dpd_eqdd2 F + __dpd_eqsd2 F + __dpd_eqtd2 F + __dpd_extendddtd2 F + __dpd_extendddtf F + __dpd_extenddfdd F + __dpd_extenddftd F + __dpd_extendsddd2 F + __dpd_extendsddf F + __dpd_extendsdtd2 F + __dpd_extendsdtf F + __dpd_extendsfdd F + __dpd_extendsfsd F + __dpd_extendsftd F + __dpd_extendtftd F + __dpd_fixdddi F + __dpd_fixddsi F + __dpd_fixsddi F + __dpd_fixsdsi F + __dpd_fixtddi F + __dpd_fixtdsi F + __dpd_fixunsdddi F + __dpd_fixunsddsi F + __dpd_fixunssddi F + __dpd_fixunssdsi F + __dpd_fixunstddi F + __dpd_fixunstdsi F + __dpd_floatdidd F + __dpd_floatdisd F + __dpd_floatditd F + __dpd_floatsidd F + __dpd_floatsisd F + __dpd_floatsitd F + __dpd_floatunsdidd F + __dpd_floatunsdisd F + __dpd_floatunsditd F + __dpd_floatunssidd F + __dpd_floatunssisd F + __dpd_floatunssitd F + __dpd_gedd2 F + __dpd_gesd2 F + __dpd_getd2 F + __dpd_gtdd2 F + __dpd_gtsd2 F + __dpd_gttd2 F + __dpd_ledd2 F + __dpd_lesd2 F + __dpd_letd2 F + __dpd_ltdd2 F + __dpd_ltsd2 F + __dpd_lttd2 F + __dpd_muldd3 F + __dpd_mulsd3 F + __dpd_multd3 F + __dpd_nedd2 F + __dpd_nesd2 F + __dpd_netd2 F + __dpd_subdd3 F + __dpd_subsd3 F + __dpd_subtd3 F + __dpd_truncdddf F + __dpd_truncddsd2 F + __dpd_truncddsf F + __dpd_truncdfsd F + __dpd_truncsdsf F + __dpd_trunctddd2 F + __dpd_trunctddf F + __dpd_trunctdsd2 F + __dpd_trunctdsf F + __dpd_trunctdtf F + __dpd_trunctfdd F + __dpd_trunctfsd F + __dpd_unorddd2 F + __dpd_unordsd2 F + __dpd_unordtd2 F + acosd128 F + acosd32 F + acosd64 F + acoshd128 F + acoshd32 F + acoshd64 F + asind128 F + asind32 F + asind64 F + asinhd128 F + asinhd32 F + asinhd64 F + atan2d128 F + atan2d32 F + atan2d64 F + atand128 F + atand32 F + atand64 F + atanhd128 F + atanhd32 F + atanhd64 F + cbrtd128 F + cbrtd32 F + cbrtd64 F + ceild128 F + ceild32 F + ceild64 F + copysignd128 F + copysignd32 F + copysignd64 F + cosd128 F + cosd32 F + cosd64 F + coshd128 F + coshd32 F + coshd64 F + decoded128 F + decoded32 F + decoded64 F + erfcd128 F + erfcd32 F + erfcd64 F + erfd128 F + erfd32 F + erfd64 F + exp2d128 F + exp2d32 F + exp2d64 F + expd128 F + expd32 F + expd64 F + expm1d128 F + expm1d32 F + expm1d64 F + fabsd128 F + fabsd32 F + fabsd64 F + fdimd128 F + fdimd32 F + fdimd64 F + fe_dec_getround F + fe_dec_setround F + finited128 F + finited32 F + finited64 F + floord128 F + floord32 F + floord64 F + fmad128 F + fmad32 F + fmad64 F + fmaxd128 F + fmaxd32 F + fmaxd64 F + fmind128 F + fmind32 F + fmind64 F + fmodd128 F + fmodd32 F + fmodd64 F + fpclassifyd128 F + fpclassifyd32 F + fpclassifyd64 F + frexpd128 F + frexpd32 F + frexpd64 F + hypotd128 F + hypotd32 F + hypotd64 F + ilogbd128 F + ilogbd32 F + ilogbd64 F + isgreaterd128 F + isgreaterd32 F + isgreaterd64 F + isgreaterequald128 F + isgreaterequald32 F + isgreaterequald64 F + isinfd128 F + isinfd32 F + isinfd64 F + islessd128 F + islessd32 F + islessd64 F + islessequald128 F + islessequald32 F + islessequald64 F + islessgreaterd128 F + islessgreaterd32 F + islessgreaterd64 F + isnand128 F + isnand32 F + isnand64 F + isnormald128 F + isnormald32 F + isnormald64 F + isunorderedd128 F + isunorderedd32 F + isunorderedd64 F + ldexpd128 F + ldexpd32 F + ldexpd64 F + lgammad128 F + lgammad32 F + lgammad64 F + llrintd128 F + llrintd32 F + llrintd64 F + llroundd128 F + llroundd32 F + llroundd64 F + log10d128 F + log10d32 F + log10d64 F + log1pd128 F + log1pd32 F + log1pd64 F + log2d128 F + log2d32 F + log2d64 F + logbd128 F + logbd32 F + logbd64 F + logd128 F + logd32 F + logd64 F + lrintd128 F + lrintd32 F + lrintd64 F + lroundd128 F + lroundd32 F + lroundd64 F + modfd128 F + modfd32 F + modfd64 F + nand128 F + nand32 F + nand64 F + nearbyintd128 F + nearbyintd32 F + nearbyintd64 F + nextafterd128 F + nextafterd32 F + nextafterd64 F + nexttowardd128 F + nexttowardd32 F + nexttowardd64 F + powd128 F + powd32 F + powd64 F + printf_dfp F + quantized128 F + quantized32 F + quantized64 F + register_printf_dfp F + remainderd128 F + remainderd32 F + remainderd64 F + rintd128 F + rintd32 F + rintd64 F + roundd128 F + roundd32 F + roundd64 F + samequantumd128 F + samequantumd32 F + samequantumd64 F + scalblnd128 F + scalblnd32 F + scalblnd64 F + scalbnd128 F + scalbnd32 F + scalbnd64 F + signbitd128 F + signbitd32 F + signbitd64 F + sind128 F + sind32 F + sind64 F + sinhd128 F + sinhd32 F + sinhd64 F + sqrtd128 F + sqrtd32 F + sqrtd64 F + strtod128 F + strtod32 F + strtod64 F + tand128 F + tand32 F + tand64 F + tanhd128 F + tanhd32 F + tanhd64 F + tgammad128 F + tgammad32 F + tgammad64 F + truncd128 F + truncd32 F + truncd64 F + wcstod128 F + wcstod32 F + wcstod64 F +LIBDFP_1.0.13 + LIBDFP_1.0.13 A +LIBDFP_1.0.2 + LIBDFP_1.0.2 A + __isinfd128 F + __isinfd32 F + __isinfd64 F + __isnand128 F + __isnand32 F + __isnand64 F +LIBDFP_1.0.3 + LIBDFP_1.0.3 A + __fabsd128 F + __fabsd32 F + __fabsd64 F + __finited128 F + __finited32 F + __finited64 F + __fpclassifyd128 F + __fpclassifyd32 F + __fpclassifyd64 F + __isfinited128 F + __isfinited32 F + __isfinited64 F + __signbitd128 F + __signbitd32 F + __signbitd64 F + isfinited128 F + isfinited32 F + isfinited64 F +LIBDFP_1.0.9 + LIBDFP_1.0.9 A + __issignalingd128 F + __issignalingd32 F + __issignalingd64 F + issignalingd128 F + issignalingd32 F + issignalingd64 F + llogbd128 F + llogbd32 F + llogbd64 F + llquantexpd128 F + llquantexpd32 F + llquantexpd64 F + quantumd128 F + quantumd32 F + quantumd64 F + roundevend128 F + roundevend32 F + roundevend64 F +LIBDFP_PRIVATE + LIBDFP_PRIVATE A + __decoded128 F + __decoded32 F + __decoded64 F + __fe_dec_getround F + __fe_dec_setround F + __fmt_d128 F + __fmt_d32 F + __fmt_d64 F diff --git a/sysdeps/powerpc/dfpu/libdfp.abilist b/sysdeps/powerpc/dfpu/libdfp.abilist index dbb7d604..e00e4615 100644 --- a/sysdeps/powerpc/dfpu/libdfp.abilist +++ b/sysdeps/powerpc/dfpu/libdfp.abilist @@ -304,6 +304,16 @@ LIBDFP_1.0.0 wcstod128 F wcstod32 F wcstod64 F +LIBDFP_1.0.13 + LIBDFP_1.0.13 A + __dpd_fixddti F + __dpd_fixsdti F + __dpd_fixtdti F + __dpd_fixunsddti F + __dpd_fixunssdti F + __dpd_fixunstdti F + __dpd_floattitd F + __dpd_floatunstitd F LIBDFP_1.0.2 LIBDFP_1.0.2 A __isinfd128 F diff --git a/sysdeps/powerpc/fpu/libdfp-no-ti.abilist b/sysdeps/powerpc/fpu/libdfp-no-ti.abilist new file mode 100644 index 00000000..d1aeb908 --- /dev/null +++ b/sysdeps/powerpc/fpu/libdfp-no-ti.abilist @@ -0,0 +1,367 @@ +LIBDFP_1.0.0 + LIBDFP_1.0.0 A + __dpd_adddd3 F + __dpd_addsd3 F + __dpd_addtd3 F + __dpd_divdd3 F + __dpd_divsd3 F + __dpd_divtd3 F + __dpd_eqdd2 F + __dpd_eqsd2 F + __dpd_eqtd2 F + __dpd_extendddtd2 F + __dpd_extendddtf F + __dpd_extenddfdd F + __dpd_extenddftd F + __dpd_extendsddd2 F + __dpd_extendsddf F + __dpd_extendsdtd2 F + __dpd_extendsdtf F + __dpd_extendsfdd F + __dpd_extendsfsd F + __dpd_extendsftd F + __dpd_extendtftd F + __dpd_fixdddi F + __dpd_fixddsi F + __dpd_fixsddi F + __dpd_fixsdsi F + __dpd_fixtddi F + __dpd_fixtdsi F + __dpd_fixunsdddi F + __dpd_fixunsddsi F + __dpd_fixunssddi F + __dpd_fixunssdsi F + __dpd_fixunstddi F + __dpd_fixunstdsi F + __dpd_floatdidd F + __dpd_floatdisd F + __dpd_floatditd F + __dpd_floatsidd F + __dpd_floatsisd F + __dpd_floatsitd F + __dpd_floatunsdidd F + __dpd_floatunsdisd F + __dpd_floatunsditd F + __dpd_floatunssidd F + __dpd_floatunssisd F + __dpd_floatunssitd F + __dpd_gedd2 F + __dpd_gesd2 F + __dpd_getd2 F + __dpd_gtdd2 F + __dpd_gtsd2 F + __dpd_gttd2 F + __dpd_ledd2 F + __dpd_lesd2 F + __dpd_letd2 F + __dpd_ltdd2 F + __dpd_ltsd2 F + __dpd_lttd2 F + __dpd_muldd3 F + __dpd_mulsd3 F + __dpd_multd3 F + __dpd_nedd2 F + __dpd_nesd2 F + __dpd_netd2 F + __dpd_subdd3 F + __dpd_subsd3 F + __dpd_subtd3 F + __dpd_truncdddf F + __dpd_truncddsd2 F + __dpd_truncddsf F + __dpd_truncdfsd F + __dpd_truncsdsf F + __dpd_trunctddd2 F + __dpd_trunctddf F + __dpd_trunctdsd2 F + __dpd_trunctdsf F + __dpd_trunctdtf F + __dpd_trunctfdd F + __dpd_trunctfsd F + __dpd_unorddd2 F + __dpd_unordsd2 F + __dpd_unordtd2 F + acosd128 F + acosd32 F + acosd64 F + acoshd128 F + acoshd32 F + acoshd64 F + asind128 F + asind32 F + asind64 F + asinhd128 F + asinhd32 F + asinhd64 F + atan2d128 F + atan2d32 F + atan2d64 F + atand128 F + atand32 F + atand64 F + atanhd128 F + atanhd32 F + atanhd64 F + cbrtd128 F + cbrtd32 F + cbrtd64 F + ceild128 F + ceild32 F + ceild64 F + copysignd128 F + copysignd32 F + copysignd64 F + cosd128 F + cosd32 F + cosd64 F + coshd128 F + coshd32 F + coshd64 F + decoded128 F + decoded32 F + decoded64 F + erfcd128 F + erfcd32 F + erfcd64 F + erfd128 F + erfd32 F + erfd64 F + exp2d128 F + exp2d32 F + exp2d64 F + expd128 F + expd32 F + expd64 F + expm1d128 F + expm1d32 F + expm1d64 F + fabsd128 F + fabsd32 F + fabsd64 F + fdimd128 F + fdimd32 F + fdimd64 F + fe_dec_getround F + fe_dec_setround F + finited128 F + finited32 F + finited64 F + floord128 F + floord32 F + floord64 F + fmad128 F + fmad32 F + fmad64 F + fmaxd128 F + fmaxd32 F + fmaxd64 F + fmind128 F + fmind32 F + fmind64 F + fmodd128 F + fmodd32 F + fmodd64 F + fpclassifyd128 F + fpclassifyd32 F + fpclassifyd64 F + frexpd128 F + frexpd32 F + frexpd64 F + hypotd128 F + hypotd32 F + hypotd64 F + ilogbd128 F + ilogbd32 F + ilogbd64 F + isgreaterd128 F + isgreaterd32 F + isgreaterd64 F + isgreaterequald128 F + isgreaterequald32 F + isgreaterequald64 F + isinfd128 F + isinfd32 F + isinfd64 F + islessd128 F + islessd32 F + islessd64 F + islessequald128 F + islessequald32 F + islessequald64 F + islessgreaterd128 F + islessgreaterd32 F + islessgreaterd64 F + isnand128 F + isnand32 F + isnand64 F + isnormald128 F + isnormald32 F + isnormald64 F + isunorderedd128 F + isunorderedd32 F + isunorderedd64 F + ldexpd128 F + ldexpd32 F + ldexpd64 F + lgammad128 F + lgammad32 F + lgammad64 F + llrintd128 F + llrintd32 F + llrintd64 F + llroundd128 F + llroundd32 F + llroundd64 F + log10d128 F + log10d32 F + log10d64 F + log1pd128 F + log1pd32 F + log1pd64 F + log2d128 F + log2d32 F + log2d64 F + logbd128 F + logbd32 F + logbd64 F + logd128 F + logd32 F + logd64 F + lrintd128 F + lrintd32 F + lrintd64 F + lroundd128 F + lroundd32 F + lroundd64 F + modfd128 F + modfd32 F + modfd64 F + nand128 F + nand32 F + nand64 F + nearbyintd128 F + nearbyintd32 F + nearbyintd64 F + nextafterd128 F + nextafterd32 F + nextafterd64 F + nexttowardd128 F + nexttowardd32 F + nexttowardd64 F + powd128 F + powd32 F + powd64 F + printf_dfp F + quantized128 F + quantized32 F + quantized64 F + register_printf_dfp F + remainderd128 F + remainderd32 F + remainderd64 F + rintd128 F + rintd32 F + rintd64 F + roundd128 F + roundd32 F + roundd64 F + samequantumd128 F + samequantumd32 F + samequantumd64 F + scalblnd128 F + scalblnd32 F + scalblnd64 F + scalbnd128 F + scalbnd32 F + scalbnd64 F + signbitd128 F + signbitd32 F + signbitd64 F + sind128 F + sind32 F + sind64 F + sinhd128 F + sinhd32 F + sinhd64 F + sqrtd128 F + sqrtd32 F + sqrtd64 F + strtod128 F + strtod32 F + strtod64 F + tand128 F + tand32 F + tand64 F + tanhd128 F + tanhd32 F + tanhd64 F + tgammad128 F + tgammad32 F + tgammad64 F + truncd128 F + truncd32 F + truncd64 F + wcstod128 F + wcstod32 F + wcstod64 F +LIBDFP_1.0.13 + LIBDFP_1.0.13 A +LIBDFP_1.0.2 + LIBDFP_1.0.2 A + __isinfd128 F + __isinfd32 F + __isinfd64 F + __isnand128 F + __isnand32 F + __isnand64 F +LIBDFP_1.0.3 + LIBDFP_1.0.3 A + __fabsd128 F + __fabsd32 F + __fabsd64 F + __finited128 F + __finited32 F + __finited64 F + __fpclassifyd128 F + __fpclassifyd32 F + __fpclassifyd64 F + __isfinited128 F + __isfinited32 F + __isfinited64 F + __signbitd128 F + __signbitd32 F + __signbitd64 F + isfinited128 F + isfinited32 F + isfinited64 F +LIBDFP_1.0.9 + LIBDFP_1.0.9 A + __issignalingd128 F + __issignalingd32 F + __issignalingd64 F + issignalingd128 F + issignalingd32 F + issignalingd64 F + llogbd128 F + llogbd32 F + llogbd64 F + llquantexpd128 F + llquantexpd32 F + llquantexpd64 F + quantumd128 F + quantumd32 F + quantumd64 F + roundevend128 F + roundevend32 F + roundevend64 F +LIBDFP_PRIVATE + LIBDFP_PRIVATE A + __decoded128 F + __decoded32 F + __decoded64 F + __decrm_location F + __fe_dec_getround F + __fe_dec_setround F + __fmt_d128 F + __fmt_d32 F + __fmt_d64 F diff --git a/sysdeps/powerpc/fpu/libdfp.abilist b/sysdeps/powerpc/fpu/libdfp.abilist index 5bc8389c..0614dc8d 100644 --- a/sysdeps/powerpc/fpu/libdfp.abilist +++ b/sysdeps/powerpc/fpu/libdfp.abilist @@ -304,6 +304,16 @@ LIBDFP_1.0.0 wcstod128 F wcstod32 F wcstod64 F +LIBDFP_1.0.13 + LIBDFP_1.0.13 A + __dpd_fixddti F + __dpd_fixsdti F + __dpd_fixtdti F + __dpd_fixunsddti F + __dpd_fixunssdti F + __dpd_fixunstdti F + __dpd_floattitd F + __dpd_floatunstitd F LIBDFP_1.0.2 LIBDFP_1.0.2 A __isinfd128 F diff --git a/tests/test-fix.c b/tests/test-fix.c new file mode 100644 index 00000000..cd8e4f7a --- /dev/null +++ b/tests/test-fix.c @@ -0,0 +1,262 @@ +/* Unit test the ti (int128) conversion routines. + + Copyright (C) 2015 Free Software Foundation, Inc. + + This file is part of the Decimal Floating Point C Library. + + Author(s): Paul E. Murphy + + The Decimal Floating Point C Library is free software; you can + redistribute it and/or modify it under the terms of the GNU Lesser + General Public License version 2.1. + + The Decimal Floating Point 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 version 2.1 for more details. + + You should have received a copy of the GNU Lesser General Public + License version 2.1 along with the Decimal Floating Point C Library; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA. + + Please see libdfp/COPYING.txt for more information. */ + +#ifndef __STDC_WANT_DEC_FP__ +#define __STDC_WANT_DEC_FP__ +#endif + +#include /* DEC_NAN definition. */ +#include +#include + +#include + +#define _DECIMAL_SIZE 32 +#define DEC_TYPE _Decimal32 +#include +#undef _DECIMAL_SIZE +#undef DEC_TYPE + +#define _DECIMAL_SIZE 64 +#define DEC_TYPE _Decimal64 +#include +#undef _DECIMAL_SIZE +#undef DEC_TYPE + +#define _DECIMAL_SIZE 128 +#define DEC_TYPE _Decimal128 +#include +#undef _DECIMAL_SIZE +#undef DEC_TYPE + +#include "scaffold.c" + +/* TODO: For now, BID does not have dpd conversions. */ +#ifndef __DECIMAL_BID_FORMAT__ +#define HAS_TI 1 +#endif + +union tidi +{ + __int128 ti; + unsigned long long int di[2]; +}; + +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define INT128_MIN ({union tidi d = { .di = {0x8000000000000000LL, 0LL}}; d.ti; }) +#else +# define INT128_MIN ({union tidi d = { .di = {0x0LL, 0x8000000000000000LL}}; d.ti; }) +#endif + +/* 128b integer lacks printf support. */ +#define DECLARE_TESTS(_t,_n) \ + struct \ + { \ + int line; \ + _Decimal##_t x; \ + char const *e; \ + } d##_t##_n[] + +DECLARE_TESTS(128,) = { +#if HAS_TI + {__LINE__, 0.DL, "0"}, + {__LINE__, 1.DL, "1"}, + {__LINE__, -1.DL, "-1"}, + {__LINE__, -1.12DL, "-1"}, + {__LINE__, 170141183460469231731687303715884100000.DL, "170141183460469231731687303715884100000"}, + {__LINE__, -170141183460469231731687303715884100000.DL, "-170141183460469231731687303715884100000"}, + {__LINE__, 170141183460469231731687303715884200000.DL, "170141183460469231731687303715884105727"}, + {__LINE__, -170141183460469231731687303715884200000.DL, "−170141183460469231731687303715884105728"}, + {__LINE__, -1e17DL, "-100000000000000000"}, + {__LINE__, 1e17DL, "100000000000000000"}, + {__LINE__, 1e20DL, "100000000000000000000"}, + {__LINE__, DEC_INFINITY, "170141183460469231731687303715884105727"}, + {__LINE__, -DEC_INFINITY, "−170141183460469231731687303715884105728"}, + {__LINE__, __builtin_nand128 (""), "−170141183460469231731687303715884105728"}, +#endif /* HAS_TI */ +}; + +DECLARE_TESTS(128,uns) = { +#if HAS_TI + {__LINE__, 0.DL, "0"}, + {__LINE__, 1.DL, "1"}, + {__LINE__, -1.DL, "0"}, + {__LINE__, -.1DL, "0"}, + {__LINE__, 340282366920938463463374607431768200000.DL, "340282366920938463463374607431768200000"}, + {__LINE__, 340282366920938463463374607431768300000.DL, "340282366920938463463374607431768211455"}, + {__LINE__, 1e5DL, "100000"}, + {__LINE__, 1e17DL, "100000000000000000"}, + {__LINE__, 1e22DL, "10000000000000000000000"}, + {__LINE__, -1e17DL, "0"}, + {__LINE__, __builtin_nand128 (""), "0"}, + {__LINE__, DEC_INFINITY, "340282366920938463463374607431768211455"}, +#endif /* HAS_TI */ +}; + +DECLARE_TESTS(64,) = { + {__LINE__, 0.DD, "0"}, + {__LINE__, 1.DD, "1"}, + {__LINE__, -1.DD, "-1"}, + {__LINE__, -123.DD, "-123"}, + {__LINE__, 123.DD, "123"}, + {__LINE__, -1.12DD, "-1"}, + {__LINE__, 170141183460469200000000000000000000000.DD, "170141183460469200000000000000000000000"}, + {__LINE__,-170141183460469200000000000000000000000.DD,"-170141183460469200000000000000000000000"}, + {__LINE__, 170141183460469300000000000000000000000.DD, "170141183460469231731687303715884105727"}, + {__LINE__,-170141183460469300000000000000000000000.DD,"−170141183460469231731687303715884105728"}, + {__LINE__, -1e17DD, "-100000000000000000"}, + {__LINE__, 1e17DD, "100000000000000000"}, + {__LINE__, 1e20DD, "100000000000000000000"}, + {__LINE__, DEC_INFINITY, "170141183460469231731687303715884105727"}, + {__LINE__, -DEC_INFINITY, "−170141183460469231731687303715884105728"}, + {__LINE__, __builtin_nand64(""), "−170141183460469231731687303715884105728"}, +}; + +DECLARE_TESTS(64,uns) = { + {__LINE__, 0.DD, "0"}, + {__LINE__, 1.DD, "1"}, + {__LINE__, -1.DD, "0"}, + {__LINE__, -.1DD, "0"}, + {__LINE__, 340282366920938400000000000000000000000.DD, "340282366920938400000000000000000000000"}, + {__LINE__, 340282366920938500000000000000000000000.DD, "340282366920938463463374607431768211455"}, + {__LINE__, 1e5DD, "100000"}, + {__LINE__, 1e17DD, "100000000000000000"}, + {__LINE__, 1e22DD, "10000000000000000000000"}, + {__LINE__, -1e17DD, "0"}, + {__LINE__, __builtin_nand64 (""), "0"}, + {__LINE__, DEC_INFINITY, "340282366920938463463374607431768211455"}, +}; + +DECLARE_TESTS(32,) = { + {__LINE__, 0.DF, "0"}, + {__LINE__, 1.DF, "1"}, + {__LINE__, -1.DF, "-1"}, + {__LINE__, -123.DF, "-123"}, + {__LINE__, 123.DF, "123"}, + {__LINE__, -1.12DF, "-1"}, + {__LINE__, 170141100000000000000000000000000000000.DF, "170141100000000000000000000000000000000"}, + {__LINE__,-170141100000000000000000000000000000000.DF,"-170141100000000000000000000000000000000"}, + {__LINE__, 170141200000000000000000000000000000000.DF, "170141183460469231731687303715884105727"}, + {__LINE__,-170141200000000000000000000000000000000.DF,"−170141183460469231731687303715884105728"}, + {__LINE__, -1e17DF, "-100000000000000000"}, + {__LINE__, 1e17DF, "100000000000000000"}, + {__LINE__, 1e20DF, "100000000000000000000"}, + {__LINE__, DEC_INFINITY, "170141183460469231731687303715884105727"}, + {__LINE__, -DEC_INFINITY, "−170141183460469231731687303715884105728"}, + {__LINE__, __builtin_nand32(""), "−170141183460469231731687303715884105728"}, +}; + +DECLARE_TESTS(32,uns) = { + {__LINE__, 0.DF, "0"}, + {__LINE__, 1.DF, "1"}, + {__LINE__, -1.DF, "0"}, + {__LINE__, -.1DF, "0"}, + {__LINE__, 340282300000000000000000000000000000000.DF, "340282300000000000000000000000000000000"}, + {__LINE__, 340282400000000000000000000000000000000.DF, "340282366920938463463374607431768211455"}, + {__LINE__, 1e5DF, "100000"}, + {__LINE__, 1e17DF, "100000000000000000"}, + {__LINE__, 1e22DF, "10000000000000000000000"}, + {__LINE__, -1e17DF, "0"}, + {__LINE__, __builtin_nand32 (""), "0"}, + {__LINE__, DEC_INFINITY, "340282366920938463463374607431768211455"}, +}; + +/* Mediocre stringify routing for all valid td conversions to ti/unsti. */ +static char const * +stringifyti (__int128 val) +{ + static char s128str[60]; + memset (s128str, ' ', sizeof (s128str)); + long i = sizeof (s128str) - 2, neg = 0; + s128str[sizeof (s128str) - 1] = 0; + s128str[sizeof (s128str) - 2] = '0'; + if (val == 0) + i--; + else if(val == INT128_MIN) + return "−170141183460469231731687303715884105728"; + if (val < 0) + { + neg = 1; + val = -val; + } + while (val) + { + __int128 rem = val % (__int128) 10; + val /= (__int128) 10; + s128str[i--] = '0' + (char) rem; + } + if (neg) + s128str[i--] = '-'; + return &s128str[i + 1]; +} + +/* Likewise for unsigned. */ +static char const * +stringifyunsti (unsigned __int128 val) +{ + static char s128str[60]; + memset (s128str, ' ', sizeof (s128str)); + long i = sizeof (s128str) - 2; + s128str[sizeof (s128str) - 1] = 0; + s128str[sizeof (s128str) - 2] = '0'; + if (val == 0) + i--; + while (val) + { + __int128 rem = val % (__int128) 10; + val /= (__int128) 10; + s128str[i--] = '0' + (char) rem; + } + return &s128str[i + 1]; +} + +typedef __int128 ti; +typedef unsigned __int128 unsti; + +#define RUN_TEST_SERIES(_t, _type, _name) \ + for (i = 0; i < (int)(sizeof(_t)/sizeof(_t[0])); ++i) \ + { \ + _type r = _t[i].x; \ + fprintf (stdout, #_name " (%DDgDL) in: %s:%d\n", \ + (_Decimal128) _t[i].x, __FILE__, __LINE__ - 1); \ + _SC_P (__FILE__, _t[i].line, _t[i].e, stringify##_type (r)); \ + } + +int +main (void) +{ + int i; + + RUN_TEST_SERIES (d128, ti, fixtdti); + RUN_TEST_SERIES (d128uns, unsti, fixunstdti); + RUN_TEST_SERIES (d64, ti, fixddti); + RUN_TEST_SERIES (d64uns, unsti, fixunsddti); + RUN_TEST_SERIES (d32, ti, fixsdti); + RUN_TEST_SERIES (d32uns, unsti, fixunssdti); + + _REPORT (); + + /* fail comes from scaffold.c */ + return fail; +} diff --git a/tests/test-float.c b/tests/test-float.c new file mode 100644 index 00000000..9b4a38db --- /dev/null +++ b/tests/test-float.c @@ -0,0 +1,155 @@ +/* Unit test the ti (int128) conversion routines. + + Copyright (C) 2015 Free Software Foundation, Inc. + + This file is part of the Decimal Floating Point C Library. + + Author(s): Paul E. Murphy + + The Decimal Floating Point C Library is free software; you can + redistribute it and/or modify it under the terms of the GNU Lesser + General Public License version 2.1. + + The Decimal Floating Point 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 version 2.1 for more details. + + You should have received a copy of the GNU Lesser General Public + License version 2.1 along with the Decimal Floating Point C Library; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA. + + Please see libdfp/COPYING.txt for more information. */ + +#ifndef __STDC_WANT_DEC_FP__ +#define __STDC_WANT_DEC_FP__ +#endif + +#include /* DEC_NAN definition. */ +#include +#include + +#include + +#define _DECIMAL_SIZE 32 +#define DEC_TYPE _Decimal32 +#include +#undef _DECIMAL_SIZE +#undef DEC_TYPE + +#define _DECIMAL_SIZE 64 +#define DEC_TYPE _Decimal64 +#include +#undef _DECIMAL_SIZE +#undef DEC_TYPE + +#define _DECIMAL_SIZE 128 +#define DEC_TYPE _Decimal128 +#include +#undef _DECIMAL_SIZE +#undef DEC_TYPE + +/* TODO: For now, BID does not have dpd conversions. */ +#ifndef __DECIMAL_BID_FORMAT__ +#define HAS_TI 1 +#endif + +#define _WANT_VC 1 /* Pick up the _VC_P(x,y,fmt) macro. */ +#include "scaffold.c" /* Pick up the _VC_P(x,y,fmt) macro. */ + +/* We're going to be comparing fields so we need to extract the data. This is a + * sneaky way to get around the fact that get_digits_d* isn't exported from + * libdfp. */ +#ifdef __DECIMAL_BID_FORMAT__ +#include "../sysdeps/bid/bid-private.c" +#else +#include "../sysdeps/dpd/dpd-private.c" +#endif + +typedef struct +{ + const char *format; /* Expected value printf format. */ + int uns; /* Signed or unsigned conversion. */ + int line; + char const *x; /* Stringified __int128 input value. */ + _Decimal128 e; /* Expected result. */ +} d128_type; + +static d128_type d128[] = { +#if HAS_TI + {"%DDe", 0, __LINE__, "0", 0.DL}, + {"%DDe", 0, __LINE__, "1", 1.DL}, + {"%DDe", 0, __LINE__, "-1", -1.DL}, + {"%DDe", 0, __LINE__, "170141183460469231731687303715884100000", + 170141183460469231731687303715884100000.DL}, + {"%DDe", 0, __LINE__, "170141183460469231731687303715884100001", + 170141183460469231731687303715884100000.DL}, + {"%DDe", 0, __LINE__, "-170141183460469231731687303715884100000", + -170141183460469231731687303715884100000.DL}, + {"%DDe", 0, __LINE__, "-100000000000000000", -1e17DL}, + {"%DDe", 0, __LINE__, "100000000000000000", 1e17DL}, + + /* Unsigned conversions. */ + {"%DDe", 1, __LINE__, "340282366920938463463374607431768211455", + 340282366920938463463374607431768200000.DL}, + {"%DDe", 1, __LINE__, "1000000", 1000000.DL}, + {"%DDe", 1, __LINE__, "100000000000000000", 100000000000000000.DL}, + {"%DDe", 1, __LINE__, "0", 0.DL}, +#endif /* HAS_TI */ +}; + +static int d128_s = sizeof (d128) / sizeof (d128[0]); + +/* Mediocre string to ti/unsti function. */ +static __int128 +intifyti (char const *str) +{ + unsigned __int128 val = 0; + long neg = 0; + if (*str == '-') + { + neg = 1; + str++; + } + while (*str) + { + val *= (__int128) 10; + val += (*str - '0'); + str++; + } + if (neg) + return -((__int128) val); + return val; +} + +int +main (void) +{ + int i; + + for (i = 0; i < d128_s; ++i) + { + _Decimal128 x; + char const *fmt; + if (d128[i].uns) + { + fmt = "floatunstitd (%s) in: %s:%d\n"; + unsigned __int128 x_ti = intifyti (d128[i].x); + x = x_ti; + } + else + { + fmt = "floattitd (%s) in: %s:%d\n"; + __int128 x_ti = intifyti (d128[i].x); + x = x_ti; + } + fprintf (stdout, fmt, d128[i].x, __FILE__, __LINE__); + _VC_P (__FILE__, d128[i].line, d128[i].e, x, d128[i].format); + } + + _REPORT (); + + /* fail comes from scaffold.c */ + return fail; +}