Skip to content

Commit de00485

Browse files
committed
Omit low precision digits in calculations
1 parent 1d288a8 commit de00485

File tree

1 file changed

+31
-10
lines changed
  • ext/bcmath/libbcmath/src

1 file changed

+31
-10
lines changed

ext/bcmath/libbcmath/src/sqrt.c

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -177,24 +177,33 @@ static inline void bc_standard_sqrt(bc_num *num, size_t rscale, size_t num_calc_
177177

178178
guess1_vector[guess_arr_size - 1] = 0;
179179

180-
size_t quot_size = n_arr_size - (guess_arr_size - 1) + 1;
181-
182180
BC_VECTOR two[1] = { 2 };
183181

182+
size_t guess_precision = 2;
183+
184184
/* Newton's algorithm. */
185185
bool done = false;
186186
do {
187-
for (size_t i = 0; i < n_arr_size; i++) {
187+
size_t guess_offset = guess_arr_size - 1 - guess_precision;
188+
size_t n_offset = guess_offset * 2;
189+
for (size_t i = n_offset; i < n_arr_size; i++) {
188190
n_vector_copy[i] = n_vector[i];
189191
}
190-
bool div_ret = bc_divide_vector(n_vector_copy, n_arr_size, guess_vector, guess_arr_size - 1, tmp_div_ret_vector, quot_size);
192+
193+
size_t n_precision = n_arr_size - n_offset;
194+
size_t quot_size = n_precision - (guess_precision) + 1;
195+
bool div_ret = bc_divide_vector(
196+
n_vector_copy + n_offset, n_precision,
197+
guess_vector + guess_offset, guess_precision,
198+
tmp_div_ret_vector + guess_offset, quot_size
199+
);
191200
ZEND_ASSERT(div_ret);
192201

193202
BC_VECTOR *tmp_vptr = guess1_vector;
194203
guess1_vector = guess_vector;
195204
guess_vector = tmp_vptr;
196205
int carry = 0;
197-
for (size_t i = 0; i < guess_arr_size - 1; i++) {
206+
for (size_t i = guess_offset; i < guess_arr_size; i++) {
198207
guess_vector[i] = guess1_vector[i] + tmp_div_ret_vector[i] + carry;
199208
if (guess_vector[i] >= BC_VECTOR_BOUNDARY_NUM) {
200209
guess_vector[i] -= BC_VECTOR_BOUNDARY_NUM;
@@ -205,23 +214,35 @@ static inline void bc_standard_sqrt(bc_num *num, size_t rscale, size_t num_calc_
205214
}
206215
guess_vector[guess_arr_size - 1] = carry;
207216

208-
div_ret = bc_divide_vector(guess_vector, guess_arr_size, two, 1, tmp_div_ret_vector, guess_arr_size);
217+
div_ret = bc_divide_vector(
218+
guess_vector + guess_offset, guess_precision + 1,
219+
two, 1,
220+
tmp_div_ret_vector + guess_offset, guess_precision + 1
221+
);
209222
ZEND_ASSERT(div_ret);
210223

211-
for (size_t i = 0; i < guess_arr_size; i++) {
224+
for (size_t i = guess_offset; i < guess_arr_size; i++) {
212225
guess_vector[i] = tmp_div_ret_vector[i];
213226
}
214227

215-
size_t diff = guess_vector[0] > guess1_vector[0] ? guess_vector[0] - guess1_vector[0] : guess1_vector[0] - guess_vector[0];
228+
size_t diff = guess_vector[guess_offset] > guess1_vector[guess_offset]
229+
? guess_vector[guess_offset] - guess1_vector[guess_offset]
230+
: guess1_vector[guess_offset] - guess_vector[guess_offset];
216231
if (diff <= 1) {
217232
bool is_same = true;
218-
for (size_t i = 1; i < guess_arr_size - 1; i++) {
233+
for (size_t i = guess_offset + 1; i < guess_arr_size - 1; i++) {
219234
if (guess_vector[i] != guess1_vector[i]) {
220235
is_same = false;
221236
break;
222237
}
223238
}
224-
done = is_same;
239+
if (is_same) {
240+
if (guess_precision < guess_arr_size - 1) {
241+
guess_precision = MIN(guess_precision * 3, guess_arr_size - 1);
242+
} else {
243+
done = is_same;
244+
}
245+
}
225246
}
226247
} while (!done);
227248

0 commit comments

Comments
 (0)