1/* Test file for mpfr_set_z_2exp.
2
3Copyright 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4Contributed by the Arenaire and Cacao projects, INRIA.
5
6This file is part of the GNU MPFR Library.
7
8The GNU MPFR Library is free software; you can redistribute it and/or modify
9it under the terms of the GNU Lesser General Public License as published by
10the Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13The GNU MPFR Library is distributed in the hope that it will be useful, but
14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16License for more details.
17
18You should have received a copy of the GNU Lesser General Public License
19along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
2151 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <limits.h>
26
27#include "mpfr-test.h"
28
29static mpfr_exp_t
30randexp (void)
31{
32  return (mpfr_exp_t) (randlimb () % (__gmpfr_emax - __gmpfr_emin))
33    + __gmpfr_emin;
34}
35
36static void
37check0 (void)
38{
39  mpz_t y;
40  mpfr_t x;
41  int inexact, r;
42  mpfr_exp_t e;
43
44  /* Check for +0 */
45  mpfr_init (x);
46  mpz_init (y);
47  mpz_set_si (y, 0);
48  for (r = 0; r < MPFR_RND_MAX; r++)
49    {
50      e = randexp ();
51      inexact = mpfr_set_z_2exp (x, y, e, (mpfr_rnd_t) r);
52      if (!MPFR_IS_ZERO(x) || !MPFR_IS_POS(x) || inexact)
53        {
54          printf ("mpfr_set_z_2exp(x,0,e) failed for e=%ld, rnd=%s\n", e,
55                  mpfr_print_rnd_mode ((mpfr_rnd_t) r));
56          exit (1);
57        }
58    }
59  mpfr_clear(x);
60  mpz_clear(y);
61}
62
63/* FIXME: It'd be better to examine the actual data in an mpfr_t to see that
64   it's as expected.  Comparing mpfr_set_z with mpfr_cmp or against
65   mpfr_get_si is a rather indirect test of a low level routine.  */
66
67static void
68check (long i, mpfr_rnd_t rnd)
69{
70  mpfr_t f;
71  mpz_t z;
72  mpfr_exp_t e;
73  int inex;
74
75  /* using CHAR_BIT * sizeof(long) bits of precision ensures that
76     mpfr_set_z_2exp is exact below */
77  mpfr_init2 (f, CHAR_BIT * sizeof(long));
78  mpz_init (z);
79  mpz_set_ui (z, i);
80  /* the following loop ensures that no overflow occurs */
81  do
82    e = randexp ();
83  while (e > mpfr_get_emax () - CHAR_BIT * sizeof(long));
84  inex = mpfr_set_z_2exp (f, z, e, rnd);
85  if (inex != 0)
86    {
87      printf ("Error in mpfr_set_z_2exp for i=%ld, e=%ld,"
88              " wrong ternary value\n", i, (long) e);
89      printf ("expected 0, got %d\n", inex);
90      exit (1);
91    }
92  mpfr_div_2si (f, f, e, rnd);
93  if (mpfr_get_si (f, MPFR_RNDZ) != i)
94    {
95      printf ("Error in mpfr_set_z_2exp for i=%ld e=%ld rnd_mode=%d\n",
96              i, e, rnd);
97      printf ("expected %ld\n", i);
98      mpfr_printf ("got %Re\n", f);
99      exit (1);
100    }
101  mpfr_clear (f);
102  mpz_clear (z);
103}
104
105int
106main (int argc, char *argv[])
107{
108  long j;
109
110  tests_start_mpfr ();
111
112  check (0, MPFR_RNDN);
113  for (j = 0; j < 200000; j++)
114    check (randlimb () & LONG_MAX, RND_RAND ());
115  check0 ();
116
117  tests_end_mpfr ();
118
119  return 0;
120}
121