How would you write the equivalent of this C++ loop in Rust - loops

Rust's for loops are a bit different than those in C-style languages. I am trying to figure out if I can achieve the same result below in a similar fashion in Rust. Note the condition where the i^2 < n.
for (int i = 2; i * i < n; i++)
{
// code goes here ...
}

You can always do a literal translation to a while loop.
let mut i = 2;
while i * i < n {
// code goes here
i += 1;
}
You can also always write a for loop over an infinite range and break out on an arbitrary condition:
for i in 2.. {
if i * i >= n { break }
// code goes here
}
For this specific problem, you could also use take_while, but I don't know if that is actually more readable than breaking out of the for loop. It would make more sense as part of a longer chain of "combinators".
for i in (2..).take_while(|i| i * i < n) {
// code goes here
}

The take_while suggestion from zwol's answer is the most idiomatic, and therefore usually the best choice. All of the information about the loop is kept together in a single expression instead of getting mixed into the body of the loop.
However, the fastest implementation is to precompute the square root of n (actually a weird sort of rounded-down square root). This lets you avoid doing a comparison every iteration, since you know this is always the final value of i.
let m = (n as f64 - 0.5).sqrt() as _;
for i in 2 ..= m {
// code goes here
}
As a side note, I tried to benchmark these different loops. The take_while was the slowest. The version I just suggested always reported 0 ns/iter, and I'm not sure if that's just due to some code being optimised to the point of not running at all, or if it really is too fast to measure. For most uses, the difference shouldn't be important though.

Update: I have learned more Rust since I wrote this answer. This structure is still useful for some rare situations (like when the logic inside the loop needs to conditionally mutate the counter variable), but usually you'll want to use a Range Expression like zwol said.
I like this form, since it keeps the increment at the top of the loop instead of the bottom:
let mut i = 2 - 1; // You need to subtract 1 from the initial value.
loop {
i+=1; if i*i >= n { break }
// code goes here...
}

Related

Can a recursive function containing a for loop that contains a call of the mentioned function be implemented using only for loops?

Similar questions have been asked and the general consensus is that anything can be converted from recursion to for loops and vice versa. However, I can't find a way to convert a function of the following pseudocode type to a for loop:
def recursive(n):
if n == 0:
return
for i in range(some_number):
do_sth...
recursive(n-1)
In this case, there is n nested loops and n varies depending on the given argument. When using only for loops, the number of nested loops seems to be always predetermined in the code, it doesn't vary depending on "input". Is there a way to make something like this using only for loops?
Is there a way to make something like this using only for loops?
Well, if you admit a while loop as a case of a pseudocode for loop, at least your example can be made:
def nonrecursive(n):
a = []
z = 0
while n:
while n:
i = z
if i == some_number: break
print((n, i))
a += [[n, i]]
n -= 1
z = 0
if not a: break
n, i = a.pop()
i += 1
z = i
We need to be careful here.
The general true statement is that loops can replace recursion and vice versa. This can be shown lots of ways; see the structured programming theorem for ideas.
Whether for loops can replace recursion depends upon your definitions. Can your for loops run forever, or for an indefinite amount of time not known in advance? If so, they are functionally equivalent to while loops, and they can replace recursion. If your for loops cannot be made to run forever or for an unknown (initially) number of iterations, recursion cannot always be replaced.
Really, it's while loops (plus a stack data structure) that can replace recursion without much trouble.

Does Ruby create a copy when referencing an array with its [..] (slice) method?

I want to loop on a slice of an array. I have basically two main options.
ar.each_with_index{|e,i|
next if i < start_ind
break if i > end_ind
foo(e)
#maybe more code...
}
Another option, which I think is more elegant, would be to run:
ar[start_ind..end_ind].each{|e|
foo(e)
#maybe more code...
}
My concern is Ruby potentially creating a huge array under the hood and doing a lot of memory allocation. Or is there something "smarter" at play that does not create a copy?
You could do a loop of index values... not as elegant as your second solution but economical.
(start_ind..end_ind).each do |index|
foo(ar[index])
# maybe more code
end
You may want to refer to methods' C source code, but it takes a bit of time to read the code. May I help you in this
First: each_index
It's source code in C is tricky, but boils down to something similar to 'each' which looks like
VALUE rb_ary_each(VALUE ary) {
long i;
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
for (i=0; i<RARRAY_LEN(ary); i++) {
rb_yield(RARRAY_AREF(ary, i));
}
return ary;
}
It does not create any other array internally by itself. What it effectively does is it simply loops through elements, takes each element and passes it into the block provided (rb_yield part). What's actually inside the block that you provide is a different story.
Second: [...].each
You actually have to notice it is two function calls. The second being 'each' is of little interest to us since it is described above The first function call is '[]'. Logically you expect it to output an subarray as variable, which has to be stored at least temporary.
Let's verify. Source code for C is rather long, but the piece of the greatest importance to you is:
VALUE rb_ary_aref(int argc, const VALUE *argv, VALUE ary) {
// some code
if (argc == 2) {
beg = NUM2LONG(argv[0]);
len = NUM2LONG(argv[1]);
if (beg < 0) {
beg += RARRAY_LEN(ary);
}
return rb_ary_subseq(ary, beg, len);
}
// some more code
}
It's actually for a function call like ar[start_ind, end_ind] and not ar[start_ind..end_ind]. The difference is immaterial, but this way is easier to understand.
The thing that answers your question is called "rb_ary_subseq". As you may guess from its name or learn from its source, it actually does create a new array. So it would create a copy under the hood of size equal or less of the array given.
You'd want to consider computational cost of functional calls, but the question is about memory.

