mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Made bcmath extension thread safe.
@Made bcmath extension thread safe. (Sander)
This commit is contained in:
parent
64a75d6d77
commit
f200f739d8
14 changed files with 186 additions and 202 deletions
|
@ -30,6 +30,8 @@
|
||||||
#include "php_bcmath.h"
|
#include "php_bcmath.h"
|
||||||
#include "libbcmath/src/bcmath.h"
|
#include "libbcmath/src/bcmath.h"
|
||||||
|
|
||||||
|
ZEND_DECLARE_MODULE_GLOBALS(bcmath);
|
||||||
|
|
||||||
function_entry bcmath_functions[] = {
|
function_entry bcmath_functions[] = {
|
||||||
PHP_FE(bcadd, NULL)
|
PHP_FE(bcadd, NULL)
|
||||||
PHP_FE(bcsub, NULL)
|
PHP_FE(bcsub, NULL)
|
||||||
|
@ -47,7 +49,11 @@ zend_module_entry bcmath_module_entry = {
|
||||||
STANDARD_MODULE_HEADER,
|
STANDARD_MODULE_HEADER,
|
||||||
"bcmath",
|
"bcmath",
|
||||||
bcmath_functions,
|
bcmath_functions,
|
||||||
|
#if ZTS
|
||||||
|
PHP_MODULE_STARTUP_N(bcmath),
|
||||||
|
#else
|
||||||
NULL,
|
NULL,
|
||||||
|
#endif
|
||||||
NULL,
|
NULL,
|
||||||
PHP_RINIT(bcmath),
|
PHP_RINIT(bcmath),
|
||||||
PHP_RSHUTDOWN(bcmath),
|
PHP_RSHUTDOWN(bcmath),
|
||||||
|
@ -64,32 +70,22 @@ ZEND_GET_MODULE(bcmath)
|
||||||
static long bc_precision;
|
static long bc_precision;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Storage used for special numbers. */
|
#if ZTS
|
||||||
extern bc_num _zero_;
|
PHP_MODULE_STARTUP_D(bcmath)
|
||||||
extern bc_num _one_;
|
|
||||||
extern bc_num _two_;
|
|
||||||
|
|
||||||
|
|
||||||
/* Make a copy of a number! Just increments the reference count! */
|
|
||||||
bc_num copy_num (bc_num num)
|
|
||||||
{
|
{
|
||||||
num->n_refs++;
|
zend_bcmath_globals *bcmath_globals;
|
||||||
return num;
|
|
||||||
|
ts_allocate_id(&bcmath_globals_id, sizeof(zend_bcmath_globals), NULL, NULL);
|
||||||
|
bcmath_globals = ts_resource(bcmath_globals_id);
|
||||||
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Initialize a number NUM by making it a copy of zero. */
|
|
||||||
void init_num (bc_num *num)
|
|
||||||
{
|
|
||||||
*num = copy_num (_zero_);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PHP_RSHUTDOWN_FUNCTION(bcmath)
|
PHP_RSHUTDOWN_FUNCTION(bcmath)
|
||||||
{
|
{
|
||||||
bc_free_num(&_zero_);
|
bc_free_num(&BCG(_zero_));
|
||||||
bc_free_num(&_one_);
|
bc_free_num(&BCG(_one_));
|
||||||
bc_free_num(&_two_);
|
bc_free_num(&BCG(_two_));
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -101,7 +97,7 @@ PHP_RINIT_FUNCTION(bcmath)
|
||||||
bc_precision=0;
|
bc_precision=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bc_init_numbers();
|
bc_init_numbers(TSRMLS_C);
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -141,11 +137,11 @@ PHP_FUNCTION(bcadd)
|
||||||
}
|
}
|
||||||
convert_to_string_ex(left);
|
convert_to_string_ex(left);
|
||||||
convert_to_string_ex(right);
|
convert_to_string_ex(right);
|
||||||
bc_init_num(&first);
|
bc_init_num(&first TSRMLS_CC);
|
||||||
bc_init_num(&second);
|
bc_init_num(&second TSRMLS_CC);
|
||||||
bc_init_num(&result);
|
bc_init_num(&result TSRMLS_CC);
|
||||||
bc_str2num(&first, Z_STRVAL_PP(left), scale);
|
bc_str2num(&first, Z_STRVAL_PP(left), scale TSRMLS_CC);
|
||||||
bc_str2num(&second, Z_STRVAL_PP(right), scale);
|
bc_str2num(&second, Z_STRVAL_PP(right), scale TSRMLS_CC);
|
||||||
bc_add (first, second, &result, scale);
|
bc_add (first, second, &result, scale);
|
||||||
Z_STRVAL_P(return_value) = bc_num2str(result);
|
Z_STRVAL_P(return_value) = bc_num2str(result);
|
||||||
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
||||||
|
@ -184,11 +180,11 @@ PHP_FUNCTION(bcsub)
|
||||||
}
|
}
|
||||||
convert_to_string_ex(left);
|
convert_to_string_ex(left);
|
||||||
convert_to_string_ex(right);
|
convert_to_string_ex(right);
|
||||||
bc_init_num(&first);
|
bc_init_num(&first TSRMLS_CC);
|
||||||
bc_init_num(&second);
|
bc_init_num(&second TSRMLS_CC);
|
||||||
bc_init_num(&result);
|
bc_init_num(&result TSRMLS_CC);
|
||||||
bc_str2num(&first, Z_STRVAL_PP(left), scale);
|
bc_str2num(&first, Z_STRVAL_PP(left), scale TSRMLS_CC);
|
||||||
bc_str2num(&second, Z_STRVAL_PP(right), scale);
|
bc_str2num(&second, Z_STRVAL_PP(right), scale TSRMLS_CC);
|
||||||
bc_sub (first, second, &result, scale);
|
bc_sub (first, second, &result, scale);
|
||||||
Z_STRVAL_P(return_value) = bc_num2str(result);
|
Z_STRVAL_P(return_value) = bc_num2str(result);
|
||||||
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
||||||
|
@ -227,12 +223,12 @@ PHP_FUNCTION(bcmul)
|
||||||
}
|
}
|
||||||
convert_to_string_ex(left);
|
convert_to_string_ex(left);
|
||||||
convert_to_string_ex(right);
|
convert_to_string_ex(right);
|
||||||
bc_init_num(&first);
|
bc_init_num(&first TSRMLS_CC);
|
||||||
bc_init_num(&second);
|
bc_init_num(&second TSRMLS_CC);
|
||||||
bc_init_num(&result);
|
bc_init_num(&result TSRMLS_CC);
|
||||||
bc_str2num(&first, Z_STRVAL_PP(left), scale);
|
bc_str2num(&first, Z_STRVAL_PP(left), scale TSRMLS_CC);
|
||||||
bc_str2num(&second, Z_STRVAL_PP(right), scale);
|
bc_str2num(&second, Z_STRVAL_PP(right), scale TSRMLS_CC);
|
||||||
bc_multiply (first, second, &result, scale);
|
bc_multiply (first, second, &result, scale TSRMLS_CC);
|
||||||
Z_STRVAL_P(return_value) = bc_num2str(result);
|
Z_STRVAL_P(return_value) = bc_num2str(result);
|
||||||
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
||||||
Z_TYPE_P(return_value) = IS_STRING;
|
Z_TYPE_P(return_value) = IS_STRING;
|
||||||
|
@ -270,12 +266,12 @@ PHP_FUNCTION(bcdiv)
|
||||||
}
|
}
|
||||||
convert_to_string_ex(left);
|
convert_to_string_ex(left);
|
||||||
convert_to_string_ex(right);
|
convert_to_string_ex(right);
|
||||||
bc_init_num(&first);
|
bc_init_num(&first TSRMLS_CC);
|
||||||
bc_init_num(&second);
|
bc_init_num(&second TSRMLS_CC);
|
||||||
bc_init_num(&result);
|
bc_init_num(&result TSRMLS_CC);
|
||||||
bc_str2num(&first, Z_STRVAL_PP(left), scale);
|
bc_str2num(&first, Z_STRVAL_PP(left), scale TSRMLS_CC);
|
||||||
bc_str2num(&second, Z_STRVAL_PP(right), scale);
|
bc_str2num(&second, Z_STRVAL_PP(right), scale TSRMLS_CC);
|
||||||
switch (bc_divide (first, second, &result, scale)) {
|
switch (bc_divide (first, second, &result, scale TSRMLS_CC)) {
|
||||||
case 0: /* OK */
|
case 0: /* OK */
|
||||||
Z_STRVAL_P(return_value) = bc_num2str(result);
|
Z_STRVAL_P(return_value) = bc_num2str(result);
|
||||||
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
||||||
|
@ -311,12 +307,12 @@ PHP_FUNCTION(bcmod)
|
||||||
}
|
}
|
||||||
convert_to_string_ex(left);
|
convert_to_string_ex(left);
|
||||||
convert_to_string_ex(right);
|
convert_to_string_ex(right);
|
||||||
bc_init_num(&first);
|
bc_init_num(&first TSRMLS_CC);
|
||||||
bc_init_num(&second);
|
bc_init_num(&second TSRMLS_CC);
|
||||||
bc_init_num(&result);
|
bc_init_num(&result TSRMLS_CC);
|
||||||
bc_str2num(&first, Z_STRVAL_PP(left), 0);
|
bc_str2num(&first, Z_STRVAL_PP(left), 0 TSRMLS_CC);
|
||||||
bc_str2num(&second, Z_STRVAL_PP(right), 0);
|
bc_str2num(&second, Z_STRVAL_PP(right), 0 TSRMLS_CC);
|
||||||
switch (bc_modulo(first, second, &result, 0)) {
|
switch (bc_modulo(first, second, &result, 0 TSRMLS_CC)) {
|
||||||
case 0:
|
case 0:
|
||||||
Z_STRVAL_P(return_value) = bc_num2str(result);
|
Z_STRVAL_P(return_value) = bc_num2str(result);
|
||||||
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
||||||
|
@ -360,12 +356,12 @@ PHP_FUNCTION(bcpow)
|
||||||
}
|
}
|
||||||
convert_to_string_ex(left);
|
convert_to_string_ex(left);
|
||||||
convert_to_string_ex(right);
|
convert_to_string_ex(right);
|
||||||
bc_init_num(&first);
|
bc_init_num(&first TSRMLS_CC);
|
||||||
bc_init_num(&second);
|
bc_init_num(&second TSRMLS_CC);
|
||||||
bc_init_num(&result);
|
bc_init_num(&result TSRMLS_CC);
|
||||||
bc_str2num(&first, Z_STRVAL_PP(left), scale);
|
bc_str2num(&first, Z_STRVAL_PP(left), scale TSRMLS_CC);
|
||||||
bc_str2num(&second, Z_STRVAL_PP(right), scale);
|
bc_str2num(&second, Z_STRVAL_PP(right), scale TSRMLS_CC);
|
||||||
bc_raise (first, second, &result, scale);
|
bc_raise (first, second, &result, scale TSRMLS_CC);
|
||||||
Z_STRVAL_P(return_value) = bc_num2str(result);
|
Z_STRVAL_P(return_value) = bc_num2str(result);
|
||||||
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
||||||
Z_TYPE_P(return_value) = IS_STRING;
|
Z_TYPE_P(return_value) = IS_STRING;
|
||||||
|
@ -402,9 +398,9 @@ PHP_FUNCTION(bcsqrt)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
convert_to_string_ex(left);
|
convert_to_string_ex(left);
|
||||||
bc_init_num(&result);
|
bc_init_num(&result TSRMLS_CC);
|
||||||
bc_str2num(&result, Z_STRVAL_PP(left), scale);
|
bc_str2num(&result, Z_STRVAL_PP(left), scale TSRMLS_CC);
|
||||||
if (bc_sqrt (&result, scale) != 0) {
|
if (bc_sqrt (&result, scale TSRMLS_CC) != 0) {
|
||||||
Z_STRVAL_P(return_value) = bc_num2str(result);
|
Z_STRVAL_P(return_value) = bc_num2str(result);
|
||||||
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
|
||||||
Z_TYPE_P(return_value) = IS_STRING;
|
Z_TYPE_P(return_value) = IS_STRING;
|
||||||
|
@ -444,11 +440,11 @@ PHP_FUNCTION(bccomp)
|
||||||
|
|
||||||
convert_to_string_ex(left);
|
convert_to_string_ex(left);
|
||||||
convert_to_string_ex(right);
|
convert_to_string_ex(right);
|
||||||
bc_init_num(&first);
|
bc_init_num(&first TSRMLS_CC);
|
||||||
bc_init_num(&second);
|
bc_init_num(&second TSRMLS_CC);
|
||||||
|
|
||||||
bc_str2num(&first, Z_STRVAL_PP(left), scale);
|
bc_str2num(&first, Z_STRVAL_PP(left), scale TSRMLS_CC);
|
||||||
bc_str2num(&second, Z_STRVAL_PP(right), scale);
|
bc_str2num(&second, Z_STRVAL_PP(right), scale TSRMLS_CC);
|
||||||
Z_LVAL_P(return_value) = bc_compare(first, second);
|
Z_LVAL_P(return_value) = bc_compare(first, second);
|
||||||
Z_TYPE_P(return_value) = IS_LONG;
|
Z_TYPE_P(return_value) = IS_LONG;
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,9 @@ typedef struct bc_struct
|
||||||
in the case of leading zeros generated. */
|
in the case of leading zeros generated. */
|
||||||
} bc_struct;
|
} bc_struct;
|
||||||
|
|
||||||
|
#include <php.h>
|
||||||
|
#include <ext/bcmath/php_bcmath.h>
|
||||||
|
|
||||||
|
|
||||||
/* The base used in storing the numbers in n_value above.
|
/* The base used in storing the numbers in n_value above.
|
||||||
Currently this MUST be 10. */
|
Currently this MUST be 10. */
|
||||||
|
@ -81,12 +84,6 @@ typedef struct bc_struct
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Global numbers. */
|
|
||||||
extern bc_num _zero_;
|
|
||||||
extern bc_num _one_;
|
|
||||||
extern bc_num _two_;
|
|
||||||
|
|
||||||
|
|
||||||
/* Function Prototypes */
|
/* Function Prototypes */
|
||||||
|
|
||||||
/* Define the _PROTOTYPE macro if it is needed. */
|
/* Define the _PROTOTYPE macro if it is needed. */
|
||||||
|
@ -99,7 +96,7 @@ extern bc_num _two_;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_PROTOTYPE(void bc_init_numbers, (void));
|
_PROTOTYPE(void bc_init_numbers, (TSRMLS_D));
|
||||||
|
|
||||||
_PROTOTYPE(bc_num bc_new_num, (int length, int scale));
|
_PROTOTYPE(bc_num bc_new_num, (int length, int scale));
|
||||||
|
|
||||||
|
@ -107,9 +104,9 @@ _PROTOTYPE(void bc_free_num, (bc_num *num));
|
||||||
|
|
||||||
_PROTOTYPE(bc_num bc_copy_num, (bc_num num));
|
_PROTOTYPE(bc_num bc_copy_num, (bc_num num));
|
||||||
|
|
||||||
_PROTOTYPE(void bc_init_num, (bc_num *num));
|
_PROTOTYPE(void bc_init_num, (bc_num *num TSRMLS_DC));
|
||||||
|
|
||||||
_PROTOTYPE(void bc_str2num, (bc_num *num, char *str, int scale));
|
_PROTOTYPE(void bc_str2num, (bc_num *num, char *str, int scale TSRMLS_DC));
|
||||||
|
|
||||||
_PROTOTYPE(char *bc_num2str, (bc_num num));
|
_PROTOTYPE(char *bc_num2str, (bc_num num));
|
||||||
|
|
||||||
|
@ -119,7 +116,7 @@ _PROTOTYPE(long bc_num2long, (bc_num num));
|
||||||
|
|
||||||
_PROTOTYPE(int bc_compare, (bc_num n1, bc_num n2));
|
_PROTOTYPE(int bc_compare, (bc_num n1, bc_num n2));
|
||||||
|
|
||||||
_PROTOTYPE(char bc_is_zero, (bc_num num));
|
_PROTOTYPE(char bc_is_zero, (bc_num num TSRMLS_DC));
|
||||||
|
|
||||||
_PROTOTYPE(char bc_is_near_zero, (bc_num num, int scale));
|
_PROTOTYPE(char bc_is_near_zero, (bc_num num, int scale));
|
||||||
|
|
||||||
|
@ -129,26 +126,26 @@ _PROTOTYPE(void bc_add, (bc_num n1, bc_num n2, bc_num *result, int scale_min));
|
||||||
|
|
||||||
_PROTOTYPE(void bc_sub, (bc_num n1, bc_num n2, bc_num *result, int scale_min));
|
_PROTOTYPE(void bc_sub, (bc_num n1, bc_num n2, bc_num *result, int scale_min));
|
||||||
|
|
||||||
_PROTOTYPE(void bc_multiply, (bc_num n1, bc_num n2, bc_num *prod, int scale));
|
_PROTOTYPE(void bc_multiply, (bc_num n1, bc_num n2, bc_num *prod, int scale TSRMLS_DC));
|
||||||
|
|
||||||
_PROTOTYPE(int bc_divide, (bc_num n1, bc_num n2, bc_num *quot, int scale));
|
_PROTOTYPE(int bc_divide, (bc_num n1, bc_num n2, bc_num *quot, int scale TSRMLS_DC));
|
||||||
|
|
||||||
_PROTOTYPE(int bc_modulo, (bc_num num1, bc_num num2, bc_num *result,
|
_PROTOTYPE(int bc_modulo, (bc_num num1, bc_num num2, bc_num *result,
|
||||||
int scale));
|
int scale TSRMLS_DC));
|
||||||
|
|
||||||
_PROTOTYPE(int bc_divmod, (bc_num num1, bc_num num2, bc_num *quot,
|
_PROTOTYPE(int bc_divmod, (bc_num num1, bc_num num2, bc_num *quot,
|
||||||
bc_num *rem, int scale));
|
bc_num *rem, int scale TSRMLS_DC));
|
||||||
|
|
||||||
_PROTOTYPE(int bc_raisemod, (bc_num base, bc_num expo, bc_num mod,
|
_PROTOTYPE(int bc_raisemod, (bc_num base, bc_num expo, bc_num mod,
|
||||||
bc_num *result, int scale));
|
bc_num *result, int scale TSRMLS_DC));
|
||||||
|
|
||||||
_PROTOTYPE(void bc_raise, (bc_num num1, bc_num num2, bc_num *result,
|
_PROTOTYPE(void bc_raise, (bc_num num1, bc_num num2, bc_num *result,
|
||||||
int scale));
|
int scale TSRMLS_DC));
|
||||||
|
|
||||||
_PROTOTYPE(int bc_sqrt, (bc_num *num, int scale));
|
_PROTOTYPE(int bc_sqrt, (bc_num *num, int scale TSRMLS_DC));
|
||||||
|
|
||||||
_PROTOTYPE(void bc_out_num, (bc_num num, int o_base, void (* out_char)(int),
|
_PROTOTYPE(void bc_out_num, (bc_num num, int o_base, void (* out_char)(int),
|
||||||
int leading_zero));
|
int leading_zero TSRMLS_DC));
|
||||||
|
|
||||||
/* Prototypes needed for external utility routines. */
|
/* Prototypes needed for external utility routines. */
|
||||||
|
|
||||||
|
|
|
@ -48,10 +48,9 @@ out_char (int c)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
pn (num)
|
pn (bc_num num TSRMLS_DC)
|
||||||
bc_num num;
|
|
||||||
{
|
{
|
||||||
bc_out_num (num, 10, out_char, 0);
|
bc_out_num (num, 10, out_char, 0 TSRMLS_CC);
|
||||||
out_char ('\n');
|
out_char ('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,9 +85,7 @@ _one_mult (num, size, digit, result)
|
||||||
by zero is tried. The algorithm is found in Knuth Vol 2. p237. */
|
by zero is tried. The algorithm is found in Knuth Vol 2. p237. */
|
||||||
|
|
||||||
int
|
int
|
||||||
bc_divide (n1, n2, quot, scale)
|
bc_divide (bc_num n1, bc_num n2, bc_num *quot, int scale TSRMLS_DC)
|
||||||
bc_num n1, n2, *quot;
|
|
||||||
int scale;
|
|
||||||
{
|
{
|
||||||
bc_num qval;
|
bc_num qval;
|
||||||
unsigned char *num1, *num2;
|
unsigned char *num1, *num2;
|
||||||
|
@ -100,7 +98,7 @@ bc_divide (n1, n2, quot, scale)
|
||||||
unsigned int norm;
|
unsigned int norm;
|
||||||
|
|
||||||
/* Test for divide by zero. */
|
/* Test for divide by zero. */
|
||||||
if (bc_is_zero (n2)) return -1;
|
if (bc_is_zero (n2 TSRMLS_CC)) return -1;
|
||||||
|
|
||||||
/* Test for divide by 1. If it is we must truncate. */
|
/* Test for divide by 1. If it is we must truncate. */
|
||||||
if (n2->n_scale == 0)
|
if (n2->n_scale == 0)
|
||||||
|
@ -261,7 +259,7 @@ bc_divide (n1, n2, quot, scale)
|
||||||
|
|
||||||
/* Clean up and return the number. */
|
/* Clean up and return the number. */
|
||||||
qval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS );
|
qval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS );
|
||||||
if (bc_is_zero (qval)) qval->n_sign = PLUS;
|
if (bc_is_zero (qval TSRMLS_CC)) qval->n_sign = PLUS;
|
||||||
_bc_rm_leading_zeros (qval);
|
_bc_rm_leading_zeros (qval);
|
||||||
bc_free_num (quot);
|
bc_free_num (quot);
|
||||||
*quot = qval;
|
*quot = qval;
|
||||||
|
|
|
@ -45,26 +45,24 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
bc_divmod (num1, num2, quot, rem, scale)
|
bc_divmod (bc_num num1, bc_num num2, bc_num *quot, bc_num *rem, int scale TSRMLS_DC)
|
||||||
bc_num num1, num2, *quot, *rem;
|
|
||||||
int scale;
|
|
||||||
{
|
{
|
||||||
bc_num quotient = NULL;
|
bc_num quotient = NULL;
|
||||||
bc_num temp;
|
bc_num temp;
|
||||||
int rscale;
|
int rscale;
|
||||||
|
|
||||||
/* Check for correct numbers. */
|
/* Check for correct numbers. */
|
||||||
if (bc_is_zero (num2)) return -1;
|
if (bc_is_zero (num2 TSRMLS_CC)) return -1;
|
||||||
|
|
||||||
/* Calculate final scale. */
|
/* Calculate final scale. */
|
||||||
rscale = MAX (num1->n_scale, num2->n_scale+scale);
|
rscale = MAX (num1->n_scale, num2->n_scale+scale);
|
||||||
bc_init_num(&temp);
|
bc_init_num(&temp TSRMLS_CC);
|
||||||
|
|
||||||
/* Calculate it. */
|
/* Calculate it. */
|
||||||
bc_divide (num1, num2, &temp, scale);
|
bc_divide (num1, num2, &temp, scale TSRMLS_CC);
|
||||||
if (quot)
|
if (quot)
|
||||||
quotient = bc_copy_num (temp);
|
quotient = bc_copy_num (temp);
|
||||||
bc_multiply (temp, num2, &temp, rscale);
|
bc_multiply (temp, num2, &temp, rscale TSRMLS_CC);
|
||||||
bc_sub (num1, temp, rem, rscale);
|
bc_sub (num1, temp, rem, rscale);
|
||||||
bc_free_num (&temp);
|
bc_free_num (&temp);
|
||||||
|
|
||||||
|
@ -82,10 +80,8 @@ bc_divmod (num1, num2, quot, rem, scale)
|
||||||
result in RESULT. */
|
result in RESULT. */
|
||||||
|
|
||||||
int
|
int
|
||||||
bc_modulo (num1, num2, result, scale)
|
bc_modulo (bc_num num1, bc_num num2, bc_num *result, int scale TSRMLS_DC)
|
||||||
bc_num num1, num2, *result;
|
|
||||||
int scale;
|
|
||||||
{
|
{
|
||||||
return bc_divmod (num1, num2, NULL, result, scale);
|
return bc_divmod (num1, num2, NULL, result, scale TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,11 +38,6 @@
|
||||||
#include "bcmath.h"
|
#include "bcmath.h"
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
|
|
||||||
/* Storage used for special numbers. */
|
|
||||||
bc_num _zero_;
|
|
||||||
bc_num _one_;
|
|
||||||
bc_num _two_;
|
|
||||||
|
|
||||||
bc_num _bc_Free_list = NULL;
|
bc_num _bc_Free_list = NULL;
|
||||||
|
|
||||||
/* new_num allocates a number and sets fields to known values. */
|
/* new_num allocates a number and sets fields to known values. */
|
||||||
|
@ -103,21 +98,20 @@ bc_free_num (num)
|
||||||
/* Intitialize the number package! */
|
/* Intitialize the number package! */
|
||||||
|
|
||||||
void
|
void
|
||||||
bc_init_numbers ()
|
bc_init_numbers (TSRMLS_D)
|
||||||
{
|
{
|
||||||
_zero_ = bc_new_num (1,0);
|
BCG(_zero_) = bc_new_num (1,0);
|
||||||
_one_ = bc_new_num (1,0);
|
BCG(_one_) = bc_new_num (1,0);
|
||||||
_one_->n_value[0] = 1;
|
BCG(_one_)->n_value[0] = 1;
|
||||||
_two_ = bc_new_num (1,0);
|
BCG(_two_) = bc_new_num (1,0);
|
||||||
_two_->n_value[0] = 2;
|
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_num
|
||||||
bc_copy_num (num)
|
bc_copy_num (bc_num num)
|
||||||
bc_num num;
|
|
||||||
{
|
{
|
||||||
num->n_refs++;
|
num->n_refs++;
|
||||||
return num;
|
return num;
|
||||||
|
@ -127,9 +121,8 @@ bc_copy_num (num)
|
||||||
/* Initialize a number NUM by making it a copy of zero. */
|
/* Initialize a number NUM by making it a copy of zero. */
|
||||||
|
|
||||||
void
|
void
|
||||||
bc_init_num (num)
|
bc_init_num (bc_num *num TSRMLS_DC)
|
||||||
bc_num *num;
|
|
||||||
{
|
{
|
||||||
*num = bc_copy_num (_zero_);
|
*num = bc_copy_num (BCG(_zero_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,15 +86,11 @@ bc_out_long (val, size, space, out_char)
|
||||||
as the routine to do the actual output of the characters. */
|
as the routine to do the actual output of the characters. */
|
||||||
|
|
||||||
void
|
void
|
||||||
bc_out_num (num, o_base, out_char, leading_zero)
|
|
||||||
bc_num num;
|
|
||||||
int o_base;
|
|
||||||
#ifdef __STDC__
|
#ifdef __STDC__
|
||||||
void (*out_char)(int);
|
bc_out_num (bc_num num, int o_base, void (*out_char)(int), int leading_zero TSRMLS_DC)
|
||||||
#else
|
#else
|
||||||
void (*out_char)();
|
bc_out_num (bc_num num, int o_base, void (*out_char)(), int leading_zero TSRMLS_DC)
|
||||||
#endif
|
#endif
|
||||||
int leading_zero;
|
|
||||||
{
|
{
|
||||||
char *nptr;
|
char *nptr;
|
||||||
int index, fdigit, pre_space;
|
int index, fdigit, pre_space;
|
||||||
|
@ -105,7 +101,7 @@ bc_out_num (num, o_base, out_char, leading_zero)
|
||||||
if (num->n_sign == MINUS) (*out_char) ('-');
|
if (num->n_sign == MINUS) (*out_char) ('-');
|
||||||
|
|
||||||
/* Output the number. */
|
/* Output the number. */
|
||||||
if (bc_is_zero (num))
|
if (bc_is_zero (num TSRMLS_CC))
|
||||||
(*out_char) ('0');
|
(*out_char) ('0');
|
||||||
else
|
else
|
||||||
if (o_base == 10)
|
if (o_base == 10)
|
||||||
|
@ -118,7 +114,7 @@ bc_out_num (num, o_base, out_char, leading_zero)
|
||||||
else
|
else
|
||||||
nptr++;
|
nptr++;
|
||||||
|
|
||||||
if (leading_zero && bc_is_zero (num))
|
if (leading_zero && bc_is_zero (num TSRMLS_CC))
|
||||||
(*out_char) ('0');
|
(*out_char) ('0');
|
||||||
|
|
||||||
/* Now the fraction. */
|
/* Now the fraction. */
|
||||||
|
@ -132,36 +128,36 @@ bc_out_num (num, o_base, out_char, leading_zero)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* special case ... */
|
/* special case ... */
|
||||||
if (leading_zero && bc_is_zero (num))
|
if (leading_zero && bc_is_zero (num TSRMLS_CC))
|
||||||
(*out_char) ('0');
|
(*out_char) ('0');
|
||||||
|
|
||||||
/* The number is some other base. */
|
/* The number is some other base. */
|
||||||
digits = NULL;
|
digits = NULL;
|
||||||
bc_init_num (&int_part);
|
bc_init_num (&int_part TSRMLS_CC);
|
||||||
bc_divide (num, _one_, &int_part, 0);
|
bc_divide (num, BCG(_one_), &int_part, 0 TSRMLS_CC);
|
||||||
bc_init_num (&frac_part);
|
bc_init_num (&frac_part TSRMLS_CC);
|
||||||
bc_init_num (&cur_dig);
|
bc_init_num (&cur_dig TSRMLS_CC);
|
||||||
bc_init_num (&base);
|
bc_init_num (&base TSRMLS_CC);
|
||||||
bc_sub (num, int_part, &frac_part, 0);
|
bc_sub (num, int_part, &frac_part, 0);
|
||||||
/* Make the INT_PART and FRAC_PART positive. */
|
/* Make the INT_PART and FRAC_PART positive. */
|
||||||
int_part->n_sign = PLUS;
|
int_part->n_sign = PLUS;
|
||||||
frac_part->n_sign = PLUS;
|
frac_part->n_sign = PLUS;
|
||||||
bc_int2num (&base, o_base);
|
bc_int2num (&base, o_base);
|
||||||
bc_init_num (&max_o_digit);
|
bc_init_num (&max_o_digit TSRMLS_CC);
|
||||||
bc_int2num (&max_o_digit, o_base-1);
|
bc_int2num (&max_o_digit, o_base-1);
|
||||||
|
|
||||||
|
|
||||||
/* Get the digits of the integer part and push them on a stack. */
|
/* Get the digits of the integer part and push them on a stack. */
|
||||||
while (!bc_is_zero (int_part))
|
while (!bc_is_zero (int_part TSRMLS_CC))
|
||||||
{
|
{
|
||||||
bc_modulo (int_part, base, &cur_dig, 0);
|
bc_modulo (int_part, base, &cur_dig, 0 TSRMLS_CC);
|
||||||
/* PHP Change: malloc() -> emalloc() */
|
/* PHP Change: malloc() -> emalloc() */
|
||||||
temp = (stk_rec *) emalloc (sizeof(stk_rec));
|
temp = (stk_rec *) emalloc (sizeof(stk_rec));
|
||||||
if (temp == NULL) bc_out_of_memory();
|
if (temp == NULL) bc_out_of_memory();
|
||||||
temp->digit = bc_num2long (cur_dig);
|
temp->digit = bc_num2long (cur_dig);
|
||||||
temp->next = digits;
|
temp->next = digits;
|
||||||
digits = temp;
|
digits = temp;
|
||||||
bc_divide (int_part, base, &int_part, 0);
|
bc_divide (int_part, base, &int_part, 0 TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print the digits on the stack. */
|
/* Print the digits on the stack. */
|
||||||
|
@ -185,9 +181,9 @@ bc_out_num (num, o_base, out_char, leading_zero)
|
||||||
{
|
{
|
||||||
(*out_char) ('.');
|
(*out_char) ('.');
|
||||||
pre_space = 0;
|
pre_space = 0;
|
||||||
t_num = bc_copy_num (_one_);
|
t_num = bc_copy_num (BCG(_one_));
|
||||||
while (t_num->n_len <= num->n_scale) {
|
while (t_num->n_len <= num->n_scale) {
|
||||||
bc_multiply (frac_part, base, &frac_part, num->n_scale);
|
bc_multiply (frac_part, base, &frac_part, num->n_scale TSRMLS_CC);
|
||||||
fdigit = bc_num2long (frac_part);
|
fdigit = bc_num2long (frac_part);
|
||||||
bc_int2num (&int_part, fdigit);
|
bc_int2num (&int_part, fdigit);
|
||||||
bc_sub (frac_part, int_part, &frac_part, 0);
|
bc_sub (frac_part, int_part, &frac_part, 0);
|
||||||
|
@ -197,7 +193,7 @@ bc_out_num (num, o_base, out_char, leading_zero)
|
||||||
bc_out_long (fdigit, max_o_digit->n_len, pre_space, out_char);
|
bc_out_long (fdigit, max_o_digit->n_len, pre_space, out_char);
|
||||||
pre_space = 1;
|
pre_space = 1;
|
||||||
}
|
}
|
||||||
bc_multiply (t_num, base, &t_num, 0);
|
bc_multiply (t_num, base, &t_num, 0 TSRMLS_CC);
|
||||||
}
|
}
|
||||||
bc_free_num (&t_num);
|
bc_free_num (&t_num);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,9 +44,7 @@
|
||||||
only the integer part is used. */
|
only the integer part is used. */
|
||||||
|
|
||||||
void
|
void
|
||||||
bc_raise (num1, num2, result, scale)
|
bc_raise (bc_num num1, bc_num num2, bc_num *result, int scale TSRMLS_DC)
|
||||||
bc_num num1, num2, *result;
|
|
||||||
int scale;
|
|
||||||
{
|
{
|
||||||
bc_num temp, power;
|
bc_num temp, power;
|
||||||
long exponent;
|
long exponent;
|
||||||
|
@ -66,7 +64,7 @@ bc_raise (num1, num2, result, scale)
|
||||||
if (exponent == 0)
|
if (exponent == 0)
|
||||||
{
|
{
|
||||||
bc_free_num (result);
|
bc_free_num (result);
|
||||||
*result = bc_copy_num (_one_);
|
*result = bc_copy_num (BCG(_one_));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +87,7 @@ bc_raise (num1, num2, result, scale)
|
||||||
while ((exponent & 1) == 0)
|
while ((exponent & 1) == 0)
|
||||||
{
|
{
|
||||||
pwrscale = 2*pwrscale;
|
pwrscale = 2*pwrscale;
|
||||||
bc_multiply (power, power, &power, pwrscale);
|
bc_multiply (power, power, &power, pwrscale TSRMLS_CC);
|
||||||
exponent = exponent >> 1;
|
exponent = exponent >> 1;
|
||||||
}
|
}
|
||||||
temp = bc_copy_num (power);
|
temp = bc_copy_num (power);
|
||||||
|
@ -100,10 +98,10 @@ bc_raise (num1, num2, result, scale)
|
||||||
while (exponent > 0)
|
while (exponent > 0)
|
||||||
{
|
{
|
||||||
pwrscale = 2*pwrscale;
|
pwrscale = 2*pwrscale;
|
||||||
bc_multiply (power, power, &power, pwrscale);
|
bc_multiply (power, power, &power, pwrscale TSRMLS_CC);
|
||||||
if ((exponent & 1) == 1) {
|
if ((exponent & 1) == 1) {
|
||||||
calcscale = pwrscale + calcscale;
|
calcscale = pwrscale + calcscale;
|
||||||
bc_multiply (temp, power, &temp, calcscale);
|
bc_multiply (temp, power, &temp, calcscale TSRMLS_CC);
|
||||||
}
|
}
|
||||||
exponent = exponent >> 1;
|
exponent = exponent >> 1;
|
||||||
}
|
}
|
||||||
|
@ -111,7 +109,7 @@ bc_raise (num1, num2, result, scale)
|
||||||
/* Assign the value. */
|
/* Assign the value. */
|
||||||
if (neg)
|
if (neg)
|
||||||
{
|
{
|
||||||
bc_divide (_one_, temp, result, rscale);
|
bc_divide (BCG(_one_), temp, result, rscale TSRMLS_CC);
|
||||||
bc_free_num (&temp);
|
bc_free_num (&temp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -43,22 +43,20 @@
|
||||||
only the integer part is used. */
|
only the integer part is used. */
|
||||||
|
|
||||||
int
|
int
|
||||||
bc_raisemod (base, expo, mod, result, scale)
|
bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale TSRMLS_DC)
|
||||||
bc_num base, expo, mod, *result;
|
|
||||||
int scale;
|
|
||||||
{
|
{
|
||||||
bc_num power, exponent, parity, temp;
|
bc_num power, exponent, parity, temp;
|
||||||
int rscale;
|
int rscale;
|
||||||
|
|
||||||
/* Check for correct numbers. */
|
/* Check for correct numbers. */
|
||||||
if (bc_is_zero(mod)) return -1;
|
if (bc_is_zero(mod TSRMLS_CC)) return -1;
|
||||||
if (bc_is_neg(expo)) return -1;
|
if (bc_is_neg(expo)) return -1;
|
||||||
|
|
||||||
/* Set initial values. */
|
/* Set initial values. */
|
||||||
power = bc_copy_num (base);
|
power = bc_copy_num (base);
|
||||||
exponent = bc_copy_num (expo);
|
exponent = bc_copy_num (expo);
|
||||||
temp = bc_copy_num (_one_);
|
temp = bc_copy_num (BCG(_one_));
|
||||||
bc_init_num(&parity);
|
bc_init_num(&parity TSRMLS_CC);
|
||||||
|
|
||||||
/* Check the base for scale digits. */
|
/* Check the base for scale digits. */
|
||||||
if (base->n_scale != 0)
|
if (base->n_scale != 0)
|
||||||
|
@ -68,7 +66,7 @@ bc_raisemod (base, expo, mod, result, scale)
|
||||||
if (exponent->n_scale != 0)
|
if (exponent->n_scale != 0)
|
||||||
{
|
{
|
||||||
bc_rt_warn ("non-zero scale in exponent");
|
bc_rt_warn ("non-zero scale in exponent");
|
||||||
bc_divide (exponent, _one_, &exponent, 0); /*truncate */
|
bc_divide (exponent, BCG(_one_), &exponent, 0 TSRMLS_CC); /*truncate */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the modulus for scale digits. */
|
/* Check the modulus for scale digits. */
|
||||||
|
@ -77,17 +75,17 @@ bc_raisemod (base, expo, mod, result, scale)
|
||||||
|
|
||||||
/* Do the calculation. */
|
/* Do the calculation. */
|
||||||
rscale = MAX(scale, base->n_scale);
|
rscale = MAX(scale, base->n_scale);
|
||||||
while ( !bc_is_zero(exponent) )
|
while ( !bc_is_zero(exponent TSRMLS_CC) )
|
||||||
{
|
{
|
||||||
(void) bc_divmod (exponent, _two_, &exponent, &parity, 0);
|
(void) bc_divmod (exponent, BCG(_two_), &exponent, &parity, 0 TSRMLS_CC);
|
||||||
if ( !bc_is_zero(parity) )
|
if ( !bc_is_zero(parity TSRMLS_CC) )
|
||||||
{
|
{
|
||||||
bc_multiply (temp, power, &temp, rscale);
|
bc_multiply (temp, power, &temp, rscale TSRMLS_CC);
|
||||||
(void) bc_modulo (temp, mod, &temp, scale);
|
(void) bc_modulo (temp, mod, &temp, scale TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
|
||||||
bc_multiply (power, power, &power, rscale);
|
bc_multiply (power, power, &power, rscale TSRMLS_CC);
|
||||||
(void) bc_modulo (power, mod, &power, scale);
|
(void) bc_modulo (power, mod, &power, scale TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assign the value. */
|
/* Assign the value. */
|
||||||
|
|
|
@ -176,7 +176,7 @@ _bc_shift_addsub (bc_num accum, bc_num val, int shift, int sub)
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
_bc_rec_mul (bc_num u, int ulen, bc_num v, int vlen, bc_num *prod,
|
_bc_rec_mul (bc_num u, int ulen, bc_num v, int vlen, bc_num *prod,
|
||||||
int full_scale)
|
int full_scale TSRMLS_DC)
|
||||||
{
|
{
|
||||||
bc_num u0, u1, v0, v1;
|
bc_num u0, u1, v0, v1;
|
||||||
int u0len, v0len;
|
int u0len, v0len;
|
||||||
|
@ -197,14 +197,14 @@ _bc_rec_mul (bc_num u, int ulen, bc_num v, int vlen, bc_num *prod,
|
||||||
|
|
||||||
/* Split u and v. */
|
/* Split u and v. */
|
||||||
if (ulen < n) {
|
if (ulen < n) {
|
||||||
u1 = bc_copy_num (_zero_);
|
u1 = bc_copy_num (BCG(_zero_));
|
||||||
u0 = new_sub_num (ulen,0, u->n_value);
|
u0 = new_sub_num (ulen,0, u->n_value);
|
||||||
} else {
|
} else {
|
||||||
u1 = new_sub_num (ulen-n, 0, u->n_value);
|
u1 = new_sub_num (ulen-n, 0, u->n_value);
|
||||||
u0 = new_sub_num (n, 0, u->n_value+ulen-n);
|
u0 = new_sub_num (n, 0, u->n_value+ulen-n);
|
||||||
}
|
}
|
||||||
if (vlen < n) {
|
if (vlen < n) {
|
||||||
v1 = bc_copy_num (_zero_);
|
v1 = bc_copy_num (BCG(_zero_));
|
||||||
v0 = new_sub_num (vlen,0, v->n_value);
|
v0 = new_sub_num (vlen,0, v->n_value);
|
||||||
} else {
|
} else {
|
||||||
v1 = new_sub_num (vlen-n, 0, v->n_value);
|
v1 = new_sub_num (vlen-n, 0, v->n_value);
|
||||||
|
@ -217,12 +217,12 @@ _bc_rec_mul (bc_num u, int ulen, bc_num v, int vlen, bc_num *prod,
|
||||||
_bc_rm_leading_zeros (v0);
|
_bc_rm_leading_zeros (v0);
|
||||||
v0len = v0->n_len;
|
v0len = v0->n_len;
|
||||||
|
|
||||||
m1zero = bc_is_zero(u1) || bc_is_zero(v1);
|
m1zero = bc_is_zero(u1 TSRMLS_CC) || bc_is_zero(v1 TSRMLS_CC);
|
||||||
|
|
||||||
/* Calculate sub results ... */
|
/* Calculate sub results ... */
|
||||||
|
|
||||||
bc_init_num(&d1);
|
bc_init_num(&d1 TSRMLS_CC);
|
||||||
bc_init_num(&d2);
|
bc_init_num(&d2 TSRMLS_CC);
|
||||||
bc_sub (u1, u0, &d1, 0);
|
bc_sub (u1, u0, &d1, 0);
|
||||||
d1len = d1->n_len;
|
d1len = d1->n_len;
|
||||||
bc_sub (v0, v1, &d2, 0);
|
bc_sub (v0, v1, &d2, 0);
|
||||||
|
@ -231,19 +231,19 @@ _bc_rec_mul (bc_num u, int ulen, bc_num v, int vlen, bc_num *prod,
|
||||||
|
|
||||||
/* Do recursive multiplies and shifted adds. */
|
/* Do recursive multiplies and shifted adds. */
|
||||||
if (m1zero)
|
if (m1zero)
|
||||||
m1 = bc_copy_num (_zero_);
|
m1 = bc_copy_num (BCG(_zero_));
|
||||||
else
|
else
|
||||||
_bc_rec_mul (u1, u1->n_len, v1, v1->n_len, &m1, 0);
|
_bc_rec_mul (u1, u1->n_len, v1, v1->n_len, &m1, 0 TSRMLS_CC);
|
||||||
|
|
||||||
if (bc_is_zero(d1) || bc_is_zero(d2))
|
if (bc_is_zero(d1 TSRMLS_CC) || bc_is_zero(d2 TSRMLS_CC))
|
||||||
m2 = bc_copy_num (_zero_);
|
m2 = bc_copy_num (BCG(_zero_));
|
||||||
else
|
else
|
||||||
_bc_rec_mul (d1, d1len, d2, d2len, &m2, 0);
|
_bc_rec_mul (d1, d1len, d2, d2len, &m2, 0 TSRMLS_CC);
|
||||||
|
|
||||||
if (bc_is_zero(u0) || bc_is_zero(v0))
|
if (bc_is_zero(u0 TSRMLS_CC) || bc_is_zero(v0 TSRMLS_CC))
|
||||||
m3 = bc_copy_num (_zero_);
|
m3 = bc_copy_num (BCG(_zero_));
|
||||||
else
|
else
|
||||||
_bc_rec_mul (u0, u0->n_len, v0, v0->n_len, &m3, 0);
|
_bc_rec_mul (u0, u0->n_len, v0, v0->n_len, &m3, 0 TSRMLS_CC);
|
||||||
|
|
||||||
/* Initialize product */
|
/* Initialize product */
|
||||||
prodlen = ulen+vlen+1;
|
prodlen = ulen+vlen+1;
|
||||||
|
@ -274,9 +274,7 @@ _bc_rec_mul (bc_num u, int ulen, bc_num v, int vlen, bc_num *prod,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
bc_multiply (n1, n2, prod, scale)
|
bc_multiply (bc_num n1, bc_num n2, bc_num *prod, int scale TSRMLS_DC)
|
||||||
bc_num n1, n2, *prod;
|
|
||||||
int scale;
|
|
||||||
{
|
{
|
||||||
bc_num pval;
|
bc_num pval;
|
||||||
int len1, len2;
|
int len1, len2;
|
||||||
|
@ -289,7 +287,7 @@ bc_multiply (n1, n2, prod, scale)
|
||||||
prod_scale = MIN(full_scale,MAX(scale,MAX(n1->n_scale,n2->n_scale)));
|
prod_scale = MIN(full_scale,MAX(scale,MAX(n1->n_scale,n2->n_scale)));
|
||||||
|
|
||||||
/* Do the multiply */
|
/* Do the multiply */
|
||||||
_bc_rec_mul (n1, len1, n2, len2, &pval, full_scale);
|
_bc_rec_mul (n1, len1, n2, len2, &pval, full_scale TSRMLS_CC);
|
||||||
|
|
||||||
/* Assign to prod and clean up the number. */
|
/* Assign to prod and clean up the number. */
|
||||||
pval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS );
|
pval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS );
|
||||||
|
@ -297,7 +295,7 @@ bc_multiply (n1, n2, prod, scale)
|
||||||
pval->n_len = len2 + len1 + 1 - full_scale;
|
pval->n_len = len2 + len1 + 1 - full_scale;
|
||||||
pval->n_scale = prod_scale;
|
pval->n_scale = prod_scale;
|
||||||
_bc_rm_leading_zeros (pval);
|
_bc_rm_leading_zeros (pval);
|
||||||
if (bc_is_zero (pval))
|
if (bc_is_zero (pval TSRMLS_CC))
|
||||||
pval->n_sign = PLUS;
|
pval->n_sign = PLUS;
|
||||||
bc_free_num (prod);
|
bc_free_num (prod);
|
||||||
*prod = pval;
|
*prod = pval;
|
||||||
|
|
|
@ -42,16 +42,14 @@
|
||||||
after the decimal place. */
|
after the decimal place. */
|
||||||
|
|
||||||
int
|
int
|
||||||
bc_sqrt (num, scale)
|
bc_sqrt (bc_num *num, int scale TSRMLS_DC)
|
||||||
bc_num *num;
|
|
||||||
int scale;
|
|
||||||
{
|
{
|
||||||
int rscale, cmp_res, done;
|
int rscale, cmp_res, done;
|
||||||
int cscale;
|
int cscale;
|
||||||
bc_num guess, guess1, point5, diff;
|
bc_num guess, guess1, point5, diff;
|
||||||
|
|
||||||
/* Initial checks. */
|
/* Initial checks. */
|
||||||
cmp_res = bc_compare (*num, _zero_);
|
cmp_res = bc_compare (*num, BCG(_zero_));
|
||||||
if (cmp_res < 0)
|
if (cmp_res < 0)
|
||||||
return 0; /* error */
|
return 0; /* error */
|
||||||
else
|
else
|
||||||
|
@ -59,23 +57,23 @@ bc_sqrt (num, scale)
|
||||||
if (cmp_res == 0)
|
if (cmp_res == 0)
|
||||||
{
|
{
|
||||||
bc_free_num (num);
|
bc_free_num (num);
|
||||||
*num = bc_copy_num (_zero_);
|
*num = bc_copy_num (BCG(_zero_));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmp_res = bc_compare (*num, _one_);
|
cmp_res = bc_compare (*num, BCG(_one_));
|
||||||
if (cmp_res == 0)
|
if (cmp_res == 0)
|
||||||
{
|
{
|
||||||
bc_free_num (num);
|
bc_free_num (num);
|
||||||
*num = bc_copy_num (_one_);
|
*num = bc_copy_num (BCG(_one_));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the variables. */
|
/* Initialize the variables. */
|
||||||
rscale = MAX (scale, (*num)->n_scale);
|
rscale = MAX (scale, (*num)->n_scale);
|
||||||
bc_init_num(&guess);
|
bc_init_num(&guess TSRMLS_CC);
|
||||||
bc_init_num(&guess1);
|
bc_init_num(&guess1 TSRMLS_CC);
|
||||||
bc_init_num(&diff);
|
bc_init_num(&diff TSRMLS_CC);
|
||||||
point5 = bc_new_num (1,1);
|
point5 = bc_new_num (1,1);
|
||||||
point5->n_value[1] = 5;
|
point5->n_value[1] = 5;
|
||||||
|
|
||||||
|
@ -84,7 +82,7 @@ bc_sqrt (num, scale)
|
||||||
if (cmp_res < 0)
|
if (cmp_res < 0)
|
||||||
{
|
{
|
||||||
/* The number is between 0 and 1. Guess should start at 1. */
|
/* The number is between 0 and 1. Guess should start at 1. */
|
||||||
guess = bc_copy_num (_one_);
|
guess = bc_copy_num (BCG(_one_));
|
||||||
cscale = (*num)->n_scale;
|
cscale = (*num)->n_scale;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -93,9 +91,9 @@ bc_sqrt (num, scale)
|
||||||
bc_int2num (&guess,10);
|
bc_int2num (&guess,10);
|
||||||
|
|
||||||
bc_int2num (&guess1,(*num)->n_len);
|
bc_int2num (&guess1,(*num)->n_len);
|
||||||
bc_multiply (guess1, point5, &guess1, 0);
|
bc_multiply (guess1, point5, &guess1, 0 TSRMLS_CC);
|
||||||
guess1->n_scale = 0;
|
guess1->n_scale = 0;
|
||||||
bc_raise (guess, guess1, &guess, 0);
|
bc_raise (guess, guess1, &guess, 0 TSRMLS_CC);
|
||||||
bc_free_num (&guess1);
|
bc_free_num (&guess1);
|
||||||
cscale = 3;
|
cscale = 3;
|
||||||
}
|
}
|
||||||
|
@ -106,9 +104,9 @@ bc_sqrt (num, scale)
|
||||||
{
|
{
|
||||||
bc_free_num (&guess1);
|
bc_free_num (&guess1);
|
||||||
guess1 = bc_copy_num (guess);
|
guess1 = bc_copy_num (guess);
|
||||||
bc_divide (*num, guess, &guess, cscale);
|
bc_divide (*num, guess, &guess, cscale TSRMLS_CC);
|
||||||
bc_add (guess, guess1, &guess, 0);
|
bc_add (guess, guess1, &guess, 0);
|
||||||
bc_multiply (guess, point5, &guess, cscale);
|
bc_multiply (guess, point5, &guess, cscale TSRMLS_CC);
|
||||||
bc_sub (guess, guess1, &diff, cscale+1);
|
bc_sub (guess, guess1, &diff, cscale+1);
|
||||||
if (bc_is_near_zero (diff, cscale))
|
if (bc_is_near_zero (diff, cscale))
|
||||||
{
|
{
|
||||||
|
@ -121,7 +119,7 @@ bc_sqrt (num, scale)
|
||||||
|
|
||||||
/* Assign the number and clean up. */
|
/* Assign the number and clean up. */
|
||||||
bc_free_num (num);
|
bc_free_num (num);
|
||||||
bc_divide (guess,_one_,num,rscale);
|
bc_divide (guess,BCG(_one_),num,rscale TSRMLS_CC);
|
||||||
bc_free_num (&guess);
|
bc_free_num (&guess);
|
||||||
bc_free_num (&guess1);
|
bc_free_num (&guess1);
|
||||||
bc_free_num (&point5);
|
bc_free_num (&point5);
|
||||||
|
|
|
@ -41,10 +41,7 @@
|
||||||
/* Convert strings to bc numbers. Base 10 only.*/
|
/* Convert strings to bc numbers. Base 10 only.*/
|
||||||
|
|
||||||
void
|
void
|
||||||
bc_str2num (num, str, scale)
|
bc_str2num (bc_num *num, char *str, int scale TSRMLS_DC)
|
||||||
bc_num *num;
|
|
||||||
char *str;
|
|
||||||
int scale;
|
|
||||||
{
|
{
|
||||||
int digits, strscale;
|
int digits, strscale;
|
||||||
char *ptr, *nptr;
|
char *ptr, *nptr;
|
||||||
|
@ -65,7 +62,7 @@ bc_str2num (num, str, scale)
|
||||||
while (isdigit((int)*ptr)) ptr++, strscale++; /* digits */
|
while (isdigit((int)*ptr)) ptr++, strscale++; /* digits */
|
||||||
if ((*ptr != '\0') || (digits+strscale == 0))
|
if ((*ptr != '\0') || (digits+strscale == 0))
|
||||||
{
|
{
|
||||||
*num = bc_copy_num (_zero_);
|
*num = bc_copy_num (BCG(_zero_));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,14 +41,13 @@
|
||||||
/* In some places we need to check if the number NUM is zero. */
|
/* In some places we need to check if the number NUM is zero. */
|
||||||
|
|
||||||
char
|
char
|
||||||
bc_is_zero (num)
|
bc_is_zero (bc_num num TSRMLS_DC)
|
||||||
bc_num num;
|
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
char *nptr;
|
char *nptr;
|
||||||
|
|
||||||
/* Quick check. */
|
/* Quick check. */
|
||||||
if (num == _zero_) return TRUE;
|
if (num == BCG(_zero_)) return TRUE;
|
||||||
|
|
||||||
/* Initialize */
|
/* Initialize */
|
||||||
count = num->n_len + num->n_scale;
|
count = num->n_len + num->n_scale;
|
||||||
|
|
|
@ -23,9 +23,30 @@
|
||||||
|
|
||||||
#if WITH_BCMATH
|
#if WITH_BCMATH
|
||||||
|
|
||||||
|
#include "libbcmath/src/bcmath.h"
|
||||||
|
|
||||||
|
ZEND_BEGIN_MODULE_GLOBALS(bcmath)
|
||||||
|
bc_num _zero_;
|
||||||
|
bc_num _one_;
|
||||||
|
bc_num _two_;
|
||||||
|
ZEND_END_MODULE_GLOBALS(bcmath)
|
||||||
|
|
||||||
|
#if ZTS
|
||||||
|
# define BCG(v) TSRMG(bcmath_globals_id, zend_bcmath_globals *, v)
|
||||||
|
extern int bcmath_globals_id;
|
||||||
|
#else
|
||||||
|
# define BCG(v) (bcmath_globals.v)
|
||||||
|
extern zend_bcmath_globals bcmath_globals;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BC
|
||||||
|
|
||||||
extern zend_module_entry bcmath_module_entry;
|
extern zend_module_entry bcmath_module_entry;
|
||||||
#define phpext_bcmath_ptr &bcmath_module_entry
|
#define phpext_bcmath_ptr &bcmath_module_entry
|
||||||
|
|
||||||
|
#if ZTS
|
||||||
|
PHP_MINIT_FUNCTION(bcmath);
|
||||||
|
#endif
|
||||||
PHP_RINIT_FUNCTION(bcmath);
|
PHP_RINIT_FUNCTION(bcmath);
|
||||||
PHP_RSHUTDOWN_FUNCTION(bcmath);
|
PHP_RSHUTDOWN_FUNCTION(bcmath);
|
||||||
PHP_MINFO_FUNCTION(bcmath);
|
PHP_MINFO_FUNCTION(bcmath);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue