forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Bad code generated for WHERE constructs
Goto page 1, 2  Next
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
mecej4



Joined: 31 Oct 2006
Posts: 1885

PostPosted: Thu Apr 30, 2015 4:45 am    Post subject: Bad code generated for WHERE constructs Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7916
Location: Salford, UK

PostPosted: Thu Apr 30, 2015 8:15 am    Post subject: Reply with quote

Thanks for the feedback. I have logged this for investigation.
Back to top
View user's profile Send private message AIM Address
IanLambley



Joined: 17 Dec 2006
Posts: 490
Location: Sunderland

PostPosted: Thu Apr 30, 2015 12:21 pm    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail
mecej4



Joined: 31 Oct 2006
Posts: 1885

PostPosted: Thu Apr 30, 2015 1:18 pm    Post subject: Re: Reply with quote

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
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Thu Apr 30, 2015 1:28 pm    Post subject: Reply with quote

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
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1885

PostPosted: Thu Apr 30, 2015 1:58 pm    Post subject: Re: Reply with quote

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
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Thu Apr 30, 2015 2:08 pm    Post subject: Reply with quote

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
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1885

PostPosted: Thu Apr 30, 2015 2:36 pm    Post subject: Re: Reply with quote

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
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Thu Apr 30, 2015 10:27 pm    Post subject: Reply with 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. 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
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Fri May 01, 2015 12:25 am    Post subject: Reply with quote

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
View user's profile Send private message
John-Silver



Joined: 30 Jul 2013
Posts: 1520
Location: Aerospace Valley

PostPosted: Fri May 01, 2015 5:34 am    Post subject: Reply with quote

just out of interest, what was the original F77 code which was substituted by this WHERE construct ?
Back to top
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1885

PostPosted: Fri May 01, 2015 1:05 pm    Post subject: Reply with quote

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
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2388
Location: Yateley, Hants, UK

PostPosted: Fri May 01, 2015 7:15 pm    Post subject: Reply with quote

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
View user's profile Send private message
John-Silver



Joined: 30 Jul 2013
Posts: 1520
Location: Aerospace Valley

PostPosted: Fri May 01, 2015 9:00 pm    Post subject: Reply with quote

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
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Sat May 02, 2015 12:13 am    Post subject: Reply with quote

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
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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