/* compose by poly2 = a*x^n + c, no aliasing; n >= 1 */ void _acb_poly_compose_axnc(acb_ptr res, acb_srcptr poly1, slong len1, const acb_t c, const acb_t a, slong n, slong prec) { slong i; _acb_vec_set_round(res, poly1, len1, prec); /* shift by c (c = 0 case will be fast) */ _acb_poly_taylor_shift(res, c, len1, prec); /* multiply by powers of a */ if (!acb_is_one(a)) { if (acb_equal_si(a, -1)) { for (i = 1; i < len1; i += 2) acb_neg(res + i, res + i); } else if (len1 == 2) { acb_mul(res + 1, res + 1, a, prec); } else { acb_t t; acb_init(t); acb_set(t, a); for (i = 1; i < len1; i++) { acb_mul(res + i, res + i, t, prec); if (i + 1 < len1) acb_mul(t, t, a, prec); } acb_clear(t); } } /* stretch */ for (i = len1 - 1; i >= 1 && n > 1; i--) { acb_swap(res + i * n, res + i); _acb_vec_zero(res + (i - 1) * n + 1, n - 1); } }
void _acb_poly_pow_ui_trunc_binexp(acb_ptr res, acb_srcptr f, long flen, ulong exp, long len, long prec) { acb_ptr v, R, S, T; long rlen; ulong bit; if (exp <= 1) { if (exp == 0) acb_one(res); else if (exp == 1) _acb_vec_set_round(res, f, len, prec); return; } /* (f * x^r)^m = x^(rm) * f^m */ while (flen > 1 && acb_is_zero(f)) { if (((ulong) len) > exp) { _acb_vec_zero(res, exp); len -= exp; res += exp; } else { _acb_vec_zero(res, len); return; } f++; flen--; } if (exp == 2) { _acb_poly_mullow(res, f, flen, f, flen, len, prec); return; } if (flen == 1) { acb_pow_ui(res, f, exp, prec); return; } v = _acb_vec_init(len); bit = 1UL << (FLINT_BIT_COUNT(exp) - 2); if (n_zerobits(exp) % 2) { R = res; S = v; } else { R = v; S = res; } MUL(R, rlen, f, flen, f, flen, len, prec); if (bit & exp) { MUL(S, rlen, R, rlen, f, flen, len, prec); T = R; R = S; S = T; } while (bit >>= 1) { if (bit & exp) { MUL(S, rlen, R, rlen, R, rlen, len, prec); MUL(R, rlen, S, rlen, f, flen, len, prec); } else { MUL(S, rlen, R, rlen, R, rlen, len, prec); T = R; R = S; S = T; } } _acb_vec_clear(v, len); }