# Use of tiny / 2

## Use of tiny / 2

I have been trying to understand the use of the intrinsic TRANSFER, to store a mixture of integer and real values in an integer array and then recover them. I had hoped to do this in a more standard conforming way.
Anyway, I experimented with TINY to see how real zero might look. I wrote the following program to test real underflow and how this might be stored.

```  integer*4, parameter :: sp = selected_real_kind (p=6)
real(sp) :: x

integer*4 i(4),j

!

i = 0

write (*,*) 'test for real kind =',sp, kind(1.0), kind(1.0d0)

x = 1

i(1) = transfer (x,j)

write (*,*) '1   ', x, i

!

x = tiny(x)

i(1:2) = transfer (x,j,2)

write (*,*) 'tiny', x, i

!

x = x/2

i(1:2) = transfer (x,j,2)

write (*,*) 'x/2 ', x, i

!

end```

this produced the following result:

Intel(R) Visual Fortran Compiler XE for applications running on IA-32, Version 12.1.5.344 Build 20120612

Microsoft (R) Incremental Linker Version 10.00.30319.01

-out:tiny2.exe
-subsystem:console
tiny2.obj
test for real kind =           4           4           8
1      1.000000      1065353216           0           0           0
tiny  1.1754944E-38     8388608           0           0           0
x/2   5.8774718E-39     4194304           0           0           0

To my surprise x/2 is not zero !

My aim is to transfer 4 byte and 8 byte reals into an integer*4 vector for later recovery, but I thought I'd test a 4 byte real first. I find the use of the size argument of TRANSFER a bit confusing.

John

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

You're getting a denormalized value. See http://en.wikipedia.org/wiki/Denormal_number If you don't want to see denormalized values, compile with /fpe0 .

As for TRANSFER, the SIZE argument specifies that TRANSFER shall return an array of size SIZE.

Retired 12/31/2016

Steve,

Thanks for your advice. I compiled with default = /O2. Wiki states that Intel's C and Fortran compilers enable the denormals-are-zero (DAZ) and flush-to-zero (FTZ) flags for SSE by default for optimization levels higher than -O0. Does that imply I am not using SSE instructions for this calculation and if x were a vector the result could be different ? ( ie, could this test be used to show if SSE instructions were used ?)

I am not sure if denormalised values would be a problem, but I assume a denormalised value would fail for "If (x == 0) " which can be a test for underflow on compilers that don't allow denormalised values. There is the potential for round-off errors to increase with a poor test for an "insignificant" value of x.

Regarding TRANSFER, thanks for your comment about SIZE. I now understand SIZE relates to the size of the array result, while the size of the source is defined by source itself. It appears that MOLD and SIZE do similar things, as I can't think of a situation where the type of MOLD and the result can be different, with the only affect of MOLD is if the result is a scalar or an array. (I might go back to EQUIVALENCE, as there is less confusion about what can happen.)

John

What Wiki? Here's what our documentation says:

Default

-fpe3 or /fpe:3

All floating-point exceptions are disabled. Floating-point underflow is gradual, unless you explicitly specify a compiler option that enables flush-to-zero.

Retired 12/31/2016

Apparently reference 9 of the link you provided me in Quote #2. It is discussed under "Disabling denormal floats at the code level".
I found the comment interesting as I am testing the use of SSE and AVX instructions.

John

Interesting. I will check with others to see what that's about.

Retired 12/31/2016

The x/2 calculation is not being done at runtime with optimisation active.

Ian is correct. If the computation is done at run-time, the default at O2 is flush-to-zero - I just tested this.

Retired 12/31/2016

Steve and Ian,

Thanks for your comments. I have tried to identify what computation is done at run time. I assume the alternative is that the computation is done at compile time ?

I tried to change to code to identify how this may occur, with interesting results. Does the compiler determine the value of y before determining how to calculate x/y ? If y is a power of 2 then the computation could be via a shift of the significand or mantissa, but only when the exponent is maxed out ? It's a lot of effort to avoid flush-to-zero, assuming I have understood what has been discussed.

```  integer*4, parameter :: sp = selected_real_kind (p=6)

real(sp) :: x, y

integer*4 i(4),j

!

i = (/ 1,2,3,4 /)

!

write (*,*) 'test for real kind =',sp, kind(1.0), kind(1.0d0)

x = 1

i(1) = transfer (x,j)

write (*,*) '1    ', x, i

!

x = tiny(x)

i(1:2) = transfer (x,j,2)

write (*,*) 'tiny ', x, i

!

x = x/2

i(1:2) = transfer (x,j,2)

write (*,*) 'x/2  ', x, i

!

y = 1.6

x = tiny(x)

x = x/y

i(1:2) = transfer (x,j,2)

write (*,*) 'x/1.6', x, i

!

y = 2.0

x = tiny(x)

x = x/y

i(1:2) = transfer (x,j,2)

write (*,*) 'x/2.0', x, i

!

end

```

This produced:

Intel(R) Visual Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 12.1.5.344 Build 20120612

Microsoft (R) Incremental Linker Version 10.00.30319.01

-out:tinyj.exe
-subsystem:console
tinyj.obj
test for real kind =           4           4           8
1       1.000000      1065353216           2           3           4
tiny   1.1754944E-38     8388608           0           3           4
x/2    5.8774718E-39     4194304           0           3           4
x/1.6  0.0000000E+00           0           0           3           4
x/2.0  5.8774718E-39     4194304           0           3           4

John