X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f X-Recipient: djgpp-workers AT delorie DOT com X-Authenticated: #27081556 X-Provags-ID: V01U2FsdGVkX18uPygPr7YuB7ac+aQAO6te6UJdz4ma8XhCFfPPl+ HnsX0+HcsOTdOJ Message-ID: <51296597.3060304@gmx.de> Date: Sun, 24 Feb 2013 01:57:59 +0100 From: Juan Manuel Guerrero User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:16.0) Gecko/20121025 Thunderbird/16.0.2 MIME-Version: 1.0 To: djgpp-workers AT delorie DOT com Subject: Implementation of trunc[fl] family of functions. Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit X-Y-GMX-Trusted: 0 Reply-To: djgpp-workers AT delorie DOT com Below a patch that implements the trunc[fl] family of functions. The files have been placed /djgpp/src/libc/c99/math so they become part of libc.a. May be it is preferred that the functions go into libm.a. If this is preferred, let me know. For every supplied function there is a test file and a .txh file. As usual, suggestions, object comments are welcome. Regards, Juan M. Guerrero 2013-02-23 Juan Manuel Guerrero * djgpp/src/libc/c99/math/truncl.c: Implementation of truncl function. * djgpp/src/libc/c99/math/truncl.txh: Documentation about truncl function. * djgpp/tests/libc/c99/math/t-truncl.c: Test truncl function. 2013-02-20 Juan Manuel Guerrero * djgpp/tests/libc/c99/math/t-trunc.c: Test trunc function. 2013-02-18 Juan Manuel Guerrero * djgpp/src/libc/c99/math/trunc.c: Implementation of trunc function. * djgpp/src/libc/c99/math/trunc.txh: Documentation about trunc function. 2013-02-17 Juan Manuel Guerrero * djgpp/include/math.h: Added trunc[fl] function prototypes. * djgpp/src/libc/c99/math/makefile: Added trunc[fl] functions. * djgpp/src/libc/c99/math/truncf.c: Implementation of truncf function. * djgpp/src/libc/c99/math/truncf.txh: Documentation about truncf function. * djgpp/src/docs/kb/wc204.txi: Info about trunc[fl] functions added. * djgpp/tests/libc/c99/math/makefile: Added t-trunc[fl] functions. * djgpp/tests/libc/c99/math/t-truncf.c: Test truncf function. diff -aprNU5 djgpp.orig/include/math.h djgpp/include/math.h --- djgpp.orig/include/math.h 2013-02-24 01:12:36 +0000 +++ djgpp/include/math.h 2013-02-24 01:30:14 +0000 @@ -145,10 +145,13 @@ double cbrt(double _x); double exp2(double _x); double expm1(double _x); double hypot(double _x, double _y); double log1p(double _x); double log2(double _x); +double trunc(double _x); +float truncf(float _x); +long double truncl(long double _x); /* These are in libm.a (Cygnus). You must link -lm to get these */ /* See libm/math.h for comments */ extern double erf(double); diff -aprNU5 djgpp.orig/src/docs/kb/wc204.txi djgpp/src/docs/kb/wc204.txi --- djgpp.orig/src/docs/kb/wc204.txi 2013-01-27 23:26:04 +0000 +++ djgpp/src/docs/kb/wc204.txi 2013-02-24 01:36:00 +0000 @@ -1272,5 +1272,11 @@ by @code{_doscan} and the @code{scanf} f @tindex rlim_t @tindex struct rlimit AT r{, and }rlim_t The type @code{rlim_t} has been added. @code{rlim_t} is now used for the @code{rlim_cur} and @code{rlim_max} members of @code{struct rlimit}. + +@findex trunc AT r{, added} +@findex truncf AT r{, added} +@findex truncl AT r{, added} +The @acronym{C99} functions @code{trunc}, @code{truncf} and @code{truncl} +were added. diff -aprNU5 djgpp.orig/src/libc/c99/math/makefile djgpp/src/libc/c99/math/makefile --- djgpp.orig/src/libc/c99/math/makefile 2008-04-06 21:06:40 +0000 +++ djgpp/src/libc/c99/math/makefile 2013-02-24 01:36:00 +0000 @@ -1,5 +1,6 @@ +# Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details # Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details # Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details TOP=../.. SRC += errhandl.c @@ -13,10 +14,13 @@ SRC += fpclassf.S SRC += fpclassd.S SRC += fpclassl.S SRC += sgnbitd.c SRC += sgnbitf.c SRC += sgnbitld.c +SRC += trunc.c +SRC += truncf.c +SRC += truncl.c include $(TOP)/../makefile.inc fpclassf.S: fp-asm.h diff -aprNU5 djgpp.orig/src/libc/c99/math/trunc.c djgpp/src/libc/c99/math/trunc.c --- djgpp.orig/src/libc/c99/math/trunc.c 1970-01-01 00:00:00 +0000 +++ djgpp/src/libc/c99/math/trunc.c 2013-02-24 01:36:00 +0000 @@ -0,0 +1,62 @@ +/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +#define DOUBLE_BIAS (0x3FFU) +#define MAX_BIN_EXPONENT (1023) +#define MIN_BIN_EXPONENT (-1022) +#define BIN_DIGITS_IN_FRACTION (51) /* Amount of binary digits in fraction part of mantissa. */ +#define BIN_DIGITS_IN_MSW (20) /* Amount of binary digits in msw of the fraction part of mantissa. */ +#define NO_SIGNIFICANT_DIGITS_IN_LSW(x) ((x) < BIN_DIGITS_IN_MSW) + + +double +trunc(double x) +{ + _double_union_t ieee_value; + int unbiased_exponent; + + + ieee_value.d = x; + unbiased_exponent = ieee_value.dt.exponent - DOUBLE_BIAS; + + if (NO_SIGNIFICANT_DIGITS_IN_LSW(unbiased_exponent)) + { + /* All significant digits are in msw. */ + if (unbiased_exponent < 0) + { + /* The magnitude of the number is < 1 so the result is +-0. */ + int sign = ieee_value.dt.sign; + ieee_value.d = 0; + ieee_value.dt.sign = sign; + } + else + { + ieee_value.dt.mantissah &= ~(0x000FFFFFU >> unbiased_exponent); + ieee_value.dt.mantissal = 0; + } + + return ieee_value.d; + } + else if (unbiased_exponent > BIN_DIGITS_IN_FRACTION) + { + if (unbiased_exponent > MAX_BIN_EXPONENT) + return x + x; /* x is NaN or infinite. */ + } + else + { + /* + * All fraction bits in msw are relevant. + * Truncate irrelevant bits from lsw. + */ + ieee_value.dt.mantissal &= ~(0xFFFFFFFFU >> (unbiased_exponent - BIN_DIGITS_IN_MSW)); + return ieee_value.d; + } + + + /* + * All bits in the fraction fields of the msw + * and lsw are needed in the result. + */ + return x; +} diff -aprNU5 djgpp.orig/src/libc/c99/math/trunc.txh djgpp/src/libc/c99/math/trunc.txh --- djgpp.orig/src/libc/c99/math/trunc.txh 1970-01-01 00:00:00 +0000 +++ djgpp/src/libc/c99/math/trunc.txh 2013-02-24 01:36:00 +0000 @@ -0,0 +1,32 @@ +@node trunc, math +@findex trunc +@subheading Syntax + +@example +#include + +double trunc(double x); +@end example + +@subheading Description + +The function rounds its argument to the integer value, in floating point +format, nearest to but no larger in magnitude than the argument. + + +@subheading Return Value + +The truncated integer value in double format. +If @var{x} is NaN, a NaN will be returned. +If @var{x} is +/-0 or +/-Inf, @var{x} will be returned. + +@subheading Portability + +@portability !ansi-c89, ansi-c99 + +@subheading Example + +@example +double pi = -3.1415926535897932384626433832795; +double integer_part = trunc(pi); /* Returns -3.0 */ +@end example diff -aprNU5 djgpp.orig/src/libc/c99/math/truncf.c djgpp/src/libc/c99/math/truncf.c --- djgpp.orig/src/libc/c99/math/truncf.c 1970-01-01 00:00:00 +0000 +++ djgpp/src/libc/c99/math/truncf.c 2013-02-24 01:36:00 +0000 @@ -0,0 +1,40 @@ +/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +#define FLOAT_BIAS (0x7FU) +#define MAX_BIN_EXPONENT (127) +#define MIN_BIN_EXPONENT (-126) +#define BIN_DIGITS_IN_FRACTION (23) /* Amount of binary digits in fraction part of mantissa. */ + + +float +truncf(float x) +{ + _float_union_t ieee_value; + int unbiased_exponent; + + + ieee_value.f = x; + unbiased_exponent = ieee_value.ft.exponent - FLOAT_BIAS; + + if (unbiased_exponent < BIN_DIGITS_IN_FRACTION) + { + if (unbiased_exponent < 0) + { + int sign = ieee_value.ft.sign; + ieee_value.f = 0; /* The magnitude of the number is < 1 so the result is +-0. */ + ieee_value.ft.sign = sign; + } + else + ieee_value.ft.mantissa &= ~(0x7FFFFFU >> unbiased_exponent); + + return ieee_value.f; + } + else if (unbiased_exponent > MAX_BIN_EXPONENT) + return x + x; /* x is NaN or infinite. */ + + + /* All bits in the fraction field are relevant. */ + return x; +} diff -aprNU5 djgpp.orig/src/libc/c99/math/truncf.txh djgpp/src/libc/c99/math/truncf.txh --- djgpp.orig/src/libc/c99/math/truncf.txh 1970-01-01 00:00:00 +0000 +++ djgpp/src/libc/c99/math/truncf.txh 2013-02-24 01:36:00 +0000 @@ -0,0 +1,32 @@ +@node truncf, math +@findex truncf +@subheading Syntax + +@example +#include + +float truncf(float x); +@end example + +@subheading Description + +The function rounds its argument to the integer value, in floating point +format, nearest to but no larger in magnitude than the argument. + + +@subheading Return Value + +The truncated integer value in floating format. +If @var{x} is NaN, a NaN will be returned. +If @var{x} is +/-0 or +/-Inf, @var{x} will be returned. + +@subheading Portability + +@portability !ansi-c89, ansi-c99 + +@subheading Example + +@example +float pi = -3.1415926535897932384626433832795; +float integer_part = truncf(pi); /* Returns -3.0 */ +@end example diff -aprNU5 djgpp.orig/src/libc/c99/math/truncl.c djgpp/src/libc/c99/math/truncl.c --- djgpp.orig/src/libc/c99/math/truncl.c 1970-01-01 00:00:00 +0000 +++ djgpp/src/libc/c99/math/truncl.c 2013-02-24 01:36:00 +0000 @@ -0,0 +1,62 @@ +/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */ +#include +#include + +#define LONG_DOUBLE_BIAS (0x3FFFU) +#define MAX_BIN_EXPONENT (16383) +#define MIN_BIN_EXPONENT (-16382) +#define BIN_DIGITS_IN_FRACTION (63) /* Amount of binary digits in fraction part of mantissa. */ +#define BIN_DIGITS_IN_MSW (31) /* Amount of binary digits in msw of the fraction part of mantissa. */ +#define NO_SIGNIFICANT_DIGITS_IN_LSW(x) ((x) < BIN_DIGITS_IN_MSW) + + +long double +truncl(long double x) +{ + _longdouble_union_t ieee_value; + int unbiased_exponent; + + + ieee_value.ld = x; + unbiased_exponent = ieee_value.ldt.exponent - LONG_DOUBLE_BIAS; + + if (NO_SIGNIFICANT_DIGITS_IN_LSW(unbiased_exponent)) + { + /* All significant digits are in msw. */ + if (unbiased_exponent < 0) + { + /* The magnitude of the number is < 1 so the result is +-0. */ + int sign = ieee_value.ldt.sign; + ieee_value.ld = 0; + ieee_value.ldt.sign = sign; + } + else + { + ieee_value.ldt.mantissah &= ~(0x7FFFFFFFU >> unbiased_exponent); + ieee_value.ldt.mantissal = 0; + } + + return ieee_value.ld; + } + else if (unbiased_exponent > BIN_DIGITS_IN_FRACTION) + { + if (unbiased_exponent > MAX_BIN_EXPONENT) + return x + x; /* x is NaN or infinite. */ + } + else + { + /* + * All fraction bits in msw are relevant. + * Truncate irrelevant bits from lsw. + */ + ieee_value.ldt.mantissal &= ~(0xFFFFFFFFU >> (unbiased_exponent - BIN_DIGITS_IN_MSW)); + return ieee_value.ld; + } + + + /* + * All bits in the fraction fields of the msw + * and lsw are needed in the result. + */ + return x; +} diff -aprNU5 djgpp.orig/src/libc/c99/math/truncl.txh djgpp/src/libc/c99/math/truncl.txh --- djgpp.orig/src/libc/c99/math/truncl.txh 1970-01-01 00:00:00 +0000 +++ djgpp/src/libc/c99/math/truncl.txh 2013-02-24 01:36:00 +0000 @@ -0,0 +1,25 @@ +@node truncl, math +@findex truncl +@subheading Syntax + +@example +#include + +long double truncl(long double x); +@end example + +@subheading Description + +The function rounds its argument to the integer value, in floating point +format, nearest to but no larger in magnitude than the argument. + + +@subheading Return Value + +The truncated integer value in long double format. +If @var{x} is NaN, a NaN will be returned. +If @var{x} is +/-0 or +/-Inf, @var{x} will be returned. + +@subheading Portability + +@portability !ansi-c89, ansi-c99 diff -aprNU5 djgpp.orig/tests/libc/c99/math/makefile djgpp/tests/libc/c99/math/makefile --- djgpp.orig/tests/libc/c99/math/makefile 2003-10-25 11:22:52 +0000 +++ djgpp/tests/libc/c99/math/makefile 2013-02-24 01:36:00 +0000 @@ -1,7 +1,10 @@ TOP=../.. SRC += t-fpclas.c SRC += t-nan.c SRC += t-nan2.c +SRC += t-trunc.c +SRC += t-truncf.c +SRC += t-truncl.c include $(TOP)/../makefile.inc diff -aprNU5 djgpp.orig/tests/libc/c99/math/t-trunc.c djgpp/tests/libc/c99/math/t-trunc.c --- djgpp.orig/tests/libc/c99/math/t-trunc.c 1970-01-01 00:00:00 +0000 +++ djgpp/tests/libc/c99/math/t-trunc.c 2013-02-24 01:36:00 +0000 @@ -0,0 +1,80 @@ +/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include + +static const double_t tests_double[][2] = +{ + /* value should be */ + /* Zeros. */ + { { 0x0U, 0x0U, 0x0U, 0 }, { 0x0U, 0x0U, 0x0U, 0 } }, /* 0.0 */ + { { 0x0U, 0x0U, 0x0U, 1 }, { 0x0U, 0x0U, 0x0U, 1 } }, /* -0.0 */ + + /* Subnormals aka denormals. */ + { { 0x1U, 0x0U, 0x0U, 0 }, { 0x0U, 0x0U, 0x0U, 0 } }, /* Very small number. */ + { { 0x1U, 0x0U, 0x0U, 1 }, { 0x0U, 0x0U, 0x0U, 1 } }, /* Very small -number. */ + + /* Normals. */ + { { 0x1U, 0x0U, 0x1U, 0 }, { 0x0U, 0x0U, 0x0U, 0 } }, /* Small number. */ + { { 0x1U, 0x0U, 0x1U, 1 }, { 0x0U, 0x0U, 0x0U, 1 } }, /* Small -number. */ + { { 0xFFFFFFFFU, 0x7FFFFU, 0x7FEU, 0 }, { 0xFFFFFFFFU, 0x7FFFFU, 0x7FEU, 0 } }, /* Big number. */ + { { 0xFFFFFFFFU, 0x7FFFFU, 0x7FEU, 1 }, { 0xFFFFFFFFU, 0x7FFFFU, 0x7FEU, 1 } }, /* Big -number. */ + + /* Infs. */ + { { 0x0U, 0x0U, 0x7FFU, 0 }, { 0x0U, 0x0U, 0x7FFU, 0 } }, /* Inf */ + { { 0x0U, 0x0U, 0x7FFU, 1 }, { 0x0U, 0x0U, 0x7FFU, 1 } }, /* -Inf */ + + /* NaNs. */ + { { 0x1U, 0x0U, 0x7FFU, 0 }, { 0x1U, 0x80000U, 0x7FFU, 0 } }, /* SNaN */ + { { 0x1U, 0x0U, 0x7FFU, 1 }, { 0x1U, 0x80000U, 0x7FFU, 1 } }, /* -SNaN */ + { { 0x0U, 0xFFFFFU, 0x7FFU, 0 }, { 0x0U, 0xFFFFFU, 0x7FFU, 0 } }, /* QNaN */ + { { 0x0U, 0xFFFFFU, 0x7FFU, 1 }, { 0x0U, 0xFFFFFU, 0x7FFU, 1 } }, /* -QNaN */ + + /* Number. */ + { { 0x54442D18U, 0x921FBU, 0x400U, 0 }, { 0x0U, 0x80000U, 0x400U, 0 } }, /* PI */ + { { 0x54442D18U, 0x921FBU, 0x400U, 1 }, { 0x0U, 0x80000U, 0x400U, 1 } }, /* -PI */ + + /* Different mantissa patterns. */ + { { 0xFFFFFFFFU, 0xF0003U, 0x3FFU + 0x016U, 0 }, { 0xC0000000U, 0xF0003U, 0x415U, 0 } }, + { { 0xFFFFFFFFU, 0xF0003U, 0x3FFU + 0x015U, 0 }, { 0x80000000U, 0xF0003U, 0x414U, 0 } }, + { { 0xFFFFFFFFU, 0xF0003U, 0x3FFU + 0x014U, 0 }, { 0x00000000U, 0xF0003U, 0x413U, 0 } }, + { { 0xFFFFFFFFU, 0xF0003U, 0x3FFU + 0x013U, 0 }, { 0x00000000U, 0xF0002U, 0x412U, 0 } } +}; + +static const size_t n_tests_double = sizeof(tests_double) / sizeof(tests_double[0]); + + + +int main(void) +{ + int i, counter; + + for (counter = i = 0; i < n_tests_double; i++) + { + _double_union_t value, result, should_be; + value.dt = tests_double[i][0]; + result.d = trunc(value.d); + should_be.dt = tests_double[i][1]; + + if (should_be.dt.sign == result.dt.sign && + should_be.dt.exponent == result.dt.exponent && + should_be.dt.mantissah == result.dt.mantissah && + should_be.dt.mantissal == result.dt.mantissal) + { + result.d = trunc(value.d); + if (should_be.dt.sign == result.dt.sign && + should_be.dt.exponent == result.dt.exponent && + should_be.dt.mantissah == result.dt.mantissah && + should_be.dt.mantissal == result.dt.mantissal) + counter++; + else + printf("Test failed: value to truncate = %.12lg result = %.12lg should be = %.12lg\n", value.d, result.d, should_be.d); + } + else + printf("Test failed: value to truncate = %.12lg result = %.12lg should be = %.12lg\n", value.d, result.d, should_be.d); + } + printf("%s\n", (counter < n_tests_double) ? "Test failed." : "Test succeded."); + + return 0; +} diff -aprNU5 djgpp.orig/tests/libc/c99/math/t-truncf.c djgpp/tests/libc/c99/math/t-truncf.c --- djgpp.orig/tests/libc/c99/math/t-truncf.c 1970-01-01 00:00:00 +0000 +++ djgpp/tests/libc/c99/math/t-truncf.c 2013-02-24 01:36:00 +0000 @@ -0,0 +1,76 @@ +/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include + +static const float_t tests_float[][2] = +{ + /* value should be */ + /* Zeros. */ + { { 0x0U, 0x0U, 0 }, { 0x0U, 0x0U, 0 } }, /* 0.0 */ + { { 0x0U, 0x0U, 1 }, { 0x0U, 0x0U, 1 } }, /* -0.0 */ + + /* Subnormals aka denormals. */ + { { 0x1U, 0x0U, 0 }, { 0x0U, 0x0U, 0 } }, /* Very small number. */ + { { 0x1U, 0x0U, 1 }, { 0x0U, 0x0U, 1 } }, /* Very small -number. */ + + /* Normals. */ + { { 0x1U, 0x1U, 0 }, { 0x0U, 0x0U, 0 } }, /* Small number. */ + { { 0x1U, 0x1U, 1 }, { 0x0U, 0x0U, 1 } }, /* Small -number. */ + { { 0xFFFFU, 0xFEU, 0 }, { 0xFFFFU, 0xFEU, 0 } }, /* Big number. */ + { { 0xFFFFU, 0xFEU, 1 }, { 0xFFFFU, 0xFEU, 1 } }, /* Big -number. */ + + /* Infs. */ + { { 0x0U, 0xFFU, 0 }, { 0x0U, 0xFFU, 0 } }, /* Inf */ + { { 0x0U, 0xFFU, 1 }, { 0x0U, 0xFFU, 1 } }, /* -Inf */ + + /* NaNs. */ + { { 0x1U, 0xFFU, 0 }, { 0x400001U, 0xFFU, 0 } }, /* SNaN */ + { { 0x1U, 0xFFU, 1 }, { 0x400001U, 0xFFU, 1 } }, /* -SNaN */ + { { 0x7FFFFFU, 0xFFU, 0 }, { 0x7FFFFFU, 0xFFU, 0 } }, /* QNaN */ + { { 0x7FFFFFU, 0xFFU, 1 }, { 0x7FFFFFU, 0xFFU, 1 } }, /* -QNaN */ + + /* Number. */ + { { 0x490FDBU, 0x80U, 0 }, { 0x400000U, 0x80U, 0 } }, /* PI */ + { { 0x490FDBU, 0x80U, 1 }, { 0x400000U, 0x80U, 1 } }, /* -PI */ + + /* Different mantissa patterns. */ + { { 0x7FFFFFU, 0x96U, 0 }, { 0x7FFFFFU, 0x96U, 0 } }, + { { 0x7FFFFFU, 0x95U, 0 }, { 0x7FFFFEU, 0x95U, 0 } }, + { { 0x1555FFU, 0x8DU, 0 }, { 0x155400U, 0x8DU, 0 } } +}; + +static const size_t n_tests_float = sizeof(tests_float) / sizeof(tests_float[0]); + + +int main(void) +{ + int i, counter; + + for (counter = i = 0; i < n_tests_float; i++) + { + _float_union_t value, result, should_be; + value.ft = tests_float[i][0]; + result.f = truncf(value.f); + should_be.ft = tests_float[i][1]; + + if (should_be.ft.sign == result.ft.sign && + should_be.ft.exponent == result.ft.exponent && + should_be.ft.mantissa == result.ft.mantissa) + { + result.f = truncf(result.f); + if (should_be.ft.sign == result.ft.sign && + should_be.ft.exponent == result.ft.exponent && + should_be.ft.mantissa == result.ft.mantissa) + counter++; + else + printf("Test failed: value to truncate = %.5g result = %.5g should be = %.5g\n", value.f, result.f, should_be.f); + } + else + printf("Test failed: value to truncate = %.5g result = %.5g should be = %.5g\n", value.f, result.f, should_be.f); + } + printf("%s\n", (counter < n_tests_float) ? "Test failed." : "Test succeded."); + + return 0; +} diff -aprNU5 djgpp.orig/tests/libc/c99/math/t-truncl.c djgpp/tests/libc/c99/math/t-truncl.c --- djgpp.orig/tests/libc/c99/math/t-truncl.c 1970-01-01 00:00:00 +0000 +++ djgpp/tests/libc/c99/math/t-truncl.c 2013-02-24 01:36:00 +0000 @@ -0,0 +1,80 @@ +/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */ + +#include +#include +#include + +static const long_double_t tests_long_double[][2] = +{ + /* value should be */ + /* Zeros. */ + { { 0x0U, 0x0U, 0x0U, 0 }, { 0x0U, 0x0U, 0x0U, 0 } }, /* 0.0 */ + { { 0x0U, 0x0U, 0x0U, 1 }, { 0x0U, 0x0U, 0x0U, 1 } }, /* -0.0 */ + + /* Subnormals aka denormals. */ + { { 0x1U, 0x0U, 0x0U, 0 }, { 0x0U, 0x0U, 0x0U, 0 } }, /* Very small number. */ + { { 0x1U, 0x0U, 0x0U, 1 }, { 0x0U, 0x0U, 0x0U, 1 } }, /* Very small -number. */ + + /* Normals. */ + { { 0x0U, 0x80000000U, 0x1U, 0 }, { 0x0U, 0x0U, 0x0U, 0 } }, /* Small number. */ + { { 0x0U, 0x80000000U, 0x1U, 1 }, { 0x0U, 0x0U, 0x0U, 1 } }, /* Small -number. */ + { { 0xFFFFFFFFU, 0xFFFFFFFFU, 0x7FFEU, 0 }, { 0xFFFFFFFFU, 0xFFFFFFFFU, 0x7FFEU, 0 } }, /* Big number. */ + { { 0xFFFFFFFFU, 0xFFFFFFFFU, 0x7FFEU, 1 }, { 0xFFFFFFFFU, 0xFFFFFFFFU, 0x7FFEU, 1 } }, /* Big -number. */ + + /* Infs. */ + { { 0x0U, 0x80000000U, 0x7FFFU, 0 }, { 0x0U, 0x80000000U, 0x7FFFU, 0 } }, /* Inf */ + { { 0x0U, 0x80000000U, 0x7FFFU, 1 }, { 0x0U, 0x80000000U, 0x7FFFU, 1 } }, /* -Inf */ + + /* NaNs. */ + { { 0x1U, 0x80000000U, 0x7FFFU, 0 }, { 0x1U, 0xC0000000U, 0x7FFFU, 0 } }, /* SNaN */ + { { 0x1U, 0x80000000U, 0x7FFFU, 1 }, { 0x1U, 0xC0000000U, 0x7FFFU, 1 } }, /* -SNaN */ + { { 0x0U, 0xFFFFFFFFU, 0x7FFFU, 0 }, { 0x0U, 0xFFFFFFFFU, 0x7FFFU, 0 } }, /* QNaN */ + { { 0x0U, 0xFFFFFFFFU, 0x7FFFU, 1 }, { 0x0U, 0xFFFFFFFFU, 0x7FFFU, 1 } }, /* -QNaN */ + + /* Number. */ + { { 0x2168C000U, 0xC90FDAA2U, 0x4000U, 0 }, { 0x0U, 0xC0000000U, 0x4000U, 0 } }, /* PI */ + { { 0x2168C000U, 0xC90FDAA2U, 0x4000U, 1 }, { 0x0U, 0xC0000000U, 0x4000U, 1 } }, /* -PI */ + + /* Different mantissa patterns. */ + { { 0xFFFFFFFFU, 0xF0000003U, 0x3FFFU + 0x0021U, 0 }, { 0xC0000000U, 0xF0000003U, 0x4020U, 0 } }, + { { 0xFFFFFFFFU, 0xF0000003U, 0x3FFFU + 0x0020U, 0 }, { 0x80000000U, 0xF0000003U, 0x401FU, 0 } }, + { { 0xFFFFFFFFU, 0xF0000003U, 0x3FFFU + 0x001FU, 0 }, { 0x00000000U, 0xF0000003U, 0x401EU, 0 } }, + { { 0xFFFFFFFFU, 0xF0000003U, 0x3FFFU + 0x001EU, 0 }, { 0x00000000U, 0xF0000002U, 0x401DU, 0 } } +}; + +static const size_t n_tests_long_double = sizeof(tests_long_double) / sizeof(tests_long_double[0]); + + + +int main(void) +{ + int i, counter; + + for (counter = i = 0; i < n_tests_long_double; i++) + { + _longdouble_union_t value, result, should_be; + value.ldt = tests_long_double[i][0]; + result.ld = truncl(value.ld); + should_be.ldt = tests_long_double[i][1]; + + if (should_be.ldt.sign == result.ldt.sign && + should_be.ldt.exponent == result.ldt.exponent && + should_be.ldt.mantissah == result.ldt.mantissah && + should_be.ldt.mantissal == result.ldt.mantissal) + { + result.ld = truncl(result.ld); + if (should_be.ldt.sign == result.ldt.sign && + should_be.ldt.exponent == result.ldt.exponent && + should_be.ldt.mantissah == result.ldt.mantissah && + should_be.ldt.mantissal == result.ldt.mantissal) + counter++; + else + printf("Test failed: value to truncate = %.15Lg result = %.15Lg should be = %.15Lg\n", value.ld, result.ld, should_be.ld); + } + else + printf("Test failed: value to truncate = %.15Lg result = %.15Lg should be = %.15Lg\n", value.ld, result.ld, should_be.ld); + } + printf("%s\n", (counter < n_tests_long_double) ? "Test failed." : "Test succeded."); + + return 0; +}