genericopenlibs/cstdlib/LMATH/S_TANH.C
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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 }