Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c62bd13

Browse files
author
Stefan Krah
committed
1) State the relative errors of the power functions for integer exponents.
2) _mpd_qpow_mpd(): Abort the loop for all specials, not only infinity. 3) _mpd_qpow_mpd(): Make the function more general and distinguish between zero clamping and folding down the exponent. The latter case is currently handled by setting context->clamp to 0 before calling the function. 4) _mpd_qpow_int(): Add one to the work precision in case of a negative exponent. This is to get the same relative error (0.1 * 10**-prec) for both positive and negative exponents. The previous relative error for negative exponents was (0.2 * 10**-prec). Both errors are _before_ the final rounding to the context precision.
1 parent f185226 commit c62bd13

1 file changed

Lines changed: 18 additions & 2 deletions

File tree

Modules/_decimal/libmpdec/mpdecimal.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5844,6 +5844,12 @@ mpd_qnext_toward(mpd_t *result, const mpd_t *a, const mpd_t *b,
58445844
/*
58455845
* Internal function: Integer power with mpd_uint_t exponent. The function
58465846
* can fail with MPD_Malloc_error.
5847+
*
5848+
* The error is equal to the error incurred in k-1 multiplications. Assuming
5849+
* the upper bound for the relative error in each operation:
5850+
*
5851+
* abs(err) = 5 * 10**-prec
5852+
* result = x**k * (1 + err)**(k-1)
58475853
*/
58485854
static inline void
58495855
_mpd_qpow_uint(mpd_t *result, const mpd_t *base, mpd_uint_t exp,
@@ -5880,6 +5886,12 @@ _mpd_qpow_uint(mpd_t *result, const mpd_t *base, mpd_uint_t exp,
58805886
/*
58815887
* Internal function: Integer power with mpd_t exponent, tbase and texp
58825888
* are modified!! Function can fail with MPD_Malloc_error.
5889+
*
5890+
* The error is equal to the error incurred in k multiplications. Assuming
5891+
* the upper bound for the relative error in each operation:
5892+
*
5893+
* abs(err) = 5 * 10**-prec
5894+
* result = x**k * (1 + err)**k
58835895
*/
58845896
static inline void
58855897
_mpd_qpow_mpd(mpd_t *result, mpd_t *tbase, mpd_t *texp, uint8_t resultsign,
@@ -5899,7 +5911,8 @@ _mpd_qpow_mpd(mpd_t *result, mpd_t *tbase, mpd_t *texp, uint8_t resultsign,
58995911
if (mpd_isodd(texp)) {
59005912
mpd_qmul(result, result, tbase, ctx, &workstatus);
59015913
*status |= workstatus;
5902-
if (workstatus & (MPD_Overflow|MPD_Clamped)) {
5914+
if (mpd_isspecial(result) ||
5915+
(mpd_iszerocoeff(result) && (workstatus & MPD_Clamped))) {
59035916
break;
59045917
}
59055918
}
@@ -5914,7 +5927,9 @@ _mpd_qpow_mpd(mpd_t *result, mpd_t *tbase, mpd_t *texp, uint8_t resultsign,
59145927
}
59155928

59165929
/*
5917-
* The power function for integer exponents.
5930+
* The power function for integer exponents. Relative error _before_ the
5931+
* final rounding to prec:
5932+
* abs(result - base**exp) < 0.1 * 10**-prec * abs(base**exp)
59185933
*/
59195934
static void
59205935
_mpd_qpow_int(mpd_t *result, const mpd_t *base, const mpd_t *exp,
@@ -5932,6 +5947,7 @@ _mpd_qpow_int(mpd_t *result, const mpd_t *base, const mpd_t *exp,
59325947
workctx.round = MPD_ROUND_HALF_EVEN;
59335948
workctx.clamp = 0;
59345949
if (mpd_isnegative(exp)) {
5950+
workctx.prec += 1;
59355951
mpd_qdiv(&tbase, &one, base, &workctx, status);
59365952
if (*status&MPD_Errors) {
59375953
mpd_setspecial(result, MPD_POS, MPD_NAN);

0 commit comments

Comments
 (0)