Skip to content

Commit da74a1b

Browse files
committed
Efficiently obtain the initial value for the standard path.
1 parent 45ce75d commit da74a1b

File tree

1 file changed

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

1 file changed

+26
-12
lines changed

ext/bcmath/libbcmath/src/sqrt.c

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -140,20 +140,34 @@ 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_vector_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_vector_size - 2] = BC_VECTOR_BOUNDARY_NUM - 1;
149-
} else {
150-
guess_vector[guess_vector_size - 2] = 0;
151-
for (size_t i = 0; i < guess_full_len % BC_VECTOR_SIZE; i++) {
152-
guess_vector[guess_vector_size - 2] *= BASE;
153-
guess_vector[guess_vector_size - 2] += 9;
154-
}
152+
const char *nptr = (*num)->n_value;
153+
BC_VECTOR n_top = 0;
154+
for (size_t i = 0; i < n_top_len_for_initial_guess; i++) {
155+
n_top *= BASE;
156+
n_top += *nptr++;
157+
}
158+
159+
for (size_t i = 0; i < guess_vector_size; i++) {
160+
guess_vector[i] = 0;
155161
}
156-
guess_vector[guess_vector_size - 1] = 0;
162+
BC_VECTOR initial_guess = bc_fast_sqrt_vector(n_top);
163+
164+
size_t initial_guess_len = SIZEOF_SIZE_T == 8 ? 9 : 5;
165+
size_t guess_top_vector_len = guess_full_len % BC_VECTOR_SIZE == 0 ? BC_VECTOR_SIZE : guess_full_len % BC_VECTOR_SIZE;
166+
size_t guess_len_diff = initial_guess_len - guess_top_vector_len;
167+
guess_vector[guess_vector_size - 2] = initial_guess / BC_POW_10_LUT[guess_len_diff];
168+
initial_guess %= BC_POW_10_LUT[guess_len_diff];
169+
guess_vector[guess_vector_size - 3] = initial_guess * BC_POW_10_LUT[BC_VECTOR_SIZE - guess_len_diff];
170+
157171
guess1_vector[guess_vector_size - 1] = 0;
158172

159173
size_t quot_size = n_vector_size - (guess_vector_size - 1) + 1;

0 commit comments

Comments
 (0)