bc: tweak overflow detection in a^b
function old new delta zbc_num_p 506 510 +4 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
e36c39a46d
commit
aece2c5f0f
@ -5,7 +5,7 @@
|
|||||||
* Original code copyright (c) 2018 Gavin D. Howard and contributors.
|
* Original code copyright (c) 2018 Gavin D. Howard and contributors.
|
||||||
*/
|
*/
|
||||||
//TODO:
|
//TODO:
|
||||||
// maybe implement a^b for non-integer b?
|
// maybe implement a^b for non-integer b? (see zbc_num_p())
|
||||||
|
|
||||||
#define DEBUG_LEXER 0
|
#define DEBUG_LEXER 0
|
||||||
#define DEBUG_COMPILE 0
|
#define DEBUG_COMPILE 0
|
||||||
@ -2163,6 +2163,9 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size
|
|||||||
if (b->num[i] != 0)
|
if (b->num[i] != 0)
|
||||||
RETURN_STATUS(bc_error("not an integer"));
|
RETURN_STATUS(bc_error("not an integer"));
|
||||||
|
|
||||||
|
// a^b for non-integer b (for a>0) can be implemented as exp(ln(a)*b).
|
||||||
|
// Possibly better precision would be given by a^int(b) * exp(ln(a)*frac(b)).
|
||||||
|
|
||||||
if (b->len == 0) {
|
if (b->len == 0) {
|
||||||
bc_num_one(c);
|
bc_num_one(c);
|
||||||
RETURN_STATUS(BC_STATUS_SUCCESS);
|
RETURN_STATUS(BC_STATUS_SUCCESS);
|
||||||
@ -2199,11 +2202,11 @@ static FAST_FUNC BC_STATUS zbc_num_p(BcNum *a, BcNum *b, BcNum *restrict c, size
|
|||||||
//but it can be improved to detect zero results etc. Example: with scale=0,
|
//but it can be improved to detect zero results etc. Example: with scale=0,
|
||||||
//result of 0.01^N for any N>1 is 0: 0.01^2 = 0.0001 ~= 0.00 (trunc to scale)
|
//result of 0.01^N for any N>1 is 0: 0.01^2 = 0.0001 ~= 0.00 (trunc to scale)
|
||||||
//then this would matter:
|
//then this would matter:
|
||||||
// if (new_scale >= pow) is false, we had overflow, correct
|
// if a_rdx != 0 and new_scale < pow, we had overflow,
|
||||||
// "new_scale" value is larger than ULONG_MAX, thus larger
|
// correct "new_scale" value is larger than ULONG_MAX,
|
||||||
// than any possible current value of "scale",
|
// thus larger than any possible current value of "scale",
|
||||||
// thus "scale = new_scale" should not be done:
|
// thus "scale = new_scale" should not be done:
|
||||||
if (new_scale >= pow)
|
if (a_rdx == 0 || new_scale >= pow)
|
||||||
if (new_scale < scale)
|
if (new_scale < scale)
|
||||||
scale = new_scale;
|
scale = new_scale;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user