s_asinh.c revision 256281
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
82116Sjkh * software is freely granted, provided that this notice
92116Sjkh * is preserved.
102116Sjkh * ====================================================
118870Srgrimes */
122116Sjkh
132116Sjkh#include <sys/cdefs.h>
142116Sjkh__FBSDID("$FreeBSD: stable/10/lib/msun/src/s_asinh.c 251599 2013-06-10 06:04:58Z das $");
152116Sjkh
162116Sjkh/* asinh(x)
1750476Speter * Method :
182116Sjkh *	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
2397413Salfred *		 := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
2497413Salfred *		 := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
252116Sjkh */
26143216Sdas
272116Sjkh#include <float.h>
282116Sjkh
292116Sjkh#include "math.h"
302116Sjkh#include "math_private.h"
312116Sjkh
322116Sjkhstatic const double
332116Sjkhone =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
348870Srgrimesln2 =  6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
358870Srgrimeshuge=  1.00000000000000000000e+300;
368870Srgrimes
37140685Sdasdouble
382116Sjkhasinh(double x)
392116Sjkh{
40143216Sdas	double t,w;
41143216Sdas	int32_t hx,ix;
428870Srgrimes	GET_HIGH_WORD(hx,x);
432116Sjkh	ix = hx&0x7fffffff;
442116Sjkh	if(ix>=0x7ff00000) return x+x;	/* x is inf or NaN */
452116Sjkh	if(ix< 0x3e300000) {	/* |x|<2**-28 */
462116Sjkh	    if(huge+x>one) return x;	/* return x inexact except 0 */
472116Sjkh	}
482116Sjkh	if(ix>0x41b00000) {	/* |x| > 2**28 */
492116Sjkh	    w = __ieee754_log(fabs(x))+ln2;
502116Sjkh	} else if (ix>0x40000000) {	/* 2**28 > |x| > 2.0 */
512116Sjkh	    t = fabs(x);
522116Sjkh	    w = __ieee754_log(2.0*t+one/(__ieee754_sqrt(x*x+one)+t));
532116Sjkh	} else {		/* 2.0 > |x| > 2**-28 */
542116Sjkh	    t = x*x;
552116Sjkh	    w =log1p(fabs(x)+t/(one+__ieee754_sqrt(one+t)));
562116Sjkh	}
572116Sjkh	if(hx>0) return w; else return -w;
582116Sjkh}
59143216Sdas
60143216Sdas#if LDBL_MANT_DIG == 53
612116Sjkh__weak_reference(asinh, asinhl);
622116Sjkh#endif
632116Sjkh