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 

Using Numerical Recipes with FTN95

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
jlb



Joined: 21 Oct 2020
Posts: 12

PostPosted: Mon Dec 21, 2020 2:30 pm    Post subject: Using Numerical Recipes with FTN95 Reply with quote

Some recipes (Numerical Recipes in Fortran 90: Volume 2, by W.H. Press et al.) use a subsidiary routine (xxx_private) for sharing / hiding data. The principle is given in the following example, without any original calculation for copyright reasons.
In its original version, the example fails at execution time with "access violation, the instruction at address xx attempted to write to an illegal location", after the value of j having been corrrectly displayed (j in mcof: 3).
Code:
PROGRAM xmin
  IMPLICIT NONE
  INTERFACE
    SUBROUTINE fg(i)
      IMPLICIT NONE
      INTEGER, INTENT(IN) :: i
    END SUBROUTINE fg
  END INTERFACE
  INTERFACE
    SUBROUTINE mmin(funcs,j)
      IMPLICIT NONE
      INTERFACE
        SUBROUTINE funcs(i)
          INTEGER, INTENT(IN) :: i
        END SUBROUTINE funcs
      END INTERFACE
      INTEGER :: j
    END SUBROUTINE mmin
  END INTERFACE
  CALL mmin(fg,3) 
END PROGRAM xmin

SUBROUTINE mmin(funcs,j)
  IMPLICIT NONE
  INTERFACE
    SUBROUTINE funcs(i)
      INTEGER, INTENT(IN) :: i
    END SUBROUTINE funcs
  END INTERFACE
  INTEGER :: j
  CALL mmin_private 
  CONTAINS
  SUBROUTINE mmin_private
    IMPLICIT NONE
    CALL mcof
  END SUBROUTINE mmin_private
  SUBROUTINE mcof
  IMPLICIT NONE
    WRITE(*,*) 'j in mcof: ', j
    CALL funcs(0)
  END SUBROUTINE mcof
END SUBROUTINE mmin

SUBROUTINE fg(i)
  IMPLICIT NONE
  INTEGER, INTENT(IN) :: i
  WRITE(*,*) 'fg: ',i+1
END SUBROUTINE fg

I made a modification at the subroutine mcof to correct this, see below, but I cannot figure out why this should be necessary.

Code:
  SUBROUTINE mmin_private
    IMPLICIT NONE
    CALL mcof(funcs)
  END SUBROUTINE mmin_private
  SUBROUTINE mcof(funcs)
    IMPLICIT NONE
    INTERFACE
      SUBROUTINE funcs(i)
        INTEGER, INTENT(IN) :: i
      END SUBROUTINE funcs
    END INTERFACE
    WRITE(*,*) 'j in mcof: ', j
    CALL funcs(0)
  END SUBROUTINE mcof

Compiler version: FTN95 8.70


Last edited by jlb on Mon Dec 21, 2020 5:16 pm; edited 2 times in total
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


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

PostPosted: Mon Dec 21, 2020 4:43 pm    Post subject: Reply with quote

jlb

This appears to be a fault in FTN95 and I have made a note of this.

The statement ordering is not correct at line 16 but that makes no difference to the outcome.
Back to top
View user's profile Send private message AIM Address
jlb



Joined: 21 Oct 2020
Posts: 12

PostPosted: Mon Dec 21, 2020 5:22 pm    Post subject: Reply with quote

Paul

Thanks for your attentive reviewing. I corrected this line in the source code above, sorry for the mistake, the interface for mmin doesn't seem to be required though.
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


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

PostPosted: Tue Feb 02, 2021 5:49 pm    Post subject: Reply with quote

I have carried out an initial investigation for this code and fixed a compilation error for 64 bit FTN95. I now have executables that fail at runtime for both 32 and 64 bit compilation. I get the same outcome with gFortran.

So the immediate question is, is this a bridge too far? If anyone has other compilers and is willing to run a test then please test with the following...
Code:
SUBROUTINE fg(i)
  WRITE(*,*) 'fg: ',i+1
END SUBROUTINE fg

SUBROUTINE mmin(fg,j)
  INTERFACE
    SUBROUTINE fg(i)
    END SUBROUTINE fg
  END INTERFACE
  j = 42
  CALL mmin_sub
CONTAINS
  SUBROUTINE mcof
    PRINT*, "Entered mcof."
    CALL fg(1) !Fails at runtime
  END SUBROUTINE mcof

  SUBROUTINE mmin_sub
    CALL mcof
  END SUBROUTINE mmin_sub
END SUBROUTINE mmin

PROGRAM xmin
  INTERFACE
    SUBROUTINE fg(i)
    END SUBROUTINE fg
  END INTERFACE
  INTERFACE
    SUBROUTINE mmin(funcs,j)
      INTERFACE
        SUBROUTINE funcs(i)
        END SUBROUTINE funcs
      END INTERFACE
    END SUBROUTINE mmin
  END INTERFACE
  CALL mmin(fg,3)
END PROGRAM xmin
Back to top
View user's profile Send private message AIM Address
mecej4



Joined: 31 Oct 2006
Posts: 1485

PostPosted: Tue Feb 02, 2021 6:21 pm    Post subject: Reply with quote

