1/* Test file for mpfr_get_q.
2
3Copyright 2017-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#include "mpfr-test.h"
24
25#ifndef MPFR_USE_MINI_GMP
26
27static void
28special (void)
29{
30  mpfr_t f;
31  mpq_t q;
32
33  mpfr_init2 (f, MPFR_PREC_MIN);
34  mpq_init (q);
35
36  /* check NaN */
37  mpfr_set_nan (f);
38  mpfr_clear_erangeflag ();
39  mpfr_get_q (q, f);
40  MPFR_ASSERTN(mpq_cmp_ui (q, 0, 1) == 0);
41  MPFR_ASSERTN(mpfr_erangeflag_p ());
42
43  /* check +Inf */
44  mpfr_set_inf (f, 1);
45  mpfr_clear_erangeflag ();
46  mpfr_get_q (q, f);
47  MPFR_ASSERTN(mpq_cmp_ui (q, 0, 1) == 0);
48  MPFR_ASSERTN(mpfr_erangeflag_p ());
49
50  /* check -Inf */
51  mpfr_set_inf (f, -1);
52  mpfr_clear_erangeflag ();
53  mpfr_get_q (q, f);
54  MPFR_ASSERTN(mpq_cmp_ui (q, 0, 1) == 0);
55  MPFR_ASSERTN(mpfr_erangeflag_p ());
56
57  /* check +0 */
58  mpfr_set_zero (f, 1);
59  mpfr_clear_erangeflag ();
60  mpfr_get_q (q, f);
61  MPFR_ASSERTN(mpq_cmp_ui (q, 0, 1) == 0);
62  MPFR_ASSERTN(!mpfr_erangeflag_p ());
63
64  /* check -0 */
65  mpfr_set_zero (f, -1);
66  mpfr_clear_erangeflag ();
67  mpfr_get_q (q, f);
68  MPFR_ASSERTN(mpq_cmp_ui (q, 0, 1) == 0);
69  MPFR_ASSERTN(!mpfr_erangeflag_p ());
70
71  mpq_clear (q);
72  mpfr_clear (f);
73}
74
75static void
76random_tests (void)
77{
78  mpfr_t f, g;
79  mpq_t q;
80  int inex;
81  mpfr_rnd_t rnd;
82  int i;
83
84  mpfr_init2 (f, MPFR_PREC_MIN + (randlimb() % 100));
85  mpfr_init2 (g, mpfr_get_prec (f));
86  mpq_init (q);
87
88  for (i = 0; i < 1000; i++)
89    {
90      mpfr_urandomb (f, RANDS);
91      mpfr_get_q (q, f);
92      rnd = RND_RAND ();
93      inex = mpfr_set_q (g, q, rnd);
94      MPFR_ASSERTN(inex == 0);
95      MPFR_ASSERTN(mpfr_cmp (f, g) == 0);
96    }
97
98  mpq_clear (q);
99  mpfr_clear (f);
100  mpfr_clear (g);
101}
102
103/* Check results are in canonical form.
104   See https://sympa.inria.fr/sympa/arc/mpfr/2017-12/msg00029.html */
105static void
106check_canonical (void)
107{
108  mpfr_t x;
109  mpq_t q;
110  mpz_t z;
111
112  mpfr_init2 (x, 53);
113  mpfr_set_ui (x, 3, MPFR_RNDN);
114  mpq_init (q);
115  mpfr_get_q (q, x);
116  /* check the denominator is positive */
117  if (mpz_sgn (mpq_denref (q)) <= 0)
118    {
119      printf ("Error, the denominator of mpfr_get_q should be positive\n");
120      exit (1);
121    }
122  mpz_init (z);
123  mpz_gcd (z, mpq_numref (q), mpq_denref (q));
124  /* check the numerator and denominator are coprime */
125  if (mpz_cmp_ui (z, 1) != 0)
126    {
127      printf ("Error, numerator and denominator of mpfr_get_q should be coprime\n");
128      exit (1);
129    }
130  mpfr_clear (x);
131  mpq_clear (q);
132  mpz_clear (z);
133}
134
135static void
136coverage (void)
137{
138  mpfr_t x;
139  mpq_t q;
140  mpz_t z;
141
142  mpfr_init2 (x, 5);
143  mpq_init (q);
144  mpz_init (z);
145
146  mpfr_set_ui_2exp (x, 17, 100, MPFR_RNDN);
147  mpfr_get_q (q, x);
148  MPFR_ASSERTN(mpz_cmp_ui (mpq_denref (q), 1) == 0);
149  mpz_set_ui (z, 17);
150  mpz_mul_2exp (z, z, 100);
151  MPFR_ASSERTN(mpz_cmp (mpq_numref (q), z) == 0);
152
153  mpfr_clear (x);
154  mpq_clear (q);
155  mpz_clear (z);
156}
157
158int
159main (void)
160{
161  tests_start_mpfr ();
162
163  coverage ();
164  special ();
165  random_tests ();
166
167  check_canonical ();
168
169  tests_end_mpfr ();
170  return 0;
171}
172
173#else
174
175int
176main (void)
177{
178  return 77;
179}
180
181#endif /* MPFR_USE_MINI_GMP */
182