@@ -175,16 +175,25 @@ static inline void bc_standard_sqrt(bc_num *num, size_t scale, size_t num_calc_f
175
175
guess_vector [guess_arr_size - 3 ] = initial_guess * BC_POW_10_LUT [BC_VECTOR_SIZE - guess_len_diff ];
176
176
guess_vector [guess_arr_size - 3 ] += BC_POW_10_LUT [BC_VECTOR_SIZE - guess_len_diff ] - 1 ;
177
177
178
- /* Initialize the uninitialized vector with zeros . */
178
+ /* Initialize the uninitialized vector with `BC_VECTOR_BOUNDARY_NUM - 1` . */
179
179
for (size_t i = 0 ; i < guess_arr_size - 3 ; i ++ ) {
180
- guess_vector [i ] = 0 ;
180
+ guess_vector [i ] = BC_VECTOR_BOUNDARY_NUM - 1 ;
181
+ guess1_vector [i ] = BC_VECTOR_BOUNDARY_NUM - 1 ;
181
182
}
182
183
guess_vector [guess_arr_size - 1 ] = 0 ;
183
184
184
- size_t quot_size = n_arr_size - (guess_arr_size - 1 ) + 1 ;
185
-
186
185
BC_VECTOR two [1 ] = { 2 };
187
186
187
+ /* The precision (number of vectors) used for the calculation.
188
+ * Since the initial value uses two vectors, the initial precision is set to 2. */
189
+ size_t guess_precision = 2 ;
190
+ size_t guess_offset = guess_arr_size - 1 - guess_precision ;
191
+ size_t n_offset = guess_offset * 2 ;
192
+ size_t n_precision = n_arr_size - n_offset ;
193
+ size_t quot_size = n_precision - (guess_precision ) + 1 ;
194
+ size_t guess_use_len = guess_top_vector_len + BC_VECTOR_SIZE ;
195
+ bool updated_precision = false;
196
+
188
197
/**
189
198
* Newton's algorithm. Iterative expression is `x_{n+1} = (x_n + a / x_n) / 2`
190
199
* If break down the calculation into detailed steps, it looks like this:
@@ -195,14 +204,23 @@ static inline void bc_standard_sqrt(bc_num *num, size_t scale, size_t num_calc_f
195
204
*/
196
205
bool done = false;
197
206
do {
207
+ if (updated_precision ) {
208
+ guess_offset = guess_arr_size - 1 - guess_precision ;
209
+ n_offset = guess_offset * 2 ;
210
+ n_precision = n_arr_size - n_offset ;
211
+ quot_size = n_precision - (guess_precision ) + 1 ;
212
+ guess_use_len = guess_top_vector_len + (guess_precision - 1 ) * BC_VECTOR_SIZE ;
213
+ updated_precision = false;
214
+ }
215
+
198
216
/* Since the value changes during division by successive approximation, use a copied version of it. */
199
- memcpy (n_vector_copy , n_vector , n_arr_size * sizeof (BC_VECTOR ));
217
+ memcpy (n_vector_copy + n_offset , n_vector + n_offset , n_precision * sizeof (BC_VECTOR ));
200
218
201
219
/* 1. quot = a / x_n */
202
220
bc_divide_vector (
203
- n_vector_copy , n_arr_size ,
204
- guess_vector , guess_arr_size - 1 , guess_full_len ,
205
- tmp_div_ret_vector , quot_size
221
+ n_vector_copy + n_offset , n_precision ,
222
+ guess_vector + guess_offset , guess_precision , guess_use_len ,
223
+ tmp_div_ret_vector + guess_offset , quot_size
206
224
);
207
225
208
226
BC_VECTOR * tmp_vptr = guess1_vector ;
@@ -211,7 +229,7 @@ static inline void bc_standard_sqrt(bc_num *num, size_t scale, size_t num_calc_f
211
229
212
230
/* 2. add = x_n + quot1 */
213
231
int carry = 0 ;
214
- for (size_t i = 0 ; i < guess_arr_size - 1 ; i ++ ) {
232
+ for (size_t i = guess_offset ; i < guess_arr_size - 1 ; i ++ ) {
215
233
guess_vector [i ] = guess1_vector [i ] + tmp_div_ret_vector [i ] + carry ;
216
234
if (guess_vector [i ] >= BC_VECTOR_BOUNDARY_NUM ) {
217
235
guess_vector [i ] -= BC_VECTOR_BOUNDARY_NUM ;
@@ -224,24 +242,30 @@ static inline void bc_standard_sqrt(bc_num *num, size_t scale, size_t num_calc_f
224
242
225
243
/* 3. x_{n+1} = add / 2 */
226
244
bc_divide_vector (
227
- guess_vector , guess_arr_size ,
245
+ guess_vector + guess_offset , guess_precision + 1 ,
228
246
two , 1 , 1 ,
229
- tmp_div_ret_vector , guess_arr_size
247
+ tmp_div_ret_vector + guess_offset , guess_precision + 1
230
248
);
231
249
232
- memcpy (guess_vector , tmp_div_ret_vector , guess_arr_size * sizeof (BC_VECTOR ));
250
+ memcpy (guess_vector + guess_offset , tmp_div_ret_vector + guess_offset , guess_precision * sizeof (BC_VECTOR ));
233
251
234
252
/* 4. repeat until the difference between the `x_n` and `x_{n+1}` is less than or equal to 1. */
235
- size_t diff = guess_vector [0 ] > guess1_vector [0 ] ? guess_vector [0 ] - guess1_vector [0 ] : guess1_vector [0 ] - guess_vector [0 ];
236
- if (diff <= 1 ) {
237
- bool is_same = true;
238
- for (size_t i = 1 ; i < guess_arr_size - 1 ; i ++ ) {
239
- if (guess_vector [i ] != guess1_vector [i ]) {
240
- is_same = false;
241
- break ;
253
+ if (guess_precision < guess_arr_size - 1 ) {
254
+ /* If the precision has not yet reached the maximum number of digits, it will be increased. */
255
+ guess_precision = MIN (guess_precision * 2 , guess_arr_size - 1 );
256
+ updated_precision = true;
257
+ } else {
258
+ size_t diff = guess_vector [0 ] > guess1_vector [0 ] ? guess_vector [0 ] - guess1_vector [0 ] : guess1_vector [0 ] - guess_vector [0 ];
259
+ if (diff <= 1 ) {
260
+ bool is_same = true;
261
+ for (size_t i = 1 ; i < guess_arr_size - 1 ; i ++ ) {
262
+ if (guess_vector [i ] != guess1_vector [i ]) {
263
+ is_same = false;
264
+ break ;
265
+ }
242
266
}
267
+ done = is_same ;
243
268
}
244
- done = is_same ;
245
269
}
246
270
} while (!done );
247
271
0 commit comments