#define GFC_FPE_TONEAREST 2
#define GFC_FPE_TOWARDZERO 3
#define GFC_FPE_UPWARD 4
+#define GFC_FPE_AWAY 5
/* Size of the buffer required to store FPU state for any target.
In particular, this has to be larger than fenv_t on all glibc targets.
--- /dev/null
+! { dg-do run }
+
+ use, intrinsic :: ieee_arithmetic
+ implicit none
+
+ real :: sx1, sx2, sx3
+ double precision :: dx1, dx2, dx3
+
+ ! IEEE_AWAY was added in Fortran 2018 and not supported by any target
+ ! at the moment. Just check we can query for its support.
+
+ ! We should support at least C float and C double types
+ if (ieee_support_rounding(ieee_away) &
+ .or. ieee_support_rounding(ieee_away, 0.) &
+ .or. ieee_support_rounding(ieee_away, 0.d0)) then
+ print *, "If a target / libc now supports this, we need to add a proper check!"
+ stop 1
+ end if
+
+end
}
int
-support_fpu_rounding_mode (int mode __attribute__((unused)))
+support_fpu_rounding_mode (int mode)
{
- return 1;
+ if (mode == GFC_FPE_AWAY)
+ return 0;
+ else
+ return 1;
}
void
int
-support_fpu_rounding_mode (int mode __attribute__((unused)))
+support_fpu_rounding_mode (int mode)
{
- return 1;
+ if (mode == GFC_FPE_AWAY)
+ return 0;
+ else
+ return 1;
}
return GFC_FPE_TOWARDZERO;
#endif
+#ifdef FE_TONEARESTFROMZERO
+ case FE_TONEARESTFROMZERO:
+ return GFC_FPE_AWAY;
+#endif
+
default:
return 0; /* Should be unreachable. */
}
break;
#endif
+#ifdef FE_TONEARESTFROMZERO
+ case GFC_FPE_AWAY:
+ rnd_mode = FE_TONEARESTFROMZERO;
+ break;
+#endif
+
default:
- return; /* Should be unreachable. */
+ return;
}
fesetround (rnd_mode);
return 0;
#endif
+ case GFC_FPE_AWAY:
+#ifdef FE_TONEARESTFROMZERO
+ return 1;
+#else
+ return 0;
+#endif
+
default:
- return 0; /* Should be unreachable. */
+ return 0;
}
}
int
get_fpu_rounding_mode (void)
-{
+{
+ return 0;
+}
+
+
+int
+support_fpu_rounding_mode (int mode __attribute__((unused)))
+{
return 0;
-}
+}
void
return GFC_FPE_TOWARDZERO;
#endif
+#ifdef FE_TONEARESTFROMZERO
+ case FE_TONEARESTFROMZERO:
+ return GFC_FPE_AWAY;
+#endif
+
default:
return 0; /* Should be unreachable. */
}
break;
#endif
+#ifdef FE_TONEARESTFROMZERO
+ case GFC_FPE_AWAY:
+ rnd_mode = FE_TONEARESTFROMZERO;
+ break;
+#endif
+
default:
return; /* Should be unreachable. */
}
return 0;
#endif
+ case GFC_FPE_AWAY:
+#ifdef FE_TONEARESTFROMZERO
+ return 1;
+#else
+ return 0;
+#endif
+
default:
return 0; /* Should be unreachable. */
}
int
-support_fpu_rounding_mode (int mode __attribute__((unused)))
+support_fpu_rounding_mode (int mode)
{
- return 1;
+ if (mode == GFC_FPE_AWAY)
+ return 0;
+ else
+ return 1;
}
IEEE_TO_ZERO = IEEE_ROUND_TYPE(GFC_FPE_TOWARDZERO), &
IEEE_UP = IEEE_ROUND_TYPE(GFC_FPE_UPWARD), &
IEEE_DOWN = IEEE_ROUND_TYPE(GFC_FPE_DOWNWARD), &
+ IEEE_AWAY = IEEE_ROUND_TYPE(GFC_FPE_AWAY), &
IEEE_OTHER = IEEE_ROUND_TYPE(0)
! IEEE_GET_ROUNDING_MODE
- subroutine IEEE_GET_ROUNDING_MODE (ROUND_VALUE)
+ subroutine IEEE_GET_ROUNDING_MODE (ROUND_VALUE, RADIX)
implicit none
type(IEEE_ROUND_TYPE), intent(out) :: ROUND_VALUE
+ integer, intent(in), optional :: RADIX
interface
integer function helper() &
! IEEE_SET_ROUNDING_MODE
- subroutine IEEE_SET_ROUNDING_MODE (ROUND_VALUE)
+ subroutine IEEE_SET_ROUNDING_MODE (ROUND_VALUE, RADIX)
implicit none
type(IEEE_ROUND_TYPE), intent(in) :: ROUND_VALUE
+ integer, intent(in), optional :: RADIX
interface
subroutine helper(val) &