1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
Copyright (C) 2012, 2016 Fredrik Johansson
This file is part of FLINT.
FLINT is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version. See <https://www.gnu.org/licenses/>.
*/
#include "arb.h"
int
arb_get_unique_fmpz(fmpz_t z, const arb_t x)
{
if (!arb_is_finite(x))
{
return 0;
}
else if (arb_is_exact(x))
{
/* x = b*2^e, e >= 0 */
if (arf_is_int(arb_midref(x)))
{
/* arf_get_fmpz aborts on overflow */
arf_get_fmpz(z, arb_midref(x), ARF_RND_DOWN);
return 1;
}
else
{
return 0;
}
}
/* if the radius is >= 1, there are at least two integers */
else if (mag_cmp_2exp_si(arb_radref(x), 0) >= 0)
{
return 0;
}
/* there are 0 or 1 integers if the radius is < 1 */
else
{
fmpz_t a, b, exp;
int res;
/* if the midpoint is exactly an integer, it is what we want */
if (arf_is_int(arb_midref(x)))
{
/* arf_get_fmpz aborts on overflow */
arf_get_fmpz(z, arb_midref(x), ARF_RND_DOWN);
return 1;
}
fmpz_init(a);
fmpz_init(b);
fmpz_init(exp);
/* if the radius is tiny, it can't be an integer */
arf_bot(a, arb_midref(x));
if (fmpz_cmp(a, MAG_EXPREF(arb_radref(x))) > 0)
{
res = 0;
}
else
{
arb_get_interval_fmpz_2exp(a, b, exp, x);
if (COEFF_IS_MPZ(*exp))
{
flint_throw(FLINT_ERROR, "arb_get_unique_fmpz: input too large\n");
}
if (*exp >= 0)
{
res = fmpz_equal(a, b);
if (res)
{
fmpz_mul_2exp(a, a, *exp);
fmpz_mul_2exp(b, b, *exp);
}
}
else
{
fmpz_cdiv_q_2exp(a, a, -(*exp));
fmpz_fdiv_q_2exp(b, b, -(*exp));
res = fmpz_equal(a, b);
}
if (res)
fmpz_set(z, a);
}
fmpz_clear(a);
fmpz_clear(b);
fmpz_clear(exp);
return res;
}
}