How to remove certain elements from an array using a conditional test in C?

I am writing a program that goes through an array of ints and calculates stdev to identify outliers in the data. From here, I would like to create a new array with the identified outliers removed in order to recalculate the avg and stdev. Is there a way that I can do this?
There is a pretty simple solution to the problem that involves switching your mindset in the if statement (which isn't actually in a for loop it seems... might want to fix that).
float dataMinusOutliers[n];
int indexTracker = 0;
for (i=0; i<n; i++) {
if (data[i] >= (-2*stdevfinal) && data[i] <= (2*stdevfinal)) {
dataMinusOutliers[indexTracker] = data[i];
indexTracker += 1;
}
}
Note that this isn't particularly scalable and that the dataMinusOutliers array is going to potentially have quite a few unused indices. You can always use indexTracker - 1 to note how large the array actually is though, and create yet another array into which you copy the important values in dataMinusOutliers. Is there likely a more elegant solution? Yes. Does this work given your requirements though? Yup.

Translate performance critical loop from C to Rust

I'm experimenting with rewriting some old C code into Rust - which I'm new to. One recurring issue I have is that the C code has a lot of loops like this:
for (i = startIndex; i < asize; i++)
{
if (firstEdge < 0 && condLeft(i))
{
firstEdge = i;
}
RightIndex = asize-1-i;
if (firstEdgeRight < 0 && condRight(RightIndex))
{
firstEdgeRight = RightIndex;
}
// Found both edges
if (firstEdge >= 0 && firstEdgeRight >= 0) {
break;
}
}
How would you translate that into Rust in a performant way? My issue is that while I could probably get the functionality I want I'm not sure how to do it obtain (roughly) the same speed.
This part of the code is the main bottleneck in our code (this part of the code at least) and when translating it would like to keep the following properties.
The loop should break ASAP since asize can be very large.
Both firstEdge and firstEdgeRight are found roughly at the same time. Therefore it has been a good thing to only have one loop instead of two - in order to avoid search from the beginning again (even though I think this solution kills the prefetcher (but I'm not sure, maybe the old machine running the code doesn't even have a prefetcher)).
While performance is important, readability is of course even more important :)
EDIT Ok, here is a possible Rust implementation by me (cond_right() and cond_left() are left out).
The things I think about is:
Is this how other people would write it if they had to implement it from scratch?
Do I really need to make first_edge and first_edge_right mutable? They are in my implementation, but it feels wrong to me since they are only assigned once.
let mut first_edge = -1;
let mut first_edge_right = -1;
// Find first edge
let start_index = 300; // or something
let asize = 10000000;
for i in start_index..asize {
if first_edge < 0 && cond_left(i) {
first_edge = i;
}
let right_index = asize - i -1;
if first_edge_right < 0 && cond_right(right_index) {
first_edge_right = right_index;
}
if (first_edge >= 0 && first_edge_right >= 0) {
break;
}
}
You need to be prepared to make a choice:
How would you translate that into Rust in a performant way?
while performance is important, readability is of course even more important
Which is actually more important to you? Here's how I would write the code, assuming that I've understood what you are asking for:
fn left_condition(i: usize) -> bool {
i > 1000
}
fn right_condition(i: usize) -> bool {
i % 73 == 0
}
fn main() {
let start_index = 300;
let asize = 10000000;
let left = (start_index..asize).position(left_condition);
let right = (start_index..asize).rev().position(right_condition);
println!("{:?}, {:?}", left, right);
}
We iterate once from left-to-right and once from right-to-left. My gut tells me that this will provide code with simple branch prediction that accesses memory in a linear manner, both of which should be optimizable.
However, the variable name asize gives me pause. It certainly sounds like an abbreviation of "array size". If that's the case, then I would 100% recommend using slices instead of array indices. Why? Because array access (foo[0]) usually has overhead of bounds checking. I'd write something with slices:
let data = vec![0; 10_000_000];
let start_index = 300;
let slice = &data[start_index..];
let left = slice.iter().position(|&i| left_condition(i));
let right = slice.iter().rev().position(|&i| right_condition(i));
However, there's only one possible true answer to your question:
Use a profiler
Use a profiler
Use a profiler
Use a profiler
Only knowing your actual data, your actual implementations of the conditions, the rest of the code you are running, etc., can you actually know how fast something will be.
Therefore it has been a good thing to only have one loop instead of two - in order to avoid search from the beginning again
This is nonintuitive to me, so I'd want to see profiling results that back up the claim.
cond_left and cond_right are important to answer the performance question. For example, will replacing an index with an iterator help? Not going to tell without knowing what cond_left does.
The other concern you have is that first_edge and first_edge_right are mutable. The proposed RFC allowing loops to return a value could be an elegant way to solve this problem. Right now you could emulate the loop return with a closure:
let (_first_edge, _first_edge_right): (i32, i32) = (||{
let (mut first_edge, mut first_edge_right) = (None, None);
// ...
return (first_edge.unwrap(), first_edge_right.unwrap());
})();
(In Playground).
Replacing -1 with None will likely make the variable larger. See Can I use the "null pointer optimization" for my own non-pointer types?.
Splitting this loop into two loops, one getting the first_edge and another examining the remaining range to get the first_edge_right seems like the right thing to do, but the CPU branch prediction will likely minimize the impact.
Since it is critical to keep looking from both sides simultaneously, I don’t think there is an easy way to avoid having mutable variables.
One thing that can improve readability is to use option instead of negative numbers. Otherwise the code is fine.
(Another thing you probably could do is to break the loop when the indices meet in the middle, if this means that there is no solution for your problem, but that’s not Rust specific.)

