os/ossrv/genericopenlibs/cstdlib/LMATH/S_TANH.C
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /* S_TANH.C
     2  * 
     3  * Portions Copyright (c) 1993-1999 Nokia Corporation and/or its subsidiary(-ies).
     4  * All rights reserved.
     5  */
     6 
     7 
     8 /* @(#)s_tanh.c 5.1 93/09/24 */
     9 /*
    10  * ====================================================
    11  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
    12  *
    13  * Developed at SunPro, a Sun Microsystems, Inc. business.
    14  * Permission to use, copy, modify, and distribute this
    15  * software is freely granted, provided that this notice 
    16  * is preserved.
    17  * ====================================================
    18  */
    19 
    20 /*
    21 
    22 FUNCTION
    23         <<tanh>>, <<tanhf>>---hyperbolic tangent
    24 
    25 INDEX
    26 tanh
    27 INDEX
    28 tanhf
    29 
    30 ANSI_SYNOPSIS
    31         #include <math.h>
    32         double tanh(double <[x]>);
    33         float tanhf(float <[x]>);
    34 
    35 TRAD_SYNOPSIS
    36         #include <math.h>
    37         double tanh(<[x]>)
    38         double <[x]>;
    39 
    40         float tanhf(<[x]>)
    41         float <[x]>;
    42 
    43 
    44 DESCRIPTION
    45 
    46 <<tanh>> computes the hyperbolic tangent of
    47 the argument <[x]>.  Angles are specified in radians.  
    48 
    49 <<tanh(<[x]>)>> is defined as 
    50 . sinh(<[x]>)/cosh(<[x]>)
    51 	
    52 <<tanhf>> is identical, save that it takes and returns <<float>> values.
    53 
    54 RETURNS
    55 The hyperbolic tangent of <[x]> is returned.
    56 
    57 PORTABILITY
    58 <<tanh>> is ANSI C.  <<tanhf>> is an extension.
    59 
    60 */
    61 
    62 /* Tanh(x)
    63  * Return the Hyperbolic Tangent of x
    64  *
    65  * Method :
    66  *				       x    -x
    67  *				      e  - e
    68  *	0. tanh(x) is defined to be -----------
    69  *				       x    -x
    70  *				      e  + e
    71  *	1. reduce x to non-negative by tanh(-x) = -tanh(x).
    72  *	2.  0      <= x <= 2**-55 : tanh(x) := x*(one+x)
    73  *					        -t
    74  *	    2**-55 <  x <=  1     : tanh(x) := -----; t = expm1(-2x)
    75  *					       t + 2
    76  *						     2
    77  *	    1      <= x <=  22.0  : tanh(x) := 1-  ----- ; t=expm1(2x)
    78  *						   t + 2
    79  *	    22.0   <  x <= INF    : tanh(x) := 1.
    80  *
    81  * Special cases:
    82  *	tanh(NaN) is NaN;
    83  *	only tanh(0)=0 is exact for finite argument.
    84  */
    85 
    86 #include "FDLIBM.H"
    87 
    88 static const double one=1.0, two=2.0, tiny = 1.0e-300;
    89 
    90 /**
    91 Calculate hyperbolic tangent.
    92 @return hyperbolic tangent of x.
    93 @param x Angle expressed in radians (180 degrees = PI radians).
    94 */	
    95 EXPORT_C double tanh(double x) __SOFTFP
    96 {
    97 	double t,z;
    98 	__int32_t jx,ix;
    99 
   100     /* High word of |x|. */
   101 	GET_HIGH_WORD(jx,x);
   102 	ix = jx&0x7fffffff;
   103 
   104     /* x is INF or NaN */
   105 	if(ix>=0x7ff00000) { 
   106 	    if (jx>=0) return one/x+one;    /* tanh(+-inf)=+-1 */
   107 	    else       return one/x-one;    /* tanh(NaN) = NaN */
   108 	}
   109 
   110     /* |x| < 22 */
   111 	if (ix < 0x40360000) {		/* |x|<22 */
   112 	    if (ix<0x3c800000) 		/* |x|<2**-55 */
   113 		return x*(one+x);    	/* tanh(small) = small */
   114 	    if (ix>=0x3ff00000) {	/* |x|>=1  */
   115 		t = expm1(two*fabs(x));
   116 		z = one - two/(t+two);
   117 	    } else {
   118 	        t = expm1(-two*fabs(x));
   119 	        z= -t/(t+two);
   120 	    }
   121     /* |x| > 22, return +-1 */
   122 	} else {
   123 	    z = one - tiny;		/* raised inexact flag */
   124 	}
   125 	return (jx>=0)? z: -z;
   126 }