www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2013/03/05/14:37:27

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 <juan DOT guerrero AT gmx DOT de>
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>
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
+<<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;
+}
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 <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;
+}
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 <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;
+}
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 <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;
+}
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 <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;
+}
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 <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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019