1d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol/* sf_scalbn.c -- float version of s_scalbn.c.
2d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
3d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol */
4d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol
5d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol/*
6d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol * ====================================================
7d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol *
9d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol * Developed at SunPro, a Sun Microsystems, Inc. business.
10d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol * Permission to use, copy, modify, and distribute this
11d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol * software is freely granted, provided that this notice
12d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol * is preserved.
13d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol * ====================================================
14d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol */
15d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol
16d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#include "fdlibm.h"
17d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#include <limits.h>
18d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#include <float.h>
19d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol
20d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#if INT_MAX > 50000
21d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#define OVERFLOW_INT 50000
22d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#else
23d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#define OVERFLOW_INT 30000
24d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#endif
25d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol
26d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#ifdef __STDC__
27d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignolstatic const float
28d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#else
29d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignolstatic float
30d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#endif
31d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignoltwo25   =  3.355443200e+07,	/* 0x4c000000 */
32d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignoltwom25  =  2.9802322388e-08,	/* 0x33000000 */
33d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignolhuge   = 1.0e+30,
34d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignoltiny   = 1.0e-30;
35d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol
36d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#ifdef __STDC__
37d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	float scalbnf (float x, int n)
38d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#else
39d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	float scalbnf (x,n)
40d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	float x; int n;
41d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#endif
42d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol{
43d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	__int32_t  k,ix;
44d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	__uint32_t hx;
45d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol
46d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	GET_FLOAT_WORD(ix,x);
47d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	hx = ix&0x7fffffff;
48d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol        k = hx>>23;		/* extract exponent */
49d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	if (FLT_UWORD_IS_ZERO(hx))
50d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	    return x;
51d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol        if (!FLT_UWORD_IS_FINITE(hx))
52d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	    return x+x;		/* NaN or Inf */
53d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol        if (FLT_UWORD_IS_SUBNORMAL(hx)) {
54d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	    x *= two25;
55d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	    GET_FLOAT_WORD(ix,x);
56d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	    k = ((ix&0x7f800000)>>23) - 25;
57d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol            if (n< -50000) return tiny*x; 	/*underflow*/
58d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol        }
59d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol        k = k+n;
60d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol        if (k > FLT_LARGEST_EXP) return huge*copysignf(huge,x); /* overflow  */
61d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol        if (k > 0) 				/* normal result */
62d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	    {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;}
63d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol        if (k < FLT_SMALLEST_EXP) {
64d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol            if (n > OVERFLOW_INT) 	/* in case integer overflow in n+k */
65d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol		return huge*copysignf(huge,x);	/*overflow*/
66d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	    else return tiny*copysignf(tiny,x);	/*underflow*/
67d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol        }
68d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol        k += 25;				/* subnormal result */
69d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23));
70d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol        return x*twom25;
71d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol}
72d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol
73d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#ifdef _DOUBLE_IS_32BITS
74d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol
75d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#ifdef __STDC__
76d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	double scalbn(double x, int n)
77d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#else
78d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	double scalbn(x,n)
79d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	double x;
80d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	int n;
81d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#endif
82d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol{
83d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol	return (double) scalbnf((float) x, n);
84d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol}
85d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol
86d61f9ebd0671c1066118199537cd6057ecbf8697Andrew Rossignol#endif /* defined(_DOUBLE_IS_32BITS) */
87