1 /*
2     Copyright (C) 2012, 2013 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_poly.h"
13 
14 void
_acb_poly_log_series(acb_ptr res,acb_srcptr f,slong flen,slong n,slong prec)15 _acb_poly_log_series(acb_ptr res, acb_srcptr f, slong flen, slong n, slong prec)
16 {
17     flen = FLINT_MIN(flen, n);
18 
19     if (flen == 1)
20     {
21         acb_log(res, f, prec);
22         _acb_vec_zero(res + 1, n - 1);
23     }
24     else if (n == 2)
25     {
26         acb_div(res + 1, f + 1, f + 0, prec);  /* safe since hlen >= 2 */
27         acb_log(res, f, prec);
28     }
29     else if (_acb_vec_is_zero(f + 1, flen - 2))  /* f = a + bx^d */
30     {
31         slong i, j, d = flen - 1;
32 
33         for (i = 1, j = d; j < n; j += d, i++)
34         {
35             if (i == 1)
36                 acb_div(res + j, f + d, f + 0, prec);
37             else
38                 acb_mul(res + j, res + j - d, res + d, prec);
39             _acb_vec_zero(res + j - d + 1, flen - 2);
40         }
41         _acb_vec_zero(res + j - d + 1, n - (j - d + 1));
42 
43         for (i = 2, j = 2 * d; j < n; j += d, i++)
44             acb_div_si(res + j, res + j, i % 2 ? i : -i, prec);
45 
46         acb_log(res, f, prec); /* done last to allow aliasing */
47     }
48     else
49     {
50         acb_ptr f_diff, f_inv;
51         acb_t a;
52         slong alloc;
53 
54         alloc = n + flen - 1;
55         f_inv = _acb_vec_init(alloc);
56         f_diff = f_inv + n;
57 
58         acb_init(a);
59         acb_log(a, f, prec);
60 
61         _acb_poly_derivative(f_diff, f, flen, prec);
62         _acb_poly_inv_series(f_inv, f, flen, n, prec);
63         _acb_poly_mullow(res, f_inv, n - 1, f_diff, flen - 1, n - 1, prec);
64         _acb_poly_integral(res, res, n, prec);
65         acb_swap(res, a);
66 
67         acb_clear(a);
68         _acb_vec_clear(f_inv, alloc);
69     }
70 }
71 
72 void
acb_poly_log_series(acb_poly_t res,const acb_poly_t f,slong n,slong prec)73 acb_poly_log_series(acb_poly_t res, const acb_poly_t f, slong n, slong prec)
74 {
75     if (n == 0)
76     {
77         acb_poly_zero(res);
78         return;
79     }
80 
81     acb_poly_fit_length(res, n);
82     if (f->length == 0)
83         _acb_vec_indeterminate(res->coeffs, n);
84     else
85         _acb_poly_log_series(res->coeffs, f->coeffs, f->length, n, prec);
86     _acb_poly_set_length(res, n);
87     _acb_poly_normalise(res);
88 }
89 
90