1
1
use alloc:: alloc:: Layout ;
2
- use core:: { mem, ptr, slice} ;
2
+ use core:: borrow:: BorrowMut as _;
3
+ use core:: mem;
3
4
use dashu_base:: { ExtendedGcd , Gcd } ;
4
5
5
6
use crate :: {
@@ -347,12 +348,12 @@ pub fn gcd_ext_in_place(
347
348
rhs : & mut [ Word ] ,
348
349
memory : & mut Memory ,
349
350
) -> ( usize , usize , Sign ) {
350
- let ( lhs_len, rhs_len) = ( lhs. len ( ) , rhs. len ( ) ) ;
351
- let ( lhs_ptr, rhs_ptr) = ( lhs. as_mut_ptr ( ) , rhs. as_mut_ptr ( ) ) ;
351
+ let lhs_len = lhs. len ( ) ;
352
352
353
353
// keep x >= y though the algorithm, and track the source of x and y using the swapped flag
354
354
debug_assert ! ( cmp_in_place( lhs, rhs) . is_ge( ) ) ;
355
- let ( mut x, mut y) = ( lhs, rhs) ;
355
+ // Use `borrow_mut` to be able to claim back `lhs` and `rhs`
356
+ let ( mut x, mut y) = ( lhs. borrow_mut ( ) , rhs. borrow_mut ( ) ) ;
356
357
let mut swapped = false ;
357
358
358
359
// the normal way is to have four variables s0, s1, t0, t1 and keep gcd(x, y) = gcd(lhs, rhs),
@@ -449,25 +450,19 @@ pub fn gcd_ext_in_place(
449
450
// If y is zero, then the gcd result is in x now.
450
451
// Note that y.len() == 0 is equivalent to y == 0, which is guaranteed by trim_leading_zeros.
451
452
if y. is_empty ( ) {
452
- // SAFETY: see the comments in the block. The safety here need to be carefully managed.
453
- unsafe {
454
- if !swapped {
455
- // if not swapped, then x is originated from lhs, copy it to rhs
456
- debug_assert ! ( x. as_ptr( ) == lhs_ptr) ;
457
- debug_assert ! ( x. len( ) <= rhs_len) ;
458
-
459
- // SAFETY: at this point, x should be from lhs, so it's not overlapping with rhs
460
- ptr:: copy_nonoverlapping ( x. as_ptr ( ) , rhs_ptr, x. len ( ) ) ;
461
- }
462
- // SAFETY: t0 is temporarily allocated space, it won't overlap with lhs or rhs
463
- ptr:: copy_nonoverlapping ( t0. as_ptr ( ) , lhs_ptr, t0_len) ;
453
+ let x_len = x. len ( ) ;
454
+ // We are not using the borrwed `x` / `y` anymore, so we can
455
+ // claim back the original `lhs` / `rhs`.
456
+ if !swapped {
457
+ rhs[ ..x_len] . copy_from_slice ( & lhs[ ..x_len] ) ;
464
458
}
459
+ lhs[ ..t0_len] . copy_from_slice ( & t0[ ..t0_len] ) ;
465
460
let sign = if swapped {
466
461
Sign :: Positive
467
462
} else {
468
463
Sign :: Negative
469
464
} ;
470
- return ( x . len ( ) , t0_len, sign) ;
465
+ return ( x_len , t0_len, sign) ;
471
466
}
472
467
473
468
// before forwarding to single word gcd, first reduce x by y:
@@ -491,15 +486,8 @@ pub fn gcd_ext_in_place(
491
486
// let lhs stores |b| = |cx| * t0 + |cy| * t1
492
487
// by now, number of words in |b| should be close to lhs
493
488
494
- // SAFETY: we don't hold any reference to lhs and rhs now, so there will be no
495
- // data racing. The pointer and length are from the original slice, so the slice
496
- // will be valid.
497
- let ( lhs, rhs) = unsafe {
498
- (
499
- slice:: from_raw_parts_mut ( lhs_ptr, lhs_len) ,
500
- slice:: from_raw_parts_mut ( rhs_ptr, rhs_len) ,
501
- )
502
- } ;
489
+ // We are not using the borrwed `x` / `y` anymore, so we can
490
+ // claim back the original `lhs` / `rhs`.
503
491
* rhs. first_mut ( ) . unwrap ( ) = g_word;
504
492
lhs. fill ( 0 ) ;
505
493
0 commit comments