1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 24 */ 25 /* 26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 #pragma weak tanh = __tanh 31 32 /* INDENT OFF */ 33 /* TANH(X) 34 * RETURN THE HYPERBOLIC TANGENT OF X 35 * code based on 4.3bsd 36 * Modified by K.C. Ng for sun 4.0, Jan 31, 1987 37 * 38 * Method : 39 * 1. reduce x to non-negative by tanh(-x) = - tanh(x). 40 * 2. 41 * 0 < x <= 1.e-10 : tanh(x) := x 42 * -expm1(-2x) 43 * 1.e-10 < x <= 1 : tanh(x) := -------------- 44 * expm1(-2x) + 2 45 * 2 46 * 1 <= x <= 22.0 : tanh(x) := 1 - --------------- 47 * expm1(2x) + 2 48 * 22.0 < x <= INF : tanh(x) := 1. 49 * 50 * Note: 22 was chosen so that fl(1.0+2/(expm1(2*22)+2)) == 1. 51 * 52 * Special cases: 53 * tanh(NaN) is NaN; 54 * only tanh(0)=0 is exact for finite argument. 55 */ 56 57 #include "libm.h" 58 #include "libm_synonyms.h" 59 #include "libm_protos.h" 60 #include <math.h> 61 62 static const double 63 one = 1.0, 64 two = 2.0, 65 small = 1.0e-10, 66 big = 1.0e10; 67 /* INDENT ON */ 68 69 double 70 tanh(double x) { 71 double t, y, z; 72 int signx; 73 volatile double dummy; 74 75 if (isnan(x)) 76 return x * x; /* + -> * for Cheetah */ 77 signx = signbit(x); 78 t = fabs(x); 79 z = one; 80 if (t <= 22.0) { 81 if (t > one) 82 z = one - two / (expm1(t + t) + two); 83 else if (t > small) { 84 y = expm1(-t - t); 85 z = -y / (y + two); 86 } 87 else { /* raise the INEXACT flag for non-zero t */ 88 dummy = t + big; 89 #ifdef lint 90 dummy = dummy; 91 #endif 92 return x; 93 } 94 } 95 else if (!finite(t)) 96 return copysign(1.0, x); 97 else 98 return signx == 1 ? -z + small * small : z - small * small; 99 100 return signx == 1 ? -z : z; 101 }