Re: problem with very small numbers - g95 versus gfortran



On May 28, 9:43 pm, "James Van Buskirk" <not_va...@xxxxxxxxxxx> wrote:
"e p chandler" <e...@xxxxxxxx> wrote in messagenews:cba2a6c6-2677-42e1-a6a8-8ce070b851c1@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Apparently there is a problem with assigning a very small double
precision literal to a 10-byte real. (MinGW on Win32). Assigning a
literal of the proper kind resolves the problem.

Yeah, and FX relates to me that it's not only g95 that can run into
problems with denormals.  He gave an example where BOZ
representations of denormals could be converted improperly, but
inconsistently so in gfortran and said that other compilers faced
problems.  Likely the problem is that denormals are a special case
so that code where they are handled is not as well tested as the
normal case.

Just for fun, tell me what g95 does with the following:

C:\gcc_mingw64a\test\denormal>type denormal.f90
real*10 x,y

x=1d-306
y=1e-306_10

print *,306,x,y
print '(2(e30.20e4,/))',x,y

x=1d-307
y=1e-307_10

print *,307,x,y
print '(2(e30.20e4,/))',x,y

x=1d-308
y=1e-308_10

print *,308,x,y
print '(2(e30.20e4,/))',x,y

print*, tiny(1.0d0), tiny(1.0e0_10)

x=2.23d-308
y=2.23e-308_10
print*,'tiny+',x,y

print '(2(e30.20e4,/))',x,y
print '(z16.16)', transfer(2.23d-308,0_8)

x=2.22d-308
y=2.22e-308_10
print*,'tiny-',x,y

print '(2(e30.20e4,/))',x,y
print '(z16.16)', transfer(2.22d-308,0_8)

end

C:\gcc_mingw64a\test\denormal>x86_64-pc-mingw32-gfortran
denormal.f90 -odenormal

C:\gcc_mingw64a\test\denormal>denormal
         306  1.00000000000000002790E-0306  1.00000000000000000003E-0306
  0.10000000000000000279E-0305
  0.10000000000000000000E-0305

         307  9.99999999999999909327E-0308  1.00000000000000000003E-0307
  0.99999999999999990933E-0307
  0.10000000000000000000E-0306

         308  9.99999999999999909327E-0309  9.99999999999999999974E-0309
  0.99999999999999990933E-0308
  0.99999999999999999997E-0308

  2.22507385850720138E-308  3.36210314311209350626E-4932
 tiny+  2.23000000000000010412E-0308  2.22999999999999999990E-0308
  0.22300000000000001041E-0307
  0.22299999999999999999E-0307

0010091177587F83
 tiny-  2.22000000000000013467E-0308  2.22000000000000000006E-0308
  0.22200000000000001347E-0307
  0.22200000000000000001E-0307

000FF6A8EBE79958

OK. Here is the run with g95:

C:\Users\epc\temp>g95 denormal.f90

C:\Users\epc\temp>a
306 1.0000000000000000279E-306 1.E-306
0.10000000000000000279E-0305
0.10000000000000000000E-0305

307 9.999999999999999093E-308 1.E-307
0.99999999999999990933E-0307
0.10000000000000000000E-0306

308 4.9999999999999995466E-309 1.E-308
0.49999999999999995466E-0308
0.99999999999999999997E-0308

2.2250738585072014E-308 3.3621031431120935063E-4932
tiny+ 2.230000000000000104E-308 2.23E-308
0.22300000000000001041E-0307
0.22299999999999999999E-0307

0010091177587F83
tiny- 1.11000000000000006733E-308 2.22E-308
0.11100000000000000673E-0307
0.22200000000000000001E-0307

000FF6A8EBE79958

C:\Users\epc\temp>

Looking up TINY() shows:

TINY(X) returns the smallest positive (non zero) number in the model
of the type of X.

Please explain what I am seeing in light of the above definition. Does
this mean that specifying a literal in double precision where that
literal is less than tiny() is invalid? Yet it seems to work with
gfortran.

At least you found the boundary where the bug is triggered.

- e

.