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