@@ -171,16 +171,25 @@ static inline void bc_standard_sqrt(bc_num *num, size_t rscale, size_t num_calc_
171171 guess_vector [guess_arr_size - 3 ] = initial_guess * BC_POW_10_LUT [BC_VECTOR_SIZE - guess_len_diff ];
172172 guess_vector [guess_arr_size - 3 ] += BC_POW_10_LUT [BC_VECTOR_SIZE - guess_len_diff ] - 1 ;
173173
174- /* Initialize the uninitialized vector with zeros . */
174+ /* Initialize the uninitialized vector with `BC_VECTOR_BOUNDARY_NUM - 1` . */
175175 for (size_t i = 0 ; i < guess_arr_size - 3 ; i ++ ) {
176- guess_vector [i ] = 0 ;
176+ guess_vector [i ] = BC_VECTOR_BOUNDARY_NUM - 1 ;
177+ guess1_vector [i ] = BC_VECTOR_BOUNDARY_NUM - 1 ;
177178 }
178179 guess_vector [guess_arr_size - 1 ] = 0 ;
179180
180- size_t quot_size = n_arr_size - (guess_arr_size - 1 ) + 1 ;
181-
182181 BC_VECTOR two [1 ] = { 2 };
183182
183+ /* The precision (number of vectors) used for the calculation.
184+ * Since the initial value uses two vectors, the initial precision is set to 2. */
185+ size_t guess_precision = 2 ;
186+ size_t guess_offset = guess_arr_size - 1 - guess_precision ;
187+ size_t n_offset = guess_offset * 2 ;
188+ size_t n_precision = n_arr_size - n_offset ;
189+ size_t quot_size = n_precision - (guess_precision ) + 1 ;
190+ size_t guess_use_len = guess_top_vector_len + BC_VECTOR_SIZE ;
191+ bool updated_precision = false;
192+
184193 /**
185194 * Newton's algorithm. Iterative expression is `x_{n+1} = (x_n + a / x_n) / 2`
186195 * If break down the calculation into detailed steps, it looks like this:
@@ -191,14 +200,23 @@ static inline void bc_standard_sqrt(bc_num *num, size_t rscale, size_t num_calc_
191200 */
192201 bool done = false;
193202 do {
203+ if (updated_precision ) {
204+ guess_offset = guess_arr_size - 1 - guess_precision ;
205+ n_offset = guess_offset * 2 ;
206+ n_precision = n_arr_size - n_offset ;
207+ quot_size = n_precision - (guess_precision ) + 1 ;
208+ guess_use_len = guess_top_vector_len + (guess_precision - 1 ) * BC_VECTOR_SIZE ;
209+ updated_precision = false;
210+ }
211+
194212 /* Since the value changes during division by successive approximation, use a copied version of it. */
195- memcpy (n_vector_copy , n_vector , n_arr_size * sizeof (BC_VECTOR ));
213+ memcpy (n_vector_copy + n_offset , n_vector + n_offset , n_precision * sizeof (BC_VECTOR ));
196214
197215 /* 1. quot = a / x_n */
198216 bc_divide_vector (
199- n_vector_copy , n_arr_size ,
200- guess_vector , guess_arr_size - 1 , guess_full_len ,
201- tmp_div_ret_vector , quot_size
217+ n_vector_copy + n_offset , n_precision ,
218+ guess_vector + guess_offset , guess_precision , guess_use_len ,
219+ tmp_div_ret_vector + guess_offset , quot_size
202220 );
203221
204222 BC_VECTOR * tmp_vptr = guess1_vector ;
@@ -207,7 +225,7 @@ static inline void bc_standard_sqrt(bc_num *num, size_t rscale, size_t num_calc_
207225
208226 /* 2. add = x_n + quot1 */
209227 int carry = 0 ;
210- for (size_t i = 0 ; i < guess_arr_size - 1 ; i ++ ) {
228+ for (size_t i = guess_offset ; i < guess_arr_size - 1 ; i ++ ) {
211229 guess_vector [i ] = guess1_vector [i ] + tmp_div_ret_vector [i ] + carry ;
212230 if (guess_vector [i ] >= BC_VECTOR_BOUNDARY_NUM ) {
213231 guess_vector [i ] -= BC_VECTOR_BOUNDARY_NUM ;
@@ -220,24 +238,30 @@ static inline void bc_standard_sqrt(bc_num *num, size_t rscale, size_t num_calc_
220238
221239 /* 3. x_{n+1} = add / 2 */
222240 bc_divide_vector (
223- guess_vector , guess_arr_size ,
241+ guess_vector + guess_offset , guess_precision + 1 ,
224242 two , 1 , 1 ,
225- tmp_div_ret_vector , guess_arr_size
243+ tmp_div_ret_vector + guess_offset , guess_precision + 1
226244 );
227245
228- memcpy (guess_vector , tmp_div_ret_vector , guess_arr_size * sizeof (BC_VECTOR ));
246+ memcpy (guess_vector + guess_offset , tmp_div_ret_vector + guess_offset , guess_precision * sizeof (BC_VECTOR ));
229247
230248 /* 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 ;
249+ if (guess_precision < guess_arr_size - 1 ) {
250+ /* If the precision has not yet reached the maximum number of digits, it will be increased. */
251+ guess_precision = MIN (guess_precision * 2 , guess_arr_size - 1 );
252+ updated_precision = true;
253+ } else {
254+ size_t diff = guess_vector [0 ] > guess1_vector [0 ] ? guess_vector [0 ] - guess1_vector [0 ] : guess1_vector [0 ] - guess_vector [0 ];
255+ if (diff <= 1 ) {
256+ bool is_same = true;
257+ for (size_t i = 1 ; i < guess_arr_size - 1 ; i ++ ) {
258+ if (guess_vector [i ] != guess1_vector [i ]) {
259+ is_same = false;
260+ break ;
261+ }
238262 }
263+ done = is_same ;
239264 }
240- done = is_same ;
241265 }
242266 } while (!done );
243267
0 commit comments