s_scalbn.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       s_scalbn.c (1887B)
       ---
            1 /* @(#)s_scalbn.c 5.1 93/09/24 */
            2 /*
            3  * ====================================================
            4  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
            5  *
            6  * Developed at SunPro, a Sun Microsystems, Inc. business.
            7  * Permission to use, copy, modify, and distribute this
            8  * software is freely granted, provided that this notice
            9  * is preserved.
           10  * ====================================================
           11  */
           12 
           13 #ifndef lint
           14 static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_scalbn.c,v 1.9 2003/07/23 04:53:47 peter Exp $";
           15 #endif
           16 
           17 /*
           18  * scalbn (double x, int n)
           19  * scalbn(x,n) returns x* 2**n  computed by  exponent
           20  * manipulation rather than by actually performing an
           21  * exponentiation or a multiplication.
           22  */
           23 
           24 #include "math.h"
           25 #include "math_private.h"
           26 
           27 static const double
           28 two54   =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
           29 twom54  =  5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
           30 huge   = 1.0e+300,
           31 tiny   = 1.0e-300;
           32 
           33 double
           34 scalbn (double x, int n)
           35 {
           36         int32_t k,hx,lx;
           37         EXTRACT_WORDS(hx,lx,x);
           38         k = (hx&0x7ff00000)>>20;                /* extract exponent */
           39         if (k==0) {                                /* 0 or subnormal x */
           40             if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
           41             x *= two54;
           42             GET_HIGH_WORD(hx,x);
           43             k = ((hx&0x7ff00000)>>20) - 54;
           44             if (n< -50000) return tiny*x;         /*underflow*/
           45             }
           46         if (k==0x7ff) return x+x;                /* NaN or Inf */
           47         k = k+n;
           48         if (k >  0x7fe) return huge*copysign(huge,x); /* overflow  */
           49         if (k > 0)                                 /* normal result */
           50             {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;}
           51         if (k <= -54)
           52             if (n > 50000)         /* in case integer overflow in n+k */
           53                 return huge*copysign(huge,x);        /*overflow*/
           54             else return tiny*copysign(tiny,x);         /*underflow*/
           55         k += 54;                                /* subnormal result */
           56         SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20));
           57         return x*twom54;
           58 }