ieee_arithmetic.F90 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. ! Implementation of the IEEE_ARITHMETIC standard intrinsic module
  2. ! Copyright (C) 2013-2015 Free Software Foundation, Inc.
  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. #include "config.h"
  26. #include "kinds.inc"
  27. #include "c99_protos.inc"
  28. #include "fpu-target.inc"
  29. module IEEE_ARITHMETIC
  30. use IEEE_EXCEPTIONS
  31. implicit none
  32. private
  33. ! Every public symbol from IEEE_EXCEPTIONS must be made public here
  34. public :: IEEE_FLAG_TYPE, IEEE_INVALID, IEEE_OVERFLOW, &
  35. IEEE_DIVIDE_BY_ZERO, IEEE_UNDERFLOW, IEEE_INEXACT, IEEE_USUAL, &
  36. IEEE_ALL, IEEE_STATUS_TYPE, IEEE_GET_FLAG, IEEE_GET_HALTING_MODE, &
  37. IEEE_GET_STATUS, IEEE_SET_FLAG, IEEE_SET_HALTING_MODE, &
  38. IEEE_SET_STATUS, IEEE_SUPPORT_FLAG, IEEE_SUPPORT_HALTING
  39. ! Derived types and named constants
  40. type, public :: IEEE_CLASS_TYPE
  41. private
  42. integer :: hidden
  43. end type
  44. type(IEEE_CLASS_TYPE), parameter, public :: &
  45. IEEE_OTHER_VALUE = IEEE_CLASS_TYPE(0), &
  46. IEEE_SIGNALING_NAN = IEEE_CLASS_TYPE(1), &
  47. IEEE_QUIET_NAN = IEEE_CLASS_TYPE(2), &
  48. IEEE_NEGATIVE_INF = IEEE_CLASS_TYPE(3), &
  49. IEEE_NEGATIVE_NORMAL = IEEE_CLASS_TYPE(4), &
  50. IEEE_NEGATIVE_DENORMAL = IEEE_CLASS_TYPE(5), &
  51. IEEE_NEGATIVE_ZERO = IEEE_CLASS_TYPE(6), &
  52. IEEE_POSITIVE_ZERO = IEEE_CLASS_TYPE(7), &
  53. IEEE_POSITIVE_DENORMAL = IEEE_CLASS_TYPE(8), &
  54. IEEE_POSITIVE_NORMAL = IEEE_CLASS_TYPE(9), &
  55. IEEE_POSITIVE_INF = IEEE_CLASS_TYPE(10)
  56. type, public :: IEEE_ROUND_TYPE
  57. private
  58. integer :: hidden
  59. end type
  60. type(IEEE_ROUND_TYPE), parameter, public :: &
  61. IEEE_NEAREST = IEEE_ROUND_TYPE(GFC_FPE_TONEAREST), &
  62. IEEE_TO_ZERO = IEEE_ROUND_TYPE(GFC_FPE_TOWARDZERO), &
  63. IEEE_UP = IEEE_ROUND_TYPE(GFC_FPE_UPWARD), &
  64. IEEE_DOWN = IEEE_ROUND_TYPE(GFC_FPE_DOWNWARD), &
  65. IEEE_OTHER = IEEE_ROUND_TYPE(0)
  66. ! Equality operators on the derived types
  67. interface operator (==)
  68. module procedure IEEE_CLASS_TYPE_EQ, IEEE_ROUND_TYPE_EQ
  69. end interface
  70. public :: operator(==)
  71. interface operator (/=)
  72. module procedure IEEE_CLASS_TYPE_NE, IEEE_ROUND_TYPE_NE
  73. end interface
  74. public :: operator (/=)
  75. ! IEEE_IS_FINITE
  76. interface
  77. elemental logical function _gfortran_ieee_is_finite_4(X)
  78. real(kind=4), intent(in) :: X
  79. end function
  80. elemental logical function _gfortran_ieee_is_finite_8(X)
  81. real(kind=8), intent(in) :: X
  82. end function
  83. end interface
  84. interface IEEE_IS_FINITE
  85. procedure _gfortran_ieee_is_finite_4, _gfortran_ieee_is_finite_8
  86. end interface
  87. public :: IEEE_IS_FINITE
  88. ! IEEE_IS_NAN
  89. interface
  90. elemental logical function _gfortran_ieee_is_nan_4(X)
  91. real(kind=4), intent(in) :: X
  92. end function
  93. elemental logical function _gfortran_ieee_is_nan_8(X)
  94. real(kind=8), intent(in) :: X
  95. end function
  96. end interface
  97. interface IEEE_IS_NAN
  98. procedure _gfortran_ieee_is_nan_4, _gfortran_ieee_is_nan_8
  99. end interface
  100. public :: IEEE_IS_NAN
  101. ! IEEE_IS_NEGATIVE
  102. interface
  103. elemental logical function _gfortran_ieee_is_negative_4(X)
  104. real(kind=4), intent(in) :: X
  105. end function
  106. elemental logical function _gfortran_ieee_is_negative_8(X)
  107. real(kind=8), intent(in) :: X
  108. end function
  109. end interface
  110. interface IEEE_IS_NEGATIVE
  111. procedure _gfortran_ieee_is_negative_4, _gfortran_ieee_is_negative_8
  112. end interface
  113. public :: IEEE_IS_NEGATIVE
  114. ! IEEE_IS_NORMAL
  115. interface
  116. elemental logical function _gfortran_ieee_is_normal_4(X)
  117. real(kind=4), intent(in) :: X
  118. end function
  119. elemental logical function _gfortran_ieee_is_normal_8(X)
  120. real(kind=8), intent(in) :: X
  121. end function
  122. end interface
  123. interface IEEE_IS_NORMAL
  124. procedure _gfortran_ieee_is_normal_4, _gfortran_ieee_is_normal_8
  125. end interface
  126. public :: IEEE_IS_NORMAL
  127. ! IEEE_COPY_SIGN
  128. interface
  129. elemental real(kind=4) function _gfortran_ieee_copy_sign_4_4 (X,Y)
  130. real(kind=4), intent(in) :: X
  131. real(kind=4), intent(in) :: Y
  132. end function
  133. elemental real(kind=4) function _gfortran_ieee_copy_sign_4_8 (X,Y)
  134. real(kind=4), intent(in) :: X
  135. real(kind=8), intent(in) :: Y
  136. end function
  137. elemental real(kind=8) function _gfortran_ieee_copy_sign_8_4 (X,Y)
  138. real(kind=8), intent(in) :: X
  139. real(kind=4), intent(in) :: Y
  140. end function
  141. elemental real(kind=8) function _gfortran_ieee_copy_sign_8_8 (X,Y)
  142. real(kind=8), intent(in) :: X
  143. real(kind=8), intent(in) :: Y
  144. end function
  145. end interface
  146. interface IEEE_COPY_SIGN
  147. procedure _gfortran_ieee_copy_sign_4_4, _gfortran_ieee_copy_sign_4_8, &
  148. _gfortran_ieee_copy_sign_8_4, _gfortran_ieee_copy_sign_8_8
  149. end interface
  150. public :: IEEE_COPY_SIGN
  151. ! IEEE_UNORDERED
  152. interface
  153. elemental logical function _gfortran_ieee_unordered_4_4 (X,Y)
  154. real(kind=4), intent(in) :: X
  155. real(kind=4), intent(in) :: Y
  156. end function
  157. elemental logical function _gfortran_ieee_unordered_4_8 (X,Y)
  158. real(kind=4), intent(in) :: X
  159. real(kind=8), intent(in) :: Y
  160. end function
  161. elemental logical function _gfortran_ieee_unordered_8_4 (X,Y)
  162. real(kind=8), intent(in) :: X
  163. real(kind=4), intent(in) :: Y
  164. end function
  165. elemental logical function _gfortran_ieee_unordered_8_8 (X,Y)
  166. real(kind=8), intent(in) :: X
  167. real(kind=8), intent(in) :: Y
  168. end function
  169. end interface
  170. interface IEEE_UNORDERED
  171. procedure _gfortran_ieee_unordered_4_4, _gfortran_ieee_unordered_4_8, &
  172. _gfortran_ieee_unordered_8_4, _gfortran_ieee_unordered_8_8
  173. end interface
  174. public :: IEEE_UNORDERED
  175. ! IEEE_LOGB
  176. interface
  177. elemental real(kind=4) function _gfortran_ieee_logb_4 (X)
  178. real(kind=4), intent(in) :: X
  179. end function
  180. elemental real(kind=8) function _gfortran_ieee_logb_8 (X)
  181. real(kind=8), intent(in) :: X
  182. end function
  183. end interface
  184. interface IEEE_LOGB
  185. procedure _gfortran_ieee_logb_4, _gfortran_ieee_logb_8
  186. end interface
  187. public :: IEEE_LOGB
  188. ! IEEE_NEXT_AFTER
  189. interface
  190. elemental real(kind=4) function _gfortran_ieee_next_after_4_4 (X, Y)
  191. real(kind=4), intent(in) :: X
  192. real(kind=4), intent(in) :: Y
  193. end function
  194. elemental real(kind=4) function _gfortran_ieee_next_after_4_8 (X, Y)
  195. real(kind=4), intent(in) :: X
  196. real(kind=8), intent(in) :: Y
  197. end function
  198. elemental real(kind=8) function _gfortran_ieee_next_after_8_4 (X, Y)
  199. real(kind=8), intent(in) :: X
  200. real(kind=4), intent(in) :: Y
  201. end function
  202. elemental real(kind=8) function _gfortran_ieee_next_after_8_8 (X, Y)
  203. real(kind=8), intent(in) :: X
  204. real(kind=8), intent(in) :: Y
  205. end function
  206. end interface
  207. interface IEEE_NEXT_AFTER
  208. procedure _gfortran_ieee_next_after_4_4, _gfortran_ieee_next_after_4_8, &
  209. _gfortran_ieee_next_after_8_4, _gfortran_ieee_next_after_8_8
  210. end interface
  211. public :: IEEE_NEXT_AFTER
  212. ! IEEE_REM
  213. interface
  214. elemental real(kind=4) function _gfortran_ieee_rem_4_4 (X, Y)
  215. real(kind=4), intent(in) :: X
  216. real(kind=4), intent(in) :: Y
  217. end function
  218. elemental real(kind=8) function _gfortran_ieee_rem_4_8 (X, Y)
  219. real(kind=4), intent(in) :: X
  220. real(kind=8), intent(in) :: Y
  221. end function
  222. elemental real(kind=8) function _gfortran_ieee_rem_8_4 (X, Y)
  223. real(kind=8), intent(in) :: X
  224. real(kind=4), intent(in) :: Y
  225. end function
  226. elemental real(kind=8) function _gfortran_ieee_rem_8_8 (X, Y)
  227. real(kind=8), intent(in) :: X
  228. real(kind=8), intent(in) :: Y
  229. end function
  230. end interface
  231. interface IEEE_REM
  232. procedure _gfortran_ieee_rem_4_4, _gfortran_ieee_rem_4_8, &
  233. _gfortran_ieee_rem_8_4, _gfortran_ieee_rem_8_8
  234. end interface
  235. public :: IEEE_REM
  236. ! IEEE_RINT
  237. interface
  238. elemental real(kind=4) function _gfortran_ieee_rint_4 (X)
  239. real(kind=4), intent(in) :: X
  240. end function
  241. elemental real(kind=8) function _gfortran_ieee_rint_8 (X)
  242. real(kind=8), intent(in) :: X
  243. end function
  244. end interface
  245. interface IEEE_RINT
  246. procedure _gfortran_ieee_rint_4, _gfortran_ieee_rint_8
  247. end interface
  248. public :: IEEE_RINT
  249. ! IEEE_SCALB
  250. interface
  251. elemental real(kind=4) function _gfortran_ieee_scalb_4 (X, I)
  252. real(kind=4), intent(in) :: X
  253. integer, intent(in) :: I
  254. end function
  255. elemental real(kind=8) function _gfortran_ieee_scalb_8 (X, I)
  256. real(kind=8), intent(in) :: X
  257. integer, intent(in) :: I
  258. end function
  259. end interface
  260. interface IEEE_SCALB
  261. procedure _gfortran_ieee_scalb_4, _gfortran_ieee_scalb_8
  262. end interface
  263. public :: IEEE_SCALB
  264. ! IEEE_VALUE
  265. interface IEEE_VALUE
  266. module procedure IEEE_VALUE_4, IEEE_VALUE_8
  267. end interface
  268. public :: IEEE_VALUE
  269. ! IEEE_CLASS
  270. interface IEEE_CLASS
  271. module procedure IEEE_CLASS_4, IEEE_CLASS_8
  272. end interface
  273. public :: IEEE_CLASS
  274. ! Public declarations for contained procedures
  275. public :: IEEE_GET_ROUNDING_MODE, IEEE_SET_ROUNDING_MODE
  276. public :: IEEE_GET_UNDERFLOW_MODE, IEEE_SET_UNDERFLOW_MODE
  277. public :: IEEE_SELECTED_REAL_KIND
  278. ! IEEE_SUPPORT_ROUNDING
  279. interface IEEE_SUPPORT_ROUNDING
  280. module procedure IEEE_SUPPORT_ROUNDING_4, IEEE_SUPPORT_ROUNDING_8, &
  281. #ifdef HAVE_GFC_REAL_10
  282. IEEE_SUPPORT_ROUNDING_10, &
  283. #endif
  284. #ifdef HAVE_GFC_REAL_16
  285. IEEE_SUPPORT_ROUNDING_16, &
  286. #endif
  287. IEEE_SUPPORT_ROUNDING_NOARG
  288. end interface
  289. public :: IEEE_SUPPORT_ROUNDING
  290. ! Interface to the FPU-specific function
  291. interface
  292. pure integer function support_rounding_helper(flag) &
  293. bind(c, name="_gfortrani_support_fpu_rounding_mode")
  294. integer, intent(in), value :: flag
  295. end function
  296. end interface
  297. ! IEEE_SUPPORT_UNDERFLOW_CONTROL
  298. interface IEEE_SUPPORT_UNDERFLOW_CONTROL
  299. module procedure IEEE_SUPPORT_UNDERFLOW_CONTROL_4, &
  300. IEEE_SUPPORT_UNDERFLOW_CONTROL_8, &
  301. #ifdef HAVE_GFC_REAL_10
  302. IEEE_SUPPORT_UNDERFLOW_CONTROL_10, &
  303. #endif
  304. #ifdef HAVE_GFC_REAL_16
  305. IEEE_SUPPORT_UNDERFLOW_CONTROL_16, &
  306. #endif
  307. IEEE_SUPPORT_UNDERFLOW_CONTROL_NOARG
  308. end interface
  309. public :: IEEE_SUPPORT_UNDERFLOW_CONTROL
  310. ! Interface to the FPU-specific function
  311. interface
  312. pure integer function support_underflow_control_helper(kind) &
  313. bind(c, name="_gfortrani_support_fpu_underflow_control")
  314. integer, intent(in), value :: kind
  315. end function
  316. end interface
  317. ! IEEE_SUPPORT_* generic functions
  318. #if defined(HAVE_GFC_REAL_10) && defined(HAVE_GFC_REAL_16)
  319. # define MACRO1(NAME) NAME/**/_4, NAME/**/_8, NAME/**/_10, NAME/**/_16, NAME/**/_NOARG
  320. #elif defined(HAVE_GFC_REAL_10)
  321. # define MACRO1(NAME) NAME/**/_4, NAME/**/_8, NAME/**/_10, NAME/**/_NOARG
  322. #elif defined(HAVE_GFC_REAL_16)
  323. # define MACRO1(NAME) NAME/**/_4, NAME/**/_8, NAME/**/_16, NAME/**/_NOARG
  324. #else
  325. # define MACRO1(NAME) NAME/**/_4, NAME/**/_8, NAME/**/_NOARG
  326. #endif
  327. #define SUPPORTGENERIC(NAME) \
  328. interface NAME ; module procedure MACRO1(NAME) ; end interface ; \
  329. public :: NAME
  330. SUPPORTGENERIC(IEEE_SUPPORT_DATATYPE)
  331. SUPPORTGENERIC(IEEE_SUPPORT_DENORMAL)
  332. SUPPORTGENERIC(IEEE_SUPPORT_DIVIDE)
  333. SUPPORTGENERIC(IEEE_SUPPORT_INF)
  334. SUPPORTGENERIC(IEEE_SUPPORT_IO)
  335. SUPPORTGENERIC(IEEE_SUPPORT_NAN)
  336. SUPPORTGENERIC(IEEE_SUPPORT_SQRT)
  337. SUPPORTGENERIC(IEEE_SUPPORT_STANDARD)
  338. contains
  339. ! Equality operators for IEEE_CLASS_TYPE and IEEE_ROUNDING_MODE
  340. elemental logical function IEEE_CLASS_TYPE_EQ (X, Y) result(res)
  341. implicit none
  342. type(IEEE_CLASS_TYPE), intent(in) :: X, Y
  343. res = (X%hidden == Y%hidden)
  344. end function
  345. elemental logical function IEEE_CLASS_TYPE_NE (X, Y) result(res)
  346. implicit none
  347. type(IEEE_CLASS_TYPE), intent(in) :: X, Y
  348. res = (X%hidden /= Y%hidden)
  349. end function
  350. elemental logical function IEEE_ROUND_TYPE_EQ (X, Y) result(res)
  351. implicit none
  352. type(IEEE_ROUND_TYPE), intent(in) :: X, Y
  353. res = (X%hidden == Y%hidden)
  354. end function
  355. elemental logical function IEEE_ROUND_TYPE_NE (X, Y) result(res)
  356. implicit none
  357. type(IEEE_ROUND_TYPE), intent(in) :: X, Y
  358. res = (X%hidden /= Y%hidden)
  359. end function
  360. ! IEEE_SELECTED_REAL_KIND
  361. integer function IEEE_SELECTED_REAL_KIND (P, R, RADIX) result(res)
  362. implicit none
  363. integer, intent(in), optional :: P, R, RADIX
  364. integer :: p2, r2
  365. p2 = 0 ; r2 = 0
  366. if (present(p)) p2 = p
  367. if (present(r)) r2 = r
  368. ! The only IEEE types we support right now are binary
  369. if (present(radix)) then
  370. if (radix /= 2) then
  371. res = -5
  372. return
  373. endif
  374. endif
  375. ! Does IEEE float fit?
  376. if (precision(0.) >= p2 .and. range(0.) >= r2) then
  377. res = kind(0.)
  378. return
  379. endif
  380. ! Does IEEE double fit?
  381. if (precision(0.d0) >= p2 .and. range(0.d0) >= r2) then
  382. res = kind(0.d0)
  383. return
  384. endif
  385. if (precision(0.d0) < p2 .and. range(0.d0) < r2) then
  386. res = -3
  387. return
  388. endif
  389. if (precision(0.d0) < p2) then
  390. res = -1
  391. return
  392. endif
  393. res = -2
  394. end function
  395. ! IEEE_CLASS
  396. elemental function IEEE_CLASS_4 (X) result(res)
  397. implicit none
  398. real(kind=4), intent(in) :: X
  399. type(IEEE_CLASS_TYPE) :: res
  400. interface
  401. pure integer function _gfortrani_ieee_class_helper_4(val)
  402. real(kind=4), intent(in) :: val
  403. end function
  404. end interface
  405. res = IEEE_CLASS_TYPE(_gfortrani_ieee_class_helper_4(X))
  406. end function
  407. elemental function IEEE_CLASS_8 (X) result(res)
  408. implicit none
  409. real(kind=8), intent(in) :: X
  410. type(IEEE_CLASS_TYPE) :: res
  411. interface
  412. pure integer function _gfortrani_ieee_class_helper_8(val)
  413. real(kind=8), intent(in) :: val
  414. end function
  415. end interface
  416. res = IEEE_CLASS_TYPE(_gfortrani_ieee_class_helper_8(X))
  417. end function
  418. ! IEEE_VALUE
  419. elemental real(kind=4) function IEEE_VALUE_4(X, C) result(res)
  420. implicit none
  421. real(kind=4), intent(in) :: X
  422. type(IEEE_CLASS_TYPE), intent(in) :: C
  423. select case (C%hidden)
  424. case (1) ! IEEE_SIGNALING_NAN
  425. res = -1
  426. res = sqrt(res)
  427. case (2) ! IEEE_QUIET_NAN
  428. res = -1
  429. res = sqrt(res)
  430. case (3) ! IEEE_NEGATIVE_INF
  431. res = huge(res)
  432. res = (-res) * res
  433. case (4) ! IEEE_NEGATIVE_NORMAL
  434. res = -42
  435. case (5) ! IEEE_NEGATIVE_DENORMAL
  436. res = -tiny(res)
  437. res = res / 2
  438. case (6) ! IEEE_NEGATIVE_ZERO
  439. res = 0
  440. res = -res
  441. case (7) ! IEEE_POSITIVE_ZERO
  442. res = 0
  443. case (8) ! IEEE_POSITIVE_DENORMAL
  444. res = tiny(res)
  445. res = res / 2
  446. case (9) ! IEEE_POSITIVE_NORMAL
  447. res = 42
  448. case (10) ! IEEE_POSITIVE_INF
  449. res = huge(res)
  450. res = res * res
  451. case default ! IEEE_OTHER_VALUE, should not happen
  452. res = 0
  453. end select
  454. end function
  455. elemental real(kind=8) function IEEE_VALUE_8(X, C) result(res)
  456. implicit none
  457. real(kind=8), intent(in) :: X
  458. type(IEEE_CLASS_TYPE), intent(in) :: C
  459. select case (C%hidden)
  460. case (1) ! IEEE_SIGNALING_NAN
  461. res = -1
  462. res = sqrt(res)
  463. case (2) ! IEEE_QUIET_NAN
  464. res = -1
  465. res = sqrt(res)
  466. case (3) ! IEEE_NEGATIVE_INF
  467. res = huge(res)
  468. res = (-res) * res
  469. case (4) ! IEEE_NEGATIVE_NORMAL
  470. res = -42
  471. case (5) ! IEEE_NEGATIVE_DENORMAL
  472. res = -tiny(res)
  473. res = res / 2
  474. case (6) ! IEEE_NEGATIVE_ZERO
  475. res = 0
  476. res = -res
  477. case (7) ! IEEE_POSITIVE_ZERO
  478. res = 0
  479. case (8) ! IEEE_POSITIVE_DENORMAL
  480. res = tiny(res)
  481. res = res / 2
  482. case (9) ! IEEE_POSITIVE_NORMAL
  483. res = 42
  484. case (10) ! IEEE_POSITIVE_INF
  485. res = huge(res)
  486. res = res * res
  487. case default ! IEEE_OTHER_VALUE, should not happen
  488. res = 0
  489. end select
  490. end function
  491. ! IEEE_GET_ROUNDING_MODE
  492. subroutine IEEE_GET_ROUNDING_MODE (ROUND_VALUE)
  493. implicit none
  494. type(IEEE_ROUND_TYPE), intent(out) :: ROUND_VALUE
  495. interface
  496. integer function helper() &
  497. bind(c, name="_gfortrani_get_fpu_rounding_mode")
  498. end function
  499. end interface
  500. ROUND_VALUE = IEEE_ROUND_TYPE(helper())
  501. end subroutine
  502. ! IEEE_SET_ROUNDING_MODE
  503. subroutine IEEE_SET_ROUNDING_MODE (ROUND_VALUE)
  504. implicit none
  505. type(IEEE_ROUND_TYPE), intent(in) :: ROUND_VALUE
  506. interface
  507. subroutine helper(val) &
  508. bind(c, name="_gfortrani_set_fpu_rounding_mode")
  509. integer, value :: val
  510. end subroutine
  511. end interface
  512. call helper(ROUND_VALUE%hidden)
  513. end subroutine
  514. ! IEEE_GET_UNDERFLOW_MODE
  515. subroutine IEEE_GET_UNDERFLOW_MODE (GRADUAL)
  516. implicit none
  517. logical, intent(out) :: GRADUAL
  518. interface
  519. integer function helper() &
  520. bind(c, name="_gfortrani_get_fpu_underflow_mode")
  521. end function
  522. end interface
  523. GRADUAL = (helper() /= 0)
  524. end subroutine
  525. ! IEEE_SET_UNDERFLOW_MODE
  526. subroutine IEEE_SET_UNDERFLOW_MODE (GRADUAL)
  527. implicit none
  528. logical, intent(in) :: GRADUAL
  529. interface
  530. subroutine helper(val) &
  531. bind(c, name="_gfortrani_set_fpu_underflow_mode")
  532. integer, value :: val
  533. end subroutine
  534. end interface
  535. call helper(merge(1, 0, GRADUAL))
  536. end subroutine
  537. ! IEEE_SUPPORT_ROUNDING
  538. pure logical function IEEE_SUPPORT_ROUNDING_4 (ROUND_VALUE, X) result(res)
  539. implicit none
  540. real(kind=4), intent(in) :: X
  541. type(IEEE_ROUND_TYPE), intent(in) :: ROUND_VALUE
  542. res = (support_rounding_helper(ROUND_VALUE%hidden) /= 0)
  543. end function
  544. pure logical function IEEE_SUPPORT_ROUNDING_8 (ROUND_VALUE, X) result(res)
  545. implicit none
  546. real(kind=8), intent(in) :: X
  547. type(IEEE_ROUND_TYPE), intent(in) :: ROUND_VALUE
  548. res = (support_rounding_helper(ROUND_VALUE%hidden) /= 0)
  549. end function
  550. #ifdef HAVE_GFC_REAL_10
  551. pure logical function IEEE_SUPPORT_ROUNDING_10 (ROUND_VALUE, X) result(res)
  552. implicit none
  553. real(kind=10), intent(in) :: X
  554. type(IEEE_ROUND_TYPE), intent(in) :: ROUND_VALUE
  555. res = .false.
  556. end function
  557. #endif
  558. #ifdef HAVE_GFC_REAL_16
  559. pure logical function IEEE_SUPPORT_ROUNDING_16 (ROUND_VALUE, X) result(res)
  560. implicit none
  561. real(kind=16), intent(in) :: X
  562. type(IEEE_ROUND_TYPE), intent(in) :: ROUND_VALUE
  563. res = .false.
  564. end function
  565. #endif
  566. pure logical function IEEE_SUPPORT_ROUNDING_NOARG (ROUND_VALUE) result(res)
  567. implicit none
  568. type(IEEE_ROUND_TYPE), intent(in) :: ROUND_VALUE
  569. #if defined(HAVE_GFC_REAL_10) || defined(HAVE_GFC_REAL_16)
  570. res = .false.
  571. #else
  572. res = (support_rounding_helper(ROUND_VALUE%hidden) /= 0)
  573. #endif
  574. end function
  575. ! IEEE_SUPPORT_UNDERFLOW_CONTROL
  576. pure logical function IEEE_SUPPORT_UNDERFLOW_CONTROL_4 (X) result(res)
  577. implicit none
  578. real(kind=4), intent(in) :: X
  579. res = (support_underflow_control_helper(4) /= 0)
  580. end function
  581. pure logical function IEEE_SUPPORT_UNDERFLOW_CONTROL_8 (X) result(res)
  582. implicit none
  583. real(kind=8), intent(in) :: X
  584. res = (support_underflow_control_helper(8) /= 0)
  585. end function
  586. #ifdef HAVE_GFC_REAL_10
  587. pure logical function IEEE_SUPPORT_UNDERFLOW_CONTROL_10 (X) result(res)
  588. implicit none
  589. real(kind=10), intent(in) :: X
  590. res = .false.
  591. end function
  592. #endif
  593. #ifdef HAVE_GFC_REAL_16
  594. pure logical function IEEE_SUPPORT_UNDERFLOW_CONTROL_16 (X) result(res)
  595. implicit none
  596. real(kind=16), intent(in) :: X
  597. res = .false.
  598. end function
  599. #endif
  600. pure logical function IEEE_SUPPORT_UNDERFLOW_CONTROL_NOARG () result(res)
  601. implicit none
  602. #if defined(HAVE_GFC_REAL_10) || defined(HAVE_GFC_REAL_16)
  603. res = .false.
  604. #else
  605. res = (support_underflow_control_helper(4) /= 0 &
  606. .and. support_underflow_control_helper(8) /= 0)
  607. #endif
  608. end function
  609. ! IEEE_SUPPORT_* functions
  610. #define SUPPORTMACRO(NAME, INTKIND, VALUE) \
  611. pure logical function NAME/**/_/**/INTKIND (X) result(res) ; \
  612. implicit none ; \
  613. real(INTKIND), intent(in) :: X(..) ; \
  614. res = VALUE ; \
  615. end function
  616. #define SUPPORTMACRO_NOARG(NAME, VALUE) \
  617. pure logical function NAME/**/_NOARG () result(res) ; \
  618. implicit none ; \
  619. res = VALUE ; \
  620. end function
  621. ! IEEE_SUPPORT_DATATYPE
  622. SUPPORTMACRO(IEEE_SUPPORT_DATATYPE,4,.true.)
  623. SUPPORTMACRO(IEEE_SUPPORT_DATATYPE,8,.true.)
  624. #ifdef HAVE_GFC_REAL_10
  625. SUPPORTMACRO(IEEE_SUPPORT_DATATYPE,10,.false.)
  626. #endif
  627. #ifdef HAVE_GFC_REAL_16
  628. SUPPORTMACRO(IEEE_SUPPORT_DATATYPE,16,.false.)
  629. #endif
  630. #if defined(HAVE_GFC_REAL_10) || defined(HAVE_GFC_REAL_16)
  631. SUPPORTMACRO_NOARG(IEEE_SUPPORT_DATATYPE,.false.)
  632. #else
  633. SUPPORTMACRO_NOARG(IEEE_SUPPORT_DATATYPE,.true.)
  634. #endif
  635. ! IEEE_SUPPORT_DENORMAL
  636. SUPPORTMACRO(IEEE_SUPPORT_DENORMAL,4,.true.)
  637. SUPPORTMACRO(IEEE_SUPPORT_DENORMAL,8,.true.)
  638. #ifdef HAVE_GFC_REAL_10
  639. SUPPORTMACRO(IEEE_SUPPORT_DENORMAL,10,.false.)
  640. #endif
  641. #ifdef HAVE_GFC_REAL_16
  642. SUPPORTMACRO(IEEE_SUPPORT_DENORMAL,16,.false.)
  643. #endif
  644. #if defined(HAVE_GFC_REAL_10) || defined(HAVE_GFC_REAL_16)
  645. SUPPORTMACRO_NOARG(IEEE_SUPPORT_DENORMAL,.false.)
  646. #else
  647. SUPPORTMACRO_NOARG(IEEE_SUPPORT_DENORMAL,.true.)
  648. #endif
  649. ! IEEE_SUPPORT_DIVIDE
  650. SUPPORTMACRO(IEEE_SUPPORT_DIVIDE,4,.true.)
  651. SUPPORTMACRO(IEEE_SUPPORT_DIVIDE,8,.true.)
  652. #ifdef HAVE_GFC_REAL_10
  653. SUPPORTMACRO(IEEE_SUPPORT_DIVIDE,10,.false.)
  654. #endif
  655. #ifdef HAVE_GFC_REAL_16
  656. SUPPORTMACRO(IEEE_SUPPORT_DIVIDE,16,.false.)
  657. #endif
  658. #if defined(HAVE_GFC_REAL_10) || defined(HAVE_GFC_REAL_16)
  659. SUPPORTMACRO_NOARG(IEEE_SUPPORT_DIVIDE,.false.)
  660. #else
  661. SUPPORTMACRO_NOARG(IEEE_SUPPORT_DIVIDE,.true.)
  662. #endif
  663. ! IEEE_SUPPORT_INF
  664. SUPPORTMACRO(IEEE_SUPPORT_INF,4,.true.)
  665. SUPPORTMACRO(IEEE_SUPPORT_INF,8,.true.)
  666. #ifdef HAVE_GFC_REAL_10
  667. SUPPORTMACRO(IEEE_SUPPORT_INF,10,.false.)
  668. #endif
  669. #ifdef HAVE_GFC_REAL_16
  670. SUPPORTMACRO(IEEE_SUPPORT_INF,16,.false.)
  671. #endif
  672. #if defined(HAVE_GFC_REAL_10) || defined(HAVE_GFC_REAL_16)
  673. SUPPORTMACRO_NOARG(IEEE_SUPPORT_INF,.false.)
  674. #else
  675. SUPPORTMACRO_NOARG(IEEE_SUPPORT_INF,.true.)
  676. #endif
  677. ! IEEE_SUPPORT_IO
  678. SUPPORTMACRO(IEEE_SUPPORT_IO,4,.true.)
  679. SUPPORTMACRO(IEEE_SUPPORT_IO,8,.true.)
  680. #ifdef HAVE_GFC_REAL_10
  681. SUPPORTMACRO(IEEE_SUPPORT_IO,10,.false.)
  682. #endif
  683. #ifdef HAVE_GFC_REAL_16
  684. SUPPORTMACRO(IEEE_SUPPORT_IO,16,.false.)
  685. #endif
  686. #if defined(HAVE_GFC_REAL_10) || defined(HAVE_GFC_REAL_16)
  687. SUPPORTMACRO_NOARG(IEEE_SUPPORT_IO,.false.)
  688. #else
  689. SUPPORTMACRO_NOARG(IEEE_SUPPORT_IO,.true.)
  690. #endif
  691. ! IEEE_SUPPORT_NAN
  692. SUPPORTMACRO(IEEE_SUPPORT_NAN,4,.true.)
  693. SUPPORTMACRO(IEEE_SUPPORT_NAN,8,.true.)
  694. #ifdef HAVE_GFC_REAL_10
  695. SUPPORTMACRO(IEEE_SUPPORT_NAN,10,.false.)
  696. #endif
  697. #ifdef HAVE_GFC_REAL_16
  698. SUPPORTMACRO(IEEE_SUPPORT_NAN,16,.false.)
  699. #endif
  700. #if defined(HAVE_GFC_REAL_10) || defined(HAVE_GFC_REAL_16)
  701. SUPPORTMACRO_NOARG(IEEE_SUPPORT_NAN,.false.)
  702. #else
  703. SUPPORTMACRO_NOARG(IEEE_SUPPORT_NAN,.true.)
  704. #endif
  705. ! IEEE_SUPPORT_SQRT
  706. SUPPORTMACRO(IEEE_SUPPORT_SQRT,4,.true.)
  707. SUPPORTMACRO(IEEE_SUPPORT_SQRT,8,.true.)
  708. #ifdef HAVE_GFC_REAL_10
  709. SUPPORTMACRO(IEEE_SUPPORT_SQRT,10,.false.)
  710. #endif
  711. #ifdef HAVE_GFC_REAL_16
  712. SUPPORTMACRO(IEEE_SUPPORT_SQRT,16,.false.)
  713. #endif
  714. #if defined(HAVE_GFC_REAL_10) || defined(HAVE_GFC_REAL_16)
  715. SUPPORTMACRO_NOARG(IEEE_SUPPORT_SQRT,.false.)
  716. #else
  717. SUPPORTMACRO_NOARG(IEEE_SUPPORT_SQRT,.true.)
  718. #endif
  719. ! IEEE_SUPPORT_STANDARD
  720. SUPPORTMACRO(IEEE_SUPPORT_STANDARD,4,.true.)
  721. SUPPORTMACRO(IEEE_SUPPORT_STANDARD,8,.true.)
  722. #ifdef HAVE_GFC_REAL_10
  723. SUPPORTMACRO(IEEE_SUPPORT_STANDARD,10,.false.)
  724. #endif
  725. #ifdef HAVE_GFC_REAL_16
  726. SUPPORTMACRO(IEEE_SUPPORT_STANDARD,16,.false.)
  727. #endif
  728. #if defined(HAVE_GFC_REAL_10) || defined(HAVE_GFC_REAL_16)
  729. SUPPORTMACRO_NOARG(IEEE_SUPPORT_STANDARD,.false.)
  730. #else
  731. SUPPORTMACRO_NOARG(IEEE_SUPPORT_STANDARD,.true.)
  732. #endif
  733. end module IEEE_ARITHMETIC