View previous topic :: View next topic |
Author |
Message |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2615 Location: Sydney
|
Posted: Tue Jan 18, 2011 12:44 am Post subject: Real*8 array move error |
|
|
Paul,
I recently re-introduced an error I had about 10 years ago. It still took me 2 days to find. The problem is if I want to move the contents of 1 vector to another vector, I introduced the following real*8 move routine: Code: | subroutine move_vector (vf, vt, neq)
integer*4 neq, k
real*8 vf(neq), vt(neq)
do k = 1,neq
vt(k) = vf(k)
end do
end subroutine move_vector
|
The problem not all the content of the vector is real*8, with the initial part being equivalenced to an integer*4 vector. The first two are : ivf(1) = 1 and ivf(2) = 47579.
Unfortunately vf(1) is reported as 0 and vt(1) becomes 0, with ivt(1) = 0 and ivt(2) = 0. The = appears to do a conversion to a valid real*8 number, rather than a simple 8-byte shift. This applies a real zero filter on the values.
I have now changed to Integer*4 vectors, as all bit formats are valid for Integer. Would Integer*8 be more efficient ?
Is this performance of the "=" with reals controlable? I tried a number of compiler options:
/p6 /opt
/opt
/debug
(default)
None appeared to have any effect on this.
If I replace the subroutine call with the array syntax:
! call Move_Vector (A, B, il)
B(1:il) = A(1:il)
Then this works without the real*8 zero filtering.
John |
|
Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8210 Location: Salford, UK
|
Posted: Tue Jan 18, 2011 10:01 am Post subject: |
|
|
John
I cannot look at this immediately but will put it on my list of things to do. |
|
Back to top |
|
 |
Sebastian
Joined: 20 Feb 2008 Posts: 177
|
Posted: Tue Jan 18, 2011 10:24 am Post subject: |
|
|
Quote: | Is this performance of the "=" with reals controlable? |
This is how the FPU works, not all bit combinations that you load into a register are preserved exactly when converting back, easiest example is the flush-to-zero functionality that rounds denormals to zero on load/on operation result.
Using integer*4 (twice) to move a real*8 should work if it is guaranteed that on all architectures integer*4 is 4 bytes long and real*8 occupies 8 bytes. |
|
Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8210 Location: Salford, UK
|
Posted: Wed Feb 16, 2011 11:36 am Post subject: |
|
|
The equals does indeed use floating point assembly instructions, dfld to load and dftp to store.
You might be able to get what you want by a clever use of the Fortran 90 intrinsic called TRANSFER. |
|
Back to top |
|
 |
|