1
/* Implementations of operations between mpfr and mpz/mpq data
3
Copyright 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
5
This file is part of the MPFR Library.
7
The MPFR Library is free software; you can redistribute it and/or modify
8
it under the terms of the GNU Lesser General Public License as published by
9
the Free Software Foundation; either version 2.1 of the License, or (at your
10
option) any later version.
12
The MPFR Library is distributed in the hope that it will be useful, but
13
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15
License for more details.
17
You should have received a copy of the GNU Lesser General Public License
18
along with the MPFR Library; see the file COPYING.LIB. If not, write to
19
the Free Software Foundation, Inc., 51 Franklin Place, Fifth Floor, Boston,
20
MA 02110-1301, USA. */
24
#define MPFR_NEED_LONGLONG_H
25
#include "mpfr-impl.h"
27
/* Init and set a mpfr_t with enought precision to store a mpz */
29
init_set_z (mpfr_ptr t, mpz_srcptr z)
34
if (mpz_size (z) <= 1)
37
MPFR_MPZ_SIZEINBASE2 (p, z);
39
i = mpfr_set_z (t, z, GMP_RNDN);
40
MPFR_ASSERTD (i == 0);
43
/* Init, set a mpfr_t with enought precision to store a mpz_t without round,
44
call the function, and clear the allocated mpfr_t */
46
foo (mpfr_ptr x, mpfr_srcptr y, mpz_srcptr z, mp_rnd_t r,
47
int (*f)(mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mp_rnd_t))
52
i = (*f) (x, y, t, r);
58
mpfr_mul_z (mpfr_ptr y, mpfr_srcptr x, mpz_srcptr z, mp_rnd_t r)
60
return foo (y, x, z, r, mpfr_mul);
64
mpfr_div_z (mpfr_ptr y, mpfr_srcptr x, mpz_srcptr z, mp_rnd_t r)
66
return foo (y, x, z, r, mpfr_div);
70
mpfr_add_z (mpfr_ptr y, mpfr_srcptr x, mpz_srcptr z, mp_rnd_t r)
72
/* Mpz 0 is unsigned */
73
if (MPFR_UNLIKELY (mpz_sgn (z) == 0))
74
return mpfr_set (y, x, r);
76
return foo (y, x, z, r, mpfr_add);
80
mpfr_sub_z (mpfr_ptr y, mpfr_srcptr x, mpz_srcptr z, mp_rnd_t r)
82
/* Mpz 0 is unsigned */
83
if (MPFR_UNLIKELY (mpz_sgn (z) == 0))
84
return mpfr_set (y, x, r);
86
return foo (y, x, z, r, mpfr_sub);
90
mpfr_cmp_z (mpfr_srcptr x, mpz_srcptr z)
95
res = mpfr_cmp (x, t);
101
mpfr_mul_q (mpfr_ptr y, mpfr_srcptr x, mpq_srcptr z, mp_rnd_t rnd_mode)
107
if (MPFR_UNLIKELY (mpq_sgn (z) == 0))
108
return mpfr_mul_ui (y, x, 0, rnd_mode);
111
MPFR_MPZ_SIZEINBASE2 (p, mpq_numref (z));
112
mpfr_init2 (tmp, MPFR_PREC (x) + p);
113
res = mpfr_mul_z (tmp, x, mpq_numref(z), GMP_RNDN );
114
MPFR_ASSERTD (res == 0);
115
res = mpfr_div_z (y, tmp, mpq_denref(z), rnd_mode);
122
mpfr_div_q (mpfr_ptr y, mpfr_srcptr x, mpq_srcptr z, mp_rnd_t rnd_mode)
128
if (MPFR_UNLIKELY (mpq_sgn (z) == 0))
129
return mpfr_div_ui (y, x, 0, rnd_mode);
130
else if (MPFR_UNLIKELY (mpz_sgn (mpq_denref (z)) == 0))
133
MPFR_MPZ_SIZEINBASE2 (p, mpq_denref (z));
134
mpfr_init2 (tmp, MPFR_PREC(x) + p);
135
res = mpfr_mul_z (tmp, x, mpq_denref(z), GMP_RNDN );
136
MPFR_ASSERTD( res == 0 );
137
res = mpfr_div_z (y, tmp, mpq_numref(z), rnd_mode);
143
mpfr_add_q (mpfr_ptr y, mpfr_srcptr x, mpq_srcptr z, mp_rnd_t rnd_mode)
149
MPFR_ZIV_DECL (loop);
151
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
158
else if (MPFR_IS_INF (x))
160
MPFR_ASSERTD (mpz_sgn (mpq_denref (z)) != 0);
162
MPFR_SET_SAME_SIGN (y, x);
167
MPFR_ASSERTD (MPFR_IS_ZERO (x));
168
if (MPFR_UNLIKELY (mpq_sgn (z) == 0))
169
return mpfr_set (y, x, rnd_mode); /* signed 0 - Unsigned 0 */
171
return mpfr_set_q (y, z, rnd_mode);
175
p = MPFR_PREC (y) + 10;
179
MPFR_ZIV_INIT (loop, p);
182
res = mpfr_set_q (q, z, GMP_RNDN); /* Error <= 1/2 ulp(q) */
183
/* If z if @INF@ (1/0), res = 0, so it quits immediately */
184
if (MPFR_UNLIKELY (res == 0))
185
/* Result is exact so we can add it directly! */
187
res = mpfr_add (y, x, q, rnd_mode);
190
mpfr_add (t, x, q, GMP_RNDN); /* Error <= 1/2 ulp(t) */
191
/* Error / ulp(t) <= 1/2 + 1/2 * 2^(EXP(q)-EXP(t))
192
If EXP(q)-EXP(t)>0, <= 2^(EXP(q)-EXP(t)-1)*(1+2^-(EXP(q)-EXP(t)))
194
If EXP(q)-EXP(t)<0, <= 2^0 */
195
/* We can get 0, but we can't round since q is inexact */
196
if (MPFR_LIKELY (!MPFR_IS_ZERO (t)))
198
err = (mp_exp_t) p - 1 - MAX (MPFR_GET_EXP(q)-MPFR_GET_EXP(t), 0);
199
if (MPFR_LIKELY (MPFR_CAN_ROUND (t, err, MPFR_PREC (y), rnd_mode)))
201
res = mpfr_set (y, t, rnd_mode);
205
MPFR_ZIV_NEXT (loop, p);
206
mpfr_set_prec (t, p);
207
mpfr_set_prec (q, p);
209
MPFR_ZIV_FREE (loop);
216
mpfr_sub_q (mpfr_ptr y, mpfr_srcptr x, mpq_srcptr z,mp_rnd_t rnd_mode)
222
MPFR_ZIV_DECL (loop);
224
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
231
else if (MPFR_IS_INF (x))
233
MPFR_ASSERTD (mpz_sgn (mpq_denref (z)) != 0);
235
MPFR_SET_SAME_SIGN (y, x);
240
MPFR_ASSERTD (MPFR_IS_ZERO (x));
242
if (MPFR_UNLIKELY (mpq_sgn (z) == 0))
243
return mpfr_set (y, x, rnd_mode); /* signed 0 - Unsigned 0 */
246
res = mpfr_set_q (y, z, MPFR_INVERT_RND (rnd_mode));
247
MPFR_CHANGE_SIGN (y);
253
p = MPFR_PREC (y) + 10;
257
MPFR_ZIV_INIT (loop, p);
260
res = mpfr_set_q(q, z, GMP_RNDN); /* Error <= 1/2 ulp(q) */
261
/* If z if @INF@ (1/0), res = 0, so it quits immediately */
262
if (MPFR_UNLIKELY (res == 0))
263
/* Result is exact so we can add it directly!*/
265
res = mpfr_sub (y, x, q, rnd_mode);
268
mpfr_sub (t, x, q, GMP_RNDN); /* Error <= 1/2 ulp(t) */
269
/* Error / ulp(t) <= 1/2 + 1/2 * 2^(EXP(q)-EXP(t))
270
If EXP(q)-EXP(t)>0, <= 2^(EXP(q)-EXP(t)-1)*(1+2^-(EXP(q)-EXP(t)))
272
If EXP(q)-EXP(t)<0, <= 2^0 */
273
/* We can get 0, but we can't round since q is inexact */
274
if (MPFR_LIKELY (!MPFR_IS_ZERO (t)))
276
err = (mp_exp_t) p - 1 - MAX (MPFR_GET_EXP(q)-MPFR_GET_EXP(t), 0);
277
res = MPFR_CAN_ROUND (t, err, MPFR_PREC (y), rnd_mode);
278
if (MPFR_LIKELY (res != 0)) /* We can round! */
280
res = mpfr_set (y, t, rnd_mode);
284
MPFR_ZIV_NEXT (loop, p);
285
mpfr_set_prec (t, p);
286
mpfr_set_prec (q, p);
288
MPFR_ZIV_FREE (loop);
295
mpfr_cmp_q (mpfr_srcptr x, mpq_srcptr z)
300
/* x < a/b ? <=> x*b < a */
301
MPFR_ASSERTD (mpz_sgn (mpq_denref (z)) != 0);
302
MPFR_MPZ_SIZEINBASE2 (p, mpq_denref (z));
303
mpfr_init2 (t, MPFR_PREC(x) + p);
304
res = mpfr_mul_z (t, x, mpq_denref (z), GMP_RNDN );
305
MPFR_ASSERTD (res == 0);
306
res = mpfr_cmp_z (t, mpq_numref (z) );
312
mpfr_cmp_f (mpfr_srcptr x, mpf_srcptr z)
317
mpfr_init2 (t, MPFR_PREC_MIN + ABS(SIZ(z)) * BITS_PER_MP_LIMB );
318
res = mpfr_set_f (t, z, GMP_RNDN);
319
MPFR_ASSERTD (res == 0);
320
res = mpfr_cmp (x, t);