Make sure modf() returns correct values for infinities. While there, drop
authormiod <miod@openbsd.org>
Sun, 13 Aug 2023 06:55:37 +0000 (06:55 +0000)
committermiod <miod@openbsd.org>
Sun, 13 Aug 2023 06:55:37 +0000 (06:55 +0000)
the few assembler versions as has been done on other *BSD systems; this
function (modf) turns out to be non-trivial enough, having only one
known-to-work version is preferrable.

Reported by Willemijn Coene.

lib/libc/arch/amd64/gen/Makefile.inc
lib/libc/arch/amd64/gen/modf.S [deleted file]
lib/libc/arch/i386/gen/Makefile.inc
lib/libc/arch/i386/gen/modf.S [deleted file]
lib/libc/arch/mips64/gen/Makefile.inc
lib/libc/arch/mips64/gen/modf.S [deleted file]
lib/libc/arch/sparc64/gen/Makefile.inc
lib/libc/arch/sparc64/gen/modf.S [deleted file]
lib/libc/gen/modf.c

index 7dcd8bd..c9f2c97 100644 (file)
@@ -1,6 +1,6 @@
-#      $OpenBSD: Makefile.inc,v 1.13 2020/07/06 13:33:05 pirofti Exp $
+#      $OpenBSD: Makefile.inc,v 1.14 2023/08/13 06:55:37 miod Exp $
 
-SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.S nan.c setjmp.S \
+SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c setjmp.S \
        sigsetjmp.S
 SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c \
        usertc.c
diff --git a/lib/libc/arch/amd64/gen/modf.S b/lib/libc/arch/amd64/gen/modf.S
deleted file mode 100644 (file)
index 394e682..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*     $OpenBSD: modf.S,v 1.6 2018/07/03 23:14:05 mortimer Exp $       */
-/*     $NetBSD: modf.S,v 1.1 2001/06/19 00:25:03 fvdl Exp $    */
-
-/*-
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Sean Eric Fagan.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *     from: @(#)modf.s        5.5 (Berkeley) 3/18/91
- */
-
-#include <machine/asm.h>
-
-/*
- * modf(value, iptr): return fractional part of value, and stores the
- * integral part into iptr (a pointer to double).
- *
- * Written by Sean Eric Fagan (sef@kithrup.COM)
- * Sun Mar 11 20:27:30 PST 1990
- */
-
-/* With CHOP mode on, frndint behaves as TRUNC does.  Useful. */
-ENTRY(modf)
-       RETGUARD_SETUP(modf, r11)
-
-       /*
-        * Set chop mode.
-        */
-       fnstcw  -12(%rsp)
-       movw    -12(%rsp),%dx
-       orw     $3072,%dx
-       movw    %dx,-16(%rsp)
-       fldcw   -16(%rsp)
-
-       /*
-        * Get integral part.
-        */
-       movsd   %xmm0,-24(%rsp)
-       fldl    -24(%rsp)
-       frndint
-       fstpl   -8(%rsp)
-
-       /*
-        * Restore control word.
-        */
-       fldcw   -12(%rsp)
-
-       /*
-        * Store integral part.
-        */
-       movsd   -8(%rsp),%xmm0
-       movsd   %xmm0,(%rdi)
-
-       /*
-        * Get fractional part and return it.
-        */
-       fldl    -24(%rsp)
-       fsubl   -8(%rsp)
-       fstpl   -8(%rsp)
-       movsd   -8(%rsp),%xmm0
-
-       RETGUARD_CHECK(modf, r11)
-       ret
-END(modf)
index 30b5f87..45d0108 100644 (file)
@@ -1,7 +1,7 @@
-#      $OpenBSD: Makefile.inc,v 1.15 2020/07/06 13:33:05 pirofti Exp $
+#      $OpenBSD: Makefile.inc,v 1.16 2023/08/13 06:55:37 miod Exp $
 
 SRCS+= _setjmp.S fabs.S infinity.c ldexp.c usertc.c \
-       modf.S nan.c setjmp.S sigsetjmp.S
+       modf.c nan.c setjmp.S sigsetjmp.S
 SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
 SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S fpsetmask.S \
        fpsetround.S fpsetsticky.S
