I am trying to implement a sieve of eratosthenes, this finds all pirmes below n by creating an array, iterating through that array and whenever a prime is found marking off all multiples of that prime as non-prime.
My code for the marking step is:
for (index, val) in is_prime[3..marking_lim].iter_mut().step_by(2).enumerate() { // borrow of is_prime
if *val == true {
primes_found.push(index as i32); // add the prime to the list
n_found = 1; // counter for primes found, cannot be exceeded in this step
for val_2 in is_prime[index..(up_to_nth as usize)].iter_mut().step_by(index) { // second borrow of is_prime
*val_2 = false;
}
}
}
However, this doesn't work as the inner loop takes a mutable borrow of is_prime
while it's still borrowed by the outer loop. Therefore, I need to somehow transfer ownership of the borrow to the inner loop so it can mark of the multiples. How can I do that?
CodePudding user response:
It's not possible to do exactly what you're asking. The easiest solution is to avoid borrowing is_prime
in the outer loop:
for (index, index_2) in (3..marking_lim).step_by(2).enumerate() {
if is_prime[index_2] {
// ...
A fancier solution is to use std::cell::Cell
, which lets you mutate the array items through a non-mut
reference:
use std::cell::Cell;
let is_prime = Cell::from_mut(&mut is_prime[..]).as_slice_of_cells();
for (index, val) in is_prime[3..marking_lim].iter().step_by(2).enumerate() {
if val.get() {
primes_found.push(index as i32);
n_found = 1;
for val_2 in is_prime[index..(up_to_nth as usize)].iter().step_by(index) {
val_2.set(false);
}
}
}