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