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:
		| @@ -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; | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user