- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Suppose we have:
integer(4) x,y
integer (8) z
z=x*y
In almost all cases, the result will be wrong, in fact, more than 99.9999 percent of the
time, since the compiler does not understand that the result can be more than 4 bytes.
This wrong result is not detected, since apparently the compiler does not check for an overflow.
At least, not on the INTEL compiler, although in my work at Aerospace and JPL IBM 7094
main frames, it did tell you about the overflow.
so to avoid this, I have to say:
z=int(x,8)*y
Is there a simpler way around this? Maybe the compiler people should take a serious look at this.
You see the same problem with INTEGER(1) AND INTEGER(2) variables, BTW...........
As well as with the ADD operator. seems like an overflow check would be a simple answer,
though it does slow down things. So maybe as an option ?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think your mental model is slightly wrong: it is not a matter of the compiler not understanding that the result can be larger than expressable in 4 bytes, but the Fortran standard prescribes that the right-hand side is evaluated independently of the left-hand side.
Furthermore, if I understand these matters correctly, detecting overflows and other such unusual conditions is a task for the computer's processor, not for the compiler/runtime and most hardware checks only for floating-point exceptions. I think I read somewhere that this behaviour (silent overlfows) is even expected in a lot of software.
The simplest solution is: do not mix different types of integers. I would use the kind mechanism to define integers of the desired range, just as is commonly done for reals.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In fact, Fortran on the 7094 didn't support mixed data types, nor even any precursor of KIND. Later f66 compilers support mixed data types only outside the standard, with vendor-specific treatments.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The problem with having ALL INTEGERS OF THE SAME TYPE, is that you can use up a lot of unwanted storage that way.
Suppose, for example, you want to get the largest product from two arrays of integer(1):
integer (1) x(1000000), y (1000000)
integer(2) xymax/0/,xy
do i=1,1000000
do j=1,1000000
xy=int(x(i),2)*y(j)
xymax=max(xymax,xy)
enddo
enddo
Print *,xymax=",xymax
It would be really stupid to make those integer arrays integer(2) and waste 2000000 bytes of storage,
don't you agree?
Of, course in this case, one should take the MAX of each array, then multiply that, but this is
just to illustrate the point.
If you know that no integer is > 127, then integer(1) is the largest you would make them.
Unfortunately, FORTEAN 95 does not give us a convenient way to multiply two INTEGER(8) quantities,
or even INTEGER(8) by a smaller size integer, with getting an overflow and detecting it. One can, however, simulate it by using
REAL(16), though, as follows:
real(16) xy
integer(8) x,y
xy=real(x,16)*real(y,16) ! they dont both HAVE to be real
You still would have trouble storing the result, however.
Also REAL(16) cannot handle a 126 bit result, since some of the 16 bytes (12 bits ?) is used by the exponent.
The largest product you can have is (2**63-1)*(2**63-1) which would be 126 bits long.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
so to avoid this, I have to say:
z=int(x,8)*y
Is there a simpler way around this?
It isn't exactly a complicated solution is it? Or would an 'easier' solution be to redfnne how the Fortran language works?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, the really bad part is you can get completely wrong answers without KNOWING it.
That can be really critical if you have a really serious application.
For example : Medical, space travel, missile launching, etc.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
arjenmarkus said "the right side is evaluated independently."
But it does NOT evaluate the RHS properly if the result is too big to fit.
Unless one forces it by using int(*,8), int (*,4), etc.
Storing it, well, that's a different matter.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Bill,
Pardon my French but as someone who has apparently been working with Fortran (and FORTRAN) for quite a few years, you should know about the risk of overflow in situations exactly like this. It has been this way for about 60 years. The way to protect against it is as others have already indicated.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It does seem a great pity that Haswell has such nice primitives as MULX, ADCX, and ADOX for performing bignum arithmetic, but Intel's Fortran compiler does not give us access to them.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have been using Fortran myself for over 50 years, since the Fortran II days.
But Intel is the only company that ignores integer overflow situations, that I have ever seen.
Even if we take all these precautions, it can still bite you in the tush.
How do I get the Haswell product ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
billsincl wrote:
How do I get the Haswell product ?
Mainstream Haswells do not support ADCOX. Some (all? I'm not sure, need to search and read Intel processor manuals to find out) Haswell-E processors do. What this implies is that if you want ADCOX instructions on, say, a laptop, you need a Broadwell or a Skylake CPU.
Even if the CPU has some desired instructions/features in its repertoire, you need support in the programming language or through support libraries and, sometimes, in the OS and even the BIOS and motherboard.
You can find out what features are available in a specific CPU by running the following C program if you have the IPP library and the Intel C compiler installed.
#include <stdio.h> #include <ippcore.h> int main(){ Ipp64u mask; IppStatus stat; stat=ippGetCpuFeatures(&mask,NULL); printf("stat(ADCOX) = %1d\n",mask & ippCPUID_ADCOX ? 1 : 0); printf("stat(AVX) = %1d\n",mask & ippCPUID_AVX ? 1 : 0); printf("stat(SSSE3) = %1d\n",mask & ippCPUID_SSSE3 ? 1 : 0); }
If the first line prints a non-zero, the ADCOX feature is available but, if your software does not allow you to exploit the capability in a convenient manner, in effect it is not available.
All that said, I think that you are making much ado about little and have unreasonable expectations. Generations of programmers have survived life without hardware interrupt/trap on integer overflow. If n-byte integers were provided, invariably some users would be asking for 2.n-byte support (in this thread, n <= 4). On x86/x64 the INTO instruction is available for use with the flags register to catch overflow, but needs support in the compiler. Some Windows Fortran compilers do let you check for integer overflow (at the expense of slowing down your programs).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I guess you're right about not having ADOX/ADCX instructions. I wrote up something to check via CPUID:
; fasm mulx.asm format MS64 coff section '.code' code readable executable public FTN_CPUID FTN_CPUID: xchg eax, edx xchg eax, ecx CPUID mov [r8], eax mov [r8+4], ecx mov [r8+8], edx mov [r8+12], ebx ret
! ifort /nologo adox.f90 mulx.obj program P use ISO_FORTRAN_ENV implicit none interface subroutine FTN_CPUID(eax,ecx,results) bind(C,name='FTN_CPUID') import implicit none integer(INT32), value :: eax integer(INT32), value :: ecx integer(INT32) results(4) end subroutine FTN_CPUID end interface integer(INT32) eax integer(INT32) ecx integer(INT32) results(4) eax = int(Z'01',INT32) ecx = int(Z'00',INT32) write(*,'(a)') 'Input:' write(*,'(a,z8.8)') 'eax = ', eax write(*,'(a,z8.8)') 'ecx = ', ecx call FTN_CPUID(eax,ecx,results) write(*,'(a)') 'Outut:' write(*,'(a,z8.8)') 'eax = ', results(1) write(*,'(a,z8.8)') 'ecx = ', results(2) write(*,'(a,z8.8)') 'edx = ', results(3) write(*,'(a,z8.8)') 'ebx = ', results(4) eax = int(Z'07',INT32) ecx = int(Z'00',INT32) write(*,'(a)') 'Input:' write(*,'(a,z8.8)') 'eax = ', eax write(*,'(a,z8.8)') 'ecx = ', ecx call FTN_CPUID(eax,ecx,results) write(*,'(a)') 'Outut:' write(*,'(a,z8.8)') 'eax = ', results(1) write(*,'(a,z8.8)') 'ecx = ', results(2) write(*,'(a,z8.8)') 'edx = ', results(3) write(*,'(a,z8.8)') 'ebx = ', results(4) end program P
Input: eax = 00000001 ecx = 00000000 Outut: eax = 000306C3 ecx = 7FFAFBFF edx = BFEBFBFF ebx = 05100800 Input: eax = 00000007 ecx = 00000000 Outut: eax = 00000000 ecx = 00000000 edx = 00000000 ebx = 000027AB
The first CPUID shows
Processor Type = B'00' -- Original OEM Processor
Family ID = Z'06' = Display Family
Model ID = Z'0C'
Extended Model ID = Z'03' => Display Model = Z'3C' => Haswell (not E)
Stepping ID = Z'03'
The second CPUID shows
BMI2 = .TRUE. => MULX available
ADX = .FALSE. => ADOX/ADCX not available :(
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
integer(8) :: x, y, z
z = x * y
if(z / y .ne. x) then
! overflow
Jim Dempsey
![](/skins/images/B7BA37F9CE4B52FF7CAE1FB0388839C8/responsive_peak/images/icon_anonymous_message.png)
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page