From: Bruno Haible Date: Tue, 3 Apr 2012 00:57:26 +0000 (+0200) Subject: logb tests: More tests. X-Git-Tag: v0.1~774 X-Git-Url: http://erislabs.org.uk/gitweb/?a=commitdiff_plain;h=36d2768bd34a963cf2b4604e3f54d904ed9f17dd;p=gnulib.git logb tests: More tests. * tests/test-logb.h: New file, based on tests/test-logb.c and tests/test-frexp.h. * tests/test-logb.c: Include minus-zero.h, test-logb.h. (main): Just invoke test_function. * modules/logb-tests (Files): Add tests/test-logb.h, tests/minus-zero.h, tests/randomd.c. (Makefile.am): Add randomd.c to test_logb_SOURCES. --- diff --git a/ChangeLog b/ChangeLog index b4c162d21..5d7218afd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2012-04-02 Bruno Haible + logb tests: More tests. + * tests/test-logb.h: New file, based on tests/test-logb.c and + tests/test-frexp.h. + * tests/test-logb.c: Include minus-zero.h, test-logb.h. + (main): Just invoke test_function. + * modules/logb-tests (Files): Add tests/test-logb.h, + tests/minus-zero.h, tests/randomd.c. + (Makefile.am): Add randomd.c to test_logb_SOURCES. + logb: Provide replacement and workarounds. * lib/math.in.h (logb): Ensure declaration. Replace if REPLACE_LOGB is 1. diff --git a/modules/logb-tests b/modules/logb-tests index f9490702f..8caac668d 100644 --- a/modules/logb-tests +++ b/modules/logb-tests @@ -1,7 +1,10 @@ Files: tests/test-logb.c +tests/test-logb.h +tests/minus-zero.h tests/signature.h tests/macros.h +tests/randomd.c Depends-on: @@ -10,4 +13,5 @@ configure.ac: Makefile.am: TESTS += test-logb check_PROGRAMS += test-logb +test_logb_SOURCES = test-logb.c randomd.c test_logb_LDADD = $(LDADD) @LOGB_LIBM@ diff --git a/tests/test-logb.c b/tests/test-logb.c index 34ad3311b..bef0ec541 100644 --- a/tests/test-logb.c +++ b/tests/test-logb.c @@ -25,38 +25,30 @@ SIGNATURE_CHECK (logb, double, (double)); #include +#include "minus-zero.h" #include "macros.h" -volatile double x; -double y; +#define DOUBLE double +/* The use of 'volatile' guarantees that excess precision bits are dropped + when dealing with denormalized numbers. It is necessary on x86 systems + where double-floats are not IEEE compliant by default, to avoid that the + results become platform and compiler option dependent. 'volatile' is a + portable alternative to gcc's -ffloat-store option. */ +#define VOLATILE volatile +#define HUGEVAL HUGE_VAL +#define L_(literal) literal +#define MINUS_ZERO minus_zerod +#define MAX_EXP DBL_MAX_EXP +#define MIN_EXP DBL_MIN_EXP +#define MIN_NORMAL_EXP DBL_MIN_EXP +#define LOGB logb +#define RANDOM randomd +#include "test-logb.h" int main () { - /* Some particular values. */ - x = 0.6; - y = logb (x); - ASSERT (y == -1.0); - - x = 1.2; - y = logb (x); - ASSERT (y == 0.0); - - x = 2.1; - y = logb (x); - ASSERT (y == 1.0); - - x = 3.9; - y = logb (x); - ASSERT (y == 1.0); - - x = 4.0; - y = logb (x); - ASSERT (y == (FLT_RADIX == 2 ? 2.0 : 1.0)); - - x = 0.25; - y = logb (x); - ASSERT (y == (FLT_RADIX == 2 ? -2.0 : -1.0)); + test_function (); return 0; } diff --git a/tests/test-logb.h b/tests/test-logb.h new file mode 100644 index 000000000..404e7dd6a --- /dev/null +++ b/tests/test-logb.h @@ -0,0 +1,145 @@ +/* Test of logb*() function family. + Copyright (C) 2012 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +static DOUBLE +my_ldexp (DOUBLE x, int d) +{ + for (; d > 0; d--) + x *= L_(2.0); + for (; d < 0; d++) + x *= L_(0.5); + return x; +} + +static void +test_function (void) +{ + int i; + VOLATILE DOUBLE x; + DOUBLE y; + + /* Some particular values. */ + x = L_(0.6); + y = LOGB (x); + ASSERT (y == - L_(1.0)); + + x = L_(1.2); + y = LOGB (x); + ASSERT (y == L_(0.0)); + + x = L_(2.1); + y = LOGB (x); + ASSERT (y == L_(1.0)); + + x = L_(3.9); + y = LOGB (x); + ASSERT (y == L_(1.0)); + + x = L_(4.0); + y = LOGB (x); + ASSERT (y == (FLT_RADIX == 2 ? L_(2.0) : L_(1.0))); + + x = L_(0.25); + y = LOGB (x); + ASSERT (y == (FLT_RADIX == 2 ? - L_(2.0) : - L_(1.0))); + + /* Zero. */ + ASSERT (LOGB (L_(0.0)) == - HUGEVAL); + ASSERT (LOGB (MINUS_ZERO) == - HUGEVAL); + + /* From here on, this test assumes FLT_RADIX == 2. */ + + for (i = 1, x = L_(1.0); i <= MAX_EXP; i++, x *= L_(2.0)) + { + y = LOGB (x); + ASSERT (y == (DOUBLE)(i - 1)); + } + for (i = 1, x = L_(1.0); i >= MIN_NORMAL_EXP; i--, x *= L_(0.5)) + { + y = LOGB (x); + ASSERT (y == (DOUBLE)(i - 1)); + } + for (; i >= MIN_EXP - 100 && x > L_(0.0); i--, x *= L_(0.5)) + { + y = LOGB (x); + ASSERT (y == (DOUBLE)(i - 1)); + } + + for (i = 1, x = - L_(1.0); i <= MAX_EXP; i++, x *= L_(2.0)) + { + y = LOGB (x); + ASSERT (y == (DOUBLE)(i - 1)); + } + for (i = 1, x = - L_(1.0); i >= MIN_NORMAL_EXP; i--, x *= L_(0.5)) + { + y = LOGB (x); + ASSERT (y == (DOUBLE)(i - 1)); + } + for (; i >= MIN_EXP - 100 && x < L_(0.0); i--, x *= L_(0.5)) + { + y = LOGB (x); + ASSERT (y == (DOUBLE)(i - 1)); + } + + for (i = 1, x = L_(1.01); i <= MAX_EXP; i++, x *= L_(2.0)) + { + y = LOGB (x); + ASSERT (y == (DOUBLE)(i - 1)); + } + for (i = 1, x = L_(1.01); i >= MIN_NORMAL_EXP; i--, x *= L_(0.5)) + { + y = LOGB (x); + ASSERT (y == (DOUBLE)(i - 1)); + } + for (; i >= MIN_EXP - 100 && x > L_(0.0); i--, x *= L_(0.5)) + { + y = LOGB (x); + ASSERT (y == (DOUBLE)(i - 1)); + } + + for (i = 1, x = L_(1.73205); i <= MAX_EXP; i++, x *= L_(2.0)) + { + y = LOGB (x); + ASSERT (y == (DOUBLE)(i - 1)); + } + for (i = 1, x = L_(1.73205); i >= MIN_NORMAL_EXP; i--, x *= L_(0.5)) + { + y = LOGB (x); + ASSERT (y == (DOUBLE)(i - 1)); + } + for (; i >= MIN_EXP - 100 && x > L_(0.0); i--, x *= L_(0.5)) + { + y = LOGB (x); + ASSERT (y == (DOUBLE)(i - 1) || y == (DOUBLE)i); + } + + /* Randomized tests. */ + for (i = 0; i < SIZEOF (RANDOM); i++) + { + x = L_(20.0) * RANDOM[i] - L_(10.0); /* -10.0 <= x <= 10.0 */ + if (x != L_(0.0)) + { + DOUBLE abs_x = (x < L_(0.0) ? - x : x); + y = LOGB (x); + ASSERT (y == (DOUBLE) (int) y); + ASSERT (abs_x >= my_ldexp (L_(1.0), (int) y)); + ASSERT (abs_x < my_ldexp (L_(1.0), (int) y + 1)); + } + } +} + +volatile DOUBLE x; +DOUBLE y;