diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index af36e399b016d..f53032fabc35c 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -32,6 +32,9 @@ ZEND_DECLARE_MODULE_GLOBALS(bcmath) static PHP_GINIT_FUNCTION(bcmath); static PHP_GSHUTDOWN_FUNCTION(bcmath); +static PHP_MINIT_FUNCTION(bcmath); +static PHP_MSHUTDOWN_FUNCTION(bcmath); +static PHP_MINFO_FUNCTION(bcmath); zend_module_entry bcmath_module_entry = { STANDARD_MODULE_HEADER, @@ -341,15 +344,13 @@ PHP_FUNCTION(bcdiv) goto cleanup; } - switch (bc_divide(first, second, &result, scale)) { - case 0: /* OK */ - RETVAL_STR(bc_num2str_ex(result, scale)); - break; - case -1: /* division by zero */ - zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Division by zero"); - break; + if (!bc_divide(first, second, &result, scale)) { + zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Division by zero"); + goto cleanup; } + RETVAL_STR(bc_num2str_ex(result, scale)); + cleanup: { bc_free_num(&first); bc_free_num(&second); @@ -397,15 +398,13 @@ PHP_FUNCTION(bcmod) goto cleanup; } - switch (bc_modulo(first, second, &result, scale)) { - case 0: - RETVAL_STR(bc_num2str_ex(result, scale)); - break; - case -1: - zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero"); - break; + if (!bc_modulo(first, second, &result, scale)) { + zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero"); + goto cleanup; } + RETVAL_STR(bc_num2str_ex(result, scale)); + cleanup: { bc_free_num(&first); bc_free_num(&second); @@ -417,16 +416,16 @@ PHP_FUNCTION(bcmod) /* {{{ Returns the value of an arbitrary precision number raised to the power of another reduced by a modulus */ PHP_FUNCTION(bcpowmod) { - zend_string *left, *right, *modulus; + zend_string *base_str, *exponent_str, *modulus_str; zend_long scale_param; bool scale_param_is_null = 1; - bc_num first, second, mod, result; + bc_num bc_base, bc_expo, bc_modulus, result; int scale = BCG(bc_precision); ZEND_PARSE_PARAMETERS_START(3, 4) - Z_PARAM_STR(left) - Z_PARAM_STR(right) - Z_PARAM_STR(modulus) + Z_PARAM_STR(base_str) + Z_PARAM_STR(exponent_str) + Z_PARAM_STR(modulus_str) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(scale_param, scale_param_is_null) ZEND_PARSE_PARAMETERS_END(); @@ -440,34 +439,53 @@ PHP_FUNCTION(bcpowmod) scale = (int) scale_param; } - bc_init_num(&first); - bc_init_num(&second); - bc_init_num(&mod); + bc_init_num(&bc_base); + bc_init_num(&bc_expo); + bc_init_num(&bc_modulus); bc_init_num(&result); - if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) { + if (php_str2num(&bc_base, ZSTR_VAL(base_str)) == FAILURE) { zend_argument_value_error(1, "is not well-formed"); goto cleanup; } - if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) { + if (php_str2num(&bc_expo, ZSTR_VAL(exponent_str)) == FAILURE) { zend_argument_value_error(2, "is not well-formed"); goto cleanup; } - if (php_str2num(&mod, ZSTR_VAL(modulus)) == FAILURE) { + if (php_str2num(&bc_modulus, ZSTR_VAL(modulus_str)) == FAILURE) { zend_argument_value_error(3, "is not well-formed"); goto cleanup; } - if (bc_raisemod(first, second, mod, &result, scale) == SUCCESS) { - RETVAL_STR(bc_num2str_ex(result, scale)); + raise_mod_status status = bc_raisemod(bc_base, bc_expo, bc_modulus, &result, scale); + switch (status) { + case BASE_HAS_FRACTIONAL: + zend_argument_value_error(1, "cannot have a fractional part"); + goto cleanup; + case EXPO_HAS_FRACTIONAL: + zend_argument_value_error(2, "cannot have a fractional part"); + goto cleanup; + case EXPO_IS_NEGATIVE: + zend_argument_value_error(2, "must be greater than or equal to 0"); + goto cleanup; + case MOD_HAS_FRACTIONAL: + zend_argument_value_error(3, "cannot have a fractional part"); + goto cleanup; + case MOD_IS_ZERO: + zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero"); + goto cleanup; + case OK: + RETVAL_STR(bc_num2str_ex(result, scale)); + break; + EMPTY_SWITCH_DEFAULT_CASE(); } cleanup: { - bc_free_num(&first); - bc_free_num(&second); - bc_free_num(&mod); + bc_free_num(&bc_base); + bc_free_num(&bc_expo); + bc_free_num(&bc_modulus); bc_free_num(&result); }; } @@ -476,15 +494,15 @@ PHP_FUNCTION(bcpowmod) /* {{{ Returns the value of an arbitrary precision number raised to the power of another */ PHP_FUNCTION(bcpow) { - zend_string *left, *right; + zend_string *base_str, *exponent_str; zend_long scale_param; bool scale_param_is_null = 1; - bc_num first, second, result; + bc_num first, bc_exponent, result; int scale = BCG(bc_precision); ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STR(left) - Z_PARAM_STR(right) + Z_PARAM_STR(base_str) + Z_PARAM_STR(exponent_str) Z_PARAM_OPTIONAL Z_PARAM_LONG_OR_NULL(scale_param, scale_param_is_null) ZEND_PARSE_PARAMETERS_END(); @@ -499,26 +517,37 @@ PHP_FUNCTION(bcpow) } bc_init_num(&first); - bc_init_num(&second); + bc_init_num(&bc_exponent); bc_init_num(&result); - if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) { + if (php_str2num(&first, ZSTR_VAL(base_str)) == FAILURE) { zend_argument_value_error(1, "is not well-formed"); goto cleanup; } - if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) { + if (php_str2num(&bc_exponent, ZSTR_VAL(exponent_str)) == FAILURE) { zend_argument_value_error(2, "is not well-formed"); goto cleanup; } - bc_raise (first, second, &result, scale); + /* Check the exponent for scale digits and convert to a long. */ + if (bc_exponent->n_scale != 0) { + zend_argument_value_error(2, "cannot have a fractional part"); + goto cleanup; + } + long exponent = bc_num2long(bc_exponent); + if (exponent == 0 && (bc_exponent->n_len > 1 || bc_exponent->n_value[0] != 0)) { + zend_argument_value_error(2, "is too large"); + goto cleanup; + } + + bc_raise(first, exponent, &result, scale); RETVAL_STR(bc_num2str_ex(result, scale)); cleanup: { bc_free_num(&first); - bc_free_num(&second); + bc_free_num(&bc_exponent); bc_free_num(&result); }; } diff --git a/ext/bcmath/libbcmath/src/add.c b/ext/bcmath/libbcmath/src/add.c index fc76d5652e39e..a57ed32afaee1 100644 --- a/ext/bcmath/libbcmath/src/add.c +++ b/ext/bcmath/libbcmath/src/add.c @@ -29,55 +29,49 @@ *************************************************************************/ -#include -#include -#include -#include -#include #include "bcmath.h" #include "private.h" +#include +#include /* Here is the full add routine that takes care of negative numbers. N1 is added to N2 and the result placed into RESULT. SCALE_MIN is the minimum scale for the result. */ -void bc_add (bc_num n1, bc_num n2, bc_num *result, int scale_min) +void bc_add (bc_num n1, bc_num n2, bc_num *result, size_t scale_min) { - bc_num sum = NULL; - int cmp_res; - int res_scale; + bc_num sum = NULL; + int cmp_res; + size_t res_scale; - if (n1->n_sign == n2->n_sign) - { - sum = _bc_do_add (n1, n2, scale_min); - sum->n_sign = n1->n_sign; - } - else - { - /* subtraction must be done. */ - cmp_res = _bc_do_compare (n1, n2, FALSE, FALSE); /* Compare magnitudes. */ - switch (cmp_res) - { - case -1: - /* n1 is less than n2, subtract n1 from n2. */ - sum = _bc_do_sub (n2, n1, scale_min); - sum->n_sign = n2->n_sign; - break; - case 0: - /* They are equal! return zero with the correct scale! */ - res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale)); - sum = bc_new_num (1, res_scale); - memset (sum->n_value, 0, res_scale+1); - break; - case 1: - /* n2 is less than n1, subtract n2 from n1. */ - sum = _bc_do_sub (n1, n2, scale_min); - sum->n_sign = n1->n_sign; + if (n1->n_sign == n2->n_sign) { + sum = _bc_do_add (n1, n2, scale_min); + sum->n_sign = n1->n_sign; + } else { + /* subtraction must be done. */ + /* Compare magnitudes. */ + cmp_res = _bc_do_compare(n1, n2, false, false); + switch (cmp_res) { + case -1: + /* n1 is less than n2, subtract n1 from n2. */ + sum = _bc_do_sub (n2, n1, scale_min); + sum->n_sign = n2->n_sign; + break; + case 0: + /* They are equal! return zero with the correct scale! */ + res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale)); + sum = bc_new_num (1, res_scale); + memset (sum->n_value, 0, res_scale+1); + break; + case 1: + /* n2 is less than n1, subtract n2 from n1. */ + sum = _bc_do_sub (n1, n2, scale_min); + sum->n_sign = n1->n_sign; + } } - } - /* Clean up and return. */ - bc_free_num (result); - *result = sum; + /* Clean up and return. */ + bc_free_num (result); + *result = sum; } diff --git a/ext/bcmath/libbcmath/src/bcmath.h b/ext/bcmath/libbcmath/src/bcmath.h index 6ce1350956417..38ad86b34c718 100644 --- a/ext/bcmath/libbcmath/src/bcmath.h +++ b/ext/bcmath/libbcmath/src/bcmath.h @@ -32,32 +32,33 @@ #ifndef _BCMATH_H_ #define _BCMATH_H_ +#include + typedef enum {PLUS, MINUS} sign; typedef struct bc_struct *bc_num; -typedef struct bc_struct - { - sign n_sign; - int n_len; /* The number of digits before the decimal point. */ - int n_scale; /* The number of digits after the decimal point. */ - int n_refs; /* The number of pointers to this number. */ - char *n_ptr; /* The pointer to the actual storage. - If NULL, n_value points to the inside of - another number (bc_multiply...) and should - not be "freed." */ - char *n_value; /* The number. Not zero char terminated. - May not point to the same place as n_ptr as - in the case of leading zeros generated. */ - } bc_struct; +typedef struct bc_struct { + sign n_sign; + size_t n_len; /* The number of digits before the decimal point. */ + size_t n_scale; /* The number of digits after the decimal point. */ + int n_refs; /* The number of pointers to this number. */ + char *n_ptr; /* The pointer to the actual storage. + If NULL, n_value points to the inside of another number + (bc_multiply...) and should not be "freed." */ + char *n_value; /* The number. Not zero char terminated. + May not point to the same place as n_ptr as + in the case of leading zeros generated. */ +} bc_struct; #ifdef HAVE_CONFIG_H #include "config.h" #endif +#include "zend.h" #include -#include "php.h" /* Needed for safe_pemalloc() in init.c */ -#include "../../php_bcmath.h" +#include "zend_string.h" +#include "../../php_bcmath.h" /* Needed for BCG() macro */ /* The base used in storing the numbers in n_value above. Currently this MUST be 10. */ @@ -77,11 +78,6 @@ typedef struct bc_struct #define MIN(a, b) ((a)>(b)?(b):(a)) #define ODD(a) ((a)&1) -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - #ifndef LONG_MAX #define LONG_MAX 0x7ffffff #endif @@ -91,17 +87,17 @@ typedef struct bc_struct void bc_init_numbers(void); -bc_num _bc_new_num_ex(int length, int scale, int persistent); +bc_num _bc_new_num_ex(size_t length, size_t scale, bool persistent); -void _bc_free_num_ex(bc_num *num, int persistent); +void _bc_free_num_ex(bc_num *num, bool persistent); bc_num bc_copy_num(bc_num num); void bc_init_num(bc_num *num); -int bc_str2num(bc_num *num, char *str, int scale); +bool bc_str2num(bc_num *num, char *str, size_t scale); -zend_string *bc_num2str_ex(bc_num num, int scale); +zend_string *bc_num2str_ex(bc_num num, size_t scale); void bc_int2num(bc_num *num, int val); @@ -109,33 +105,44 @@ long bc_num2long(bc_num num); int bc_compare(bc_num n1, bc_num n2); -char bc_is_zero(bc_num num); +bool bc_is_zero(bc_num num); -char bc_is_zero_for_scale(bc_num num, int scale); +bool bc_is_zero_for_scale(bc_num num, size_t scale); -bool bc_is_near_zero(bc_num num, int scale); +bool bc_is_near_zero(bc_num num, size_t scale); bool bc_is_neg(bc_num num); -void bc_add(bc_num n1, bc_num n2, bc_num *result, int scale_min); +void bc_add(bc_num n1, bc_num n2, bc_num *result, size_t scale_min); + +void bc_sub(bc_num n1, bc_num n2, bc_num *result, size_t scale_min); + +void bc_multiply(bc_num n1, bc_num n2, bc_num *prod, size_t scale); -void bc_sub(bc_num n1, bc_num n2, bc_num *result, int scale_min); +bool bc_divide(bc_num n1, bc_num n2, bc_num *quot, int scale); -void bc_multiply(bc_num n1, bc_num n2, bc_num *prod, int scale); +bool bc_modulo(bc_num num1, bc_num num2, bc_num *resul, size_t scale); -int bc_divide(bc_num n1, bc_num n2, bc_num *quot, int scale); +bool bc_divmod(bc_num num1, bc_num num2, bc_num *quo, bc_num *rem, size_t scale); -int bc_modulo(bc_num num1, bc_num num2, bc_num *resul, int scale); +typedef enum { + OK, + BASE_HAS_FRACTIONAL, + EXPO_HAS_FRACTIONAL, + EXPO_IS_NEGATIVE, + MOD_HAS_FRACTIONAL, + MOD_IS_ZERO +} raise_mod_status; -int bc_divmod(bc_num num1, bc_num num2, bc_num *quo, bc_num *rem, int scale); +raise_mod_status bc_raisemod(bc_num base, bc_num exponent, bc_num mod, bc_num *result, size_t scale); -zend_result bc_raisemod(bc_num base, bc_num expo, bc_num mo, bc_num *result, int scale); +void bc_raise(bc_num base, long exponent, bc_num *resul, size_t scale); -void bc_raise(bc_num num1, bc_num num2, bc_num *resul, int scale); +void bc_raise_bc_exponent(bc_num base, bc_num exponent, bc_num *resul, size_t scale); -bool bc_sqrt(bc_num *num, int scale); +bool bc_sqrt(bc_num *num, size_t scale); -void bc_out_num(bc_num num, int o_base, void (* out_char)(char), int leading_zero); +void bc_out_num(bc_num num, int o_base, void (* out_char)(char), bool leading_zero); /* Prototypes needed for external utility routines. */ #define bc_new_num(length, scale) _bc_new_num_ex((length), (scale), 0) diff --git a/ext/bcmath/libbcmath/src/compare.c b/ext/bcmath/libbcmath/src/compare.c index b23590b5ed643..d21de720cb145 100644 --- a/ext/bcmath/libbcmath/src/compare.c +++ b/ext/bcmath/libbcmath/src/compare.c @@ -29,12 +29,8 @@ *************************************************************************/ -#include -#include -#include -#include -#include #include +#include #include "bcmath.h" #include "private.h" @@ -45,110 +41,103 @@ int _bc_do_compare(bc_num n1, bc_num n2, bool use_sign, bool ignore_last) { - char *n1ptr, *n2ptr; - int count; - - /* First, compare signs. */ - if (use_sign && n1->n_sign != n2->n_sign) - { - if (n1->n_sign == PLUS) - return (1); /* Positive N1 > Negative N2 */ - else - return (-1); /* Negative N1 < Positive N1 */ - } - - /* Now compare the magnitude. */ - if (n1->n_len != n2->n_len) - { - if (n1->n_len > n2->n_len) - { - /* Magnitude of n1 > n2. */ - if (!use_sign || n1->n_sign == PLUS) - return (1); - else - return (-1); + char *n1ptr, *n2ptr; + + /* First, compare signs. */ + if (use_sign && n1->n_sign != n2->n_sign) { + if (n1->n_sign == PLUS) { + return (1); /* Positive N1 > Negative N2 */ + } else { + return (-1); /* Negative N1 < Positive N1 */ + } } - else - { - /* Magnitude of n1 < n2. */ - if (!use_sign || n1->n_sign == PLUS) - return (-1); - else - return (1); + + /* Now compare the magnitude. */ + if (n1->n_len != n2->n_len) { + if (n1->n_len > n2->n_len) { + /* Magnitude of n1 > n2. */ + if (!use_sign || n1->n_sign == PLUS) { + return (1); + } else { + return (-1); + } + } else { + /* Magnitude of n1 < n2. */ + if (!use_sign || n1->n_sign == PLUS) { + return (-1); + } else { + return (1); + } + } } - } - - /* If we get here, they have the same number of integer digits. - check the integer part and the equal length part of the fraction. */ - count = n1->n_len + MIN (n1->n_scale, n2->n_scale); - n1ptr = n1->n_value; - n2ptr = n2->n_value; - - while ((count > 0) && (*n1ptr == *n2ptr)) - { - n1ptr++; - n2ptr++; - count--; - } - if (ignore_last && count == 1 && n1->n_scale == n2->n_scale) - return (0); - if (count != 0) - { - if (*n1ptr > *n2ptr) - { - /* Magnitude of n1 > n2. */ - if (!use_sign || n1->n_sign == PLUS) - return (1); - else - return (-1); + + /* If we get here, they have the same number of integer digits. + check the integer part and the equal length part of the fraction. */ + size_t count = n1->n_len + MIN (n1->n_scale, n2->n_scale); + n1ptr = n1->n_value; + n2ptr = n2->n_value; + + while ((count > 0) && (*n1ptr == *n2ptr)) { + n1ptr++; + n2ptr++; + count--; } - else - { - /* Magnitude of n1 < n2. */ - if (!use_sign || n1->n_sign == PLUS) - return (-1); - else - return (1); + + if (ignore_last && count == 1 && n1->n_scale == n2->n_scale) { + return (0); } - } - - /* They are equal up to the last part of the equal part of the fraction. */ - if (n1->n_scale != n2->n_scale) - { - if (n1->n_scale > n2->n_scale) - { - for (count = n1->n_scale-n2->n_scale; count>0; count--) - if (*n1ptr++ != 0) - { - /* Magnitude of n1 > n2. */ - if (!use_sign || n1->n_sign == PLUS) - return (1); - else - return (-1); - } + if (count != 0) { + if (*n1ptr > *n2ptr) { + /* Magnitude of n1 > n2. */ + if (!use_sign || n1->n_sign == PLUS) { + return (1); + } else { + return (-1); + } + } else { + /* Magnitude of n1 < n2. */ + if (!use_sign || n1->n_sign == PLUS) { + return (-1); + } else { + return (1); + } + } } - else - { - for (count = n2->n_scale-n1->n_scale; count>0; count--) - if (*n2ptr++ != 0) - { - /* Magnitude of n1 < n2. */ - if (!use_sign || n1->n_sign == PLUS) - return (-1); - else - return (1); - } + + /* They are equal up to the last part of the equal part of the fraction. */ + if (n1->n_scale != n2->n_scale) { + if (n1->n_scale > n2->n_scale) { + for (count = n1->n_scale-n2->n_scale; count>0; count--) { + if (*n1ptr++ != 0) { + /* Magnitude of n1 > n2. */ + if (!use_sign || n1->n_sign == PLUS) { + return (1); + } else { + return (-1); + } + } + } + } else { + for (count = n2->n_scale-n1->n_scale; count>0; count--) { + if (*n2ptr++ != 0) { + /* Magnitude of n1 < n2. */ + if (!use_sign || n1->n_sign == PLUS) { + return (-1); + } else { + return (1); + } + } + } + } } - } - /* They must be equal! */ - return (0); + /* They must be equal! */ + return (0); } /* This is the "user callable" routine to compare numbers N1 and N2. */ - int bc_compare(bc_num n1, bc_num n2) { - return _bc_do_compare (n1, n2, true, false); + return _bc_do_compare(n1, n2, true, false); } diff --git a/ext/bcmath/libbcmath/src/config.h b/ext/bcmath/libbcmath/src/config.h index 100163d3830cc..0c7b3c220838b 100644 --- a/ext/bcmath/libbcmath/src/config.h +++ b/ext/bcmath/libbcmath/src/config.h @@ -3,8 +3,3 @@ #else #include #endif - -#include "php.h" -#include -#include "zend.h" -#include "zend_alloc.h" diff --git a/ext/bcmath/libbcmath/src/debug.c b/ext/bcmath/libbcmath/src/debug.c index a1d9afdb47d53..a9ed000196a08 100644 --- a/ext/bcmath/libbcmath/src/debug.c +++ b/ext/bcmath/libbcmath/src/debug.c @@ -29,34 +29,32 @@ *************************************************************************/ -#include #include -#include -#include -#include #include "bcmath.h" #include "private.h" +#include /* pn prints the number NUM in base 10. */ static void out_char (char c) { - putchar(c); + putchar(c); } -void pn (bc_num num) +void pn(bc_num num) { - bc_out_num(num, 10, out_char, 0); - out_char ('\n'); + bc_out_num(num, 10, out_char, 0); + out_char ('\n'); } /* pv prints a character array as if it was a string of bcd digits. */ -void pv (char *name, unsigned char *num, int len) +void pv (char *name, unsigned char *num, size_t len) { - int i; - printf ("%s=", name); - for (i=0; i -#include -#include -#include -#include #include "bcmath.h" #include "private.h" +#include +#include +#include "zend_alloc.h" /* Some utility routines for the divide: First a one digit multiply. @@ -43,222 +41,218 @@ placed into RESULT. It is written so that NUM and RESULT can be the same pointers. */ -static void _one_mult (unsigned char *num, int size, int digit, unsigned char *result) +static void _one_mult(unsigned char *num, size_t size, int digit, unsigned char *result) { - int carry, value; - unsigned char *nptr, *rptr; - - if (digit == 0) - memset (result, 0, size); - else - { - if (digit == 1) - memcpy (result, num, size); - else - { - /* Initialize */ - nptr = (unsigned char *) (num+size-1); - rptr = (unsigned char *) (result+size-1); - carry = 0; - - while (size-- > 0) - { - value = *nptr-- * digit + carry; - *rptr-- = value % BASE; - carry = value / BASE; - } - - if (carry != 0) *rptr = carry; + int carry, value; + unsigned char *nptr, *rptr; + + if (digit == 0) { + memset(result, 0, size); + } else { + if (digit == 1) { + memcpy(result, num, size); + } else { + /* Initialize */ + nptr = (unsigned char *) (num+size-1); + rptr = (unsigned char *) (result+size-1); + carry = 0; + + while (size-- > 0) { + value = *nptr-- * digit + carry; + *rptr-- = value % BASE; + carry = value / BASE; + } + + if (carry != 0) { + *rptr = carry; + } + } } - } } /* The full division routine. This computes N1 / N2. It returns - 0 if the division is ok and the result is in QUOT. The number of - digits after the decimal point is SCALE. It returns -1 if division + true if the division is ok and the result is in QUOT. The number of + digits after the decimal point is SCALE. It returns false if division by zero is tried. The algorithm is found in Knuth Vol 2. p237. */ - -int bc_divide (bc_num n1, bc_num n2, bc_num *quot, int scale) +bool bc_divide(bc_num n1, bc_num n2, bc_num *quot, int scale) { - bc_num qval; - unsigned char *num1, *num2; - unsigned char *ptr1, *ptr2, *n2ptr, *qptr; - int scale1, val; - unsigned int len1, len2, scale2, qdigits, extra, count; - unsigned int qdig, qguess, borrow, carry; - unsigned char *mval; - char zero; - unsigned int norm; - - /* Test for divide by zero. */ - if (bc_is_zero (n2)) return -1; - - /* Test for divide by 1. If it is we must truncate. */ - if (n2->n_scale == 0) - { - if (n2->n_len == 1 && *n2->n_value == 1) - { - qval = bc_new_num (n1->n_len, scale); - qval->n_sign = (n1->n_sign == n2->n_sign ? PLUS : MINUS); - memset (&qval->n_value[n1->n_len],0,scale); - memcpy (qval->n_value, n1->n_value, - n1->n_len + MIN(n1->n_scale,scale)); - bc_free_num (quot); - *quot = qval; + bc_num qval; + unsigned char *num1, *num2; + unsigned char *ptr1, *ptr2, *n2ptr, *qptr; + int scale1, val; + unsigned int len1, len2, scale2, qdigits, extra, count; + unsigned int qdig, qguess, borrow, carry; + unsigned char *mval; + bool zero; + unsigned int norm; + + /* Test for divide by zero. */ + if (bc_is_zero(n2)) { + return false; + } + + /* Test for divide by 1. If it is we must truncate. */ + if (n2->n_scale == 0) { + if (n2->n_len == 1 && *n2->n_value == 1) { + qval = bc_new_num (n1->n_len, scale); + qval->n_sign = (n1->n_sign == n2->n_sign ? PLUS : MINUS); + memset (&qval->n_value[n1->n_len],0,scale); + memcpy (qval->n_value, n1->n_value, n1->n_len + MIN(n1->n_scale,scale)); + bc_free_num (quot); + *quot = qval; + } + } + + /* Set up the divide. Move the decimal point on n1 by n2's scale. + Remember, zeros on the end of num2 are wasted effort for dividing. */ + scale2 = n2->n_scale; + n2ptr = (unsigned char *) n2->n_value+n2->n_len+scale2-1; + while ((scale2 > 0) && (*n2ptr-- == 0)) { + scale2--; + } + + len1 = n1->n_len + scale2; + scale1 = n1->n_scale - scale2; + if (scale1 < scale) { + extra = scale - scale1; + } else { + extra = 0; } - } - - /* Set up the divide. Move the decimal point on n1 by n2's scale. - Remember, zeros on the end of num2 are wasted effort for dividing. */ - scale2 = n2->n_scale; - n2ptr = (unsigned char *) n2->n_value+n2->n_len+scale2-1; - while ((scale2 > 0) && (*n2ptr-- == 0)) scale2--; - - len1 = n1->n_len + scale2; - scale1 = n1->n_scale - scale2; - if (scale1 < scale) - extra = scale - scale1; - else - extra = 0; - num1 = (unsigned char *) safe_emalloc (1, n1->n_len+n1->n_scale, extra+2); - memset (num1, 0, n1->n_len+n1->n_scale+extra+2); - memcpy (num1+1, n1->n_value, n1->n_len+n1->n_scale); - - len2 = n2->n_len + scale2; - num2 = (unsigned char *) safe_emalloc (1, len2, 1); - memcpy (num2, n2->n_value, len2); - *(num2+len2) = 0; - n2ptr = num2; - while (*n2ptr == 0) - { - n2ptr++; - len2--; - } - - /* Calculate the number of quotient digits. */ - if (len2 > len1+scale) - { - qdigits = scale+1; - zero = TRUE; - } - else - { - zero = FALSE; - if (len2>len1) - qdigits = scale+1; /* One for the zero integer part. */ - else - qdigits = len1-len2+scale+1; - } - - /* Allocate and zero the storage for the quotient. */ - qval = bc_new_num (qdigits-scale,scale); - memset (qval->n_value, 0, qdigits); - - /* Allocate storage for the temporary storage mval. */ - mval = (unsigned char *) safe_emalloc (1, len2, 1); - - /* Now for the full divide algorithm. */ - if (!zero) - { - /* Normalize */ - norm = 10 / ((int)*n2ptr + 1); - if (norm != 1) - { - _one_mult (num1, len1+scale1+extra+1, norm, num1); - _one_mult (n2ptr, len2, norm, n2ptr); + num1 = (unsigned char *) safe_emalloc (1, n1->n_len+n1->n_scale, extra+2); + memset (num1, 0, n1->n_len+n1->n_scale+extra+2); + memcpy (num1+1, n1->n_value, n1->n_len+n1->n_scale); + + len2 = n2->n_len + scale2; + num2 = (unsigned char *) safe_emalloc (1, len2, 1); + memcpy (num2, n2->n_value, len2); + *(num2+len2) = 0; + n2ptr = num2; + while (*n2ptr == 0) { + n2ptr++; + len2--; } - /* Initialize divide loop. */ - qdig = 0; - if (len2 > len1) - qptr = (unsigned char *) qval->n_value+len2-len1; - else - qptr = (unsigned char *) qval->n_value; - - /* Loop */ - while (qdig <= len1+scale-len2) - { - /* Calculate the quotient digit guess. */ - if (*n2ptr == num1[qdig]) - qguess = 9; - else - qguess = (num1[qdig]*10 + num1[qdig+1]) / *n2ptr; - - /* Test qguess. */ - if (n2ptr[1]*qguess > - (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10 - + num1[qdig+2]) - { - qguess--; - /* And again. */ - if (n2ptr[1]*qguess > - (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10 - + num1[qdig+2]) - qguess--; - } - - /* Multiply and subtract. */ - borrow = 0; - if (qguess != 0) - { - *mval = 0; - _one_mult (n2ptr, len2, qguess, mval+1); - ptr1 = (unsigned char *) num1+qdig+len2; - ptr2 = (unsigned char *) mval+len2; - for (count = 0; count < len2+1; count++) - { - val = (int) *ptr1 - (int) *ptr2-- - borrow; - if (val < 0) - { - val += 10; - borrow = 1; - } - else - borrow = 0; - *ptr1-- = val; + /* Calculate the number of quotient digits. */ + if (len2 > len1+scale) { + qdigits = scale+1; + zero = true; + } else { + zero = false; + if (len2 > len1) { + /* One for the zero integer part. */ + qdigits = scale+1; + } else { + qdigits = len1-len2+scale+1; } - } - - /* Test for negative result. */ - if (borrow == 1) - { - qguess--; - ptr1 = (unsigned char *) num1+qdig+len2; - ptr2 = (unsigned char *) n2ptr+len2-1; - carry = 0; - for (count = 0; count < len2; count++) - { - val = (int) *ptr1 + (int) *ptr2-- + carry; - if (val > 9) - { - val -= 10; - carry = 1; - } - else - carry = 0; - *ptr1-- = val; + } + + /* Allocate and zero the storage for the quotient. */ + qval = bc_new_num (qdigits-scale,scale); + memset (qval->n_value, 0, qdigits); + + /* Allocate storage for the temporary storage mval. */ + mval = (unsigned char *) safe_emalloc(1, len2, 1); + + /* Now for the full divide algorithm. */ + if (!zero) { + /* Normalize */ + norm = 10 / ((int)*n2ptr + 1); + if (norm != 1) { + _one_mult (num1, len1+scale1+extra+1, norm, num1); + _one_mult (n2ptr, len2, norm, n2ptr); } - if (carry == 1) *ptr1 = (*ptr1 + 1) % 10; - } - /* We now know the quotient digit. */ - *qptr++ = qguess; - qdig++; + /* Initialize divide loop. */ + qdig = 0; + if (len2 > len1) { + qptr = (unsigned char *) qval->n_value+len2-len1; + } else { + qptr = (unsigned char *) qval->n_value; + } + + /* Loop */ + while (qdig <= len1+scale-len2) { + /* Calculate the quotient digit guess. */ + if (*n2ptr == num1[qdig]) { + qguess = 9; + } else { + qguess = (num1[qdig]*10 + num1[qdig+1]) / *n2ptr; + } + + /* Test qguess. */ + if ( + n2ptr[1]*qguess > (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10 + num1[qdig+2] + ) { + qguess--; + /* And again. */ + if ( + n2ptr[1]*qguess > (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10 + num1[qdig+2] + ) { + qguess--; + } + } + + /* Multiply and subtract. */ + borrow = 0; + if (qguess != 0) { + *mval = 0; + _one_mult (n2ptr, len2, qguess, mval+1); + ptr1 = (unsigned char *) num1+qdig+len2; + ptr2 = (unsigned char *) mval+len2; + for (count = 0; count < len2+1; count++) { + val = (int) *ptr1 - (int) *ptr2-- - borrow; + if (val < 0) { + val += 10; + borrow = 1; + } else { + borrow = 0; + } + *ptr1-- = val; + } + } + + /* Test for negative result. */ + if (borrow == 1) { + qguess--; + ptr1 = (unsigned char *) num1+qdig+len2; + ptr2 = (unsigned char *) n2ptr+len2-1; + carry = 0; + for (count = 0; count < len2; count++) { + val = (int) *ptr1 + (int) *ptr2-- + carry; + if (val > 9) { + val -= 10; + carry = 1; + } else { + carry = 0; + } + *ptr1-- = val; + } + if (carry == 1) { + *ptr1 = (*ptr1 + 1) % 10; + } + } + + /* We now know the quotient digit. */ + *qptr++ = qguess; + qdig++; + } } - } - /* Clean up and return the number. */ - qval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS ); - if (bc_is_zero (qval)) qval->n_sign = PLUS; - _bc_rm_leading_zeros (qval); - bc_free_num (quot); - *quot = qval; + /* Clean up and return the number. */ + qval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS ); + if (bc_is_zero(qval)) { + qval->n_sign = PLUS; + } + _bc_rm_leading_zeros(qval); + bc_free_num(quot); + *quot = qval; - /* Clean up temporary storage. */ - efree (mval); - efree (num1); - efree (num2); + /* Clean up temporary storage. */ + efree(mval); + efree(num1); + efree(num2); - return 0; /* Everything is OK. */ + /* Everything is OK. */ + return true; } diff --git a/ext/bcmath/libbcmath/src/divmod.c b/ext/bcmath/libbcmath/src/divmod.c index d6f0566777a63..2999cd8cd1c34 100644 --- a/ext/bcmath/libbcmath/src/divmod.c +++ b/ext/bcmath/libbcmath/src/divmod.c @@ -29,55 +29,55 @@ *************************************************************************/ -#include -#include -#include -#include -#include #include "bcmath.h" -#include "private.h" +#include +#include /* Division *and* modulo for numbers. This computes both NUM1 / NUM2 and NUM1 % NUM2 and puts the results in QUOT and REM, except that if QUOT is NULL then that store will be omitted. + false is returned if divisor is 0. + true otherwise for success. */ -int bc_divmod (bc_num num1, bc_num num2, bc_num *quot, bc_num *rem, int scale) +bool bc_divmod(bc_num num1, bc_num num2, bc_num *quot, bc_num *rem, size_t scale) { - bc_num quotient = NULL; - bc_num temp; - int rscale; - - /* Check for correct numbers. */ - if (bc_is_zero (num2)) return -1; - - /* Calculate final scale. */ - rscale = MAX (num1->n_scale, num2->n_scale+scale); - bc_init_num(&temp); - - /* Calculate it. */ - bc_divide (num1, num2, &temp, 0); - if (quot) - quotient = bc_copy_num (temp); - bc_multiply (temp, num2, &temp, rscale); - bc_sub (num1, temp, rem, rscale); - bc_free_num (&temp); - - if (quot) - { - bc_free_num (quot); - *quot = quotient; - } - - return 0; /* Everything is OK. */ + bc_num quotient = NULL; + bc_num temp; + size_t rscale; + + /* Cannot divide/mod by 0. */ + if (bc_is_zero(num2)) { + return false; + } + + /* Calculate final scale. */ + rscale = MAX (num1->n_scale, num2->n_scale+scale); + bc_init_num(&temp); + + /* Calculate it. */ + bc_divide (num1, num2, &temp, 0); + if (quot) { + quotient = bc_copy_num(temp); + } + bc_multiply (temp, num2, &temp, rscale); + bc_sub (num1, temp, rem, rscale); + bc_free_num (&temp); + + if (quot) { + bc_free_num (quot); + *quot = quotient; + } + + return true; } /* Modulo for numbers. This computes NUM1 % NUM2 and puts the result in RESULT. */ -int bc_modulo (bc_num num1, bc_num num2, bc_num *result, int scale) +bool bc_modulo(bc_num num1, bc_num num2, bc_num *result, size_t scale) { - return bc_divmod (num1, num2, NULL, result, scale); + return bc_divmod(num1, num2, NULL, result, scale); } diff --git a/ext/bcmath/libbcmath/src/doaddsub.c b/ext/bcmath/libbcmath/src/doaddsub.c index d3db98167d4d2..29de12fb272c8 100644 --- a/ext/bcmath/libbcmath/src/doaddsub.c +++ b/ext/bcmath/libbcmath/src/doaddsub.c @@ -29,100 +29,99 @@ *************************************************************************/ -#include -#include -#include -#include -#include #include "bcmath.h" #include "private.h" +#include /* Perform addition: N1 is added to N2 and the value is returned. The signs of N1 and N2 are ignored. SCALE_MIN is to set the minimum scale of the result. */ -bc_num _bc_do_add(bc_num n1, bc_num n2, int scale_min) +bc_num _bc_do_add(bc_num n1, bc_num n2, size_t scale_min) { - bc_num sum; - int sum_scale, sum_digits; - char *n1ptr, *n2ptr, *sumptr; - int carry, n1bytes, n2bytes; - int count; - - /* Prepare sum. */ - sum_scale = MAX (n1->n_scale, n2->n_scale); - sum_digits = MAX (n1->n_len, n2->n_len) + 1; - sum = bc_new_num (sum_digits, MAX(sum_scale, scale_min)); - - /* Zero extra digits made by scale_min. */ - if (scale_min > sum_scale) - { - sumptr = (char *) (sum->n_value + sum_scale + sum_digits); - for (count = scale_min - sum_scale; count > 0; count--) - *sumptr++ = 0; - } - - /* Start with the fraction part. Initialize the pointers. */ - n1bytes = n1->n_scale; - n2bytes = n2->n_scale; - n1ptr = (char *) (n1->n_value + n1->n_len + n1bytes - 1); - n2ptr = (char *) (n2->n_value + n2->n_len + n2bytes - 1); - sumptr = (char *) (sum->n_value + sum_scale + sum_digits - 1); - - /* Add the fraction part. First copy the longer fraction.*/ - if (n1bytes != n2bytes) - { - if (n1bytes > n2bytes) - while (n1bytes>n2bytes) - { *sumptr-- = *n1ptr--; n1bytes--;} - else - while (n2bytes>n1bytes) - { *sumptr-- = *n2ptr--; n2bytes--;} - } - - /* Now add the remaining fraction part and equal size integer parts. */ - n1bytes += n1->n_len; - n2bytes += n2->n_len; - carry = 0; - while ((n1bytes > 0) && (n2bytes > 0)) - { - *sumptr = *n1ptr-- + *n2ptr-- + carry; - if (*sumptr > (BASE-1)) - { - carry = 1; - *sumptr -= BASE; + bc_num sum; + size_t sum_scale, sum_digits; + char *n1ptr, *n2ptr, *sumptr; + size_t n1bytes, n2bytes; + bool carry; + + /* Prepare sum. */ + sum_scale = MAX (n1->n_scale, n2->n_scale); + sum_digits = MAX (n1->n_len, n2->n_len) + 1; + sum = bc_new_num (sum_digits, MAX(sum_scale, scale_min)); + + /* Zero extra digits made by scale_min. */ + if (scale_min > sum_scale) { + sumptr = (char *) (sum->n_value + sum_scale + sum_digits); + for (int count = scale_min - sum_scale; count > 0; count--) { + *sumptr++ = 0; + } } - else - carry = 0; - sumptr--; - n1bytes--; - n2bytes--; - } - - /* Now add carry the longer integer part. */ - if (n1bytes == 0) - { n1bytes = n2bytes; n1ptr = n2ptr; } - while (n1bytes-- > 0) - { - *sumptr = *n1ptr-- + carry; - if (*sumptr > (BASE-1)) - { - carry = 1; - *sumptr -= BASE; - } - else + + /* Start with the fraction part. Initialize the pointers. */ + n1bytes = n1->n_scale; + n2bytes = n2->n_scale; + n1ptr = (char *) (n1->n_value + n1->n_len + n1bytes - 1); + n2ptr = (char *) (n2->n_value + n2->n_len + n2bytes - 1); + sumptr = (char *) (sum->n_value + sum_scale + sum_digits - 1); + + /* Add the fraction part. First copy the longer fraction.*/ + if (n1bytes != n2bytes) { + if (n1bytes > n2bytes) { + while (n1bytes>n2bytes) { + *sumptr-- = *n1ptr--; + n1bytes--; + } + } else { + while (n2bytes>n1bytes) { + *sumptr-- = *n2ptr--; + n2bytes--; + } + } + } + + /* Now add the remaining fraction part and equal size integer parts. */ + n1bytes += n1->n_len; + n2bytes += n2->n_len; carry = 0; - sumptr--; - } + while ((n1bytes > 0) && (n2bytes > 0)) { + *sumptr = *n1ptr-- + *n2ptr-- + carry; + if (*sumptr > (BASE-1)) { + carry = 1; + *sumptr -= BASE; + } else { + carry = 0; + } + sumptr--; + n1bytes--; + n2bytes--; + } + + /* Now add carry the longer integer part. */ + if (n1bytes == 0) { + n1bytes = n2bytes; + n1ptr = n2ptr; + } + while (n1bytes-- > 0) { + *sumptr = *n1ptr-- + carry; + if (*sumptr > (BASE-1)) { + carry = true; + *sumptr -= BASE; + } else { + carry = false; + } + sumptr--; + } - /* Set final carry. */ - if (carry == 1) - *sumptr += 1; + /* Set final carry. */ + if (carry) { + *sumptr += 1; + } - /* Adjust sum and return. */ - _bc_rm_leading_zeros (sum); - return sum; + /* Adjust sum and return. */ + _bc_rm_leading_zeros (sum); + return sum; } @@ -130,95 +129,84 @@ bc_num _bc_do_add(bc_num n1, bc_num n2, int scale_min) returned. The signs of N1 and N2 are ignored. Also, N1 is assumed to be larger than N2. SCALE_MIN is the minimum scale of the result. */ - -bc_num _bc_do_sub(bc_num n1, bc_num n2, int scale_min) +bc_num _bc_do_sub(bc_num n1, bc_num n2, size_t scale_min) { - bc_num diff; - int diff_scale, diff_len; - int min_scale, min_len; - char *n1ptr, *n2ptr, *diffptr; - int borrow, count, val; - - /* Allocate temporary storage. */ - diff_len = MAX (n1->n_len, n2->n_len); - diff_scale = MAX (n1->n_scale, n2->n_scale); - min_len = MIN (n1->n_len, n2->n_len); - min_scale = MIN (n1->n_scale, n2->n_scale); - diff = bc_new_num (diff_len, MAX(diff_scale, scale_min)); - - /* Zero extra digits made by scale_min. */ - if (scale_min > diff_scale) - { - diffptr = (char *) (diff->n_value + diff_len + diff_scale); - for (count = scale_min - diff_scale; count > 0; count--) - *diffptr++ = 0; - } - - /* Initialize the subtract. */ - n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale -1); - n2ptr = (char *) (n2->n_value + n2->n_len + n2->n_scale -1); - diffptr = (char *) (diff->n_value + diff_len + diff_scale -1); - - /* Subtract the numbers. */ - borrow = 0; - - /* Take care of the longer scaled number. */ - if (n1->n_scale != min_scale) - { - /* n1 has the longer scale */ - for (count = n1->n_scale - min_scale; count > 0; count--) - *diffptr-- = *n1ptr--; - } - else - { - /* n2 has the longer scale */ - for (count = n2->n_scale - min_scale; count > 0; count--) - { - val = - *n2ptr-- - borrow; - if (val < 0) - { - val += BASE; - borrow = 1; - } - else - borrow = 0; - *diffptr-- = val; + bc_num diff; + int diff_scale, diff_len; + size_t min_scale, min_len; + char *n1ptr, *n2ptr, *diffptr; + int borrow, count, val; + + /* Allocate temporary storage. */ + diff_len = MAX(n1->n_len, n2->n_len); + diff_scale = MAX(n1->n_scale, n2->n_scale); + min_len = MIN(n1->n_len, n2->n_len); + min_scale = MIN(n1->n_scale, n2->n_scale); + diff = bc_new_num (diff_len, MAX(diff_scale, scale_min)); + + /* Zero extra digits made by scale_min. */ + if (scale_min > diff_scale) { + diffptr = (char *) (diff->n_value + diff_len + diff_scale); + for (count = scale_min - diff_scale; count > 0; count--) { + *diffptr++ = 0; + } } - } - /* Now do the equal length scale and integer parts. */ + /* Initialize the subtract. */ + n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale -1); + n2ptr = (char *) (n2->n_value + n2->n_len + n2->n_scale -1); + diffptr = (char *) (diff->n_value + diff_len + diff_scale -1); - for (count = 0; count < min_len + min_scale; count++) - { - val = *n1ptr-- - *n2ptr-- - borrow; - if (val < 0) - { - val += BASE; - borrow = 1; - } - else + /* Subtract the numbers. */ borrow = 0; - *diffptr-- = val; - } - - /* If n1 has more digits then n2, we now do that subtract. */ - if (diff_len != min_len) - { - for (count = diff_len - min_len; count > 0; count--) - { - val = *n1ptr-- - borrow; - if (val < 0) - { - val += BASE; - borrow = 1; - } - else - borrow = 0; - *diffptr-- = val; + + /* Take care of the longer scaled number. */ + if (n1->n_scale != min_scale) { + /* n1 has the longer scale */ + for (count = n1->n_scale - min_scale; count > 0; count--) { + *diffptr-- = *n1ptr--; + } + } else { + /* n2 has the longer scale */ + for (count = n2->n_scale - min_scale; count > 0; count--) { + val = - *n2ptr-- - borrow; + if (val < 0) { + val += BASE; + borrow = 1; + } else { + borrow = 0; + } + *diffptr-- = val; + } + } + + /* Now do the equal length scale and integer parts. */ + for (count = 0; count < min_len + min_scale; count++) { + val = *n1ptr-- - *n2ptr-- - borrow; + if (val < 0) { + val += BASE; + borrow = 1; + } else { + borrow = 0; + } + *diffptr-- = val; + } + + /* If n1 has more digits then n2, we now do that subtract. */ + if (diff_len != min_len) { + for (count = diff_len - min_len; count > 0; count--) { + val = *n1ptr-- - borrow; + if (val < 0) { + val += BASE; + borrow = 1; + } else { + borrow = 0; + } + *diffptr-- = val; + } } - } - /* Clean up and return. */ - _bc_rm_leading_zeros (diff); - return diff; + /* Clean up and return. */ + _bc_rm_leading_zeros (diff); + return diff; } diff --git a/ext/bcmath/libbcmath/src/init.c b/ext/bcmath/libbcmath/src/init.c index 50d6b0653c3bf..ec1d082b5fb3b 100644 --- a/ext/bcmath/libbcmath/src/init.c +++ b/ext/bcmath/libbcmath/src/init.c @@ -29,47 +29,45 @@ *************************************************************************/ -#include -#include -#include -#include -#include #include "bcmath.h" -#include "private.h" +#include +#include +#include "zend_alloc.h" /* new_num allocates a number and sets fields to known values. */ - -bc_num _bc_new_num_ex (int length, int scale, int persistent) +bc_num _bc_new_num_ex(size_t length, size_t scale, bool persistent) { - bc_num temp; - /* PHP Change: malloc() -> pemalloc(), removed free_list code */ - temp = (bc_num) safe_pemalloc (1, sizeof(bc_struct)+length, scale, persistent); - temp->n_sign = PLUS; - temp->n_len = length; - temp->n_scale = scale; - temp->n_refs = 1; - /* PHP Change: malloc() -> pemalloc() */ - temp->n_ptr = (char *) safe_pemalloc (1, length, scale, persistent); - temp->n_value = temp->n_ptr; - memset (temp->n_ptr, 0, length+scale); - return temp; + bc_num temp; + /* PHP Change: malloc() -> pemalloc(), removed free_list code */ + temp = (bc_num) safe_pemalloc (1, sizeof(bc_struct)+length, scale, persistent); + temp->n_sign = PLUS; + temp->n_len = length; + temp->n_scale = scale; + temp->n_refs = 1; + /* PHP Change: malloc() -> pemalloc() */ + temp->n_ptr = (char *) safe_pemalloc (1, length, scale, persistent); + temp->n_value = temp->n_ptr; + memset (temp->n_ptr, 0, length+scale); + return temp; } /* "Frees" a bc_num NUM. Actually decreases reference count and only frees the storage if reference count is zero. */ - -void _bc_free_num_ex(bc_num *num, int persistent) +void _bc_free_num_ex(bc_num *num, bool persistent) { - if (*num == NULL) return; - (*num)->n_refs--; - if ((*num)->n_refs == 0) { - if ((*num)->n_ptr) - /* PHP Change: free() -> pefree(), removed free_list code */ - pefree ((*num)->n_ptr, persistent); - pefree(*num, persistent); - } - *num = NULL; + if (*num == NULL) { + return; + } + (*num)->n_refs--; + if ((*num)->n_refs == 0) { + if ((*num)->n_ptr) { + /* PHP Change: free() -> pefree(), removed free_list code */ + pefree ((*num)->n_ptr, persistent); + } + pefree(*num, persistent); + } + *num = NULL; } @@ -77,26 +75,24 @@ void _bc_free_num_ex(bc_num *num, int persistent) void bc_init_numbers(void) { - BCG(_zero_) = _bc_new_num_ex (1,0,1); - BCG(_one_) = _bc_new_num_ex (1,0,1); - BCG(_one_)->n_value[0] = 1; - BCG(_two_) = _bc_new_num_ex (1,0,1); - BCG(_two_)->n_value[0] = 2; + BCG(_zero_) = _bc_new_num_ex (1,0,1); + BCG(_one_) = _bc_new_num_ex (1,0,1); + BCG(_one_)->n_value[0] = 1; + BCG(_two_) = _bc_new_num_ex (1,0,1); + BCG(_two_)->n_value[0] = 2; } -/* Make a copy of a number! Just increments the reference count! */ - +/* Make a copy of a number! Just increments the reference count! */ bc_num bc_copy_num(bc_num num) { - num->n_refs++; - return num; + num->n_refs++; + return num; } /* Initialize a number NUM by making it a copy of zero. */ - void bc_init_num(bc_num *num) { - *num = bc_copy_num (BCG(_zero_)); + *num = bc_copy_num(BCG(_zero_)); } diff --git a/ext/bcmath/libbcmath/src/int2num.c b/ext/bcmath/libbcmath/src/int2num.c index 7564fa76ac531..e46ab06e2c7d3 100644 --- a/ext/bcmath/libbcmath/src/int2num.c +++ b/ext/bcmath/libbcmath/src/int2num.c @@ -29,46 +29,45 @@ *************************************************************************/ -#include #include "bcmath.h" - /* Convert an integer VAL to a bc number NUM. */ void bc_int2num(bc_num *num, int val) { - char buffer[30]; - char *bptr, *vptr; - int ix = 1; - char neg = 0; + char buffer[30]; + char *bptr, *vptr; + int ix = 1; + char neg = 0; - /* Sign. */ - if (val < 0) - { - neg = 1; - val = -val; - } + /* Sign. */ + if (val < 0) { + neg = 1; + val = -val; + } - /* Get things going. */ - bptr = buffer; - *bptr++ = val % BASE; - val = val / BASE; + /* Get things going. */ + bptr = buffer; + *bptr++ = val % BASE; + val = val / BASE; - /* Extract remaining digits. */ - while (val != 0) - { - *bptr++ = val % BASE; - val = val / BASE; - ix++; /* Count the digits. */ - } + /* Extract remaining digits. */ + while (val != 0) { + *bptr++ = val % BASE; + val = val / BASE; + ix++; /* Count the digits. */ + } - /* Make the number. */ - bc_free_num (num); - *num = bc_new_num (ix, 0); - if (neg) (*num)->n_sign = MINUS; + /* Make the number. */ + bc_free_num (num); + *num = bc_new_num (ix, 0); + if (neg) { + (*num)->n_sign = MINUS; + } - /* Assign the digits. */ - vptr = (*num)->n_value; - while (ix-- > 0) - *vptr++ = *--bptr; + /* Assign the digits. */ + vptr = (*num)->n_value; + while (ix-- > 0) { + *vptr++ = *--bptr; + } } diff --git a/ext/bcmath/libbcmath/src/nearzero.c b/ext/bcmath/libbcmath/src/nearzero.c index c3a826041456a..9cecbdf390654 100644 --- a/ext/bcmath/libbcmath/src/nearzero.c +++ b/ext/bcmath/libbcmath/src/nearzero.c @@ -30,30 +30,32 @@ *************************************************************************/ #include +#include #include "bcmath.h" /* In some places we need to check if the number NUM is almost zero. Specifically, all but the last digit is 0 and the last digit is 1. Last digit is defined by scale. */ -bool bc_is_near_zero(bc_num num, int scale) +bool bc_is_near_zero(bc_num num, size_t scale) { - int count; - char *nptr; - - /* Error checking */ - if (scale > num->n_scale) - scale = num->n_scale; - - /* Initialize */ - count = num->n_len + scale; - nptr = num->n_value; - - /* The check */ - while ((count > 0) && (*nptr++ == 0)) count--; - - if (count != 0 && (count != 1 || *--nptr != 1)) - return false; - else - return true; + /* Error checking */ + if (scale > num->n_scale) { + scale = num->n_scale; + } + + /* Initialize */ + size_t count = num->n_len + scale; + const char *nptr = num->n_value; + + /* The check */ + while ((count > 0) && (*nptr++ == 0)) { + count--; + } + + if (count != 0 && (count != 1 || *--nptr != 1)) { + return false; + } else { + return true; + } } diff --git a/ext/bcmath/libbcmath/src/neg.c b/ext/bcmath/libbcmath/src/neg.c index d8f2cfaed7b67..53c9af713e15b 100644 --- a/ext/bcmath/libbcmath/src/neg.c +++ b/ext/bcmath/libbcmath/src/neg.c @@ -35,5 +35,5 @@ /* In some places we need to check if the number is negative. */ bool bc_is_neg(bc_num num) { - return num->n_sign == MINUS; + return num->n_sign == MINUS; } diff --git a/ext/bcmath/libbcmath/src/num2long.c b/ext/bcmath/libbcmath/src/num2long.c index 322fb3d9c0720..1e0fca68cd530 100644 --- a/ext/bcmath/libbcmath/src/num2long.c +++ b/ext/bcmath/libbcmath/src/num2long.c @@ -29,8 +29,8 @@ *************************************************************************/ -#include #include "bcmath.h" +#include /* Convert a number NUM to a long. The function returns only the integer part of the number. For numbers that are too large to represent as @@ -39,30 +39,30 @@ long bc_num2long(bc_num num) { - long val; - char *nptr; - int index; + long val; + char *nptr; - /* Extract the int value, ignore the fraction. */ - val = 0; - nptr = num->n_value; - for (index = num->n_len; index > 0; index--) { - char n = *nptr++; + /* Extract the int value, ignore the fraction. */ + val = 0; + nptr = num->n_value; + for (size_t index = num->n_len; index > 0; index--) { + char n = *nptr++; - if (val > LONG_MAX/BASE) { - return 0; - } - val *= BASE; + if (val > LONG_MAX/BASE) { + return 0; + } + val *= BASE; - if (val > LONG_MAX - n) { - return 0; - } - val += n; - } + if (val > LONG_MAX - n) { + return 0; + } + val += n; + } - /* Return the value. */ - if (num->n_sign == PLUS) - return (val); - else - return (-val); + /* Return the value. */ + if (num->n_sign == PLUS) { + return (val); + } else { + return (-val); + } } diff --git a/ext/bcmath/libbcmath/src/num2str.c b/ext/bcmath/libbcmath/src/num2str.c index 44b05593c944f..f5667220e783d 100644 --- a/ext/bcmath/libbcmath/src/num2str.c +++ b/ext/bcmath/libbcmath/src/num2str.c @@ -29,29 +29,26 @@ *************************************************************************/ -#include -#include -#include -#include -#include #include "bcmath.h" -#include "private.h" +#include +#include "zend_string.h" /* Convert a numbers to a string. Base 10 only.*/ - -zend_string *bc_num2str_ex(bc_num num, int scale) +zend_string *bc_num2str_ex(bc_num num, size_t scale) { zend_string *str; char *sptr; char *nptr; int index, signch; + /* Number of sign chars. */ + signch = num->n_sign != PLUS && !bc_is_zero_for_scale(num, MIN(num->n_scale, scale)); /* Allocate the string memory. */ - signch = num->n_sign != PLUS && !bc_is_zero_for_scale(num, MIN(num->n_scale, scale)); /* Number of sign chars. */ - if (scale > 0) + if (scale > 0) { str = zend_string_alloc(num->n_len + scale + signch + 1, 0); - else + } else { str = zend_string_alloc(num->n_len + signch, 0); + } /* The negative sign if needed. */ sptr = ZSTR_VAL(str); @@ -59,17 +56,19 @@ zend_string *bc_num2str_ex(bc_num num, int scale) /* Load the whole number. */ nptr = num->n_value; - for (index=num->n_len; index>0; index--) + for (index=num->n_len; index>0; index--) { *sptr++ = BCD_CHAR(*nptr++); + } /* Now the fraction. */ - if (scale > 0) - { + if (scale > 0) { *sptr++ = '.'; - for (index=0; indexn_scale; index++) + for (index=0; indexn_scale; index++) { *sptr++ = BCD_CHAR(*nptr++); - for (index = num->n_scale; indexn_scale; index -#include -#include -#include -#include #include "bcmath.h" -#include "private.h" +#include +#include "zend_alloc.h" /* The following routines provide output for bcd numbers package @@ -58,137 +54,135 @@ static const char ref_str[] = "0123456789ABCDEF"; void bc_out_long (long val, size_t size, bool space, void (*out_char)(char) ) { - char digits[40]; - size_t len, ix; - - if (space) (*out_char) (' '); - snprintf(digits, sizeof(digits), "%ld", val); - len = strlen (digits); - while (size > len) - { - (*out_char) ('0'); - size--; - } - for (ix=0; ix < len; ix++) - (*out_char) (digits[ix]); + char digits[40]; + size_t len, ix; + + if (space) (*out_char) (' '); + snprintf(digits, sizeof(digits), "%ld", val); + len = strlen(digits); + while (size > len) { + (*out_char) ('0'); + size--; + } + for (ix=0; ix < len; ix++) { + (*out_char) (digits[ix]); + } } /* Output of a bcd number. NUM is written in base O_BASE using OUT_CHAR as the routine to do the actual output of the characters. */ -void bc_out_num (bc_num num, int o_base, void (*out_char)(char), int leading_zero) +void bc_out_num (bc_num num, int o_base, void (*out_char)(char), bool leading_zero) { - char *nptr; - int index, fdigit; - bool pre_space; - stk_rec *digits, *temp; - bc_num int_part, frac_part, base, cur_dig, t_num, max_o_digit; - - /* The negative sign if needed. */ - if (num->n_sign == MINUS) (*out_char) ('-'); - - /* Output the number. */ - if (bc_is_zero (num)) - (*out_char) ('0'); - else - if (o_base == 10) - { - /* The number is in base 10, do it the fast way. */ - nptr = num->n_value; - if (num->n_len > 1 || *nptr != 0) - for (index=num->n_len; index>0; index--) - (*out_char) (BCD_CHAR(*nptr++)); - else - nptr++; - - if (leading_zero && bc_is_zero (num)) - (*out_char) ('0'); - - /* Now the fraction. */ - if (num->n_scale > 0) - { - (*out_char) ('.'); - for (index=0; indexn_scale; index++) - (*out_char) (BCD_CHAR(*nptr++)); - } - } - else - { - /* special case ... */ - if (leading_zero && bc_is_zero (num)) - (*out_char) ('0'); - - /* The number is some other base. */ - digits = NULL; - bc_init_num (&int_part); - bc_divide (num, BCG(_one_), &int_part, 0); - bc_init_num (&frac_part); - bc_init_num (&cur_dig); - bc_init_num (&base); - bc_sub (num, int_part, &frac_part, 0); - /* Make the INT_PART and FRAC_PART positive. */ - int_part->n_sign = PLUS; - frac_part->n_sign = PLUS; - bc_int2num (&base, o_base); - bc_init_num (&max_o_digit); - bc_int2num (&max_o_digit, o_base-1); - - - /* Get the digits of the integer part and push them on a stack. */ - while (!bc_is_zero (int_part)) - { - bc_modulo (int_part, base, &cur_dig, 0); - /* PHP Change: malloc() -> emalloc() */ - temp = (stk_rec *) emalloc (sizeof(stk_rec)); - temp->digit = bc_num2long (cur_dig); - temp->next = digits; - digits = temp; - bc_divide (int_part, base, &int_part, 0); - } - - /* Print the digits on the stack. */ - if (digits != NULL) - { - /* Output the digits. */ - while (digits != NULL) - { - temp = digits; - digits = digits->next; - if (o_base <= 16) - (*out_char) (ref_str[ (int) temp->digit]); - else - bc_out_long (temp->digit, max_o_digit->n_len, 1, out_char); - efree (temp); - } - } - - /* Get and print the digits of the fraction part. */ - if (num->n_scale > 0) - { - (*out_char) ('.'); - pre_space = false; - t_num = bc_copy_num (BCG(_one_)); - while (t_num->n_len <= num->n_scale) { - bc_multiply (frac_part, base, &frac_part, num->n_scale); - fdigit = bc_num2long (frac_part); - bc_int2num (&int_part, fdigit); - bc_sub (frac_part, int_part, &frac_part, 0); - if (o_base <= 16) - (*out_char) (ref_str[fdigit]); - else { - bc_out_long (fdigit, max_o_digit->n_len, pre_space, out_char); - pre_space = true; - } - bc_multiply (t_num, base, &t_num, 0); - } - bc_free_num (&t_num); - } - - /* Clean up. */ - bc_free_num (&int_part); - bc_free_num (&frac_part); - bc_free_num (&base); - bc_free_num (&cur_dig); - bc_free_num (&max_o_digit); - } + char *nptr; + int index, fdigit; + bool pre_space; + stk_rec *digits, *temp; + bc_num int_part, frac_part, base, cur_dig, t_num, max_o_digit; + + /* The negative sign if needed. */ + if (num->n_sign == MINUS) (*out_char) ('-'); + + /* Output the number. */ + if (bc_is_zero (num)) { + (*out_char) ('0'); + } else { + if (o_base == 10) { + /* The number is in base 10, do it the fast way. */ + nptr = num->n_value; + if (num->n_len > 1 || *nptr != 0) { + for (index=num->n_len; index>0; index--) { + (*out_char) (BCD_CHAR(*nptr++)); + } + } else { + nptr++; + } + + if (leading_zero && bc_is_zero(num)) { + (*out_char) ('0'); + } + + /* Now the fraction. */ + if (num->n_scale > 0) { + (*out_char) ('.'); + for (index=0; indexn_scale; index++) { + (*out_char) (BCD_CHAR(*nptr++)); + } + } + } else { + /* special case ... */ + if (leading_zero && bc_is_zero (num)) { + (*out_char) ('0'); + } + + /* The number is some other base. */ + digits = NULL; + bc_init_num (&int_part); + bc_divide (num, BCG(_one_), &int_part, 0); + bc_init_num (&frac_part); + bc_init_num (&cur_dig); + bc_init_num (&base); + bc_sub (num, int_part, &frac_part, 0); + /* Make the INT_PART and FRAC_PART positive. */ + int_part->n_sign = PLUS; + frac_part->n_sign = PLUS; + bc_int2num (&base, o_base); + bc_init_num (&max_o_digit); + bc_int2num (&max_o_digit, o_base-1); + + /* Get the digits of the integer part and push them on a stack. */ + while (!bc_is_zero(int_part)) { + bc_modulo (int_part, base, &cur_dig, 0); + /* PHP Change: malloc() -> emalloc() */ + temp = (stk_rec *) emalloc (sizeof(stk_rec)); + temp->digit = bc_num2long (cur_dig); + temp->next = digits; + digits = temp; + bc_divide (int_part, base, &int_part, 0); + } + + /* Print the digits on the stack. */ + if (digits != NULL) { + /* Output the digits. */ + while (digits != NULL) { + temp = digits; + digits = digits->next; + if (o_base <= 16) { + (*out_char) (ref_str[ (int) temp->digit]); + } else { + bc_out_long (temp->digit, max_o_digit->n_len, 1, out_char); + } + efree(temp); + } + } + + /* Get and print the digits of the fraction part. */ + if (num->n_scale > 0) { + (*out_char) ('.'); + pre_space = false; + t_num = bc_copy_num (BCG(_one_)); + while (t_num->n_len <= num->n_scale) { + bc_multiply (frac_part, base, &frac_part, num->n_scale); + fdigit = bc_num2long (frac_part); + bc_int2num (&int_part, fdigit); + bc_sub (frac_part, int_part, &frac_part, 0); + if (o_base <= 16) { + (*out_char) (ref_str[fdigit]); + } else { + bc_out_long (fdigit, max_o_digit->n_len, pre_space, out_char); + pre_space = true; + } + bc_multiply (t_num, base, &t_num, 0); + } + bc_free_num (&t_num); + } + + /* Clean up. */ + bc_free_num (&int_part); + bc_free_num (&frac_part); + bc_free_num (&base); + bc_free_num (&cur_dig); + bc_free_num (&max_o_digit); + } + } } diff --git a/ext/bcmath/libbcmath/src/private.h b/ext/bcmath/libbcmath/src/private.h index aa2459563822c..92db802eb4582 100644 --- a/ext/bcmath/libbcmath/src/private.h +++ b/ext/bcmath/libbcmath/src/private.h @@ -32,9 +32,10 @@ /* "Private" routines to bcmath. */ #include +#include /* routines */ int _bc_do_compare (bc_num n1, bc_num n2, bool use_sign, bool ignore_last); -bc_num _bc_do_add (bc_num n1, bc_num n2, int scale_min); -bc_num _bc_do_sub (bc_num n1, bc_num n2, int scale_min); +bc_num _bc_do_add (bc_num n1, bc_num n2, size_t scale_min); +bc_num _bc_do_sub (bc_num n1, bc_num n2, size_t scale_min); void _bc_rm_leading_zeros (bc_num num); diff --git a/ext/bcmath/libbcmath/src/raise.c b/ext/bcmath/libbcmath/src/raise.c index 2e843f179a6d6..4560e4e6916a5 100644 --- a/ext/bcmath/libbcmath/src/raise.c +++ b/ext/bcmath/libbcmath/src/raise.c @@ -29,100 +29,91 @@ *************************************************************************/ -#include -#include -#include -#include -#include #include "bcmath.h" -#include "private.h" +#include +#include +#include /* Raise NUM1 to the NUM2 power. The result is placed in RESULT. Maximum exponent is LONG_MAX. If a NUM2 is not an integer, only the integer part is used. */ -void -bc_raise (bc_num num1, bc_num num2, bc_num *result, int scale) +void bc_raise(bc_num num1, long exponent, bc_num *result, size_t scale) { - bc_num temp, power; - long exponent; - int rscale; - int pwrscale; - int calcscale; - char neg; - - /* Check the exponent for scale digits and convert to a long. */ - if (num2->n_scale != 0) { - /* 2nd argument from PHP_FUNCTION(bcpow) */ - zend_argument_value_error(2, "cannot have a fractional part"); + bc_num temp, power; + size_t rscale; + size_t pwrscale; + size_t calcscale; + bool is_neg; + + /* Special case if exponent is a zero. */ + if (exponent == 0) { + bc_free_num (result); + *result = bc_copy_num (BCG(_one_)); return; } - exponent = bc_num2long (num2); - if (exponent == 0 && (num2->n_len > 1 || num2->n_value[0] != 0)) { - /* 2nd argument from PHP_FUNCTION(bcpow) */ - zend_argument_value_error(2, "is too large"); - return; + + /* Other initializations. */ + if (exponent < 0) { + is_neg = true; + exponent = -exponent; + rscale = scale; + } else { + is_neg = false; + rscale = MIN (num1->n_scale*exponent, MAX(scale, num1->n_scale)); + } + + /* Set initial value of temp. */ + power = bc_copy_num (num1); + pwrscale = num1->n_scale; + while ((exponent & 1) == 0) { + pwrscale = 2*pwrscale; + bc_multiply (power, power, &power, pwrscale); + exponent = exponent >> 1; + } + temp = bc_copy_num (power); + calcscale = pwrscale; + exponent = exponent >> 1; + + /* Do the calculation. */ + while (exponent > 0) { + pwrscale = 2*pwrscale; + bc_multiply (power, power, &power, pwrscale); + if ((exponent & 1) == 1) { + calcscale = pwrscale + calcscale; + bc_multiply (temp, power, &temp, calcscale); + } + exponent = exponent >> 1; } - /* Special case if exponent is a zero. */ - if (exponent == 0) - { - bc_free_num (result); - *result = bc_copy_num (BCG(_one_)); - return; - } - - /* Other initializations. */ - if (exponent < 0) - { - neg = TRUE; - exponent = -exponent; - rscale = scale; - } - else - { - neg = FALSE; - rscale = MIN (num1->n_scale*exponent, MAX(scale, num1->n_scale)); - } - - /* Set initial value of temp. */ - power = bc_copy_num (num1); - pwrscale = num1->n_scale; - while ((exponent & 1) == 0) - { - pwrscale = 2*pwrscale; - bc_multiply (power, power, &power, pwrscale); - exponent = exponent >> 1; - } - temp = bc_copy_num (power); - calcscale = pwrscale; - exponent = exponent >> 1; - - /* Do the calculation. */ - while (exponent > 0) - { - pwrscale = 2*pwrscale; - bc_multiply (power, power, &power, pwrscale); - if ((exponent & 1) == 1) { - calcscale = pwrscale + calcscale; - bc_multiply (temp, power, &temp, calcscale); - } - exponent = exponent >> 1; - } - - /* Assign the value. */ - if (neg) - { - bc_divide (BCG(_one_), temp, result, rscale); - bc_free_num (&temp); - } - else - { - bc_free_num (result); - *result = temp; - if ((*result)->n_scale > rscale) - (*result)->n_scale = rscale; - } - bc_free_num (&power); + /* Assign the value. */ + if (is_neg) { + bc_divide (BCG(_one_), temp, result, rscale); + bc_free_num (&temp); + } else { + bc_free_num (result); + *result = temp; + if ((*result)->n_scale > rscale) { + (*result)->n_scale = rscale; + } + } + bc_free_num (&power); } + +/* This is used internally by BCMath */ +void bc_raise_bc_exponent(bc_num base, bc_num expo, bc_num *result, size_t scale) +{ + /* Exponent must not have fractional part */ + assert(expo->n_scale == 0); + + long exponent = bc_num2long(expo); + /* Exponent must be properly convertable to long */ + if (exponent == 0 && (expo->n_len > 1 || expo->n_value[0] != 0)) { + assert(false && "Exponent is not well formed in internal call"); + //assert(exponent != 0 || (expo->n_len == 0 && expo->n_value[0] == 0)); + } + //assert(exponent != 0 || (expo->n_len == 0 && expo->n_value[0] == 0)); + bc_raise(base, exponent, result, scale); +} + diff --git a/ext/bcmath/libbcmath/src/raisemod.c b/ext/bcmath/libbcmath/src/raisemod.c index bb0d16f6f0a55..badee6fca6faa 100644 --- a/ext/bcmath/libbcmath/src/raisemod.c +++ b/ext/bcmath/libbcmath/src/raisemod.c @@ -29,85 +29,65 @@ *************************************************************************/ -#include -#include -#include -#include -#include #include "bcmath.h" -#include "private.h" -#include "zend_exceptions.h" +#include /* Raise BASE to the EXPO power, reduced modulo MOD. The result is placed in RESULT. */ -zend_result bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale) +raise_mod_status bc_raisemod(bc_num base, bc_num expo, bc_num mod, bc_num *result, size_t scale) { - bc_num power, exponent, modulus, parity, temp; - int rscale; + bc_num power, exponent, modulus, parity, temp; + size_t rscale; /* Check the base for scale digits. */ if (base->n_scale != 0) { - /* 1st argument from PHP_FUNCTION(bcpowmod) */ - zend_argument_value_error(1, "cannot have a fractional part"); - return FAILURE; - } + return BASE_HAS_FRACTIONAL; + } /* Check the exponent for scale digits. */ if (expo->n_scale != 0) { - /* 2nd argument from PHP_FUNCTION(bcpowmod) */ - zend_argument_value_error(2, "cannot have a fractional part"); - return FAILURE; - } + return EXPO_HAS_FRACTIONAL; + } if (bc_is_neg(expo)) { - zend_argument_value_error(2, "must be greater than or equal to 0"); - return FAILURE; + return EXPO_IS_NEGATIVE; } /* Check the modulus for scale digits. */ if (mod->n_scale != 0) { - /* 3rd argument from PHP_FUNCTION(bcpowmod) */ - zend_argument_value_error(3, "cannot have a fractional part"); - return FAILURE; - } - /* Modulus cannot be 0 */ + return MOD_HAS_FRACTIONAL; + } + /* Modulus cannot be 0 */ if (bc_is_zero(mod)) { - zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero"); - return FAILURE; + return MOD_IS_ZERO; } - /* Set initial values. */ - power = bc_copy_num (base); - exponent = bc_copy_num (expo); - modulus = bc_copy_num (mod); - temp = bc_copy_num (BCG(_one_)); - bc_init_num(&parity); - - /* Do the calculation. */ - rscale = MAX(scale, power->n_scale); - if ( !bc_compare(modulus, BCG(_one_)) ) - { - bc_free_num (&temp); - temp = bc_new_num (1, scale); - } - else - { - while ( !bc_is_zero(exponent) ) - { - (void) bc_divmod (exponent, BCG(_two_), &exponent, &parity, 0); - if ( !bc_is_zero(parity) ) - { - bc_multiply (temp, power, &temp, rscale); - (void) bc_modulo (temp, modulus, &temp, scale); - } + /* Set initial values. */ + power = bc_copy_num (base); + exponent = bc_copy_num (expo); + modulus = bc_copy_num (mod); + temp = bc_copy_num (BCG(_one_)); + bc_init_num(&parity); - bc_multiply (power, power, &power, rscale); - (void) bc_modulo (power, modulus, &power, scale); + /* Do the calculation. */ + rscale = MAX(scale, power->n_scale); + if ( !bc_compare(modulus, BCG(_one_)) ) { + bc_free_num (&temp); + temp = bc_new_num (1, scale); + } else { + while ( !bc_is_zero(exponent) ) { + (void) bc_divmod (exponent, BCG(_two_), &exponent, &parity, 0); + if ( !bc_is_zero(parity) ) { + bc_multiply (temp, power, &temp, rscale); + (void) bc_modulo (temp, modulus, &temp, scale); + } + bc_multiply (power, power, &power, rscale); + (void) bc_modulo (power, modulus, &power, scale); + } } - } - /* Assign the value. */ - bc_free_num (&power); - bc_free_num (&exponent); - bc_free_num (&modulus); - bc_free_num (result); - bc_free_num (&parity); - *result = temp; - return SUCCESS; /* Everything is OK. */ + /* Assign the value. */ + bc_free_num (&power); + bc_free_num (&exponent); + bc_free_num (&modulus); + bc_free_num (result); + bc_free_num (&parity); + *result = temp; + return OK; } diff --git a/ext/bcmath/libbcmath/src/recmul.c b/ext/bcmath/libbcmath/src/recmul.c index 5217bf4b7c083..0a4563d10b204 100644 --- a/ext/bcmath/libbcmath/src/recmul.c +++ b/ext/bcmath/libbcmath/src/recmul.c @@ -29,10 +29,12 @@ *************************************************************************/ -#include -#include #include "bcmath.h" -#include "private.h" +#include +#include +#include +#include "private.h" /* For _bc_rm_leading_zeros() */ +#include "zend_alloc.h" /* Recursive vs non-recursive multiply crossover ranges. */ #if defined(MULDIGITS) @@ -46,49 +48,49 @@ int mul_base_digits = MUL_BASE_DIGITS; /* Multiply utility routines */ -static bc_num new_sub_num(int length, int scale, char *value) +static bc_num new_sub_num(size_t length, size_t scale, char *value) { - bc_num temp; + bc_num temp; - temp = (bc_num) emalloc (sizeof(bc_struct)); + temp = (bc_num) emalloc (sizeof(bc_struct)); - temp->n_sign = PLUS; - temp->n_len = length; - temp->n_scale = scale; - temp->n_refs = 1; - temp->n_ptr = NULL; - temp->n_value = value; - return temp; + temp->n_sign = PLUS; + temp->n_len = length; + temp->n_scale = scale; + temp->n_refs = 1; + temp->n_ptr = NULL; + temp->n_value = value; + return temp; } -static void -_bc_simp_mul (bc_num n1, int n1len, bc_num n2, int n2len, bc_num *prod, - int full_scale) +static void _bc_simp_mul(bc_num n1, size_t n1len, bc_num n2, int n2len, bc_num *prod) { - char *n1ptr, *n2ptr, *pvptr; - char *n1end, *n2end; /* To the end of n1 and n2. */ - int indx, sum, prodlen; - - prodlen = n1len+n2len+1; - - *prod = bc_new_num (prodlen, 0); - - n1end = (char *) (n1->n_value + n1len - 1); - n2end = (char *) (n2->n_value + n2len - 1); - pvptr = (char *) ((*prod)->n_value + prodlen - 1); - sum = 0; - - /* Here is the loop... */ - for (indx = 0; indx < prodlen-1; indx++) - { - n1ptr = (char *) (n1end - MAX(0, indx-n2len+1)); - n2ptr = (char *) (n2end - MIN(indx, n2len-1)); - while ((n1ptr >= n1->n_value) && (n2ptr <= n2end)) - sum += *n1ptr-- * *n2ptr++; - *pvptr-- = sum % BASE; - sum = sum / BASE; - } - *pvptr = sum; + char *n1ptr, *n2ptr, *pvptr; + char *n1end, *n2end; /* To the end of n1 and n2. */ + int indx, sum, prodlen; + + prodlen = n1len+n2len+1; + + *prod = bc_new_num (prodlen, 0); + + n1end = (char *) (n1->n_value + n1len - 1); + n2end = (char *) (n2->n_value + n2len - 1); + pvptr = (char *) ((*prod)->n_value + prodlen - 1); + sum = 0; + + /* Here is the loop... */ + for (indx = 0; indx < prodlen-1; indx++) { + n1ptr = (char *) (n1end - MAX(0, indx-n2len+1)); + n2ptr = (char *) (n2end - MIN(indx, n2len-1)); + while ((n1ptr >= n1->n_value) && (n2ptr <= n2end)) { + sum += *n1ptr * *n2ptr; + n1ptr--; + n2ptr++; + } + *pvptr-- = sum % BASE; + sum = sum / BASE; + } + *pvptr = sum; } @@ -96,62 +98,62 @@ _bc_simp_mul (bc_num n1, int n1len, bc_num n2, int n2len, bc_num *prod, multiply algorithm. Note: if sub is called, accum must be larger that what is being subtracted. Also, accum and val must have n_scale = 0. (e.g. they must look like integers. *) */ -static void -_bc_shift_addsub (bc_num accum, bc_num val, int shift, int sub) +static void _bc_shift_addsub (bc_num accum, bc_num val, int shift, bool sub) { - signed char *accp, *valp; - int count, carry; - - count = val->n_len; - if (val->n_value[0] == 0) - count--; - assert (accum->n_len+accum->n_scale >= shift+count); - - /* Set up pointers and others */ - accp = (signed char *)(accum->n_value + - accum->n_len + accum->n_scale - shift - 1); - valp = (signed char *)(val->n_value + val->n_len - 1); - carry = 0; - - if (sub) { - /* Subtraction, carry is really borrow. */ - while (count--) { - *accp -= *valp-- + carry; - if (*accp < 0) { - carry = 1; - *accp-- += BASE; - } else { - carry = 0; - accp--; - } - } - while (carry) { - *accp -= carry; - if (*accp < 0) - *accp-- += BASE; - else - carry = 0; - } - } else { - /* Addition */ - while (count--) { - *accp += *valp-- + carry; - if (*accp > (BASE-1)) { - carry = 1; - *accp-- -= BASE; - } else { - carry = 0; - accp--; - } - } - while (carry) { - *accp += carry; - if (*accp > (BASE-1)) - *accp-- -= BASE; - else - carry = 0; - } - } + signed char *accp, *valp; + unsigned int carry = 0; + size_t count = val->n_len; + + if (val->n_value[0] == 0) { + count--; + } + assert(accum->n_len+accum->n_scale >= shift+count); + + /* Set up pointers and others */ + accp = (signed char *)(accum->n_value + accum->n_len + accum->n_scale - shift - 1); + valp = (signed char *)(val->n_value + val->n_len - 1); + + if (sub) { + /* Subtraction, carry is really borrow. */ + while (count--) { + *accp -= *valp-- + carry; + if (*accp < 0) { + carry = 1; + *accp-- += BASE; + } else { + carry = 0; + accp--; + } + } + while (carry) { + *accp -= carry; + if (*accp < 0) { + *accp-- += BASE; + } else { + carry = 0; + } + } + } else { + /* Addition */ + while (count--) { + *accp += *valp-- + carry; + if (*accp > (BASE-1)) { + carry = 1; + *accp-- -= BASE; + } else { + carry = 0; + accp--; + } + } + while (carry) { + *accp += carry; + if (*accp > (BASE-1)) { + *accp-- -= BASE; + } else { + carry = 0; + } + } + } } /* Recursive divide and conquer multiply algorithm. @@ -162,126 +164,128 @@ _bc_shift_addsub (bc_num accum, bc_num val, int shift, int sub) B is the base of storage, number of digits in u1,u0 close to equal. */ -static void -_bc_rec_mul (bc_num u, int ulen, bc_num v, int vlen, bc_num *prod, - int full_scale) +static void _bc_rec_mul(bc_num u, size_t ulen, bc_num v, size_t vlen, bc_num *prod) { - bc_num u0, u1, v0, v1; - bc_num m1, m2, m3, d1, d2; - int n, prodlen, m1zero; - int d1len, d2len; - - /* Base case? */ - if ((ulen+vlen) < mul_base_digits - || ulen < MUL_SMALL_DIGITS - || vlen < MUL_SMALL_DIGITS ) { - _bc_simp_mul (u, ulen, v, vlen, prod, full_scale); - return; - } - - /* Calculate n -- the u and v split point in digits. */ - n = (MAX(ulen, vlen)+1) / 2; - - /* Split u and v. */ - if (ulen < n) { - u1 = bc_copy_num (BCG(_zero_)); - u0 = new_sub_num (ulen,0, u->n_value); - } else { - u1 = new_sub_num (ulen-n, 0, u->n_value); - u0 = new_sub_num (n, 0, u->n_value+ulen-n); - } - if (vlen < n) { - v1 = bc_copy_num (BCG(_zero_)); - v0 = new_sub_num (vlen,0, v->n_value); - } else { - v1 = new_sub_num (vlen-n, 0, v->n_value); - v0 = new_sub_num (n, 0, v->n_value+vlen-n); - } - _bc_rm_leading_zeros (u1); - _bc_rm_leading_zeros (u0); - _bc_rm_leading_zeros (v1); - _bc_rm_leading_zeros (v0); - - m1zero = bc_is_zero(u1) || bc_is_zero(v1); - - /* Calculate sub results ... */ - - bc_init_num(&d1); - bc_init_num(&d2); - bc_sub (u1, u0, &d1, 0); - d1len = d1->n_len; - bc_sub (v0, v1, &d2, 0); - d2len = d2->n_len; - - - /* Do recursive multiplies and shifted adds. */ - if (m1zero) - m1 = bc_copy_num (BCG(_zero_)); - else - _bc_rec_mul (u1, u1->n_len, v1, v1->n_len, &m1, 0); - - if (bc_is_zero(d1) || bc_is_zero(d2)) - m2 = bc_copy_num (BCG(_zero_)); - else - _bc_rec_mul (d1, d1len, d2, d2len, &m2, 0); - - if (bc_is_zero(u0) || bc_is_zero(v0)) - m3 = bc_copy_num (BCG(_zero_)); - else - _bc_rec_mul (u0, u0->n_len, v0, v0->n_len, &m3, 0); - - /* Initialize product */ - prodlen = ulen+vlen+1; - *prod = bc_new_num(prodlen, 0); - - if (!m1zero) { - _bc_shift_addsub (*prod, m1, 2*n, 0); - _bc_shift_addsub (*prod, m1, n, 0); - } - _bc_shift_addsub (*prod, m3, n, 0); - _bc_shift_addsub (*prod, m3, 0, 0); - _bc_shift_addsub (*prod, m2, n, d1->n_sign != d2->n_sign); - - /* Now clean up! */ - bc_free_num (&u1); - bc_free_num (&u0); - bc_free_num (&v1); - bc_free_num (&m1); - bc_free_num (&v0); - bc_free_num (&m2); - bc_free_num (&m3); - bc_free_num (&d1); - bc_free_num (&d2); + bc_num u0, u1, v0, v1; + bc_num m1, m2, m3, d1, d2; + int n, prodlen, m1zero; + int d1len, d2len; + + /* Base case? */ + if ((ulen+vlen) < mul_base_digits + || ulen < MUL_SMALL_DIGITS + || vlen < MUL_SMALL_DIGITS + ) { + _bc_simp_mul (u, ulen, v, vlen, prod); + return; + } + + /* Calculate n -- the u and v split point in digits. */ + n = (MAX(ulen, vlen)+1) / 2; + + /* Split u and v. */ + if (ulen < n) { + u1 = bc_copy_num (BCG(_zero_)); + u0 = new_sub_num (ulen,0, u->n_value); + } else { + u1 = new_sub_num (ulen-n, 0, u->n_value); + u0 = new_sub_num (n, 0, u->n_value+ulen-n); + } + if (vlen < n) { + v1 = bc_copy_num (BCG(_zero_)); + v0 = new_sub_num (vlen,0, v->n_value); + } else { + v1 = new_sub_num (vlen-n, 0, v->n_value); + v0 = new_sub_num (n, 0, v->n_value+vlen-n); + } + _bc_rm_leading_zeros (u1); + _bc_rm_leading_zeros (u0); + _bc_rm_leading_zeros (v1); + _bc_rm_leading_zeros (v0); + + m1zero = bc_is_zero(u1) || bc_is_zero(v1); + + /* Calculate sub results ... */ + + bc_init_num(&d1); + bc_init_num(&d2); + bc_sub (u1, u0, &d1, 0); + d1len = d1->n_len; + bc_sub (v0, v1, &d2, 0); + d2len = d2->n_len; + + + /* Do recursive multiplies and shifted adds. */ + if (m1zero) { + m1 = bc_copy_num (BCG(_zero_)); + } else { + _bc_rec_mul (u1, u1->n_len, v1, v1->n_len, &m1); + } + + if (bc_is_zero(d1) || bc_is_zero(d2)) { + m2 = bc_copy_num (BCG(_zero_)); + } else { + _bc_rec_mul (d1, d1len, d2, d2len, &m2); + } + + if (bc_is_zero(u0) || bc_is_zero(v0)) { + m3 = bc_copy_num (BCG(_zero_)); + } else { + _bc_rec_mul (u0, u0->n_len, v0, v0->n_len, &m3); + } + + /* Initialize product */ + prodlen = ulen+vlen+1; + *prod = bc_new_num(prodlen, 0); + + if (!m1zero) { + _bc_shift_addsub (*prod, m1, 2*n, 0); + _bc_shift_addsub (*prod, m1, n, 0); + } + _bc_shift_addsub (*prod, m3, n, 0); + _bc_shift_addsub (*prod, m3, 0, 0); + _bc_shift_addsub (*prod, m2, n, d1->n_sign != d2->n_sign); + + /* Now clean up! */ + bc_free_num (&u1); + bc_free_num (&u0); + bc_free_num (&v1); + bc_free_num (&m1); + bc_free_num (&v0); + bc_free_num (&m2); + bc_free_num (&m3); + bc_free_num (&d1); + bc_free_num (&d2); } /* The multiply routine. N2 times N1 is put int PROD with the scale of the result being MIN(N2 scale+N1 scale, MAX (SCALE, N2 scale, N1 scale)). */ -void -bc_multiply (bc_num n1, bc_num n2, bc_num *prod, int scale) +void bc_multiply(bc_num n1, bc_num n2, bc_num *prod, size_t scale) { - bc_num pval; - int len1, len2; - int full_scale, prod_scale; - - /* Initialize things. */ - len1 = n1->n_len + n1->n_scale; - len2 = n2->n_len + n2->n_scale; - full_scale = n1->n_scale + n2->n_scale; - prod_scale = MIN(full_scale,MAX(scale,MAX(n1->n_scale,n2->n_scale))); - - /* Do the multiply */ - _bc_rec_mul (n1, len1, n2, len2, &pval, full_scale); - - /* Assign to prod and clean up the number. */ - pval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS ); - pval->n_value = pval->n_ptr; - pval->n_len = len2 + len1 + 1 - full_scale; - pval->n_scale = prod_scale; - _bc_rm_leading_zeros (pval); - if (bc_is_zero (pval)) - pval->n_sign = PLUS; - bc_free_num (prod); - *prod = pval; + bc_num pval; + size_t len1, len2; + size_t full_scale, prod_scale; + + /* Initialize things. */ + len1 = n1->n_len + n1->n_scale; + len2 = n2->n_len + n2->n_scale; + full_scale = n1->n_scale + n2->n_scale; + prod_scale = MIN(full_scale,MAX(scale,MAX(n1->n_scale,n2->n_scale))); + + /* Do the multiply */ + _bc_rec_mul (n1, len1, n2, len2, &pval); + + /* Assign to prod and clean up the number. */ + pval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS ); + pval->n_value = pval->n_ptr; + pval->n_len = len2 + len1 + 1 - full_scale; + pval->n_scale = prod_scale; + _bc_rm_leading_zeros(pval); + if (bc_is_zero(pval)) { + pval->n_sign = PLUS; + } + bc_free_num(prod); + *prod = pval; } diff --git a/ext/bcmath/libbcmath/src/rmzero.c b/ext/bcmath/libbcmath/src/rmzero.c index 6aad96a978ea3..c2e749bec43a8 100644 --- a/ext/bcmath/libbcmath/src/rmzero.c +++ b/ext/bcmath/libbcmath/src/rmzero.c @@ -29,7 +29,6 @@ *************************************************************************/ -#include #include "bcmath.h" #include "private.h" @@ -39,9 +38,9 @@ void _bc_rm_leading_zeros(bc_num num) { - /* We can move n_value to point to the first non zero digit! */ - while (*num->n_value == 0 && num->n_len > 1) { - num->n_value++; - num->n_len--; - } + /* We can move n_value to point to the first non zero digit! */ + while (*num->n_value == 0 && num->n_len > 1) { + num->n_value++; + num->n_len--; + } } diff --git a/ext/bcmath/libbcmath/src/sqrt.c b/ext/bcmath/libbcmath/src/sqrt.c index 59ef960466c3d..d28838b155358 100644 --- a/ext/bcmath/libbcmath/src/sqrt.c +++ b/ext/bcmath/libbcmath/src/sqrt.c @@ -29,89 +29,87 @@ *************************************************************************/ -#include -#include #include "bcmath.h" -#include "private.h" +#include +#include /* Take the square root NUM and return it in NUM with SCALE digits after the decimal place. */ -bool bc_sqrt(bc_num *num, int scale) +bool bc_sqrt(bc_num *num, size_t scale) { - int rscale, cmp_res; - int cscale; - bc_num guess, guess1, point5, diff; - - /* Initial checks. */ - cmp_res = bc_compare (*num, BCG(_zero_)); - if (cmp_res < 0) { - return false; /* error */ - } else { - if (cmp_res == 0) { - bc_free_num (num); - *num = bc_copy_num (BCG(_zero_)); - return true; + /* Initial checks. */ + int cmp_res = bc_compare (*num, BCG(_zero_)); + if (cmp_res < 0) { + return false; /* error */ + } else { + if (cmp_res == 0) { + bc_free_num (num); + *num = bc_copy_num (BCG(_zero_)); + return true; + } + } + cmp_res = bc_compare (*num, BCG(_one_)); + if (cmp_res == 0) { + bc_free_num (num); + *num = bc_copy_num (BCG(_one_)); + return true; + } + + /* Initialize the variables. */ + size_t rscale; + size_t cscale; + bc_num guess, guess1, point5, diff; + + rscale = MAX (scale, (*num)->n_scale); + bc_init_num(&guess1); + bc_init_num(&diff); + point5 = bc_new_num (1,1); + point5->n_value[1] = 5; + + + /* Calculate the initial guess. */ + if (cmp_res < 0) { + /* The number is between 0 and 1. Guess should start at 1. */ + guess = bc_copy_num (BCG(_one_)); + cscale = (*num)->n_scale; + } else { + /* The number is greater than 1. Guess should start at 10^(exp/2). */ + bc_init_num(&guess); + bc_int2num (&guess,10); + + bc_int2num (&guess1,(*num)->n_len); + bc_multiply (guess1, point5, &guess1, 0); + guess1->n_scale = 0; + bc_raise_bc_exponent(guess, guess1, &guess, 0); + bc_free_num (&guess1); + cscale = 3; + } + + /* Find the square root using Newton's algorithm. */ + bool done = false; + while (!done) { + bc_free_num (&guess1); + guess1 = bc_copy_num (guess); + bc_divide (*num, guess, &guess, cscale); + bc_add (guess, guess1, &guess, 0); + bc_multiply (guess, point5, &guess, cscale); + bc_sub (guess, guess1, &diff, cscale+1); + if (bc_is_near_zero (diff, cscale)) { + if (cscale < rscale+1) { + cscale = MIN (cscale*3, rscale+1); + } else { + done = true; + } + } } - } - cmp_res = bc_compare (*num, BCG(_one_)); - if (cmp_res == 0) - { - bc_free_num (num); - *num = bc_copy_num (BCG(_one_)); - return true; - } - - /* Initialize the variables. */ - rscale = MAX (scale, (*num)->n_scale); - bc_init_num(&guess1); - bc_init_num(&diff); - point5 = bc_new_num (1,1); - point5->n_value[1] = 5; - - - /* Calculate the initial guess. */ - if (cmp_res < 0) { - /* The number is between 0 and 1. Guess should start at 1. */ - guess = bc_copy_num (BCG(_one_)); - cscale = (*num)->n_scale; - } else { - /* The number is greater than 1. Guess should start at 10^(exp/2). */ - bc_init_num(&guess); - bc_int2num (&guess,10); - - bc_int2num (&guess1,(*num)->n_len); - bc_multiply (guess1, point5, &guess1, 0); - guess1->n_scale = 0; - bc_raise (guess, guess1, &guess, 0); - bc_free_num (&guess1); - cscale = 3; - } - - /* Find the square root using Newton's algorithm. */ - bool done = false; - while (!done) { - bc_free_num (&guess1); - guess1 = bc_copy_num (guess); - bc_divide (*num, guess, &guess, cscale); - bc_add (guess, guess1, &guess, 0); - bc_multiply (guess, point5, &guess, cscale); - bc_sub (guess, guess1, &diff, cscale+1); - if (bc_is_near_zero (diff, cscale)) { - if (cscale < rscale+1) { - cscale = MIN (cscale*3, rscale+1); - } else { - done = true; - } - } - } - - /* Assign the number and clean up. */ - bc_free_num (num); - bc_divide (guess,BCG(_one_),num,rscale); - bc_free_num (&guess); - bc_free_num (&guess1); - bc_free_num (&point5); - bc_free_num (&diff); - return true; + + /* Assign the number and clean up. */ + bc_free_num (num); + bc_divide (guess,BCG(_one_),num,rscale); + bc_free_num (&guess); + bc_free_num (&guess1); + bc_free_num (&point5); + bc_free_num (&diff); + return true; } diff --git a/ext/bcmath/libbcmath/src/str2num.c b/ext/bcmath/libbcmath/src/str2num.c index 22cebaf57d933..f073c1d5a84b1 100644 --- a/ext/bcmath/libbcmath/src/str2num.c +++ b/ext/bcmath/libbcmath/src/str2num.c @@ -29,84 +29,95 @@ *************************************************************************/ -#include -#include -#include -#include -#include #include "bcmath.h" -#include "private.h" +#include +#include /* Convert strings to bc numbers. Base 10 only.*/ -int -bc_str2num (bc_num *num, char *str, int scale) +bool bc_str2num (bc_num *num, char *str, size_t scale) { - int digits, strscale; - char *ptr, *nptr; - char zero_int; - - /* Prepare num. */ - bc_free_num (num); - - /* Check for valid number and count digits. */ - ptr = str; - digits = 0; - strscale = 0; - zero_int = FALSE; - if ( (*ptr == '+') || (*ptr == '-')) ptr++; /* Sign */ - while (*ptr == '0') ptr++; /* Skip leading zeros. */ - while (*ptr >= '0' && *ptr <= '9') ptr++, digits++; /* digits */ - if (*ptr == '.') ptr++; /* decimal point */ - while (*ptr >= '0' && *ptr <= '9') ptr++, strscale++; /* digits */ - if ((*ptr != '\0') || (digits+strscale == 0)) - { - *num = bc_copy_num (BCG(_zero_)); - return *ptr == '\0'; - } - - /* Adjust numbers and allocate storage and initialize fields. */ - strscale = MIN(strscale, scale); - if (digits == 0) - { - zero_int = TRUE; - digits = 1; - } - *num = bc_new_num (digits, strscale); - - /* Build the whole number. */ - ptr = str; - if (*ptr == '-') - { - (*num)->n_sign = MINUS; - ptr++; - } - else - { - (*num)->n_sign = PLUS; - if (*ptr == '+') ptr++; - } - while (*ptr == '0') ptr++; /* Skip leading zeros. */ - nptr = (*num)->n_value; - if (zero_int) - { - *nptr++ = 0; - digits = 0; - } - for (;digits > 0; digits--) - *nptr++ = CH_VAL(*ptr++); - - - /* Build the fractional part. */ - if (strscale > 0) - { - ptr++; /* skip the decimal point! */ - for (;strscale > 0; strscale--) - *nptr++ = CH_VAL(*ptr++); - } - - if (bc_is_zero (*num)) - (*num)->n_sign = PLUS; - - return 1; + size_t digits, strscale; + char *ptr, *nptr; + bool zero_int = false; + + /* Prepare num. */ + bc_free_num (num); + + /* Check for valid number and count digits. */ + ptr = str; + digits = 0; + strscale = 0; + + if ( (*ptr == '+') || (*ptr == '-')) { + /* Skip Sign */ + ptr++; + } + /* Skip leading zeros. */ + while (*ptr == '0') { + ptr++; + } + /* digits before the decimal point */ + while (*ptr >= '0' && *ptr <= '9') { + ptr++; + digits++; + } + /* decimal point */ + if (*ptr == '.') { + ptr++; + } + /* digits after the decimal point */ + while (*ptr >= '0' && *ptr <= '9') { + ptr++; + strscale++; + } + if ((*ptr != '\0') || (digits+strscale == 0)) { + *num = bc_copy_num (BCG(_zero_)); + return *ptr == '\0'; + } + + /* Adjust numbers and allocate storage and initialize fields. */ + strscale = MIN(strscale, scale); + if (digits == 0) { + zero_int = true; + digits = 1; + } + *num = bc_new_num (digits, strscale); + + /* Build the whole number. */ + ptr = str; + if (*ptr == '-') { + (*num)->n_sign = MINUS; + ptr++; + } else { + (*num)->n_sign = PLUS; + if (*ptr == '+') ptr++; + } + /* Skip leading zeros. */ + while (*ptr == '0') { + ptr++; + } + nptr = (*num)->n_value; + if (zero_int) { + *nptr++ = 0; + digits = 0; + } + for (;digits > 0; digits--) { + *nptr++ = CH_VAL(*ptr++); + } + + /* Build the fractional part. */ + if (strscale > 0) { + /* skip the decimal point! */ + ptr++; + for (;strscale > 0; strscale--) { + *nptr++ = CH_VAL(*ptr++); + } + } + + if (bc_is_zero (*num)) { + (*num)->n_sign = PLUS; + } + + return true; } diff --git a/ext/bcmath/libbcmath/src/sub.c b/ext/bcmath/libbcmath/src/sub.c index 3d277e51ee7e7..4907ae5bcecdb 100644 --- a/ext/bcmath/libbcmath/src/sub.c +++ b/ext/bcmath/libbcmath/src/sub.c @@ -29,52 +29,49 @@ *************************************************************************/ -#include #include "bcmath.h" #include "private.h" +#include +#include /* Here is the full subtract routine that takes care of negative numbers. N2 is subtracted from N1 and the result placed in RESULT. SCALE_MIN is the minimum scale for the result. */ -void bc_sub(bc_num n1, bc_num n2, bc_num *result, int scale_min) +void bc_sub(bc_num n1, bc_num n2, bc_num *result, size_t scale_min) { - bc_num diff = NULL; - int cmp_res; - int res_scale; + bc_num diff = NULL; + int cmp_res; - if (n1->n_sign != n2->n_sign) - { - diff = _bc_do_add (n1, n2, scale_min); - diff->n_sign = n1->n_sign; - } - else - { - /* subtraction must be done. */ - /* Compare magnitudes. */ - cmp_res = _bc_do_compare (n1, n2, FALSE, FALSE); - switch (cmp_res) - { - case -1: - /* n1 is less than n2, subtract n1 from n2. */ - diff = _bc_do_sub (n2, n1, scale_min); - diff->n_sign = (n2->n_sign == PLUS ? MINUS : PLUS); - break; - case 0: - /* They are equal! return zero! */ - res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale)); - diff = bc_new_num (1, res_scale); - memset (diff->n_value, 0, res_scale+1); - break; - case 1: - /* n2 is less than n1, subtract n2 from n1. */ - diff = _bc_do_sub (n1, n2, scale_min); - diff->n_sign = n1->n_sign; - break; + if (n1->n_sign != n2->n_sign) { + diff = _bc_do_add (n1, n2, scale_min); + diff->n_sign = n1->n_sign; + } else { + /* subtraction must be done. */ + /* Compare magnitudes. */ + cmp_res = _bc_do_compare(n1, n2, false, false); + switch (cmp_res) { + case -1: + /* n1 is less than n2, subtract n1 from n2. */ + diff = _bc_do_sub (n2, n1, scale_min); + diff->n_sign = (n2->n_sign == PLUS ? MINUS : PLUS); + break; + case 0: { + /* They are equal! return zero! */ + size_t res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale)); + diff = bc_new_num (1, res_scale); + memset (diff->n_value, 0, res_scale+1); + break; + } + case 1: + /* n2 is less than n1, subtract n2 from n1. */ + diff = _bc_do_sub (n1, n2, scale_min); + diff->n_sign = n1->n_sign; + break; + } } - } - /* Clean up and return. */ - bc_free_num (result); - *result = diff; + /* Clean up and return. */ + bc_free_num (result); + *result = diff; } diff --git a/ext/bcmath/libbcmath/src/zero.c b/ext/bcmath/libbcmath/src/zero.c index ba188d04369b3..edcd188acb8db 100644 --- a/ext/bcmath/libbcmath/src/zero.c +++ b/ext/bcmath/libbcmath/src/zero.c @@ -29,40 +29,33 @@ *************************************************************************/ -#include -#include -#include -#include -#include #include "bcmath.h" -#include "private.h" +#include +#include /* In some places we need to check if the number NUM is zero. */ -char -bc_is_zero_for_scale (bc_num num, int scale) +bool bc_is_zero_for_scale (bc_num num, size_t scale) { - int count; - char *nptr; + size_t count; + char *nptr; - /* Quick check. */ - if (num == BCG(_zero_)) return TRUE; + /* Quick check. */ + if (num == BCG(_zero_)) { + return true; + } - /* Initialize */ - count = num->n_len + scale; - nptr = num->n_value; + /* Initialize */ + count = num->n_len + scale; + nptr = num->n_value; - /* The check */ - while ((count > 0) && (*nptr++ == 0)) count--; + /* The check */ + while ((count > 0) && (*nptr++ == 0)) count--; - if (count != 0) - return FALSE; - else - return TRUE; + return count == 0; } -char -bc_is_zero (bc_num num) +bool bc_is_zero(bc_num num) { - return bc_is_zero_for_scale(num, num->n_scale); + return bc_is_zero_for_scale(num, num->n_scale); } diff --git a/ext/bcmath/php_bcmath.h b/ext/bcmath/php_bcmath.h index ebf57eee8f56e..1045019d64ca9 100644 --- a/ext/bcmath/php_bcmath.h +++ b/ext/bcmath/php_bcmath.h @@ -18,6 +18,7 @@ #define PHP_BCMATH_H #include "libbcmath/src/bcmath.h" +#include "zend_API.h" extern zend_module_entry bcmath_module_entry; #define phpext_bcmath_ptr &bcmath_module_entry @@ -25,10 +26,6 @@ extern zend_module_entry bcmath_module_entry; #include "php_version.h" #define PHP_BCMATH_VERSION PHP_VERSION -PHP_MINIT_FUNCTION(bcmath); -PHP_MSHUTDOWN_FUNCTION(bcmath); -PHP_MINFO_FUNCTION(bcmath); - ZEND_BEGIN_MODULE_GLOBALS(bcmath) bc_num _zero_; bc_num _one_;