]>
Commit | Line | Data |
---|---|---|
82a4f54c TB |
1 | ! { dg-do run } |
2 | ! { dg-add-options ieee } | |
d9f069ab | 3 | ! { dg-skip-if "PR libfortran/58015" { hppa*-*-hpux* } } |
82a4f54c TB |
4 | ! |
5 | ! PR fortran/35862 | |
6 | ! | |
7 | ! Test whether I/O rounding works. Uses internally (libgfortran) strtod | |
8 | ! for the conversion - and sets the CPU rounding mode accordingly. | |
9 | ! | |
13b670ac BE |
10 | ! Only few strtod implementations currently support rounding. Therefore |
11 | ! we use a heuristic to determine if the rounding support is available. | |
12 | ! The assumption is that if strtod gives *different* results for up/down | |
13 | ! rounding, then it will give *correct* results for nearest/zero/up/down | |
14 | ! rounding too. And that is what is effectively checked. | |
15 | ! | |
82a4f54c | 16 | ! If it doesn't work on your system, please check whether strtod handles |
13b670ac BE |
17 | ! rounding correctly and whether your system is supported in |
18 | ! libgfortran/config/fpu*.c | |
82a4f54c TB |
19 | ! |
20 | ! Please only add ... run { target { ! { triplets } } } if it is unfixable | |
13b670ac | 21 | ! on your target - and a note why (strtod has broken rounding support, etc.) |
82a4f54c TB |
22 | ! |
23 | program main | |
24 | use iso_fortran_env | |
25 | implicit none | |
26 | ||
27 | ! The following uses kinds=10 and 16 if available or | |
28 | ! 8 and 10 - or 8 and 16 - or 4 and 8. | |
29 | integer, parameter :: xp = real_kinds(ubound(real_kinds,dim=1)-1) | |
30 | integer, parameter :: qp = real_kinds(ubound(real_kinds,dim=1)) | |
31 | ||
32 | real(4) :: r4p, r4m, ref4u, ref4d | |
33 | real(8) :: r8p, r8m, ref8u, ref8d | |
34 | real(xp) :: r10p, r10m, ref10u, ref10d | |
35 | real(qp) :: r16p, r16m, ref16u, ref16d | |
36 | character(len=20) :: str, round | |
13b670ac BE |
37 | logical :: rnd4, rnd8, rnd10, rnd16 |
38 | ||
39 | ! Test for which types glibc's strtod function supports rounding | |
40 | str = '0.01 0.01 0.01 0.01' | |
41 | read (str, *, round='up') r4p, r8p, r10p, r16p | |
42 | read (str, *, round='down') r4m, r8m, r10m, r16m | |
43 | rnd4 = r4p /= r4m | |
44 | rnd8 = r8p /= r8m | |
45 | rnd10 = r10p /= r10m | |
46 | rnd16 = r16p /= r16m | |
47 | ! write (*, *) rnd4, rnd8, rnd10, rnd16 | |
82a4f54c TB |
48 | |
49 | ref4u = 0.100000001_4 | |
50 | ref8u = 0.10000000000000001_8 | |
51 | ||
52 | if (xp == 4) then | |
53 | ref10u = 0.100000001_xp | |
54 | elseif (xp == 8) then | |
55 | ref10u = 0.10000000000000001_xp | |
56 | else ! xp == 10 | |
57 | ref10u = 0.1000000000000000000014_xp | |
58 | end if | |
59 | ||
60 | if (qp == 8) then | |
61 | ref16u = 0.10000000000000001_qp | |
62 | elseif (qp == 10) then | |
63 | ref16u = 0.1000000000000000000014_qp | |
64 | else ! qp == 16 | |
65 | ref16u = 0.10000000000000000000000000000000000481_qp | |
66 | end if | |
67 | ||
68 | ! ref*d = 9.999999... | |
69 | ref4d = nearest (ref4u, -1.0_4) | |
70 | ref8d = nearest (ref8u, -1.0_8) | |
71 | ref10d = nearest (ref10u, -1.0_xp) | |
72 | ref16d = nearest (ref16u, -1.0_qp) | |
73 | ||
74 | round = 'up' | |
75 | call t() | |
13b670ac BE |
76 | if (rnd4 .and. (r4p /= ref4u .or. r4m /= -ref4d)) call abort() |
77 | if (rnd8 .and. (r8p /= ref8u .or. r8m /= -ref8d)) call abort() | |
78 | if (rnd10 .and. (r10p /= ref10u .or. r10m /= -ref10d)) call abort() | |
79 | if (rnd16 .and. (r16p /= ref16u .or. r16m /= -ref16d)) call abort() | |
82a4f54c TB |
80 | |
81 | round = 'down' | |
82 | call t() | |
13b670ac BE |
83 | if (rnd4 .and. (r4p /= ref4d .or. r4m /= -ref4u)) call abort() |
84 | if (rnd8 .and. (r8p /= ref8d .or. r8m /= -ref8u)) call abort() | |
85 | if (rnd10 .and. (r10p /= ref10d .or. r10m /= -ref10u)) call abort() | |
86 | if (rnd16 .and. (r16p /= ref16d .or. r16m /= -ref16u)) call abort() | |
82a4f54c TB |
87 | |
88 | round = 'zero' | |
89 | call t() | |
13b670ac BE |
90 | if (rnd4 .and. (r4p /= ref4d .or. r4m /= -ref4d)) call abort() |
91 | if (rnd8 .and. (r8p /= ref8d .or. r8m /= -ref8d)) call abort() | |
92 | if (rnd10 .and. (r10p /= ref10d .or. r10m /= -ref10d)) call abort() | |
93 | if (rnd16 .and. (r16p /= ref16d .or. r16m /= -ref16d)) call abort() | |
82a4f54c TB |
94 | |
95 | round = 'nearest' | |
96 | call t() | |
13b670ac BE |
97 | if (rnd4 .and. (r4p /= ref4u .or. r4m /= -ref4u)) call abort() |
98 | if (rnd8 .and. (r8p /= ref8u .or. r8m /= -ref8u)) call abort() | |
99 | if (rnd10 .and. (r10p /= ref10u .or. r10m /= -ref10u)) call abort() | |
100 | if (rnd16 .and. (r16p /= ref16u .or. r16m /= -ref16u)) call abort() | |
82a4f54c TB |
101 | |
102 | ! Same as nearest (but rounding towards zero if there is a tie | |
103 | ! [does not apply here]) | |
104 | round = 'compatible' | |
105 | call t() | |
13b670ac BE |
106 | if (rnd4 .and. (r4p /= ref4u .or. r4m /= -ref4u)) call abort() |
107 | if (rnd8 .and. (r8p /= ref8u .or. r8m /= -ref8u)) call abort() | |
108 | if (rnd10 .and. (r10p /= ref10u .or. r10m /= -ref10u)) call abort() | |
109 | if (rnd16 .and. (r16p /= ref16u .or. r16m /= -ref16u)) call abort() | |
82a4f54c TB |
110 | contains |
111 | subroutine t() | |
112 | ! print *, round | |
113 | str = "0.1 0.1 0.1 0.1" | |
114 | read (str, *,round=round) r4p, r8p, r10p, r16p | |
115 | ! write (*, '(*(g0:" "))') r4p, r8p, r10p, r16p | |
116 | str = "-0.1 -0.1 -0.1 -0.1" | |
117 | read (str, *,round=round) r4m, r8m, r10m, r16m | |
118 | ! write (*, *) r4m, r8m, r10m, r16m | |
119 | end subroutine t | |
120 | end program main |