BCmath extension code reformatting (#11896)

Re-formats the BCmath extension to have consistent formatting.

Mostly, it adds the spaces in calculations to have them more readable.

Also:

   -  removes unused headers
   -  removes few variables which are used only once in the code

Co-authored-by: George Peter Banyard <girgias@php.net>
This commit is contained in:
Jorg Adam Sowa 2023-08-13 17:17:36 +02:00 committed by GitHub
parent bb092ab4c6
commit e56ed6e1ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 265 additions and 286 deletions

View file

@ -39,34 +39,30 @@
N1 is added to N2 and the result placed into RESULT. SCALE_MIN N1 is added to N2 and the result placed into RESULT. SCALE_MIN
is the minimum scale for the result. */ is the minimum scale for the result. */
void bc_add (bc_num n1, bc_num n2, bc_num *result, size_t scale_min) void bc_add(bc_num n1, bc_num n2, bc_num *result, size_t scale_min)
{ {
bc_num sum = NULL; bc_num sum = NULL;
int cmp_res;
size_t res_scale;
if (n1->n_sign == n2->n_sign) { if (n1->n_sign == n2->n_sign) {
sum = _bc_do_add (n1, n2, scale_min); sum = _bc_do_add(n1, n2, scale_min);
sum->n_sign = n1->n_sign; sum->n_sign = n1->n_sign;
} else { } else {
/* subtraction must be done. */ /* subtraction must be done. */
/* Compare magnitudes. */ /* Compare magnitudes. */
cmp_res = _bc_do_compare(n1, n2, false, false); switch (_bc_do_compare(n1, n2, false, false)) {
switch (cmp_res) {
case -1: case -1:
/* n1 is less than n2, subtract n1 from n2. */ /* n1 is less than n2, subtract n1 from n2. */
sum = _bc_do_sub (n2, n1, scale_min); sum = _bc_do_sub(n2, n1, scale_min);
sum->n_sign = n2->n_sign; sum->n_sign = n2->n_sign;
break; break;
case 0: case 0:
/* They are equal! return zero with the correct scale! */ /* 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, MAX(scale_min, MAX(n1->n_scale, n2->n_scale)));
sum = bc_new_num (1, res_scale); memset(sum->n_value, 0, sum->n_scale + 1);
memset (sum->n_value, 0, res_scale+1);
break; break;
case 1: case 1:
/* n2 is less than n1, subtract n2 from n1. */ /* n2 is less than n1, subtract n2 from n1. */
sum = _bc_do_sub (n1, n2, scale_min); sum = _bc_do_sub(n1, n2, scale_min);
sum->n_sign = n1->n_sign; sum->n_sign = n1->n_sign;
} }
} }

View file

@ -61,7 +61,7 @@ typedef struct bc_struct {
#include "../../php_bcmath.h" /* Needed for BCG() macro */ #include "../../php_bcmath.h" /* Needed for BCG() macro */
/* 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. */
#define BASE 10 #define BASE 10

View file

@ -30,9 +30,9 @@
*************************************************************************/ *************************************************************************/
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h>
#include "bcmath.h" #include "bcmath.h"
#include "private.h" #include "private.h"
#include <stddef.h>
/* Compare two bc numbers. Return value is 0 if equal, -1 if N1 is less /* Compare two bc numbers. Return value is 0 if equal, -1 if N1 is less
@ -46,9 +46,11 @@ int _bc_do_compare(bc_num n1, bc_num n2, bool use_sign, bool ignore_last)
/* First, compare signs. */ /* First, compare signs. */
if (use_sign && n1->n_sign != n2->n_sign) { if (use_sign && n1->n_sign != n2->n_sign) {
if (n1->n_sign == PLUS) { if (n1->n_sign == PLUS) {
return (1); /* Positive N1 > Negative N2 */ /* Positive N1 > Negative N2 */
return (1);
} else { } else {
return (-1); /* Negative N1 < Positive N1 */ /* Negative N1 < Positive N1 */
return (-1);
} }
} }
@ -107,7 +109,7 @@ int _bc_do_compare(bc_num n1, bc_num n2, bool use_sign, bool ignore_last)
/* They are equal up to the last part of the equal part of the fraction. */ /* 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) {
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--) { for (count = n1->n_scale - n2->n_scale; count > 0; count--) {
if (*n1ptr++ != 0) { if (*n1ptr++ != 0) {
/* Magnitude of n1 > n2. */ /* Magnitude of n1 > n2. */
if (!use_sign || n1->n_sign == PLUS) { if (!use_sign || n1->n_sign == PLUS) {
@ -118,7 +120,7 @@ int _bc_do_compare(bc_num n1, bc_num n2, bool use_sign, bool ignore_last)
} }
} }
} else { } else {
for (count = n2->n_scale-n1->n_scale; count>0; count--) { for (count = n2->n_scale - n1->n_scale; count > 0; count--) {
if (*n2ptr++ != 0) { if (*n2ptr++ != 0) {
/* Magnitude of n1 < n2. */ /* Magnitude of n1 < n2. */
if (!use_sign || n1->n_sign == PLUS) { if (!use_sign || n1->n_sign == PLUS) {

View file

@ -36,7 +36,7 @@
/* pn prints the number NUM in base 10. */ /* pn prints the number NUM in base 10. */
static void out_char (char c) static void out_char(char c)
{ {
putchar(c); putchar(c);
} }
@ -45,16 +45,16 @@ static void out_char (char c)
void pn(bc_num num) void pn(bc_num num)
{ {
bc_out_num(num, 10, out_char, 0); bc_out_num(num, 10, out_char, 0);
out_char ('\n'); out_char('\n');
} }
/* pv prints a character array as if it was a string of bcd digits. */ /* pv prints a character array as if it was a string of bcd digits. */
void pv (char *name, unsigned char *num, size_t len) void pv(char *name, unsigned char *num, size_t len)
{ {
printf("%s=", name); printf("%s=", name);
for (size_t i = 0; i < len; i++){ for (size_t i = 0; i < len; i++) {
printf ("%c",BCD_CHAR(num[i])); printf("%c", BCD_CHAR(num[i]));
} }
printf("\n"); printf("\n");
} }

View file

@ -33,6 +33,7 @@
#include "private.h" #include "private.h"
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <string.h>
#include "zend_alloc.h" #include "zend_alloc.h"
@ -43,7 +44,7 @@
static void _one_mult(unsigned char *num, size_t size, int digit, unsigned char *result) static void _one_mult(unsigned char *num, size_t size, int digit, unsigned char *result)
{ {
int carry, value; size_t carry, value;
unsigned char *nptr, *rptr; unsigned char *nptr, *rptr;
if (digit == 0) { if (digit == 0) {
@ -53,8 +54,8 @@ static void _one_mult(unsigned char *num, size_t size, int digit, unsigned char
memcpy(result, num, size); memcpy(result, num, size);
} else { } else {
/* Initialize */ /* Initialize */
nptr = (unsigned char *) (num+size-1); nptr = (unsigned char *) (num + size - 1);
rptr = (unsigned char *) (result+size-1); rptr = (unsigned char *) (result + size - 1);
carry = 0; carry = 0;
while (size-- > 0) { while (size-- > 0) {
@ -74,59 +75,55 @@ static void _one_mult(unsigned char *num, size_t size, int digit, unsigned char
/* The full division routine. This computes N1 / N2. It returns /* The full division routine. This computes N1 / N2. It returns
true if the division is ok and the result is in QUOT. The number of 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 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. */ by zero is tried. The algorithm is found in Knuth Vol 2. p237. */
bool 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; bc_num qval;
unsigned char *num1, *num2; unsigned char *num1, *num2;
unsigned char *ptr1, *ptr2, *n2ptr, *qptr; unsigned char *ptr1, *ptr2, *n2ptr, *qptr;
int scale1, val; int scale1, val;
unsigned int len1, len2, scale2, qdigits, extra, count; unsigned int len1, len2, scale2, qdigits, extra, count;
unsigned int qdig, qguess, borrow, carry; unsigned int qdig, qguess, borrow, carry;
unsigned char *mval; unsigned char *mval;
unsigned int norm;
bool zero; bool zero;
unsigned int norm;
/* Test for divide by zero. */ /* Test for divide by zero. */
if (bc_is_zero(n2)) { if (bc_is_zero(n2)) {
return false; return false;
} }
/* 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 && n2->n_len == 1 && *n2->n_value == 1) {
if (n2->n_len == 1 && *n2->n_value == 1) { qval = bc_new_num (n1->n_len, scale);
qval = bc_new_num (n1->n_len, scale); qval->n_sign = (n1->n_sign == n2->n_sign ? PLUS : MINUS);
qval->n_sign = (n1->n_sign == n2->n_sign ? PLUS : MINUS); memset(&qval->n_value[n1->n_len], 0, scale);
memset (&qval->n_value[n1->n_len],0,scale); memcpy(qval->n_value, n1->n_value, n1->n_len + MIN(n1->n_scale, scale));
memcpy (qval->n_value, n1->n_value, n1->n_len + MIN(n1->n_scale,scale)); bc_free_num (quot);
bc_free_num (quot); *quot = qval;
*quot = qval;
}
} }
/* Set up the divide. Move the decimal point on n1 by n2's scale. /* 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. */ Remember, zeros on the end of num2 are wasted effort for dividing. */
scale2 = n2->n_scale; scale2 = n2->n_scale;
n2ptr = (unsigned char *) n2->n_value+n2->n_len+scale2-1; n2ptr = (unsigned char *) n2->n_value + n2->n_len + scale2 - 1;
while ((scale2 > 0) && (*n2ptr-- == 0)) { while ((scale2 > 0) && (*n2ptr == 0)) {
scale2--; scale2--;
n2ptr--;
} }
len1 = n1->n_len + scale2; len1 = n1->n_len + scale2;
scale1 = n1->n_scale - scale2; scale1 = n1->n_scale - scale2;
if (scale1 < scale) { extra = MAX(scale - scale1, 0);
extra = scale - scale1;
} else { num1 = (unsigned char *) safe_emalloc(1, n1->n_len + n1->n_scale, extra + 2);
extra = 0; memset(num1, 0, n1->n_len + n1->n_scale + extra + 2);
} memcpy(num1 + 1, n1->n_value, n1->n_len + n1->n_scale);
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; len2 = n2->n_len + scale2;
num2 = (unsigned char *) safe_emalloc (1, len2, 1); num2 = (unsigned char *) safe_emalloc(1, len2, 1);
memcpy (num2, n2->n_value, len2); memcpy(num2, n2->n_value, len2);
*(num2+len2) = 0; *(num2 + len2) = 0;
n2ptr = num2; n2ptr = num2;
while (*n2ptr == 0) { while (*n2ptr == 0) {
n2ptr++; n2ptr++;
@ -134,22 +131,22 @@ bool bc_divide(bc_num n1, bc_num n2, bc_num *quot, int scale)
} }
/* Calculate the number of quotient digits. */ /* Calculate the number of quotient digits. */
if (len2 > len1+scale) { if (len2 > len1 + scale) {
qdigits = scale+1; qdigits = scale + 1;
zero = true; zero = true;
} else { } else {
zero = false; zero = false;
if (len2 > len1) { if (len2 > len1) {
/* One for the zero integer part. */ /* One for the zero integer part. */
qdigits = scale+1; qdigits = scale + 1;
} else { } else {
qdigits = len1-len2+scale+1; qdigits = len1 - len2 + scale + 1;
} }
} }
/* Allocate and zero the storage for the quotient. */ /* Allocate and zero the storage for the quotient. */
qval = bc_new_num (qdigits-scale,scale); qval = bc_new_num (qdigits - scale, scale);
memset (qval->n_value, 0, qdigits); memset(qval->n_value, 0, qdigits);
/* Allocate storage for the temporary storage mval. */ /* Allocate storage for the temporary storage mval. */
mval = (unsigned char *) safe_emalloc(1, len2, 1); mval = (unsigned char *) safe_emalloc(1, len2, 1);
@ -157,38 +154,34 @@ bool bc_divide(bc_num n1, bc_num n2, bc_num *quot, int scale)
/* Now for the full divide algorithm. */ /* Now for the full divide algorithm. */
if (!zero) { if (!zero) {
/* Normalize */ /* Normalize */
norm = 10 / ((int)*n2ptr + 1); norm = 10 / ((int) *n2ptr + 1);
if (norm != 1) { if (norm != 1) {
_one_mult (num1, len1+scale1+extra+1, norm, num1); _one_mult(num1, len1 + scale1 + extra + 1, norm, num1);
_one_mult (n2ptr, len2, norm, n2ptr); _one_mult(n2ptr, len2, norm, n2ptr);
} }
/* Initialize divide loop. */ /* Initialize divide loop. */
qdig = 0; qdig = 0;
if (len2 > len1) { if (len2 > len1) {
qptr = (unsigned char *) qval->n_value+len2-len1; qptr = (unsigned char *) qval->n_value + len2 - len1;
} else { } else {
qptr = (unsigned char *) qval->n_value; qptr = (unsigned char *) qval->n_value;
} }
/* Loop */ /* Loop */
while (qdig <= len1+scale-len2) { while (qdig <= len1 + scale - len2) {
/* Calculate the quotient digit guess. */ /* Calculate the quotient digit guess. */
if (*n2ptr == num1[qdig]) { if (*n2ptr == num1[qdig]) {
qguess = 9; qguess = 9;
} else { } else {
qguess = (num1[qdig]*10 + num1[qdig+1]) / *n2ptr; qguess = (num1[qdig] * 10 + num1[qdig + 1]) / *n2ptr;
} }
/* Test qguess. */ /* Test qguess. */
if ( if (n2ptr[1] * qguess > (num1[qdig] * 10 + num1[qdig + 1] - *n2ptr * qguess) * 10 + num1[qdig + 2]) {
n2ptr[1]*qguess > (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10 + num1[qdig+2]
) {
qguess--; qguess--;
/* And again. */ /* And again. */
if ( if (n2ptr[1] * qguess > (num1[qdig] * 10 + num1[qdig + 1] - *n2ptr * qguess) * 10 + num1[qdig + 2]) {
n2ptr[1]*qguess > (num1[qdig]*10 + num1[qdig+1] - *n2ptr*qguess)*10 + num1[qdig+2]
) {
qguess--; qguess--;
} }
} }
@ -197,10 +190,10 @@ bool bc_divide(bc_num n1, bc_num n2, bc_num *quot, int scale)
borrow = 0; borrow = 0;
if (qguess != 0) { if (qguess != 0) {
*mval = 0; *mval = 0;
_one_mult (n2ptr, len2, qguess, mval+1); _one_mult(n2ptr, len2, qguess, mval + 1);
ptr1 = (unsigned char *) num1+qdig+len2; ptr1 = (unsigned char *) num1 + qdig + len2;
ptr2 = (unsigned char *) mval+len2; ptr2 = (unsigned char *) mval + len2;
for (count = 0; count < len2+1; count++) { for (count = 0; count < len2 + 1; count++) {
val = (int) *ptr1 - (int) *ptr2-- - borrow; val = (int) *ptr1 - (int) *ptr2-- - borrow;
if (val < 0) { if (val < 0) {
val += 10; val += 10;
@ -215,8 +208,8 @@ bool bc_divide(bc_num n1, bc_num n2, bc_num *quot, int scale)
/* Test for negative result. */ /* Test for negative result. */
if (borrow == 1) { if (borrow == 1) {
qguess--; qguess--;
ptr1 = (unsigned char *) num1+qdig+len2; ptr1 = (unsigned char *) num1 + qdig + len2;
ptr2 = (unsigned char *) n2ptr+len2-1; ptr2 = (unsigned char *) n2ptr + len2 - 1;
carry = 0; carry = 0;
for (count = 0; count < len2; count++) { for (count = 0; count < len2; count++) {
val = (int) *ptr1 + (int) *ptr2-- + carry; val = (int) *ptr1 + (int) *ptr2-- + carry;
@ -240,7 +233,7 @@ bool bc_divide(bc_num n1, bc_num n2, bc_num *quot, int 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)) { if (bc_is_zero(qval)) {
qval->n_sign = PLUS; qval->n_sign = PLUS;
} }

View file

@ -53,16 +53,16 @@ bool bc_divmod(bc_num num1, bc_num num2, bc_num *quot, bc_num *rem, size_t scale
} }
/* 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);
/* Calculate it. */ /* Calculate it. */
bc_divide (num1, num2, &temp, 0); bc_divide(num1, num2, &temp, 0);
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);
bc_sub (num1, temp, rem, rscale); bc_sub(num1, temp, rem, rscale);
bc_free_num (&temp); bc_free_num (&temp);
if (quot) { if (quot) {

View file

@ -69,12 +69,12 @@ bc_num _bc_do_add(bc_num n1, bc_num n2, size_t scale_min)
/* Add the fraction part. First copy the longer fraction.*/ /* Add the fraction part. First copy the longer fraction.*/
if (n1bytes != n2bytes) { if (n1bytes != n2bytes) {
if (n1bytes > n2bytes) { if (n1bytes > n2bytes) {
while (n1bytes>n2bytes) { while (n1bytes > n2bytes) {
*sumptr-- = *n1ptr--; *sumptr-- = *n1ptr--;
n1bytes--; n1bytes--;
} }
} else { } else {
while (n2bytes>n1bytes) { while (n2bytes > n1bytes) {
*sumptr-- = *n2ptr--; *sumptr-- = *n2ptr--;
n2bytes--; n2bytes--;
} }
@ -87,7 +87,7 @@ bc_num _bc_do_add(bc_num n1, bc_num n2, size_t scale_min)
carry = 0; carry = 0;
while ((n1bytes > 0) && (n2bytes > 0)) { while ((n1bytes > 0) && (n2bytes > 0)) {
*sumptr = *n1ptr-- + *n2ptr-- + carry; *sumptr = *n1ptr-- + *n2ptr-- + carry;
if (*sumptr > (BASE-1)) { if (*sumptr > (BASE - 1)) {
carry = 1; carry = 1;
*sumptr -= BASE; *sumptr -= BASE;
} else { } else {
@ -105,7 +105,7 @@ bc_num _bc_do_add(bc_num n1, bc_num n2, size_t scale_min)
} }
while (n1bytes-- > 0) { while (n1bytes-- > 0) {
*sumptr = *n1ptr-- + carry; *sumptr = *n1ptr-- + carry;
if (*sumptr > (BASE-1)) { if (*sumptr > (BASE - 1)) {
carry = true; carry = true;
*sumptr -= BASE; *sumptr -= BASE;
} else { } else {
@ -120,7 +120,7 @@ bc_num _bc_do_add(bc_num n1, bc_num n2, size_t scale_min)
} }
/* Adjust sum and return. */ /* Adjust sum and return. */
_bc_rm_leading_zeros (sum); _bc_rm_leading_zeros(sum);
return sum; return sum;
} }
@ -132,10 +132,11 @@ 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) bc_num _bc_do_sub(bc_num n1, bc_num n2, size_t scale_min)
{ {
bc_num diff; bc_num diff;
int diff_scale, diff_len; size_t diff_scale, diff_len;
size_t min_scale, min_len; size_t min_scale, min_len;
size_t borrow, count;
int val;
char *n1ptr, *n2ptr, *diffptr; char *n1ptr, *n2ptr, *diffptr;
int borrow, count, val;
/* Allocate temporary storage. */ /* Allocate temporary storage. */
diff_len = MAX(n1->n_len, n2->n_len); diff_len = MAX(n1->n_len, n2->n_len);
@ -153,9 +154,9 @@ bc_num _bc_do_sub(bc_num n1, bc_num n2, size_t scale_min)
} }
/* Initialize the subtract. */ /* Initialize the subtract. */
n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale -1); n1ptr = (char *) (n1->n_value + n1->n_len + n1->n_scale - 1);
n2ptr = (char *) (n2->n_value + n2->n_len + n2->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); diffptr = (char *) (diff->n_value + diff_len + diff_scale - 1);
/* Subtract the numbers. */ /* Subtract the numbers. */
borrow = 0; borrow = 0;
@ -169,7 +170,7 @@ bc_num _bc_do_sub(bc_num n1, bc_num n2, size_t scale_min)
} else { } else {
/* n2 has the longer scale */ /* n2 has the longer scale */
for (count = n2->n_scale - min_scale; count > 0; count--) { for (count = n2->n_scale - min_scale; count > 0; count--) {
val = - *n2ptr-- - borrow; val = -*n2ptr-- - borrow;
if (val < 0) { if (val < 0) {
val += BASE; val += BASE;
borrow = 1; borrow = 1;
@ -192,7 +193,7 @@ bc_num _bc_do_sub(bc_num n1, bc_num n2, size_t scale_min)
*diffptr-- = val; *diffptr-- = val;
} }
/* If n1 has more digits then n2, we now do that subtract. */ /* If n1 has more digits than n2, we now do that subtract. */
if (diff_len != min_len) { if (diff_len != min_len) {
for (count = diff_len - min_len; count > 0; count--) { for (count = diff_len - min_len; count > 0; count--) {
val = *n1ptr-- - borrow; val = *n1ptr-- - borrow;
@ -207,6 +208,6 @@ bc_num _bc_do_sub(bc_num n1, bc_num n2, size_t scale_min)
} }
/* Clean up and return. */ /* Clean up and return. */
_bc_rm_leading_zeros (diff); _bc_rm_leading_zeros(diff);
return diff; return diff;
} }

View file

@ -32,22 +32,22 @@
#include "bcmath.h" #include "bcmath.h"
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <string.h>
#include "zend_alloc.h" #include "zend_alloc.h"
/* new_num allocates a number and sets fields to known values. */ /* new_num allocates a number and sets fields to known values. */
bc_num _bc_new_num_ex(size_t length, size_t scale, bool 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 */ /* PHP Change: malloc() -> pemalloc(), removed free_list code */
temp = (bc_num) safe_pemalloc (1, sizeof(bc_struct)+length, scale, persistent); bc_num temp = (bc_num) safe_pemalloc(1, sizeof(bc_struct) + length, scale, persistent);
temp->n_sign = PLUS; temp->n_sign = PLUS;
temp->n_len = length; temp->n_len = length;
temp->n_scale = scale; temp->n_scale = scale;
temp->n_refs = 1; temp->n_refs = 1;
/* PHP Change: malloc() -> pemalloc() */ /* PHP Change: malloc() -> pemalloc() */
temp->n_ptr = (char *) safe_pemalloc (1, length, scale, persistent); temp->n_ptr = (char *) safe_pemalloc(1, length, scale, persistent);
temp->n_value = temp->n_ptr; temp->n_value = temp->n_ptr;
memset (temp->n_ptr, 0, length+scale); memset(temp->n_ptr, 0, length + scale);
return temp; return temp;
} }
@ -63,7 +63,7 @@ void _bc_free_num_ex(bc_num *num, bool persistent)
if ((*num)->n_refs == 0) { if ((*num)->n_refs == 0) {
if ((*num)->n_ptr) { if ((*num)->n_ptr) {
/* PHP Change: free() -> pefree(), removed free_list code */ /* PHP Change: free() -> pefree(), removed free_list code */
pefree ((*num)->n_ptr, persistent); pefree((*num)->n_ptr, persistent);
} }
pefree(*num, persistent); pefree(*num, persistent);
} }
@ -75,10 +75,10 @@ void _bc_free_num_ex(bc_num *num, bool persistent)
void bc_init_numbers(void) void bc_init_numbers(void)
{ {
BCG(_zero_) = _bc_new_num_ex (1,0,1); BCG(_zero_) = _bc_new_num_ex(1, 0, 1);
BCG(_one_) = _bc_new_num_ex (1,0,1); BCG(_one_) = _bc_new_num_ex(1, 0, 1);
BCG(_one_)->n_value[0] = 1; BCG(_one_)->n_value[0] = 1;
BCG(_two_) = _bc_new_num_ex (1,0,1); BCG(_two_) = _bc_new_num_ex(1, 0, 1);
BCG(_two_)->n_value[0] = 2; BCG(_two_)->n_value[0] = 2;
} }

View file

@ -37,7 +37,7 @@ void bc_int2num(bc_num *num, int val)
{ {
char buffer[30]; char buffer[30];
char *bptr, *vptr; char *bptr, *vptr;
int ix = 1; int ix = 1;
char neg = 0; char neg = 0;
/* Sign. */ /* Sign. */
@ -55,7 +55,8 @@ void bc_int2num(bc_num *num, int val)
while (val != 0) { while (val != 0) {
*bptr++ = val % BASE; *bptr++ = val % BASE;
val = val / BASE; val = val / BASE;
ix++; /* Count the digits. */ /* Count the digits. */
ix++;
} }
/* Make the number. */ /* Make the number. */

View file

@ -30,8 +30,8 @@
*************************************************************************/ *************************************************************************/
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h>
#include "bcmath.h" #include "bcmath.h"
#include <stddef.h>
/* In some places we need to check if the number NUM is almost zero. /* 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. Specifically, all but the last digit is 0 and the last digit is 1.
@ -53,9 +53,5 @@ bool bc_is_near_zero(bc_num num, size_t scale)
count--; count--;
} }
if (count != 0 && (count != 1 || *--nptr != 1)) { return count == 0 || (count == 1 && *--nptr == 1);
return false;
} else {
return true;
}
} }

View file

@ -39,16 +39,13 @@
long bc_num2long(bc_num num) long bc_num2long(bc_num num)
{ {
long val;
char *nptr;
/* Extract the int value, ignore the fraction. */ /* Extract the int value, ignore the fraction. */
val = 0; long val = 0;
nptr = num->n_value; const char *nptr = num->n_value;
for (size_t index = num->n_len; index > 0; index--) { for (size_t index = num->n_len; index > 0; index--) {
char n = *nptr++; char n = *nptr++;
if (val > LONG_MAX/BASE) { if (val > LONG_MAX / BASE) {
return 0; return 0;
} }
val *= BASE; val *= BASE;

View file

@ -38,8 +38,8 @@ zend_string *bc_num2str_ex(bc_num num, size_t scale)
{ {
zend_string *str; zend_string *str;
char *sptr; char *sptr;
char *nptr; size_t index;
int index, signch; bool signch;
/* Number of sign chars. */ /* Number of sign chars. */
signch = num->n_sign != PLUS && !bc_is_zero_for_scale(num, MIN(num->n_scale, scale)); signch = num->n_sign != PLUS && !bc_is_zero_for_scale(num, MIN(num->n_scale, scale));
@ -55,18 +55,18 @@ zend_string *bc_num2str_ex(bc_num num, size_t scale)
if (signch) *sptr++ = '-'; if (signch) *sptr++ = '-';
/* Load the whole number. */ /* Load the whole number. */
nptr = num->n_value; const char *nptr = num->n_value;
for (index=num->n_len; index>0; index--) { for (index = num->n_len; index > 0; index--) {
*sptr++ = BCD_CHAR(*nptr++); *sptr++ = BCD_CHAR(*nptr++);
} }
/* Now the fraction. */ /* Now the fraction. */
if (scale > 0) { if (scale > 0) {
*sptr++ = '.'; *sptr++ = '.';
for (index=0; index<scale && index<num->n_scale; index++) { for (index = 0; index < scale && index < num->n_scale; index++) {
*sptr++ = BCD_CHAR(*nptr++); *sptr++ = BCD_CHAR(*nptr++);
} }
for (index = num->n_scale; index<scale; index++) { for (index = num->n_scale; index < scale; index++) {
*sptr++ = BCD_CHAR(0); *sptr++ = BCD_CHAR(0);
} }
} }

View file

@ -31,6 +31,7 @@
#include "bcmath.h" #include "bcmath.h"
#include <stdbool.h> #include <stdbool.h>
#include <string.h>
#include "zend_alloc.h" #include "zend_alloc.h"
@ -39,7 +40,7 @@
/* This structure is used for saving digits in the conversion process. */ /* This structure is used for saving digits in the conversion process. */
typedef struct stk_rec { typedef struct stk_rec {
long digit; long digit;
struct stk_rec *next; struct stk_rec *next;
} stk_rec; } stk_rec;
@ -52,93 +53,93 @@ static const char ref_str[] = "0123456789ABCDEF";
non-zero, we must output one space before the number. OUT_CHAR non-zero, we must output one space before the number. OUT_CHAR
is the actual routine for writing the characters. */ is the actual routine for writing the characters. */
void bc_out_long (long val, size_t size, bool space, void (*out_char)(char) ) void bc_out_long(long val, size_t size, bool space, void (*out_char)(char))
{ {
char digits[40]; char digits[40];
size_t len, ix; size_t len, ix;
if (space) (*out_char) (' '); if (space) (*out_char)(' ');
snprintf(digits, sizeof(digits), "%ld", val); snprintf(digits, sizeof(digits), "%ld", val);
len = strlen(digits); len = strlen(digits);
while (size > len) { while (size > len) {
(*out_char) ('0'); (*out_char)('0');
size--; size--;
} }
for (ix=0; ix < len; ix++) { for (ix = 0; ix < len; ix++) {
(*out_char) (digits[ix]); (*out_char)(digits[ix]);
} }
} }
/* Output of a bcd number. NUM is written in base O_BASE using OUT_CHAR /* 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. */ 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), bool leading_zero) void bc_out_num(bc_num num, int o_base, void (*out_char)(char), bool leading_zero)
{ {
char *nptr; char *nptr;
int index, fdigit; int index, fdigit;
bool pre_space; bool pre_space;
stk_rec *digits, *temp; stk_rec *digits, *temp;
bc_num int_part, frac_part, base, cur_dig, t_num, max_o_digit; bc_num int_part, frac_part, base, cur_dig, t_num, max_o_digit;
/* The negative sign if needed. */ /* The negative sign if needed. */
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)) {
(*out_char) ('0'); (*out_char)('0');
} else { } else {
if (o_base == 10) { if (o_base == 10) {
/* The number is in base 10, do it the fast way. */ /* The number is in base 10, do it the fast way. */
nptr = num->n_value; nptr = num->n_value;
if (num->n_len > 1 || *nptr != 0) { if (num->n_len > 1 || *nptr != 0) {
for (index=num->n_len; index>0; index--) { for (index = num->n_len; index > 0; index--) {
(*out_char) (BCD_CHAR(*nptr++)); (*out_char)(BCD_CHAR(*nptr++));
} }
} else { } else {
nptr++; nptr++;
} }
if (leading_zero && bc_is_zero(num)) { if (leading_zero && bc_is_zero(num)) {
(*out_char) ('0'); (*out_char)('0');
} }
/* Now the fraction. */ /* Now the fraction. */
if (num->n_scale > 0) { if (num->n_scale > 0) {
(*out_char) ('.'); (*out_char)('.');
for (index=0; index<num->n_scale; index++) { for (index = 0; index < num->n_scale; index++) {
(*out_char) (BCD_CHAR(*nptr++)); (*out_char)(BCD_CHAR(*nptr++));
} }
} }
} else { } else {
/* special case ... */ /* special case ... */
if (leading_zero && bc_is_zero (num)) { if (leading_zero && bc_is_zero(num)) {
(*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);
bc_divide (num, BCG(_one_), &int_part, 0); bc_divide(num, BCG(_one_), &int_part, 0);
bc_init_num (&frac_part); bc_init_num(&frac_part);
bc_init_num (&cur_dig); bc_init_num(&cur_dig);
bc_init_num (&base); bc_init_num(&base);
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);
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)) {
bc_modulo (int_part, base, &cur_dig, 0); bc_modulo(int_part, base, &cur_dig, 0);
/* PHP Change: malloc() -> emalloc() */ /* PHP Change: malloc() -> emalloc() */
temp = (stk_rec *) emalloc (sizeof(stk_rec)); temp = (stk_rec *) emalloc(sizeof(stk_rec));
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);
} }
/* Print the digits on the stack. */ /* Print the digits on the stack. */
@ -148,9 +149,9 @@ void bc_out_num (bc_num num, int o_base, void (*out_char)(char), bool leading_ze
temp = digits; temp = digits;
digits = digits->next; digits = digits->next;
if (o_base <= 16) { if (o_base <= 16) {
(*out_char) (ref_str[ (int) temp->digit]); (*out_char)(ref_str[(int) temp->digit]);
} else { } else {
bc_out_long (temp->digit, max_o_digit->n_len, 1, out_char); bc_out_long(temp->digit, max_o_digit->n_len, 1, out_char);
} }
efree(temp); efree(temp);
} }
@ -158,21 +159,21 @@ void bc_out_num (bc_num num, int o_base, void (*out_char)(char), bool leading_ze
/* Get and print the digits of the fraction part. */ /* Get and print the digits of the fraction part. */
if (num->n_scale > 0) { if (num->n_scale > 0) {
(*out_char) ('.'); (*out_char)('.');
pre_space = false; pre_space = false;
t_num = bc_copy_num (BCG(_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);
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);
if (o_base <= 16) { if (o_base <= 16) {
(*out_char) (ref_str[fdigit]); (*out_char)(ref_str[fdigit]);
} else { } else {
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 = true; pre_space = true;
} }
bc_multiply (t_num, base, &t_num, 0); bc_multiply(t_num, base, &t_num, 0);
} }
bc_free_num (&t_num); bc_free_num (&t_num);
} }

View file

@ -50,7 +50,7 @@ void bc_raise(bc_num num1, long exponent, bc_num *result, size_t scale)
/* Special case if exponent is a zero. */ /* Special case if exponent is a zero. */
if (exponent == 0) { if (exponent == 0) {
bc_free_num (result); bc_free_num (result);
*result = bc_copy_num (BCG(_one_)); *result = bc_copy_num(BCG(_one_));
return; return;
} }
@ -61,35 +61,35 @@ void bc_raise(bc_num num1, long exponent, bc_num *result, size_t scale)
rscale = scale; rscale = scale;
} else { } else {
is_neg = false; is_neg = false;
rscale = MIN (num1->n_scale*exponent, MAX(scale, num1->n_scale)); rscale = MIN (num1->n_scale * exponent, MAX(scale, num1->n_scale));
} }
/* Set initial value of temp. */ /* Set initial value of temp. */
power = bc_copy_num (num1); power = bc_copy_num(num1);
pwrscale = num1->n_scale; pwrscale = num1->n_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);
exponent = exponent >> 1; exponent = exponent >> 1;
} }
temp = bc_copy_num (power); temp = bc_copy_num(power);
calcscale = pwrscale; calcscale = pwrscale;
exponent = exponent >> 1; exponent = exponent >> 1;
/* Do the calculation. */ /* Do the calculation. */
while (exponent > 0) { while (exponent > 0) {
pwrscale = 2*pwrscale; pwrscale = 2 * pwrscale;
bc_multiply (power, power, &power, pwrscale); bc_multiply(power, power, &power, pwrscale);
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);
} }
exponent = exponent >> 1; exponent = exponent >> 1;
} }
/* Assign the value. */ /* Assign the value. */
if (is_neg) { if (is_neg) {
bc_divide (BCG(_one_), temp, result, rscale); bc_divide(BCG(_one_), temp, result, rscale);
bc_free_num (&temp); bc_free_num (&temp);
} else { } else {
bc_free_num (result); bc_free_num (result);

View file

@ -59,26 +59,26 @@ raise_mod_status bc_raisemod(bc_num base, bc_num expo, bc_num mod, bc_num *resul
} }
/* 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);
modulus = bc_copy_num (mod); modulus = bc_copy_num(mod);
temp = bc_copy_num (BCG(_one_)); temp = bc_copy_num(BCG(_one_));
bc_init_num(&parity); bc_init_num(&parity);
/* Do the calculation. */ /* Do the calculation. */
rscale = MAX(scale, power->n_scale); rscale = MAX(scale, power->n_scale);
if ( !bc_compare(modulus, BCG(_one_)) ) { if (!bc_compare(modulus, BCG(_one_))) {
bc_free_num (&temp); bc_free_num (&temp);
temp = bc_new_num (1, scale); temp = bc_new_num (1, scale);
} else { } else {
while ( !bc_is_zero(exponent) ) { while (!bc_is_zero(exponent)) {
(void) bc_divmod (exponent, BCG(_two_), &exponent, &parity, 0); (void) bc_divmod(exponent, BCG(_two_), &exponent, &parity, 0);
if ( !bc_is_zero(parity) ) { if (!bc_is_zero(parity)) {
bc_multiply (temp, power, &temp, rscale); bc_multiply(temp, power, &temp, rscale);
(void) bc_modulo (temp, modulus, &temp, scale); (void) bc_modulo(temp, modulus, &temp, scale);
} }
bc_multiply (power, power, &power, rscale); bc_multiply(power, power, &power, rscale);
(void) bc_modulo (power, modulus, &power, scale); (void) bc_modulo(power, modulus, &power, scale);
} }
} }

View file

@ -50,9 +50,7 @@ int mul_base_digits = MUL_BASE_DIGITS;
static bc_num new_sub_num(size_t length, size_t scale, char *value) static bc_num new_sub_num(size_t length, size_t scale, char *value)
{ {
bc_num temp; bc_num temp = (bc_num) emalloc(sizeof(bc_struct));
temp = (bc_num) emalloc (sizeof(bc_struct));
temp->n_sign = PLUS; temp->n_sign = PLUS;
temp->n_len = length; temp->n_len = length;
@ -66,22 +64,21 @@ static bc_num new_sub_num(size_t length, size_t scale, char *value)
static void _bc_simp_mul(bc_num n1, size_t n1len, bc_num n2, int n2len, bc_num *prod) static void _bc_simp_mul(bc_num n1, size_t n1len, bc_num n2, int n2len, bc_num *prod)
{ {
char *n1ptr, *n2ptr, *pvptr; char *n1ptr, *n2ptr, *pvptr;
char *n1end, *n2end; /* To the end of n1 and n2. */ char *n1end, *n2end; /* To the end of n1 and n2. */
int indx, sum, prodlen; int sum = 0;
prodlen = n1len+n2len+1; int prodlen = n1len + n2len + 1;
*prod = bc_new_num (prodlen, 0); *prod = bc_new_num (prodlen, 0);
n1end = (char *) (n1->n_value + n1len - 1); n1end = (char *) (n1->n_value + n1len - 1);
n2end = (char *) (n2->n_value + n2len - 1); n2end = (char *) (n2->n_value + n2len - 1);
pvptr = (char *) ((*prod)->n_value + prodlen - 1); pvptr = (char *) ((*prod)->n_value + prodlen - 1);
sum = 0;
/* Here is the loop... */ /* Here is the loop... */
for (indx = 0; indx < prodlen-1; indx++) { for (int index = 0; index < prodlen - 1; index++) {
n1ptr = (char *) (n1end - MAX(0, indx-n2len+1)); n1ptr = (char *) (n1end - MAX(0, index - n2len + 1));
n2ptr = (char *) (n2end - MIN(indx, n2len-1)); n2ptr = (char *) (n2end - MIN(index, n2len - 1));
while ((n1ptr >= n1->n_value) && (n2ptr <= n2end)) { while ((n1ptr >= n1->n_value) && (n2ptr <= n2end)) {
sum += *n1ptr * *n2ptr; sum += *n1ptr * *n2ptr;
n1ptr--; n1ptr--;
@ -98,7 +95,7 @@ static void _bc_simp_mul(bc_num n1, size_t n1len, bc_num n2, int n2len, bc_num *
multiply algorithm. Note: if sub is called, accum must multiply algorithm. Note: if sub is called, accum must
be larger that what is being subtracted. Also, accum and val be larger that what is being subtracted. Also, accum and val
must have n_scale = 0. (e.g. they must look like integers. *) */ 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, bool sub) static void _bc_shift_addsub(bc_num accum, bc_num val, int shift, bool sub)
{ {
signed char *accp, *valp; signed char *accp, *valp;
unsigned int carry = 0; unsigned int carry = 0;
@ -107,11 +104,11 @@ static void _bc_shift_addsub (bc_num accum, bc_num val, int shift, bool sub)
if (val->n_value[0] == 0) { if (val->n_value[0] == 0) {
count--; count--;
} }
assert(accum->n_len+accum->n_scale >= shift+count); assert(accum->n_len + accum->n_scale >= shift + count);
/* Set up pointers and others */ /* Set up pointers and others */
accp = (signed char *)(accum->n_value + accum->n_len + accum->n_scale - shift - 1); accp = (signed char *) (accum->n_value + accum->n_len + accum->n_scale - shift - 1);
valp = (signed char *)(val->n_value + val->n_len - 1); valp = (signed char *) (val->n_value + val->n_len - 1);
if (sub) { if (sub) {
/* Subtraction, carry is really borrow. */ /* Subtraction, carry is really borrow. */
@ -137,7 +134,7 @@ static void _bc_shift_addsub (bc_num accum, bc_num val, int shift, bool sub)
/* Addition */ /* Addition */
while (count--) { while (count--) {
*accp += *valp-- + carry; *accp += *valp-- + carry;
if (*accp > (BASE-1)) { if (*accp > (BASE - 1)) {
carry = 1; carry = 1;
*accp-- -= BASE; *accp-- -= BASE;
} else { } else {
@ -147,7 +144,7 @@ static void _bc_shift_addsub (bc_num accum, bc_num val, int shift, bool sub)
} }
while (carry) { while (carry) {
*accp += carry; *accp += carry;
if (*accp > (BASE-1)) { if (*accp > (BASE - 1)) {
*accp-- -= BASE; *accp-- -= BASE;
} else { } else {
carry = 0; carry = 0;
@ -168,40 +165,40 @@ static void _bc_rec_mul(bc_num u, size_t ulen, bc_num v, size_t vlen, bc_num *pr
{ {
bc_num u0, u1, v0, v1; bc_num u0, u1, v0, v1;
bc_num m1, m2, m3, d1, d2; bc_num m1, m2, m3, d1, d2;
int n, prodlen, m1zero; size_t n;
int d1len, d2len; bool m1zero;
/* Base case? */ /* Base case? */
if ((ulen+vlen) < mul_base_digits if ((ulen + vlen) < mul_base_digits
|| ulen < MUL_SMALL_DIGITS || ulen < MUL_SMALL_DIGITS
|| vlen < MUL_SMALL_DIGITS || vlen < MUL_SMALL_DIGITS
) { ) {
_bc_simp_mul (u, ulen, v, vlen, prod); _bc_simp_mul(u, ulen, v, vlen, prod);
return; return;
} }
/* Calculate n -- the u and v split point in digits. */ /* Calculate n -- the u and v split point in digits. */
n = (MAX(ulen, vlen)+1) / 2; n = (MAX(ulen, vlen) + 1) / 2;
/* Split u and v. */ /* Split u and v. */
if (ulen < n) { if (ulen < n) {
u1 = bc_copy_num (BCG(_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 (BCG(_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);
v0 = new_sub_num (n, 0, v->n_value+vlen-n); v0 = new_sub_num(n, 0, v->n_value + vlen - n);
} }
_bc_rm_leading_zeros (u1); _bc_rm_leading_zeros(u1);
_bc_rm_leading_zeros (u0); _bc_rm_leading_zeros(u0);
_bc_rm_leading_zeros (v1); _bc_rm_leading_zeros(v1);
_bc_rm_leading_zeros (v0); _bc_rm_leading_zeros(v0);
m1zero = bc_is_zero(u1) || bc_is_zero(v1); m1zero = bc_is_zero(u1) || bc_is_zero(v1);
@ -209,42 +206,39 @@ static void _bc_rec_mul(bc_num u, size_t ulen, bc_num v, size_t vlen, bc_num *pr
bc_init_num(&d1); bc_init_num(&d1);
bc_init_num(&d2); bc_init_num(&d2);
bc_sub (u1, u0, &d1, 0); bc_sub(u1, u0, &d1, 0);
d1len = d1->n_len; bc_sub(v0, v1, &d2, 0);
bc_sub (v0, v1, &d2, 0);
d2len = d2->n_len;
/* Do recursive multiplies and shifted adds. */ /* Do recursive multiplies and shifted adds. */
if (m1zero) { if (m1zero) {
m1 = bc_copy_num (BCG(_zero_)); m1 = bc_copy_num(BCG(_zero_));
} else { } else {
_bc_rec_mul (u1, u1->n_len, v1, v1->n_len, &m1); _bc_rec_mul(u1, u1->n_len, v1, v1->n_len, &m1);
} }
if (bc_is_zero(d1) || bc_is_zero(d2)) { if (bc_is_zero(d1) || bc_is_zero(d2)) {
m2 = bc_copy_num (BCG(_zero_)); m2 = bc_copy_num(BCG(_zero_));
} else { } else {
_bc_rec_mul (d1, d1len, d2, d2len, &m2); _bc_rec_mul(d1, d1->n_len, d2, d2->n_len, &m2);
} }
if (bc_is_zero(u0) || bc_is_zero(v0)) { if (bc_is_zero(u0) || bc_is_zero(v0)) {
m3 = bc_copy_num (BCG(_zero_)); m3 = bc_copy_num(BCG(_zero_));
} else { } else {
_bc_rec_mul (u0, u0->n_len, v0, v0->n_len, &m3); _bc_rec_mul(u0, u0->n_len, v0, v0->n_len, &m3);
} }
/* Initialize product */ /* Initialize product */
prodlen = ulen+vlen+1; *prod = bc_new_num(ulen + vlen + 1, 0);
*prod = bc_new_num(prodlen, 0);
if (!m1zero) { if (!m1zero) {
_bc_shift_addsub (*prod, m1, 2*n, 0); _bc_shift_addsub(*prod, m1, 2 * n, false);
_bc_shift_addsub (*prod, m1, n, 0); _bc_shift_addsub(*prod, m1, n, false);
} }
_bc_shift_addsub (*prod, m3, n, 0); _bc_shift_addsub(*prod, m3, n, false);
_bc_shift_addsub (*prod, m3, 0, 0); _bc_shift_addsub(*prod, m3, 0, false);
_bc_shift_addsub (*prod, m2, n, d1->n_sign != d2->n_sign); _bc_shift_addsub(*prod, m2, n, d1->n_sign != d2->n_sign);
/* Now clean up! */ /* Now clean up! */
bc_free_num (&u1); bc_free_num (&u1);
@ -272,13 +266,13 @@ void bc_multiply(bc_num n1, bc_num n2, bc_num *prod, size_t scale)
len1 = n1->n_len + n1->n_scale; len1 = n1->n_len + n1->n_scale;
len2 = n2->n_len + n2->n_scale; len2 = n2->n_len + n2->n_scale;
full_scale = n1->n_scale + 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))); 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); _bc_rec_mul(n1, len1, n2, len2, &pval);
/* 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);
pval->n_value = pval->n_ptr; pval->n_value = pval->n_ptr;
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;

View file

@ -38,7 +38,7 @@
void _bc_rm_leading_zeros(bc_num num) void _bc_rm_leading_zeros(bc_num num)
{ {
/* We can move n_value to point to the first non zero digit! */ /* We can move n_value to point to the first non-zero digit! */
while (*num->n_value == 0 && num->n_len > 1) { while (*num->n_value == 0 && num->n_len > 1) {
num->n_value++; num->n_value++;
num->n_len--; num->n_len--;

View file

@ -30,8 +30,8 @@
*************************************************************************/ *************************************************************************/
#include "bcmath.h" #include "bcmath.h"
#include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h>
/* Take the square root NUM and return it in NUM with SCALE digits /* Take the square root NUM and return it in NUM with SCALE digits
after the decimal place. */ after the decimal place. */
@ -39,20 +39,20 @@
bool bc_sqrt(bc_num *num, size_t scale) bool bc_sqrt(bc_num *num, size_t scale)
{ {
/* Initial checks. */ /* Initial checks. */
int cmp_res = bc_compare (*num, BCG(_zero_)); int cmp_res = bc_compare(*num, BCG(_zero_));
if (cmp_res < 0) { if (cmp_res < 0) {
return false; /* error */ return false; /* error */
} else { } else {
if (cmp_res == 0) { if (cmp_res == 0) {
bc_free_num (num); bc_free_num (num);
*num = bc_copy_num (BCG(_zero_)); *num = bc_copy_num(BCG(_zero_));
return true; return true;
} }
} }
cmp_res = bc_compare (*num, BCG(_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 (BCG(_one_)); *num = bc_copy_num(BCG(_one_));
return true; return true;
} }
@ -64,22 +64,22 @@ bool bc_sqrt(bc_num *num, size_t scale)
rscale = MAX (scale, (*num)->n_scale); rscale = MAX (scale, (*num)->n_scale);
bc_init_num(&guess1); bc_init_num(&guess1);
bc_init_num(&diff); bc_init_num(&diff);
point5 = bc_new_num (1,1); point5 = bc_new_num (1, 1);
point5->n_value[1] = 5; point5->n_value[1] = 5;
/* Calculate the initial guess. */ /* Calculate the initial guess. */
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 (BCG(_one_)); guess = bc_copy_num(BCG(_one_));
cscale = (*num)->n_scale; cscale = (*num)->n_scale;
} else { } else {
/* The number is greater than 1. Guess should start at 10^(exp/2). */ /* The number is greater than 1. Guess should start at 10^(exp/2). */
bc_init_num(&guess); bc_init_num(&guess);
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);
guess1->n_scale = 0; guess1->n_scale = 0;
bc_raise_bc_exponent(guess, guess1, &guess, 0); bc_raise_bc_exponent(guess, guess1, &guess, 0);
bc_free_num (&guess1); bc_free_num (&guess1);
@ -90,14 +90,14 @@ bool bc_sqrt(bc_num *num, size_t scale)
bool done = false; bool done = false;
while (!done) { while (!done) {
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);
bc_add (guess, guess1, &guess, 0); bc_add(guess, guess1, &guess, 0);
bc_multiply (guess, point5, &guess, cscale); bc_multiply(guess, point5, &guess, cscale);
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)) {
if (cscale < rscale+1) { if (cscale < rscale + 1) {
cscale = MIN (cscale*3, rscale+1); cscale = MIN (cscale * 3, rscale + 1);
} else { } else {
done = true; done = true;
} }
@ -106,7 +106,7 @@ bool bc_sqrt(bc_num *num, size_t scale)
/* Assign the number and clean up. */ /* Assign the number and clean up. */
bc_free_num (num); bc_free_num (num);
bc_divide (guess,BCG(_one_),num,rscale); bc_divide(guess, BCG(_one_), num, rscale);
bc_free_num (&guess); bc_free_num (&guess);
bc_free_num (&guess1); bc_free_num (&guess1);
bc_free_num (&point5); bc_free_num (&point5);

View file

@ -35,22 +35,21 @@
/* Convert strings to bc numbers. Base 10 only.*/ /* Convert strings to bc numbers. Base 10 only.*/
bool bc_str2num (bc_num *num, char *str, size_t scale) bool bc_str2num(bc_num *num, char *str, size_t scale)
{ {
size_t digits, strscale; size_t digits = 0;
size_t strscale = 0;
char *ptr, *nptr; char *ptr, *nptr;
bool zero_int = false;
size_t trailing_zeros = 0; size_t trailing_zeros = 0;
bool zero_int = false;
/* Prepare num. */ /* Prepare num. */
bc_free_num (num); bc_free_num (num);
/* Check for valid number and count digits. */ /* Check for valid number and count digits. */
ptr = str; ptr = str;
digits = 0;
strscale = 0;
if ( (*ptr == '+') || (*ptr == '-')) { if ((*ptr == '+') || (*ptr == '-')) {
/* Skip Sign */ /* Skip Sign */
ptr++; ptr++;
} }
@ -79,11 +78,11 @@ bool bc_str2num (bc_num *num, char *str, size_t scale)
} }
if (trailing_zeros > 0) { if (trailing_zeros > 0) {
/* Trailining zeros should not take part in the computation of the overall scale, as it is pointless. */ /* Trailing zeros should not take part in the computation of the overall scale, as it is pointless. */
strscale = strscale - trailing_zeros; strscale = strscale - trailing_zeros;
} }
if ((*ptr != '\0') || (digits+strscale == 0)) { if ((*ptr != '\0') || (digits + strscale == 0)) {
*num = bc_copy_num (BCG(_zero_)); *num = bc_copy_num(BCG(_zero_));
return *ptr == '\0'; return *ptr == '\0';
} }
@ -113,7 +112,7 @@ bool bc_str2num (bc_num *num, char *str, size_t scale)
*nptr++ = 0; *nptr++ = 0;
digits = 0; digits = 0;
} }
for (;digits > 0; digits--) { for (; digits > 0; digits--) {
*nptr++ = CH_VAL(*ptr++); *nptr++ = CH_VAL(*ptr++);
} }
@ -121,12 +120,12 @@ bool bc_str2num (bc_num *num, char *str, size_t scale)
if (strscale > 0) { if (strscale > 0) {
/* skip the decimal point! */ /* skip the decimal point! */
ptr++; ptr++;
for (;strscale > 0; strscale--) { for (; strscale > 0; strscale--) {
*nptr++ = CH_VAL(*ptr++); *nptr++ = CH_VAL(*ptr++);
} }
} }
if (bc_is_zero (*num)) { if (bc_is_zero(*num)) {
(*num)->n_sign = PLUS; (*num)->n_sign = PLUS;
} }

View file

@ -33,6 +33,7 @@
#include "private.h" #include "private.h"
#include <stddef.h> #include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h>
/* Here is the full subtract routine that takes care of negative numbers. /* 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 N2 is subtracted from N1 and the result placed in RESULT. SCALE_MIN
@ -41,31 +42,29 @@
void bc_sub(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)
{ {
bc_num diff = NULL; bc_num diff = NULL;
int cmp_res;
if (n1->n_sign != n2->n_sign) { if (n1->n_sign != n2->n_sign) {
diff = _bc_do_add (n1, n2, scale_min); diff = _bc_do_add(n1, n2, scale_min);
diff->n_sign = n1->n_sign; diff->n_sign = n1->n_sign;
} else { } else {
/* subtraction must be done. */ /* subtraction must be done. */
/* Compare magnitudes. */ /* Compare magnitudes. */
cmp_res = _bc_do_compare(n1, n2, false, false); switch (_bc_do_compare(n1, n2, false, false)) {
switch (cmp_res) {
case -1: case -1:
/* n1 is less than n2, subtract n1 from n2. */ /* n1 is less than n2, subtract n1 from n2. */
diff = _bc_do_sub (n2, n1, scale_min); diff = _bc_do_sub(n2, n1, scale_min);
diff->n_sign = (n2->n_sign == PLUS ? MINUS : PLUS); diff->n_sign = (n2->n_sign == PLUS ? MINUS : PLUS);
break; break;
case 0: { case 0: {
/* They are equal! return zero! */ /* They are equal! return zero! */
size_t res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale)); size_t res_scale = MAX (scale_min, MAX(n1->n_scale, n2->n_scale));
diff = bc_new_num (1, res_scale); diff = bc_new_num (1, res_scale);
memset (diff->n_value, 0, res_scale+1); memset(diff->n_value, 0, res_scale + 1);
break; break;
} }
case 1: case 1:
/* n2 is less than n1, subtract n2 from n1. */ /* n2 is less than n1, subtract n2 from n1. */
diff = _bc_do_sub (n1, n2, scale_min); diff = _bc_do_sub(n1, n2, scale_min);
diff->n_sign = n1->n_sign; diff->n_sign = n1->n_sign;
break; break;
} }

View file

@ -30,12 +30,12 @@
*************************************************************************/ *************************************************************************/
#include "bcmath.h" #include "bcmath.h"
#include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h>
/* 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. */
bool bc_is_zero_for_scale (bc_num num, size_t scale) bool bc_is_zero_for_scale(bc_num num, size_t scale)
{ {
size_t count; size_t count;
char *nptr; char *nptr;