|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1985 Regents of the University of California. ! 3: * ! 4: * Use and reproduction of this software are granted in accordance with ! 5: * the terms and conditions specified in the Berkeley Software License ! 6: * Agreement (in particular, this entails acknowledgement of the programs' ! 7: * source, and inclusion of this notice) with the additional understanding ! 8: * that all recipients should regard themselves as participants in an ! 9: * ongoing research project and hence should feel obligated to report ! 10: * their experiences (good or bad) with these elementary function codes, ! 11: * using "sendbug 4bsd-bugs@BERKELEY", to the authors. ! 12: */ ! 13: ! 14: #ifndef lint ! 15: static char sccsid[] = "@(#)sinh.c 4.3 (Berkeley) 8/21/85"; ! 16: #endif not lint ! 17: ! 18: /* SINH(X) ! 19: * RETURN THE HYPERBOLIC SINE OF X ! 20: * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS) ! 21: * CODED IN C BY K.C. NG, 1/8/85; ! 22: * REVISED BY K.C. NG on 2/8/85, 3/7/85, 3/24/85, 4/16/85. ! 23: * ! 24: * Required system supported functions : ! 25: * copysign(x,y) ! 26: * scalb(x,N) ! 27: * ! 28: * Required kernel functions: ! 29: * expm1(x) ...return exp(x)-1 ! 30: * ! 31: * Method : ! 32: * 1. reduce x to non-negative by sinh(-x) = - sinh(x). ! 33: * 2. ! 34: * ! 35: * expm1(x) + expm1(x)/(expm1(x)+1) ! 36: * 0 <= x <= lnovfl : sinh(x) := -------------------------------- ! 37: * 2 ! 38: * lnovfl <= x <= lnovfl+ln2 : sinh(x) := expm1(x)/2 (avoid overflow) ! 39: * lnovfl+ln2 < x < INF : overflow to INF ! 40: * ! 41: * ! 42: * Special cases: ! 43: * sinh(x) is x if x is +INF, -INF, or NaN. ! 44: * only sinh(0)=0 is exact for finite argument. ! 45: * ! 46: * Accuracy: ! 47: * sinh(x) returns the exact hyperbolic sine of x nearly rounded. In ! 48: * a test run with 1,024,000 random arguments on a VAX, the maximum ! 49: * observed error was 1.93 ulps (units in the last place). ! 50: * ! 51: * Constants: ! 52: * The hexadecimal values are the intended ones for the following constants. ! 53: * The decimal values may be used, provided that the compiler will convert ! 54: * from decimal to binary accurately enough to produce the hexadecimal values ! 55: * shown. ! 56: */ ! 57: #ifdef VAX ! 58: /* double static */ ! 59: /* mln2hi = 8.8029691931113054792E1 , Hex 2^ 7 * .B00F33C7E22BDB */ ! 60: /* mln2lo = -4.9650192275318476525E-16 , Hex 2^-50 * -.8F1B60279E582A */ ! 61: /* lnovfl = 8.8029691931113053016E1 ; Hex 2^ 7 * .B00F33C7E22BDA */ ! 62: static long mln2hix[] = { 0x0f3343b0, 0x2bdbc7e2}; ! 63: static long mln2lox[] = { 0x1b60a70f, 0x582a279e}; ! 64: static long lnovflx[] = { 0x0f3343b0, 0x2bdac7e2}; ! 65: #define mln2hi (*(double*)mln2hix) ! 66: #define mln2lo (*(double*)mln2lox) ! 67: #define lnovfl (*(double*)lnovflx) ! 68: #else /* IEEE double */ ! 69: double static ! 70: mln2hi = 7.0978271289338397310E2 , /*Hex 2^ 10 * 1.62E42FEFA39EF */ ! 71: mln2lo = 2.3747039373786107478E-14 , /*Hex 2^-45 * 1.ABC9E3B39803F */ ! 72: lnovfl = 7.0978271289338397310E2 ; /*Hex 2^ 9 * 1.62E42FEFA39EF */ ! 73: #endif ! 74: ! 75: #ifdef VAX ! 76: static max = 126 ; ! 77: #else /* IEEE double */ ! 78: static max = 1023 ; ! 79: #endif ! 80: ! 81: ! 82: double sinh(x) ! 83: double x; ! 84: { ! 85: static double one=1.0, half=1.0/2.0 ; ! 86: double expm1(), t, scalb(), copysign(), sign; ! 87: #ifndef VAX ! 88: if(x!=x) return(x); /* x is NaN */ ! 89: #endif ! 90: sign=copysign(one,x); ! 91: x=copysign(x,one); ! 92: if(x<lnovfl) ! 93: {t=expm1(x); return(copysign((t+t/(one+t))*half,sign));} ! 94: ! 95: else if(x <= lnovfl+0.7) ! 96: /* subtract x by ln(2^(max+1)) and return 2^max*exp(x) ! 97: to avoid unnecessary overflow */ ! 98: return(copysign(scalb(one+expm1((x-mln2hi)-mln2lo),max),sign)); ! 99: ! 100: else /* sinh(+-INF) = +-INF, sinh(+-big no.) overflow to +-INF */ ! 101: return( expm1(x)*sign ); ! 102: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.