The attached patch has been tested on x86_64-*-freebsd. It provides the missing pieces for IEEE_SCALB to allow it to be generic function. Briefly, when FX contributed IEEE_SCALB, he implemented a casting of the integer argument to the default integer kind. For integer(1) and integer(2), this is a simple cast. For integer(8) and integer(16), he first checks to see if the value is in the range of default integer kind. So, one essentially has
ieee_scalb(x, 2_1) --> ieee_scalb(x, int(2_1, 4)) ieee_scalb(x, 2_8) --> ieee_scalb(x, int(max(min(2_8,huge(0)),-huge(0)), 4) Unfortnately, the interface exposed by the IEEE_ARITHMETIC module did not allow for non-default integer kind arguments. The patch corrects that omission. OK to commit? 2018-12-20 Steven G. Kargl <ka...@gcc.gnu.org> PR fortran/69121 * libgfortran/ieee/ieee_arithmetic.F90: Provide missing functions in interface for IEEE_SCALB. 2018-12-20 Steven G. Kargl <ka...@gcc.gnu.org> PR fortran/69121 * gfortran.dg/ieee/ieee_9.f90: New test. -- Steve
Index: libgfortran/ieee/ieee_arithmetic.F90 =================================================================== --- libgfortran/ieee/ieee_arithmetic.F90 (revision 267312) +++ libgfortran/ieee/ieee_arithmetic.F90 (working copy) @@ -532,37 +532,170 @@ REM_MACRO(4,4,4) ! IEEE_SCALB interface - elemental real(kind=4) function _gfortran_ieee_scalb_4 (X, I) +#ifdef HAVE_GFC_INTEGER_16 +#ifdef HAVE_GFC_REAL_16 + elemental real(kind=16) function _gfortran_ieee_scalb_16_16 (X, I) + real(kind=16), intent(in) :: X + integer(kind=16), intent(in) :: I + end function +#endif +#ifdef HAVE_GFC_REAL_10 + elemental real(kind=10) function _gfortran_ieee_scalb_10_16 (X, I) + real(kind=10), intent(in) :: X + integer(kind=16), intent(in) :: I + end function +#endif + elemental real(kind=8) function _gfortran_ieee_scalb_8_16 (X, I) + real(kind=8), intent(in) :: X + integer(kind=16), intent(in) :: I + end function + elemental real(kind=4) function _gfortran_ieee_scalb_4_16 (X, I) real(kind=4), intent(in) :: X - integer, intent(in) :: I + integer(kind=16), intent(in) :: I end function - elemental real(kind=8) function _gfortran_ieee_scalb_8 (X, I) +#endif + +#ifdef HAVE_GFC_INTEGER_8 +#ifdef HAVE_GFC_REAL_16 + elemental real(kind=16) function _gfortran_ieee_scalb_16_8 (X, I) + real(kind=16), intent(in) :: X + integer(kind=8), intent(in) :: I + end function +#endif +#ifdef HAVE_GFC_REAL_10 + elemental real(kind=10) function _gfortran_ieee_scalb_10_8 (X, I) + real(kind=10), intent(in) :: X + integer(kind=8), intent(in) :: I + end function +#endif + elemental real(kind=8) function _gfortran_ieee_scalb_8_8 (X, I) real(kind=8), intent(in) :: X - integer, intent(in) :: I + integer(kind=8), intent(in) :: I end function + elemental real(kind=4) function _gfortran_ieee_scalb_4_8 (X, I) + real(kind=4), intent(in) :: X + integer(kind=8), intent(in) :: I + end function +#endif + +#ifdef HAVE_GFC_INTEGER_2 +#ifdef HAVE_GFC_REAL_16 + elemental real(kind=16) function _gfortran_ieee_scalb_16_2 (X, I) + real(kind=16), intent(in) :: X + integer(kind=2), intent(in) :: I + end function +#endif #ifdef HAVE_GFC_REAL_10 - elemental real(kind=10) function _gfortran_ieee_scalb_10 (X, I) + elemental real(kind=10) function _gfortran_ieee_scalb_10_2 (X, I) real(kind=10), intent(in) :: X - integer, intent(in) :: I + integer(kind=2), intent(in) :: I end function #endif + elemental real(kind=8) function _gfortran_ieee_scalb_8_2 (X, I) + real(kind=8), intent(in) :: X + integer(kind=2), intent(in) :: I + end function + elemental real(kind=4) function _gfortran_ieee_scalb_4_2 (X, I) + real(kind=4), intent(in) :: X + integer(kind=2), intent(in) :: I + end function +#endif + +#ifdef HAVE_GFC_INTEGER_1 #ifdef HAVE_GFC_REAL_16 - elemental real(kind=16) function _gfortran_ieee_scalb_16 (X, I) + elemental real(kind=16) function _gfortran_ieee_scalb_16_1 (X, I) real(kind=16), intent(in) :: X + integer(kind=1), intent(in) :: I + end function +#endif +#ifdef HAVE_GFC_REAL_10 + elemental real(kind=10) function _gfortran_ieee_scalb_10_1 (X, I) + real(kind=10), intent(in) :: X + integer(kind=1), intent(in) :: I + end function +#endif + elemental real(kind=8) function _gfortran_ieee_scalb_8_1 (X, I) + real(kind=8), intent(in) :: X + integer(kind=1), intent(in) :: I + end function + elemental real(kind=4) function _gfortran_ieee_scalb_4_1 (X, I) + real(kind=4), intent(in) :: X + integer(kind=1), intent(in) :: I + end function +#endif + +#ifdef HAVE_GFC_REAL_16 + elemental real(kind=16) function _gfortran_ieee_scalb_16_4 (X, I) + real(kind=16), intent(in) :: X integer, intent(in) :: I end function #endif +#ifdef HAVE_GFC_REAL_10 + elemental real(kind=10) function _gfortran_ieee_scalb_10_4 (X, I) + real(kind=10), intent(in) :: X + integer, intent(in) :: I + end function +#endif + elemental real(kind=8) function _gfortran_ieee_scalb_8_4 (X, I) + real(kind=8), intent(in) :: X + integer, intent(in) :: I + end function + elemental real(kind=4) function _gfortran_ieee_scalb_4_4 (X, I) + real(kind=4), intent(in) :: X + integer, intent(in) :: I + end function end interface interface IEEE_SCALB procedure & +#ifdef HAVE_GFC_INTEGER_16 #ifdef HAVE_GFC_REAL_16 - _gfortran_ieee_scalb_16, & + _gfortran_ieee_scalb_16_16, & #endif #ifdef HAVE_GFC_REAL_10 - _gfortran_ieee_scalb_10, & + _gfortran_ieee_scalb_10_16, & #endif - _gfortran_ieee_scalb_8, _gfortran_ieee_scalb_4 + _gfortran_ieee_scalb_8_16, & + _gfortran_ieee_scalb_4_16, & +#endif +#ifdef HAVE_GFC_INTEGER_8 +#ifdef HAVE_GFC_REAL_16 + _gfortran_ieee_scalb_16_8, & +#endif +#ifdef HAVE_GFC_REAL_10 + _gfortran_ieee_scalb_10_8, & +#endif + _gfortran_ieee_scalb_8_8, & + _gfortran_ieee_scalb_4_8, & +#endif +#ifdef HAVE_GFC_INTEGER_2 +#ifdef HAVE_GFC_REAL_16 + _gfortran_ieee_scalb_16_2, & +#endif +#ifdef HAVE_GFC_REAL_10 + _gfortran_ieee_scalb_10_2, & +#endif + _gfortran_ieee_scalb_8_2, & + _gfortran_ieee_scalb_4_2, & +#endif +#ifdef HAVE_GFC_INTEGER_1 +#ifdef HAVE_GFC_REAL_16 + _gfortran_ieee_scalb_16_1, & +#endif +#ifdef HAVE_GFC_REAL_10 + _gfortran_ieee_scalb_10_1, & +#endif + _gfortran_ieee_scalb_8_1, & + _gfortran_ieee_scalb_4_1, & +#endif +#ifdef HAVE_GFC_REAL_16 + _gfortran_ieee_scalb_16_4, & +#endif +#ifdef HAVE_GFC_REAL_10 + _gfortran_ieee_scalb_10_4, & +#endif + _gfortran_ieee_scalb_8_4, & + _gfortran_ieee_scalb_4_4 end interface public :: IEEE_SCALB Index: gcc/testsuite/gfortran.dg/ieee/ieee_9.f90 =================================================================== --- gcc/testsuite/gfortran.dg/ieee/ieee_9.f90 (nonexistent) +++ gcc/testsuite/gfortran.dg/ieee/ieee_9.f90 (working copy) @@ -0,0 +1,70 @@ +! { dg-do run } +program foo + use ieee_arithmetic + use iso_fortran_env + integer i, p + real x + x = 4 + i = 4 + + if (int8 > 0) then + if (real32 > 0) then + p = int(ieee_scalb(real(x, real32), int(i, int8))) + if (p /= 64) stop 1 + endif + if (real64 > 0) then + p = int(ieee_scalb(real(x, real64), int(i, int8))) + if (p /= 64) stop 2 + endif + if (real128 > 0) then + p = int(ieee_scalb(real(x, real128), int(i, int8))) + if (p /= 64) stop 3 + end if + end if + + if (int16 > 0) then + if (real32 > 0) then + p = int(ieee_scalb(real(x, real32), int(i, int16))) + if (p /= 64) stop 4 + endif + if (real64 > 0) then + p = int(ieee_scalb(real(x, real64), int(i, int16))) + if (p /= 64) stop 5 + endif + if (real128 > 0) then + p = int(ieee_scalb(real(x, real128), int(i, int16))) + if (p /= 64) stop 6 + end if + end if + + if (int32 > 0) then + if (real32 > 0) then + p = int(ieee_scalb(real(x, real32), int(i, int32))) + if (p /= 64) stop 7 + endif + if (real64 > 0) then + p = int(ieee_scalb(real(x, real64), int(i, int32))) + if (p /= 64) stop 8 + endif + if (real128 > 0) then + p = int(ieee_scalb(real(x, real128), int(i, int32))) + if (p /= 64) stop 9 + end if + end if + + if (int64 > 0) then + if (real32 > 0) then + p = int(ieee_scalb(real(x, real32), int(i, int64))) + if (p /= 64) stop 10 + endif + if (real64 > 0) then + p = int(ieee_scalb(real(x, real64), int(i, int64))) + if (p /= 64) stop 11 + endif + if (real128 > 0) then + p = int(ieee_scalb(real(x, real128), int(i, int64))) + if (p /= 64) stop 12 + end if + end if + +end program foo