33
33
#include "private.h"
34
34
#include <stdbool.h>
35
35
#include <stddef.h>
36
+ #include <string.h>
36
37
#include "zend_alloc.h"
37
38
38
39
43
44
44
45
static void _one_mult (unsigned char * num , size_t size , int digit , unsigned char * result )
45
46
{
46
- int carry , value ;
47
+ size_t carry , value ;
47
48
unsigned char * nptr , * rptr ;
48
49
49
50
if (digit == 0 ) {
@@ -53,8 +54,8 @@ static void _one_mult(unsigned char *num, size_t size, int digit, unsigned char
53
54
memcpy (result , num , size );
54
55
} else {
55
56
/* Initialize */
56
- nptr = (unsigned char * ) (num + size - 1 );
57
- rptr = (unsigned char * ) (result + size - 1 );
57
+ nptr = (unsigned char * ) (num + size - 1 );
58
+ rptr = (unsigned char * ) (result + size - 1 );
58
59
carry = 0 ;
59
60
60
61
while (size -- > 0 ) {
@@ -74,121 +75,113 @@ static void _one_mult(unsigned char *num, size_t size, int digit, unsigned char
74
75
/* The full division routine. This computes N1 / N2. It returns
75
76
true if the division is ok and the result is in QUOT. The number of
76
77
digits after the decimal point is SCALE. It returns false if division
77
- by zero is tried. The algorithm is found in Knuth Vol 2. p237. */
78
+ by zero is tried. The algorithm is found in Knuth Vol 2. p237. */
78
79
bool bc_divide (bc_num n1 , bc_num n2 , bc_num * quot , int scale )
79
80
{
80
81
bc_num qval ;
81
82
unsigned char * num1 , * num2 ;
82
83
unsigned char * ptr1 , * ptr2 , * n2ptr , * qptr ;
83
- int scale1 , val ;
84
- unsigned int len1 , len2 , scale2 , qdigits , extra , count ;
85
- unsigned int qdig , qguess , borrow , carry ;
84
+ int scale1 , val ;
85
+ unsigned int len1 , len2 , scale2 , qdigits , extra , count ;
86
+ unsigned int qdig , qguess , borrow , carry ;
86
87
unsigned char * mval ;
88
+ unsigned int norm ;
87
89
bool zero ;
88
- unsigned int norm ;
89
90
90
91
/* Test for divide by zero. */
91
92
if (bc_is_zero (n2 )) {
92
93
return false;
93
94
}
94
95
95
- /* Test for divide by 1. If it is we must truncate. */
96
- if (n2 -> n_scale == 0 ) {
97
- if (n2 -> n_len == 1 && * n2 -> n_value == 1 ) {
98
- qval = bc_new_num (n1 -> n_len , scale );
99
- qval -> n_sign = (n1 -> n_sign == n2 -> n_sign ? PLUS : MINUS );
100
- memset (& qval -> n_value [n1 -> n_len ],0 ,scale );
101
- memcpy (qval -> n_value , n1 -> n_value , n1 -> n_len + MIN (n1 -> n_scale ,scale ));
102
- bc_free_num (quot );
103
- * quot = qval ;
104
- }
96
+ /* Test for divide by 1. If it is we must truncate. */
97
+ if (n2 -> n_scale == 0 && n2 -> n_len == 1 && * n2 -> n_value == 1 ) {
98
+ qval = bc_new_num (n1 -> n_len , scale );
99
+ qval -> n_sign = (n1 -> n_sign == n2 -> n_sign ? PLUS : MINUS );
100
+ memset (& qval -> n_value [n1 -> n_len ], 0 , scale );
101
+ memcpy (qval -> n_value , n1 -> n_value , n1 -> n_len + MIN (n1 -> n_scale , scale ));
102
+ bc_free_num (quot );
103
+ * quot = qval ;
105
104
}
106
105
107
106
/* Set up the divide. Move the decimal point on n1 by n2's scale.
108
107
Remember, zeros on the end of num2 are wasted effort for dividing. */
109
108
scale2 = n2 -> n_scale ;
110
- n2ptr = (unsigned char * ) n2 -> n_value + n2 -> n_len + scale2 - 1 ;
111
- while ((scale2 > 0 ) && (* n2ptr -- == 0 )) {
109
+ n2ptr = (unsigned char * ) n2 -> n_value + n2 -> n_len + scale2 - 1 ;
110
+ while ((scale2 > 0 ) && (* n2ptr == 0 )) {
112
111
scale2 -- ;
112
+ n2ptr -- ;
113
113
}
114
114
115
115
len1 = n1 -> n_len + scale2 ;
116
116
scale1 = n1 -> n_scale - scale2 ;
117
- if (scale1 < scale ) {
118
- extra = scale - scale1 ;
119
- } else {
120
- extra = 0 ;
121
- }
122
- num1 = (unsigned char * ) safe_emalloc (1 , n1 -> n_len + n1 -> n_scale , extra + 2 );
123
- memset (num1 , 0 , n1 -> n_len + n1 -> n_scale + extra + 2 );
124
- memcpy (num1 + 1 , n1 -> n_value , n1 -> n_len + n1 -> n_scale );
117
+ extra = MAX (scale - scale1 , 0 );
118
+
119
+ num1 = (unsigned char * ) safe_emalloc (1 , n1 -> n_len + n1 -> n_scale , extra + 2 );
120
+ memset (num1 , 0 , n1 -> n_len + n1 -> n_scale + extra + 2 );
121
+ memcpy (num1 + 1 , n1 -> n_value , n1 -> n_len + n1 -> n_scale );
125
122
126
123
len2 = n2 -> n_len + scale2 ;
127
- num2 = (unsigned char * ) safe_emalloc (1 , len2 , 1 );
128
- memcpy (num2 , n2 -> n_value , len2 );
129
- * (num2 + len2 ) = 0 ;
124
+ num2 = (unsigned char * ) safe_emalloc (1 , len2 , 1 );
125
+ memcpy (num2 , n2 -> n_value , len2 );
126
+ * (num2 + len2 ) = 0 ;
130
127
n2ptr = num2 ;
131
128
while (* n2ptr == 0 ) {
132
129
n2ptr ++ ;
133
130
len2 -- ;
134
131
}
135
132
136
133
/* Calculate the number of quotient digits. */
137
- if (len2 > len1 + scale ) {
138
- qdigits = scale + 1 ;
134
+ if (len2 > len1 + scale ) {
135
+ qdigits = scale + 1 ;
139
136
zero = true;
140
137
} else {
141
138
zero = false;
142
139
if (len2 > len1 ) {
143
140
/* One for the zero integer part. */
144
- qdigits = scale + 1 ;
141
+ qdigits = scale + 1 ;
145
142
} else {
146
- qdigits = len1 - len2 + scale + 1 ;
143
+ qdigits = len1 - len2 + scale + 1 ;
147
144
}
148
145
}
149
146
150
147
/* Allocate and zero the storage for the quotient. */
151
- qval = bc_new_num (qdigits - scale ,scale );
152
- memset (qval -> n_value , 0 , qdigits );
148
+ qval = bc_new_num (qdigits - scale , scale );
149
+ memset (qval -> n_value , 0 , qdigits );
153
150
154
151
/* Allocate storage for the temporary storage mval. */
155
152
mval = (unsigned char * ) safe_emalloc (1 , len2 , 1 );
156
153
157
154
/* Now for the full divide algorithm. */
158
155
if (!zero ) {
159
156
/* Normalize */
160
- norm = 10 / ((int )* n2ptr + 1 );
157
+ norm = 10 / ((int ) * n2ptr + 1 );
161
158
if (norm != 1 ) {
162
- _one_mult (num1 , len1 + scale1 + extra + 1 , norm , num1 );
163
- _one_mult (n2ptr , len2 , norm , n2ptr );
159
+ _one_mult (num1 , len1 + scale1 + extra + 1 , norm , num1 );
160
+ _one_mult (n2ptr , len2 , norm , n2ptr );
164
161
}
165
162
166
163
/* Initialize divide loop. */
167
164
qdig = 0 ;
168
165
if (len2 > len1 ) {
169
- qptr = (unsigned char * ) qval -> n_value + len2 - len1 ;
166
+ qptr = (unsigned char * ) qval -> n_value + len2 - len1 ;
170
167
} else {
171
168
qptr = (unsigned char * ) qval -> n_value ;
172
169
}
173
170
174
171
/* Loop */
175
- while (qdig <= len1 + scale - len2 ) {
172
+ while (qdig <= len1 + scale - len2 ) {
176
173
/* Calculate the quotient digit guess. */
177
174
if (* n2ptr == num1 [qdig ]) {
178
175
qguess = 9 ;
179
176
} else {
180
- qguess = (num1 [qdig ]* 10 + num1 [qdig + 1 ]) / * n2ptr ;
177
+ qguess = (num1 [qdig ] * 10 + num1 [qdig + 1 ]) / * n2ptr ;
181
178
}
182
179
183
180
/* Test qguess. */
184
- if (
185
- n2ptr [1 ]* qguess > (num1 [qdig ]* 10 + num1 [qdig + 1 ] - * n2ptr * qguess )* 10 + num1 [qdig + 2 ]
186
- ) {
181
+ if (n2ptr [1 ] * qguess > (num1 [qdig ] * 10 + num1 [qdig + 1 ] - * n2ptr * qguess ) * 10 + num1 [qdig + 2 ]) {
187
182
qguess -- ;
188
183
/* And again. */
189
- if (
190
- n2ptr [1 ]* qguess > (num1 [qdig ]* 10 + num1 [qdig + 1 ] - * n2ptr * qguess )* 10 + num1 [qdig + 2 ]
191
- ) {
184
+ if (n2ptr [1 ] * qguess > (num1 [qdig ] * 10 + num1 [qdig + 1 ] - * n2ptr * qguess ) * 10 + num1 [qdig + 2 ]) {
192
185
qguess -- ;
193
186
}
194
187
}
@@ -197,10 +190,10 @@ bool bc_divide(bc_num n1, bc_num n2, bc_num *quot, int scale)
197
190
borrow = 0 ;
198
191
if (qguess != 0 ) {
199
192
* mval = 0 ;
200
- _one_mult (n2ptr , len2 , qguess , mval + 1 );
201
- ptr1 = (unsigned char * ) num1 + qdig + len2 ;
202
- ptr2 = (unsigned char * ) mval + len2 ;
203
- for (count = 0 ; count < len2 + 1 ; count ++ ) {
193
+ _one_mult (n2ptr , len2 , qguess , mval + 1 );
194
+ ptr1 = (unsigned char * ) num1 + qdig + len2 ;
195
+ ptr2 = (unsigned char * ) mval + len2 ;
196
+ for (count = 0 ; count < len2 + 1 ; count ++ ) {
204
197
val = (int ) * ptr1 - (int ) * ptr2 -- - borrow ;
205
198
if (val < 0 ) {
206
199
val += 10 ;
@@ -215,8 +208,8 @@ bool bc_divide(bc_num n1, bc_num n2, bc_num *quot, int scale)
215
208
/* Test for negative result. */
216
209
if (borrow == 1 ) {
217
210
qguess -- ;
218
- ptr1 = (unsigned char * ) num1 + qdig + len2 ;
219
- ptr2 = (unsigned char * ) n2ptr + len2 - 1 ;
211
+ ptr1 = (unsigned char * ) num1 + qdig + len2 ;
212
+ ptr2 = (unsigned char * ) n2ptr + len2 - 1 ;
220
213
carry = 0 ;
221
214
for (count = 0 ; count < len2 ; count ++ ) {
222
215
val = (int ) * ptr1 + (int ) * ptr2 -- + carry ;
@@ -240,7 +233,7 @@ bool bc_divide(bc_num n1, bc_num n2, bc_num *quot, int scale)
240
233
}
241
234
242
235
/* Clean up and return the number. */
243
- qval -> n_sign = ( n1 -> n_sign == n2 -> n_sign ? PLUS : MINUS );
236
+ qval -> n_sign = (n1 -> n_sign == n2 -> n_sign ? PLUS : MINUS );
244
237
if (bc_is_zero (qval )) {
245
238
qval -> n_sign = PLUS ;
246
239
}
0 commit comments