- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I realize there was an issue with multiplying two integer(4) quantites, but this is an entirely different
"can of worms." See source code.
! Apparently the compiler does not know how to work with some literal expressions
! larger than 31 bits. It computes the wrong values for MASK, MAXREP, etc.
! As long as I keep the power of 2 < 31, it computes the correct expression values.
! I didn't see anything in the writeups about this limitation.
! The compiler does not give any warning messages.
PROGRAM TEST_DoLoop
implicit NONE
integer(2) ipwr,iadd
integer(8) nrep,maxrep,mask,wrong1,wrong2
! mask=2**32 + 2**16 + 2**5 + 1 ! DOES NOT WORK
mask=2**16 ! the workaround
mask=mask*mask + 2**16 + 2**5 + 1 ! the workaround
print *,"mask=",mask
! if I set ipwr to 31 and addon to -1
! it executes the proper number of reps.
! If addon = 0 or higher, the # of reps is ZERO.
print *,"power of 2, addon:"
read *,ipwr,iadd
maxrep=2**ipwr+iadd ! gives wrong results for ipwr > 31
! to get around this problem, I have to resort to something like thei
maxrep=2**(ipwr/2)
maxrep=maxrep**2 + iadd
! is there anything in the compiler setup parameters that might address this issue?
! this seems pretty straightforward - - - -
do nrep=1,maxrep
enddo
print *,"nrep=",nrep
wrong1=5**30 ! gives wrong results
wrong2=7**27 ! Same here
! Could it be the ** operator?
print *,"wrong1=",wrong1
print *,"wrong2=",wrong2
pause "exiting"
end program
Suggestion: Give a REWARD for finding these problems (if not detected already).
"can of worms." See source code.
! Apparently the compiler does not know how to work with some literal expressions
! larger than 31 bits. It computes the wrong values for MASK, MAXREP, etc.
! As long as I keep the power of 2 < 31, it computes the correct expression values.
! I didn't see anything in the writeups about this limitation.
! The compiler does not give any warning messages.
PROGRAM TEST_DoLoop
implicit NONE
integer(2) ipwr,iadd
integer(8) nrep,maxrep,mask,wrong1,wrong2
! mask=2**32 + 2**16 + 2**5 + 1 ! DOES NOT WORK
mask=2**16 ! the workaround
mask=mask*mask + 2**16 + 2**5 + 1 ! the workaround
print *,"mask=",mask
! if I set ipwr to 31 and addon to -1
! it executes the proper number of reps.
! If addon = 0 or higher, the # of reps is ZERO.
print *,"power of 2, addon:"
read *,ipwr,iadd
maxrep=2**ipwr+iadd ! gives wrong results for ipwr > 31
! to get around this problem, I have to resort to something like thei
maxrep=2**(ipwr/2)
maxrep=maxrep**2 + iadd
! is there anything in the compiler setup parameters that might address this issue?
! this seems pretty straightforward - - - -
do nrep=1,maxrep
enddo
print *,"nrep=",nrep
wrong1=5**30 ! gives wrong results
wrong2=7**27 ! Same here
! Could it be the ** operator?
print *,"wrong1=",wrong1
print *,"wrong2=",wrong2
pause "exiting"
end program
Suggestion: Give a REWARD for finding these problems (if not detected already).
Link Copied
6 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Bill,
You will find a "writeup" of this issue, and others you have reported, in a Fortran 90/95/2003 textbook. You share a common misunderstanding of how Fortran determines the type and kind of an expression.
In the case of:
mask=2**32 + 2**16 + 2**5 + 1
everything on the right side of ther assignment is "default integer" or integer(4). It does not matter that the variable being assigned to is integer(8) - that is not taken into consideration. Since all elements of the expression are integer(4), the whole expression is integer(4). It would be nice if the compiler warned you of integer overflow, but it doesn't.
One solution is to use kind specifiers, as I recommended in an earlier thread. For example:
mask=2_8**32 + 2_8**16 + 2_8**5 + 1_8
Your workaround works because mask, an integer(8) entity, is in the expression so the other operand gets converted to integer(8) before the addition. This can still be risky, though, if other elements are still integer(4).
Read up on mixed-mode arithmetic and take care to use kind specifiers consistently when you are using non-default kinds.
You will find a "writeup" of this issue, and others you have reported, in a Fortran 90/95/2003 textbook. You share a common misunderstanding of how Fortran determines the type and kind of an expression.
In the case of:
mask=2**32 + 2**16 + 2**5 + 1
everything on the right side of ther assignment is "default integer" or integer(4). It does not matter that the variable being assigned to is integer(8) - that is not taken into consideration. Since all elements of the expression are integer(4), the whole expression is integer(4). It would be nice if the compiler warned you of integer overflow, but it doesn't.
One solution is to use kind specifiers, as I recommended in an earlier thread. For example:
mask=2_8**32 + 2_8**16 + 2_8**5 + 1_8
Your workaround works because mask, an integer(8) entity, is in the expression so the other operand gets converted to integer(8) before the addition. This can still be risky, though, if other elements are still integer(4).
Read up on mixed-mode arithmetic and take care to use kind specifiers consistently when you are using non-default kinds.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Still, wouldn't it be nice if we could at least get a warning, namely
that integer(4) computations are being used for an integer(8) result?
The book I have doesn't discuss this issue in much of any useful detail.
Perhaps you can recommend a better text (?) if that isn't against Intel's
policy.
Even if the computations ARE integer(4), why wouldn't the compiler flag
a quantity like 5**30, since it's pretty obvious that won't fit into a 32
bit word?
Or if you multiply two literals together, i.e. 14289473*34582930, the compiler should KNOW that
the result would be too big.
Seems pretty obvious to me anyway . . . .
that integer(4) computations are being used for an integer(8) result?
The book I have doesn't discuss this issue in much of any useful detail.
Perhaps you can recommend a better text (?) if that isn't against Intel's
policy.
Even if the computations ARE integer(4), why wouldn't the compiler flag
a quantity like 5**30, since it's pretty obvious that won't fit into a 32
bit word?
Or if you multiply two literals together, i.e. 14289473*34582930, the compiler should KNOW that
the result would be too big.
Seems pretty obvious to me anyway . . . .
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A warning would not be appropriate for the assignment as that's perfectly legal Fortran.
There are several books listed in our documentation under "Related Information", as follows:
I agree that the compiler should warn when a compile-time expression overflows. I will ask the developers about that.
There are several books listed in our documentation under "Related Information", as follows:
-
Introduction to Programming with Fortran with coverage of Fortran 90, 95, 2003 and 77, by I.D. Chivers and J. Sleightholme; published by Springer, ISBN 9781846280535
-
The Fortran 2003 Handbook: The Complete Syntax, Features and Procedures, by Adams, J.C., Brainerd, W.S., Hendrickson, R.A., Maine, R.E., Martin, J.T., Smith, B.T., published by Springer Verlag, ISBN: 9781846283789
-
Fortran 95/2003 For Scientists and Engineers, by Chapman S.J., published by McGraw- Hill. ISBN ISBN 0073191574
-
Fortran 95/2003 Explained, by Metcalf M., Reid J. and Cohen M., 2004, published by Oxford University Press. ISBN 0-19-852693-8
I agree that the compiler should warn when a compile-time expression overflows. I will ask the developers about that.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ok, to play it safe, I did as you suggested, and used 8 byte literals everywhere appropriate.
BTW, this gives the wrong answer also:
print *,2_8**63
It gives a negative number.
This is germaine to our previous discussion.
So a good compiler option (enhancement) would be to allow the user to specify that all literal expressions
could use 64 bit (integer(8)) computations instead.
Especially when it give wrong results with no warnings.
BTW, this gives the wrong answer also:
print *,2_8**63
It gives a negative number.
This is germaine to our previous discussion.
So a good compiler option (enhancement) would be to allow the user to specify that all literal expressions
could use 64 bit (integer(8)) computations instead.
Especially when it give wrong results with no warnings.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What would you expect that to print? 2**63 is, in two's-complement binary, a negative number. Fortran does not have unsigned numbers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
An unaware person would think that 2**63 should be a positive number, since any power of a positive integer has to be > 0.
Of course, we know that 2**63-1 is the largest number possible in the integer(8) range.
print *,2_8**63 -1
does give the correct answer.
Of course, we know that 2**63-1 is the largest number possible in the integer(8) range.
print *,2_8**63 -1
does give the correct answer.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page