diff --git a/lib/libc/arch/i386/gen/modf.S b/lib/libc/arch/i386/gen/modf.S
deleted file mode 100644 (file)
index 4b62361..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* $OpenBSD: modf.S,v 1.7 2011/07/08 22:28:33 martynas Exp $ */
-/*-
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Sean Eric Fagan.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <machine/asm.h>
-
-/*
- * modf(value, iptr): return fractional part of value, and stores the
- * integral part into iptr (a pointer to double).
- *
- * Written by Sean Eric Fagan (sef@kithrup.COM)
- * Sun Mar 11 20:27:30 PST 1990
- */
-
-/* With CHOP mode on, frndint behaves as TRUNC does.  Useful. */
-ENTRY(modf)
-       pushl   %ebp
-       movl    %esp,%ebp
-       subl    $16,%esp
-       fnstcw  -12(%ebp)
-       movw    -12(%ebp),%dx
-       orw     $3072,%dx
-       movw    %dx,-16(%ebp)
-       fldcw   -16(%ebp)
-       fldl    8(%ebp)
-       frndint
-       fstpl   -8(%ebp)
-       fldcw   -12(%ebp)
-       movl    16(%ebp),%eax
-       movl    -8(%ebp),%edx
-       movl    -4(%ebp),%ecx
-       movl    %edx,(%eax)
-       movl    %ecx,4(%eax)
-       fldl    8(%ebp)
-       fsubl   -8(%ebp)
-       jmp     L1
-L1:
-       leave
-       ret
index f3f8895..ca34aef 100644 (file)
@@ -1,6 +1,6 @@
-#      $OpenBSD: Makefile.inc,v 1.13 2020/07/06 13:33:05 pirofti Exp $
+#      $OpenBSD: Makefile.inc,v 1.14 2023/08/13 06:55:37 miod Exp $
 
-SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c usertc.c
+SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.c nan.c usertc.c
 SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
        fpsetround.c fpsetsticky.c
 SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c
diff --git a/lib/libc/arch/mips64/gen/modf.S b/lib/libc/arch/mips64/gen/modf.S
deleted file mode 100644 (file)
index 029e704..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/* $OpenBSD: modf.S,v 1.5 2011/07/08 22:28:33 martynas Exp $ */
-/*-
- * Copyright (c) 1991, 1993, 1995
- *     The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Ralph Campbell.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <machine/asm.h>
-
-/*
- * double modf(val, iptr)
- *     double val, *iptr;
- * returns: xxx and n (in *iptr) where val == n.xxx
- */
-LEAF(modf, 0)
-       .set    reorder
-       cfc1    t0, $31                 # get the control register
-       li.d    $f2, 4503599627370496e0 # f2 <- 2^52
-
-       or      t1, t0, 0x3             # set rounding mode to round to zero
-       xor     t1, t1, 0x2             #  (i.e., 01)
-       ctc1    t1, $31
-
-       mov.d   $f0, $f12               # f0 <- f12
-       abs.d   $f4, $f12               # f4 <- |f12|
-       c.olt.d $f4, $f2                # f4 ? < f2 
-       bc1f    1f                      # leave f0 alone if Nan, infinity 
-                                       # or >=2^52
-       c.eq.d  $f12,$f4                # was f12 positive ?
-       add.d   $f4,$f2,$f4             # round off to integer
-       bc1f    2f                      # No -> will have to negate result
-       sub.d   $f0,$f4,$f2             # Remove fudge factor
-       j       1f                      # integer fraction got
-2:     
-       sub.d   $f0,$f2,$f4             # Remove fudge factor and negate
-1:     
-       ctc1    t0, $31                 # restore old rounding mode
-#ifdef __mips64
-       s.d     $f0, 0(a1)              # save the integer part
-#else
-       s.d     $f0, 0(a2)              # save the integer part
-#endif
-       sub.d   $f0, $f12, $f0          # subtract val - integer part
-       j       ra
-END(modf)
index 6d19faf..5cbb1e6 100644 (file)
@@ -1,9 +1,9 @@
-#      $OpenBSD: Makefile.inc,v 1.16 2020/07/08 09:20:28 kettenis Exp $
+#      $OpenBSD: Makefile.inc,v 1.17 2023/08/13 06:55:37 miod Exp $
 
 SRCS+= _setjmp.S fabs.S fixunsdfsi.S flt_rounds.c fpclassifyl.c \
        fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
        fpsetround.c fpsetsticky.c infinity.c isfinitel.c \
