@@ -167,16 +167,25 @@ static inline void bc_standard_sqrt(bc_num *num, size_t rscale, size_t num_calc_
167167 initial_guess %= BC_POW_10_LUT [guess_len_diff ];
168168 guess_vector [guess_arr_size - 3 ] = initial_guess * BC_POW_10_LUT [BC_VECTOR_SIZE - guess_len_diff ];
169169
170- /* Initialize the uninitialized vector with zeros . */
170+ /* Initialize the uninitialized vector with `BC_VECTOR_BOUNDARY_NUM - 1` . */
171171 for (size_t i = 0 ; i < guess_arr_size - 3 ; i ++ ) {
172- guess_vector [i ] = 0 ;
172+ guess_vector [i ] = BC_VECTOR_BOUNDARY_NUM - 1 ;
173+ guess1_vector [i ] = BC_VECTOR_BOUNDARY_NUM - 1 ;
173174 }
174175 guess_vector [guess_arr_size - 1 ] = 0 ;
175176
176- size_t quot_size = n_arr_size - (guess_arr_size - 1 ) + 1 ;
177-
178177 BC_VECTOR two [1 ] = { 2 };
179178
179+ /* The precision (number of vectors) used for the calculation.
180+ * Since the initial value uses two vectors, the initial precision is set to 2. */
181+ size_t guess_precision = 2 ;
182+ size_t guess_offset = guess_arr_size - 1 - guess_precision ;
183+ size_t n_offset = guess_offset * 2 ;
184+ size_t n_precision = n_arr_size - n_offset ;
185+ size_t quot_size = n_precision - (guess_precision ) + 1 ;
186+ size_t guess_use_len = guess_top_vector_len + BC_VECTOR_SIZE ;
187+ bool updated_precision = false;
188+
180189 /**
181190 * Newton's algorithm. Iterative expression is `x_{n+1} = (x_n + a / x_n) / 2`
182191 * If break down the calculation into detailed steps, it looks like this:
@@ -187,16 +196,25 @@ static inline void bc_standard_sqrt(bc_num *num, size_t rscale, size_t num_calc_
187196 */
188197 bool done = false;
189198 do {
199+ if (updated_precision ) {
200+ guess_offset = guess_arr_size - 1 - guess_precision ;
201+ n_offset = guess_offset * 2 ;
202+ n_precision = n_arr_size - n_offset ;
203+ quot_size = n_precision - (guess_precision ) + 1 ;
204+ guess_use_len = guess_top_vector_len + (guess_precision - 1 ) * BC_VECTOR_SIZE ;
205+ updated_precision = false;
206+ }
207+
190208 /* Since the value changes during division by successive approximation, use a copied version of it. */
191- for (size_t i = 0 ; i < n_arr_size ; i ++ ) {
209+ for (size_t i = n_offset ; i < n_arr_size ; i ++ ) {
192210 n_vector_copy [i ] = n_vector [i ];
193211 }
194212
195213 /* 1. quot = a / x_n */
196214 bc_divide_vector (
197- n_vector_copy , n_arr_size ,
198- guess_vector , guess_arr_size - 1 , guess_full_len ,
199- tmp_div_ret_vector , quot_size
215+ n_vector_copy + n_offset , n_precision ,
216+ guess_vector + guess_offset , guess_precision , guess_use_len ,
217+ tmp_div_ret_vector + guess_offset , quot_size
200218 );
201219
202220 BC_VECTOR * tmp_vptr = guess1_vector ;
@@ -205,7 +223,7 @@ static inline void bc_standard_sqrt(bc_num *num, size_t rscale, size_t num_calc_
205223
206224 /* 2. add = x_n + quot1 */
207225 int carry = 0 ;
208- for (size_t i = 0 ; i < guess_arr_size - 1 ; i ++ ) {
226+ for (size_t i = guess_offset ; i < guess_arr_size ; i ++ ) {
209227 guess_vector [i ] = guess1_vector [i ] + tmp_div_ret_vector [i ] + carry ;
210228 if (guess_vector [i ] >= BC_VECTOR_BOUNDARY_NUM ) {
211229 guess_vector [i ] -= BC_VECTOR_BOUNDARY_NUM ;
@@ -214,30 +232,41 @@ static inline void bc_standard_sqrt(bc_num *num, size_t rscale, size_t num_calc_
214232 carry = 0 ;
215233 }
216234 }
217- guess_vector [guess_arr_size - 1 ] = carry ;
235+ guess_vector [guess_arr_size - 1 ] = tmp_div_ret_vector [ guess_arr_size - 1 ] + carry ;
218236
219237 /* 3. x_{n+1} = add / 2 */
220238 bc_divide_vector (
221- guess_vector , guess_arr_size ,
239+ guess_vector + guess_offset , guess_precision + 1 ,
222240 two , 1 , 1 ,
223- tmp_div_ret_vector , guess_arr_size
241+ tmp_div_ret_vector + guess_offset , guess_precision + 1
224242 );
225243
226- for (size_t i = 0 ; i < guess_arr_size ; i ++ ) {
244+ for (size_t i = guess_offset ; i < guess_arr_size ; i ++ ) {
227245 guess_vector [i ] = tmp_div_ret_vector [i ];
228246 }
247+ /* When estimating the square root of a number like 99,999,999, the result may sometimes have too many digits.
248+ * In such cases, the value is adjusted (corrected). */
249+ if (UNEXPECTED (tmp_div_ret_vector [guess_arr_size - 1 ] > 0 )) {
250+ guess_vector [guess_arr_size - 1 ] = BC_VECTOR_BOUNDARY_NUM - 1 ;
251+ }
229252
230253 /* 4. repeat until the difference between the `x_n` and `x_{n+1}` is less than or equal to 1. */
231- size_t diff = guess_vector [0 ] > guess1_vector [0 ] ? guess_vector [0 ] - guess1_vector [0 ] : guess1_vector [0 ] - guess_vector [0 ];
232- if (diff <= 1 ) {
233- bool is_same = true;
234- for (size_t i = 1 ; i < guess_arr_size - 1 ; i ++ ) {
235- if (guess_vector [i ] != guess1_vector [i ]) {
236- is_same = false;
237- break ;
254+ if (guess_precision < guess_arr_size - 1 ) {
255+ /* If the precision has not yet reached the maximum number of digits, it will be increased. */
256+ guess_precision = MIN (guess_precision * 2 , guess_arr_size - 1 );
257+ updated_precision = true;
258+ } else {
259+ size_t diff = guess_vector [0 ] > guess1_vector [0 ] ? guess_vector [0 ] - guess1_vector [0 ] : guess1_vector [0 ] - guess_vector [0 ];
260+ if (diff <= 1 ) {
261+ bool is_same = true;
262+ for (size_t i = 1 ; i < guess_arr_size - 1 ; i ++ ) {
263+ if (guess_vector [i ] != guess1_vector [i ]) {
264+ is_same = false;
265+ break ;
266+ }
238267 }
268+ done = is_same ;
239269 }
240- done = is_same ;
241270 }
242271 } while (!done );
243272
0 commit comments