1 /*
2     Copyright (C) 2015 Fredrik Johansson
3 
4     This file is part of Arb.
5 
6     Arb is free software: you can redistribute it and/or modify it under
7     the terms of the GNU Lesser General Public License (LGPL) as published
8     by the Free Software Foundation; either version 2.1 of the License, or
9     (at your option) any later version.  See <http://www.gnu.org/licenses/>.
10 */
11 
12 #include "acb.h"
13 
14 slong
acb_rel_error_bits(const acb_t x)15 acb_rel_error_bits(const acb_t x)
16 {
17     int am, ar, bm, br;
18     slong result;
19     const fmpz * radmag;
20     const fmpz * midmag;
21     fmpz_t t;
22 
23     am = !arf_is_zero(arb_midref(acb_realref(x)));
24     ar = !mag_is_zero(arb_radref(acb_realref(x)));
25 
26     bm = !arf_is_zero(arb_midref(acb_imagref(x)));
27     br = !mag_is_zero(arb_radref(acb_imagref(x)));
28 
29     /* no radius -- exact */
30     if (!ar && !br)
31         return -ARF_PREC_EXACT;
32 
33     /* no midpoint -- infinite relative error */
34     if (!am && !bm)
35         return ARF_PREC_EXACT;
36 
37     if (!acb_is_finite(x))
38         return ARF_PREC_EXACT;
39 
40 #define ame ARF_EXPREF(arb_midref(acb_realref(x)))
41 #define are MAG_EXPREF(arb_radref(acb_realref(x)))
42 #define bme ARF_EXPREF(arb_midref(acb_imagref(x)))
43 #define bre MAG_EXPREF(arb_radref(acb_imagref(x)))
44 
45     if (am && bm)
46         midmag = fmpz_cmp(ame, bme) >= 0 ? ame : bme;
47     else if (am)
48         midmag = ame;
49     else
50         midmag = bme;
51 
52     if (ar && br)
53         radmag = fmpz_cmp(are, bre) >= 0 ? are : bre;
54     else if (ar)
55         radmag = are;
56     else
57         radmag = bre;
58 
59     fmpz_init(t);
60     fmpz_add_ui(t, radmag, 1);
61     result = _fmpz_sub_small(t, midmag);
62     fmpz_clear(t);
63 
64     return result;
65 }
66 
acb_rel_one_accuracy_bits(const acb_t z)67 slong acb_rel_one_accuracy_bits(const acb_t z)
68 {
69     if (arf_cmpabs_2exp_si(arb_midref(acb_realref(z)), -1) < 0 &&
70         arf_cmpabs_2exp_si(arb_midref(acb_imagref(z)), -1) < 0)
71     {
72         acb_t t;
73         arf_init(arb_midref(acb_realref(t)));
74         arf_one(arb_midref(acb_realref(t)));
75         arf_init(arb_midref(acb_imagref(t)));
76         *arb_radref(acb_realref(t)) = *arb_radref(acb_realref(z));
77         *arb_radref(acb_imagref(t)) = *arb_radref(acb_imagref(z));
78         return acb_rel_accuracy_bits(t);
79     }
80     else
81     {
82         return acb_rel_accuracy_bits(z);
83     }
84 }
85 
86