What is the most idiomatic way in Chapel to loop over a series of real numbers with a fixed increment?
The C equivalent code would be:
for (x = 0.0; x<1.0; x+=0.1) {}
In Python/Numpy, one might write
x = numpy.arange(0.0, 1.0, 0.1)
I could imagine writing an iterator as below, but is there an equivalent built into the language/standard modules? (and then of course, there is the question of writing parallel versions of this)
iter arange(start, stop, step) {
var x = start;
while (x < stop) {
yield x;
x += step;
}
}
Just to expand on the iterator option : Defining an iterator then gets you nice array semantics with no extra work (thanks, Chapel!). Taking the code above and expanding it with some test cases:
// Define the general case
iter arange(type t, start, stop, step=1:t) {
assert(stop > start, "Stop must be greater than start");
assert(step > 0, "Step must be greater than 0");
var x : t = start;
while (x < stop) {
yield x;
x += step;
}
}
// Overload for type from arguments
iter arange(start:?t, stop:t, step:t=1:t) {
for x in arange(t, start, stop, step) do yield x;
}
// Overload for no start and default step = 1
iter arange(type t, stop) {
for x in arange(t, 0, stop, 1) do yield x;
}
// Overload for no start and default step = 1
iter arange(stop:?t) {
for x in arange(t, 0, stop, 1) do yield x;
}
// Example of simple iteration
for xi in arange(0.0,1.0,0.1) do writef(" %r",xi);
writef("\n");
for xi in arange(real,0,1,0.1) do writef(" %r",xi);
writef("\n");
// But Chapel allows other wonderful things once you
// define an iterator
// Array assignment
var x = arange(real, 0, 1, 0.1);
writeln(x);
// Promote a scalar function
var y = sin(2*pi*arange(real, 0, 1, 0.1));
for yi in y do writef(" %.3r",yi);
writef("\n");
// Step is optional
writeln(arange(real, 0, 10));
writeln(arange(0.0, 10.0));
Running this produces
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
0 0.588 0.951 0.951 0.588 1.22e-16 -0.588 -0.951 -0.951 -0.588 -1.13e-15
0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0
0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0
Chapel doesn't currently have built-in support for iterating over regular sequences of floating point values. At times, we've discussed extending Chapel's range type to support floating point index types, but have not pursued that idea so far. I believe that, at present, there isn't any standard library support for such patterns either. Either of these would be reasonable feature requests to make on Chapel's GitHub issues page.
If I were writing this pattern today, I'd either write the iterator you did or simply put the while loop directly in my code. For parallel iteration over a range of floating point values, creating a family of iterator overloads as described in Chapel's parallel iterators primer would be the way to go.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With