Silverfrost Forums

Welcome to our forums

Data passing between a REAL array and an INTEGER array

26 Jun 2011 2:44 #8462

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.

26 Jun 2011 8:34 #8463

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:

      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.

      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
26 Jun 2011 10:11 #8464

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.

26 Jun 2011 1:29 #8465

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 INTEGER4 and REAL8 then it may have addressed the problem that real8 is 8 bytes and integer4 is 4 bytes. An example code that could be used is

    integer4, parameter :: million = 1000000 integer4, parameter :: R8_size = 50million integer4, parameter :: I4_size = R8_size2 ! COMMON /Big_Mem/ AA_mem ! integer4 IA_mem(I4_size) real8 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_array2-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 integer4 and real8 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 real4. There are few areas of FEA calculations where real4 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

28 Jun 2011 3:26 #8468

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?

28 Jun 2011 4:16 #8469

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

28 Jun 2011 5:26 #8470

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.

29 Jun 2011 6:50 #8481

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

    //      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
30 Jun 2011 2:05 #8484

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

30 Jun 2011 7:54 #8485

/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.

4 Jul 2011 9:04 #8504

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

4 Jul 2011 12:45 #8505

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.

Please login to reply.