POK
scalbnf.c
1 /*
2  * POK header
3  *
4  * The following file is a part of the POK project. Any modification should
5  * made according to the POK licence. You CANNOT use this file or a part of
6  * this file is this part of a file for your own project
7  *
8  * For more information on the POK licence, please see our LICENCE FILE
9  *
10  * Please follow the coding guidelines described in doc/CODING_GUIDELINES
11  *
12  * Copyright (c) 2007-2009 POK team
13  *
14  * Created by julien on Fri Jan 30 14:41:34 2009
15  */
16 
17 /* s_scalbnf.c -- float version of s_scalbn.c.
18  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
19  */
20 
21 /*
22  * ====================================================
23  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
24  *
25  * Developed at SunPro, a Sun Microsystems, Inc. business.
26  * Permission to use, copy, modify, and distribute this
27  * software is freely granted, provided that this notice
28  * is preserved.
29  * ====================================================
30  */
31 
32 #ifdef POK_NEEDS_LIBMATH
33 
34 #include <libm.h>
35 #include "math_private.h"
36 
37 static const float
38 two25 = 3.355443200e+07, /* 0x4c000000 */
39 twom25 = 2.9802322388e-08, /* 0x33000000 */
40 huge = 1.0e+30,
41 tiny = 1.0e-30;
42 
43 float
44 scalbnf(float x, int n)
45 {
46  int32_t k,ix;
47  GET_FLOAT_WORD(ix,x);
48  k = (ix&0x7f800000)>>23; /* extract exponent */
49  if (k==0) { /* 0 or subnormal x */
50  if ((ix&0x7fffffff)==0) return x; /* +-0 */
51  x *= two25;
52  GET_FLOAT_WORD(ix,x);
53  k = ((ix&0x7f800000)>>23) - 25;
54  if (n< -50000) return tiny*x; /*underflow*/
55  }
56  if (k==0xff) return x+x; /* NaN or Inf */
57  k = k+n;
58  if (k > 0xfe) return huge*copysignf(huge,x); /* overflow */
59  if (k > 0) /* normal result */
60  {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;}
61  if (k <= -25) {
62  if (n > 50000) /* in case integer overflow in n+k */
63  return huge*copysignf(huge,x); /*overflow*/
64  else return tiny*copysignf(tiny,x); /*underflow*/
65  }
66  k += 25; /* subnormal result */
67  SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23));
68  return x*twom25;
69 }
70 
71 #endif