2012-08-05 19:57:08 +02:00
|
|
|
/*=============================================================================
|
|
|
|
|
2012-09-01 23:32:52 +02:00
|
|
|
This file is part of ARB.
|
2012-08-05 19:57:08 +02:00
|
|
|
|
2012-09-01 23:32:52 +02:00
|
|
|
ARB is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
2012-08-05 19:57:08 +02:00
|
|
|
|
2012-09-01 23:32:52 +02:00
|
|
|
ARB is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
2012-08-05 19:57:08 +02:00
|
|
|
|
2012-09-01 23:32:52 +02:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with ARB; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
2012-08-05 19:57:08 +02:00
|
|
|
|
|
|
|
=============================================================================*/
|
|
|
|
/******************************************************************************
|
|
|
|
|
2012-09-01 23:32:52 +02:00
|
|
|
Copyright (C) 2012 Fredrik Johansson
|
2012-08-05 19:57:08 +02:00
|
|
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
#ifndef FMPR_H
|
|
|
|
#define FMPR_H
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <limits.h>
|
2013-05-07 17:41:32 +01:00
|
|
|
#include <gmp.h>
|
2012-08-05 19:57:08 +02:00
|
|
|
#include <mpfr.h>
|
|
|
|
#include "flint.h"
|
|
|
|
#include "fmpz.h"
|
|
|
|
#include "fmpq.h"
|
2013-02-17 17:58:15 +01:00
|
|
|
#include "fmpz_extras.h"
|
2012-08-05 19:57:08 +02:00
|
|
|
|
2013-04-27 21:07:57 +02:00
|
|
|
#include "config.h"
|
|
|
|
#ifdef HAVE_TLS
|
|
|
|
#if HAVE_TLS
|
|
|
|
#define TLS_PREFIX __thread
|
|
|
|
#else
|
|
|
|
#define TLS_PREFIX
|
|
|
|
#endif
|
2013-04-27 21:10:41 +02:00
|
|
|
#else
|
|
|
|
#define TLS_PREFIX
|
2013-04-27 21:07:57 +02:00
|
|
|
#endif
|
|
|
|
|
2012-08-05 19:57:08 +02:00
|
|
|
#define fmpr_rnd_t int
|
|
|
|
#define FMPR_RND_FLOOR 0
|
|
|
|
#define FMPR_RND_CEIL 1
|
|
|
|
#define FMPR_RND_UP 2
|
|
|
|
#define FMPR_RND_DOWN 3
|
|
|
|
#define FMPR_RND_NEAR 4
|
|
|
|
|
2013-05-27 15:24:03 +02:00
|
|
|
static __inline__ int
|
|
|
|
rounds_up(fmpr_rnd_t rnd, int negative)
|
|
|
|
{
|
|
|
|
if (rnd == FMPR_RND_DOWN) return 0;
|
|
|
|
if (rnd == FMPR_RND_UP) return 1;
|
|
|
|
if (rnd == FMPR_RND_FLOOR) return negative;
|
|
|
|
return !negative;
|
|
|
|
}
|
|
|
|
|
2013-02-05 15:10:27 +01:00
|
|
|
static __inline__ mpfr_rnd_t rnd_to_mpfr(fmpr_rnd_t rnd)
|
|
|
|
{
|
|
|
|
if (rnd == FMPR_RND_DOWN) return MPFR_RNDZ;
|
|
|
|
else if (rnd == FMPR_RND_UP) return MPFR_RNDA;
|
|
|
|
else if (rnd == FMPR_RND_FLOOR) return MPFR_RNDD;
|
|
|
|
else if (rnd == FMPR_RND_CEIL) return MPFR_RNDU;
|
|
|
|
else return MPFR_RNDN;
|
|
|
|
}
|
|
|
|
|
2012-08-05 19:57:08 +02:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
fmpz man;
|
|
|
|
fmpz exp;
|
|
|
|
}
|
|
|
|
fmpr_struct;
|
|
|
|
|
|
|
|
typedef fmpr_struct fmpr_t[1];
|
|
|
|
|
|
|
|
#define fmpr_manref(x) (&(x)->man)
|
|
|
|
#define fmpr_expref(x) (&(x)->exp)
|
|
|
|
|
|
|
|
|
|
|
|
static __inline__ void
|
|
|
|
fmpr_init(fmpr_t x)
|
|
|
|
{
|
|
|
|
fmpz_init(fmpr_manref(x));
|
|
|
|
fmpz_init(fmpr_expref(x));
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ void
|
|
|
|
fmpr_clear(fmpr_t x)
|
|
|
|
{
|
|
|
|
fmpz_clear(fmpr_manref(x));
|
|
|
|
fmpz_clear(fmpr_expref(x));
|
|
|
|
}
|
|
|
|
|
2012-09-06 15:50:20 +02:00
|
|
|
|
|
|
|
/* The return value encodes an error bound, or FMPR_RESULT_EXACT if exact */
|
|
|
|
#define FMPR_RESULT_EXACT LONG_MAX
|
|
|
|
|
|
|
|
/* Allow 'infinite' precision for operations where a result can be computed exactly */
|
|
|
|
#define FMPR_PREC_EXACT LONG_MAX
|
|
|
|
|
|
|
|
#define FMPR_PREC_ADD(prec,extra) ((prec) == FMPR_PREC_EXACT ? FMPR_PREC_EXACT : (prec) + (extra))
|
|
|
|
|
2012-08-05 19:57:08 +02:00
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
/* Special values */
|
|
|
|
|
|
|
|
/*
|
|
|
|
Special values (0, +inf, -inf, NaN) are encoded using a zero mantissa.
|
|
|
|
Zero is encoded with a zero exponent.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define FMPR_EXP_POS_INF 1L
|
|
|
|
#define FMPR_EXP_NEG_INF 2L
|
|
|
|
#define FMPR_EXP_NAN 3L
|
|
|
|
|
|
|
|
static __inline__ void fmpr_zero(fmpr_t x) {
|
|
|
|
fmpz_zero(fmpr_manref(x));
|
|
|
|
fmpz_zero(fmpr_expref(x));
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ int fmpr_is_zero(const fmpr_t x) {
|
|
|
|
return fmpz_is_zero(fmpr_manref(x)) && fmpz_is_zero(fmpr_expref(x));
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ int fmpr_is_special(const fmpr_t x) {
|
|
|
|
return fmpz_is_zero(fmpr_manref(x));
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ int fmpr_is_normal(const fmpr_t x) {
|
|
|
|
return !fmpz_is_zero(fmpr_manref(x));
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ int fmpr_is_inf(const fmpr_t x) {
|
|
|
|
return fmpr_is_special(x) && (*fmpr_expref(x) == FMPR_EXP_POS_INF ||
|
|
|
|
*fmpr_expref(x) == FMPR_EXP_NEG_INF);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ int fmpr_is_pos_inf(const fmpr_t x) {
|
|
|
|
return fmpr_is_special(x) && (*fmpr_expref(x) == FMPR_EXP_POS_INF);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ int fmpr_is_neg_inf(const fmpr_t x) {
|
|
|
|
return fmpr_is_special(x) && (*fmpr_expref(x) == FMPR_EXP_NEG_INF);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ int fmpr_is_nan(const fmpr_t x) {
|
|
|
|
return fmpr_is_special(x) && (*fmpr_expref(x) == FMPR_EXP_NAN);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ void fmpr_pos_inf(fmpr_t x) {
|
|
|
|
fmpz_zero(fmpr_manref(x));
|
|
|
|
fmpz_set_si(fmpr_expref(x), FMPR_EXP_POS_INF);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ void fmpr_neg_inf(fmpr_t x) {
|
|
|
|
fmpz_zero(fmpr_manref(x));
|
|
|
|
fmpz_set_si(fmpr_expref(x), FMPR_EXP_NEG_INF);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ void fmpr_nan(fmpr_t x) {
|
|
|
|
fmpz_zero(fmpr_manref(x));
|
|
|
|
fmpz_set_si(fmpr_expref(x), FMPR_EXP_NAN);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-09-02 06:09:40 +02:00
|
|
|
static __inline__ int
|
|
|
|
fmpr_is_one(const fmpr_t x)
|
|
|
|
{
|
|
|
|
return fmpz_is_one(fmpr_manref(x)) && fmpz_is_zero(fmpr_expref(x));
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ void
|
|
|
|
fmpr_one(fmpr_t x)
|
|
|
|
{
|
|
|
|
fmpz_one(fmpr_manref(x));
|
|
|
|
fmpz_zero(fmpr_expref(x));
|
|
|
|
}
|
2012-08-05 19:57:08 +02:00
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
|
2013-01-09 16:35:49 +01:00
|
|
|
long _fmpr_normalise_naive(fmpz_t man, fmpz_t exp, long prec, fmpr_rnd_t rnd);
|
2012-09-01 23:32:52 +02:00
|
|
|
|
|
|
|
static __inline__ void
|
|
|
|
fmpr_set(fmpr_t y, const fmpr_t x)
|
|
|
|
{
|
|
|
|
if (y != x)
|
|
|
|
{
|
|
|
|
fmpz_set(fmpr_manref(y), fmpr_manref(x));
|
|
|
|
fmpz_set(fmpr_expref(y), fmpr_expref(x));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-28 15:13:21 +01:00
|
|
|
static __inline__ void
|
|
|
|
fmpr_swap(fmpr_t x, fmpr_t y)
|
|
|
|
{
|
|
|
|
fmpz_swap(fmpr_manref(x), fmpr_manref(y));
|
|
|
|
fmpz_swap(fmpr_expref(x), fmpr_expref(y));
|
|
|
|
}
|
|
|
|
|
2013-01-09 16:35:49 +01:00
|
|
|
long _fmpr_set_round(fmpz_t rman, fmpz_t rexp,
|
|
|
|
const fmpz_t man, const fmpz_t exp, long prec, fmpr_rnd_t rnd);
|
|
|
|
|
2012-09-01 23:32:52 +02:00
|
|
|
static __inline__ long
|
2013-01-09 16:35:49 +01:00
|
|
|
_fmpr_normalise(fmpz_t man, fmpz_t exp, long prec, fmpr_rnd_t rnd)
|
|
|
|
{
|
|
|
|
if (fmpz_is_zero(man))
|
|
|
|
{
|
|
|
|
fmpz_zero(man);
|
|
|
|
fmpz_zero(exp);
|
2013-01-10 15:38:19 +01:00
|
|
|
return FMPR_RESULT_EXACT;
|
2013-01-09 16:35:49 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return _fmpr_set_round(man, exp, man, exp, prec, rnd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ long
|
|
|
|
fmpr_set_round_naive(fmpr_t y, const fmpr_t x, long prec, fmpr_rnd_t rnd)
|
2012-09-01 23:32:52 +02:00
|
|
|
{
|
|
|
|
fmpr_set(y, x);
|
|
|
|
if (fmpr_is_special(y))
|
|
|
|
return FMPR_RESULT_EXACT;
|
|
|
|
else
|
|
|
|
return _fmpr_normalise(fmpr_manref(y), fmpr_expref(y), prec, rnd);
|
|
|
|
}
|
|
|
|
|
2013-01-09 16:35:49 +01:00
|
|
|
static __inline__ long
|
|
|
|
fmpr_set_round(fmpr_t y, const fmpr_t x, long prec, fmpr_rnd_t rnd)
|
|
|
|
{
|
|
|
|
if (fmpr_is_special(x))
|
|
|
|
{
|
|
|
|
fmpr_set(y, x);
|
2013-01-10 15:38:19 +01:00
|
|
|
return FMPR_RESULT_EXACT;
|
2013-01-09 16:35:49 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return _fmpr_set_round(fmpr_manref(y), fmpr_expref(y),
|
|
|
|
fmpr_manref(x), fmpr_expref(x), prec, rnd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-09 18:02:38 +01:00
|
|
|
static __inline__ long
|
|
|
|
fmpr_set_round_fmpz_2exp(fmpr_t y, const fmpz_t x, const fmpz_t exp, long prec, fmpr_rnd_t rnd)
|
|
|
|
{
|
|
|
|
if (fmpz_is_zero(x))
|
|
|
|
{
|
|
|
|
fmpr_zero(y);
|
2013-01-10 15:38:19 +01:00
|
|
|
return FMPR_RESULT_EXACT;
|
2013-01-09 18:02:38 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return _fmpr_set_round(fmpr_manref(y), fmpr_expref(y), x, exp, prec, rnd);
|
|
|
|
}
|
|
|
|
}
|
2013-01-09 16:35:49 +01:00
|
|
|
|
2013-01-09 18:02:38 +01:00
|
|
|
static __inline__ long
|
|
|
|
fmpr_set_round_fmpz(fmpr_t y, const fmpz_t x, long prec, fmpr_rnd_t rnd)
|
|
|
|
{
|
|
|
|
if (fmpz_is_zero(x))
|
|
|
|
{
|
|
|
|
fmpr_zero(y);
|
2013-01-10 15:38:19 +01:00
|
|
|
return FMPR_RESULT_EXACT;
|
2013-01-09 18:02:38 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
long ret;
|
|
|
|
fmpz_t exp;
|
|
|
|
fmpz_init(exp);
|
|
|
|
ret = _fmpr_set_round(fmpr_manref(y), fmpr_expref(y), x, exp, prec, rnd);
|
|
|
|
fmpz_clear(exp);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
2012-08-05 19:57:08 +02:00
|
|
|
|
2013-05-24 17:26:54 +02:00
|
|
|
long _fmpr_set_round_mpn(long * shift, fmpz_t man, mp_srcptr x, mp_size_t xn, int negative, long prec, fmpr_rnd_t rnd);
|
|
|
|
|
2013-05-27 15:24:03 +02:00
|
|
|
long fmpr_set_round_ui_2exp_fmpz(fmpr_t z,
|
|
|
|
mp_limb_t lo, const fmpz_t exp, int negative,
|
|
|
|
long prec, fmpr_rnd_t rnd);
|
|
|
|
|
|
|
|
long fmpr_set_round_uiui_2exp_fmpz(fmpr_t z,
|
|
|
|
mp_limb_t hi, mp_limb_t lo, const fmpz_t exp, int negative,
|
|
|
|
long prec, fmpr_rnd_t rnd);
|
|
|
|
|
|
|
|
|
2012-08-05 19:57:08 +02:00
|
|
|
static __inline__ int
|
|
|
|
fmpr_equal(const fmpr_t x, const fmpr_t y)
|
|
|
|
{
|
2012-09-03 00:05:16 +02:00
|
|
|
return fmpz_equal(fmpr_expref(x), fmpr_expref(y)) &&
|
|
|
|
fmpz_equal(fmpr_manref(x), fmpr_manref(y));
|
2012-08-05 19:57:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ int
|
|
|
|
fmpr_sgn(const fmpr_t x)
|
|
|
|
{
|
|
|
|
if (fmpr_is_special(x))
|
|
|
|
{
|
|
|
|
if (fmpr_is_zero(x))
|
|
|
|
return 0;
|
|
|
|
if (fmpr_is_pos_inf(x))
|
|
|
|
return 1;
|
|
|
|
if (fmpr_is_neg_inf(x))
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmpz_sgn(fmpr_manref(x));
|
|
|
|
}
|
|
|
|
|
2012-09-03 00:05:16 +02:00
|
|
|
int fmpr_cmp(const fmpr_t x, const fmpr_t y);
|
|
|
|
|
2012-09-14 12:38:43 +02:00
|
|
|
int fmpr_cmpabs(const fmpr_t x, const fmpr_t y);
|
2012-09-01 23:32:52 +02:00
|
|
|
|
2012-08-05 19:57:08 +02:00
|
|
|
void fmpr_randtest(fmpr_t x, flint_rand_t state, long bits, long exp_bits);
|
|
|
|
|
2012-09-04 16:11:16 +02:00
|
|
|
void fmpr_randtest_not_zero(fmpr_t x, flint_rand_t state, long bits, long exp_bits);
|
|
|
|
|
2012-08-05 19:57:08 +02:00
|
|
|
void fmpr_randtest_special(fmpr_t x, flint_rand_t state, long bits, long exp_bits);
|
|
|
|
|
2013-02-05 15:10:27 +01:00
|
|
|
int fmpr_get_mpfr(mpfr_t x, const fmpr_t y, mpfr_rnd_t rnd);
|
2012-08-05 19:57:08 +02:00
|
|
|
|
2013-02-05 15:10:27 +01:00
|
|
|
void fmpr_set_mpfr(fmpr_t x, const mpfr_t y);
|
2012-09-07 12:46:58 +02:00
|
|
|
|
2013-02-05 15:10:27 +01:00
|
|
|
double fmpr_get_d(const fmpr_t x, fmpr_rnd_t rnd);
|
2012-08-05 19:57:08 +02:00
|
|
|
|
2012-09-01 23:32:52 +02:00
|
|
|
static __inline__ void fmpr_set_ui(fmpr_t x, ulong c)
|
|
|
|
{
|
|
|
|
if (c == 0)
|
|
|
|
{
|
|
|
|
fmpr_zero(x);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int b;
|
|
|
|
count_trailing_zeros(b, c);
|
|
|
|
fmpz_set_ui(fmpr_manref(x), c >> b);
|
|
|
|
fmpz_set_ui(fmpr_expref(x), b);
|
|
|
|
}
|
|
|
|
}
|
2012-08-05 19:57:08 +02:00
|
|
|
|
2012-09-01 23:32:52 +02:00
|
|
|
static __inline__ void fmpr_set_si(fmpr_t x, long c)
|
|
|
|
{
|
|
|
|
if (c == 0)
|
|
|
|
{
|
|
|
|
fmpr_zero(x);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int b;
|
|
|
|
count_trailing_zeros(b, c);
|
|
|
|
fmpz_set_si(fmpr_manref(x), c >> b);
|
|
|
|
fmpz_set_ui(fmpr_expref(x), b);
|
|
|
|
}
|
|
|
|
}
|
2012-08-05 19:57:08 +02:00
|
|
|
|
|
|
|
static __inline__ void
|
2012-09-01 23:32:52 +02:00
|
|
|
fmpr_set_fmpz(fmpr_t x, const fmpz_t c)
|
2012-08-05 19:57:08 +02:00
|
|
|
{
|
2012-09-01 23:32:52 +02:00
|
|
|
if (fmpz_is_zero(c))
|
|
|
|
{
|
|
|
|
fmpr_zero(x);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
long v = fmpz_val2(c);
|
|
|
|
|
|
|
|
fmpz_tdiv_q_2exp(fmpr_manref(x), c, v);
|
|
|
|
fmpz_set_ui(fmpr_expref(x), v);
|
|
|
|
}
|
2012-08-05 19:57:08 +02:00
|
|
|
}
|
|
|
|
|
2012-09-06 13:18:02 +02:00
|
|
|
/* Arithmetic */
|
|
|
|
|
2012-08-05 19:57:08 +02:00
|
|
|
|
2012-09-01 23:32:52 +02:00
|
|
|
long _fmpr_add_eps(fmpr_t z, const fmpr_t x, int sign, long prec, fmpr_rnd_t rnd);
|
|
|
|
|
2013-01-03 15:11:55 +01:00
|
|
|
long fmpr_mul_naive(fmpr_t z, const fmpr_t x, const fmpr_t y, long prec, fmpr_rnd_t rnd);
|
2012-09-01 23:32:52 +02:00
|
|
|
long fmpr_mul(fmpr_t z, const fmpr_t x, const fmpr_t y, long prec, fmpr_rnd_t rnd);
|
2012-09-06 13:18:02 +02:00
|
|
|
long fmpr_mul_ui(fmpr_t z, const fmpr_t x, ulong y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_mul_si(fmpr_t z, const fmpr_t x, long y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_mul_fmpz(fmpr_t z, const fmpr_t x, const fmpz_t y, long prec, fmpr_rnd_t rnd);
|
2012-09-01 23:32:52 +02:00
|
|
|
|
|
|
|
long fmpr_add(fmpr_t z, const fmpr_t x, const fmpr_t y, long prec, fmpr_rnd_t rnd);
|
2012-09-06 13:18:02 +02:00
|
|
|
long fmpr_add_ui(fmpr_t z, const fmpr_t x, ulong y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_add_si(fmpr_t z, const fmpr_t x, long y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_add_fmpz(fmpr_t z, const fmpr_t x, const fmpz_t y, long prec, fmpr_rnd_t rnd);
|
2012-09-01 23:32:52 +02:00
|
|
|
|
2013-05-27 16:21:37 +02:00
|
|
|
long fmpr_add_naive(fmpr_t z, const fmpr_t x, const fmpr_t y, long prec, fmpr_rnd_t rnd);
|
|
|
|
|
2012-09-01 23:32:52 +02:00
|
|
|
long fmpr_sub(fmpr_t z, const fmpr_t x, const fmpr_t y, long prec, fmpr_rnd_t rnd);
|
2012-09-06 13:18:02 +02:00
|
|
|
long fmpr_sub_ui(fmpr_t z, const fmpr_t x, ulong y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_sub_si(fmpr_t z, const fmpr_t x, long y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_sub_fmpz(fmpr_t z, const fmpr_t x, const fmpz_t y, long prec, fmpr_rnd_t rnd);
|
2012-09-01 23:32:52 +02:00
|
|
|
|
2013-03-14 15:13:44 +01:00
|
|
|
long fmpr_sum(fmpr_t s, const fmpr_struct * terms, long len, long prec, fmpr_rnd_t rnd);
|
|
|
|
|
2012-09-01 23:32:52 +02:00
|
|
|
long fmpr_div(fmpr_t z, const fmpr_t x, const fmpr_t y, long prec, fmpr_rnd_t rnd);
|
2012-09-06 13:18:02 +02:00
|
|
|
long fmpr_div_ui(fmpr_t z, const fmpr_t x, ulong y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_ui_div(fmpr_t z, ulong x, const fmpr_t y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_div_si(fmpr_t z, const fmpr_t x, long y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_si_div(fmpr_t z, long x, const fmpr_t y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_div_fmpz(fmpr_t z, const fmpr_t x, const fmpz_t y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_fmpz_div(fmpr_t z, const fmpz_t x, const fmpr_t y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_fmpz_div_fmpz(fmpr_t z, const fmpz_t x, const fmpz_t y, long prec, fmpr_rnd_t rnd);
|
2012-09-01 23:32:52 +02:00
|
|
|
|
2013-06-09 19:53:01 +02:00
|
|
|
void fmpr_divappr_abs_ubound(fmpr_t z, const fmpr_t x, const fmpr_t y, long prec);
|
|
|
|
|
2012-09-01 23:32:52 +02:00
|
|
|
long fmpr_addmul(fmpr_t z, const fmpr_t x, const fmpr_t y, long prec, fmpr_rnd_t rnd);
|
2012-09-06 13:18:02 +02:00
|
|
|
long fmpr_addmul_ui(fmpr_t z, const fmpr_t x, ulong y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_addmul_si(fmpr_t z, const fmpr_t x, long y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_addmul_fmpz(fmpr_t z, const fmpr_t x, const fmpz_t y, long prec, fmpr_rnd_t rnd);
|
2012-09-01 23:32:52 +02:00
|
|
|
|
|
|
|
long fmpr_submul(fmpr_t z, const fmpr_t x, const fmpr_t y, long prec, fmpr_rnd_t rnd);
|
2012-09-06 13:18:02 +02:00
|
|
|
long fmpr_submul_ui(fmpr_t z, const fmpr_t x, ulong y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_submul_si(fmpr_t z, const fmpr_t x, long y, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_submul_fmpz(fmpr_t z, const fmpr_t x, const fmpz_t y, long prec, fmpr_rnd_t rnd);
|
2012-09-01 23:32:52 +02:00
|
|
|
|
|
|
|
long fmpr_sqrt(fmpr_t y, const fmpr_t x, long prec, fmpr_rnd_t rnd);
|
2012-09-06 13:18:02 +02:00
|
|
|
long fmpr_sqrt_ui(fmpr_t z, ulong x, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_sqrt_fmpz(fmpr_t z, const fmpz_t x, long prec, fmpr_rnd_t rnd);
|
2012-09-01 23:32:52 +02:00
|
|
|
|
2013-06-09 16:20:44 +02:00
|
|
|
long fmpr_rsqrt(fmpr_t y, const fmpr_t x, long prec, fmpr_rnd_t rnd);
|
|
|
|
|
2013-02-28 14:32:59 +01:00
|
|
|
long fmpr_root(fmpr_t y, const fmpr_t x, ulong k, long prec, fmpr_rnd_t rnd);
|
|
|
|
|
2012-09-02 06:09:40 +02:00
|
|
|
long fmpr_log(fmpr_t y, const fmpr_t x, long prec, fmpr_rnd_t rnd);
|
2012-09-07 12:19:27 +02:00
|
|
|
long fmpr_log1p(fmpr_t y, const fmpr_t x, long prec, fmpr_rnd_t rnd);
|
|
|
|
|
|
|
|
long fmpr_exp(fmpr_t y, const fmpr_t x, long prec, fmpr_rnd_t rnd);
|
|
|
|
long fmpr_expm1(fmpr_t y, const fmpr_t x, long prec, fmpr_rnd_t rnd);
|
2012-09-01 23:32:52 +02:00
|
|
|
|
2012-08-05 19:57:08 +02:00
|
|
|
static __inline__ void
|
|
|
|
fmpr_neg(fmpr_t y, const fmpr_t x)
|
|
|
|
{
|
|
|
|
if (fmpr_is_special(x))
|
|
|
|
{
|
|
|
|
if (fmpr_is_pos_inf(x))
|
|
|
|
fmpr_neg_inf(y);
|
|
|
|
else if (fmpr_is_neg_inf(x))
|
|
|
|
fmpr_pos_inf(y);
|
|
|
|
else
|
|
|
|
fmpr_set(y, x);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fmpz_neg(fmpr_manref(y), fmpr_manref(x));
|
|
|
|
fmpz_set(fmpr_expref(y), fmpr_expref(x));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-01 23:32:52 +02:00
|
|
|
static __inline__ long
|
2012-08-05 19:57:08 +02:00
|
|
|
fmpr_neg_round(fmpr_t y, const fmpr_t x, long prec, fmpr_rnd_t rnd)
|
|
|
|
{
|
|
|
|
fmpr_neg(y, x);
|
2012-09-01 23:32:52 +02:00
|
|
|
if (fmpr_is_special(y))
|
|
|
|
return FMPR_RESULT_EXACT;
|
|
|
|
else
|
|
|
|
return _fmpr_normalise(fmpr_manref(y), fmpr_expref(y), prec, rnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ void
|
|
|
|
fmpr_abs(fmpr_t y, const fmpr_t x)
|
|
|
|
{
|
|
|
|
if (fmpr_sgn(x) < 0)
|
|
|
|
fmpr_neg(y, x);
|
|
|
|
else
|
|
|
|
fmpr_set(y, x);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert return value to error bound */
|
|
|
|
static __inline__ void
|
|
|
|
fmpr_set_error_result(fmpr_t err, const fmpr_t result, long rret)
|
|
|
|
{
|
|
|
|
if (rret == FMPR_RESULT_EXACT)
|
|
|
|
{
|
|
|
|
fmpr_zero(err);
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
XXX: normally, a special value should not result from inexact arithmetic
|
|
|
|
else if (fmpr_is_special(result))
|
|
|
|
{
|
|
|
|
fmpr_pos_inf(err);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
else
|
|
|
|
{
|
2013-01-09 18:02:38 +01:00
|
|
|
/* TODO: inline this */
|
2012-09-01 23:32:52 +02:00
|
|
|
fmpz_sub_ui(fmpr_expref(err), fmpr_expref(result), rret);
|
|
|
|
fmpz_one(fmpr_manref(err));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ void
|
|
|
|
fmpr_add_error_result(fmpr_t err, const fmpr_t err_in,
|
|
|
|
const fmpr_t result, long rret, long prec, fmpr_rnd_t rnd)
|
|
|
|
{
|
|
|
|
if (rret == FMPR_RESULT_EXACT)
|
|
|
|
{
|
|
|
|
fmpr_set(err, err_in);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fmpr_t t;
|
|
|
|
fmpr_init(t);
|
|
|
|
fmpr_set_error_result(t, result, rret);
|
|
|
|
fmpr_add(err, err_in, t, prec, rnd);
|
|
|
|
fmpr_clear(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-06 13:18:02 +02:00
|
|
|
void fmpr_print(const fmpr_t x);
|
|
|
|
|
|
|
|
void fmpr_printd(const fmpr_t x, long digits);
|
2012-09-01 23:32:52 +02:00
|
|
|
|
2012-08-05 19:57:08 +02:00
|
|
|
|
2012-09-03 16:26:41 +02:00
|
|
|
static __inline__ void
|
|
|
|
fmpr_mul_2exp_si(fmpr_t y, const fmpr_t x, long e)
|
|
|
|
{
|
|
|
|
if (e == 0 || fmpr_is_special(x))
|
|
|
|
{
|
|
|
|
fmpr_set(y, x);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fmpz_set(fmpr_manref(y), fmpr_manref(x));
|
2013-02-17 20:31:33 +01:00
|
|
|
fmpz_add_si_inline(fmpr_expref(y), fmpr_expref(x), e);
|
2012-09-03 16:26:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-04 13:43:10 +02:00
|
|
|
static __inline__ void
|
|
|
|
fmpr_mul_2exp_fmpz(fmpr_t y, const fmpr_t x, const fmpz_t e)
|
|
|
|
{
|
|
|
|
if (e == 0 || fmpr_is_special(x))
|
|
|
|
{
|
|
|
|
fmpr_set(y, x);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fmpz_set(fmpr_manref(y), fmpr_manref(x));
|
|
|
|
fmpz_add(fmpr_expref(y), fmpr_expref(x), e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-04 16:11:16 +02:00
|
|
|
void fmpr_get_fmpq(fmpq_t y, const fmpr_t x);
|
|
|
|
|
|
|
|
long fmpr_set_fmpq(fmpr_t x, const fmpq_t y, long prec, fmpr_rnd_t rnd);
|
2012-09-04 13:43:10 +02:00
|
|
|
|
2013-02-13 11:22:03 +01:00
|
|
|
void fmpr_get_fmpz(fmpz_t z, const fmpr_t x, fmpr_rnd_t rnd);
|
|
|
|
|
|
|
|
long fmpr_get_si(const fmpr_t x, fmpr_rnd_t rnd);
|
|
|
|
|
2012-09-10 16:33:59 +02:00
|
|
|
void fmpr_set_fmpz_2exp(fmpr_t x, const fmpz_t man, const fmpz_t exp);
|
|
|
|
|
|
|
|
void fmpr_get_fmpz_2exp(fmpz_t man, fmpz_t exp, const fmpr_t x);
|
|
|
|
|
2012-09-21 13:53:20 +02:00
|
|
|
int fmpr_get_fmpz_fixed_fmpz(fmpz_t y, const fmpr_t x, const fmpz_t e);
|
|
|
|
|
|
|
|
int fmpr_get_fmpz_fixed_si(fmpz_t y, const fmpr_t x, long e);
|
|
|
|
|
2012-09-20 12:00:13 +02:00
|
|
|
static __inline__ void
|
|
|
|
fmpr_set_si_2exp_si(fmpr_t x, long man, long exp)
|
|
|
|
{
|
|
|
|
fmpr_set_si(x, man);
|
|
|
|
fmpr_mul_2exp_si(x, x, exp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ void
|
|
|
|
fmpr_set_ui_2exp_si(fmpr_t x, ulong man, long exp)
|
|
|
|
{
|
|
|
|
fmpr_set_ui(x, man);
|
|
|
|
fmpr_mul_2exp_si(x, x, exp);
|
|
|
|
}
|
|
|
|
|
2013-02-17 19:29:23 +01:00
|
|
|
int fmpr_cmp_2exp_si(const fmpr_t x, long e);
|
2012-12-18 11:36:54 +01:00
|
|
|
|
2013-02-17 19:29:23 +01:00
|
|
|
int fmpr_cmpabs_2exp_si(const fmpr_t x, long e);
|
2012-12-18 11:36:54 +01:00
|
|
|
|
2013-02-28 14:36:42 +01:00
|
|
|
static __inline__ void
|
|
|
|
fmpr_min(fmpr_t z, const fmpr_t a, const fmpr_t b)
|
|
|
|
{
|
|
|
|
if (fmpr_cmp(a, b) <= 0)
|
|
|
|
fmpr_set(z, a);
|
|
|
|
else
|
|
|
|
fmpr_set(z, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline__ void
|
|
|
|
fmpr_max(fmpr_t z, const fmpr_t a, const fmpr_t b)
|
|
|
|
{
|
|
|
|
if (fmpr_cmp(a, b) > 0)
|
|
|
|
fmpr_set(z, a);
|
|
|
|
else
|
|
|
|
fmpr_set(z, b);
|
|
|
|
}
|
|
|
|
|
2013-03-01 14:16:42 +01:00
|
|
|
static __inline__ long
|
|
|
|
fmpr_bits(const fmpr_t x)
|
|
|
|
{
|
|
|
|
if (fmpr_is_special(x))
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return fmpz_bits(fmpr_manref(x));
|
|
|
|
}
|
|
|
|
|
2012-09-07 12:19:27 +02:00
|
|
|
#define CALL_MPFR_FUNC(r, func, y, x, prec, rnd) \
|
|
|
|
do { \
|
2012-09-20 17:32:42 +02:00
|
|
|
mpfr_t __t, __u; \
|
|
|
|
mpfr_rnd_t __rnd; \
|
2013-02-05 15:10:27 +01:00
|
|
|
__rnd = rnd_to_mpfr(rnd); \
|
2012-09-20 17:32:42 +02:00
|
|
|
mpfr_init2(__t, 2 + fmpz_bits(fmpr_manref(x))); \
|
|
|
|
mpfr_init2(__u, FLINT_MAX(2, prec)); \
|
|
|
|
fmpr_get_mpfr(__t, x, MPFR_RNDD); \
|
|
|
|
func(__u, __t, __rnd); \
|
2012-09-13 13:47:22 +02:00
|
|
|
if (mpfr_overflow_p() || mpfr_underflow_p()) \
|
|
|
|
{ \
|
|
|
|
printf("exception: mpfr overflow\n"); \
|
|
|
|
abort(); \
|
|
|
|
} \
|
2012-09-20 17:32:42 +02:00
|
|
|
fmpr_set_mpfr(y, __u); \
|
2012-09-07 12:19:27 +02:00
|
|
|
r = prec - fmpz_bits(fmpr_manref(y)); \
|
2012-09-20 17:32:42 +02:00
|
|
|
mpfr_clear(__t); \
|
|
|
|
mpfr_clear(__u); \
|
2012-09-07 12:19:27 +02:00
|
|
|
} while (0);
|
|
|
|
|
2013-02-28 14:32:59 +01:00
|
|
|
|
|
|
|
#define CALL_MPFR_FUNC_K(r, func, y, x, k, prec, rnd) \
|
|
|
|
do { \
|
|
|
|
mpfr_t __t, __u; \
|
|
|
|
mpfr_rnd_t __rnd; \
|
|
|
|
__rnd = rnd_to_mpfr(rnd); \
|
|
|
|
mpfr_init2(__t, 2 + fmpz_bits(fmpr_manref(x))); \
|
|
|
|
mpfr_init2(__u, FLINT_MAX(2, prec)); \
|
|
|
|
fmpr_get_mpfr(__t, x, MPFR_RNDD); \
|
|
|
|
func(__u, __t, k, __rnd); \
|
|
|
|
if (mpfr_overflow_p() || mpfr_underflow_p()) \
|
|
|
|
{ \
|
|
|
|
printf("exception: mpfr overflow\n"); \
|
|
|
|
abort(); \
|
|
|
|
} \
|
|
|
|
fmpr_set_mpfr(y, __u); \
|
|
|
|
r = prec - fmpz_bits(fmpr_manref(y)); \
|
|
|
|
mpfr_clear(__t); \
|
|
|
|
mpfr_clear(__u); \
|
|
|
|
} while (0);
|
|
|
|
|
2012-11-16 13:26:56 +01:00
|
|
|
#define CALL_MPFR_FUNC_2X1(r1, r2, func, y1, y2, x, prec, rnd) \
|
|
|
|
do { \
|
|
|
|
mpfr_t __t, __u, __v; \
|
|
|
|
mpfr_rnd_t __rnd; \
|
2013-02-05 15:10:27 +01:00
|
|
|
__rnd = rnd_to_mpfr(rnd); \
|
2012-11-16 13:26:56 +01:00
|
|
|
mpfr_init2(__t, 2 + fmpz_bits(fmpr_manref(x))); \
|
|
|
|
mpfr_init2(__u, FLINT_MAX(2, prec)); \
|
|
|
|
mpfr_init2(__v, FLINT_MAX(2, prec)); \
|
|
|
|
fmpr_get_mpfr(__t, x, MPFR_RNDD); \
|
|
|
|
func(__u, __v, __t, __rnd); \
|
|
|
|
if (mpfr_overflow_p() || mpfr_underflow_p()) \
|
|
|
|
{ \
|
|
|
|
printf("exception: mpfr overflow\n"); \
|
|
|
|
abort(); \
|
|
|
|
} \
|
|
|
|
fmpr_set_mpfr(y1, __u); \
|
|
|
|
r1 = prec - fmpz_bits(fmpr_manref(y1)); \
|
|
|
|
fmpr_set_mpfr(y2, __v); \
|
|
|
|
r2 = prec - fmpz_bits(fmpr_manref(y2)); \
|
|
|
|
mpfr_clear(__t); \
|
|
|
|
mpfr_clear(__u); \
|
|
|
|
mpfr_clear(__v); \
|
|
|
|
} while (0);
|
|
|
|
|
2012-09-16 03:22:13 +02:00
|
|
|
void fmpr_pow_sloppy_fmpz(fmpr_t y, const fmpr_t b, const fmpz_t e,
|
|
|
|
long prec, fmpr_rnd_t rnd);
|
|
|
|
|
|
|
|
void fmpr_pow_sloppy_ui(fmpr_t y, const fmpr_t b, ulong e,
|
|
|
|
long prec, fmpr_rnd_t rnd);
|
|
|
|
|
|
|
|
void fmpr_pow_sloppy_si(fmpr_t y, const fmpr_t b, long e,
|
|
|
|
long prec, fmpr_rnd_t rnd);
|
|
|
|
|
2012-08-05 19:57:08 +02:00
|
|
|
#endif
|
|
|
|
|