@@ -177,24 +177,33 @@ static inline void bc_standard_sqrt(bc_num *num, size_t rscale, size_t num_calc_
177
177
178
178
guess1_vector [guess_arr_size - 1 ] = 0 ;
179
179
180
- size_t quot_size = n_arr_size - (guess_arr_size - 1 ) + 1 ;
181
-
182
180
BC_VECTOR two [1 ] = { 2 };
183
181
182
+ size_t guess_precision = 2 ;
183
+
184
184
/* Newton's algorithm. */
185
185
bool done = false;
186
186
do {
187
- for (size_t i = 0 ; i < n_arr_size ; i ++ ) {
187
+ size_t guess_offset = guess_arr_size - 1 - guess_precision ;
188
+ size_t n_offset = guess_offset * 2 ;
189
+ for (size_t i = n_offset ; i < n_arr_size ; i ++ ) {
188
190
n_vector_copy [i ] = n_vector [i ];
189
191
}
190
- bool div_ret = bc_divide_vector (n_vector_copy , n_arr_size , guess_vector , guess_arr_size - 1 , tmp_div_ret_vector , quot_size );
192
+
193
+ size_t n_precision = n_arr_size - n_offset ;
194
+ size_t quot_size = n_precision - (guess_precision ) + 1 ;
195
+ bool div_ret = bc_divide_vector (
196
+ n_vector_copy + n_offset , n_precision ,
197
+ guess_vector + guess_offset , guess_precision ,
198
+ tmp_div_ret_vector + guess_offset , quot_size
199
+ );
191
200
ZEND_ASSERT (div_ret );
192
201
193
202
BC_VECTOR * tmp_vptr = guess1_vector ;
194
203
guess1_vector = guess_vector ;
195
204
guess_vector = tmp_vptr ;
196
205
int carry = 0 ;
197
- for (size_t i = 0 ; i < guess_arr_size - 1 ; i ++ ) {
206
+ for (size_t i = guess_offset ; i < guess_arr_size ; i ++ ) {
198
207
guess_vector [i ] = guess1_vector [i ] + tmp_div_ret_vector [i ] + carry ;
199
208
if (guess_vector [i ] >= BC_VECTOR_BOUNDARY_NUM ) {
200
209
guess_vector [i ] -= BC_VECTOR_BOUNDARY_NUM ;
@@ -205,23 +214,35 @@ static inline void bc_standard_sqrt(bc_num *num, size_t rscale, size_t num_calc_
205
214
}
206
215
guess_vector [guess_arr_size - 1 ] = carry ;
207
216
208
- div_ret = bc_divide_vector (guess_vector , guess_arr_size , two , 1 , tmp_div_ret_vector , guess_arr_size );
217
+ div_ret = bc_divide_vector (
218
+ guess_vector + guess_offset , guess_precision + 1 ,
219
+ two , 1 ,
220
+ tmp_div_ret_vector + guess_offset , guess_precision + 1
221
+ );
209
222
ZEND_ASSERT (div_ret );
210
223
211
- for (size_t i = 0 ; i < guess_arr_size ; i ++ ) {
224
+ for (size_t i = guess_offset ; i < guess_arr_size ; i ++ ) {
212
225
guess_vector [i ] = tmp_div_ret_vector [i ];
213
226
}
214
227
215
- size_t diff = guess_vector [0 ] > guess1_vector [0 ] ? guess_vector [0 ] - guess1_vector [0 ] : guess1_vector [0 ] - guess_vector [0 ];
228
+ size_t diff = guess_vector [guess_offset ] > guess1_vector [guess_offset ]
229
+ ? guess_vector [guess_offset ] - guess1_vector [guess_offset ]
230
+ : guess1_vector [guess_offset ] - guess_vector [guess_offset ];
216
231
if (diff <= 1 ) {
217
232
bool is_same = true;
218
- for (size_t i = 1 ; i < guess_arr_size - 1 ; i ++ ) {
233
+ for (size_t i = guess_offset + 1 ; i < guess_arr_size - 1 ; i ++ ) {
219
234
if (guess_vector [i ] != guess1_vector [i ]) {
220
235
is_same = false;
221
236
break ;
222
237
}
223
238
}
224
- done = is_same ;
239
+ if (is_same ) {
240
+ if (guess_precision < guess_arr_size - 1 ) {
241
+ guess_precision = MIN (guess_precision * 3 , guess_arr_size - 1 );
242
+ } else {
243
+ done = is_same ;
244
+ }
245
+ }
225
246
}
226
247
} while (!done );
227
248
0 commit comments