Is there a Chapel analog for the Fortran do loop increment? e.g., Fortran such as:
do i = 0, numprocs, istep ...
Thanks very much.
Try this:
config const numprocs = 5;
config const istep = 2;
for i in 0..numprocs by istep {
writeln(i);
}
Note that a negative step will iterate over the range in reverse.
More information and examples are available in the range primer.
Related
The fold manual gives an example:
input price = close;
input length = 9;
plot SMA = (fold n = 0 to length with s do s + getValue(price, n, length - 1)) / lenth;
This effectively calls a function iteratively like in a for loop body.
When I use this statement to call my own function as follows, then it breaks because the loop index variable is not recognized as a variable that can be passed to my function:
script getItem{
input index = 0;
plot output = index * index;
}
script test{
def total = fold index = 0 to 10 with accumulator = 0 do
accumulator + getItem(index);########## Error: No such variable: index
}
It is a known bug / limitation. Has been acknowledged without a time line for a fix. No workaround available.
Have you tried adding a small remainder to your defined variable within the fold and then pass that variable? You can strip the integer value and then use the remainder as your counter value. I've been playing around with somethin similar but it isn't working (yet). Here's an example:
script TailOverlap{
input i = 0;
def ii = (Round(i, 1) - i) * 1000;
... more stuff
plot result = result;
};
def _S = (
fold i = displace to period
with c = 0
do if
TailOverlap(i = _S) #send cur val of _S to script
then _S[1] + 1.0001 #increment variable and counter
else _S[1] + 0.0001 #increment the counter only
);
I'm going to continue playing around with this. If I get it to work I'll post the final solution. If you're able to get work this (or have discovered another solution) please do post it here so I know.
Thanks!
I am converting a cpp prog (from another author) to a Fortran prog, my C is not too strong. I came across for-loop constructs starting with
for (int n = 1; 1; ++n) {
...
I would have expected this to convert to a Fortran Do as per
Do n=1, 1, 2
...
... at least that is my guess based on my understanding of what ++n will do.
Is my translation correct? If so, the loop will cycle at most once, so what am I missing ???
I understand that in some ways c for-loops have a "do-while" aspect, and hence wrinkles porting to Fortran Do's.
Anyway ... a clarification would be much appreciated.
EDITED: after some prompt responses, and I think I see where this is going
First, the exact C code copy/paste but "trimming" a little, is
for (int n = 1; 1; ++n) {
const double coef = exp(-a2*(n*n)) * expx2 / (a2*(n*n) + y*y);
prod2ax *= exp2ax;
prodm2ax *= expm2ax;
sum1 += coef;
sum2 += coef * prodm2ax;
sum4 += (coef * prodm2ax) * (a*n);
sum3 += coef * prod2ax;
sum5 += (coef * prod2ax) * (a*n);
// test convergence via sum5, since this sum has the slowest decay
if ((coef * prod2ax) * (a*n) < relerr * sum5) break;
}
So yes, there is a "break" in the loop, which on the Fortran side is replaced with an "Exit".
I think the key seems to be from the answers below that the original code's author created the
for (int n=1; 1 ; ++n )
precisely to create a an infinite loop, and I had not guessed that this for construct would create an infinite loop.
Anyway, I can certainly create an infinite loop with an "Exit" in Fortran (though I expect I might "do" it a bit more judiciously)
Many thanks to all.
It seems the Mr Gregory's response was the one that imediately lead to a solution for me, so I will mark his correct. As for the Fortran side, there are a number of alternatives such as:
Do While
:
If( something ) Exit
End Do
but being old fashioned I would probably use a construct with a "limit" such as
Do i=1, MaxIter
:
If( something ) Exit
End Do
For slightly fancier applications I might include a return flag in case it did not converge in MaxIter's etc.
It's difficult to be definitive without seeing how the C++ program breaks out of that loop, but a straightforward Fortran equivalent would be
n = 1
do
! code, including an exit under some condition, presumably on the value of n
n = n+1
end do
If the loop is terminated when n reaches a critical value then the equivalent might be
do n = 1, critical_value ! no need to indicate step size if it is 1
! code
end do
Are you sure you wrote the C code correctly? Typically loops in C/C++ are done like this:
for (int n = 1; n < 10; ++n) {
// ...
}
Note the "n < 10" test condition. Your code's test condition is simply 1, which will always evaluate to Boolean "true". This means the code will loop infinitely, unless there's a break inside the loop, which you haven't shown.
++n means "increment n".
So if the code you've shown is indeed correct, the FORTRAN equivalent would be:
n = 1
do
[Body of the loop, which you haven't shown]
n = n + 1
enddo
Here's what
for (int n = 1; 1; ++n)
does:
It sets n to 1, then loops infinitely, incrementing n by 1 at the end of each loop iteration. The loop will never terminate unless something inside the loop breaks out.
It's been a long time since I wrote Fortran but as I recall the do loop you translated it to is not correct.
I don't think you can translate
for (int n = 1; 1; ++n)
to a FORTRAN DO loop. From what I recall, the notion of the generic conditional in C/C++ cannot be emulated in a FORTRAN DO loop.
The equivalent of
Do n=1, 1, 2
in C/C++ is
for ( int n = 1; n <= 1; n += 2 )
A few notes in addition to CareyGregory’s answer.
++n means ‘increment n by one (before n is evaluated)’
In C and C++, a for loop has three clauses, much like in FORTRAN:
for (init; condition; increment)
The difference is that each of the clauses must be a complete expression, whereas in FORTRAN the clauses are just values. It is just a ‘short’ way of writing an equivalent while loop:
int n = 1; │ for (int n = 1; 1; ++n) │ n = 1
while (1) │ { │ do
{ │ ... │ ...
... │ } │ n = n + 1
++n; │ │ enddo
} │ │
Like any normal C++ programmer, when I type this code...
for (int m = 0; m < 3; m++){
for (int n = 0; n < 3; n++){
if (A[m].substr(size,location) == B[n].substr(size,location)){
return false;
}
}
}
I expect the first value of m to be 0 in my iteration. (because I literally declared it as having a value of 0) However, my program was acting a tad funky, so I decided to look at it in the debugger. Interestingly, rather than having a starting value of 0, C++ decided that m should have a starting value of 32767.
Could someone explain to my why and how this could possibly happen?
Ah, templatetypedef was right. Once I stepped over to the next breakpoint its value was initialized. Thanks guys!
I have a problem while using a do loop in fortran,
REAL W,V,X
DO 50 W = 0.5,5.0,0.5
DO 50 V = 10.0,1000.0,10.0
DO 50 X = 1.0,10,1.0
C=(W*V*X)/1000.0
WRITE(*,*) W,V,X,C
50 CONTINUE
STOP
END
If I gave this it is showing that only integers needs to be used in do loop, is there any way to give integers in do loop or any other way to do it?
Use integers as your looping indices
REAL W,V,X
INTEGER I,J,K
DO 50 I = 1,10
DO 50 J = 1,100
DO 50 K = 1,10
W = 0.5 * I
V = 10.0 * J
X = 1.0 * K
C=(W*V*X)/1000.0
WRITE(*,*) W,V,X,C
50 CONTINUE
STOP
END
You should be able to accomplish the same thing by incrementing a real variable by adding your step value, and using an if then to exit the loop. Clunky, but should work.
The last time I programmed in Fortran, I used punch cards and an IBM-360, so I'm not going to pretend I remember the syntax.
Hey, I wrote this (fortran) with the aim of finding the minimum spanning tree of a bunch of points (syscount of them). I know for a fact that this approach works, since i wrote it in javascript earlier today. js is slow though, and i wanted to see how much faster fortran would be!!
only problem is it's not working, i'm getting an annoying error;
prims.f95:72.43:
if((check == 1) .and. (path(nodesin(j))(k) < minpath)) then
1
Error: Expected a right parenthesis in expression at (1)
What the hell is that about?! the 43rd character on the line is the "h" of "path"
nodesin(1) = 1
do i = 1,syscount-1
pathstart = -1
pathend = -1
minpath = 2000
do j = 1,i
do k = 1, syscount
check = 1
do l = 1, i
if(nodesin(l) == k) then
check = 0
end if
end do
if((check == 1) .and. (path(nodesin(j))(k) < minpath)) then
minpath = path(nodesin(j))(k)
pathstart = nodesin(j)
pathend = k
end if
end do
end do
nodesin(i+1) = pathend
minpaths(i)(1) = pathstart
minpaths(i)(2) = pathend
end do
Also, i'm fairly new to fortran, so i have a few other questions;
can i use && instead of .and. ?
is there a versions of the for(object in list){} loop found in many other languages?
is there a verion of the php function in_array ? i.e. bool in_array(needle,haystack), and if there is, is there a better way of doing it than:
check = false
Asize = size(array)
do i = 1, Asize
if(array(i) == needle) then
check = true
end if
end do
then to using the check variable to see if it's there?
(I haven't posted anything on stackoverflow before. please don't get angry if i've broken loads of etiquette things!)
It looks like you have defined path and minpaths as two-dimensional arrays. Multi-dimensional arrays are accessed differently in Fortran when compared to C-like languages. In Fortran you separate the indices by commas within one set of parentheses.
I'm guessing by the use of these variables they are integer arrays. Here is how you access elements of those arrays (since you didn't share your variable declarations I am making up the shape of these arrays):
integer :: path(n1, n2)
integer :: minpaths(n3, 2)
your if statement should be:
if((check == 1) .and. (path(nodesin(j), k) < minpath)) then
your access to minpaths should be:
minpaths(i, 1) = pathstart
minpaths(i, 2) = pathend
Also, if you are not using IMPLICIT NONE I recommend you consider it. Not using it is dangerous, and you are using variable names that are close to each other (minpath and minpaths). You could save hours of hair pulling debugging by using IMPLICIT NONE.
While .EQ. can be replaced with ==, there is still only .AND.
For your code block to check whether a "variable is there", you can use "where" and have much shorter code!
In Fortran >= 90 statements and functions can operate on arrays so that explicit loops don't have to be used as frequently.
There is no for (object in list), but using the where statement can do something very similar.
Many of the intrinsic functions that act on arrays also take masks as optional arguments to selectively operate.
I suggest reading a book to learn about these features. I like the one by Metcalf, Reid and Cohen. In the meantime, the second Wikipedia article may help: http://en.wikipedia.org/wiki/Fortran_95_language_features