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

mod() and modulo() behavior under the -fltconsistency flag

Marshall_Ward
Beginner
877 Views
This is actually two questions:
First is related to the behavior of the mod() intrinsic. If I compute the following using only the default flags:
mod(360., 0.1)
then the result is9.9994637E-02.According to the Intel manual and my Metcalf,Reid,and Cohen textbook,
mod(a,p) = a - int(a/p)*p.
But if I calculate this quantity:
360. - int(360./0.1)*0.1
then it gives0.0000000E+00.Is this the result of some implicit optimizations? Or is there another explanation?
The second question is similar. If I use the modulo() intrinsic instead, then I always get zero. That is:
modulo(360., 0.1)
returns0.0000000E+00. However, if I turn on the -fltconsistency flag, then it returns-5.3644180E-06.If I extend this to double precision (-r8) the numbers are different but the results are otherwise similar. But if I use the varios -fp-model flags, the result for modulo() remains zero.
I am guessing that all of these differences are the result of the inexact binary representation of 0.1. But I am not sure how to reproduce these differences, and what the best practice is for computing a modulo and determining if 'a' is a multiple of 'p'.I'd be grateful for any comments or explanations. TIA
0 Kudos
1 Reply
jimdempseyatthecove
Honored Contributor III
877 Views
>>what the best practice is for computing a modulo and determining if 'a' is a multiple of 'p'.

The problem that you have pointed out is that if 'p' is 0.1 that (using floating point) 'p' cannot be accurately stored in FP representation. What you are asking for is to determine if 'a' is a multiple of 'an unrepresentable number'. You have two options available:

a) determine if 'a' is approximately equal to a multiple of 'p' to within precision of 'x'
b) convert your units to precision of 'x' for all calculations then
if 'a' has fractional component or 'p' has fractional component then assume results are approximate
if 'a' and 'p' are both integral (in units of x) then *** with compiler optimizations off

temp = p / a
if((temp == int(temp)) .and. (p == (temp * a))goto isMultiple

Note, there are many subsets of a) where an exact result can be determined. However, these subsets are indistinguishable from those that are not.

For b) as an example if your precision is to 0.1 degree (or 0.01 degree) then represent your degrees as 1/10ths. IOW 3600 tenths to a circle (36000 hundredths, ...). However, bear in mind that your mantissa can saturate if you add small incriments to large values. Therfore, reduce the 'a' mod 360, (or3600, or 36000) prior to use.

Jim Dempsey
0 Kudos
Reply