• problem with NINT() and DOUBLEPRECISION input values

    From John@21:1/5 to All on Wed Nov 16 05:09:41 2022
    I am on a Linux mint box using KVM and
    running a virtual box that is
    OpenBSD mo.my.domain 7.2 GENERIC#381 i386
    using
    GNU Fortran (GCC) 11.2.0
    and am getting negative values from NINT()
    on doubleprecision values when I do not expect
    them.

    I thought NINT() took any KIND of REAL so I did
    not expect that; but it has been a while since
    I ran on i386, and I am on a virtual box.

    If I do a NINT(REAL(value)) instead of NINT(value)
    I get the expected INTEGER value.

    Any reason I should expect NINT() to not work
    with values still within the range of the default
    INTEGER kind?

    Anyone have a 32-bit box with gfortran on it that
    could see if they start getting negative values
    with doubleprecision input values below HUGE(0)?

    > program testit
    > use,intrinsic :: iso_fortran_env, only : int8, int16, int32, int64
    > use,intrinsic :: iso_fortran_env, only : real32, real64, real128
    > implicit none
    > doubleprecision :: value
    > integer :: i
    > do i=0,huge(0)-1
    > value=i
    > if(nint(value).lt.0)then
    > write(*,*)'VALUE:',value
    > write(*,*)'REAL(VALUE):',real(value)
    > write(*,*)'NINT(REAL(VALUE)):',nint(real(value))
    > write(*,*)'NINT(VALUE):',nint(value-1)
    > write(*,*)'NINT(VALUE):',nint(value)
    > write(*,*)'NINT(VALUE):',nint(value+1)
    > write(*,*)'INT:',int(value-1)
    > write(*,*)'INT:',int(value)
    > write(*,*)'INT:',int(value+1)
    > exit
    > endif
    > enddo
    > write(*,*)'value:',value
    > write(*,*)'huge(0):',huge(0)
    > write(*,*)'huge(0_int64):',huge(0_int64)
    > write(*,*)'huge(0_int32):',huge(0_int32)
    > write(*,*)'huge(0_int16):',huge(0_int16)
    > write(*,*)'huge(0_int8):',huge(0_int8)
    > end program testit
    >
    > VALUE: 2097153.0000000000
    > REAL(VALUE): 2097153.00
    > NINT(REAL(VALUE)): 2097153
    > NINT(VALUE): 2097152
    > NINT(VALUE): -1
    > NINT(VALUE): 2097154
    > INT: 2097152
    > INT: 2097153
    > INT: 2097154
    > value: 2097153.0000000000
    > huge(0): 2147483647
    > huge(0_int64): 9223372036854775807
    > huge(0_int32): 2147483647
    > huge(0_int16): 32767
    > huge(0_int8): 127

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Steven G. Kargl@21:1/5 to John on Wed Nov 16 17:45:27 2022
    On Wed, 16 Nov 2022 05:09:41 -0800, John wrote:

    I am on a Linux mint box using KVM and
    running a virtual box that is
    OpenBSD mo.my.domain 7.2 GENERIC#381 i386
    using
    GNU Fortran (GCC) 11.2.0
    and am getting negative values from NINT()
    on doubleprecision values when I do not expect
    them.

    John,

    At least on FreeBSD, gfortran maps nint() to the
    libm function lroundf(). I suspect that you're
    seeing an OpenBSD bug. Writing the equivalent
    test in C and linking with libm should either
    verify my assertion or invalidate it.

    --
    steve

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robert Corbett@21:1/5 to urba...@comcast.net on Wed Nov 16 10:44:04 2022
    I do not know what the problem is, but note that

    2**21 = 2097152

    Therefore, 2097153.0D0 is the smallest positive
    integer value where a bit is set in the low-order
    32-bits of its IEEE float64 representation. It might
    be interesting to know what the value of

    NINT(2097155.0D0)

    is.

    Bob Corbett

    On Wednesday, November 16, 2022 at 5:09:43 AM UTC-8, urba...@comcast.net wrote:
    I am on a Linux mint box using KVM and
    running a virtual box that is
    OpenBSD mo.my.domain 7.2 GENERIC#381 i386
    using
    GNU Fortran (GCC) 11.2.0
    and am getting negative values from NINT()
    on doubleprecision values when I do not expect
    them.

    I thought NINT() took any KIND of REAL so I did
    not expect that; but it has been a while since
    I ran on i386, and I am on a virtual box.

    If I do a NINT(REAL(value)) instead of NINT(value)
    I get the expected INTEGER value.

    Any reason I should expect NINT() to not work
    with values still within the range of the default
    INTEGER kind?

    Anyone have a 32-bit box with gfortran on it that
    could see if they start getting negative values
    with doubleprecision input values below HUGE(0)?

    program testit
    use,intrinsic :: iso_fortran_env, only : int8, int16, int32, int64 use,intrinsic :: iso_fortran_env, only : real32, real64, real128
    implicit none
    doubleprecision :: value
    integer :: i
    do i=0,huge(0)-1
    value=i
    if(nint(value).lt.0)then
    write(*,*)'VALUE:',value
    write(*,*)'REAL(VALUE):',real(value) write(*,*)'NINT(REAL(VALUE)):',nint(real(value)) write(*,*)'NINT(VALUE):',nint(value-1)
    write(*,*)'NINT(VALUE):',nint(value)
    write(*,*)'NINT(VALUE):',nint(value+1)
    write(*,*)'INT:',int(value-1)
    write(*,*)'INT:',int(value)
    write(*,*)'INT:',int(value+1)
    exit
    endif
    enddo
    write(*,*)'value:',value
    write(*,*)'huge(0):',huge(0)
    write(*,*)'huge(0_int64):',huge(0_int64) write(*,*)'huge(0_int32):',huge(0_int32) write(*,*)'huge(0_int16):',huge(0_int16) write(*,*)'huge(0_int8):',huge(0_int8)
    end program testit

    VALUE: 2097153.0000000000
    REAL(VALUE): 2097153.00
    NINT(REAL(VALUE)): 2097153
    NINT(VALUE): 2097152
    NINT(VALUE): -1
    NINT(VALUE): 2097154
    INT: 2097152
    INT: 2097153
    INT: 2097154
    value: 2097153.0000000000
    huge(0): 2147483647
    huge(0_int64): 9223372036854775807
    huge(0_int32): 2147483647
    huge(0_int16): 32767
    huge(0_int8): 127

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to urba...@comcast.net on Wed Nov 16 15:47:30 2022
    On Wednesday, November 16, 2022 at 5:09:43 AM UTC-8, urba...@comcast.net wrote:

    (snip)

    Anyone have a 32-bit box with gfortran on it that
    could see if they start getting negative values
    with doubleprecision input values below HUGE(0)?

    value: 2147483646.00000
    huge(0): 2147483647
    huge(0_int64): 9223372036854775807
    huge(0_int32): 2147483647
    huge(0_int16): 32767
    huge(0_int8): 127

    This is from: GNU Fortran (GCC) 4.1.2 20080704 (Red Hat 4.1.2-50)
    and: Linux pion.egn2.com 2.6.18-164.11.1.el5xen #1 SMP Wed Jan 20 01:48:45 EST 2010 i686 athlon i386 GNU/Linux

    I had to put in constants for the intxxx values, as it doesn't have them.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Steven G. Kargl@21:1/5 to All on Wed Nov 16 23:53:30 2022
    On Wed, 16 Nov 2022 15:47:30 -0800, gah4 wrote:

    This is from: GNU Fortran (GCC) 4.1.2 20080704 (Red Hat 4.1.2-50)

    20080704 is a few years beyond its use-by-date.

    and: Linux pion.egn2.com 2.6.18-164.11.1.el5xen #1 SMP Wed Jan 20 01:48:45 EST 2010 i686 athlon i386 GNU/Linux

    I had to put in constants for the intxxx values, as it doesn't have them.

    I suspect some bug fixes and features of the Fortran language may
    have been implemented in the last 14 years.

    --
    steve

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From gah4@21:1/5 to Steven G. Kargl on Wed Nov 16 16:42:49 2022
    On Wednesday, November 16, 2022 at 3:53:34 PM UTC-8, Steven G. Kargl wrote:
    On Wed, 16 Nov 2022 15:47:30 -0800, gah4 wrote:

    This is from: GNU Fortran (GCC) 4.1.2 20080704 (Red Hat 4.1.2-50)
    20080704 is a few years beyond its use-by-date.
    and: Linux pion.egn2.com 2.6.18-164.11.1.el5xen #1 SMP Wed Jan 20 01:48:45 EST 2010 i686 athlon i386 GNU/Linux

    I had to put in constants for the intxxx values, as it doesn't have them.

    I suspect some bug fixes and features of the Fortran language may
    have been implemented in the last 14 years.

    I think the one I use more is 64 bit, though, and the OP asked for 32 bit.

    That is on ScientificLinux, the version that installs with it.
    I did try to update once, but it failed.

    In any case, it seemed useful as a comparison to see if/when
    the bug appeared. And it is interesting to see where it
    did go negative, where it wasn't so obvious.

    I do sometimes use the C compiler on that machine, though
    it is also old.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From John@21:1/5 to All on Thu Nov 17 05:55:54 2022
    Not sure I am testing what you suggested well enough, but this did not indicate any problem. Maybe some type of type mismatch;
    the odd numbers all start returning -1; which makes the point about the "magic number" being the first incorrect result even more interesting;
    maybe a type mismatch issue(?). So works if input value is REAL instead of DOUBLEPRECISION; works on 64-bit OpenBSD; going to try some intentional type mismatches to see if I can reproduce at the C level; opened a bugzilla report in gfortran as I
    guessing it might be something simple as it works fine for default REAL and C confidence test passed. If that is not the type of C test intended let me know.

    #include <math.h>
    #include <errno.h>
    #include <fenv.h>
    #include <stdio.h>
    #include <limits.h>
    main(){
    double xl;
    int ierr;
    int i;
    int iout;
    printf("size of xl is %ld\n",sizeof(xl));
    for(i=0;i<=INT_MAX;i=i+1){
    xl=i;
    errno=0;
    feclearexcept(FE_ALL_EXCEPT);
    iout=lroundf(xl);
    if(iout < 0){
    printf("%d xl rounded is %d \n",i,iout);
    if (errno != 0){
    printf("errno is %d\n",errno);
    ierr = fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW);
    printf("ERRNO:%d:FPE: %d\n" , errno, ierr);
    }
    break;
    }
    }
    printf("all done \%d\n",i);

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Steven G. Kargl@21:1/5 to John on Thu Nov 17 17:51:17 2022
    On Thu, 17 Nov 2022 05:55:54 -0800, John wrote:

    Not sure I am testing what you suggested well enough, but this did not indicate any problem. Maybe some type of type mismatch;
    the odd numbers all start returning -1; which makes the point about the "magic number" being the first incorrect result even more interesting;
    maybe a type mismatch issue(?). So works if input value is REAL instead of DOUBLEPRECISION; works on 64-bit OpenBSD; going to try some intentional type mismatches to see if I can reproduce at the C level; opened a bugzilla report in gfortran as I
    guessing it might be something simple as it works fine for default REAL and C confidence test passed. If that is not the type of C test intended let me know.

    The first thing I would do is look under gfortran's hood.
    Compile

    function foo1(x)
    real foo1, x
    foo1 = nint(x)
    end function

    function foo2(x)
    double precision foo2, x
    foo2 = nint(x)
    end function

    with -fdump-tree-original. Look at the file to see if
    you have __builtin_lroundx() calls with x = 'f' or missing.

    Next compile to assembly and check if you are getting calls
    to libm functions lroundf() and lround(). If you are, this
    is not a gfortran bug. It is an OpenBSD on i386 bug.

    I would then look at OpenBSD to see if any changes have
    occurred that might be related to lround().

    https://cvsweb.openbsd.org/src/lib/libm/src/?sortby=date#dirlist

    --
    steve

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From John@21:1/5 to Steven G. Kargl on Fri Nov 18 15:52:27 2022
    On Thursday, November 17, 2022 at 12:51:21 PM UTC-5, Steven G. Kargl wrote:
    On Thu, 17 Nov 2022 05:55:54 -0800, John wrote:

    Not sure I am testing what you suggested well enough, but this did not indicate any problem. Maybe some type of type mismatch;
    the odd numbers all start returning -1; which makes the point about the "magic number" being the first incorrect result even more interesting;
    maybe a type mismatch issue(?). So works if input value is REAL instead of DOUBLEPRECISION; works on 64-bit OpenBSD; going to try some intentional type mismatches to see if I can reproduce at the C level; opened a bugzilla report in gfortran as I
    guessing it might be something simple as it works fine for default REAL and C confidence test passed. If that is not the type of C test intended let me know.
    The first thing I would do is look under gfortran's hood.
    Compile

    function foo1(x)
    real foo1, x
    foo1 = nint(x)
    end function

    function foo2(x)
    double precision foo2, x
    foo2 = nint(x)
    end function

    with -fdump-tree-original. Look at the file to see if
    you have __builtin_lroundx() calls with x = 'f' or missing.

    Next compile to assembly and check if you are getting calls
    to libm functions lroundf() and lround(). If you are, this
    is not a gfortran bug. It is an OpenBSD on i386 bug.

    I would then look at OpenBSD to see if any changes have
    occurred that might be related to lround().

    https://cvsweb.openbsd.org/src/lib/libm/src/?sortby=date#dirlist

    --
    steve
    have some time constraints right now, but thanks for the great roadmap. I will use all of that.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)