13a8617a8SJordan K. Hubbard /* s_cbrtf.c -- float version of s_cbrt.c. 23a8617a8SJordan K. Hubbard * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. 36de073b4SBruce Evans * Debugged by Bruce D. Evans. 43a8617a8SJordan K. Hubbard */ 53a8617a8SJordan K. Hubbard 63a8617a8SJordan K. Hubbard /* 73a8617a8SJordan K. Hubbard * ==================================================== 83a8617a8SJordan K. Hubbard * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 93a8617a8SJordan K. Hubbard * 103a8617a8SJordan K. Hubbard * Developed at SunPro, a Sun Microsystems, Inc. business. 113a8617a8SJordan K. Hubbard * Permission to use, copy, modify, and distribute this 123a8617a8SJordan K. Hubbard * software is freely granted, provided that this notice 133a8617a8SJordan K. Hubbard * is preserved. 143a8617a8SJordan K. Hubbard * ==================================================== 153a8617a8SJordan K. Hubbard */ 163a8617a8SJordan K. Hubbard 173a8617a8SJordan K. Hubbard #ifndef lint 187f3dea24SPeter Wemm static char rcsid[] = "$FreeBSD$"; 193a8617a8SJordan K. Hubbard #endif 203a8617a8SJordan K. Hubbard 213a8617a8SJordan K. Hubbard #include "math.h" 223a8617a8SJordan K. Hubbard #include "math_private.h" 233a8617a8SJordan K. Hubbard 243a8617a8SJordan K. Hubbard /* cbrtf(x) 253a8617a8SJordan K. Hubbard * Return cube root of x 263a8617a8SJordan K. Hubbard */ 273a8617a8SJordan K. Hubbard static const unsigned 28af7f9913SBruce Evans B1 = 709958130, /* B1 = (127-127.0/3-0.03306235651)*2**23 */ 29af7f9913SBruce Evans B2 = 642849266; /* B2 = (127-127.0/3-24/3-0.03306235651)*2**23 */ 303a8617a8SJordan K. Hubbard 313a8617a8SJordan K. Hubbard static const float 323a8617a8SJordan K. Hubbard C = 5.4285717010e-01, /* 19/35 = 0x3f0af8b0 */ 333a8617a8SJordan K. Hubbard D = -7.0530611277e-01, /* -864/1225 = 0xbf348ef1 */ 343a8617a8SJordan K. Hubbard E = 1.4142856598e+00, /* 99/70 = 0x3fb50750 */ 353a8617a8SJordan K. Hubbard F = 1.6071428061e+00, /* 45/28 = 0x3fcdb6db */ 363a8617a8SJordan K. Hubbard G = 3.5714286566e-01; /* 5/14 = 0x3eb6db6e */ 373a8617a8SJordan K. Hubbard 3859b19ff1SAlfred Perlstein float 3959b19ff1SAlfred Perlstein cbrtf(float x) 403a8617a8SJordan K. Hubbard { 416de073b4SBruce Evans float r,s,t,w; 423a8617a8SJordan K. Hubbard int32_t hx; 433a8617a8SJordan K. Hubbard u_int32_t sign; 443a8617a8SJordan K. Hubbard u_int32_t high; 453a8617a8SJordan K. Hubbard 463a8617a8SJordan K. Hubbard GET_FLOAT_WORD(hx,x); 473a8617a8SJordan K. Hubbard sign=hx&0x80000000; /* sign= sign(x) */ 483a8617a8SJordan K. Hubbard hx ^=sign; 493a8617a8SJordan K. Hubbard if(hx>=0x7f800000) return(x+x); /* cbrt(NaN,INF) is itself */ 503a8617a8SJordan K. Hubbard if(hx==0) 513a8617a8SJordan K. Hubbard return(x); /* cbrt(0) is itself */ 523a8617a8SJordan K. Hubbard 533a8617a8SJordan K. Hubbard SET_FLOAT_WORD(x,hx); /* x <- |x| */ 543a8617a8SJordan K. Hubbard /* rough cbrt to 5 bits */ 557d5a4821SBruce Evans if(hx<0x00800000) { /* subnormal number */ 567d5a4821SBruce Evans SET_FLOAT_WORD(t,0x4b800000); /* set t= 2**24 */ 577d5a4821SBruce Evans t*=x; 587d5a4821SBruce Evans GET_FLOAT_WORD(high,t); 597d5a4821SBruce Evans SET_FLOAT_WORD(t,high/3+B2); 607d5a4821SBruce Evans } else 613a8617a8SJordan K. Hubbard SET_FLOAT_WORD(t,hx/3+B1); 623a8617a8SJordan K. Hubbard 633a8617a8SJordan K. Hubbard /* new cbrt to 23 bits */ 643a8617a8SJordan K. Hubbard r=t*t/x; 653a8617a8SJordan K. Hubbard s=C+r*t; 663a8617a8SJordan K. Hubbard t*=G+F/(s+E+D/s); 673a8617a8SJordan K. Hubbard 686de073b4SBruce Evans /* chop t to 12 bits and make it larger than cbrt(x) */ 696de073b4SBruce Evans GET_FLOAT_WORD(high,t); 70288a8c86SBruce Evans SET_FLOAT_WORD(t,(high&0xfffff000)+0x00001000); 716de073b4SBruce Evans 72288a8c86SBruce Evans /* one step Newton iteration to 24 bits with error less than 0.667 ulps */ 736de073b4SBruce Evans s=t*t; /* t*t is exact */ 746de073b4SBruce Evans r=x/s; 756de073b4SBruce Evans w=t+t; 766de073b4SBruce Evans r=(r-t)/(w+r); /* r-t is exact */ 776de073b4SBruce Evans t=t+t*r; 786de073b4SBruce Evans 79af7f9913SBruce Evans /* restore the sign bit */ 803a8617a8SJordan K. Hubbard GET_FLOAT_WORD(high,t); 813a8617a8SJordan K. Hubbard SET_FLOAT_WORD(t,high|sign); 823a8617a8SJordan K. Hubbard return(t); 833a8617a8SJordan K. Hubbard } 84