C initializing a (very) large integer array with values corresponding to index

Edit3: Optimized by limiting the initialization of the array to only odd numbers. Thank you #Ronnie !
Edit2: Thank you all, seems as if there's nothing more I can do for this.
Edit: I know Python and Haskell are implemented in other languages and more or less perform the same operation I have bellow, and that the complied C code will beat them out any day. I'm just wondering if standard C (or any libraries) have built-in functions for doing this faster.
I'm implementing a prime sieve in C using Eratosthenes' algorithm and need to initialize an integer array of arbitrary size n from 0 to n. I know that in Python you could do:
integer_array = range(n)
and that's it. Or in Haskell:
integer_array = [1..n]
However, I can't seem to find an analogous method implemented in C. The solution I've come up with initializes the array and then iterates over it, assigning each value to the index at that point, but it feels incredibly inefficient.
int init_array()
{
/*
* assigning upper_limit manually in function for now, will expand to take value for
* upper_limit from the command line later.
*/
int upper_limit = 100000000;
int size = floor(upper_limit / 2) + 1;
int *int_array = malloc(sizeof(int) * size);
// debug macro, basically replaces assert(), disregard.
check(int_array != NULL, "Memory allocation error");
int_array[0] = 0;
int_array[1] = 2;
int i;
for(i = 2; i < size; i++) {
int_array[i] = (i * 2) - 1;
}
// checking some arbitrary point in the array to make sure it assigned properly.
// the value at any index 'i' should equal (i * 2) - 1 for i >= 2
printf("%d\n", int_array[1000]); // should equal 1999
printf("%d\n", int_array[size-1]); // should equal 99999999
free(int_array);
return 0;
error:
return -1;
}
Is there a better way to do this? (no, apparently there's not!)
The solution I've come up with initializes the array and then iterates over it, assigning each value to the index at that point, but it feels incredibly inefficient.
You may be able to cut down on the number of lines of code, but I do not think this has anything to do with "efficiency".
While there is only one line of code in Haskell and Python, what happens under the hood is the same thing as your C code does (in the best case; it could perform much worse depending on how it is implemented).
There are standard library functions to fill an array with constant values (and they could conceivably perform better, although I would not bet on that), but this does not apply here.
Here a better algorithm is probably a better bet in terms of optimising the allocation:-
Halve the size int_array_ptr by taking advantage of the fact that
you'll only need to test for odd numbers in the sieve
Run this through some wheel factorisation for numbers 3,5,7 to reduce the subsequent comparisons by 70%+
That should speed things up.

Resources