-       isinfl.c isnanl.c isnormall.c ldexp.c usertc.c modf.S \
+       isinfl.c isnanl.c isnormall.c ldexp.c usertc.c modf.c \
        mul.S nan.c setjmp.S signbitl.c sigsetjmp.S umul.S
 
 CFLAGS += -Wa,-Av9b
diff --git a/lib/libc/arch/sparc64/gen/modf.S b/lib/libc/arch/sparc64/gen/modf.S
deleted file mode 100644 (file)
index 4fa2ea5..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/*     $OpenBSD: modf.S,v 1.7 2023/01/13 17:52:08 miod Exp $   */
-/*     $NetBSD: modf.S,v 1.3 2000/11/01 23:32:41 eeh Exp $     */
-
-/*
- * Copyright (c) 1992, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * This software was developed by the Computer Systems Engineering group
- * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
- * contributed to Berkeley.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <machine/asm.h>
-
-#include <machine/fsr.h>
-
-/*
- * double modf(double val, double *iptr)
- *
- * Returns the fractional part of `val', storing the integer part of
- * `val' in *iptr.  Both *iptr and the return value have the same sign
- * as `val'.
- *
- * Method:
- *
- * We use the fpu's normalization hardware to compute the integer portion
- * of the double precision argument.  Sun IEEE double precision numbers
- * have 52 bits of mantissa, 11 bits of exponent, and one bit of sign,
- * with the sign occupying bit 31 of word 0, and the exponent bits 30:20
- * of word 0.  Thus, values >= 2^52 are by definition integers.
- *
- * If we take a value that is in the range [+0..2^52) and add 2^52, all
- * of the fractional bits fall out and all of the integer bits are summed
- * with 2^52.  If we then subtract 2^52, we get those integer bits back.
- * This must be done with rounding set to `towards 0' or `towards -inf'.
- * `Toward -inf' fails when the value is 0 (we get -0 back)....
- *
- * Note that this method will work anywhere, but is machine dependent in
- * various aspects.
- *
- * Stack usage:
- *     4@[%fp + BIAS - 4]      saved %fsr
- *     4@[%fp + BIAS - 8]      new %fsr with rounding set to `towards 0'
- *     8@[%fp + BIAS - 16]     space for moving between %i and %f registers
- * Register usage:
- *     %f0:f1          double val;
- *     %l0             scratch
- *     %l1             sign bit (0x80000000)
- *     %i1             double *iptr;
- *     %f2:f3          `magic number' 2^52, in fpu registers
- *     %f4:f5          double v, in fpu registers
- *     %f6:f7          double temp.
- */
-
-       .section .rodata
-       .align  8
-Lmagic:
-       .word   0x43300000      ! sign = 0, exponent = 52 + 1023, mantissa = 0
-       .word   0               ! (i.e., .double 0r4503599627370496e+00)
-
-L0:
-       .word   0               ! 0.0
-       .word   0
-
-       .text
-ENTRY(modf)
-       save    %sp, -CC64FSZ-16, %sp
-#ifdef __PIC__
-       PIC_PROLOGUE(%o5, %o4)
-#endif
-
-       /*
-        * First, compute v = abs(val)
-        */
-       fabsd   %f0, %f4                ! %f4:f5 = v
-       fcmped  %fcc1, %f0, %f4         ! %fcc1 = (val == abs(val))
-#ifdef __PIC__
-       set     Lmagic, %o4
-       ldx     [%o5 + %o4], %l0
-       ldd     [%l0], %f2
-#else
-       sethi   %hi(Lmagic), %l0
-       ldd     [%l0 + %lo(Lmagic)], %f2
-#endif
-
-       /*
-        * Is %f4:f5 >= %f2:f3 ?  If so, it is all integer bits.
-        * It is probably less, though.
-        */
-       fcmped  %f4, %f2
-       fbuge   Lbig                    ! if >= (or unordered), go out
-       nop
-
-       /*
-        * v < 2^52, so add 2^52, then subtract 2^52, but do it all
-        * with rounding set towards zero.  We leave any enabled
-        * traps enabled, but change the rounding mode.  This might
-        * not be so good.  Oh well....
-        */
-       st      %fsr, [%fp + BIAS - 4]  ! %l5 = current FSR mode
-       set     FSR_RD, %l3             ! %l3 = rounding direction mask
-       ld      [%fp + BIAS - 4], %l5
-       set     FSR_RD_RZ << FSR_RD_SHIFT, %l4
-       andn    %l5, %l3, %l6
-       or      %l6, %l4, %l6           ! round towards zero, please
-       and     %l5, %l3, %l5           ! save original rounding mode
-       st      %l6, [%fp + BIAS - 8]
-       ld      [%fp + BIAS - 8], %fsr
-
-       faddd   %f4, %f2, %f4           ! %f4:f5 += 2^52
-       fsubd   %f4, %f2, %f4           ! %f4:f5 -= 2^52
-
-       /*
-        * Restore %fsr, but leave exceptions accrued.
-        */
-       st      %fsr, [%fp + BIAS - 4]
-       ld      [%fp + BIAS - 4], %l6
-       andn    %l6, %l3, %l6           ! %l6 = %fsr & ~FSR_RD;
-       or      %l5, %l6, %l5           ! %l5 |= %l6;
-       st      %l5, [%fp + BIAS - 4]
-       ld      [%fp + BIAS - 4], %fsr  ! restore %fsr, leaving accrued stuff
-
-       /*
-        * Now insert the original sign in %f4:f5.
-        * %fcc1 should still have the reults of (val == abs(val))
-        * from above, so we use a conditional move on %fcc1 to: 
-        *
-        *      %f4 = (val == abs(val)) ? %f4 : -%f4
-        *
-        */
-       fnegd   %f4, %f6
-       fmovdnz %fcc1, %f6, %f4
-1:
-
-       /*
-        * The value in %f4:f5 is now the integer portion of the original
-        * argument.  We need to store this in *ival (%i1), subtract it
-        * from the original value argument (%d0), and return the result.
-        */
-       std     %f4, [%i1]              ! *ival = %f4:f5;
-       fsubd   %f0, %f4, %f0           ! %f0:f1 -= %f4:f5;
-       ret
-       restore
-
-Lbig:
-       /*
-        * We get here if the original comparison of %f4:f5 (v) to
-        * %f2:f3 (2^52) came out `greater or unordered'.  In this
-        * case the integer part is the original value, and the
-        * fractional part is 0.
-        */
-#ifdef __PIC__
-       set     L0, %o4
-       ldx     [%o5 + %o4], %l0
-       std     %f0, [%i1]              ! *ival = val;
-       ldd     [%l0], %f0              ! return 0.0;
-#else
-       sethi   %hi(L0), %l0
-       std     %f0, [%i1]              ! *ival = val;
-       ldd     [%l0 + %lo(L0)], %f0    ! return 0.0;
-#endif
-       ret
-        restore
-
index 5c52351..e02e8c1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: modf.c,v 1.6 2013/07/03 04:46:36 espie Exp $  */
+/*     $OpenBSD: modf.c,v 1.7 2023/08/13 06:55:37 miod Exp $   */
 /*     $NetBSD: modf.c,v 1.1 1995/02/10 17:50:25 cgd Exp $     */
 
 /*
@@ -51,11 +51,13 @@ modf(double val, double *iptr)
        u_int64_t frac;
 
        /*
-        * If input is Inf or NaN, return it and leave i alone.
+        * If input is +/-Inf or NaN, return +/-0 or NaN.
         */
        u.v = val;
-       if (u.s.dbl_exp == DBL_EXP_INFNAN)
-               return (u.v);
+       if (u.s.dbl_exp == DBL_EXP_INFNAN) {
+               *iptr = u.v;
+               return (0.0 / u.v);
+       }
 
        /*
         * If input can't have a fractional part, return