replica nfl jerseysreplica nfl jerseyssoccer jerseyreplica nfl jerseys forums.silverfrost.com :: View topic - Data passing between a REAL array and an INTEGER array
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 

Data passing between a REAL array and an INTEGER array

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



Joined: 13 Jun 2011
Posts: 3

PostPosted: Sun Jun 26, 2011 3:44 am    Post subject: Data passing between a REAL array and an INTEGER array Reply with quote

Dear Sir or Madam,

In FEA program, a lot of REAL and INTEGER variables are often stored in a 1-D REAL array, say in an array called A(K) for data passing. The part of the integer numbers stored in A must be passed around in the FEA program in different places to some INTEGER arrays (1-D or 2-D), say ML(M,N), by calling some specific subroutines.

FORTRAN 77 allows this kind of data exchange between a REAL array and an INTEGER array. I guess FORTRAN 95 also allows it. But when using FTN95 to compile the progam, link problems always come up with error message like this:

"SUBROUTINE 'XXXX' called with argument no 3 as a REAL(KIND=1) when a INTEGER(KIND=3) was expected (from SUBROUTINE 'YYYY')"

Does it mean that the arguments for data passing have different lengths?

Thanks in advance.
Back to top
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Sun Jun 26, 2011 9:34 am    Post subject: Reply with quote

It is illegal Fortran (Fortran 77 and Fortran 95) to call a subroutine with a REAL actual argument when an INTEGER dummy argument is expected.
(If you are compiling separate files, this is picked up by the Linker. If you put the routines in one file, the compiler should give an error.)


You can't do the following, for example:

Code:

      subroutine driver()
      real a
      a = 12.0  ! Integer stored as real
      call foo(a)
      end

      subroutine foo(n)
      integer n
      print *,n
      end



You would have to do something like the following.

Code:

      subroutine driver()
      integer a
      real a
      a = 12.0  ! Integer stored as real

      ! Note, you can replace the three lines with call foo(nint(a)) if you know a is not modified by foo (as is the case here).
      ia = nint(a) ! convert to nearest integer
      call foo(ia)
      a = real(ia) ! convert to real

      end

      subroutine foo(n)
      integer n
      print *,n
      end
Back to top
View user's profile Send private message
Sebastian



Joined: 20 Feb 2008
Posts: 177

PostPosted: Sun Jun 26, 2011 11:11 am    Post subject: Reply with quote

Quote:
ia = nint(a) ! convert to nearest integeria = nint(a) ! convert to nearest integer

Please note that this may change the bit encoding, so it's most likely not what "people with an A-field" who use real-fields just as intermediate storage would expect.
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2615
Location: Sydney

PostPosted: Sun Jun 26, 2011 2:29 pm    Post subject: Reply with quote

The method of memory management you describe predates ALLOCATE, which was introduced in Fortran 90.
There are many programs, including my FEA program which still use these methods successfully. Many public domain programs were developed in 70's and 80's using this approach and they are still in use today.
There are many tricks that can be used to overcome the problem you have found.
1) The easiest is to not use /check when you compile and the problem will go away.
2) You could try to convert the memory management to using ALLOCATE, although ALLOCATE does not easily support resizeing arrays, such as when you allocate a "big" array then resize it after you know how big it needs to be. There are many things that ALLOCATE is good at but this in not one of them. Any change involving ALLOCATE involves significant re-programming.
3) Involving even more re-programming is using a MODULE of all key arrays and making these arrays ALLOCATABLE. This is the neatest approach.
4) If you want to keep using /CHECK and minimise your changes, you can use two arrays and equivalence them. The problem you need to check is when the program was written. If it uses INTEGER*4 and REAL*8 then it may have addressed the problem that real*8 is 8 bytes and integer*4 is 4 bytes. An example code that could be used is
Code:
integer*4, parameter :: million = 1000000
integer*4, parameter :: R8_size = 50*million
integer*4, parameter :: I4_size = R8_size*2
!
COMMON /Big_Mem/ AA_mem
!
integer*4 IA_mem(I4_size)
real*8    AA_mem(r8_size)
equivalence (IA_mem, AA_mem)
!
! note as you allocate address pointers to AA_mem, say p_array
! the same address pointer for IA_mem is ip_array = P_array*2-1
!


This code is typically in an include file.
You can not use it in a module, as EQUIVALENCE is not allowed in a module.

You can then substitute all calls referencing AA for integers as IA with an appropriate calculation of the array pointer. I've written my own "MALLOC" routine to manage all the P_ARRAY pointer calculations.

You will find that ALLOCATE can be easier for new code, unless you need to resize a large array.

Be warned, programs that were developed in 70's for Cyber computers, had the same length INTEGER and REAL (60 bits). These do not recognise the different byte size of say IA(100) and AA(100). Converting to integer*4 and real*8 requires careful checking. Sometimes the same address was given as multiple arguments and the array shared both integer and real values. I still use this approach for reading nodes, which share real coordinates and integer fixity info.

You also indicate that you use real (kind=1), which is real*4. There are few areas of FEA calculations where real*4 is sufficiently accurate. These typically have to be converted to real*8 to obtain the necessary precision, which applied to all public domain programs developed on cyber machines. Generic intrinsics, introduced in Fortran 90 made this a lot easier.

It may not be legal Fortran, but it is widely used, especially in FEA programs.

John
Back to top
View user's profile Send private message
jayxwang



Joined: 13 Jun 2011
Posts: 3

PostPosted: Tue Jun 28, 2011 4:26 am    Post subject: Data passing Reply with quote

Many Thanks to davidb, Sebastian and John. Special thanks for John for his sigificant amount of time and attention and great solutions to the problem.

