@@ -165,16 +165,25 @@ static inline void bc_standard_sqrt(bc_num *num, size_t scale, size_t num_calc_f
165165 guess_vector [guess_arr_size - 3 ] = initial_guess * BC_POW_10_LUT [BC_VECTOR_SIZE - guess_len_diff ];
166166 guess_vector [guess_arr_size - 3 ] += BC_POW_10_LUT [BC_VECTOR_SIZE - guess_len_diff ] - 1 ;
167167
168- /* Initialize the uninitialized vector with zeros . */
168+ /* Initialize the uninitialized vector with `BC_VECTOR_BOUNDARY_NUM - 1` . */
169169 for (size_t i = 0 ; i < guess_arr_size - 3 ; i ++ ) {
170- guess_vector [i ] = 0 ;
170+ guess_vector [i ] = BC_VECTOR_BOUNDARY_NUM - 1 ;
171+ guess1_vector [i ] = BC_VECTOR_BOUNDARY_NUM - 1 ;
171172 }
172173 guess_vector [guess_arr_size - 1 ] = 0 ;
173174
174- size_t quot_size = n_arr_size - (guess_arr_size - 1 ) + 1 ;
175-
176175 BC_VECTOR two [1 ] = { 2 };
177176
177+ /* The precision (number of vectors) used for the calculation.
178+ * Since the initial value uses two vectors, the initial precision is set to 2. */
179+ size_t guess_precision = 2 ;
180+ size_t guess_offset = guess_arr_size - 1 - guess_precision ;
181+ size_t n_offset = guess_offset * 2 ;
182+ size_t n_precision = n_arr_size - n_offset ;
183+ size_t quot_size = n_precision - (guess_precision ) + 1 ;
184+ size_t guess_use_len = guess_top_vector_len + BC_VECTOR_SIZE ;
185+ bool updated_precision = false;
186+
178187 /**
179188 * Newton's algorithm. Iterative expression is `x_{n+1} = (x_n + a / x_n) / 2`
180189 * If break down the calculation into detailed steps, it looks like this:
@@ -185,14 +194,23 @@ static inline void bc_standard_sqrt(bc_num *num, size_t scale, size_t num_calc_f
185194 */
186195 bool done = false;
187196 do {
197+ if (updated_precision ) {
198+ guess_offset = guess_arr_size - 1 - guess_precision ;
199+ n_offset = guess_offset * 2 ;
200+ n_precision = n_arr_size - n_offset ;
201+ quot_size = n_precision - (guess_precision ) + 1 ;
202+ guess_use_len = guess_top_vector_len + (guess_precision - 1 ) * BC_VECTOR_SIZE ;
203+ updated_precision = false;
204+ }
205+
188206 /* Since the value changes during division by successive approximation, use a copied version of it. */
189- memcpy (n_vector_copy , n_vector , n_arr_size * sizeof (BC_VECTOR ));
207+ memcpy (n_vector_copy + n_offset , n_vector + n_offset , n_precision * sizeof (BC_VECTOR ));
190208
191209 /* 1. quot = a / x_n */
192210 bc_divide_vector (
193- n_vector_copy , n_arr_size ,
194- guess_vector , guess_arr_size - 1 , guess_full_len ,
195- tmp_div_ret_vector , quot_size
211+ n_vector_copy + n_offset , n_precision ,
212+ guess_vector + guess_offset , guess_precision , guess_use_len ,
213+ tmp_div_ret_vector + guess_offset , quot_size
196214 );
197215
198216 BC_VECTOR * tmp_vptr = guess1_vector ;
@@ -201,7 +219,7 @@ static inline void bc_standard_sqrt(bc_num *num, size_t scale, size_t num_calc_f
201219
202220 /* 2. add = x_n + quot1 */
203221 int carry = 0 ;
204- for (size_t i = 0 ; i < guess_arr_size - 1 ; i ++ ) {
222+ for (size_t i = guess_offset ; i < guess_arr_size - 1 ; i ++ ) {
205223 guess_vector [i ] = guess1_vector [i ] + tmp_div_ret_vector [i ] + carry ;
206224 if (guess_vector [i ] >= BC_VECTOR_BOUNDARY_NUM ) {
207225 guess_vector [i ] -= BC_VECTOR_BOUNDARY_NUM ;
@@ -214,24 +232,30 @@ static inline void bc_standard_sqrt(bc_num *num, size_t scale, size_t num_calc_f
214232
215233 /* 3. x_{n+1} = add / 2 */
216234 bc_divide_vector (
217- guess_vector , guess_arr_size ,
235+ guess_vector + guess_offset , guess_precision + 1 ,
218236 two , 1 , 1 ,
219- tmp_div_ret_vector , guess_arr_size
237+ tmp_div_ret_vector + guess_offset , guess_precision + 1
220238 );
221239
222- memcpy (guess_vector , tmp_div_ret_vector , guess_arr_size * sizeof (BC_VECTOR ));
240+ memcpy (guess_vector + guess_offset , tmp_div_ret_vector + guess_offset , guess_precision * sizeof (BC_VECTOR ));
223241
224242 /* 4. repeat until the difference between the `x_n` and `x_{n+1}` is less than or equal to 1. */
225- size_t diff = guess_vector [0 ] > guess1_vector [0 ] ? guess_vector [0 ] - guess1_vector [0 ] : guess1_vector [0 ] - guess_vector [0 ];
226- if (diff <= 1 ) {
227- bool is_same = true;
228- for (size_t i = 1 ; i < guess_arr_size - 1 ; i ++ ) {
229- if (guess_vector [i ] != guess1_vector [i ]) {
230- is_same = false;
231- break ;
243+ if (guess_precision < guess_arr_size - 1 ) {
244+ /* If the precision has not yet reached the maximum number of digits, it will be increased. */
245+ guess_precision = MIN (guess_precision * 2 , guess_arr_size - 1 );
246+ updated_precision = true;
247+ } else {
248+ size_t diff = guess_vector [0 ] > guess1_vector [0 ] ? guess_vector [0 ] - guess1_vector [0 ] : guess1_vector [0 ] - guess_vector [0 ];
249+ if (diff <= 1 ) {
250+ bool is_same = true;
251+ for (size_t i = 1 ; i < guess_arr_size - 1 ; i ++ ) {
252+ if (guess_vector [i ] != guess1_vector [i ]) {
253+ is_same = false;
254+ break ;
255+ }
232256 }
257+ done = is_same ;
233258 }
234- done = is_same ;
235259 }
236260 } while (!done );
237261
0 commit comments