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: V01U2FsdGVkX1/2vQMEVfD2Satk9jgAAPMLAwInI8sbSEl45DiuTD m+mN55JCTO6wnA Message-ID: <51364668.8060607@gmx.de> Date: Tue, 05 Mar 2013 20:24:24 +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: Re: Implementation of trunc[fl] family of functions. References: <51296597 DOT 3060304 AT gmx DOT de> In-Reply-To: <51296597.3060304@gmx.de> 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 OFYI, I committed the patch below. Regards, Juan M. Guerrero Index: djgpp/include/math.h =================================================================== RCS file: /cvs/djgpp/djgpp/include/math.h,v retrieving revision 1.17 diff -U 5 -r1.17 math.h --- djgpp/include/math.h 5 Mar 2013 18:04:11 -0000 1.17 +++ djgpp/include/math.h 5 Mar 2013 19:03:17 -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) 1999 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #ifndef __dj_include_math_h_ @@ -159,10 +160,12 @@ extern double remainder(double, double); extern double copysign(double, double); extern int ilogb(double); extern double rint(double); extern double scalbn(double, int); +extern double trunc(double); +extern long double truncl(long double); extern float erff(float); extern float erfcf(float); extern float hypotf(float, float); extern float lgammaf(float); extern float acoshf(float); @@ -177,10 +180,11 @@ extern int ilogbf(float); extern float rintf(float); extern float scalbnf(float, int); extern float expm1f(float); extern float log1pf(float); +extern float truncf(float); /* End libm.a. */ #endif /* (__STDC_VERSION__ >= 199901L) || !__STRICT_ANSI__ */ Index: djgpp/include/libm/math.h =================================================================== RCS file: /cvs/djgpp/djgpp/include/libm/math.h,v retrieving revision 1.4 diff -U 5 -r1.4 math.h --- djgpp/include/libm/math.h 22 Mar 2003 12:09:08 -0000 1.4 +++ djgpp/include/libm/math.h 5 Mar 2013 19:03:17 -0000 @@ -152,10 +152,20 @@ extern double ceil __P((double)); extern double fabs __P((double)); extern double floor __P((double)); extern double fmod __P((double, double)); +#if !defined(__STRICT_ANSI__) || defined(__cplusplus) || \ + defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* ISO C99 types and macros. */ +extern float truncf __P((float)); +extern double trunc __P((double)); +extern long double truncl __P((long double)); +#endif /* !defined (__STRICT_ANSI__) || defined(__cplusplus) + || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L */ + #if !defined(__STRICT_ANSI__) && !defined(_POSIX_SOURCE) extern double erf __P((double)); extern double erfc __P((double)); extern double gamma __P((double)); extern double hypot __P((double, double)); Index: djgpp/src/libm/math/makefile =================================================================== RCS file: /cvs/djgpp/djgpp/src/libm/math/makefile,v retrieving revision 1.3 diff -U 5 -r1.3 makefile --- djgpp/src/libm/math/makefile 22 Mar 2003 12:27:27 -0000 1.3 +++ djgpp/src/libm/math/makefile 5 Mar 2013 19:03:18 -0000 @@ -1,5 +1,6 @@ +# Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details # Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details TOP=.. SRC += k_standard.c SRC += k_rem_pio2.c @@ -161,21 +162,24 @@ SRC += sf_tan.c SRC += sf_tanh.c SRC += sf_infinity.c SRC += sf_isinf.c SRC += sf_nan.c +SRC += trunc +SRC += truncf +SRC += truncl chobj = w_acos.def w_acosh.def w_asin.def s_asinh.def \ s_atan.def w_atan2.def w_atanh.def w_j0.def \ s_copysign.def w_cosh.def s_erf.def w_exp.def \ s_fabs.def s_floor.def w_fmod.def s_frexp.def \ w_gamma.def w_hypot.def s_ldexp.def w_log.def \ w_log10.def s_log1p.def s_matherr.def s_modf.def \ w_pow.def w_remainder.def s_sin.def w_sinh.def \ s_cbrt.def w_sqrt.def s_tan.def s_tanh.def \ s_infinity.def s_isnan.def s_scalbn.def s_nextafter.def \ - s_nan.def s_ilogb.def s_expm1.def + s_nan.def s_ilogb.def s_expm1.def trunc.def CFLAGS = -D_USE_LIBM_MATH_H EXTRA_FILES = $(TOP)/../../info/libm.info # chew emits non-fatal warnings, so we redirect them to the void CHEW = ./chew.exe -f ./doc.str -e /dev/null Index: djgpp/src/libm/math/math.texi =================================================================== RCS file: /cvs/djgpp/djgpp/src/libm/math/math.texi,v retrieving revision 1.1 diff -U 5 -r1.1 math.texi --- djgpp/src/libm/math/math.texi 6 Jul 1998 13:48:26 -0000 1.1 +++ djgpp/src/libm/math/math.texi 5 Mar 2013 19:03:18 -0000 @@ -66,10 +66,11 @@ * sin:: Sine or cosine (sin, cos) * sinh:: Hyperbolic sine * sqrt:: Positive square root * tan:: Tangent * tanh:: Hyperbolic tangent +* trunc:: Round to integer, towards zero @end menu @page @node version @section Version of library @@ -220,5 +221,8 @@ @page @include s_tan.def @page @include s_tanh.def + +@page +@include trunc.def Index: djgpp/src/libm/math/trunc.c =================================================================== RCS file: djgpp/src/libm/math/trunc.c diff -N djgpp/src/libm/math/trunc.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ djgpp/src/libm/math/trunc.c 5 Mar 2013 19:03:18 -0000 @@ -0,0 +1,100 @@ +/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */ + +/* +FUNCTION +<>, <>, <>--round to integer, towards zero +INDEX + trunc +INDEX + truncf +INDEX + truncl + +ANSI_SYNOPSIS + #include + double trunc(double <[x]>); + float truncf(float <[x]>); + long double truncl(long double <[x]>); + +DESCRIPTION + The <> functions round their argument to the integer value, in + floating format, nearest to but no larger in magnitude than the + argument, regardless of the current rounding direction. + +RETURNS +<[x]> truncated to an integral value. +If <[x]> is NaN, a NaN will be returned. +If <[x]> is +/-0 or +/-Inf, <[x]> will be returned. + +PORTABILITY +ANSI C, POSIX + +*/ + +#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) +#define IS_INF_OR_NAN(x) ((x) > MAX_BIN_EXPONENT) +#define MAGNITUDE_IS_LESS_THAN_ONE(x) ((x) < 0) + + +#ifdef __STDC__ +double trunc(double x) +#else +double trunc(x) +double x; +#endif +{ + _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 (MAGNITUDE_IS_LESS_THAN_ONE(unbiased_exponent)) + { + /* 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 (IS_INF_OR_NAN(unbiased_exponent)) + return x + x; /* Trigger an exception. */ + } + 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; +} Index: djgpp/src/libm/math/truncf.c =================================================================== RCS file: djgpp/src/libm/math/truncf.c diff -N djgpp/src/libm/math/truncf.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ djgpp/src/libm/math/truncf.c 5 Mar 2013 19:03:18 -0000 @@ -0,0 +1,48 @@ +/* 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. */ +#define IS_INF_OR_NAN(x) ((x) > MAX_BIN_EXPONENT) +#define MAGNITUDE_IS_LESS_THAN_ONE(x) ((x) < 0) + + +#ifdef __STDC__ +float truncf(float x) +#else +float truncf(x) +float x; +#endif +{ + _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 (MAGNITUDE_IS_LESS_THAN_ONE(unbiased_exponent)) + { + /* The magnitude of the number is < 1 so the result is +-0. */ + int sign = ieee_value.ft.sign; + ieee_value.f = 0; + ieee_value.ft.sign = sign; + } + else + ieee_value.ft.mantissa &= ~(0x7FFFFFU >> unbiased_exponent); + + return ieee_value.f; + } + else if (IS_INF_OR_NAN(unbiased_exponent)) + return x + x; /* Trigger an exception. */ + + + /* All bits in the fraction field are relevant. */ + return x; +} Index: djgpp/src/libm/math/truncl.c =================================================================== RCS file: djgpp/src/libm/math/truncl.c diff -N djgpp/src/libm/math/truncl.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ djgpp/src/libm/math/truncl.c 5 Mar 2013 19:03:18 -0000 @@ -0,0 +1,69 @@ +/* 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) +#define IS_INF_OR_NAN(x) ((x) > MAX_BIN_EXPONENT) +#define MAGNITUDE_IS_LESS_THAN_ONE(x) ((x) < 0) + + +#ifdef __STDC__ +long double truncl(long double x) +#else +long double truncl(x) +long double x; +#endif +{ + _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 (MAGNITUDE_IS_LESS_THAN_ONE(unbiased_exponent)) + { + /* 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 (IS_INF_OR_NAN(unbiased_exponent)) + return x + x; /* Trigger an exception. */ + } + 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; +} Index: djgpp/tests/cygnus/makefile =================================================================== RCS file: /cvs/djgpp/djgpp/tests/cygnus/makefile,v retrieving revision 1.6 diff -U 5 -r1.6 makefile --- djgpp/tests/cygnus/makefile 9 Nov 2003 20:08:40 -0000 1.6 +++ djgpp/tests/cygnus/makefile 5 Mar 2013 19:03:18 -0000 @@ -92,12 +92,15 @@ $(OFILES): CFLAGS = $(DEFS) -fno-builtin -O2 -g -Wall all: check -check: mtest.exe +check: mtest.exe t-trunc.exe t-truncf.exe t-truncl.exe ./mtest.exe > mtest.results + ./t-trunc.exe + ./t-truncf.exe + ./t-truncl.exe # Pattern rules to generate test vectors. (The funky vec.c=%.c replacement # is meant to create a pattern rule where actually a normal rule will # do, since only pattern rules can tell Make that several targets are # generated all at once. Without this, Make will invoke the vector- @@ -123,13 +126,22 @@ QFLOAT=$(HERE)/tgen/qfloat TEST=$(HERE) MATH=$(TOP)/../lib mtest.exe: $(OFILES) $(VEC_OFILES) $(CC) -o $@ $(LDFLAGS) $(OFILES) $(VEC_OFILES) $(LIBS) +t-trunc.exe: t-trunc.o + $(CC) -o $@ $(LDFLAGS) t-trunc.o $(LIBS) + +t-truncf.exe: t-truncf.o + $(CC) -o $@ $(LDFLAGS) t-truncf.o $(LIBS) + +t-truncl.exe: t-truncl.o + $(CC) -o $@ $(LDFLAGS) t-truncl.o $(LIBS) + $(OFILES) $(VEC_OFILES) : test.h clean mostlyclean: -cd tgen; $(MAKE) $@ - cd $(HERE); $(RM) $(OFILES) $(VEC_OFILES) *~ *.exe mtest.results + cd $(HERE); $(RM) $(OFILES) $(VEC_OFILES) *~ *.exe mtest.results t-trunc*.o .SECONDARY: $(GEN_PROGS) $(GEN_VEC_FILES) .PHONY: all check clean mostlyclean Index: djgpp/tests/cygnus/t-trunc.c =================================================================== RCS file: djgpp/tests/cygnus/t-trunc.c diff -N djgpp/tests/cygnus/t-trunc.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ djgpp/tests/cygnus/t-trunc.c 5 Mar 2013 19:03:18 -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(result.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("trunc test failed: value to truncate = %.12lg result = %.12lg should be = %.12lg\n", value.d, result.d, should_be.d); + } + else + printf("trunc 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) ? "trunc test failed." : "trunc test succeded."); + + return 0; +} Index: djgpp/tests/cygnus/t-truncf.c =================================================================== RCS file: djgpp/tests/cygnus/t-truncf.c diff -N djgpp/tests/cygnus/t-truncf.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ djgpp/tests/cygnus/t-truncf.c 5 Mar 2013 19:03:18 -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("truncf test failed: value to truncate = %.5g result = %.5g should be = %.5g\n", value.f, result.f, should_be.f); + } + else + printf("truncf 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) ? "truncf test failed." : "truncf test succeded."); + + return 0; +} Index: djgpp/tests/cygnus/t-truncl.c =================================================================== RCS file: djgpp/tests/cygnus/t-truncl.c diff -N djgpp/tests/cygnus/t-truncl.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ djgpp/tests/cygnus/t-truncl.c 5 Mar 2013 19:03:18 -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("truncl test failed: value to truncate = %.15Lg result = %.15Lg should be = %.15Lg\n", value.ld, result.ld, should_be.ld); + } + else + printf("truncl 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) ? "truncl test failed." : "truncl test succeded."); + + return 0; +}