#include "gr_special.h"
#include "gr_vec.h"
#include "gr_poly.h"
int
_gr_poly_sin_cos_series_tangent(gr_ptr s, gr_ptr c,
gr_srcptr h, slong hlen, slong len, int times_pi, gr_ctx_t ctx)
{
slong sz = ctx->sizeof_elem;
int status = GR_SUCCESS;
gr_ptr t, u, v, s0, c0;
hlen = FLINT_MIN(hlen, len);
if (hlen == 1)
{
if (times_pi)
status |= gr_sin_cos_pi(s, c, h, ctx);
else
status |= gr_sin_cos(s, c, h, ctx);
status |= _gr_vec_zero(GR_ENTRY(s, 1, sz), len - 1, ctx);
status |= _gr_vec_zero(GR_ENTRY(c, 1, sz), len - 1, ctx);
return status;
}
GR_TMP_INIT_VEC(t, 3 * len + 2, ctx);
u = GR_ENTRY(t, len, sz);
v = GR_ENTRY(u, len, sz);
s0 = GR_ENTRY(v, len, sz);
c0 = GR_ENTRY(s0, 1, sz);
if (times_pi)
status |= gr_sin_cos_pi(s0, c0, h, ctx);
else
status |= gr_sin_cos(s0, c0, h, ctx);
status |= gr_zero(u, ctx);
status |= _gr_vec_mul_scalar_2exp_si(GR_ENTRY(u, 1, sz), GR_ENTRY(h, 1, sz), hlen - 1, -1, ctx);
if (times_pi)
{
status |= gr_pi(t, ctx);
status |= _gr_vec_mul_scalar(GR_ENTRY(u, 1, sz), GR_ENTRY(u, 1, sz), hlen - 1, t, ctx);
}
status |= _gr_poly_tan_series(t, u, hlen, len, ctx);
status |= _gr_poly_mullow(v, t, len, t, len, len, ctx);
status |= gr_add_ui(v, v, 1, ctx);
status |= _gr_poly_inv_series(u, v, len, len, ctx);
status |= _gr_poly_mullow(s, t, len, u, len, len, ctx);
status |= _gr_vec_mul_scalar_2exp_si(s, s, len, 1, ctx);
status |= gr_sub_ui(v, v, 2, ctx);
status |= _gr_vec_neg(v, v, len, ctx);
status |= _gr_poly_mullow(c, v, len, u, len, len, ctx);
if (gr_is_zero(s0, ctx) != T_TRUE)
{
status |= _gr_vec_mul_scalar(t, s, len, c0, ctx);
status |= _gr_vec_mul_scalar(u, c, len, s0, ctx);
status |= _gr_vec_mul_scalar(v, s, len, s0, ctx);
status |= _gr_vec_add(s, t, u, len, ctx);
status |= _gr_vec_mul_scalar(t, c, len, c0, ctx);
status |= _gr_vec_sub(c, t, v, len, ctx);
}
GR_TMP_CLEAR_VEC(t, 3 * len + 2, ctx);
return status;
}
int
gr_poly_sin_cos_series_tangent(gr_poly_t s, gr_poly_t c,
const gr_poly_t h, slong n, int times_pi, gr_ctx_t ctx)
{
int status = GR_SUCCESS;
slong hlen = h->length;
if (n == 0)
{
status |= gr_poly_zero(s, ctx);
status |= gr_poly_zero(c, ctx);
return status;
}
if (hlen == 0)
{
status |= gr_poly_zero(s, ctx);
status |= gr_poly_one(c, ctx);
return status;
}
gr_poly_fit_length(s, n, ctx);
gr_poly_fit_length(c, n, ctx);
status |= _gr_poly_sin_cos_series_tangent(s->coeffs, c->coeffs,
h->coeffs, hlen, n, times_pi, ctx);
_gr_poly_set_length(s, n, ctx);
_gr_poly_normalise(s, ctx);
_gr_poly_set_length(c, n, ctx);
_gr_poly_normalise(c, ctx);
return status;
}