Mail Archives: cygwin/2008/08/04/16:45:07
Dave Korn wrote:
> Take a look at the (legendary) GCC PR323:
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323
>
> ... and in particular comment #60:
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323#c60
>
> ... which has a bit of code you can adapt (google for the definition of
> _FPU_SETCW, it's an inline asm you can copy from linux/x86 headers); using
> that to set double precision mode in your thread startup code, and using
> double (never float) types throughout your code is probably the best you can
> do.
... and in Fortran?
I have flagged a similar problem on fortran list a few weeeks ago [1].
And obviously they pointed out the same solution [2,3].
Now rereading '...323#c60', this simple solution in F2003 comes in mind:
$ cat set_math_double_precision.c
/*
We cannot use
#include <fpu_control.h>
because Cygwin haven't that header. It can be downloaded from
http://boinc.gorlaeus.net/download/DownLoads/Classical/crlibm_libs/freebsd/includes/fpu_control.h
*/
#include "fpu_control.h"
void set_math_double_precision() {
fpu_control_t fpu_control = 0x027f ;
_FPU_SETCW(fpu_control);
}
$ cat test_case.f90
!
! gfortran -c set_math_double_precision.c
!
! (or gcc4 -c set_math_double_precision.c)
!
! gfortran test_case.f90 -o test_case set_math_double_precision.o
!
! See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323
! And also: http://cygwin.com/ml/cygwin/2008-08/msg00075.html,
! http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323#c60
!
module fpu95
interface
subroutine set_math_double_precision() &
bind(C,name='set_math_double_precision')
use, intrinsic :: iso_c_binding
end subroutine set_math_double_precision
end interface
end module fpu95
program test_case
use fpu95
implicit none
integer :: k
integer, parameter :: DP = kind(1.D0),&
N = 29
real(DP), parameter :: A(0:N) = &
(/1.0000000000000D0,3.8860009363293D0,7.4167881843083D0,&
9.8599837415463D0,10.431383465276D0,9.4077161304727D0,&
7.5332956276775D0,5.4995844630326D0,3.7275104474917D0,&
2.3766149078263D0,1.4394444941337D0,0.8344437543616D0,&
0.4657058294147D0,0.2514185849207D0,0.1317920740387D0,&
0.0672995854816D0,0.0335554996094D0,0.0163785206816D0,&
0.0078368645385D0,0.0036846299276D0,0.0017020281304D0,&
0.0007756352209D0,0.0003469750783D0,0.0001544224626D0,&
0.0000666379875D0,0.0000295655909D0,0.0000118821415D0,&
0.0000057747681D0,0.0000017502652D0,0.0000014682034D0/)
real(DP), parameter :: BB(0:N-1) = &
(/(((k+2)*A(k+2)-A(k+1)*(A(1)+(k+1))),k = 0,N-2),&
(-A(N)*(A(1)+N))/)
real(DP) :: b(0:N-1),bbb(0:N-1)
call set_math_double_precision()
do k = 0,N-2
b(k) = (k+2)*A(k+2)-A(k+1)*(A(1)+(k+1))
enddo
b(N-1) = -A(N)*(A(1)+N)
bbb(0:N-1) = (/(((k+2)*A(k+2)-A(k+1)*(A(1)+(k+1))),k = 0,N-2),&
(-A(N)*(A(1)+N))/)
do k = 0,N-1
print *, k,b(k)-BB(k),b(k)-bbb(k),BB(k)-bbb(k)
enddo
end program test_case
$ gfortran -c set_math_double_precision.c
$ gfortran test_case.f90 -o test_case set_math_double_precision.o
Running './test_case' it prints all zeroes!
Cheers,
Angelo.
---
[1] http://gcc.gnu.org/ml/fortran/2008-06/msg00065.html
[2] http://gcc.gnu.org/ml/fortran/2008-06/msg00118.html
[3] http://gcc.gnu.org/ml/fortran/2008-06/msg00119.html
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Problem reports: http://cygwin.com/problems.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/
- Raw text -