1 /*
2     Copyright (C) 2014 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 "flint/double_extras.h"
13 #include "mag.h"
14 
15 void
mag_log1p(mag_t z,const mag_t x)16 mag_log1p(mag_t z, const mag_t x)
17 {
18     if (mag_is_special(x))
19     {
20         if (mag_is_zero(x))
21             mag_zero(z);
22         else
23             mag_inf(z);
24     }
25     else
26     {
27         double t;
28         fmpz exp = MAG_EXP(x);
29 
30         if (!COEFF_IS_MPZ(exp))
31         {
32             /* Quick bound by x */
33             if (exp < -10)
34             {
35                 mag_set(z, x);
36             }
37             else if (exp < 1000)
38             {
39                 t = ldexp(MAG_MAN(x), exp - MAG_BITS);
40                 t = (1.0 + t) * (1 + 1e-14);
41                 t = mag_d_log_upper_bound(t);
42                 mag_set_d(z, t);
43             }
44             else
45             {
46                 /* log(2^(exp-1) * (2*v)) = exp*log(2) + log(2*v), 1 <= 2v < 2 */
47                 t = (MAG_MAN(x) + 1) * ldexp(1.0, 1 - MAG_BITS);
48                 t = mag_d_log_upper_bound(t);
49                 t += (exp - 1) * 0.69314718055994530942;
50                 t *= (1 + 1e-13);
51                 mag_set_d(z, t);
52             }
53         }
54         else if (fmpz_sgn(MAG_EXPREF(x)) < 0)
55         {
56             /* Quick bound by x */
57             mag_set(z, x);
58         }
59         else
60         {
61             mag_add_ui(z, x, 1);
62             mag_log(z, z);
63         }
64     }
65 }
66 
67