]> gcc.gnu.org Git - gcc.git/blame - libgfortran/ieee/ieee_exceptions.F90
Update copyright years.
[gcc.git] / libgfortran / ieee / ieee_exceptions.F90
CommitLineData
8b198102 1! Implementation of the IEEE_EXCEPTIONS standard intrinsic module
83ffe9cd 2! Copyright (C) 2013-2023 Free Software Foundation, Inc.
8b198102
FXC
3! Contributed by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
4!
5! This file is part of the GNU Fortran runtime library (libgfortran).
6!
7! Libgfortran is free software; you can redistribute it and/or
8! modify it under the terms of the GNU General Public
9! License as published by the Free Software Foundation; either
10! version 3 of the License, or (at your option) any later version.
11!
12! Libgfortran is distributed in the hope that it will be useful,
13! but WITHOUT ANY WARRANTY; without even the implied warranty of
14! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15! GNU General Public License for more details.
16!
17! Under Section 7 of GPL version 3, you are granted additional
18! permissions described in the GCC Runtime Library Exception, version
19! 3.1, as published by the Free Software Foundation.
20!
21! You should have received a copy of the GNU General Public License and
22! a copy of the GCC Runtime Library Exception along with this program;
23! see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24! <http://www.gnu.org/licenses/>. */
25
26#include "config.h"
27#include "kinds.inc"
28#include "c99_protos.inc"
29#include "fpu-target.inc"
30
31module IEEE_EXCEPTIONS
32
33 implicit none
34 private
35
36! Derived types and named constants
37
38 type, public :: IEEE_FLAG_TYPE
39 private
40 integer :: hidden
41 end type
42
43 type(IEEE_FLAG_TYPE), parameter, public :: &
44 IEEE_INVALID = IEEE_FLAG_TYPE(GFC_FPE_INVALID), &
45 IEEE_OVERFLOW = IEEE_FLAG_TYPE(GFC_FPE_OVERFLOW), &
46 IEEE_DIVIDE_BY_ZERO = IEEE_FLAG_TYPE(GFC_FPE_ZERO), &
47 IEEE_UNDERFLOW = IEEE_FLAG_TYPE(GFC_FPE_UNDERFLOW), &
48 IEEE_INEXACT = IEEE_FLAG_TYPE(GFC_FPE_INEXACT)
49
50 type(IEEE_FLAG_TYPE), parameter, public :: &
51 IEEE_USUAL(3) = [ IEEE_OVERFLOW, IEEE_DIVIDE_BY_ZERO, IEEE_INVALID ], &
52 IEEE_ALL(5) = [ IEEE_USUAL, IEEE_UNDERFLOW, IEEE_INEXACT ]
53
54 type, public :: IEEE_STATUS_TYPE
55 private
56 character(len=GFC_FPE_STATE_BUFFER_SIZE) :: hidden
57 end type
58
de40fab2
FXC
59 type, public :: IEEE_MODES_TYPE
60 private
61 integer :: rounding
62 integer :: underflow
63 integer :: halting
64 end type
65
8b198102 66 interface IEEE_SUPPORT_FLAG
22a49988
FXC
67 module procedure IEEE_SUPPORT_FLAG_4, &
68 IEEE_SUPPORT_FLAG_8, &
69#ifdef HAVE_GFC_REAL_10
70 IEEE_SUPPORT_FLAG_10, &
71#endif
72#ifdef HAVE_GFC_REAL_16
73 IEEE_SUPPORT_FLAG_16, &
74#endif
75 IEEE_SUPPORT_FLAG_NOARG
8b198102
FXC
76 end interface IEEE_SUPPORT_FLAG
77
78 public :: IEEE_SUPPORT_FLAG, IEEE_SUPPORT_HALTING
79 public :: IEEE_SET_HALTING_MODE, IEEE_GET_HALTING_MODE
80 public :: IEEE_SET_FLAG, IEEE_GET_FLAG
81 public :: IEEE_SET_STATUS, IEEE_GET_STATUS
de40fab2 82 public :: IEEE_SET_MODES, IEEE_GET_MODES
8b198102
FXC
83
84contains
85
de40fab2
FXC
86! Fortran 2018: Saving and restoring floating-point modes
87! (rounding modes, underflow mode, and halting mode)
88!
89! For now, we only have one rounding mode for all kinds.
90! Some targets could optimize getting/setting all modes at once, but for now
91! we make three calls. This code must be kept in sync with:
92! - IEEE_{GET,SET}_ROUNDING_MODE
93! - IEEE_{GET,SET}_UNDERFLOW_MODE
94! - IEEE_{GET,SET}_HALTING_MODE
95
96 subroutine IEEE_GET_MODES (MODES)
97 implicit none
98 type(IEEE_MODES_TYPE), intent(out) :: MODES
99
100 interface
101 integer function helper_rounding() &
102 bind(c, name="_gfortrani_get_fpu_rounding_mode")
103 end function
104 integer function helper_underflow() &
105 bind(c, name="_gfortrani_get_fpu_underflow_mode")
106 end function
107 pure integer function helper_halting() &
108 bind(c, name="_gfortrani_get_fpu_trap_exceptions")
109 end function
110 end interface
111
112 MODES%rounding = helper_rounding()
113 MODES%underflow = helper_underflow()
114 MODES%halting = helper_halting()
115 end subroutine
116
117 subroutine IEEE_SET_MODES (MODES)
118 implicit none
119 type(IEEE_MODES_TYPE), intent(in) :: MODES
120
121 interface
122 subroutine helper_rounding(val) &
123 bind(c, name="_gfortrani_set_fpu_rounding_mode")
124 integer, value :: val
125 end subroutine
126 subroutine helper_underflow(val) &
127 bind(c, name="_gfortrani_set_fpu_underflow_mode")
128 integer, value :: val
129 end subroutine
130 pure subroutine helper_halting(trap, notrap) &
131 bind(c, name="_gfortrani_set_fpu_trap_exceptions")
132 integer, intent(in), value :: trap, notrap
133 end subroutine
134 end interface
135
136 call helper_rounding(MODES%rounding)
137 call helper_underflow(MODES%underflow)
138 call helper_halting(MODES%halting, NOT(MODES%halting))
139 end subroutine
140
8b198102
FXC
141! Saving and restoring floating-point status
142
143 subroutine IEEE_GET_STATUS (STATUS_VALUE)
144 implicit none
145 type(IEEE_STATUS_TYPE), intent(out) :: STATUS_VALUE
146
147 interface
148 subroutine helper(ptr) &
149 bind(c, name="_gfortrani_get_fpu_state")
150 use, intrinsic :: iso_c_binding, only : c_char
151 character(kind=c_char) :: ptr(*)
152 end subroutine
153 end interface
154
155 call helper(STATUS_VALUE%hidden)
156 end subroutine
157
158 subroutine IEEE_SET_STATUS (STATUS_VALUE)
159 implicit none
160 type(IEEE_STATUS_TYPE), intent(in) :: STATUS_VALUE
161
162 interface
163 subroutine helper(ptr) &
164 bind(c, name="_gfortrani_set_fpu_state")
165 use, intrinsic :: iso_c_binding, only : c_char
166 character(kind=c_char) :: ptr(*)
167 end subroutine
168 end interface
169
170 call helper(STATUS_VALUE%hidden)
171 end subroutine
172
173! Getting and setting flags
174
175 elemental subroutine IEEE_GET_FLAG (FLAG, FLAG_VALUE)
176 implicit none
177 type(IEEE_FLAG_TYPE), intent(in) :: FLAG
178 logical, intent(out) :: FLAG_VALUE
179
180 interface
181 pure integer function helper() &
182 bind(c, name="_gfortrani_get_fpu_except_flags")
183 end function
184 end interface
185
186 FLAG_VALUE = (IAND(helper(), FLAG%hidden) /= 0)
187 end subroutine
188
189 elemental subroutine IEEE_SET_FLAG (FLAG, FLAG_VALUE)
190 implicit none
191 type(IEEE_FLAG_TYPE), intent(in) :: FLAG
192 logical, intent(in) :: FLAG_VALUE
193
194 interface
195 pure subroutine helper(set, clear) &
196 bind(c, name="_gfortrani_set_fpu_except_flags")
197 integer, intent(in), value :: set, clear
198 end subroutine
199 end interface
200
201 if (FLAG_VALUE) then
202 call helper(FLAG%hidden, 0)
203 else
204 call helper(0, FLAG%hidden)
205 end if
206 end subroutine
207
208! Querying and changing the halting mode
209
210 elemental subroutine IEEE_GET_HALTING_MODE (FLAG, HALTING)
211 implicit none
212 type(IEEE_FLAG_TYPE), intent(in) :: FLAG
213 logical, intent(out) :: HALTING
214
215 interface
216 pure integer function helper() &
217 bind(c, name="_gfortrani_get_fpu_trap_exceptions")
218 end function
219 end interface
220
221 HALTING = (IAND(helper(), FLAG%hidden) /= 0)
222 end subroutine
223
224 elemental subroutine IEEE_SET_HALTING_MODE (FLAG, HALTING)
225 implicit none
226 type(IEEE_FLAG_TYPE), intent(in) :: FLAG
227 logical, intent(in) :: HALTING
228
229 interface
230 pure subroutine helper(trap, notrap) &
231 bind(c, name="_gfortrani_set_fpu_trap_exceptions")
232 integer, intent(in), value :: trap, notrap
233 end subroutine
234 end interface
235
236 if (HALTING) then
237 call helper(FLAG%hidden, 0)
238 else
239 call helper(0, FLAG%hidden)
240 end if
241 end subroutine
242
243! Querying support
244
245 pure logical function IEEE_SUPPORT_HALTING (FLAG)
246 implicit none
247 type(IEEE_FLAG_TYPE), intent(in) :: FLAG
248
249 interface
250 pure integer function helper(flag) &
251 bind(c, name="_gfortrani_support_fpu_trap")
252 integer, intent(in), value :: flag
253 end function
254 end interface
255
256 IEEE_SUPPORT_HALTING = (helper(FLAG%hidden) /= 0)
257 end function
258
259 pure logical function IEEE_SUPPORT_FLAG_NOARG (FLAG)
260 implicit none
261 type(IEEE_FLAG_TYPE), intent(in) :: FLAG
262
263 interface
264 pure integer function helper(flag) &
265 bind(c, name="_gfortrani_support_fpu_flag")
266 integer, intent(in), value :: flag
267 end function
268 end interface
269
270 IEEE_SUPPORT_FLAG_NOARG = (helper(FLAG%hidden) /= 0)
271 end function
272
273 pure logical function IEEE_SUPPORT_FLAG_4 (FLAG, X) result(res)
274 implicit none
275 type(IEEE_FLAG_TYPE), intent(in) :: FLAG
276 real(kind=4), intent(in) :: X
277 res = IEEE_SUPPORT_FLAG_NOARG(FLAG)
278 end function
279
280 pure logical function IEEE_SUPPORT_FLAG_8 (FLAG, X) result(res)
281 implicit none
282 type(IEEE_FLAG_TYPE), intent(in) :: FLAG
283 real(kind=8), intent(in) :: X
284 res = IEEE_SUPPORT_FLAG_NOARG(FLAG)
285 end function
286
22a49988
FXC
287#ifdef HAVE_GFC_REAL_10
288 pure logical function IEEE_SUPPORT_FLAG_10 (FLAG, X) result(res)
289 implicit none
290 type(IEEE_FLAG_TYPE), intent(in) :: FLAG
291 real(kind=10), intent(in) :: X
292 res = IEEE_SUPPORT_FLAG_NOARG(FLAG)
293 end function
294#endif
295
296#ifdef HAVE_GFC_REAL_16
297 pure logical function IEEE_SUPPORT_FLAG_16 (FLAG, X) result(res)
298 implicit none
299 type(IEEE_FLAG_TYPE), intent(in) :: FLAG
300 real(kind=16), intent(in) :: X
301 res = IEEE_SUPPORT_FLAG_NOARG(FLAG)
302 end function
303#endif
304
8b198102 305end module IEEE_EXCEPTIONS
This page took 0.811373 seconds and 5 git commands to generate.