1/* tinternals -- Test for internals.
2
3Copyright 2005-2023 Free Software Foundation, Inc.
4Contributed by the AriC and Caramba 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
20https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
2151 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23#define MPFR_NEED_LONGLONG_H
24#include "mpfr-test.h"
25
26static void
27test_int_ceil_log2 (void)
28{
29  int i;
30  int val[16] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 };
31
32  for (i = 1; i < 17; i++)
33    {
34      if (MPFR_INT_CEIL_LOG2 (i) != val[i-1])
35        {
36          printf ("Error 1 in test_int_ceil_log2 for i = %d\n", i);
37          exit (1);
38        }
39      if (MPFR_INT_CEIL_LOG2 (i) != __gmpfr_int_ceil_log2 (i))
40        {
41          printf ("Error 2 in test_int_ceil_log2 for i = %d\n", i);
42          exit (1);
43        }
44    }
45}
46
47static void
48test_round_near_x (void)
49{
50  mpfr_t x, y, z, eps;
51  mpfr_exp_t e;
52  int failures = 0, mx, neg, err, dir, r, inex, inex2;
53  char buffer[7], *p;
54
55  mpfr_inits (x, y, z, eps, (mpfr_ptr) 0);
56  mpfr_set_prec (x, 5);
57  mpfr_set_prec (y, 3);
58  mpfr_set_prec (z, 3);
59  mpfr_set_prec (eps, 2);
60  mpfr_set_ui_2exp (eps, 1, -32, MPFR_RNDN);
61
62  for (mx = 16; mx < 32; mx++)
63    {
64      mpfr_set_ui_2exp (x, mx, -2, MPFR_RNDN);
65      for (p = buffer, neg = 0;
66           neg <= 1;
67           mpfr_neg (x, x, MPFR_RNDN), p++, neg++)
68        for (err = 2; err <= 6; err++)
69          for (dir = 0; dir <= 1; dir++)
70            RND_LOOP_NO_RNDF (r)
71              {
72                inex = mpfr_round_near_x (y, x, err, dir, (mpfr_rnd_t) r);
73
74                if (inex == 0 && err < 6)
75                  {
76                    /* The test is more restrictive than necessary.
77                       So, no failure in this case. */
78                    continue;
79                  }
80
81                inex2 = ((dir ^ neg) ? mpfr_add : mpfr_sub)
82                  (z, x, eps, (mpfr_rnd_t) r);
83                if (inex * inex2 <= 0)
84                  printf ("Bad return value (%d instead of %d) for:\n",
85                          inex, inex2);
86                else if (mpfr_equal_p (y, z))
87                  continue;  /* correct inex and y */
88                else
89                  {
90                    printf ("Bad MPFR value (should have got ");
91                    mpfr_out_str (stdout, 2, 3, z, MPFR_RNDZ);
92                    printf (") for:\n");
93                  }
94
95                if (!mpfr_get_str (buffer, &e, 2, 5, x, MPFR_RNDZ) || e != 3)
96                  {
97                    printf ("mpfr_get_str failed in test_round_near_x\n");
98                    exit (1);
99                  }
100                printf ("x = %c%c%c%c.%c%c, ", neg ? '-' : '+',
101                        p[0], p[1], p[2], p[3], p[4]);
102                printf ("err = %d, dir = %d, r = %s --> inex = %2d",
103                        err, dir, mpfr_print_rnd_mode ((mpfr_rnd_t) r), inex);
104                if (inex != 0)
105                  {
106                    printf (", y = ");
107                    mpfr_out_str (stdout, 2, 3, y, MPFR_RNDZ);
108                  }
109                printf ("\n");
110                if (inex == 0)
111                  printf ("Rounding was possible!\n");
112                if (++failures == 10)  /* show at most 10 failures */
113                  exit (1);
114              }
115    }
116
117  if (failures)
118    exit (1);
119
120  mpfr_clears (x, y, z, eps, (mpfr_ptr) 0);
121}
122
123static void
124test_set_prec_raw (void)
125{
126  mpfr_t x;
127  int i;
128
129  mpfr_init2 (x, 53);
130  for (i = 2; i < 11; i++)
131    {
132      mpfr_set_prec_raw (x, i);
133      if (MPFR_PREC (x) != i)
134        {
135          printf ("[ERROR]: mpfr_set_prec_raw %d\n", i);
136          exit (1);
137        }
138    }
139  mpfr_clear (x);
140}
141
142int
143main (int argc, char **argv)
144{
145  tests_start_mpfr ();
146
147  test_int_ceil_log2 ();
148
149  test_round_near_x ();
150  test_set_prec_raw ();
151
152  tests_end_mpfr ();
153  return 0;
154}
155