Back to index

glibc  2.9
s_modfl.c
Go to the documentation of this file.
00001 /* s_modfl.c -- long double version of s_modf.c.
00002  * Conversion to long double by Ulrich Drepper,
00003  * Cygnus Support, drepper@cygnus.com.
00004  */
00005 
00006 /*
00007  * ====================================================
00008  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
00009  *
00010  * Developed at SunPro, a Sun Microsystems, Inc. business.
00011  * Permission to use, copy, modify, and distribute this
00012  * software is freely granted, provided that this notice
00013  * is preserved.
00014  * ====================================================
00015  */
00016 
00017 #if defined(LIBM_SCCS) && !defined(lint)
00018 static char rcsid[] = "$NetBSD: $";
00019 #endif
00020 
00021 /*
00022  * modfl(long double x, long double *iptr)
00023  * return fraction part of x, and return x's integral part in *iptr.
00024  * Method:
00025  *     Bit twiddling.
00026  *
00027  * Exception:
00028  *     No exception.
00029  */
00030 
00031 #include "math.h"
00032 #include "math_private.h"
00033 
00034 #ifdef __STDC__
00035 static const long double one = 1.0;
00036 #else
00037 static long double one = 1.0;
00038 #endif
00039 
00040 #ifdef __STDC__
00041        long double __modfl(long double x, long double *iptr)
00042 #else
00043        long double __modfl(x, iptr)
00044        long double x,*iptr;
00045 #endif
00046 {
00047        int32_t i0,i1,j0;
00048        u_int32_t i,se;
00049        GET_LDOUBLE_WORDS(se,i0,i1,x);
00050        j0 = (se&0x7fff)-0x3fff;    /* exponent of x */
00051        if(j0<32) {                 /* integer part in high x */
00052            if(j0<0) {                     /* |x|<1 */
00053                SET_LDOUBLE_WORDS(*iptr,se&0x8000,0,0);  /* *iptr = +-0 */
00054               return x;
00055            } else {
00056               i = (0x7fffffff)>>j0;
00057               if(((i0&i)|i1)==0) {        /* x is integral */
00058                   *iptr = x;
00059                   SET_LDOUBLE_WORDS(x,se&0x8000,0,0);   /* return +-0 */
00060                   return x;
00061               } else {
00062                   SET_LDOUBLE_WORDS(*iptr,se,i0&(~i),0);
00063                   return x - *iptr;
00064               }
00065            }
00066        } else if (j0>63) {         /* no fraction part */
00067            *iptr = x*one;
00068            /* We must handle NaNs separately.  */
00069            if (j0 == 0x4000 && ((i0 & 0x7fffffff) | i1))
00070              return x*one;
00071            SET_LDOUBLE_WORDS(x,se&0x8000,0,0);   /* return +-0 */
00072            return x;
00073        } else {                    /* fraction part in low x */
00074            i = ((u_int32_t)(0x7fffffff))>>(j0-32);
00075            if((i1&i)==0) {         /* x is integral */
00076               *iptr = x;
00077               SET_LDOUBLE_WORDS(x,se&0x8000,0,0);       /* return +-0 */
00078               return x;
00079            } else {
00080               SET_LDOUBLE_WORDS(*iptr,se,i0,i1&(~i));
00081               return x - *iptr;
00082            }
00083        }
00084 }
00085 weak_alias (__modfl, modfl)