Q re integer multiply

Q re integer multiply

I noticed that when I multiply two integer(4) quantities together,

the compiler does not allow the result to be integer(8).

So is there a way to FORCE the correct answer?

For example:

integer(4) x,y

integer(8) z

Z=x*y does not give correct results in MOST cases, unless x and y are small.

What can I do to MAKE SURE I will get the correct answer?

Notice that if x and y are each 31 bits, Z can be 62 bits, which will fit into a INTEGER(8) result.

Is there a way to force the compiler to look for an integer overflow?

12 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

BTW, I could not find an intrinsic function that converts integer quantities into longer ones.

I have to resort to:

integer(4) x,y

integer(8) XX,Z

XX=x

Z=XX*y

Seems pretty awkward, anyway......

The problem is that the xy multiplication I would expect to take place as 32 bit and after the answer is made it is then transferred into a 64 bit value. If one of the items on the right hand side was 64 bit in the first place the compiler should promote the other elements and do that calculation as as 64 bit.

so the expressions below should work as you expect I would expect

z=int(x,8)*y
z=1_8*x*y

The root cause of your problem is that, by rule, if two operands are of the same type and kind, then the intermediate result is of the same type and kind as the operands.  Also, by rule, if two operands are of different types and/or kinds, then both of the operands are converted to the type and kind of the result before the operation is performed (Fortran 2008 standard, s. 7.1.5.2.1).

Thus, since both x any y are of 32-bit integer, the intermediate result is of 32-bit integer, which is then assigned to a 64-bit integer.  This behavior is required by the rules of Fortran.

Here is a robust method of getting what you really want.

Integer  ::  WP  ! Working Precision
WP = Kind (Z)  ! Working precision is the same kind as Z.
Z = Int (A=X, Kind=WP) * Y

Or, if you don't want to use the intermediate variable of WP, you could collapse this to:

Z = Int (A=X, Kind=Kind(Z)) * Y

However, I find the second form less readable.

Hope this helps.

However,

z = x*y*1_8 would not widen until after the 32-bit multiplication is completed.

You could check for overflow either by looking for an unexpected sign change or by comparing the 32-bit result against a 64-bit one.

Digressing slightly, 64-bit integer multiplication costs nothing extra (except for storage) in 64-bit mode, but could take over twice as long as 32-bit multiplication when running in 32-bit mode.

You would think that the compiler SHOULD be smart enough to know that the result in MOST cases can overflow 32 bits.

Actually for signed arithmetic, the highest number can be only 31 bits, since the sign bit is counted.

If I know that I am only going to be working with positive numbers (like you can in C++) then all 32 bits of

precision are available, and integer(8) can give us 64 bits.

Unfortunately, there is no easy way to force it to check for an integer overflow, at least no flag that can be turned on

at execution time. I remember in my early computer days that an integer overflow always caused a trap.

We don't have that luxury any more, alas.

The standard does not allow the compiler to give you free conversion to a larger kind. You can write that yourself, as noted, using the INT intrinsic with the KIND= argument.

Steve - Intel Developer Support

Do you happen to know why they turned off the integer overflow trap?

Did it have to do with subscripting?

Just curious - - - 

 

Also, is there a package anywhere that deals with arbitrarily long integers?

 

One application would be in encryption software.

For example I want to multiply 

7777777777777777777777777777777777777777777   by

9999999999999999999999999999999999999999999

A quick google of "arbitrary precision arithmetic fortran" threw up several links

e.g http://crd-legacy.lbl.gov/~dhbailey/mpdist/ for ARPREC (Arbitrary Precision), among others.

Les

The processor design has no concept of integer overflow trap. It is the programmer's responsibility to handle this.

While there is an integer Overflow Flag, it does not generate a trap. FORTRAN has no means to test this.

C/C++ doesn't even have this direct test, though an intrinsic "could" possible address this, inline assembler can address this.

You, as a programmer would be responsible to add an external function to provide this capability.

For example you can write a call to an integer function written in C that contains inline assembler (or write directly in assembler), that performs say an integer add or integer multiply, passed two arguments in (as reference or value), computes integer result, obtains .NOT. Overflow Flag, integer divides 1 by prior obtained flag (producing DIV0 trap when prior ~OF was 0)) , returns results value when not trap.

RE arbitrary long multiplication

Search for C/C++ code to perform this (there are many such packages). Some of the newer processors have extensions to improve multi-precision math in the AVX registers. This is relatively easy to do with older processors in scalar using general purpose registers.

Jim Dempsey

www.quickthreadprogramming.com

While it is true that Intel Architecture (IA-32 and Intel 64) doesn't have the concept of an integer overflow trap, it is possible to check for overflow after individual operations. CVF had this, but the Intel code generator doesn't support it. It has been on the feature request list for a long time, but I am not hopeful it will be implemented,

Steve - Intel Developer Support

Have you considered declaring a type and defining operator functions that contain the overflow tests and action? Then for those cases where you want overflow protection, use those type. It may be easier to fix your code to contain sanity checks.

Note, what one programmer considers as an overflow, a different programmer may consider it as a functional requirement.

Consider as an example a home brew random number generator

integer(8) :: Seed
...
Seed = SomePrimeNumberNot2_8
...
Seed = Seed * SomePrimeNumberNot2_8
YourRnd = INT(RSHIFT(Seed, 16), YourRnd)

The above relies upon overflow not causing a trap.

Jim Dempsey

www.quickthreadprogramming.com

Leave a Comment

Please sign in to add a comment. Not a member? Join today