summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--doc/mpfr.texi11
-rw-r--r--src/Makefile.am3
-rw-r--r--src/mpfr-impl.h3
-rw-r--r--src/mpfr.h10
-rw-r--r--src/nbits_ulong.c54
-rw-r--r--src/pow_si.c40
-rw-r--r--src/pow_ui.c22
-rw-r--r--tests/tpow.c3
9 files changed, 118 insertions, 32 deletions
diff --git a/NEWS b/NEWS
index ffe436be6..c645a5212 100644
--- a/NEWS
+++ b/NEWS
@@ -26,9 +26,9 @@ Changes from versions 4.1.* to version 4.2.0:
mpfr_atanu and mpfr_atan2u.
- New functions mpfr_cospi, mpfr_sinpi, mpfr_tanpi, mpfr_acospi, mpfr_asinpi,
mpfr_atanpi and mpfr_atan2pi.
-- New function mpfr_log2p1, mpfr_log10p1, mpfr_exp2m1, mpfr_exp10m1 and
+- New functions mpfr_log2p1, mpfr_log10p1, mpfr_exp2m1, mpfr_exp10m1 and
mpfr_compound.
-- New function mpfr_fmod_ui.
+- New functions mpfr_fmod_ui, mpfr_pow_uj and mpfr_pow_sj.
- Bug fixes.
In particular, for the formatted output functions (mpfr_printf, etc.),
the case where the precision consists only of a period has been fixed
diff --git a/doc/mpfr.texi b/doc/mpfr.texi
index 023afc7a5..87a031c82 100644
--- a/doc/mpfr.texi
+++ b/doc/mpfr.texi
@@ -2242,15 +2242,16 @@ rounded in the direction @var{rnd}.
@deftypefun int mpfr_pow (mpfr_t @var{rop}, mpfr_t @var{op1}, mpfr_t @var{op2}, mpfr_rnd_t @var{rnd})
@deftypefunx int mpfr_pow_ui (mpfr_t @var{rop}, mpfr_t @var{op1}, unsigned long int @var{op2}, mpfr_rnd_t @var{rnd})
@deftypefunx int mpfr_pow_si (mpfr_t @var{rop}, mpfr_t @var{op1}, long int @var{op2}, mpfr_rnd_t @var{rnd})
-@deftypefunx int mpfr_pow_n (mpfr_t @var{rop}, mpfr_t @var{op1}, long int @var{op2}, mpfr_rnd_t @var{rnd})
+@deftypefunx int mpfr_pow_uj (mpfr_t @var{rop}, mpfr_t @var{op1}, uintmax_t @var{op2}, mpfr_rnd_t @var{rnd})
+@deftypefunx int mpfr_pow_sj (mpfr_t @var{rop}, mpfr_t @var{op1}, intmax_t @var{op2}, mpfr_rnd_t @var{rnd})
+@deftypefunx int mpfr_pow_n (mpfr_t @var{rop}, mpfr_t @var{op1}, intmax_t @var{op2}, mpfr_rnd_t @var{rnd})
@deftypefunx int mpfr_pow_z (mpfr_t @var{rop}, mpfr_t @var{op1}, mpz_t @var{op2}, mpfr_rnd_t @var{rnd})
@deftypefunx int mpfr_ui_pow_ui (mpfr_t @var{rop}, unsigned long int @var{op1}, unsigned long int @var{op2}, mpfr_rnd_t @var{rnd})
@deftypefunx int mpfr_ui_pow (mpfr_t @var{rop}, unsigned long int @var{op1}, mpfr_t @var{op2}, mpfr_rnd_t @var{rnd})
Set @var{rop} to @m{@var{op1}^{@var{op2}}, @var{op1} raised to @var{op2}},
rounded in the direction @var{rnd}.
-@c FIXME: mpfr_pown should be an alias of mpfr_pow_sj to follow ISO C2x.
-@c The function @code{mpfr_pow_n} is just an alias for @code{mpfr_pow_si},
-@c %to mimic the IEEE@tie{}754-2019 function @code{pown}.
+(The @code{mpfr_pow_n} function is just an alias for @code{mpfr_pow_sj},
+to follow the C2x function @code{pown}.)
Special values are handled as described in the ISO C99 and IEEE@tie{}754-2008
standards for the @code{pow} function:
@itemize @bullet
@@ -4279,6 +4280,8 @@ use @code{mpfr_get_z_exp}.
@item @code{mpfr_nrandom} in MPFR@tie{}4.0.
+@item @code{mpfr_pow_sj} and @code{mpfr_pow_uj} in MPFR@tie{}4.2.
+
@item @code{mpfr_printf} in MPFR@tie{}2.4.
@item @code{mpfr_rec_sqrt} in MPFR@tie{}2.4.
diff --git a/src/Makefile.am b/src/Makefile.am
index fea49b27a..935f54990 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -38,7 +38,8 @@ div_2ui.c div.c div_ui.c dot.c dump.c eq.c exp10.c exp2.c exp3.c exp.c \
frac.c frexp.c get_d.c get_exp.c get_str.c init.c inp_str.c isinteger.c \
isinf.c isnan.c isnum.c const_log2.c log.c modf.c mul_2exp.c mul_2si.c \
mul_2ui.c mul.c mul_ui.c neg.c next.c out_str.c printf.c vasprintf.c \
-const_pi.c pow.c pow_si.c pow_ui.c print_raw.c print_rnd_mode.c \
+const_pi.c pow.c pow_si.c pow_ui.c pow_sj.c pow_uj.c print_raw.c \
+print_rnd_mode.c \
reldiff.c round_prec.c set.c setmax.c setmin.c set_d.c set_dfl_prec.c \
set_exp.c set_rnd.c set_f.c set_prc_raw.c set_prec.c set_q.c set_si.c \
set_str.c set_str_raw.c set_ui.c set_z.c sqrt.c sqrt_ui.c sub.c sub1.c \
diff --git a/src/mpfr-impl.h b/src/mpfr-impl.h
index 5707eec10..b7e7d1792 100644
--- a/src/mpfr-impl.h
+++ b/src/mpfr-impl.h
@@ -2489,6 +2489,9 @@ __MPFR_DECLSPEC void mpfr_mpz_clear (mpz_ptr);
__MPFR_DECLSPEC int mpfr_odd_p (mpfr_srcptr);
__MPFR_DECLSPEC int mpfr_nbits_ulong (unsigned long);
+#ifdef _MPFR_H_HAVE_INTMAX_T
+__MPFR_DECLSPEC int mpfr_nbits_uj (uintmax_t);
+#endif
#ifdef _MPFR_H_HAVE_VA_LIST
/* Declared only if <stdarg.h> has been included. */
diff --git a/src/mpfr.h b/src/mpfr.h
index 220d6af05..5a4d3cfa1 100644
--- a/src/mpfr.h
+++ b/src/mpfr.h
@@ -563,10 +563,6 @@ __MPFR_DECLSPEC int mpfr_snprintf (char*, size_t, const char*, ...);
__MPFR_DECLSPEC int mpfr_pow (mpfr_ptr, mpfr_srcptr, mpfr_srcptr, mpfr_rnd_t);
__MPFR_DECLSPEC int mpfr_pow_si (mpfr_ptr, mpfr_srcptr, long, mpfr_rnd_t);
-/* FIXME: mpfr_pown should be an alias of mpfr_pow_sj to follow ISO C2x,
- where pown is defined with intmax_t n. */
-/* define mpfr_pown (defined in IEEE 754-2019) as an alias for mpfr_pow_si */
-#define mpfr_pown mpfr_pow_si
__MPFR_DECLSPEC int mpfr_compound (mpfr_ptr, mpfr_srcptr, long, mpfr_rnd_t);
__MPFR_DECLSPEC int mpfr_pow_ui (mpfr_ptr, mpfr_srcptr, unsigned long,
mpfr_rnd_t);
@@ -1119,6 +1115,8 @@ extern "C" {
#define mpfr_set_uj_2exp __gmpfr_set_uj_2exp
#define mpfr_get_sj __gmpfr_mpfr_get_sj
#define mpfr_get_uj __gmpfr_mpfr_get_uj
+#define mpfr_pow_uj __gmpfr_mpfr_pow_uj
+#define mpfr_pow_sj __gmpfr_mpfr_pow_sj
__MPFR_DECLSPEC int mpfr_set_sj (mpfr_ptr, intmax_t, mpfr_rnd_t);
__MPFR_DECLSPEC int mpfr_set_sj_2exp (mpfr_ptr, intmax_t, intmax_t,
mpfr_rnd_t);
@@ -1127,6 +1125,10 @@ __MPFR_DECLSPEC int mpfr_set_uj_2exp (mpfr_ptr, uintmax_t, intmax_t,
mpfr_rnd_t);
__MPFR_DECLSPEC intmax_t mpfr_get_sj (mpfr_srcptr, mpfr_rnd_t);
__MPFR_DECLSPEC uintmax_t mpfr_get_uj (mpfr_srcptr, mpfr_rnd_t);
+__MPFR_DECLSPEC int mpfr_pow_uj (mpfr_ptr, mpfr_srcptr, uintmax_t, mpfr_rnd_t);
+__MPFR_DECLSPEC int mpfr_pow_sj (mpfr_ptr, mpfr_srcptr, intmax_t, mpfr_rnd_t);
+/* define mpfr_pown (defined in IEEE 754-2019) as an alias for mpfr_pow_sj */
+#define mpfr_pown mpfr_pow_sj
#if defined (__cplusplus)
}
diff --git a/src/nbits_ulong.c b/src/nbits_ulong.c
index 13bf11cd3..4f6d35110 100644
--- a/src/nbits_ulong.c
+++ b/src/nbits_ulong.c
@@ -1,4 +1,5 @@
/* mpfr_nbits_ulong -- number of significant bits in an unsigned long
+ mpfr_nbits_uj -- number of significant bits in an uintmax_t
Copyright 2018-2021 Free Software Foundation, Inc.
Contributed by the AriC and Caramba projects, INRIA.
@@ -21,6 +22,7 @@ https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
#define MPFR_NEED_LONGLONG_H /* for count_leading_zeros */
+#define MPFR_NEED_INTMAX_H
#include "mpfr-impl.h"
/* count the number of significant bits of n, i.e.,
@@ -81,3 +83,55 @@ mpfr_nbits_ulong (unsigned long n)
MPFR_ASSERTD (cnt >= 0);
return cnt;
}
+
+#ifdef _MPFR_H_HAVE_INTMAX_T
+/* count the number of significant bits of n, i.e.,
+ nbits(uintmax_t) - count_leading_zeros (n) */
+int
+mpfr_nbits_uj (uintmax_t n)
+{
+ int cnt;
+
+ MPFR_ASSERTD (n > 0);
+
+ cnt = 0;
+
+ while (n >= 0x10000)
+ {
+ n >>= 16;
+ cnt += 16;
+ }
+
+ MPFR_ASSERTD (n <= 0xffff);
+
+ if (n >= 0x100)
+ {
+ n >>= 8;
+ cnt += 8;
+ }
+
+ MPFR_ASSERTD (n <= 0xff);
+
+ if (n >= 0x10)
+ {
+ n >>= 4;
+ cnt += 4;
+ }
+
+ MPFR_ASSERTD (n <= 0xf);
+
+ if (n >= 4)
+ {
+ n >>= 2;
+ cnt += 2;
+ }
+
+ MPFR_ASSERTD (n <= 3);
+
+ /* now n = 1, 2, or 3 */
+ cnt += 1 + (n >= 2);
+
+ MPFR_ASSERTD (cnt >= 0);
+ return cnt;
+}
+#endif
diff --git a/src/pow_si.c b/src/pow_si.c
index c17a19fa1..5bfd74775 100644
--- a/src/pow_si.c
+++ b/src/pow_si.c
@@ -23,21 +23,34 @@ https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
#define MPFR_NEED_LONGLONG_H /* for MPFR_INT_CEIL_LOG2 */
#include "mpfr-impl.h"
-/* The computation of y = pow_si(x,n) is done by
- * y = pow_ui(x,n) if n >= 0
- * y = 1 / pow_ui(x,-n) if n < 0
+/* The computation of y = pow_si/sj(x,n) is done by
+ * y = pow_ui/uj(x,n) if n >= 0
+ * y = 1 / pow_ui/uj(x,-n) if n < 0
*/
+#ifndef POW_S
+#define POW_S mpfr_pow_si
+#define POW_U mpfr_pow_ui
+#define SET_S mpfr_set_si
+#define SET_S_2EXP mpfr_set_si_2exp
+#define NBITS_UTYPE mpfr_nbits_ulong
+#define TYPE long int
+#define UTYPE unsigned long
+#define LONG_TYPE 1
+#endif
+
int
-mpfr_pow_si (mpfr_ptr y, mpfr_srcptr x, long int n, mpfr_rnd_t rnd)
+POW_S (mpfr_ptr y, mpfr_srcptr x, TYPE n, mpfr_rnd_t rnd)
{
+#ifdef LONG_TYPE /* FIXME: what printf format for intmax_t? */
MPFR_LOG_FUNC
(("x[%Pu]=%.*Rg n=%ld rnd=%d",
mpfr_get_prec (x), mpfr_log_prec, x, n, rnd),
("y[%Pu]=%.*Rg", mpfr_get_prec (y), mpfr_log_prec, y));
+#endif
if (n >= 0)
- return mpfr_pow_ui (y, x, n, rnd);
+ return POW_U (y, x, n, rnd);
else
{
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
@@ -49,7 +62,7 @@ mpfr_pow_si (mpfr_ptr y, mpfr_srcptr x, long int n, mpfr_rnd_t rnd)
}
else
{
- int positive = MPFR_IS_POS (x) || ((unsigned long) n & 1) == 0;
+ int positive = MPFR_IS_POS (x) || ((UTYPE) n & 1) == 0;
if (MPFR_IS_INF (x))
MPFR_SET_ZERO (y);
else /* x is zero */
@@ -130,8 +143,7 @@ mpfr_pow_si (mpfr_ptr y, mpfr_srcptr x, long int n, mpfr_rnd_t rnd)
MPFR_EMIN_MIN - 2 /* Underflow */ :
n != -1 && expx < 0 && expx < (__gmpfr_emax - 1) / n ?
MPFR_EMAX_MAX /* Overflow */ : n * expx;
- return mpfr_set_si_2exp (y, n % 2 ? MPFR_INT_SIGN (x) : 1,
- expy, rnd);
+ return SET_S_2EXP (y, n % 2 ? MPFR_INT_SIGN (x) : 1, expy, rnd);
}
/* General case */
@@ -144,12 +156,12 @@ mpfr_pow_si (mpfr_ptr y, mpfr_srcptr x, long int n, mpfr_rnd_t rnd)
mpfr_rnd_t rnd1;
int size_n;
int inexact;
- unsigned long abs_n;
+ UTYPE abs_n;
MPFR_SAVE_EXPO_DECL (expo);
MPFR_ZIV_DECL (loop);
- abs_n = - (unsigned long) n;
- size_n = mpfr_nbits_ulong (abs_n);
+ abs_n = - (UTYPE) n;
+ size_n = NBITS_UTYPE (abs_n);
/* initial working precision */
Ny = MPFR_PREC (y);
@@ -177,7 +189,7 @@ mpfr_pow_si (mpfr_ptr y, mpfr_srcptr x, long int n, mpfr_rnd_t rnd)
/* t = (1/x)*(1+theta) where |theta| <= 2^(-Nt) */
if (MPFR_UNLIKELY (MPFR_OVERFLOW (flags)))
goto overflow;
- MPFR_BLOCK (flags, mpfr_pow_ui (t, t, abs_n, rnd));
+ MPFR_BLOCK (flags, POW_U (t, t, abs_n, rnd));
/* t = (1/x)^|n|*(1+theta')^(|n|+1) where |theta'| <= 2^(-Nt).
If (|n|+1)*2^(-Nt) <= 1/2, which is satisfied as soon as
Nt >= bits(n)+2, then we can use Lemma \ref{lemma_graillat}
@@ -210,8 +222,8 @@ mpfr_pow_si (mpfr_ptr y, mpfr_srcptr x, long int n, mpfr_rnd_t rnd)
MPFR_ASSERTD (mpfr_cmp_si_2exp (x, MPFR_SIGN (x),
MPFR_EXP (x) - 1) != 0);
mpfr_init2 (y2, 2);
- mpfr_init2 (nn, sizeof (long) * CHAR_BIT);
- inexact = mpfr_set_si (nn, n, MPFR_RNDN);
+ mpfr_init2 (nn, sizeof (TYPE) * CHAR_BIT);
+ inexact = SET_S (nn, n, MPFR_RNDN);
MPFR_ASSERTN (inexact == 0);
inexact = mpfr_pow_general (y2, x, nn, rnd, 1,
(mpfr_save_expo_t *) NULL);
diff --git a/src/pow_ui.c b/src/pow_ui.c
index fba1e44ab..20e4de1c7 100644
--- a/src/pow_ui.c
+++ b/src/pow_ui.c
@@ -1,5 +1,4 @@
-/* mpfr_pow_ui-- compute the power of a floating-point
- by a machine integer
+/* mpfr_pow_ui -- compute the power of a floating-point by a machine integer
Copyright 1999-2021 Free Software Foundation, Inc.
Contributed by the AriC and Caramba projects, INRIA.
@@ -24,11 +23,18 @@ https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
#define MPFR_NEED_LONGLONG_H
#include "mpfr-impl.h"
+#ifndef POW_U
+#define POW_U mpfr_pow_ui
+#define MPZ_SET_U mpz_set_ui
+#define UTYPE unsigned long int
+#define LONG_TYPE 1
+#endif
+
/* sets y to x^n, and return 0 if exact, non-zero otherwise */
int
-mpfr_pow_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int n, mpfr_rnd_t rnd)
+POW_U (mpfr_ptr y, mpfr_srcptr x, UTYPE n, mpfr_rnd_t rnd)
{
- unsigned long m;
+ UTYPE m;
mpfr_t res;
mpfr_prec_t prec, err;
int inexact;
@@ -37,11 +43,13 @@ mpfr_pow_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int n, mpfr_rnd_t rnd)
MPFR_ZIV_DECL (loop);
MPFR_BLOCK_DECL (flags);
+#ifdef LONG_TYPE /* FIXME: how to print a uintmax_t? */
MPFR_LOG_FUNC
(("x[%Pu]=%.*Rg n=%lu rnd=%d",
mpfr_get_prec (x), mpfr_log_prec, x, n, rnd),
("y[%Pu]=%.*Rg inexact=%d",
mpfr_get_prec (y), mpfr_log_prec, y, inexact));
+#endif
/* x^0 = 1 for any x, even a NaN */
if (MPFR_UNLIKELY (n == 0))
@@ -110,12 +118,12 @@ mpfr_pow_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int n, mpfr_rnd_t rnd)
MPFR_BLOCK (flags,
inexact = mpfr_sqr (res, x, MPFR_RNDU);
MPFR_ASSERTD (i >= 2);
- if (n & (1UL << (i-2)))
+ if (n & ((UTYPE) 1 << (i-2)))
inexact |= mpfr_mul (res, res, x, rnd1);
for (i -= 3; i >= 0 && !MPFR_BLOCK_EXCEP; i--)
{
inexact |= mpfr_sqr (res, res, MPFR_RNDU);
- if (n & (1UL << i))
+ if (n & ((UTYPE) 1 << i))
inexact |= mpfr_mul (res, res, x, rnd1);
});
/* let r(n) be the number of roundings: we have r(2)=1, r(3)=2,
@@ -150,7 +158,7 @@ mpfr_pow_ui (mpfr_ptr y, mpfr_srcptr x, unsigned long int n, mpfr_rnd_t rnd)
mpfr_clear (res);
MPFR_SAVE_EXPO_FREE (expo);
mpz_init (z);
- mpz_set_ui (z, n);
+ MPZ_SET_U (z, n);
inexact = mpfr_pow_z (y, x, z, rnd);
mpz_clear (z);
return inexact;
diff --git a/tests/tpow.c b/tests/tpow.c
index 6a3192b21..50d04e4c7 100644
--- a/tests/tpow.c
+++ b/tests/tpow.c
@@ -21,6 +21,7 @@ https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
#define _MPFR_NO_DEPRECATED_ROOT
+#define MPFR_NEED_INTMAX_H
#include "mpfr-test.h"
#ifdef CHECK_EXTERNAL
@@ -360,6 +361,7 @@ check_pow_si (void)
static void
check_pown_ieee754_2019 (void)
{
+#ifdef _MPFR_H_HAVE_INTMAX_T
mpfr_t x;
mpfr_init2 (x, 5); /* ensures 17 is exact */
@@ -458,6 +460,7 @@ check_pown_ieee754_2019 (void)
MPFR_ASSERTN(mpfr_zero_p (x) && mpfr_signbit (x) == 0);
mpfr_clear (x);
+#endif
}
static void