blob: e394008b078cb2db2bec1942b7c71e9cb5da8b1a [file] [log] [blame]
Charles L. Doriana0690b62010-02-01 22:21:40 -08001// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package math
6
Charles L. Doriana0690b62010-02-01 22:21:40 -08007// The original C code, the long comment, and the constants
8// below are from FreeBSD's /usr/src/lib/msun/src/e_acosh.c
9// and came with this notice. The go code is a simplified
10// version of the original C.
11//
12// ====================================================
13// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
14//
15// Developed at SunPro, a Sun Microsystems, Inc. business.
16// Permission to use, copy, modify, and distribute this
17// software is freely granted, provided that this notice
18// is preserved.
19// ====================================================
20//
21//
22// __ieee754_acosh(x)
23// Method :
24// Based on
25// acosh(x) = log [ x + sqrt(x*x-1) ]
26// we have
27// acosh(x) := log(x)+ln2, if x is large; else
28// acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else
29// acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1.
30//
31// Special cases:
32// acosh(x) is NaN with signal if x<1.
33// acosh(NaN) is NaN without signal.
34//
35
Charles L. Dorianf2734872012-04-06 14:01:12 -040036// Acosh returns the inverse hyperbolic cosine of x.
Charles L. Doriana0690b62010-02-01 22:21:40 -080037//
38// Special cases are:
Charles L. Dorian94b03422011-12-08 17:07:13 -050039// Acosh(+Inf) = +Inf
Charles L. Doriana0690b62010-02-01 22:21:40 -080040// Acosh(x) = NaN if x < 1
41// Acosh(NaN) = NaN
42func Acosh(x float64) float64 {
43 const (
44 Ln2 = 6.93147180559945286227e-01 // 0x3FE62E42FEFA39EF
Charles L. Dorian3c3e68b2010-04-09 14:37:33 -070045 Large = 1 << 28 // 2**28
Charles L. Doriana0690b62010-02-01 22:21:40 -080046 )
Charles L. Dorian78e918c2010-02-22 17:12:48 -080047 // first case is special case
Charles L. Doriana0690b62010-02-01 22:21:40 -080048 switch {
Luuk van Dijk8dd3de42012-02-01 16:08:31 +010049 case x < 1 || IsNaN(x):
Charles L. Doriana0690b62010-02-01 22:21:40 -080050 return NaN()
51 case x == 1:
52 return 0
53 case x >= Large:
Charles L. Dorian3c3e68b2010-04-09 14:37:33 -070054 return Log(x) + Ln2 // x > 2**28
Charles L. Doriana0690b62010-02-01 22:21:40 -080055 case x > 2:
Charles L. Dorian3c3e68b2010-04-09 14:37:33 -070056 return Log(2*x - 1/(x+Sqrt(x*x-1))) // 2**28 > x > 2
Charles L. Doriana0690b62010-02-01 22:21:40 -080057 }
58 t := x - 1
59 return Log1p(t + Sqrt(2*t+t*t)) // 2 >= x > 1
60}