Consider the statement

CALL mmin(fg,3).

in the code posted by Paul.

The second argument, namely, the constant 3, corresponds to the dummy argument j of MMIN. Inside subroutine MMIN, an assignment is made to j. Thus, an attempt is made to write into a non-writeable argument.

Depending on the compiler, this is very likely to cause an access violation.

The code posted by JLB, however, causes FTN95 to generate bad code (32-bit, stops on access violation) or fail to compile (64-bit, AMD backend failure). This code runs normally when compiled with other compilers.
Back to top
View user's profile Send private message
mecej4



Joined: 31 Oct 2006
Posts: 1485

PostPosted: Tue Feb 02, 2021 6:43 pm    Post subject: Reply with quote

All those interfaces and indirections (misdirections, perhaps?) in the code attributed to Numerical Recipes make me dizzy. Rewritten in F77, the code is, essentially, the same as

Code:
      PROGRAM xmin
        IMPLICIT NONE
        external fg
        CALL mmin(fg,3)
      END PROGRAM xmin

      SUBROUTINE mmin(funcs,j)
        IMPLICIT NONE
        INTEGER :: j
        external funcs
        CALL funcs(0)
      END SUBROUTINE mmin

      SUBROUTINE fg(i)
        IMPLICIT NONE
        INTEGER, INTENT(IN) :: i
        WRITE(*,*) 'fg: ',i+1
      END SUBROUTINE fg
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


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

PostPosted: Wed Feb 03, 2021 10:34 am    Post subject: Reply with quote

mecej4

Thanks for the information. That's very useful.
Back to top
View user's profile Send private message AIM Address
jlb



Joined: 21 Oct 2020
Posts: 12

PostPosted: Wed Feb 03, 2021 12:44 pm    Post subject: Reply with quote

Some complemental informations. First for the anecdote, William H. Press et al. have also published "Numerical Recipes in Fortran 77". When stripping the calculations from the code, the remaining structure corresponds to the code proposed above by mecej4, with two minimal differences: no use of IMPLICIT NONE and no EXTERNAL declaration of funcs in subroutine mmin, as in the following.
Code:
      PROGRAM xmin
C        IMPLICIT NONE
        external fg
        CALL mmin(fg,3)
      END PROGRAM xmin

      SUBROUTINE mmin(funcs,j)
C        IMPLICIT NONE
        INTEGER :: j
C        external funcs
        CALL funcs(0)
      END SUBROUTINE mmin

      SUBROUTINE fg(i)
C       IMPLICIT NONE
        INTEGER, INTENT(IN) :: i
        WRITE(*,*) 'fg: ',i+1
      END SUBROUTINE fg

The full Fortran 77 code of the considered "numerical recipe" compiles also with FTN95 and runs as expected.

The use of a subsidiary routine (xxx_private) for sharing / hiding data in the Fortran 90 version, which leads to those interfaces and indirections that can make ones dizzy, is described by the authors under of Numerical Recipes in Fortran 90: Volume 2 under "21.5 Advanced Fortran 90 Topics - Scope, Visibility and Data Hiding" as their way of dealing with sharing or hiding variables and procedures, see http://numerical.recipes/F210

For the anecdote again, William H. Press et al. state in the preface to the second edition of their Numerical Recipes
Quote:
"It is a sobering fact that our standard test suite (exercising all the routines in this book) has uncovered compiler bugs in a large majority of the compilers tried."


Last edited by jlb on Thu Feb 04, 2021 9:59 am; edited 1 time in total
Back to top
View user's profile Send private message
LitusSaxonicum



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

PostPosted: Wed Feb 03, 2021 6:21 pm    Post subject: Reply with quote

The obfuscation of code for various reasons is better known to some programmers than to others. In my case, I prefer things to be straightforward so that I can understand what I did when I return to it after a gap of months, years or even decades. It's a matter of taste and priorities, I suppose.

In the case illustrated, even Mecej4 cannot make head nor tail of it, and I'm not even going to try. I do wonder if the eponymous William H. Press et al. still understand it?

However, Leo Colston's view* that while the past is a foreign country where they do things differently applies to the difference between Fortrans 77 and 90 et seq., it has reinforced my own view that in some respect they do things rather better there.

Eddie

* Or L. P. Hartley's, if you prefer.
Back to top
View user's profile Send private message
jlb



Joined: 21 Oct 2020
Posts: 12

PostPosted: Wed Feb 03, 2021 6:58 pm    Post subject: Reply with quote

Regardless of the beauty of the code or the meaningfulness of doing so like the authors of the Numerical Recipes, the sample of principle runs normally - according to mecej4 - when compiled with other compilers, with FTN95 not.
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


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

PostPosted: Mon Apr 12, 2021 7:24 am    Post subject: Reply with quote

This failure has now been fixed for the next release of FTN95.
Back to top
View user's profile Send private message AIM Address
jlb



Joined: 21 Oct 2020
Posts: 12

PostPosted: Mon Apr 12, 2021 12:34 pm    Post subject: Reply with quote

Paul

Thanks a lot for the investigation and the fixing of this weird and quite particular issue.
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
Page 1 of 1

 
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