Charles L. Dorian | a0690b6 | 2010-02-01 22:21:40 -0800 | [diff] [blame] | 1 | // 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 | |
| 5 | package math |
| 6 | |
Charles L. Dorian | a0690b6 | 2010-02-01 22:21:40 -0800 | [diff] [blame] | 7 | // 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. Dorian | f273487 | 2012-04-06 14:01:12 -0400 | [diff] [blame] | 36 | // Acosh returns the inverse hyperbolic cosine of x. |
Charles L. Dorian | a0690b6 | 2010-02-01 22:21:40 -0800 | [diff] [blame] | 37 | // |
| 38 | // Special cases are: |
Charles L. Dorian | 94b0342 | 2011-12-08 17:07:13 -0500 | [diff] [blame] | 39 | // Acosh(+Inf) = +Inf |
Charles L. Dorian | a0690b6 | 2010-02-01 22:21:40 -0800 | [diff] [blame] | 40 | // Acosh(x) = NaN if x < 1 |
| 41 | // Acosh(NaN) = NaN |
| 42 | func Acosh(x float64) float64 { |
| 43 | const ( |
| 44 | Ln2 = 6.93147180559945286227e-01 // 0x3FE62E42FEFA39EF |
Charles L. Dorian | 3c3e68b | 2010-04-09 14:37:33 -0700 | [diff] [blame] | 45 | Large = 1 << 28 // 2**28 |
Charles L. Dorian | a0690b6 | 2010-02-01 22:21:40 -0800 | [diff] [blame] | 46 | ) |
Charles L. Dorian | 78e918c | 2010-02-22 17:12:48 -0800 | [diff] [blame] | 47 | // first case is special case |
Charles L. Dorian | a0690b6 | 2010-02-01 22:21:40 -0800 | [diff] [blame] | 48 | switch { |
Luuk van Dijk | 8dd3de4 | 2012-02-01 16:08:31 +0100 | [diff] [blame] | 49 | case x < 1 || IsNaN(x): |
Charles L. Dorian | a0690b6 | 2010-02-01 22:21:40 -0800 | [diff] [blame] | 50 | return NaN() |
| 51 | case x == 1: |
| 52 | return 0 |
| 53 | case x >= Large: |
Charles L. Dorian | 3c3e68b | 2010-04-09 14:37:33 -0700 | [diff] [blame] | 54 | return Log(x) + Ln2 // x > 2**28 |
Charles L. Dorian | a0690b6 | 2010-02-01 22:21:40 -0800 | [diff] [blame] | 55 | case x > 2: |
Charles L. Dorian | 3c3e68b | 2010-04-09 14:37:33 -0700 | [diff] [blame] | 56 | return Log(2*x - 1/(x+Sqrt(x*x-1))) // 2**28 > x > 2 |
Charles L. Dorian | a0690b6 | 2010-02-01 22:21:40 -0800 | [diff] [blame] | 57 | } |
| 58 | t := x - 1 |
| 59 | return Log1p(t + Sqrt(2*t+t*t)) // 2 >= x > 1 |
| 60 | } |