s_asinh.c revision 8870
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
132116Sjkh#ifndef lint
148870Srgrimesstatic char rcsid[] = "$Id: s_asinh.c,v 1.1.1.1 1994/08/19 09:39:45 jkh Exp $";
152116Sjkh#endif
162116Sjkh
172116Sjkh/* asinh(x)
182116Sjkh * Method :
198870Srgrimes *	Based on
202116Sjkh *		asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
212116Sjkh *	we have
222116Sjkh *	asinh(x) := x  if  1+x*x=1,
232116Sjkh *		 := sign(x)*(log(x)+ln2)) for large |x|, else
242116Sjkh *		 := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
258870Srgrimes *		 := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
262116Sjkh */
272116Sjkh
282116Sjkh#include "math.h"
292116Sjkh#include "math_private.h"
302116Sjkh
312116Sjkh#ifdef __STDC__
328870Srgrimesstatic const double
332116Sjkh#else
348870Srgrimesstatic double
352116Sjkh#endif
362116Sjkhone =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
372116Sjkhln2 =  6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
388870Srgrimeshuge=  1.00000000000000000000e+300;
392116Sjkh
402116Sjkh#ifdef __STDC__
412116Sjkh	double asinh(double x)
422116Sjkh#else
432116Sjkh	double asinh(x)
442116Sjkh	double x;
452116Sjkh#endif
468870Srgrimes{
472116Sjkh	double t,w;
482116Sjkh	int32_t hx,ix;
492116Sjkh	GET_HIGH_WORD(hx,x);
502116Sjkh	ix = hx&0x7fffffff;
512116Sjkh	if(ix>=0x7ff00000) return x+x;	/* x is inf or NaN */
522116Sjkh	if(ix< 0x3e300000) {	/* |x|<2**-28 */
532116Sjkh	    if(huge+x>one) return x;	/* return x inexact except 0 */
548870Srgrimes	}
552116Sjkh	if(ix>0x41b00000) {	/* |x| > 2**28 */
562116Sjkh	    w = __ieee754_log(fabs(x))+ln2;
572116Sjkh	} else if (ix>0x40000000) {	/* 2**28 > |x| > 2.0 */
582116Sjkh	    t = fabs(x);
592116Sjkh	    w = __ieee754_log(2.0*t+one/(sqrt(x*x+one)+t));
602116Sjkh	} else {		/* 2.0 > |x| > 2**-28 */
612116Sjkh	    t = x*x;
622116Sjkh	    w =log1p(fabs(x)+t/(one+sqrt(one+t)));
632116Sjkh	}
642116Sjkh	if(hx>0) return w; else return -w;
652116Sjkh}
66