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 /* 27 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 #pragma weak __tanh = tanh 32 33 34 /* 35 * TANH(X) 36 * RETURN THE HYPERBOLIC TANGENT OF X 37 * code based on 4.3bsd 38 * Modified by K.C. Ng for sun 4.0, Jan 31, 1987 39 * 40 * Method : 41 * 1. reduce x to non-negative by tanh(-x) = - tanh(x). 42 * 2. 43 * 0 < x <= 1.e-10 : tanh(x) := x 44 * -expm1(-2x) 45 * 1.e-10 < x <= 1 : tanh(x) := -------------- 46 * expm1(-2x) + 2 47 * 2 48 * 1 <= x <= 22.0 : tanh(x) := 1 - --------------- 49 * expm1(2x) + 2 50 * 22.0 < x <= INF : tanh(x) := 1. 51 * 52 * Note: 22 was chosen so that fl(1.0+2/(expm1(2*22)+2)) == 1. 53 * 54 * Special cases: 55 * tanh(NaN) is NaN; 56 * only tanh(0)=0 is exact for finite argument. 57 */ 58 59 #include "libm.h" 60 #include "libm_protos.h" 61 #include <math.h> 62 63 static const double one = 1.0, two = 2.0, small = 1.0e-10, big = 1.0e10; 64 65 66 double 67 tanh(double x) 68 { 69 double t, y, z; 70 int signx; 71 volatile double dummy __unused; 72 73 if (isnan(x)) 74 return (x * x); /* + -> * for Cheetah */ 75 76 signx = signbit(x); 77 t = fabs(x); 78 z = one; 79 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 } else { 87 /* 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 } else if (!finite(t)) { 95 return (copysign(1.0, x)); 96 } else { 97 return ((signx != 0) ? -z + small * small : z - small * small); 98 } 99 100 return ((signx != 0) ? -z : z); 101 }