s_asinh.c revision 176451
12116Sjkh/* @(#)s_asinh.c 5.1 93/09/24 */
22116Sjkh/*
32116Sjkh * ====================================================
42116Sjkh * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
52116Sjkh *
62116Sjkh * Developed at SunPro, a Sun Microsystems, Inc. business.
72116Sjkh * Permission to use, copy, modify, and distribute this
88870Srgrimes * software is freely granted, provided that this notice
92116Sjkh * is preserved.
102116Sjkh * ====================================================
112116Sjkh */
122116Sjkh
13176451Sdas#include <sys/cdefs.h>
14176451Sdas__FBSDID("$FreeBSD: head/lib/msun/src/s_asinh.c 176451 2008-02-22 02:30:36Z das $");
152116Sjkh
162116Sjkh/* asinh(x)
172116Sjkh * Method :
188870Srgrimes *	Based on
192116Sjkh *		asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
202116Sjkh *	we have
212116Sjkh *	asinh(x) := x  if  1+x*x=1,
222116Sjkh *		 := sign(x)*(log(x)+ln2)) for large |x|, else
232116Sjkh *		 := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
248870Srgrimes *		 := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
252116Sjkh */
262116Sjkh
272116Sjkh#include "math.h"
282116Sjkh#include "math_private.h"
292116Sjkh
308870Srgrimesstatic const double
312116Sjkhone =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
322116Sjkhln2 =  6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
338870Srgrimeshuge=  1.00000000000000000000e+300;
342116Sjkh
3597413Salfreddouble
3697413Salfredasinh(double x)
378870Srgrimes{
382116Sjkh	double t,w;
392116Sjkh	int32_t hx,ix;
402116Sjkh	GET_HIGH_WORD(hx,x);
412116Sjkh	ix = hx&0x7fffffff;
422116Sjkh	if(ix>=0x7ff00000) return x+x;	/* x is inf or NaN */
432116Sjkh	if(ix< 0x3e300000) {	/* |x|<2**-28 */
442116Sjkh	    if(huge+x>one) return x;	/* return x inexact except 0 */
458870Srgrimes	}
462116Sjkh	if(ix>0x41b00000) {	/* |x| > 2**28 */
472116Sjkh	    w = __ieee754_log(fabs(x))+ln2;
482116Sjkh	} else if (ix>0x40000000) {	/* 2**28 > |x| > 2.0 */
492116Sjkh	    t = fabs(x);
5023579Sbde	    w = __ieee754_log(2.0*t+one/(__ieee754_sqrt(x*x+one)+t));
512116Sjkh	} else {		/* 2.0 > |x| > 2**-28 */
522116Sjkh	    t = x*x;
5323579Sbde	    w =log1p(fabs(x)+t/(one+__ieee754_sqrt(one+t)));
542116Sjkh	}
552116Sjkh	if(hx>0) return w; else return -w;
562116Sjkh}
57