Message ID | 20181220214739.GA86993@troutmask.apl.washington.edu |
---|---|
State | New |
Headers | show |
Series | fortran/69121 -- Make IEEE_SCALB generic | expand |
On Thu, Dec 20, 2018 at 01:47:39PM -0800, Steve Kargl wrote: > The attached patch has been tested on x86_64-*-freebsd. > > OK to commit? > > 2018-12-20 Steven G. Kargl <kargl@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 <kargl@gcc.gnu.org> > > PR fortran/69121 > * gfortran.dg/ieee/ieee_9.f90: New test. Now, tested on i586-*-freebsd.
On Fri, Dec 21, 2018 at 8:22 AM Steve Kargl < sgk@troutmask.apl.washington.edu> wrote: > On Thu, Dec 20, 2018 at 01:47:39PM -0800, Steve Kargl wrote: > > The attached patch has been tested on x86_64-*-freebsd. > > > > OK to commit? > > > > 2018-12-20 Steven G. Kargl <kargl@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 <kargl@gcc.gnu.org> > > > > PR fortran/69121 > > * gfortran.dg/ieee/ieee_9.f90: New test. > > Now, tested on i586-*-freebsd. > > -- > Steve > Hi, looks ok for trunk. A few questions popped into my mind while looking into this: 1) Why are none of the _gfortran_ieee_scalb_X_Y functions mentioned in gfortran.map? I guess they should all be there? 2) Currently all the intrinsics map to the scalbn{,f,l} builtins. However, when the integer argument is of kind int64 or int128 we should instead use scalbln{,f,l}. This also applies to other intrinsics that use scalbn under the hood. To clarify, fixing these is not a prerequisite for accepting the patch (I already accepted it), but more like topics for further work.
On Fri, Dec 21, 2018 at 11:07:08AM +0200, Janne Blomqvist wrote: > On Fri, Dec 21, 2018 at 8:22 AM Steve Kargl < > sgk@troutmask.apl.washington.edu> wrote: > > > On Thu, Dec 20, 2018 at 01:47:39PM -0800, Steve Kargl wrote: > > > The attached patch has been tested on x86_64-*-freebsd. > > > > > > OK to commit? > > > > > > 2018-12-20 Steven G. Kargl <kargl@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 <kargl@gcc.gnu.org> > > > > > > PR fortran/69121 > > > * gfortran.dg/ieee/ieee_9.f90: New test. > > > > Now, tested on i586-*-freebsd. > > > > Hi, looks ok for trunk. > > A few questions popped into my mind while looking into this: > > 1) Why are none of the _gfortran_ieee_scalb_X_Y functions mentioned in > gfortran.map? I guess they should all be there? > > 2) Currently all the intrinsics map to the scalbn{,f,l} builtins. However, > when the integer argument is of kind int64 or int128 we should instead use > scalbln{,f,l}. This also applies to other intrinsics that use scalbn under > the hood. > > To clarify, fixing these is not a prerequisite for accepting the patch (I > already accepted it), but more like topics for further work. Just, sent shorter note in private email to Thomas. No, I'm adding the missing functions to the INTERFACE. This will not compile: program foo use ieee_arithmetic real x integer(8) i x = 2 i = 2_8 print *, ieee_scalb(x,i) end program because the module has a generic interface that does not include the integer(8) argument. FX seems to have wanted to avoid the explosion of functions in the library. In trans-intrinsic.c (conv_intrinsic_ieee_scalb), he does a conversion of the integer(8) to an integer(4). Unfortunately, checking the interface for ieee_scalb occurs before code generation. Compiling the above after my patch, the -ftree-dump-original contains D.3769 = __builtin_scalbnf (x, (integer(kind=4)) MAX_EXPR <MIN_EXPR <D.3768, 2147483647>, -2147483647>);
Hi Steve,
> No, I'm adding the missing functions to the INTERFACE.
Ah, I see. What I missed was that the function is actually translated
to something else.
So, OK for trunk, and thanks for the patch!
Regards
Thomas
On Fri, Dec 21, 2018 at 11:07:08AM +0200, Janne Blomqvist wrote: > On Fri, Dec 21, 2018 at 8:22 AM Steve Kargl < > sgk@troutmask.apl.washington.edu> wrote: > > > On Thu, Dec 20, 2018 at 01:47:39PM -0800, Steve Kargl wrote: > > > The attached patch has been tested on x86_64-*-freebsd. > > > > > > OK to commit? > > > > > > 2018-12-20 Steven G. Kargl <kargl@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 <kargl@gcc.gnu.org> > > > > > > PR fortran/69121 > > > * gfortran.dg/ieee/ieee_9.f90: New test. > > > > Now, tested on i586-*-freebsd. > > > > Hi, looks ok for trunk. > > A few questions popped into my mind while looking into this: > > 1) Why are none of the _gfortran_ieee_scalb_X_Y functions mentioned in > gfortran.map? I guess they should all be there? > > 2) Currently all the intrinsics map to the scalbn{,f,l} builtins. However, > when the integer argument is of kind int64 or int128 we should instead use > scalbln{,f,l}. This also applies to other intrinsics that use scalbn under > the hood. > > To clarify, fixing these is not a prerequisite for accepting the patch (I > already accepted it), but more like topics for further work. > I forgot to address your had a 2) item above. ieee_scalb appears to do the right thing. FX addressed that with his implementation. The 2nd argument is always cast to integer after reducing the range to that of integer(4). The binary floating point representation for a REAL(16) finite number is x=f*2**e with f in [0.5,1) and e in [-16059,16384]. scalb(x,n) is x*2**n, which becomes f*2**e*2**n = f*2**(e+n). If x is the smallest positive subnormal number, then n can be at most 32443 to still return a finite REAL(16) number. Any larger value overflows to infinity. If x is the largest positive finite number, then n can be -32443 to return the small positive subnormal number. Any more negative value of n underflows to zero. (Note, I could be off-by-one, but that is just a detail.) Consider function foo(x,i) use ieee_arithmetic real(16) foo, c integer(8) i print *, ieee_scalb(c, i) end function foo -fdump-tree-original gives D.3853 = *i; __result_foo = scalbnq (c, (integer(kind=4)) MAX_EXPR <MIN_EXPR <D.3853, 2147483647>, -2147483647>); The range [-32443,32443] is a subset of [-huge(),huge(0)].
On Fri, Dec 21, 2018 at 06:31:27PM +0100, Thomas Koenig wrote: > Hi Steve, > > > No, I'm adding the missing functions to the INTERFACE. > > Ah, I see. What I missed was that the function is actually translated > to something else. > > So, OK for trunk, and thanks for the patch! > Janne, Thomas, Thanks for the quick review. I first reported the bug 2 years ago (2016-01-02). I left it as low-hanging fruit with the hope that a junior gfortran hacker would cut his/her teeth on a patch. Junior hasn't come along, and with nearly 1000 open PRs, I decided to fix it. I took a 5-6 month break from working on gfortran. When I looked a month ago, there were 1002 open PRs. With my recent burst of fixing/closing 16 PRs in December, we're still at 991. Too many PRs, too few hands. :-(
On Fri, Dec 21, 2018 at 7:59 PM Steve Kargl < sgk@troutmask.apl.washington.edu> wrote: > On Fri, Dec 21, 2018 at 11:07:08AM +0200, Janne Blomqvist wrote: > > On Fri, Dec 21, 2018 at 8:22 AM Steve Kargl < > > sgk@troutmask.apl.washington.edu> wrote: > > > > > On Thu, Dec 20, 2018 at 01:47:39PM -0800, Steve Kargl wrote: > > > > The attached patch has been tested on x86_64-*-freebsd. > > > > > > > > OK to commit? > > > > > > > > 2018-12-20 Steven G. Kargl <kargl@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 <kargl@gcc.gnu.org> > > > > > > > > PR fortran/69121 > > > > * gfortran.dg/ieee/ieee_9.f90: New test. > > > > > > Now, tested on i586-*-freebsd. > > > > > > > Hi, looks ok for trunk. > > > > A few questions popped into my mind while looking into this: > > > > 1) Why are none of the _gfortran_ieee_scalb_X_Y functions mentioned in > > gfortran.map? I guess they should all be there? > > > > 2) Currently all the intrinsics map to the scalbn{,f,l} builtins. > However, > > when the integer argument is of kind int64 or int128 we should instead > use > > scalbln{,f,l}. This also applies to other intrinsics that use scalbn > under > > the hood. > > > > To clarify, fixing these is not a prerequisite for accepting the patch (I > > already accepted it), but more like topics for further work. > > > > I forgot to address your had a 2) item above. ieee_scalb appears > to do the right thing. FX addressed that with his implementation. > The 2nd argument is always cast to integer after reducing the range > to that of integer(4). > > The binary floating point representation for a REAL(16) finite number > is x=f*2**e with f in [0.5,1) and e in [-16059,16384]. scalb(x,n) is > x*2**n, which becomes f*2**e*2**n = f*2**(e+n). If x is the smallest > positive subnormal number, then n can be at most 32443 to still return > a finite REAL(16) number. Any larger value overflows to infinity. > If x is the largest positive finite number, then n can be -32443 to > return the small positive subnormal number. Any more negative value > of n underflows to zero. (Note, I could be off-by-one, but that is > just a detail.) > > Consider > > function foo(x,i) > use ieee_arithmetic > real(16) foo, c > integer(8) i > print *, ieee_scalb(c, i) > end function foo > > -fdump-tree-original gives > > D.3853 = *i; > __result_foo = scalbnq (c, > (integer(kind=4)) MAX_EXPR <MIN_EXPR <D.3853, 2147483647>, > -2147483647>); > > The range [-32443,32443] is a subset of [-huge(),huge(0)]. > True. I guess the advantage of scalbln* would be to avoid the MAX/MIN_EXPR and casting for kind int64.
On Fri, Dec 21, 2018 at 08:59:04PM +0200, Janne Blomqvist wrote: > On Fri, Dec 21, 2018 at 7:59 PM Steve Kargl < > > > > D.3853 = *i; > > __result_foo = scalbnq (c, > > (integer(kind=4)) MAX_EXPR <MIN_EXPR <D.3853, 2147483647>, > > -2147483647>); > > > > The range [-32443,32443] is a subset of [-huge(),huge(0)]. > > > > True. I guess the advantage of scalbln* would be to avoid the MAX/MIN_EXPR > and casting for kind int64. > fdlibm-based libm has #define NMAX 65536 #define NMIN -65536 double scalbln(double x, long n) { return (scalbn(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n)); } A search for glibc's libm locates https://tinyurl.com/ybcy8w4t which is a bit-twiddling routine. Not sure it's worth the effort. Joseph Myers might have an opinion.
On Fri, 21 Dec 2018, Steve Kargl wrote: > scalbln(double x, long n) > { > > return (scalbn(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n)); > } > > A search for glibc's libm locates https://tinyurl.com/ybcy8w4t > which is a bit-twiddling routine. Not sure it's worth the > effort. Joseph Myers might have an opinion. Such comparisons are needed in the scalbn / scalbln implementations anyway to deal with large exponents. I suppose where there's a suitable scalbln implementation, and you don't know if the arguments are within the range of int, calling scalbln at least saves code size in the caller and avoids duplicating those range checks.
On Fri, Dec 21, 2018 at 07:39:45PM +0000, Joseph Myers wrote: > On Fri, 21 Dec 2018, Steve Kargl wrote: > > > scalbln(double x, long n) > > { > > > > return (scalbn(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n)); > > } > > > > A search for glibc's libm locates https://tinyurl.com/ybcy8w4t > > which is a bit-twiddling routine. Not sure it's worth the > > effort. Joseph Myers might have an opinion. > > Such comparisons are needed in the scalbn / scalbln implementations anyway > to deal with large exponents. I suppose where there's a suitable scalbln > implementation, and you don't know if the arguments are within the range > of int, calling scalbln at least saves code size in the caller and avoids > duplicating those range checks. > I was thinking along the lines of -ffast-math and whether __builtin_scalbn and __builtin_scalbln are then inlined. The comparisons may inhibit inlining __builtin_scalbn; while, if gfortran used __builtin_scalbln, inlining would occur. As it is, for function foo(x,i) use ieee_arithmetic real(8) foo, c integer(8) i foo = ieee_scalb(c, i) end function foo the options -ffast-math -O3 -fdump-tree-optimized give <bb 2> [local count: 1073741824]: _gfortran_ieee_procedure_entry (&fpstate.0); _8 = *i_7(D); _1 = MIN_EXPR <_8, 2147483647>; _2 = MAX_EXPR <_1, -2147483647>; _3 = (integer(kind=4)) _2; _4 = __builtin_scalbn (c_9(D), _3); _gfortran_ieee_procedure_exit (&fpstate.0); fpstate.0 ={v} {CLOBBER}; return _4; It seems this could be <bb 2> [local count: 1073741824]: _gfortran_ieee_procedure_entry (&fpstate.0); _3 = (integer(kind=4)) *i_7(D); _4 = __builtin_scalbn (c_9(D), _3); _gfortran_ieee_procedure_exit (&fpstate.0); fpstate.0 ={v} {CLOBBER};
Hi Steve On 21/12/18 8:01 PM, Steve Kargl wrote: > On Fri, Dec 21, 2018 at 07:39:45PM +0000, Joseph Myers wrote: >> On Fri, 21 Dec 2018, Steve Kargl wrote: >> >>> scalbln(double x, long n) >>> { >>> >>> return (scalbn(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n)); >>> } >>> >>> A search for glibc's libm locateshttps://tinyurl.com/ybcy8w4t >>> which is a bit-twiddling routine. Not sure it's worth the >>> effort. Joseph Myers might have an opinion. >> Such comparisons are needed in the scalbn / scalbln implementations anyway >> to deal with large exponents. I suppose where there's a suitable scalbln >> implementation, and you don't know if the arguments are within the range >> of int, calling scalbln at least saves code size in the caller and avoids >> duplicating those range checks. >> > I was thinking along the lines of -ffast-math and whether > __builtin_scalbn and __builtin_scalbln are then inlined. > The comparisons may inhibit inlining __builtin_scalbn; > while, if gfortran used __builtin_scalbln, inlining would > occur. > > As it is, for > > function foo(x,i) > use ieee_arithmetic > real(8) foo, c > integer(8) i > foo = ieee_scalb(c, i) > end function foo > > the options -ffast-math -O3 -fdump-tree-optimized give > > <bb 2> [local count: 1073741824]: > _gfortran_ieee_procedure_entry (&fpstate.0); > _8 = *i_7(D); > _1 = MIN_EXPR <_8, 2147483647>; > _2 = MAX_EXPR <_1, -2147483647>; > _3 = (integer(kind=4)) _2; > _4 = __builtin_scalbn (c_9(D), _3); > _gfortran_ieee_procedure_exit (&fpstate.0); > fpstate.0 ={v} {CLOBBER}; > return _4; > > It seems this could be > > <bb 2> [local count: 1073741824]: > _gfortran_ieee_procedure_entry (&fpstate.0); > _3 = (integer(kind=4)) *i_7(D); > _4 = __builtin_scalbn (c_9(D), _3 > _gfortran_ieee_procedure_exit (&fpstate.0); > fpstate.0 ={v} {CLOBBER}; > I am observing your new test pr88328.f90 failing on arm-none-linux-gnueabihf: Excess errors: /build/src/gcc/gcc/testsuite/gfortran.dg/ieee/ieee_9.f90:20:36: Error: Invalid kind for REAL at (1) /build/src/gcc/gcc/testsuite/gfortran.dg/ieee/ieee_9.f90:35:36: Error: Invalid kind for REAL at (1) /build/src/gcc/gcc/testsuite/gfortran.dg/ieee/ieee_9.f90:50:36: Error: Invalid kind for REAL at (1) /build/src/gcc/gcc/testsuite/gfortran.dg/ieee/ieee_9.f90:65:36: Error: Invalid kind for REAL at (1)
On Mon, Dec 24, 2018 at 12:26:46PM +0000, Sudakshina Das wrote: > > > I am observing your new test pr88328.f90 failing on > arm-none-linux-gnueabihf: > Excess errors: > /build/src/gcc/gcc/testsuite/gfortran.dg/ieee/ieee_9.f90:20:36: Error: > Invalid kind for REAL at (1) > /build/src/gcc/gcc/testsuite/gfortran.dg/ieee/ieee_9.f90:35:36: Error: > Invalid kind for REAL at (1) > /build/src/gcc/gcc/testsuite/gfortran.dg/ieee/ieee_9.f90:50:36: Error: > Invalid kind for REAL at (1) > /build/src/gcc/gcc/testsuite/gfortran.dg/ieee/ieee_9.f90:65:36: Error: > Invalid kind for REAL at (1) pr88328.f90 or ieee_9.f90? In either case, you can XFAIL the testcase for arm-none-linux-gnueabihf.
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