11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* @(#)e_atanh.c 1.3 95/01/18 */
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 SunSoft, 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
15a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes#include <sys/cdefs.h>
16a0ee07829a9ba7e99ef68e8c12551301cc797f0fElliott Hughes__FBSDID("$FreeBSD$");
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* __ieee754_atanh(x)
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Method :
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    1.Reduced x to positive by atanh(-x) = -atanh(x)
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    2.For x>=0.5
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *                  1              2x                          x
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *                  2             1 - x                      1 - x
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 	For x<0.5
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Special cases:
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	atanh(x) is NaN if |x| > 1 with signal;
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	atanh(NaN) is that NaN with no signal;
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *	atanh(+-1) is +-INF with signal.
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math.h"
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "math_private.h"
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const double one = 1.0, huge = 1e300;
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic const double zero = 0.0;
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdouble
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__ieee754_atanh(double x)
441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	double t;
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int32_t hx,ix;
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	u_int32_t lx;
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	EXTRACT_WORDS(hx,lx,x);
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	ix = hx&0x7fffffff;
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((ix|((lx|(-lx))>>31))>0x3ff00000) /* |x|>1 */
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    return (x-x)/(x-x);
521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(ix==0x3ff00000)
531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    return x/zero;
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(ix<0x3e300000&&(huge+x)>zero) return x;	/* x<2**-28 */
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	SET_HIGH_WORD(x,ix);
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(ix<0x3fe00000) {		/* x < 0.5 */
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    t = x+x;
581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    t = 0.5*log1p(t+t*x/(one-x));
591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else
601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    t = 0.5*log1p((x+x)/(one-x));
611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if(hx>=0) return t; else return -t;
621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
63