@@ -129,18 +129,51 @@ static inline void bc_standard_sqrt(bc_num *num, size_t rscale, size_t num_calc_
129
129
130
130
bc_convert_to_vector_with_zero_pad (n_vector , nend , n_full_len , n_extend_zeros );
131
131
132
- /* Prepare guess_vector (Temporary implementation) */
133
- for (size_t i = 0 ; i < guess_arr_size - 2 ; i ++ ) {
134
- guess_vector [i ] = BC_VECTOR_BOUNDARY_NUM - 1 ;
132
+ /* Prepare guess_vector. Use `bc_fast_sqrt_vector()` to quickly obtain a highly accurate initial value. */
133
+
134
+ /* 18 on 64-bit, 10 on 32-bit */
135
+ size_t n_top_len_for_initial_guess = (MAX_LENGTH_OF_LONG - 1 ) & ~1 ;
136
+
137
+ /* Set the number of digits of num to be used as the initial value for Newton's method.
138
+ * Just as the square roots of 1000 and 100 differ significantly, the number of digits
139
+ * to "ignore" here must be even. */
140
+ if (num_calc_full_len & 1 ) {
141
+ #if SIZEOF_SIZE_T == 8
142
+ n_top_len_for_initial_guess ++ ; /* 19 */
143
+ #else
144
+ n_top_len_for_initial_guess -- ; /* 9 */
145
+ #endif
135
146
}
136
- if (guess_full_len % BC_VECTOR_SIZE == 0 ) {
137
- guess_vector [guess_arr_size - 2 ] = BC_VECTOR_BOUNDARY_NUM - 1 ;
138
- } else {
139
- guess_vector [guess_arr_size - 2 ] = 0 ;
140
- for (size_t i = 0 ; i < guess_full_len % BC_VECTOR_SIZE ; i ++ ) {
141
- guess_vector [guess_arr_size - 2 ] *= BASE ;
142
- guess_vector [guess_arr_size - 2 ] += 9 ;
143
- }
147
+
148
+ BC_VECTOR n_top = n_vector [n_arr_size - 1 ];
149
+ size_t n_top_index = n_arr_size - 2 ;
150
+ size_t n_top_vector_len = num_calc_full_len % BC_VECTOR_SIZE == 0 ? BC_VECTOR_SIZE : num_calc_full_len % BC_VECTOR_SIZE ;
151
+ size_t count = n_top_len_for_initial_guess - n_top_vector_len ;
152
+ while (count >= BC_VECTOR_SIZE ) {
153
+ n_top *= BC_VECTOR_BOUNDARY_NUM ;
154
+ n_top += n_vector [n_top_index -- ];
155
+ count -= BC_VECTOR_SIZE ;
156
+ }
157
+ if (count > 0 ) {
158
+ n_top *= BC_POW_10_LUT [count ];
159
+ n_top += n_vector [n_top_index ] / BC_POW_10_LUT [BC_VECTOR_SIZE - count ];
160
+ }
161
+
162
+ /* Calculate the initial guess. */
163
+ BC_VECTOR initial_guess = bc_fast_sqrt_vector (n_top );
164
+
165
+ /* Set the obtained initial guess to guess_vector. */
166
+ size_t initial_guess_len = (n_top_len_for_initial_guess + 1 ) / 2 ;
167
+ size_t guess_top_vector_len = guess_full_len % BC_VECTOR_SIZE == 0 ? BC_VECTOR_SIZE : guess_full_len % BC_VECTOR_SIZE ;
168
+ size_t guess_len_diff = initial_guess_len - guess_top_vector_len ;
169
+ guess_vector [guess_arr_size - 2 ] = initial_guess / BC_POW_10_LUT [guess_len_diff ];
170
+ initial_guess %= BC_POW_10_LUT [guess_len_diff ];
171
+ guess_vector [guess_arr_size - 3 ] = initial_guess * BC_POW_10_LUT [BC_VECTOR_SIZE - guess_len_diff ];
172
+ guess_vector [guess_arr_size - 3 ] += BC_POW_10_LUT [BC_VECTOR_SIZE - guess_len_diff ] - 1 ;
173
+
174
+ /* Initialize the uninitialized vector with zeros. */
175
+ for (size_t i = 0 ; i < guess_arr_size - 3 ; i ++ ) {
176
+ guess_vector [i ] = 0 ;
144
177
}
145
178
guess_vector [guess_arr_size - 1 ] = 0 ;
146
179
0 commit comments