Mail Archives: djgpp-workers/2013/02/24/15:53:03
On linux, if an application uses trunc(), requires to link with math.
library.
So I have moved to code into the math library folders.
Suggestion, objections, comments are welcome.
Regards,
Juan M. Guerrero
2013-02-24 Juan Manuel Guerrero <juan DOT guerrero AT gmx DOT de>
* djgpp/include/math.h: Added trunc[fl] function prototypes.
* djgpp/include/libm/math.h: Added trunc[fl] function prototypes.
* djgpp/src/libm/makefile: Added trunc[fl] functions.
* djgpp/src/libm/math/math.texi: Documentation about trunc[fl]
functions added.
* djgpp/src/libm/trunc.c: Implementation of trunc function.
* djgpp/src/libm/truncf.c: Implementation of truncf function.
* djgpp/src/libm/truncl.c: Implementation of truncl function.
* djgpp/src/docs/kb/wc204.txi: Info about trunc[fl] functions added.
* djgpp/tests/cygnus/makefile: Added checks for trunc[fl] functions.
* djgpp/tests/cygnus/t-trunc.c: Test trunc function.
* djgpp/tests/cygnus/t-truncf.c: Test truncf function.
* djgpp/tests/cygnus/t-truncl.c: Test truncl function.
diff -aprNU5 djgpp.orig/include/libm/math.h djgpp/include/libm/math.h
--- djgpp.orig/include/libm/math.h 2003-03-22 12:09:08 +0000
+++ djgpp/include/libm/math.h 2013-02-24 20:01:06 +0000
@@ -152,10 +152,20 @@ extern double sqrt __P((double));
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));
diff -aprNU5 djgpp.orig/include/math.h djgpp/include/math.h
--- djgpp.orig/include/math.h 2013-02-24 16:45:50 +0000
+++ djgpp/include/math.h 2013-02-24 20:01:06 +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 nextafter(double, double);
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 float copysignf(float, float);
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__ */
diff -aprNU5 djgpp.orig/src/libm/math/makefile djgpp/src/libm/math/makefile
--- djgpp.orig/src/libm/math/makefile 2003-03-22 12:27:26 +0000
+++ djgpp/src/libm/math/makefile 2013-02-24 20:01:06 +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_sin.c
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
diff -aprNU5 djgpp.orig/src/libm/math/math.texi
djgpp/src/libm/math/math.texi
--- djgpp.orig/src/libm/math/math.texi 1998-07-06 13:48:26 +0000
+++ djgpp/src/libm/math/math.texi 2013-02-24 20:01:06 +0000
@@ -66,10 +66,11 @@ available when you include @file{math.h}
* 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 @@ The library is set to X/Open mode by def
@page
@include s_tan.def
@page
@include s_tanh.def
+
+@page
+@include trunc.def
diff -aprNU5 djgpp.orig/src/libm/math/trunc.c djgpp/src/libm/math/trunc.c
--- djgpp.orig/src/libm/math/trunc.c 1970-01-01 00:00:00 +0000
+++ djgpp/src/libm/math/trunc.c 2013-02-24 20:01:06 +0000
@@ -0,0 +1,100 @@
+/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */
+
+/*
+FUNCTION
+<<trunc>>, <<truncf>>, <<truncl>>--round to integer, towards zero
+INDEX
+ trunc
+INDEX
+ truncf
+INDEX
+ truncl
+
+ANSI_SYNOPSIS
+ #include <math.h>
+ double trunc(double <[x]>);
+ float truncf(float <[x]>);
+ long double truncl(long double <[x]>);
+
+DESCRIPTION
+ The <<trunc>> 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 <math.h>
+#include <libc/ieee.h>
+
+#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;
+}
diff -aprNU5 djgpp.orig/src/libm/math/truncf.c djgpp/src/libm/math/truncf.c
--- djgpp.orig/src/libm/math/truncf.c 1970-01-01 00:00:00 +0000
+++ djgpp/src/libm/math/truncf.c 2013-02-24 20:01:06 +0000
@@ -0,0 +1,48 @@
+/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */
+
+#include <math.h>
+#include <libc/ieee.h>
+
+#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;
+}
diff -aprNU5 djgpp.orig/src/libm/math/truncl.c djgpp/src/libm/math/truncl.c
--- djgpp.orig/src/libm/math/truncl.c 1970-01-01 00:00:00 +0000
+++ djgpp/src/libm/math/truncl.c 2013-02-24 20:01:06 +0000
@@ -0,0 +1,69 @@
+/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */
+
+#include <math.h>
+#include <libc/ieee.h>
+
+#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;
+}
diff -aprNU5 djgpp.orig/tests/cygnus/makefile djgpp/tests/cygnus/makefile
--- djgpp.orig/tests/cygnus/makefile 2003-11-09 20:08:40 +0000
+++ djgpp/tests/cygnus/makefile 2013-02-24 20:05:04 +0000
@@ -92,12 +92,15 @@ VEC_OFILES = $(GEN_VEC_FILES:.c=.o)
$(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 @@ tgen/g%vec.exe: tgen/g%vec.cpp tgen/genm
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
diff -aprNU5 djgpp.orig/tests/cygnus/t-trunc.c djgpp/tests/cygnus/t-trunc.c
--- djgpp.orig/tests/cygnus/t-trunc.c 1970-01-01 00:00:00 +0000
+++ djgpp/tests/cygnus/t-trunc.c 2013-02-24 20:05:06 +0000
@@ -0,0 +1,80 @@
+/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */
+
+#include <stdio.h>
+#include <math.h>
+#include <libc/ieee.h>
+
+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;
+}
diff -aprNU5 djgpp.orig/tests/cygnus/t-truncf.c
djgpp/tests/cygnus/t-truncf.c
--- djgpp.orig/tests/cygnus/t-truncf.c 1970-01-01 00:00:00 +0000
+++ djgpp/tests/cygnus/t-truncf.c 2013-02-24 20:05:06 +0000
@@ -0,0 +1,76 @@
+/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */
+
+#include <stdio.h>
+#include <math.h>
+#include <libc/ieee.h>
+
+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;
+}
diff -aprNU5 djgpp.orig/tests/cygnus/t-truncl.c
djgpp/tests/cygnus/t-truncl.c
--- djgpp.orig/tests/cygnus/t-truncl.c 1970-01-01 00:00:00 +0000
+++ djgpp/tests/cygnus/t-truncl.c 2013-02-24 20:05:04 +0000
@@ -0,0 +1,80 @@
+/* Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details */
+
+#include <stdio.h>
+#include <math.h>
+#include <libc/ieee.h>
+
+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;
+}
- Raw text -