|
Packit Service |
2e9770 |
/* mpc_sqrt -- Take the square root of a complex number.
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
Copyright (C) 2002, 2008, 2009, 2010, 2011, 2012 INRIA
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
This file is part of GNU MPC.
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
GNU MPC is free software; you can redistribute it and/or modify it under
|
|
Packit Service |
2e9770 |
the terms of the GNU Lesser General Public License as published by the
|
|
Packit Service |
2e9770 |
Free Software Foundation; either version 3 of the License, or (at your
|
|
Packit Service |
2e9770 |
option) any later version.
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
Packit Service |
2e9770 |
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
Packit Service |
2e9770 |
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
|
Packit Service |
2e9770 |
more details.
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
You should have received a copy of the GNU Lesser General Public License
|
|
Packit Service |
2e9770 |
along with this program. If not, see http://www.gnu.org/licenses/ .
|
|
Packit Service |
2e9770 |
*/
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
#include "mpc-impl.h"
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
#if MPFR_VERSION_MAJOR < 3
|
|
Packit Service |
2e9770 |
#define mpfr_min_prec(x) \
|
|
Packit Service |
2e9770 |
( ((prec + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB) * BITS_PER_MP_LIMB \
|
|
Packit Service |
2e9770 |
- mpn_scan1 (x->_mpfr_d, 0))
|
|
Packit Service |
2e9770 |
#endif
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
int
|
|
Packit Service |
2e9770 |
mpc_sqrt (mpc_ptr a, mpc_srcptr b, mpc_rnd_t rnd)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
int ok_w, ok_t = 0;
|
|
Packit Service |
2e9770 |
mpfr_t w, t;
|
|
Packit Service |
2e9770 |
mpfr_rnd_t rnd_w, rnd_t;
|
|
Packit Service |
2e9770 |
mpfr_prec_t prec_w, prec_t;
|
|
Packit Service |
2e9770 |
/* the rounding mode and the precision required for w and t, which can */
|
|
Packit Service |
2e9770 |
/* be either the real or the imaginary part of a */
|
|
Packit Service |
2e9770 |
mpfr_prec_t prec;
|
|
Packit Service |
2e9770 |
int inex_w, inex_t = 1, inex_re, inex_im, loops = 0;
|
|
Packit Service |
2e9770 |
const int re_cmp = mpfr_cmp_ui (mpc_realref (b), 0),
|
|
Packit Service |
2e9770 |
im_cmp = mpfr_cmp_ui (mpc_imagref (b), 0);
|
|
Packit Service |
2e9770 |
/* comparison of the real/imaginary part of b with 0 */
|
|
Packit Service |
2e9770 |
int repr_w, repr_t = 0 /* to avoid gcc warning */ ;
|
|
Packit Service |
2e9770 |
/* flag indicating whether the computed value is already representable
|
|
Packit Service |
2e9770 |
at the target precision */
|
|
Packit Service |
2e9770 |
const int im_sgn = mpfr_signbit (mpc_imagref (b)) == 0 ? 0 : -1;
|
|
Packit Service |
2e9770 |
/* we need to know the sign of Im(b) when it is +/-0 */
|
|
Packit Service |
2e9770 |
const mpfr_rnd_t r = im_sgn ? MPFR_RNDD : MPFR_RNDU;
|
|
Packit Service |
2e9770 |
/* rounding mode used when computing t */
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
/* special values */
|
|
Packit Service |
2e9770 |
if (!mpc_fin_p (b)) {
|
|
Packit Service |
2e9770 |
/* sqrt(x +i*Inf) = +Inf +I*Inf, even if x = NaN */
|
|
Packit Service |
2e9770 |
/* sqrt(x -i*Inf) = +Inf -I*Inf, even if x = NaN */
|
|
Packit Service |
2e9770 |
if (mpfr_inf_p (mpc_imagref (b)))
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
mpfr_set_inf (mpc_realref (a), +1);
|
|
Packit Service |
2e9770 |
mpfr_set_inf (mpc_imagref (a), im_sgn);
|
|
Packit Service |
2e9770 |
return MPC_INEX (0, 0);
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
if (mpfr_inf_p (mpc_realref (b)))
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
if (mpfr_signbit (mpc_realref (b)))
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
if (mpfr_number_p (mpc_imagref (b)))
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
/* sqrt(-Inf +i*y) = +0 +i*Inf, when y positive */
|
|
Packit Service |
2e9770 |
/* sqrt(-Inf +i*y) = +0 -i*Inf, when y positive */
|
|
Packit Service |
2e9770 |
mpfr_set_ui (mpc_realref (a), 0, MPFR_RNDN);
|
|
Packit Service |
2e9770 |
mpfr_set_inf (mpc_imagref (a), im_sgn);
|
|
Packit Service |
2e9770 |
return MPC_INEX (0, 0);
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
/* sqrt(-Inf +i*NaN) = NaN +/-i*Inf */
|
|
Packit Service |
2e9770 |
mpfr_set_nan (mpc_realref (a));
|
|
Packit Service |
2e9770 |
mpfr_set_inf (mpc_imagref (a), im_sgn);
|
|
Packit Service |
2e9770 |
return MPC_INEX (0, 0);
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
if (mpfr_number_p (mpc_imagref (b)))
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
/* sqrt(+Inf +i*y) = +Inf +i*0, when y positive */
|
|
Packit Service |
2e9770 |
/* sqrt(+Inf +i*y) = +Inf -i*0, when y positive */
|
|
Packit Service |
2e9770 |
mpfr_set_inf (mpc_realref (a), +1);
|
|
Packit Service |
2e9770 |
mpfr_set_ui (mpc_imagref (a), 0, MPFR_RNDN);
|
|
Packit Service |
2e9770 |
if (im_sgn)
|
|
Packit Service |
2e9770 |
mpc_conj (a, a, MPC_RNDNN);
|
|
Packit Service |
2e9770 |
return MPC_INEX (0, 0);
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
/* sqrt(+Inf -i*Inf) = +Inf -i*Inf */
|
|
Packit Service |
2e9770 |
/* sqrt(+Inf +i*Inf) = +Inf +i*Inf */
|
|
Packit Service |
2e9770 |
/* sqrt(+Inf +i*NaN) = +Inf +i*NaN */
|
|
Packit Service |
2e9770 |
return mpc_set (a, b, rnd);
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
/* sqrt(x +i*NaN) = NaN +i*NaN, if x is not infinite */
|
|
Packit Service |
2e9770 |
/* sqrt(NaN +i*y) = NaN +i*NaN, if y is not infinite */
|
|
Packit Service |
2e9770 |
if (mpfr_nan_p (mpc_realref (b)) || mpfr_nan_p (mpc_imagref (b)))
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
mpfr_set_nan (mpc_realref (a));
|
|
Packit Service |
2e9770 |
mpfr_set_nan (mpc_imagref (a));
|
|
Packit Service |
2e9770 |
return MPC_INEX (0, 0);
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
/* purely real */
|
|
Packit Service |
2e9770 |
if (im_cmp == 0)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
if (re_cmp == 0)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
mpc_set_ui_ui (a, 0, 0, MPC_RNDNN);
|
|
Packit Service |
2e9770 |
if (im_sgn)
|
|
Packit Service |
2e9770 |
mpc_conj (a, a, MPC_RNDNN);
|
|
Packit Service |
2e9770 |
return MPC_INEX (0, 0);
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else if (re_cmp > 0)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
inex_w = mpfr_sqrt (mpc_realref (a), mpc_realref (b), MPC_RND_RE (rnd));
|
|
Packit Service |
2e9770 |
mpfr_set_ui (mpc_imagref (a), 0, MPFR_RNDN);
|
|
Packit Service |
2e9770 |
if (im_sgn)
|
|
Packit Service |
2e9770 |
mpc_conj (a, a, MPC_RNDNN);
|
|
Packit Service |
2e9770 |
return MPC_INEX (inex_w, 0);
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
mpfr_init2 (w, MPC_PREC_RE (b));
|
|
Packit Service |
2e9770 |
mpfr_neg (w, mpc_realref (b), MPFR_RNDN);
|
|
Packit Service |
2e9770 |
if (im_sgn)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
inex_w = -mpfr_sqrt (mpc_imagref (a), w, INV_RND (MPC_RND_IM (rnd)));
|
|
Packit Service |
2e9770 |
mpfr_neg (mpc_imagref (a), mpc_imagref (a), MPFR_RNDN);
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
inex_w = mpfr_sqrt (mpc_imagref (a), w, MPC_RND_IM (rnd));
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
mpfr_set_ui (mpc_realref (a), 0, MPFR_RNDN);
|
|
Packit Service |
2e9770 |
mpfr_clear (w);
|
|
Packit Service |
2e9770 |
return MPC_INEX (0, inex_w);
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
/* purely imaginary */
|
|
Packit Service |
2e9770 |
if (re_cmp == 0)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
mpfr_t y;
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
y[0] = mpc_imagref (b)[0];
|
|
Packit Service |
2e9770 |
/* If y/2 underflows, so does sqrt(y/2) */
|
|
Packit Service |
2e9770 |
mpfr_div_2ui (y, y, 1, MPFR_RNDN);
|
|
Packit Service |
2e9770 |
if (im_cmp > 0)
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
inex_w = mpfr_sqrt (mpc_realref (a), y, MPC_RND_RE (rnd));
|
|
Packit Service |
2e9770 |
inex_t = mpfr_sqrt (mpc_imagref (a), y, MPC_RND_IM (rnd));
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
mpfr_neg (y, y, MPFR_RNDN);
|
|
Packit Service |
2e9770 |
inex_w = mpfr_sqrt (mpc_realref (a), y, MPC_RND_RE (rnd));
|
|
Packit Service |
2e9770 |
inex_t = -mpfr_sqrt (mpc_imagref (a), y, INV_RND (MPC_RND_IM (rnd)));
|
|
Packit Service |
2e9770 |
mpfr_neg (mpc_imagref (a), mpc_imagref (a), MPFR_RNDN);
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
return MPC_INEX (inex_w, inex_t);
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
prec = MPC_MAX_PREC(a);
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
mpfr_init (w);
|
|
Packit Service |
2e9770 |
mpfr_init (t);
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
if (re_cmp > 0) {
|
|
Packit Service |
2e9770 |
rnd_w = MPC_RND_RE (rnd);
|
|
Packit Service |
2e9770 |
prec_w = MPC_PREC_RE (a);
|
|
Packit Service |
2e9770 |
rnd_t = MPC_RND_IM(rnd);
|
|
Packit Service |
2e9770 |
if (rnd_t == MPFR_RNDZ)
|
|
Packit Service |
2e9770 |
/* force MPFR_RNDD or MPFR_RNDUP, using sign(t) = sign(y) */
|
|
Packit Service |
2e9770 |
rnd_t = (im_cmp > 0 ? MPFR_RNDD : MPFR_RNDU);
|
|
Packit Service |
2e9770 |
prec_t = MPC_PREC_IM (a);
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else {
|
|
Packit Service |
2e9770 |
prec_w = MPC_PREC_IM (a);
|
|
Packit Service |
2e9770 |
prec_t = MPC_PREC_RE (a);
|
|
Packit Service |
2e9770 |
if (im_cmp > 0) {
|
|
Packit Service |
2e9770 |
rnd_w = MPC_RND_IM(rnd);
|
|
Packit Service |
2e9770 |
rnd_t = MPC_RND_RE(rnd);
|
|
Packit Service |
2e9770 |
if (rnd_t == MPFR_RNDZ)
|
|
Packit Service |
2e9770 |
rnd_t = MPFR_RNDD;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else {
|
|
Packit Service |
2e9770 |
rnd_w = INV_RND(MPC_RND_IM (rnd));
|
|
Packit Service |
2e9770 |
rnd_t = INV_RND(MPC_RND_RE (rnd));
|
|
Packit Service |
2e9770 |
if (rnd_t == MPFR_RNDZ)
|
|
Packit Service |
2e9770 |
rnd_t = MPFR_RNDU;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
do
|
|
Packit Service |
2e9770 |
{
|
|
Packit Service |
2e9770 |
loops ++;
|
|
Packit Service |
2e9770 |
prec += (loops <= 2) ? mpc_ceil_log2 (prec) + 4 : prec / 2;
|
|
Packit Service |
2e9770 |
mpfr_set_prec (w, prec);
|
|
Packit Service |
2e9770 |
mpfr_set_prec (t, prec);
|
|
Packit Service |
2e9770 |
/* let b = x + iy */
|
|
Packit Service |
2e9770 |
/* w = sqrt ((|x| + sqrt (x^2 + y^2)) / 2), rounded down */
|
|
Packit Service |
2e9770 |
/* total error bounded by 3 ulps */
|
|
Packit Service |
2e9770 |
inex_w = mpc_abs (w, b, MPFR_RNDD);
|
|
Packit Service |
2e9770 |
if (re_cmp < 0)
|
|
Packit Service |
2e9770 |
inex_w |= mpfr_sub (w, w, mpc_realref (b), MPFR_RNDD);
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
inex_w |= mpfr_add (w, w, mpc_realref (b), MPFR_RNDD);
|
|
Packit Service |
2e9770 |
inex_w |= mpfr_div_2ui (w, w, 1, MPFR_RNDD);
|
|
Packit Service |
2e9770 |
inex_w |= mpfr_sqrt (w, w, MPFR_RNDD);
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
repr_w = mpfr_min_prec (w) <= prec_w;
|
|
Packit Service |
2e9770 |
if (!repr_w)
|
|
Packit Service |
2e9770 |
/* use the usual trick for obtaining the ternary value */
|
|
Packit Service |
2e9770 |
ok_w = mpfr_can_round (w, prec - 2, MPFR_RNDD, MPFR_RNDU,
|
|
Packit Service |
2e9770 |
prec_w + (rnd_w == MPFR_RNDN));
|
|
Packit Service |
2e9770 |
else {
|
|
Packit Service |
2e9770 |
/* w is representable in the target precision and thus cannot be
|
|
Packit Service |
2e9770 |
rounded up */
|
|
Packit Service |
2e9770 |
if (rnd_w == MPFR_RNDN)
|
|
Packit Service |
2e9770 |
/* If w can be rounded to nearest, then actually no rounding
|
|
Packit Service |
2e9770 |
occurs, and the ternary value is known from inex_w. */
|
|
Packit Service |
2e9770 |
ok_w = mpfr_can_round (w, prec - 2, MPFR_RNDD, MPFR_RNDN, prec_w);
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
/* If w can be rounded down, then any direct rounding and the
|
|
Packit Service |
2e9770 |
ternary flag can be determined from inex_w. */
|
|
Packit Service |
2e9770 |
ok_w = mpfr_can_round (w, prec - 2, MPFR_RNDD, MPFR_RNDD, prec_w);
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
if (!inex_w || ok_w) {
|
|
Packit Service |
2e9770 |
/* t = y / 2w, rounded away */
|
|
Packit Service |
2e9770 |
/* total error bounded by 7 ulps */
|
|
Packit Service |
2e9770 |
inex_t = mpfr_div (t, mpc_imagref (b), w, r);
|
|
Packit Service |
2e9770 |
if (!inex_t && inex_w)
|
|
Packit Service |
2e9770 |
/* The division was exact, but w was not. */
|
|
Packit Service |
2e9770 |
inex_t = im_sgn ? -1 : 1;
|
|
Packit Service |
2e9770 |
inex_t |= mpfr_div_2ui (t, t, 1, r);
|
|
Packit Service |
2e9770 |
repr_t = mpfr_min_prec (t) <= prec_t;
|
|
Packit Service |
2e9770 |
if (!repr_t)
|
|
Packit Service |
2e9770 |
/* As for w; since t was rounded away, we check whether rounding to 0
|
|
Packit Service |
2e9770 |
is possible. */
|
|
Packit Service |
2e9770 |
ok_t = mpfr_can_round (t, prec - 3, r, MPFR_RNDZ,
|
|
Packit Service |
2e9770 |
prec_t + (rnd_t == MPFR_RNDN));
|
|
Packit Service |
2e9770 |
else {
|
|
Packit Service |
2e9770 |
if (rnd_t == MPFR_RNDN)
|
|
Packit Service |
2e9770 |
ok_t = mpfr_can_round (t, prec - 3, r, MPFR_RNDN, prec_t);
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
ok_t = mpfr_can_round (t, prec - 3, r, r, prec_t);
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
while ((inex_w && !ok_w) || (inex_t && !ok_t));
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
if (re_cmp > 0) {
|
|
Packit Service |
2e9770 |
inex_re = mpfr_set (mpc_realref (a), w, MPC_RND_RE(rnd));
|
|
Packit Service |
2e9770 |
inex_im = mpfr_set (mpc_imagref (a), t, MPC_RND_IM(rnd));
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else if (im_cmp > 0) {
|
|
Packit Service |
2e9770 |
inex_re = mpfr_set (mpc_realref(a), t, MPC_RND_RE(rnd));
|
|
Packit Service |
2e9770 |
inex_im = mpfr_set (mpc_imagref(a), w, MPC_RND_IM(rnd));
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else {
|
|
Packit Service |
2e9770 |
inex_re = mpfr_neg (mpc_realref (a), t, MPC_RND_RE(rnd));
|
|
Packit Service |
2e9770 |
inex_im = mpfr_neg (mpc_imagref (a), w, MPC_RND_IM(rnd));
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
if (repr_w && inex_w) {
|
|
Packit Service |
2e9770 |
if (rnd_w == MPFR_RNDN) {
|
|
Packit Service |
2e9770 |
/* w has not been rounded with mpfr_set/mpfr_neg, determine ternary
|
|
Packit Service |
2e9770 |
value from inex_w instead */
|
|
Packit Service |
2e9770 |
if (re_cmp > 0)
|
|
Packit Service |
2e9770 |
inex_re = inex_w;
|
|
Packit Service |
2e9770 |
else if (im_cmp > 0)
|
|
Packit Service |
2e9770 |
inex_im = inex_w;
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
inex_im = -inex_w;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else {
|
|
Packit Service |
2e9770 |
/* determine ternary value, but also potentially add 1 ulp; can only
|
|
Packit Service |
2e9770 |
be done now when we are in the target precision */
|
|
Packit Service |
2e9770 |
if (re_cmp > 0) {
|
|
Packit Service |
2e9770 |
if (rnd_w == MPFR_RNDU) {
|
|
Packit Service |
2e9770 |
MPFR_ADD_ONE_ULP (mpc_realref (a));
|
|
Packit Service |
2e9770 |
inex_re = +1;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
inex_re = -1;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else if (im_cmp > 0) {
|
|
Packit Service |
2e9770 |
if (rnd_w == MPFR_RNDU) {
|
|
Packit Service |
2e9770 |
MPFR_ADD_ONE_ULP (mpc_imagref (a));
|
|
Packit Service |
2e9770 |
inex_im = +1;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
inex_im = -1;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else {
|
|
Packit Service |
2e9770 |
if (rnd_w == MPFR_RNDU) {
|
|
Packit Service |
2e9770 |
MPFR_ADD_ONE_ULP (mpc_imagref (a));
|
|
Packit Service |
2e9770 |
inex_im = -1;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
inex_im = +1;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
if (repr_t && inex_t) {
|
|
Packit Service |
2e9770 |
if (rnd_t == MPFR_RNDN) {
|
|
Packit Service |
2e9770 |
if (re_cmp > 0)
|
|
Packit Service |
2e9770 |
inex_im = inex_t;
|
|
Packit Service |
2e9770 |
else if (im_cmp > 0)
|
|
Packit Service |
2e9770 |
inex_re = inex_t;
|
|
Packit Service |
2e9770 |
else
|
|
Packit Service |
2e9770 |
inex_re = -inex_t;
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else {
|
|
Packit Service |
2e9770 |
if (re_cmp > 0) {
|
|
Packit Service |
2e9770 |
if (rnd_t == r)
|
|
Packit Service |
2e9770 |
inex_im = inex_t;
|
|
Packit Service |
2e9770 |
else {
|
|
Packit Service |
2e9770 |
inex_im = -inex_t;
|
|
Packit Service |
2e9770 |
/* im_cmp > 0 implies that Im(b) > 0, thus im_sgn = 0
|
|
Packit Service |
2e9770 |
and r = MPFR_RNDU.
|
|
Packit Service |
2e9770 |
im_cmp < 0 implies that Im(b) < 0, thus im_sgn = -1
|
|
Packit Service |
2e9770 |
and r = MPFR_RNDD. */
|
|
Packit Service |
2e9770 |
MPFR_SUB_ONE_ULP (mpc_imagref (a));
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else if (im_cmp > 0) {
|
|
Packit Service |
2e9770 |
if (rnd_t == r)
|
|
Packit Service |
2e9770 |
inex_re = inex_t;
|
|
Packit Service |
2e9770 |
else {
|
|
Packit Service |
2e9770 |
inex_re = -inex_t;
|
|
Packit Service |
2e9770 |
/* im_cmp > 0 implies r = MPFR_RNDU (see above) */
|
|
Packit Service |
2e9770 |
MPFR_SUB_ONE_ULP (mpc_realref (a));
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
else { /* im_cmp < 0 */
|
|
Packit Service |
2e9770 |
if (rnd_t == r)
|
|
Packit Service |
2e9770 |
inex_re = -inex_t;
|
|
Packit Service |
2e9770 |
else {
|
|
Packit Service |
2e9770 |
inex_re = inex_t;
|
|
Packit Service |
2e9770 |
/* im_cmp < 0 implies r = MPFR_RNDD (see above) */
|
|
Packit Service |
2e9770 |
MPFR_SUB_ONE_ULP (mpc_realref (a));
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
}
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
mpfr_clear (w);
|
|
Packit Service |
2e9770 |
mpfr_clear (t);
|
|
Packit Service |
2e9770 |
|
|
Packit Service |
2e9770 |
return MPC_INEX (inex_re, inex_im);
|
|
Packit Service |
2e9770 |
}
|