xref: /dragonfly/contrib/openbsd_libm/src/e_acosh.c (revision 4382f29d99a100bd77a81697c2f699c11f6a472a)
1 /* @(#)e_acosh.c 5.1 93/09/24 */
2 /*
3  * ====================================================
4  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
5  *
6  * Developed at SunPro, a Sun Microsystems, Inc. business.
7  * Permission to use, copy, modify, and distribute this
8  * software is freely granted, provided that this notice
9  * is preserved.
10  * ====================================================
11  */
12 
13 /* acosh(x)
14  * Method :
15  *        Based on
16  *                  acosh(x) = log [ x + sqrt(x*x-1) ]
17  *        we have
18  *                  acosh(x) := log(x)+ln2,       if x is large; else
19  *                  acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else
20  *                  acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1.
21  *
22  * Special cases:
23  *        acosh(x) is NaN with signal if x<1.
24  *        acosh(NaN) is NaN without signal.
25  */
26 
27 #include <float.h>
28 #include <math.h>
29 
30 #include "math_private.h"
31 
32 static const double
33 one       = 1.0,
34 ln2       = 6.93147180559945286227e-01;  /* 0x3FE62E42, 0xFEFA39EF */
35 
36 double
acosh(double x)37 acosh(double x)
38 {
39           double t;
40           int32_t hx;
41           u_int32_t lx;
42           EXTRACT_WORDS(hx,lx,x);
43           if(hx<0x3ff00000) {           /* x < 1 */
44               return (x-x)/(x-x);
45           } else if(hx >=0x41b00000) {  /* x > 2**28 */
46               if(hx >=0x7ff00000) {     /* x is inf of NaN */
47                   return x+x;
48               } else
49                     return log(x)+ln2;  /* acosh(huge)=log(2x) */
50           } else if(((hx-0x3ff00000)|lx)==0) {
51               return 0.0;                         /* acosh(1) = 0 */
52           } else if (hx > 0x40000000) { /* 2**28 > x > 2 */
53               t=x*x;
54               return log(2.0*x-one/(x+sqrt(t-one)));
55           } else {                      /* 1<x<2 */
56               t = x-one;
57               return log1p(t+sqrt(2.0*t+t*t));
58           }
59 }
60 
61 #if       LDBL_MANT_DIG == DBL_MANT_DIG
62 __strong_alias(acoshl, acosh);
63 #endif    /* LDBL_MANT_DIG == DBL_MANT_DIG */
64