Must I use '.d0' when attributing values to variable even if I use REAL(8) to declare it in Fortran? - variables

I'm relatively new using the Fortran language and I'm dealing with a pre-written program that I have to make some changes, and I have all 8 bytes variables declared as REAL(8) on the program's statement area. However, when attributing numerical values to the variables and/or arrays, the original program's author always uses something like:
...
REAL(8) A
A = 1.d0
...
Is that strict necessary given that 'A' is declared not as DOUBLE PRECISION, but literally as REAL(8), even thought -- I think -- both have the same KIND?
Furthermore, I have read somewhere that the use of REAL(8) should be abandoned? Is that so? Why?
As far as I know (and I certainly can be wrong), the number of bytes used in a DOUBLE PRECISION variable is dependent of the compiler, making it dangerous (I assume) or at least undesirable its use in place of REAL(8), if my intention is to declare an 8 bytes variable.
(I am working with Fortran 90/95)
I would gratefully receive comments to clarify this issue! Thanks a lot!

Related

Resizing matrix using pointer attribute

I have a Fortran program which uses a routine in a module to resize a matrix like:
module resizemod
contains
subroutine ResizeMatrix(A,newSize,lindx)
integer,dimension(:,:),intent(inout),pointer :: A
integer,intent(in) :: newSize(2)
integer,dimension(:,:),allocatable :: B
integer,optional,intent(in) :: lindx(2)
integer :: i,j
allocate(B(lbound(A,1):ubound(A,1),lbound(A,2):ubound(A,2)))
forall (i=lbound(A,1):ubound(A,1),j=lbound(A,2):ubound(A,2))
B(i,j)=A(i,j)
end forall
if (associated(A)) deallocate(A)
if (present(lindx)) then
allocate(A(lindx(1):lindx(1)+newSize(1)-1,lindx(2):lindx(2)+newSize(2)-1))
else
allocate(A(newSize(1),newSize(2)))
end if
do i=lbound(B,1),ubound(B,1)
do j=lbound(B,2), ubound(B,2)
A(i,j)=B(i,j)
end do
end do
deallocate(B)
end subroutine ResizeMatrix
end module resizemod
The main program looks like:
program resize
use :: resizemod
implicit none
integer,pointer :: mtest(:,:)
allocate(mtest(0:1,3))
mtest(0,:)=[1,2,3]
mtest(1,:)=[1,4,5]
call ResizeMatrix(mtest,[3,3],lindx=[0,1])
mtest(2,:)=0
print *,mtest(0,:)
print *,mtest(1,:)
print *,mtest(2,:)
end program resize
I use ifort 14.0 to compile the codes. The issue that I am facing is that sometimes I don't get the desired result:
1 0 0
1 0 5
0 0 -677609912
Actually I couldn't reproduce the issue (which is present in my original program) using the minimal test codes. But the point that I noticed was that when I remove the compiler option -fast, this problem disappears.
Then my question would be
If the pieces of code that I use are completely legal?
If any other method for resizing the matrices would be recommended which is better than the one presented in here?
The relevance of the described issue and the compiler option "-fast".
If I've read the code right it's legal but incorrect. In your example you've resized a 2x3 array into 3x3 but the routine ResizeMatrix doesn't do anything to set the values of the extra elements. The strange values you see, such as -677609912, are the interpretation, as integers. of whatever bits were lying around in memory when the memory location corresponding to the unset array element was read (so that it's value could be written out).
The relevance of -fast is that it is common for compilers in debug or low-optimisation modes, to zero-out memory locations but not to bother when higher optimisation is switched on. The program is legal in the sense that it contains no compiler-determinable syntax errors. But it is incorrect in the sense that reading a variable whose value has not been initialised or assigned is not something you regularly ought to do; doing so makes your program, essentially, non-deterministic.
As for your question 2, it raises the possibility that you are not familiar with the intrinsic functions reshape or (F2003) move_alloc. The latter is almost certainly what you want, the former may help too.
As an aside: these days I rarely use pointer on arrays, allocatable is much more useful and generally easier and safer too. But you may have requirements of which I wot not.

gfortran optimisation of overflowing integers

I have "inherited" a simple congruential pseudo-random-number generator that looks like this:
subroutine ribm(rndm,ial)
implicit none
integer :: ial
real :: rndm, al
ial=ial*65539
if(ial.lt.0) then
ial=ial+2147483647+1
endif
al=ial
rndm=al*0.4656613e-9
end subroutine ribm
The ial variable contains the RNG seed and it is initialised once outside the generator. The generator is supposed to produce pseudo-random numbers between 0 and 1, as usual. Therefore, ial must always stay non-negative. The code tries to enforce this condition using the if statement.
I test the generator using the following program:
program testribm
implicit none
real :: r
integer :: i
data i /12345/
call ribm(r,i)
call ribm(r,i)
call ribm(r,i)
call ribm(r,i)
call ribm(r,i)
call ribm(r,i)
print *,r,i
contains
subroutine ribm(rndm,ial)
! [...]
end subroutine ribm
end program testribm
If I compile with gfortran v4.8.2 with optimisation -O1 or lower, I get:
0.580895185 1247462939
OTOH, if I use -O2 I get:
-0.709615409 -1523887535
Note the negative seed value. Optimisation affects the integer arithmetics and the final result of the repeated calls to ribm.
I know how to work around/fix this problem. My question is: is this a gfortran bug? Or is this behaviour due to the fact that the code is non-standard? But if this is the case, shouldn't gfortran produce some warning message?
Optimization can change the actual calculations done. Don't be surprised if the results change for a non-standard calculation, such as one that involves integer overflow. My suggestion to implement algorithms in Fortran that use unsigned integers is to use the next-larger integer type. e.g., if the algorithm should be done with unsigned 32-bit integers, use Fortran's signed 64-bit integer.
I would add to M.S.B.'s answer, that the problem occurs only when the compiler optimizes several calls to ribm in one go. (My previous suggestion was invalid.)
But the answer to the original question. I don't think it's a compiler bug. 2147483647+1 is simply out of range. The question is why there is no warning even with -pedantic -Wall -Wextra. It turns out, pointed out by #Arek' Fu that one needs -Wstrict-overflow, whis is included only as -Wstrict-overflow=1 in -Wall.
Where possible, I recommend using functions iand, ior, ieor, ishft and similar for portable results, instead of arithmetic.
both answers are nice, as for a solution, I would think using parenthesis is the right way to go to prevent the compiler optimizing away?
subroutine ribm(rndm,ial)
implicit none
integer :: ial
real :: rndm, al
ial=ial*65539
if(ial.lt.0) then
ial=(ial+1)+2147483647
endif
al=ial
rndm=al*0.4656613e-9
end subroutine ribm

Does fortran 90 (gfortran) optimise array syntax?

I have done a lot of work with array-based interpreted languages, but I'm having a look at Fortran. What has just occurred to me after writing my first bit of code is the question of whether or not gfortran will optimise an expression using array syntax by placing the expression in a single loop. In most array-based interpreters an expression such as A=B/n*2*pi (where B is an array) would require 5 loops and multiple array temporaries to evaluate. Is gfortran clever enough to optimise this out, and will my code below (the line that calculates the array from 0 to 2pi) be as efficient as an explicit do loop around the expression? Is there anything I should look out for when using array syntax if I'm worried about performance?
PROGRAM Sine
IMPLICIT NONE
REAL, PARAMETER :: PI = 3.415926535
INTEGER, PARAMETER :: z = 500
INTEGER :: ier
INTEGER, EXTERNAL :: PGBEG
REAL, DIMENSION(z) :: x,y
x=(indgen(z)-1.0)/z*(2*pi) ! This line...``
y=sin(x)
CALL plot(y,x)
CONTAINS
FUNCTION indgen(n) result(i)
INTEGER :: n
INTEGER, DIMENSION(n) :: i
INTEGER :: l
DO l=1,n
i(l)=l
END DO
END FUNCTION indgen
SUBROUTINE plot(y,x)
REAL, DIMENSION(:) :: x,y
ier=PGBEG(0,'/XWINDOW',1,1)
CALL PGENV(0.0,7.0,-1.0,1.0,0,1)
CALL PGLINE(SIZE(x),x,y)
CALL PGEND()
END SUBROUTINE plot
END PROGRAM Sine
In gfortran you can use the -Warray-temporaries flag to see all array temporaries generated. When I try your example no extra array temporary is generated (other than the one necessary to store the results of indgen(z)), so I guess gfortran is clever enough.
The expression z*(2*pi) is a compile-time constant, which the compiler can easily verify, so that should not be evaluated at run time regardless. Additionally, virtually all modern compilers should perform one-line "elemental" array operations within a single loop, and in many cases SIMD instructions will be generated (auto-vectorization).
Whether a temporary is generated usually depends on whether or not each element can be handled independently, and whether or not the compiler can prove this. Xiaolei Zhu's suggestion of using -Warray-temporaries is a good one. Don't mix this up wih -fcheck=array-temps, which I think only applies to temporaries generated for function calls.
Here's an example of such a message from gfortran:
foo.F90:4.12:
foo(1:20) = 2*foo(20:1:-1)
1
Warning: Creating array temporary at (1)
Your function call will be done in a separate loop, unless the compiler can inline it. Whether or not the compiler inlines a short function can be pretty unpredictable; it potentially depends on where that other function is defined, whether or not the function has the pure attribute (although in practice this rarely seems to matter), the vendor and version of the compiler itself, and the options you pass. Some compilers can generate a report for this; as I recall, the Intel compiler has a decent one.
Edit: It's also possible to inline the expression in this line pretty easily by hand, using an "implied do loop":
x = [ ( real(i)/z*(2*pi), i = 0, z-1) ]
Yes.
Fortran is compiled rather than interpreted.
It handles loops very well.

Do integers, whose size is not a power of two, make sense?

This is an 8 bit architecture, with a word size of 16 bits. I now need to use a 48-bit integer variable. My understanding is that libm implements 8, 16, 32, 64 bit operations (addition, multiplication, signed and unsigned).
So in order to make calculations, I must store the value in a 64-bit signed or unsigned integer. Correct?
If so, what is there to prevent general routines from being used? For example, for addition:
start with the LSB of both variables
add them up
if more bytes are available continue, otherways goto ready
shift both variables 1 byte to the right
goto 1)
libm implements the routines for the standard sizes of types, and the compiler chooses the right one to use for expression.
If you want to implement your own types, you can. If you want to use the usual operators, then you have to get into the compilation process to get the compiler to choose yours.
You could implement the operations as functions, say add(int48_t, int48_t), but then the compiler won't be able to do optimizations like constant folding, etc.
So, there is nothing stopping you from implementing your own custom compiler, but is it really necessary? Do you really need to save that space? If so, then go for it!
That is correct, saving a couple of bits is (in almost all cases) not worth the trouble of implementing your own logic.

What is _Complex?

Reading Objective-C type encodings documentation (GCC's and Apple's pages somewhat complement each other), I stumbled upon the _Complex keyword. I've never heard about it, and when I tried to look it up, I found tons of results talking about erroneous uses of it, but never what it really did.
What is _Complex, and how does it work?
A complex number type which looks like it uses half the bit-width for the real part and half for the imaginary part:
_Complex double x; declares x as a variable whose real part and imaginary
part are both of type double.
_Complex short int y; declares y to
have real and imaginary parts of type
short int; this is not likely to be
useful, but it shows that the set of
complex types is complete.
Posts about "EXC_BAD_ACCESS _Complex double return"
http://hintsforums.macworld.com/showthread.php?t=92768
http://developer.apple.com/library/mac/#documentation/DeveloperTools/gcc-4.0.1/gcc/Complex.html
Complex numbers.