John: Visual FTN95 is brand new for me. Where can I turn off "/check", please?
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2615
Location: Sydney

PostPosted: Tue Jun 28, 2011 5:16 am    Post subject: Reply with quote

I don't use Visual Studio, so don't know if Check, Debug or Production are 3 compilation modes available to be selected. I think they are somewhere. (someone else may be able to help)

The basic problem you are identifying is that it would be good to have a modified /check available for the other parts of the code, except for:
1) argument type checking is ignored,
2) upper bound checking of arrays is ignored only for arrays dimensioned (*) or (1), but lower bound checking is maintained (subscript < 1)

I did get that change in some compilers in 80's but in general most compiler developers are reluctant to consider this programming method.

It's a shame, as I think there is still a significant number of programs which use this memory approach and ALLOCATE does not easily cope. The main area is when reading data where you do not know the number of active elements. You first allocate a large array, then once read, the array can be re-sized smaller and the balance of memory returned to the memory pool. It is possible to do this legally with ALLOCATED arrays by allocating a temporary array, copying then re-allocating the original array, but it is difficult if the start of the main array is an argument to the working routine.

Another for the wish list !

John
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


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

PostPosted: Tue Jun 28, 2011 6:26 am    Post subject: Reply with quote

When using either Visual Studio or Plato you can configure the compiler for /check etc from the main toolbar. At the same time you can select between .NET and Win32.

Alternatively, from the FTN95 command line you can use /check etc.

/check has various components that can be selectively switched off by using /inhibit_check <integer> on the command line but the details are not documented so it is a case of trial and error to see which <integer> is needed. However, in your case it looks like you need /inhibit_check 5

/check can be applied (or not) on a file by file basis or even for different routines by using the OPTIONS directive in the code. You might be able to apply /inhibit_check 5 gloabally by configuring the compiler via /config.
Back to top
View user's profile Send private message AIM Address
PaulLaidler
Site Admin


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

PostPosted: Wed Jun 29, 2011 7:50 am    Post subject: Reply with quote

I do not have time right now to provide documentation for /inhibit_check but here is the information that I have...

Code:
    //      1 - suppress marking DO-loop indices as unwritable in a function call
    //      2 -     "       "    INTENT(IN) args  "       "      "      "
    //      3 - suppress POINTER checking via PCHECK (although PALLOCATE and PFREE are still used)
    //      4 -   "         "       "     completely (i.e. PALLOCATE and PFREE will not be called)
    //      5 - suppress the argument type/size checking on function entry
    //      6 - suppress the extra information added to a CHECK mode function call
    //      7 - suppress CHARACTER length checks on procedure entry
    //      8 - suppress UNDEF check with WRITE/PRINT statements
    //      9 - suppress FULL_UNDEF check with CHARACTER WRITE/PRINT statements
    //     10 - suppress checking of overwriting of DO-loop index using "(Writability of ...)"
    //     11 - suppress checking of overwriting of DO-loop index after SUBROUTINE call using "(Value of ...)"
    //     12 - suppress checking of overwriting of DO-loop index after FUNCTION call using "(Value of ...)"
    //     13 - suppress checking of overwriting of EQUIVALENCEd/COMMON DO-loop index after assignment using "(Value of ...)"
    //     14 - suppress making INTENT(OUT) variables undefined on subprogram entry
Back to top
View user's profile Send private message AIM Address
JohnCampbell



Joined: 16 Feb 2006
Posts: 2615
Location: Sydney

PostPosted: Thu Jun 30, 2011 3:05 am    Post subject: Reply with quote

Paul,

Thanks very much for the list.

Option 5 - suppress the argument type/size checking on function entry
For me, this is a key aspect of looking for program errors. I would like to suggest that this could be improved a lot.

I don't know how many others experience the programming errors I do, but I find that "Type" and "size" checks are very different aspects.
I'd like an option to exclude type but keep size checks. This would allow /check to be used in a lot of cases and cope with pre-90 programming techniques, where type mixing was often used. My variable length record disk random I/O library is a good example of where this can be applied, where I am transferring a memory record address and byte length.

The most common size error I have encountered is having a subscript = 0; which typically occurs if it is not defined or references data that is not provided.
It would be good to have a size check option for subroutine argument arrays dimensioned as either:
INTEGER AA(*), BB(1)
When applying size check to these arrays, the lower bound check is included (index < 1) but no upper bound check is applied.

This may already be the case?

Does the /BOUND_CHECK option still work or has it's functionality been replaced by /CHECK? I recall a post that some of these compiler checking options are no longer supported.

John
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


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

PostPosted: Thu Jun 30, 2011 8:54 am    Post subject: Reply with quote

/bounds_check is still implemented and, according to the documentation, it checks array subscripts only. It is included in /check.

I can add your request to the wish list but it would probably be quite tricky to implement.
Back to top
View user's profile Send private message AIM Address
JohnCampbell



Joined: 16 Feb 2006
Posts: 2615
Location: Sydney

PostPosted: Mon Jul 04, 2011 10:04 am    Post subject: Reply with quote

Paul,

I'm pleased to hear than /BOUNDS_CHECK is still implemented. It may be only in my memory that it isn't !

I described a bit of functionality in my last post. Could you clarify what checks are done with /bound_check for array declarations of the type "INTEGER AA(*), BB(1) ". Having a lower bound check available would be good, as I find undefined subscripts can be the most common problem.
Is this the case ?

John
Back to top
View user's profile Send private message
PaulLaidler
Site Admin


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

PostPosted: Mon Jul 04, 2011 1:45 pm    Post subject: Reply with quote

The easiest way to get this information is by trial and error.
If you find anything useful then let me know and I will add it to the documentation.
Back to top
View user's profile Send private message AIM Address
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