Skip to content

Commit b4071ec

Browse files
committed
Efficiently obtain the initial value for the standard path.
1 parent b60f757 commit b4071ec

File tree

1 file changed

+32
-12
lines changed
  • ext/bcmath/libbcmath/src

1 file changed

+32
-12
lines changed

ext/bcmath/libbcmath/src/sqrt.c

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -140,20 +140,40 @@ static inline void bc_standard_sqrt(bc_num *num, size_t rscale, size_t num_calc_
140140

141141
bc_convert_to_vector_with_zero_pad(n_vector, nend, n_full_len, n_extend_zeros);
142142

143-
/* Prepare guess_vector (Temporary implementation) */
144-
for (size_t i = 0; i < guess_arr_size - 2; i++) {
145-
guess_vector[i] = BC_VECTOR_BOUNDARY_NUM - 1;
143+
/* Prepare guess_vector. Use bc_fast_sqrt_vector to quickly obtain a highly accurate initial value. */
144+
size_t n_top_len_for_initial_guess = SIZEOF_SIZE_T == 8 ? 18 : 10;
145+
146+
/* Set the number of digits of num to be used as the initial value for Newton's method.
147+
* Just as the square roots of 1000 and 100 differ significantly, the number of digits
148+
* to "ignore" here must be even. */
149+
if (num_calc_full_len & 1) {
150+
n_top_len_for_initial_guess--;
146151
}
147-
if (guess_full_len % BC_VECTOR_SIZE == 0) {
148-
guess_vector[guess_arr_size - 2] = BC_VECTOR_BOUNDARY_NUM - 1;
149-
} else {
150-
guess_vector[guess_arr_size - 2] = 0;
151-
for (size_t i = 0; i < guess_full_len % BC_VECTOR_SIZE; i++) {
152-
guess_vector[guess_arr_size - 2] *= BASE;
153-
guess_vector[guess_arr_size - 2] += 9;
154-
}
152+
BC_VECTOR n_top = n_vector[n_arr_size - 1];
153+
size_t n_top_index = n_arr_size - 2;
154+
size_t count = n_top_len_for_initial_guess - num_calc_full_len % BC_VECTOR_SIZE;
155+
while (count >= BC_VECTOR_SIZE) {
156+
n_top *= BC_VECTOR_SIZE;
157+
n_top += n_vector[n_top_index--];
158+
count -= BC_VECTOR_SIZE;
155159
}
156-
guess_vector[guess_arr_size - 1] = 0;
160+
if (count > 0) {
161+
n_top *= BC_POW_10_LUT[count];
162+
n_top += n_vector[n_top_index] / BC_POW_10_LUT[BC_VECTOR_SIZE - count];
163+
}
164+
165+
for (size_t i = 0; i < guess_arr_size; i++) {
166+
guess_vector[i] = 0;
167+
}
168+
BC_VECTOR initial_guess = bc_fast_sqrt_vector(n_top);
169+
170+
size_t initial_guess_len = SIZEOF_SIZE_T == 8 ? 9 : 5;
171+
size_t guess_top_vector_len = guess_full_len % BC_VECTOR_SIZE == 0 ? BC_VECTOR_SIZE : guess_full_len % BC_VECTOR_SIZE;
172+
size_t guess_len_diff = initial_guess_len - guess_top_vector_len;
173+
guess_vector[guess_arr_size - 2] = initial_guess / BC_POW_10_LUT[guess_len_diff];
174+
initial_guess %= BC_POW_10_LUT[guess_len_diff];
175+
guess_vector[guess_arr_size - 3] = initial_guess * BC_POW_10_LUT[BC_VECTOR_SIZE - guess_len_diff];
176+
157177
guess1_vector[guess_arr_size - 1] = 0;
158178

159179
size_t quot_size = n_arr_size - (guess_arr_size - 1) + 1;

0 commit comments

Comments
 (0)