Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Some Do Loops fail with integer(8) as well

WSinc
New Contributor I
491 Views

I put together this little test program, to see better when we get problems.

Apparently , having the upper limit near HUGE() does not seem related to this.

Especially when the compiler pre-computes the number of iterations using this formula:

KCALC = (K8HI - K8LO)/DK8 + 1

Consider the trivial case where KCALC = 3

Then the values of K8 should be:

K8HI - 2*DK8,   K*HI-DK8, and  K8HI

So it does not have a chance to overflow the integer(8) high value,

even when K*HI8 = HUGE(K8)

This little test program steps thru values of K8LO starting with zero.

You start off getting wrong numbers  of number of iterations thru the loop,

then when it reaches the value of KI8, the problem goes away.

So I have to conclude that the compiler has an error in the way it computes the number of iterations.

Why would it ever give you ZERO passes? Unless the result was negative.....

Some call this the "integer overflow curse."

Actually, if it DID overflow the integer(8), you would get an infinite number of iterations, since the NEXT

value would be NEGATIVE. You sure would NOT get zero passes thru the loop, unless KLO8 > KHI8

and they are both <= HUGE(k8)

Even if KLO8 = KHI8, you still get ONE pass.

This littlle DO LOOP does work:

DO K = huge(k)-10, huge(k), 2

ENDDO

You get 6 passes, as you should.

0 Kudos
12 Replies
WSinc
New Contributor I
491 Views

Actually, that "little DO LOOP" did not work.

But if I adjust the upper and lower limits down a little bit, it does.

 

Actually, I think I know what they did wrong -

Suppose they tried to evaluate it as follows:

(Khi - Klo + Kinc) / Kinc

 

If they added Khi to Kinc FIRST and did NOT check for an integer overflow

then they would get ZERO or a NEGATIVE result.

 

Which is what we get under certain conditions - - 

 

The proper order is:

first Khi- kLo, then divide by Kinc, then add 1.

0 Kudos
andrew_4619
Honored Contributor III
491 Views

I think that does not really move things on from my post #19 made some time back in your other thread (https://software.intel.com/en-us/forums/topic/542641).

To reiterate, for a DO loop , if  finish+step>= huge the loop does not run. Clearly this is not right as the loop index shouldn't need to take values higher than finish and could in fact productively run.  However you cannot say much more about what the compiler is doing in its pre-checks that is just guesswork I will leave that to the Intel guys.

Your case is unusual as both step and finish are very large, outside what people would routinely do, but IMO the compiler should be able to cope with this as it is valid code. 

0 Kudos
mecej4
Honored Contributor III
491 Views

I think that Dr. Fortran gave a clear statement about this matter in https://software.intel.com/en-us/forums/topic/542641#comment-1816351. This is what the 2008 standard says regarding the execution count of the loop body:

8.1.6.4.1(3) The iteration count is established and is the value of the expression (m2 −m1 +m3)/m3, unless that value is negative, in which case the iteration count is 0.

Other parts of the standard stipulate that the order of evaluation of an expression without parentheses is not specified. However, even if we take the order to be left to right, BillSincl's values of m1, m2, m3 are such that integer overflow occurs when m3 is added, even though m1 was subtracted first; the computed value of the calculated iteration count is negative, and  then the count is set to 0 as the standard states. The standard does not require that a processor should strive to avoid integer overflow, nor does it specify what should be done when integer overflow occurs. In standard-speak, the program is non-conforming and the results of compiling/running the program are undefined.

Bill's dispute is with the standard, it seems. If he can show that IFort behaves differently than other compilers and/or that the behavior of the compiler does not comply with the standard, a complaint in this forum would be valid. Even a valid criticism of the standard might draw some interest. But when someone blithely ignores the standard and faults the compiler for not behaving in a way that one wishes for, there is a simple counter argument: most users want the compiler to be standard-compliant.

In older versions of Fortran (and, with a "legacy code" option, with some current compilers), there was a provision for a minimum one-trip DO loop. That behavior may have been common but was probably not specified in a previous standard, and such behavior is not to be expected in modern code.

0 Kudos
WSinc
New Contributor I
491 Views

Like I said before, and app4619 and others also said:

If they do it in THE PROPER ORDER, i.e.

 

(M1-M3+M2)/M2  rather than

(M1+M2-M3)/M2  it will work OK.

Its kinda interesting that they don't get the integer overflow for INTEGER(1) and INTEGER(2) situations.

whereas for the 4 and 8 byte cases, we CAN get it.

 

My attitude is : It ought to be right 100 per cent of the time, rather than 99.9 per cent of the time.

You never know when that other 0.1 per cent will bite you in the tush.

I may have more of a perfectionist attitude, since I came from a background where you could lose

a billion dollar spacecraft with one little glitch in the code - - - so, I apologize.

That integer overflow stuff  is pretty stupid anyway. But one way to check it is to

see if the sum (or product) of two positive numbers is still positive.

As I am sure most of you already know, when you MULTIPLY two 4 byte integers, the result is

almost ALWAYS more than 4 bytes. and even if you put an 8 byte variable to the LEFT of the equals,

