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

How to reduce the loss of precision when call subroutines?

cjfunsw
Beginner
933 Views
Dear Sir,

I notice that when I assign a value to a variable and it is passed into the subroutine. I found that the value changed. How can I maintain the precision. all the variables I have declared them as double precision. Some values they changed but some does not.

Do you have any ideas on this issue.

Thank you so much for your help.

Best Regards,
Jingfen
0 Kudos
11 Replies
DavidWhite
Valued Contributor II
933 Views
Jingfen,

Can you please give some example code? it is difficult to understand what is happening without examples.

Using the compiler option /fp:precise may be useful to look at.

David
0 Kudos
Les_Neilson
Valued Contributor II
933 Views
Jingfen

You saidwhen "it is passed into the subroutine I found that the value changed"
You asked "How can I maintain the precision?"

Do you really mean "precision" ?
As David says, it is difficult to give you a definitive answer without us seeing at least a relevant portion of code.
But ...
Could it be that you have an argument mismatch ?

example :

double precision x
x = 3.14159265358979d0

call asub(x) ! there is a mismatch here
The actual argument X needs to match the "dummy" argument W in asub


subroutine asub(w)
realw ! Herew is SINGLE precision
! any value assigned toit will be single precision
w= 3.14159
...


If you suspect this may beyour problem you should turn on the diagnostics to check routine interfaces when you build your exe

Les
0 Kudos
mecej4
Honored Contributor III
933 Views
Mismatches of this type (REAL and DOUBLE) can cause more catastrophic errors than mere loss of precision. If the MMX/XMM registers are used to pass real arguments rather than the x87 stack:

[fortran]program tst
double precision :: x
x=4*atan(1d0)
call asub(x)
end program tst
subroutine asub(x)
real :: x
write(*,10)x
10 format(G18.10)
return
end subroutine asub
[/fortran]
will print bogus output such as
[bash]  0.3370280550E+13
[/bash]
instead of the value of \pi.
0 Kudos
Les_Neilson
Valued Contributor II
933 Views

Mismatches of this type (REAL and DOUBLE) can cause more catastrophic errors than mere loss of precision. If the MMX/XMM registers are used to pass real arguments rather than the x87 stack


Yes I thought about the problem ofstack corruption (due to argument mismatch)after I posted, andlater thought the original problem might beaboutsimple assignmentwhere if one has

X = 3.1415926535897932384626433832795

the numeric literal is single precision no matter how many digits are specified. The rhs is evaluated first and then the SINGLE precision result is assigned to the lhs.If X is double precision then the trailing bits are set to zero.

Les

0 Kudos
cjfunsw
Beginner
933 Views

Dearfriends,

Thank you so much for yourkind help.I am moreclear aboutwhat might cause the loss of precision.

But, Sorry,because I was working witha user subroutine to be called by another software called ABAQUS.And Causethe data Icompared belong to two different integration point. In the two sets of data, some values arethe same and othersarenot. Soat the first thought, I thought it was the problem of the loss of precision between subroutines.

But, I also output the value of one variable in the subroutine. it is as below.

-------------------------------------------------------------------------
DOUBLE PRECISION TOL,

TOL=1.0E-6

WRITE(7,*) "TOL=",TOL
--------------------------------------------------------------------------


but the results gives as : TOL= 9.999999974752427E-007

It's not called by other subroutines. so it is also a kind of loss of precision? did I get it wrong?

Thank you so much.

Jingfen Chen

0 Kudos
ZlamalJakub
New Contributor III
933 Views
You should use
TOL=1.0D-6 ! see D instead E

Jakub
0 Kudos
onkelhotte
New Contributor II
933 Views
You have to set

doubleVariable = 3742.37D0

in order to maintain the precision. With 3742.37 you set only the first 4 Bytes and the other 4 are random. Thats a common issue with IVF, so just add a D0 (zero, not the letter o) after your number.

Markus
0 Kudos
mecej4
Honored Contributor III
933 Views
"Thats a common issue with IVF..." -- correction: it is required by the Fortran Standard, and it is not specific to IVF.

That's what every compiler is supposed to do, and the topic of mixed precision and the related topic of mixed types are both covered well in the compiler documentation.
0 Kudos
TimP
Honored Contributor III
933 Views
No, when a single precision constant is assigned to a double precision variable, the value is the same as if it were assigned to a single precision variable (no random bytes). In many cases, including the one quoted, it's the nearest single precision value (which probably is not what is wanted).
0 Kudos
cjfunsw
Beginner
933 Views

hi, all,

thank you so much for your help. I change the "E" into "D" and it works. And i am also more clear about this problem.assign a value of the singl precision will also change the type of the variable even though i have already declare it as double precision. I got it.

Best Regards,
Jingfen

0 Kudos
ZlamalJakub
New Contributor III
933 Views
Double precision variable is not changed to single precision!!!

tol=1.0e-6

means

1. load to the mathematic coprocessor single precision value 1.0E-6
2. so on the coprocesssor appears something like 1.000000956446544 because single precision have only 6 decimal places and other digits are garbage
3. then put value on the coprocessor to the double precision variable tol
4. in the tol variable is 1.000000956446544

you can use also
tol=DBLE(1.0E-6)
first is single precision value converted to double and then assigned.

Jakub
0 Kudos
Reply