|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
mecej4
Joined: 31 Oct 2006 Posts: 1885
|
Posted: Thu Apr 30, 2015 4:45 am Post subject: Bad code generated for WHERE constructs |
|
|
The following test program compiles and runs correctly with three other compilers.
Code: | program drvr
implicit none
integer, parameter :: np=7
integer :: i=1
integer :: m
integer :: n=np
integer, dimension(np) :: f = (/ 1,2,3,4,5,6,7 /)
double precision, dimension(np) :: c = &
(/ 0.62, 0.61, 1., 1., 0.9998, 1., 0.997 /)
double precision, dimension(np) :: e = (/ 0.,0.,0.,0.,0.,0.,0. /)
double precision, dimension(np) :: q = &
(/ 0.89, -0.36, 0.56, -0.008, -0.188, -0.28, -0.369 /)
double precision, dimension(np) :: r = &
(/ 0.62, 0.61, 1., 1., 1., 0.9998, 0.9970 /)
double precision, dimension(np) :: w = &
(/ 5.,10.,0.5,0.5,0.5,0.5,0.5 /)
double precision :: a(2,np) = &
reshape( (/ 5.,10.,5.,10., 0.,1.,0.,1.,0.,1.,0.,1.,0.,1. /), &
(/ 2, 7 /))
call sub(n,m)
write(*,*)'Result = ',m
CONTAINS
subroutine sub(n, s)
implicit none
integer, intent(in) :: n
integer, intent(out) :: s
integer :: j
integer :: a01u(n), a11u(n)
double precision :: a91u(n), ae1u(n)
logical :: l2v(n), l3v(n)
m = 0
a11u = 0
if (i < 0) e(1:n) = 0d0
i = 1
l3v = .FALSE.
a01u = f(:n)
a91u = -q(:n)*r(:n)/c(a01u)
ae1u = w(a01u) - a91u
l2v = ae1u >= a(1,a01u)
where (l2v)
l3v = ae1u > a(2,a01u)
end where
where (l3v) ! <<<=== access error
a11u = (/(j,j=1,n)/)
end where
s=sum(a11u)
return
end subroutine sub
end program |
When this program is run using FTN95 7.10, with the command ftn95 whereprog.f90 /lgo,, the program crashes with an access violation on the line indicated (Line 47). The program should run without error and produce the output Result = 3
[P.S., 15 June 2015: This bug is also present in FTN95-7.20]
Last edited by mecej4 on Mon Jun 15, 2015 11:18 pm; edited 2 times in total |
|
Back to top |
|
|
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 7916 Location: Salford, UK
|
Posted: Thu Apr 30, 2015 8:15 am Post subject: |
|
|
Thanks for the feedback. I have logged this for investigation. |
|
Back to top |
|
|
IanLambley
Joined: 17 Dec 2006 Posts: 490 Location: Sunderland
|
Posted: Thu Apr 30, 2015 12:21 pm Post subject: |
|
|
I didn't know that arrays can be dimensioned with dummy arguments without passing them through the call statement as parameters.
Do L2V and L3V need to be dimensioned? |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1885
|
Posted: Thu Apr 30, 2015 1:18 pm Post subject: Re: |
|
|
IanLambley wrote: | I didn't know that arrays can be dimensioned with dummy arguments without passing them through the call statement as parameters. |
[revision]The "automatic" local arrays can be declared using scalar integer variables that are in the containing scope, or with dummy arguments.[/revision] This feature of the language has been with us since Fortran 90/95. Here is a quotation from the Fortran 95 Standard, Section 5.1.2.4.1:
Quote: | An automatic array is an explicit-shape array that is declared in a subprogram, is not a dummy argument, and has bounds that are nonconstant specification expressions.
If an explicit-shape array has bounds that are nonconstant specification expressions, the bounds, and hence shape, are determined at entry to the procedure by evaluating the bounds expressions. The bounds of such an array are unaffected by any redefinition or undefinition of the specification expression variables during execution of the procedure. |
IanLambley wrote: | Do L2V and L3V need to be dimensioned? | Yes, without declaring them as arrays one cannot use them in the array expressions and array assignments inside WHERE constructs. The test program cannot be compiled with a Fortran 77 compiler, even after converting to fixed format source.
Last edited by mecej4 on Thu Apr 30, 2015 1:59 pm; edited 2 times in total |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Thu Apr 30, 2015 1:28 pm Post subject: |
|
|
Ian,
There are a few different array types in this example.
L2v and L3v are automatic arrays, which have had problems in the past.
I am not sure of the name of the array "(/(j,j=1,n)/)", but FTN95 appears to have problems with this type also.
I tried to change this expression to the following, but it still crashed:
Code: | where (l3v) ! <<<=== access error
a11u = f(:n)
end where |
I use "where" even less often that FORALL or DO WHILE. I am sure that Eddie would agree with me and prefer to replace the WHERE construct with the combination of a DO loop and an IF (L3v(I)) ... , or with the following FORALL expressions:
forall ( j=1:n, L2v(j) ) L3v(j) = ae1u(j) >= a(2,a01u(j))
forall ( j=1:n, L3v(j) ) a11u(j) = j
What is your choice ?
Mecej4, I am not sure I agree with your containing scope reference, as I would have thought that the dummy argument "n" would override the n, associated with CONTAINS; although either source of defining the automatic array dimension would be suitable.
FTN95 is definitely struggling with this WHERE block; probably with "l3v = ae1u > a(2,a01u)"
John |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1885
|
Posted: Thu Apr 30, 2015 1:58 pm Post subject: Re: |
|
|
JohnCampbell wrote: | Ian,
Mecej4, I am not sure I agree with your containing scope reference, as I would have thought that the dummy argument "n" would override the n, associated with CONTAINS; although either source of defining the automatic array dimension would be suitable.
John |
Thanks, John, I see that I misstated the situation, and I have edited the post accordingly. Please see if the revised version is acceptable. |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Thu Apr 30, 2015 2:08 pm Post subject: |
|
|
Mecej4,
Thanks, but which "n" would you expect to be used for the automatic arrays ? ( I would have expected the dummy argument, but am not sure. )
The main point I was trying to make is that the WHERE construct is a very obscure definition, with even more hidden meaning than FORALL.
I would expect that the earlier use of "a(2,a01u)" would likely confuse FTN95, although at the end of this WHERE structure, it had the right answer for L3v; it just could not continue.
Wasn't FORALL and WHERE Fortran 90's start at parallel programming, although I suspect there wasn't much take-up of this syntax. It has taken 20 years for these WHERE bugs to be exposed !
John |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1885
|
Posted: Thu Apr 30, 2015 2:36 pm Post subject: Re: |
|
|
JohnCampbell wrote: | Mecej4,
Thanks, but which "n" would you expect to be used for the automatic arrays ? ( I would have expected the dummy argument, but am not sure. ) |
The dummy n should suppress the n from the containing program. In this example, the n from the main program is passed as an argument, so the value of n is the same whichever variable is used for the automatic array size.
Quote: |
Wasn't FORALL and WHERE Fortran 90's start at parallel programming, although I suspect there wasn't much take-up of this syntax. It has taken 20 years for these WHERE bugs to be exposed !
John | Until the last decade, I did not have a computer with a multicore CPU, and had little interest in parallelization. As of now, I think that there are many ways to do parallelization and it is not easy to select the one best suited for one's needs.
But WHERE does not require parallellization. It enables performing some work on a subset of an array based on a qualifying condition.
An F77->F90 converter produced the code with the WHEREs that malfunctioned. My role was to pare down the converted code to obtain a reasonably short compiler bug reproducer. |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Thu Apr 30, 2015 10:27 pm Post subject: |
|
|
If code is standard-compliant, then a compiler should compile it correctly, and that is completely separate from what I like or don't like. I don't think that I'll ever use a FORALL, let alone a WHERE, but I'd hesitate to advocate avoiding their use: if the constructs are useful to other folks then that's fine by me. What does bother me (slightly) is a proliferation of alternative ways of doing the same thing instead of doing something that can't be done with existing tools.
As far as like and dislike, I think that the ambiguity in the way n is passed is something I definitely don't like.
Eddie |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Fri May 01, 2015 12:25 am Post subject: |
|
|
mecej4,
I am interested that the WHERE code was produced by an F77 > F90 converter.
What I don't like about the approach is the needless complexity of what has resulted. The S generating code in ds7bqnv could be replaced by a single DO loop Code: | s = 0
do j = 1,n
k = f(j)
aj = w(k) + q(j)*r(j)/c(k)
if ( aj >= max (a(1,k),a(2,k)) ) s = s + j
end do
|
This removes the need for the temporary arrays and logical constructions. My personal view is that my change is easier to follow and would be easier to support.
I don't think the complexity associated with the WHERE mask helps at all.
F77 provided a language subset and Lahey produced a F90 subset. It is my view that much of the complexity that has been introduced into the Fortran standard has not significantly improved the function of the language or provided a more robust coding approach.
There has been much discussion of the science of computer languages, with an object oriented approach improving the way languages work. As a language user, I don't find the argument or the results at all convincing.
John |
|
Back to top |
|
|
John-Silver
Joined: 30 Jul 2013 Posts: 1520 Location: Aerospace Valley
|
Posted: Fri May 01, 2015 5:34 am Post subject: |
|
|
just out of interest, what was the original F77 code which was substituted by this WHERE construct ? |
|
Back to top |
|
|
mecej4
Joined: 31 Oct 2006 Posts: 1885
|
Posted: Fri May 01, 2015 1:05 pm Post subject: |
|
|
Eddie (see above) gives me safe refuge with his comment:
Quote: | If code is standard-compliant, then a compiler should compile it correctly, and that is completely separate from what I like or don't like. |
The sole purpose of this thread is to report an instance where the compiler does not work correctly.
That having been said, here is an indented and lower-cased version of the old Fortran source from which the WHERE constructs were generated.
Code: | do 30 j = 1, n
a0 = f(j)
a9 = u(j) / c(a0)
ae = w(a0) - a9
if (ae - a(1, a0)) 10, 5, 5
5 if (ae - a(2, a0)) 30, 30, 6
6 ac = (w(a0) - a(2, a0)) / a9
a1=j
go to 20
10 ac = (w(a0) - a(1, a0))/a9
a1 = -j
20 if(ab - ac) 30, 30, 7
7 ab = ac
30 continue
|
|
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Fri May 01, 2015 7:15 pm Post subject: |
|
|
I shall leave it to John to decide whether this code fragment is effectively the same as his translation of the WHERE business, but I suspect not.
Certainly, the report when FTN95 does not compile correctly is of use, but having opened this particular can of worms it can't be readily discarded.
IF John's simplification of the WHERE business is correct, AND IF it is not functionally the same as the original code, then he has found an equivalent bugginess in your Fortran 77 to Fortran 90 converter! Surely that is an important result too?
The new is not always better than the old, even if sometimes it is. There are cases when the new is never better than the old.
Eddie |
|
Back to top |
|
|
John-Silver
Joined: 30 Jul 2013 Posts: 1520 Location: Aerospace Valley
|
Posted: Fri May 01, 2015 9:00 pm Post subject: |
|
|
I wish I'd never asked to seethe F77 original it made my head hurt trying to associate the 2 !!!! Each as bad as the other imo.
What's the converter program used called btw ... I'd like to know so I can avoid it like the plague !!! LOL
More importantly .....
John C touched on the problem I think
Quote: | I am not sure of the name of the array "(/(j,j=1,n)/)", but FTN95 appears to have prob lems with this type also.
|
I did a bit of 'old fashioned' debugging to try to narrow down the cause from all the perfectly possiìble hypotheses above.
Try this:-
1. add a print * for l3v between the first WHERE block and 2nd
you'll see there is 1 TRUE present
2. Go back to first WHERE block and put l3v=.FALSE.
this sets ALL to FALSE - Program runs OK !!!!! (because it skips the 2nd WHERE ! every time)
3. Do same but setting all to .TRUE. - you'll see the program fails
4. Now go into 2nd WHERE and put: a11u=n , for example. PROGRAM runs (albeit of course with wrong answer) !!!!!
5. Go back to original and try just the mod in 4. - program runs.
q.e.d. John C's 'theorem'. (unless I'm wrong, which is a perfectly plausible possibility).
FORALL CASEs WHERE forum_members_bugs( : )=.PLAUSIBLE THEN IF he sees fit to do so ....
...... Over to Paul to discover why exactly !
see, you all knew there was a perfectly useful application for these new fandangled arty constructs :O)
What is that anyway the " a11u = (/(j,j=1,n)/) " is there a name for it ? |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Sat May 02, 2015 12:13 am Post subject: |
|
|
This is not F77 code, but 1960's IBM Fortran. It is also not the code that the WHERE structures were created from. My best tidy up is: Code: | do j = 1, n
k = f(j)
a9 = u(j) / c(k)
ae = w(k) - a9
if (ae < a(1,k)) THEN
a1 = -j
ab = min ( ab, (w(k) - a(1,k)) / a9 )
else if (ae > a(2,k)) THEN
a1 = j
ab = min ( ab, (w(k) - a(2,k)) / a9 )
end if
end do
|
The output from the DO is a1 (possibly s) and ab.
Actually, if you consider the challenge of introducing WHERE structures to a Fortran 66 code, it sounds like a very difficult assignment, so I would not be too critical of the converter.
The original part of this thread is FTN95 does not handle the WHERE code originally supplied, which was legal Fortran 95.
It is also interesting that it has taken 20 years for this bug to be identified.
My side issue is that I don't like WHERE code, as it is not clear what are arrays and what are variables, eg "l3v = ae1u > a(2,a01u)". I find a DO loop better documents the logic involved, although this is partly due to my limited Fortran vocabulary. |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|