you still almost always get the wrong answer. Unless of course you say:

C = int(A,8)*INT(b)  or

C = 100000000_8 * 3

 

PS: It can still be positive, yet still wrong in some cases, so thats not a definitive test.

0 Kudos
IanH
Honored Contributor II
491 Views

app4619 wrote:

I think that does not really move things on from my post #19 made some time back in your other thread (https://software.intel.com/en-us/forums/topic/542641).

To reiterate, for a DO loop , if  finish+step>= huge the loop does not run. Clearly this is not right as the loop index shouldn't need to take values higher than finish and could in fact productively run. 

I haven't been following this closely, but several of the examples that bill has posted are non-conforming - in particular - for the syntax example `DO variable = start, finish, step`, if finish + step would be greater than HUGE(variable), the program is in error.  You cannot rely on any number of iterations in this case - non-conforming program - anything can happen. 

Perhaps you were simply stating this a different way - but I read you comment as implying that it should still work in this case.

0 Kudos
WSinc
New Contributor I
491 Views

I was simply saying that it should be able to run ALL the steps called for in the DO LOOP,

and it should not be relevant what happens on any step OUTSIDE of the DO LOOP.

Unfortunately, the sources I have looked at don't address the integer overflow problem.

And I don't think the standard does either.

Probably because in the "days of yore," we had processors that would TRAP on an integer overflow, 

so you would immediately be alerted to any problems like that. At least I dont remember any CPU

or any mainframe computer that simply ignored that situation. Then INTEL came along, and said "Ahh, we wont bother with that."

This was AFTER the standard was posed back in the1960's. Personal computers first came along in the early 80's right?

0 Kudos
WSinc
New Contributor I
491 Views

Actually, back then when I did machine code, if you did a MULTIPLY of two 32-bit quantities, you always assumed that the result

was up to 64 bits. And if you added them, you always assumed the result could be 33 bits. So it was up to the programmer 

to assure that all possible cases were covered - - something that compilers don't do for us.

A really smart compiler would at least give you a warning, like:

INTEGER  A,B,C

C = A + B

"WARNING: results may be incorrect."

Likewise for:

C = A * B

"Warning: results will HARDLY EVER be correct."

0 Kudos
IanH
Honored Contributor II
491 Views

billsincl wrote:

I was simply saying that it should be able to run ALL the steps called for in the DO LOOP,

and it should not be relevant what happens on any step OUTSIDE of the DO LOOP.

Unfortunately, the sources I have looked at don't address the integer overflow problem.

And I don't think the standard does either.

"The execution of any numeric operation whose result is not defined by the arithmetic used by the processor is prohibited."

Execution of many (all?) of the do loop examples here and in the other similar thread require that the do variable be defined immediately prior to loop termination (we are not talking about a "step OUTSIDE of the DO LOOP") with a value greater than what can be stored in the variable.  That's a clear violation of the above.  Those examples are non-conforming.

These sorts of restrictions on a program are taken into account when implementing compilers.  If you violate those restrictions then you shouldn't be surprised that the compiler doesn't do what you want it to do.

0 Kudos
WSinc
New Contributor I
491 Views

Now we are getting into "legalese." Where does it say that?

 

Maybe they mean "define the LOOP variable" BEFORE termination ?

i.e. test the results of adding the increment BEFORE going back thru the loop again.

 

Is that spelled out ?

0 Kudos
IanH
Honored Contributor II
491 Views

Those words are in Fortran 95 on.  In the current standard (F2008) they are in 7.1.5.2.4.  There are also restrictions on calling intrinsic functions such that a result doesn't fit in the result variable that may be invoked - the intrinsic functions are implicitly referenced in the description of the behaviour of a do construct for things like kind conversion of parameters.

(There is also a general processor dependent size and complexity limit on a program that could come into play here - but I don't think that needs to be relied upon to argue that most of the examples are non-conforming.)

The definition of the do variable as part of the execution of the do loop is in the sequence described in the execution cycle (8.1.6.6.2).  There is no test on adding the increment - the number of iterations is hypothetically based on an iteration count as described previously in this thread (or maybe it was in the other thread) and that iteration count check occurs before execution of the statements in the body of the do construct begins.  It is the specified number of iterations in conjunction with the requirement that the do variable be incremented at the end of every iteration that makes [most of] your examples non-conforming.

0 Kudos
WSinc
New Contributor I
491 Views

Well, to me "conforming" means the expression for the number of iterations,

N= (stop-start+increment)/increment

gives CORRECT results. In all cases.

If start <= stop, then it can NEVER be zero or negative.

The programmer has no way to know that ahead of time, since the

start, stop and increment values can be expressions, OR coming from DATA inputs.

Or a mixture of those.

 

So, how would he know either way?

 

Apparently we dont get this problem if the values are 1 or 2 bytes.

why would it not be consistent at least?

0 Kudos
andrew_4619
Honored Contributor III
491 Views

billsincl wrote:
N= (stop-start+increment)/increment

gives CORRECT results. In all cases.

errr no it doesn't consider cases where start is negative and large) and stop is positive  and large for example....

0 Kudos
Reply