11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* @(#)s_scalbn.c 5.1 93/09/24 */
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* @(#)fdlibm.h 5.1 93/09/24 */
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ====================================================
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Developed at SunPro, a Sun Microsystems, Inc. business.
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Permission to use, copy, modify, and distribute this
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * software is freely granted, provided that this notice
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * is preserved.
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ====================================================
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/cdefs.h>
1557a883640f3b43bf5e332d64489b3eab67a5ac3fElliott Hughes__FBSDID("$FreeBSD$");
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/types.h>
1857a883640f3b43bf5e332d64489b3eab67a5ac3fElliott Hughes#include <machine/endian.h>
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <math.h>
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Bit fiddling routines copied from msun/src/math_private.h,v 1.15 */
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if BYTE_ORDER == BIG_ENDIAN
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttypedef union
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  double value;
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  struct
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  {
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    u_int32_t msw;
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    u_int32_t lsw;
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  } parts;
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} ieee_double_shape_type;
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if BYTE_ORDER == LITTLE_ENDIAN
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttypedef union
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  double value;
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  struct
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  {
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    u_int32_t lsw;
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    u_int32_t msw;
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  } parts;
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} ieee_double_shape_type;
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Get two 32 bit ints from a double.  */
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define EXTRACT_WORDS(ix0,ix1,d)				\
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdo {								\
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  ieee_double_shape_type ew_u;					\
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  ew_u.value = (d);						\
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  (ix0) = ew_u.parts.msw;					\
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  (ix1) = ew_u.parts.lsw;					\
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} while (0)
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Get the more significant 32 bit int from a double.  */
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define GET_HIGH_WORD(i,d)					\
641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdo {								\
651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  ieee_double_shape_type gh_u;					\
661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  gh_u.value = (d);						\
671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  (i) = gh_u.parts.msw;						\
681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} while (0)
691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* Set the more significant 32 bits of a double from an int.  */
711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define SET_HIGH_WORD(d,v)					\
731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdo {								\
741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  ieee_double_shape_type sh_u;					\
751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  sh_u.value = (d);						\
761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  sh_u.parts.msw = (v);						\
771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project  (d) = sh_u.value;						\
781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} while (0)
791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const double
821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttwo54   =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttwom54  =  5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecthuge   = 1.0e+300,
851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecttiny   = 1.0e-300;
861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic double
881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project_copysign(double x, double y)
891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_int32_t hx,hy;
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	GET_HIGH_WORD(hx,x);
921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	GET_HIGH_WORD(hy,y);
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000));
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return x;
951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdouble
981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectldexp(double x, int n)
991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int32_t k,hx,lx;
1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	EXTRACT_WORDS(hx,lx,x);
1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        k = (hx&0x7ff00000)>>20;		/* extract exponent */
1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if (k==0) {				/* 0 or subnormal x */
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    x *= two54;
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    GET_HIGH_WORD(hx,x);
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    k = ((hx&0x7ff00000)>>20) - 54;
1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if (n< -50000) return tiny*x; 	/*underflow*/
1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    }
1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if (k==0x7ff) return x+x;		/* NaN or Inf */
1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        k = k+n;
1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if (k >  0x7fe) return huge*_copysign(huge,x); /* overflow  */
1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if (k > 0) 				/* normal result */
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;}
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        if (k <= -54) {
1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project            if (n > 50000) 	/* in case integer overflow in n+k */
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return huge*_copysign(huge,x);	/*overflow*/
1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    else return tiny*_copysign(tiny,x); 	/*underflow*/
1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        k += 54;				/* subnormal result */
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20));
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        return x*twom54;
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
124