arb/arb/addmul.c
2016-04-26 17:20:05 +02:00

138 lines
3.5 KiB
C

/*
Copyright (C) 2014 Fredrik Johansson
This file is part of Arb.
Arb is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "arb.h"
void
arb_addmul_arf(arb_t z, const arb_t x, const arf_t y, slong prec)
{
mag_t ym;
int inexact;
if (arb_is_exact(x))
{
inexact = arf_addmul(arb_midref(z), arb_midref(x), y, prec, ARB_RND);
if (inexact)
arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec);
}
else if (ARB_IS_LAGOM(x) && ARF_IS_LAGOM(y) && ARB_IS_LAGOM(z))
{
mag_fast_init_set_arf(ym, y);
mag_fast_addmul(arb_radref(z), ym, arb_radref(x));
inexact = arf_addmul(arb_midref(z), arb_midref(x), y, prec, ARB_RND);
if (inexact)
arf_mag_fast_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec);
}
else
{
mag_init_set_arf(ym, y);
mag_addmul(arb_radref(z), ym, arb_radref(x));
inexact = arf_addmul(arb_midref(z), arb_midref(x), y, prec, ARB_RND);
if (inexact)
arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec);
mag_clear(ym);
}
}
void
arb_addmul(arb_t z, const arb_t x, const arb_t y, slong prec)
{
mag_t zr, xm, ym;
int inexact;
if (arb_is_exact(y))
{
arb_addmul_arf(z, x, arb_midref(y), prec);
}
else if (arb_is_exact(x))
{
arb_addmul_arf(z, y, arb_midref(x), prec);
}
else if (ARB_IS_LAGOM(x) && ARB_IS_LAGOM(y) && ARB_IS_LAGOM(z))
{
mag_fast_init_set_arf(xm, arb_midref(x));
mag_fast_init_set_arf(ym, arb_midref(y));
mag_fast_init_set(zr, arb_radref(z));
mag_fast_addmul(zr, xm, arb_radref(y));
mag_fast_addmul(zr, ym, arb_radref(x));
mag_fast_addmul(zr, arb_radref(x), arb_radref(y));
inexact = arf_addmul(arb_midref(z), arb_midref(x), arb_midref(y),
prec, ARF_RND_DOWN);
if (inexact)
arf_mag_fast_add_ulp(zr, zr, arb_midref(z), prec);
*arb_radref(z) = *zr;
}
else
{
mag_init_set_arf(xm, arb_midref(x));
mag_init_set_arf(ym, arb_midref(y));
mag_init_set(zr, arb_radref(z));
mag_addmul(zr, xm, arb_radref(y));
mag_addmul(zr, ym, arb_radref(x));
mag_addmul(zr, arb_radref(x), arb_radref(y));
inexact = arf_addmul(arb_midref(z), arb_midref(x), arb_midref(y),
prec, ARF_RND_DOWN);
if (inexact)
arf_mag_add_ulp(arb_radref(z), zr, arb_midref(z), prec);
else
mag_set(arb_radref(z), zr);
mag_clear(zr);
mag_clear(xm);
mag_clear(ym);
}
}
void
arb_addmul_si(arb_t z, const arb_t x, slong y, slong prec)
{
arf_t t;
arf_init_set_si(t, y); /* no need to free */
arb_addmul_arf(z, x, t, prec);
}
void
arb_addmul_ui(arb_t z, const arb_t x, ulong y, slong prec)
{
arf_t t;
arf_init_set_ui(t, y); /* no need to free */
arb_addmul_arf(z, x, t, prec);
}
void
arb_addmul_fmpz(arb_t z, const arb_t x, const fmpz_t y, slong prec)
{
arf_t t;
if (!COEFF_IS_MPZ(*y))
{
arf_init_set_si(t, *y); /* no need to free */
arb_addmul_arf(z, x, t, prec);
}
else
{
arf_init(t);
arf_set_fmpz(t, y);
arb_addmul_arf(z, x, t, prec);
arf_clear(t);
}
}