xref: /freebsd/lib/msun/src/s_modfl.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
19abb1ff6SDavid Schultz /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
35e53a4f9SPedro F. Giffuni  *
49abb1ff6SDavid Schultz  * Copyright (c) 2007 David Schultz <das@FreeBSD.ORG>
59abb1ff6SDavid Schultz  * All rights reserved.
69abb1ff6SDavid Schultz  *
79abb1ff6SDavid Schultz  * Redistribution and use in source and binary forms, with or without
89abb1ff6SDavid Schultz  * modification, are permitted provided that the following conditions
99abb1ff6SDavid Schultz  * are met:
109abb1ff6SDavid Schultz  * 1. Redistributions of source code must retain the above copyright
119abb1ff6SDavid Schultz  *    notice, this list of conditions and the following disclaimer.
129abb1ff6SDavid Schultz  * 2. Redistributions in binary form must reproduce the above copyright
139abb1ff6SDavid Schultz  *    notice, this list of conditions and the following disclaimer in the
149abb1ff6SDavid Schultz  *    documentation and/or other materials provided with the distribution.
159abb1ff6SDavid Schultz  *
169abb1ff6SDavid Schultz  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
179abb1ff6SDavid Schultz  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
189abb1ff6SDavid Schultz  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
199abb1ff6SDavid Schultz  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
209abb1ff6SDavid Schultz  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
219abb1ff6SDavid Schultz  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
229abb1ff6SDavid Schultz  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
239abb1ff6SDavid Schultz  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
249abb1ff6SDavid Schultz  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
259abb1ff6SDavid Schultz  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
269abb1ff6SDavid Schultz  * SUCH DAMAGE.
279abb1ff6SDavid Schultz  *
289abb1ff6SDavid Schultz  * Derived from s_modf.c, which has the following Copyright:
299abb1ff6SDavid Schultz  * ====================================================
309abb1ff6SDavid Schultz  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
319abb1ff6SDavid Schultz  *
329abb1ff6SDavid Schultz  * Developed at SunPro, a Sun Microsystems, Inc. business.
339abb1ff6SDavid Schultz  * Permission to use, copy, modify, and distribute this
349abb1ff6SDavid Schultz  * software is freely granted, provided that this notice
359abb1ff6SDavid Schultz  * is preserved.
369abb1ff6SDavid Schultz  * ====================================================
379abb1ff6SDavid Schultz  */
389abb1ff6SDavid Schultz 
399abb1ff6SDavid Schultz #include <float.h>
409abb1ff6SDavid Schultz #include <math.h>
419abb1ff6SDavid Schultz #include <sys/types.h>
429abb1ff6SDavid Schultz 
439abb1ff6SDavid Schultz #include "fpmath.h"
449abb1ff6SDavid Schultz 
459abb1ff6SDavid Schultz #if LDBL_MANL_SIZE > 32
469abb1ff6SDavid Schultz #define	MASK	((uint64_t)-1)
479abb1ff6SDavid Schultz #else
489abb1ff6SDavid Schultz #define	MASK	((uint32_t)-1)
499abb1ff6SDavid Schultz #endif
509abb1ff6SDavid Schultz /* Return the last n bits of a word, representing the fractional part. */
519abb1ff6SDavid Schultz #define	GETFRAC(bits, n)	((bits) & ~(MASK << (n)))
529abb1ff6SDavid Schultz /* The number of fraction bits in manh, not counting the integer bit */
539abb1ff6SDavid Schultz #define	HIBITS	(LDBL_MANT_DIG - LDBL_MANL_SIZE)
549abb1ff6SDavid Schultz 
559abb1ff6SDavid Schultz static const long double zero[] = { 0.0L, -0.0L };
569abb1ff6SDavid Schultz 
579abb1ff6SDavid Schultz long double
modfl(long double x,long double * iptr)589abb1ff6SDavid Schultz modfl(long double x, long double *iptr)
599abb1ff6SDavid Schultz {
609abb1ff6SDavid Schultz 	union IEEEl2bits ux;
619abb1ff6SDavid Schultz 	int e;
629abb1ff6SDavid Schultz 
639abb1ff6SDavid Schultz 	ux.e = x;
649abb1ff6SDavid Schultz 	e = ux.bits.exp - LDBL_MAX_EXP + 1;
659abb1ff6SDavid Schultz 	if (e < HIBITS) {			/* Integer part is in manh. */
669abb1ff6SDavid Schultz 		if (e < 0) {			/* |x|<1 */
679abb1ff6SDavid Schultz 			*iptr = zero[ux.bits.sign];
689abb1ff6SDavid Schultz 			return (x);
699abb1ff6SDavid Schultz 		} else {
709abb1ff6SDavid Schultz 			if ((GETFRAC(ux.bits.manh, HIBITS - 1 - e) |
719abb1ff6SDavid Schultz 			     ux.bits.manl) == 0) {	/* X is an integer. */
729abb1ff6SDavid Schultz 				*iptr = x;
739abb1ff6SDavid Schultz 				return (zero[ux.bits.sign]);
749abb1ff6SDavid Schultz 			} else {
759abb1ff6SDavid Schultz 				/* Clear all but the top e+1 bits. */
769abb1ff6SDavid Schultz 				ux.bits.manh >>= HIBITS - 1 - e;
779abb1ff6SDavid Schultz 				ux.bits.manh <<= HIBITS - 1 - e;
789abb1ff6SDavid Schultz 				ux.bits.manl = 0;
799abb1ff6SDavid Schultz 				*iptr = ux.e;
809abb1ff6SDavid Schultz 				return (x - ux.e);
819abb1ff6SDavid Schultz 			}
829abb1ff6SDavid Schultz 		}
839abb1ff6SDavid Schultz 	} else if (e >= LDBL_MANT_DIG - 1) {	/* x has no fraction part. */
849abb1ff6SDavid Schultz 		*iptr = x;
859abb1ff6SDavid Schultz 		if (x != x)			/* Handle NaNs. */
869abb1ff6SDavid Schultz 			return (x);
879abb1ff6SDavid Schultz 		return (zero[ux.bits.sign]);
889abb1ff6SDavid Schultz 	} else {				/* Fraction part is in manl. */
899abb1ff6SDavid Schultz 		if (GETFRAC(ux.bits.manl, LDBL_MANT_DIG - 1 - e) == 0) {
909abb1ff6SDavid Schultz 			/* x is integral. */
919abb1ff6SDavid Schultz 			*iptr = x;
929abb1ff6SDavid Schultz 			return (zero[ux.bits.sign]);
939abb1ff6SDavid Schultz 		} else {
949abb1ff6SDavid Schultz 			/* Clear all but the top e+1 bits. */
959abb1ff6SDavid Schultz 			ux.bits.manl >>= LDBL_MANT_DIG - 1 - e;
969abb1ff6SDavid Schultz 			ux.bits.manl <<= LDBL_MANT_DIG - 1 - e;
979abb1ff6SDavid Schultz 			*iptr = ux.e;
989abb1ff6SDavid Schultz 			return (x - ux.e);
999abb1ff6SDavid Schultz 		}
1009abb1ff6SDavid Schultz 	}
1019abb1ff6SDavid Schultz }
102