1 /*
   2  * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 4851625 4900189 4939441
  27  * @summary Tests for {Math, StrictMath}.{sinh, cosh, tanh}
  28  * @library /lib/testlibrary
  29  * @build jdk.testlibrary.DoubleUtils jdk.testlibrary.FloatUtils
  30  * @run main HyperbolicTests
  31  * @author Joseph D. Darcy
  32  */
  33 
  34 import static jdk.testlibrary.DoubleUtils.*;
  35 
  36 public class HyperbolicTests {
  37     private HyperbolicTests(){}
  38 
  39     static final double NaNd = Double.NaN;
  40 
  41     /**
  42      * Test accuracy of {Math, StrictMath}.sinh.  The specified
  43      * accuracy is 2.5 ulps.
  44      *
  45      * The defintion of sinh(x) is
  46      *
  47      * (e^x - e^(-x))/2
  48      *
  49      * The series expansion of sinh(x) =
  50      *
  51      * x + x^3/3! + x^5/5! + x^7/7! +...
  52      *
  53      * Therefore,
  54      *
  55      * 1. For large values of x sinh(x) ~= signum(x)*exp(|x|)/2
  56      *
  57      * 2. For small values of x, sinh(x) ~= x.
  58      *
  59      * Additionally, sinh is an odd function; sinh(-x) = -sinh(x).
  60      *
  61      */
  62     static int testSinh() {
  63         int failures = 0;
  64         /*
  65          * Array elements below generated using a quad sinh
  66          * implementation.  Rounded to a double, the quad result
  67          * *should* be correctly rounded, unless we are quite unlucky.
  68          * Assuming the quad value is a correctly rounded double, the
  69          * allowed error is 3.0 ulps instead of 2.5 since the quad
  70          * value rounded to double can have its own 1/2 ulp error.
  71          */
  72         double [][] testCases = {
  73             // x                sinh(x)
  74             {0.0625,            0.06254069805219182172183988501029229},
  75             {0.1250,            0.12532577524111545698205754229137154},
  76             {0.1875,            0.18860056562029018382047025055167585},
  77             {0.2500,            0.25261231680816830791412515054205787},
  78             {0.3125,            0.31761115611357728583959867611490292},
  79             {0.3750,            0.38385106791361456875429567642050245},
  80             {0.4375,            0.45159088610312053032509815226723017},
  81             {0.5000,            0.52109530549374736162242562641149155},
  82             {0.5625,            0.59263591611468777373870867338492247},
  83             {0.6250,            0.66649226445661608227260655608302908},
  84             {0.6875,            0.74295294580567543571442036910465007},
  85             {0.7500,            0.82231673193582998070366163444691386},
  86             {0.8125,            0.90489373856606433650504536421491368},
  87             {0.8750,            0.99100663714429475605317427568995231},
  88             {0.9375,            1.08099191569306394011007867453992548},
  89             {1.0000,            1.17520119364380145688238185059560082},
  90             {1.0625,            1.27400259579739321279181130344911907},
  91             {1.1250,            1.37778219077984075760379987065228373},
  92             {1.1875,            1.48694549961380717221109202361777593},
  93             {1.2500,            1.60191908030082563790283030151221415},
  94             {1.3125,            1.72315219460596010219069206464391528},
  95             {1.3750,            1.85111856355791532419998548438506416},
  96             {1.4375,            1.98631821852425112898943304217629457},
  97             {1.5000,            2.12927945509481749683438749467763195},
  98             {1.5625,            2.28056089740825247058075476705718764},
  99             {1.6250,            2.44075368098794353221372986997161132},
 100             {1.6875,            2.61048376261693140366028569794027603},
 101             {1.7500,            2.79041436627764265509289122308816092},
 102             {1.8125,            2.98124857471401377943765253243875520},
 103             {1.8750,            3.18373207674259205101326780071803724},
 104             {1.9375,            3.39865608104779099764440244167531810},
 105             {2.0000,            3.62686040784701876766821398280126192},
 106             {2.0625,            3.86923677050642806693938384073620450},
 107             {2.1250,            4.12673225993027252260441410537905269},
 108             {2.1875,            4.40035304533919660406976249684469164},
 109             {2.2500,            4.69116830589833069188357567763552003},
 110             {2.3125,            5.00031440855811351554075363240262157},
 111             {2.3750,            5.32899934843284576394645856548481489},
 112             {2.4375,            5.67850746906785056212578751630266858},
 113             {2.5000,            6.05020448103978732145032363835040319},
 114             {2.5625,            6.44554279850040875063706020260185553},
 115             {2.6250,            6.86606721451642172826145238779845813},
 116             {2.6875,            7.31342093738196587585692115636603571},
 117             {2.7500,            7.78935201149073201875513401029935330},
 118             {2.8125,            8.29572014785741787167717932988491961},
 119             {2.8750,            8.83450399097893197351853322827892144},
 120             {2.9375,            9.40780885043076394429977972921690859},
 121             {3.0000,            10.01787492740990189897459361946582867},
 122             {3.0625,            10.66708606836969224165124519209968368},
 123             {3.1250,            11.35797907995166028304704128775698426},
 124             {3.1875,            12.09325364161259019614431093344260209},
 125             {3.2500,            12.87578285468067003959660391705481220},
 126             {3.3125,            13.70862446906136798063935858393686525},
 127             {3.3750,            14.59503283146163690015482636921657975},
 128             {3.4375,            15.53847160182039311025096666980558478},
 129             {3.5000,            16.54262728763499762495673152901249743},
 130             {3.5625,            17.61142364906941482858466494889121694},
 131             {3.6250,            18.74903703113232171399165788088277979},
 132             {3.6875,            19.95991268283598684128844120984214675},
 133             {3.7500,            21.24878212710338697364101071825171163},
 134             {3.8125,            22.62068164929685091969259499078125023},
 135             {3.8750,            24.08097197661255803883403419733891573},
 136             {3.9375,            25.63535922523855307175060244757748997},
 137             {4.0000,            27.28991719712775244890827159079382096},
 138             {4.0625,            29.05111111351106713777825462100160185},
 139             {4.1250,            30.92582287788986031725487699744107092},
 140             {4.1875,            32.92137796722343190618721270937061472},
 141             {4.2500,            35.04557405638942942322929652461901154},
 142             {4.3125,            37.30671148776788628118833357170042385},
 143             {4.3750,            39.71362570500944929025069048612806024},
 144             {4.4375,            42.27572177772344954814418332587050658},
 145             {4.5000,            45.00301115199178562180965680564371424},
 146             {4.5625,            47.90615077031205065685078058248081891},
 147             {4.6250,            50.99648471383193131253995134526177467},
 148             {4.6875,            54.28608852959281437757368957713936555},
 149             {4.7500,            57.78781641599226874961859781628591635},
 150             {4.8125,            61.51535145084362283008545918273109379},
 151             {4.8750,            65.48325905829987165560146562921543361},
 152             {4.9375,            69.70704392356508084094318094283346381},
 153             {5.0000,            74.20321057778875897700947199606456364},
 154             {5.0625,            78.98932788987998983462810080907521151},
 155             {5.1250,            84.08409771724448958901392613147384951},
 156             {5.1875,            89.50742798369883598816307922895346849},
 157             {5.2500,            95.28051047011540739630959111303975956},
 158             {5.3125,            101.42590362176666730633859252034238987},
 159             {5.3750,            107.96762069594029162704530843962700133},
 160             {5.4375,            114.93122359426386042048760580590182604},
 161             {5.5000,            122.34392274639096192409774240457730721},
 162             {5.5625,            130.23468343534638291488502321709913206},
 163             {5.6250,            138.63433897999898233879574111119546728},
 164             {5.6875,            147.57571121692522056519568264304815790},
 165             {5.7500,            157.09373875244884423880085377625986165},
 166             {5.8125,            167.22561348600435888568183143777868662},
 167             {5.8750,            178.01092593829229887752609866133883987},
 168             {5.9375,            189.49181995209921964640216682906501778},
 169             {6.0000,            201.71315737027922812498206768797872263},
 170             {6.0625,            214.72269333437984291483666459592578915},
 171             {6.1250,            228.57126288889537420461281285729970085},
 172             {6.1875,            243.31297962030799867970551767086092471},
 173             {6.2500,            259.00544710710289911522315435345489966},
 174             {6.3125,            275.70998400700299790136562219920451185},
 175             {6.3750,            293.49186366095654566861661249898332253},
 176             {6.4375,            312.42056915013535342987623229485223434},
 177             {6.5000,            332.57006480258443156075705566965111346},
 178             {6.5625,            354.01908521044116928437570109827956007},
 179             {6.6250,            376.85144288706511933454985188849781703},
 180             {6.6875,            401.15635576625530823119100750634165252},
 181             {6.7500,            427.02879582326538080306830640235938517},
 182             {6.8125,            454.56986017986077163530945733572724452},
 183             {6.8750,            483.88716614351897894746751705315210621},
 184             {6.9375,            515.09527172439720070161654727225752288},
 185             {7.0000,            548.31612327324652237375611757601851598},
 186             {7.0625,            583.67953198942753384680988096024373270},
 187             {7.1250,            621.32368116099280160364794462812762880},
 188             {7.1875,            661.39566611888784148449430491465857519},
 189             {7.2500,            704.05206901515336623551137120663358760},
 190             {7.3125,            749.45957067108712382864538206200700256},
 191             {7.3750,            797.79560188617531521347351754559776282},
 192             {7.4375,            849.24903675279739482863565789325699416},
 193             {7.5000,            904.02093068584652953510919038935849651},
 194             {7.5625,            962.32530605113249628368993221570636328},
 195             {7.6250,            1024.38998846242707559349318193113614698},
 196             {7.6875,            1090.45749701500081956792547346904792325},
 197             {7.7500,            1160.78599193425808533255719118417856088},
 198             {7.8125,            1235.65028334242796895820912936318532502},
 199             {7.8750,            1315.34290508508890654067255740428824014},
 200             {7.9375,            1400.17525781352742299995139486063802583},
 201             {8.0000,            1490.47882578955018611587663903188144796},
 202             {8.0625,            1586.60647216744061169450001100145859236},
 203             {8.1250,            1688.93381781440241350635231605477507900},
 204             {8.1875,            1797.86070905726094477721128358866360644},
 205             {8.2500,            1913.81278009067446281883262689250118009},
 206             {8.3125,            2037.24311615199935553277163192983440062},
 207             {8.3750,            2168.63402396170125867037749369723761636},
 208             {8.4375,            2308.49891634734644432370720900969004306},
 209             {8.5000,            2457.38431841538268239359965370719928775},
 210             {8.5625,            2615.87200310986940554256648824234335262},
 211             {8.6250,            2784.58126450289932429469130598902487336},
 212             {8.6875,            2964.17133769964321637973459949999057146},
 213             {8.7500,            3155.34397481384944060352507473513108710},
 214             {8.8125,            3358.84618707947841898217318996045550438},
 215             {8.8750,            3575.47316381333288862617411467285480067},
 216             {8.9375,            3806.07137963459383403903729660349293583},
 217             {9.0000,            4051.54190208278996051522359589803425598},
 218             {9.0625,            4312.84391255878980330955246931164633615},
 219             {9.1250,            4590.99845434696991399363282718106006883},
 220             {9.1875,            4887.09242236403719571363798584676797558},
 221             {9.2500,            5202.28281022453561319352901552085348309},
 222             {9.3125,            5537.80123121853803935727335892054791265},
 223             {9.3750,            5894.95873086734181634245918412592155656},
 224             {9.4375,            6275.15090986233399457103055108344546942},
 225             {9.5000,            6679.86337740502119410058225086262108741},
 226             {9.5625,            7110.67755625726876329967852256934334025},
 227             {9.6250,            7569.27686218510919585241049433331592115},
 228             {9.6875,            8057.45328194243077504648484392156371121},
 229             {9.7500,            8577.11437549816065709098061006273039092},
 230             {9.8125,            9130.29072986829727910801024120918114778},
 231             {9.8750,            9719.14389367880274015504995181862860062},
 232             {9.9375,            10345.97482346383208590278839409938269134},
 233             {10.0000,           11013.23287470339337723652455484636420303},
 234         };
 235 
 236         for(int i = 0; i < testCases.length; i++) {
 237             double [] testCase = testCases[i];
 238             failures += testSinhCaseWithUlpDiff(testCase[0],
 239                                                 testCase[1],
 240                                                 3.0);
 241         }
 242 
 243         double [][] specialTestCases = {
 244             {0.0,                       0.0},
 245             {NaNd,                      NaNd},
 246             {Double.longBitsToDouble(0x7FF0000000000001L),      NaNd},
 247             {Double.longBitsToDouble(0xFFF0000000000001L),      NaNd},
 248             {Double.longBitsToDouble(0x7FF8555555555555L),      NaNd},
 249             {Double.longBitsToDouble(0xFFF8555555555555L),      NaNd},
 250             {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL),      NaNd},
 251             {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL),      NaNd},
 252             {Double.longBitsToDouble(0x7FFDeadBeef00000L),      NaNd},
 253             {Double.longBitsToDouble(0xFFFDeadBeef00000L),      NaNd},
 254             {Double.longBitsToDouble(0x7FFCafeBabe00000L),      NaNd},
 255             {Double.longBitsToDouble(0xFFFCafeBabe00000L),      NaNd},
 256             {Double.POSITIVE_INFINITY,  Double.POSITIVE_INFINITY}
 257         };
 258 
 259         for(int i = 0; i < specialTestCases.length; i++) {
 260             failures += testSinhCaseWithUlpDiff(specialTestCases[i][0],
 261                                                 specialTestCases[i][1],
 262                                                 0.0);
 263         }
 264 
 265         // For powers of 2 less than 2^(-27), the second and
 266         // subsequent terms of the Taylor series expansion will get
 267         // rounded away since |n-n^3| > 53, the binary precision of a
 268         // double significand.
 269 
 270         for(int i = MIN_SUB_EXPONENT; i < -27; i++) {
 271             double d = Math.scalb(2.0, i);
 272 
 273             // Result and expected are the same.
 274             failures += testSinhCaseWithUlpDiff(d, d, 2.5);
 275         }
 276 
 277         // For values of x larger than 22, the e^(-x) term is
 278         // insignificant to the floating-point result.  Util exp(x)
 279         // overflows around 709.8, sinh(x) ~= exp(x)/2; will will test
 280         // 10000 values in this range.
 281 
 282         long trans22 = Double.doubleToLongBits(22.0);
 283         // (approximately) largest value such that exp shouldn't
 284         // overflow
 285         long transExpOvfl = Double.doubleToLongBits(Math.nextDown(709.7827128933841));
 286 
 287         for(long i = trans22;
 288             i < transExpOvfl;
 289             i +=(transExpOvfl-trans22)/10000) {
 290 
 291             double d = Double.longBitsToDouble(i);
 292 
 293             // Allow 3.5 ulps of error to deal with error in exp.
 294             failures += testSinhCaseWithUlpDiff(d, StrictMath.exp(d)*0.5, 3.5);
 295         }
 296 
 297         // (approximately) largest value such that sinh shouldn't
 298         // overflow.
 299         long transSinhOvfl = Double.doubleToLongBits(710.4758600739439);
 300 
 301         // Make sure sinh(x) doesn't overflow as soon as exp(x)
 302         // overflows.
 303 
 304         /*
 305          * For large values of x, sinh(x) ~= 0.5*(e^x).  Therefore,
 306          *
 307          * sinh(x) ~= e^(ln 0.5) * e^x = e^(x + ln 0.5)
 308          *
 309          * So, we can calculate the approximate expected result as
 310          * exp(x + -0.693147186).  However, this sum suffers from
 311          * roundoff, limiting the accuracy of the approximation.  The
 312          * accuracy can be improved by recovering the rounded-off
 313          * information.  Since x is larger than ln(0.5), the trailing
 314          * bits of ln(0.5) get rounded away when the two values are
 315          * added.  However, high-order bits of ln(0.5) that
 316          * contribute to the sum can be found:
 317          *
 318          * offset = log(0.5);
 319          * effective_offset = (x + offset) - x; // exact subtraction
 320          * rounded_away_offset = offset - effective_offset; // exact subtraction
 321          *
 322          * Therefore, the product
 323          *
 324          * exp(x + offset)*exp(rounded_away_offset)
 325          *
 326          * will be a better approximation to the exact value of
 327          *
 328          * e^(x + offset)
 329          *
 330          * than exp(x+offset) alone.  (The expected result cannot be
 331          * computed as exp(x)*exp(offset) since exp(x) by itself would
 332          * overflow to infinity.)
 333          */
 334         double offset = StrictMath.log(0.5);
 335         for(long i = transExpOvfl+1; i < transSinhOvfl;
 336             i += (transSinhOvfl-transExpOvfl)/1000 ) {
 337             double input = Double.longBitsToDouble(i);
 338 
 339             double expected =
 340                 StrictMath.exp(input + offset) *
 341                 StrictMath.exp( offset - ((input + offset) - input) );
 342 
 343             failures += testSinhCaseWithUlpDiff(input, expected, 4.0);
 344         }
 345 
 346         // sinh(x) overflows for values greater than 710; in
 347         // particular, it overflows for all 2^i, i > 10.
 348         for(int i = 10; i <= Double.MAX_EXPONENT; i++) {
 349             double d = Math.scalb(2.0, i);
 350 
 351             // Result and expected are the same.
 352             failures += testSinhCaseWithUlpDiff(d,
 353                                                 Double.POSITIVE_INFINITY, 0.0);
 354         }
 355 
 356         return failures;
 357     }
 358 
 359     public static int testSinhCaseWithTolerance(double input,
 360                                                 double expected,
 361                                                 double tolerance) {
 362         int failures = 0;
 363         failures += Tests.testTolerance("Math.sinh(double)",
 364                                         input, Math.sinh(input),
 365                                         expected, tolerance);
 366         failures += Tests.testTolerance("Math.sinh(double)",
 367                                         -input, Math.sinh(-input),
 368                                         -expected, tolerance);
 369 
 370         failures += Tests.testTolerance("StrictMath.sinh(double)",
 371                                         input, StrictMath.sinh(input),
 372                                         expected, tolerance);
 373         failures += Tests.testTolerance("StrictMath.sinh(double)",
 374                                         -input, StrictMath.sinh(-input),
 375                                         -expected, tolerance);
 376         return failures;
 377     }
 378 
 379     public static int testSinhCaseWithUlpDiff(double input,
 380                                               double expected,
 381                                               double ulps) {
 382         int failures = 0;
 383         failures += Tests.testUlpDiff("Math.sinh(double)",
 384                                       input, Math.sinh(input),
 385                                       expected, ulps);
 386         failures += Tests.testUlpDiff("Math.sinh(double)",
 387                                       -input, Math.sinh(-input),
 388                                       -expected, ulps);
 389 
 390         failures += Tests.testUlpDiff("StrictMath.sinh(double)",
 391                                       input, StrictMath.sinh(input),
 392                                       expected, ulps);
 393         failures += Tests.testUlpDiff("StrictMath.sinh(double)",
 394                                       -input, StrictMath.sinh(-input),
 395                                       -expected, ulps);
 396         return failures;
 397     }
 398 
 399 
 400     /**
 401      * Test accuracy of {Math, StrictMath}.cosh.  The specified
 402      * accuracy is 2.5 ulps.
 403      *
 404      * The defintion of cosh(x) is
 405      *
 406      * (e^x + e^(-x))/2
 407      *
 408      * The series expansion of cosh(x) =
 409      *
 410      * 1 + x^2/2! + x^4/4! + x^6/6! +...
 411      *
 412      * Therefore,
 413      *
 414      * 1. For large values of x cosh(x) ~= exp(|x|)/2
 415      *
 416      * 2. For small values of x, cosh(x) ~= 1.
 417      *
 418      * Additionally, cosh is an even function; cosh(-x) = cosh(x).
 419      *
 420      */
 421     static int testCosh() {
 422         int failures = 0;
 423         /*
 424          * Array elements below generated using a quad cosh
 425          * implementation.  Rounded to a double, the quad result
 426          * *should* be correctly rounded, unless we are quite unlucky.
 427          * Assuming the quad value is a correctly rounded double, the
 428          * allowed error is 3.0 ulps instead of 2.5 since the quad
 429          * value rounded to double can have its own 1/2 ulp error.
 430          */
 431         double [][] testCases = {
 432             // x                cosh(x)
 433             {0.0625,            1.001953760865667607841550709632597376},
 434             {0.1250,            1.007822677825710859846949685520422223},
 435             {0.1875,            1.017629683800690526835115759894757615},
 436             {0.2500,            1.031413099879573176159295417520378622},
 437             {0.3125,            1.049226785060219076999158096606305793},
 438             {0.3750,            1.071140346704586767299498015567016002},
 439             {0.4375,            1.097239412531012567673453832328262160},
 440             {0.5000,            1.127625965206380785226225161402672030},
 441             {0.5625,            1.162418740845610783505338363214045218},
 442             {0.6250,            1.201753692975606324229229064105075301},
 443             {0.6875,            1.245784523776616395403056980542275175},
 444             {0.7500,            1.294683284676844687841708185390181730},
 445             {0.8125,            1.348641048647144208352285714214372703},
 446             {0.8750,            1.407868656822803158638471458026344506},
 447             {0.9375,            1.472597542369862933336886403008640891},
 448             {1.0000,            1.543080634815243778477905620757061497},
 449             {1.0625,            1.619593348374367728682469968448090763},
 450             {1.1250,            1.702434658138190487400868008124755757},
 451             {1.1875,            1.791928268324866464246665745956119612},
 452             {1.2500,            1.888423877161015738227715728160051696},
 453             {1.3125,            1.992298543335143985091891077551921106},
 454             {1.3750,            2.103958159362661802010972984204389619},
 455             {1.4375,            2.223839037619709260803023946704272699},
 456             {1.5000,            2.352409615243247325767667965441644201},
 457             {1.5625,            2.490172284559350293104864895029231913},
 458             {1.6250,            2.637665356192137582275019088061812951},
 459             {1.6875,            2.795465162524235691253423614360562624},
 460             {1.7500,            2.964188309728087781773608481754531801},
 461             {1.8125,            3.144494087167972176411236052303565201},
 462             {1.8750,            3.337087043587520514308832278928116525},
 463             {1.9375,            3.542719740149244276729383650503145346},
 464             {2.0000,            3.762195691083631459562213477773746099},
 465             {2.0625,            3.996372503438463642260225717607554880},
 466             {2.1250,            4.246165228196992140600291052990934410},
 467             {2.1875,            4.512549935859540340856119781585096760},
 468             {2.2500,            4.796567530460195028666793366876218854},
 469             {2.3125,            5.099327816921939817643745917141739051},
 470             {2.3750,            5.422013837643509250646323138888569746},
 471             {2.4375,            5.765886495263270945949271410819116399},
 472             {2.5000,            6.132289479663686116619852312817562517},
 473             {2.5625,            6.522654518468725462969589397439224177},
 474             {2.6250,            6.938506971550673190999796241172117288},
 475             {2.6875,            7.381471791406976069645686221095397137},
 476             {2.7500,            7.853279872697439591457564035857305647},
 477             {2.8125,            8.355774815752725814638234943192709129},
 478             {2.8750,            8.890920130482709321824793617157134961},
 479             {2.9375,            9.460806908834119747071078865866737196},
 480             {3.0000,            10.067661995777765841953936035115890343},
 481             {3.0625,            10.713856690753651225304006562698007312},
 482             {3.1250,            11.401916013575067700373788969458446177},
 483             {3.1875,            12.134528570998387744547733730974713055},
 484             {3.2500,            12.914557062512392049483503752322408761},
 485             {3.3125,            13.745049466398732213877084541992751273},
 486             {3.3750,            14.629250949773302934853381428660210721},
 487             {3.4375,            15.570616549147269180921654324879141947},
 488             {3.5000,            16.572824671057316125696517821376119469},
 489             {3.5625,            17.639791465519127930722105721028711044},
 490             {3.6250,            18.775686128468677200079039891415789429},
 491             {3.6875,            19.984947192985946987799359614758598457},
 492             {3.7500,            21.272299872959396081877161903352144126},
 493             {3.8125,            22.642774526961913363958587775566619798},
 494             {3.8750,            24.101726314486257781049388094955970560},
 495             {3.9375,            25.654856121347151067170940701379544221},
 496             {4.0000,            27.308232836016486629201989612067059978},
 497             {4.0625,            29.068317063936918520135334110824828950},
 498             {4.1250,            30.941986372478026192360480044849306606},
 499             {4.1875,            32.936562165180269851350626768308756303},
 500             {4.2500,            35.059838290298428678502583470475012235},
 501             {4.3125,            37.320111495433027109832850313172338419},
 502             {4.3750,            39.726213847251883288518263854094284091},
 503             {4.4375,            42.287547242982546165696077854963452084},
 504             {4.5000,            45.014120148530027928305799939930642658},
 505             {4.5625,            47.916586706774825161786212701923307169},
 506             {4.6250,            51.006288368867753140854830589583165950},
 507             {4.6875,            54.295298211196782516984520211780624960},
 508             {4.7500,            57.796468111195389383795669320243166117},
 509             {4.8125,            61.523478966332915041549750463563672435},
 510             {4.8750,            65.490894152518731617237739112888213645},
 511             {4.9375,            69.714216430810089539924900313140922323},
 512             {5.0000,            74.209948524787844444106108044487704798},
 513             {5.0625,            78.995657605307475581204965926043112946},
 514             {5.1250,            84.090043934600961683400343038519519678},
 515             {5.1875,            89.513013937957834087706670952561002466},
 516             {5.2500,            95.285757988514588780586084642381131013},
 517             {5.3125,            101.430833209098212357990123684449846912},
 518             {5.3750,            107.972251614673824873137995865940755392},
 519             {5.4375,            114.935573939814969189535554289886848550},
 520             {5.5000,            122.348009517829425991091207107262038316},
 521             {5.5625,            130.238522601820409078244923165746295574},
 522             {5.6250,            138.637945543134998069351279801575968875},
 523             {5.6875,            147.579099269447055276899288971207106581},
 524             {5.7500,            157.096921533245353905868840194264636395},
 525             {5.8125,            167.228603431860671946045256541679445836},
 526             {5.8750,            178.013734732486824390148614309727161925},
 527             {5.9375,            189.494458570056311567917444025807275896},
 528             {6.0000,            201.715636122455894483405112855409538488},
 529             {6.0625,            214.725021906554080628430756558271312513},
 530             {6.1250,            228.573450380013557089736092321068279231},
 531             {6.1875,            243.315034578039208138752165587134488645},
 532             {6.2500,            259.007377561239126824465367865430519592},
 533             {6.3125,            275.711797500835732516530131577254654076},
 534             {6.3750,            293.493567280752348242602902925987643443},
 535             {6.4375,            312.422169552825597994104814531010579387},
 536             {6.5000,            332.571568241777409133204438572983297292},
 537             {6.5625,            354.020497560858198165985214519757890505},
 538             {6.6250,            376.852769667496146326030849450983914197},
 539             {6.6875,            401.157602161123700280816957271992998156},
 540             {6.7500,            427.029966702886171977469256622451185850},
 541             {6.8125,            454.570960119471524953536004647195906721},
 542             {6.8750,            483.888199441157626584508920036981010995},
 543             {6.9375,            515.096242417696720610477570797503766179},
 544             {7.0000,            548.317035155212076889964120712102928484},
 545             {7.0625,            583.680388623257719787307547662358502345},
 546             {7.1250,            621.324485894002926216918634755431456031},
 547             {7.1875,            661.396422095589629755266517362992812037},
 548             {7.2500,            704.052779189542208784574955807004218856},
 549             {7.3125,            749.460237818184878095966335081928645934},
 550             {7.3750,            797.796228612873763671070863694973560629},
 551             {7.4375,            849.249625508044731271830060572510241864},
 552             {7.5000,            904.021483770216677368692292389446994987},
 553             {7.5625,            962.325825625814651122171697031114091993},
 554             {7.6250,            1024.390476557670599008492465853663578558},
 555             {7.6875,            1090.457955538048482588540574008226583335},
 556             {7.7500,            1160.786422676798661020094043586456606003},
 557             {7.8125,            1235.650687987597295222707689125107720568},
 558             {7.8750,            1315.343285214046776004329388551335841550},
 559             {7.9375,            1400.175614911635999247504386054087931958},
 560             {8.0000,            1490.479161252178088627715460421007179728},
 561             {8.0625,            1586.606787305415349050508956232945539108},
 562             {8.1250,            1688.934113859132470361718199038326340668},
 563             {8.1875,            1797.860987165547537276364148450577336075},
 564             {8.2500,            1913.813041349231764486365114317586148767},
 565             {8.3125,            2037.243361581700856522236313401822532385},
 566             {8.3750,            2168.634254521568851112005905503069409349},
 567             {8.4375,            2308.499132938297821208734949028296170563},
 568             {8.5000,            2457.384521883751693037774022640629666294},
 569             {8.5625,            2615.872194250713123494312356053193077854},
 570             {8.6250,            2784.581444063104750127653362960649823247},
 571             {8.6875,            2964.171506380845754878370650565756538203},
 572             {8.7500,            3155.344133275174556354775488913749659006},
 573             {8.8125,            3358.846335940117183452010789979584950102},
 574             {8.8750,            3575.473303654961482727206202358956274888},
 575             {8.9375,            3806.071511003646460448021740303914939059},
 576             {9.0000,            4051.542025492594047194773093534725371440},
 577             {9.0625,            4312.844028491571841588188869958240355518},
 578             {9.1250,            4590.998563255739769060078863130940205710},
 579             {9.1875,            4887.092524674358252509551443117048351290},
 580             {9.2500,            5202.282906336187674588222835339193136030},
 581             {9.3125,            5537.801321507079474415176386655744387251},
 582             {9.3750,            5894.958815685577062811620236195525504885},
 583             {9.4375,            6275.150989541692149890530417987358096221},
 584             {9.5000,            6679.863452256851081801173722051940058824},
 585             {9.5625,            7110.677626574055535297758456126491707647},
 586             {9.6250,            7569.276928241617224537226019600213961572},
 587             {9.6875,            8057.453343996777301036241026375049070162},
 588             {9.7500,            8577.114433792824387959788368429252257664},
 589             {9.8125,            9130.290784631065880205118262838330689429},
 590             {9.8750,            9719.143945123662919857326995631317996715},
 591             {9.9375,            10345.974871791805753327922796701684092861},
 592             {10.0000,           11013.232920103323139721376090437880844591},
 593         };
 594 
 595         for(int i = 0; i < testCases.length; i++) {
 596             double [] testCase = testCases[i];
 597             failures += testCoshCaseWithUlpDiff(testCase[0],
 598                                                 testCase[1],
 599                                                 3.0);
 600         }
 601 
 602 
 603         double [][] specialTestCases = {
 604             {0.0,                       1.0},
 605             {NaNd,                      NaNd},
 606             {Double.longBitsToDouble(0x7FF0000000000001L),      NaNd},
 607             {Double.longBitsToDouble(0xFFF0000000000001L),      NaNd},
 608             {Double.longBitsToDouble(0x7FF8555555555555L),      NaNd},
 609             {Double.longBitsToDouble(0xFFF8555555555555L),      NaNd},
 610             {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL),      NaNd},
 611             {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL),      NaNd},
 612             {Double.longBitsToDouble(0x7FFDeadBeef00000L),      NaNd},
 613             {Double.longBitsToDouble(0xFFFDeadBeef00000L),      NaNd},
 614             {Double.longBitsToDouble(0x7FFCafeBabe00000L),      NaNd},
 615             {Double.longBitsToDouble(0xFFFCafeBabe00000L),      NaNd},
 616             {Double.POSITIVE_INFINITY,  Double.POSITIVE_INFINITY}
 617         };
 618 
 619         for(int i = 0; i < specialTestCases.length; i++ ) {
 620             failures += testCoshCaseWithUlpDiff(specialTestCases[i][0],
 621                                                 specialTestCases[i][1],
 622                                                 0.0);
 623         }
 624 
 625         // For powers of 2 less than 2^(-27), the second and
 626         // subsequent terms of the Taylor series expansion will get
 627         // rounded.
 628 
 629         for(int i = MIN_SUB_EXPONENT; i < -27; i++) {
 630             double d = Math.scalb(2.0, i);
 631 
 632             // Result and expected are the same.
 633             failures += testCoshCaseWithUlpDiff(d, 1.0, 2.5);
 634         }
 635 
 636         // For values of x larger than 22, the e^(-x) term is
 637         // insignificant to the floating-point result.  Util exp(x)
 638         // overflows around 709.8, cosh(x) ~= exp(x)/2; will will test
 639         // 10000 values in this range.
 640 
 641         long trans22 = Double.doubleToLongBits(22.0);
 642         // (approximately) largest value such that exp shouldn't
 643         // overflow
 644         long transExpOvfl = Double.doubleToLongBits(Math.nextDown(709.7827128933841));
 645 
 646         for(long i = trans22;
 647             i < transExpOvfl;
 648             i +=(transExpOvfl-trans22)/10000) {
 649 
 650             double d = Double.longBitsToDouble(i);
 651 
 652             // Allow 3.5 ulps of error to deal with error in exp.
 653             failures += testCoshCaseWithUlpDiff(d, StrictMath.exp(d)*0.5, 3.5);
 654         }
 655 
 656         // (approximately) largest value such that cosh shouldn't
 657         // overflow.
 658         long transCoshOvfl = Double.doubleToLongBits(710.4758600739439);
 659 
 660         // Make sure sinh(x) doesn't overflow as soon as exp(x)
 661         // overflows.
 662 
 663         /*
 664          * For large values of x, cosh(x) ~= 0.5*(e^x).  Therefore,
 665          *
 666          * cosh(x) ~= e^(ln 0.5) * e^x = e^(x + ln 0.5)
 667          *
 668          * So, we can calculate the approximate expected result as
 669          * exp(x + -0.693147186).  However, this sum suffers from
 670          * roundoff, limiting the accuracy of the approximation.  The
 671          * accuracy can be improved by recovering the rounded-off
 672          * information.  Since x is larger than ln(0.5), the trailing
 673          * bits of ln(0.5) get rounded away when the two values are
 674          * added.  However, high-order bits of ln(0.5) that
 675          * contribute to the sum can be found:
 676          *
 677          * offset = log(0.5);
 678          * effective_offset = (x + offset) - x; // exact subtraction
 679          * rounded_away_offset = offset - effective_offset; // exact subtraction
 680          *
 681          * Therefore, the product
 682          *
 683          * exp(x + offset)*exp(rounded_away_offset)
 684          *
 685          * will be a better approximation to the exact value of
 686          *
 687          * e^(x + offset)
 688          *
 689          * than exp(x+offset) alone.  (The expected result cannot be
 690          * computed as exp(x)*exp(offset) since exp(x) by itself would
 691          * overflow to infinity.)
 692          */
 693         double offset = StrictMath.log(0.5);
 694         for(long i = transExpOvfl+1; i < transCoshOvfl;
 695             i += (transCoshOvfl-transExpOvfl)/1000 ) {
 696             double input = Double.longBitsToDouble(i);
 697 
 698             double expected =
 699                 StrictMath.exp(input + offset) *
 700                 StrictMath.exp( offset - ((input + offset) - input) );
 701 
 702             failures += testCoshCaseWithUlpDiff(input, expected, 4.0);
 703         }
 704 
 705         // cosh(x) overflows for values greater than 710; in
 706         // particular, it overflows for all 2^i, i > 10.
 707         for(int i = 10; i <= Double.MAX_EXPONENT; i++) {
 708             double d = Math.scalb(2.0, i);
 709 
 710             // Result and expected are the same.
 711             failures += testCoshCaseWithUlpDiff(d,
 712                                                 Double.POSITIVE_INFINITY, 0.0);
 713         }
 714         return failures;
 715     }
 716 
 717     public static int testCoshCaseWithTolerance(double input,
 718                                                 double expected,
 719                                                 double tolerance) {
 720         int failures = 0;
 721         failures += Tests.testTolerance("Math.cosh(double)",
 722                                         input, Math.cosh(input),
 723                                         expected, tolerance);
 724         failures += Tests.testTolerance("Math.cosh(double)",
 725                                         -input, Math.cosh(-input),
 726                                         expected, tolerance);
 727 
 728         failures += Tests.testTolerance("StrictMath.cosh(double)",
 729                                         input, StrictMath.cosh(input),
 730                                         expected, tolerance);
 731         failures += Tests.testTolerance("StrictMath.cosh(double)",
 732                                         -input, StrictMath.cosh(-input),
 733                                         expected, tolerance);
 734         return failures;
 735     }
 736 
 737     public static int testCoshCaseWithUlpDiff(double input,
 738                                               double expected,
 739                                               double ulps) {
 740         int failures = 0;
 741         failures += Tests.testUlpDiff("Math.cosh(double)",
 742                                       input, Math.cosh(input),
 743                                       expected, ulps);
 744         failures += Tests.testUlpDiff("Math.cosh(double)",
 745                                       -input, Math.cosh(-input),
 746                                       expected, ulps);
 747 
 748         failures += Tests.testUlpDiff("StrictMath.cosh(double)",
 749                                       input, StrictMath.cosh(input),
 750                                       expected, ulps);
 751         failures += Tests.testUlpDiff("StrictMath.cosh(double)",
 752                                       -input, StrictMath.cosh(-input),
 753                                       expected, ulps);
 754         return failures;
 755     }
 756 
 757 
 758     /**
 759      * Test accuracy of {Math, StrictMath}.tanh.  The specified
 760      * accuracy is 2.5 ulps.
 761      *
 762      * The defintion of tanh(x) is
 763      *
 764      * (e^x - e^(-x))/(e^x + e^(-x))
 765      *
 766      * The series expansion of tanh(x) =
 767      *
 768      * x - x^3/3 + 2x^5/15 - 17x^7/315 + ...
 769      *
 770      * Therefore,
 771      *
 772      * 1. For large values of x tanh(x) ~= signum(x)
 773      *
 774      * 2. For small values of x, tanh(x) ~= x.
 775      *
 776      * Additionally, tanh is an odd function; tanh(-x) = -tanh(x).
 777      *
 778      */
 779     static int testTanh() {
 780         int failures = 0;
 781         /*
 782          * Array elements below generated using a quad sinh
 783          * implementation.  Rounded to a double, the quad result
 784          * *should* be correctly rounded, unless we are quite unlucky.
 785          * Assuming the quad value is a correctly rounded double, the
 786          * allowed error is 3.0 ulps instead of 2.5 since the quad
 787          * value rounded to double can have its own 1/2 ulp error.
 788          */
 789         double [][] testCases = {
 790             // x                tanh(x)
 791             {0.0625,            0.06241874674751251449014289119421133},
 792             {0.1250,            0.12435300177159620805464727580589271},
 793             {0.1875,            0.18533319990813951753211997502482787},
 794             {0.2500,            0.24491866240370912927780113149101697},
 795             {0.3125,            0.30270972933210848724239738970991712},
 796             {0.3750,            0.35835739835078594631936023155315807},
 797             {0.4375,            0.41157005567402245143207555859415687},
 798             {0.5000,            0.46211715726000975850231848364367256},
 799             {0.5625,            0.50982997373525658248931213507053130},
 800             {0.6250,            0.55459972234938229399903909532308371},
 801             {0.6875,            0.59637355547924233984437303950726939},
 802             {0.7500,            0.63514895238728731921443435731249638},
 803             {0.8125,            0.67096707420687367394810954721913358},
 804             {0.8750,            0.70390560393662106058763026963135371},
 805             {0.9375,            0.73407151960434149263991588052503660},
 806             {1.0000,            0.76159415595576488811945828260479366},
 807             {1.0625,            0.78661881210869761781941794647736081},
 808             {1.1250,            0.80930107020178101206077047354332696},
 809             {1.1875,            0.82980190998595952708572559629034476},
 810             {1.2500,            0.84828363995751289761338764670750445},
 811             {1.3125,            0.86490661772074179125443141102709751},
 812             {1.3750,            0.87982669965198475596055310881018259},
 813             {1.4375,            0.89319334040035153149249598745889365},
 814             {1.5000,            0.90514825364486643824230369645649557},
 815             {1.5625,            0.91582454416876231820084311814416443},
 816             {1.6250,            0.92534622531174107960457166792300374},
 817             {1.6875,            0.93382804322259173763570528576138652},
 818             {1.7500,            0.94137553849728736226942088377163687},
 819             {1.8125,            0.94808528560440629971240651310180052},
 820             {1.8750,            0.95404526017994877009219222661968285},
 821             {1.9375,            0.95933529331468249183399461756952555},
 822             {2.0000,            0.96402758007581688394641372410092317},
 823             {2.0625,            0.96818721657637057702714316097855370},
 824             {2.1250,            0.97187274591350905151254495374870401},
 825             {2.1875,            0.97513669829362836159665586901156483},
 826             {2.2500,            0.97802611473881363992272924300618321},
 827             {2.3125,            0.98058304703705186541999427134482061},
 828             {2.3750,            0.98284502917257603002353801620158861},
 829             {2.4375,            0.98484551746427837912703608465407824},
 830             {2.5000,            0.98661429815143028888127603923734964},
 831             {2.5625,            0.98817786228751240824802592958012269},
 832             {2.6250,            0.98955974861288320579361709496051109},
 833             {2.6875,            0.99078085564125158320311117560719312},
 834             {2.7500,            0.99185972456820774534967078914285035},
 835             {2.8125,            0.99281279483715982021711715899682324},
 836             {2.8750,            0.99365463431502962099607366282699651},
 837             {2.9375,            0.99439814606575805343721743822723671},
 838             {3.0000,            0.99505475368673045133188018525548849},
 839             {3.0625,            0.99563456710930963835715538507891736},
 840             {3.1250,            0.99614653067334504917102591131792951},
 841             {3.1875,            0.99659855517712942451966113109487039},
 842             {3.2500,            0.99699763548652601693227592643957226},
 843             {3.3125,            0.99734995516557367804571991063376923},
 844             {3.3750,            0.99766097946988897037219469409451602},
 845             {3.4375,            0.99793553792649036103161966894686844},
 846             {3.5000,            0.99817789761119870928427335245061171},
 847             {3.5625,            0.99839182812874152902001617480606320},
 848             {3.6250,            0.99858065920179882368897879066418294},
 849             {3.6875,            0.99874733168378115962760304582965538},
 850             {3.7500,            0.99889444272615280096784208280487888},
 851             {3.8125,            0.99902428575443546808677966295308778},
 852             {3.8750,            0.99913888583735077016137617231569011},
 853             {3.9375,            0.99924003097049627100651907919688313},
 854             {4.0000,            0.99932929973906704379224334434172499},
 855             {4.0625,            0.99940808577297384603818654530731215},
 856             {4.1250,            0.99947761936180856115470576756499454},
 857             {4.1875,            0.99953898655601372055527046497863955},
 858             {4.2500,            0.99959314604388958696521068958989891},
 859             {4.3125,            0.99964094406130644525586201091350343},
 860             {4.3750,            0.99968312756179494813069349082306235},
 861             {4.4375,            0.99972035584870534179601447812936151},
 862             {4.5000,            0.99975321084802753654050617379050162},
 863             {4.5625,            0.99978220617994689112771768489030236},
 864             {4.6250,            0.99980779516900105210240981251048167},
 865             {4.6875,            0.99983037791655283849546303868853396},
 866             {4.7500,            0.99985030754497877753787358852000255},
 867             {4.8125,            0.99986789571029070417475400133989992},
 868             {4.8750,            0.99988341746867772271011794614780441},
 869             {4.9375,            0.99989711557251558205051185882773206},
 870             {5.0000,            0.99990920426259513121099044753447306},
 871             {5.0625,            0.99991987261554158551063867262784721},
 872             {5.1250,            0.99992928749851651137225712249720606},
 873             {5.1875,            0.99993759617721206697530526661105307},
 874             {5.2500,            0.99994492861777083305830639416802036},
 875             {5.3125,            0.99995139951851344080105352145538345},
 876             {5.3750,            0.99995711010315817210152906092289064},
 877             {5.4375,            0.99996214970350792531554669737676253},
 878             {5.5000,            0.99996659715630380963848952941756868},
 879             {5.5625,            0.99997052203605101013786592945475432},
 880             {5.6250,            0.99997398574306704793434088941484766},
 881             {5.6875,            0.99997704246374583929961850444364696},
 882             {5.7500,            0.99997974001803825215761760428815437},
 883             {5.8125,            0.99998212060739040166557477723121777},
 884             {5.8750,            0.99998422147482750993344503195672517},
 885             {5.9375,            0.99998607548749972326220227464612338},
 886             {6.0000,            0.99998771165079557056434885235523206},
 887             {6.0625,            0.99998915556205996764518917496149338},
 888             {6.1250,            0.99999042981101021976277974520745310},
 889             {6.1875,            0.99999155433311068015449574811497719},
 890             {6.2500,            0.99999254672143162687722782398104276},
 891             {6.3125,            0.99999342250186907900400800240980139},
 892             {6.3750,            0.99999419537602957780612639767025158},
 893             {6.4375,            0.99999487743557848265406225515388994},
 894             {6.5000,            0.99999547935140419285107893831698753},
 895             {6.5625,            0.99999601054055694588617385671796346},
 896             {6.6250,            0.99999647931357331502887600387959900},
 897             {6.6875,            0.99999689300449080997594368612277442},
 898             {6.7500,            0.99999725808558628431084200832778748},
 899             {6.8125,            0.99999758026863294516387464046135924},
 900             {6.8750,            0.99999786459425991170635407313276785},
 901             {6.9375,            0.99999811551081218572759991597586905},
 902             {7.0000,            0.99999833694394467173571641595066708},
 903             {7.0625,            0.99999853235803894918375164252059190},
 904             {7.1250,            0.99999870481040359014665019356422927},
 905             {7.1875,            0.99999885699910593255108365463415411},
 906             {7.2500,            0.99999899130518359709674536482047025},
 907             {7.3125,            0.99999910982989611769943303422227663},
 908             {7.3750,            0.99999921442759946591163427422888252},
 909             {7.4375,            0.99999930673475777603853435094943258},
 910             {7.5000,            0.99999938819554614875054970643513124},
 911             {7.5625,            0.99999946008444508183970109263856958},
 912             {7.6250,            0.99999952352618001331402589096040117},
 913             {7.6875,            0.99999957951331792817413683491979752},
 914             {7.7500,            0.99999962892179632633374697389145081},
 915             {7.8125,            0.99999967252462750190604116210421169},
 916             {7.8750,            0.99999971100399253750324718031574484},
 917             {7.9375,            0.99999974496191422474977283863588658},
 918             {8.0000,            0.99999977492967588981001883295636840},
 919             {8.0625,            0.99999980137613348259726597081723424},
 920             {8.1250,            0.99999982471505097353529823063673263},
 921             {8.1875,            0.99999984531157382142423402736529911},
 922             {8.2500,            0.99999986348794179107425910499030547},
 923             {8.3125,            0.99999987952853049895833839645847571},
 924             {8.3750,            0.99999989368430056302584289932834041},
 925             {8.4375,            0.99999990617672396471542088609051728},
 926             {8.5000,            0.99999991720124905211338798152800748},
 927             {8.5625,            0.99999992693035839516545287745322387},
 928             {8.6250,            0.99999993551626733394129009365703767},
 929             {8.6875,            0.99999994309330543951799157347876934},
 930             {8.7500,            0.99999994978001814614368429416607424},
 931             {8.8125,            0.99999995568102143535399207289008504},
 932             {8.8750,            0.99999996088863858914831986187674522},
 933             {8.9375,            0.99999996548434461974481685677429908},
 934             {9.0000,            0.99999996954004097447930211118358244},
 935             {9.0625,            0.99999997311918045901919121395899372},
 936             {9.1250,            0.99999997627775997868467948564005257},
 937             {9.1875,            0.99999997906519662964368381583648379},
 938             {9.2500,            0.99999998152510084671976114264303159},
 939             {9.3125,            0.99999998369595870397054673668361266},
 940             {9.3750,            0.99999998561173404286033236040150950},
 941             {9.4375,            0.99999998730239984852716512979473289},
 942             {9.5000,            0.99999998879440718770812040917618843},
 943             {9.5625,            0.99999999011109904501789298212541698},
 944             {9.6250,            0.99999999127307553219220251303121960},
 945             {9.6875,            0.99999999229851618412119275358396363},
 946             {9.7500,            0.99999999320346438410630581726217930},
 947             {9.8125,            0.99999999400207836827291739324060736},
 948             {9.8750,            0.99999999470685273619047001387577653},
 949             {9.9375,            0.99999999532881393331131526966058758},
 950             {10.0000,           0.99999999587769276361959283713827574},
 951         };
 952 
 953         for(int i = 0; i < testCases.length; i++) {
 954             double [] testCase = testCases[i];
 955             failures += testTanhCaseWithUlpDiff(testCase[0],
 956                                                 testCase[1],
 957                                                 3.0);
 958         }
 959 
 960 
 961         double [][] specialTestCases = {
 962             {0.0,                       0.0},
 963             {NaNd,                      NaNd},
 964             {Double.longBitsToDouble(0x7FF0000000000001L),      NaNd},
 965             {Double.longBitsToDouble(0xFFF0000000000001L),      NaNd},
 966             {Double.longBitsToDouble(0x7FF8555555555555L),      NaNd},
 967             {Double.longBitsToDouble(0xFFF8555555555555L),      NaNd},
 968             {Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL),      NaNd},
 969             {Double.longBitsToDouble(0xFFFFFFFFFFFFFFFFL),      NaNd},
 970             {Double.longBitsToDouble(0x7FFDeadBeef00000L),      NaNd},
 971             {Double.longBitsToDouble(0xFFFDeadBeef00000L),      NaNd},
 972             {Double.longBitsToDouble(0x7FFCafeBabe00000L),      NaNd},
 973             {Double.longBitsToDouble(0xFFFCafeBabe00000L),      NaNd},
 974             {Double.POSITIVE_INFINITY,  1.0}
 975         };
 976 
 977         for(int i = 0; i < specialTestCases.length; i++) {
 978             failures += testTanhCaseWithUlpDiff(specialTestCases[i][0],
 979                                                 specialTestCases[i][1],
 980                                                 0.0);
 981         }
 982 
 983         // For powers of 2 less than 2^(-27), the second and
 984         // subsequent terms of the Taylor series expansion will get
 985         // rounded away since |n-n^3| > 53, the binary precision of a
 986         // double significand.
 987 
 988         for(int i = MIN_SUB_EXPONENT; i < -27; i++) {
 989             double d = Math.scalb(2.0, i);
 990 
 991             // Result and expected are the same.
 992             failures += testTanhCaseWithUlpDiff(d, d, 2.5);
 993         }
 994 
 995         // For values of x larger than 22, tanh(x) is 1.0 in double
 996         // floating-point arithmetic.
 997 
 998         for(int i = 22; i < 32; i++) {
 999             failures += testTanhCaseWithUlpDiff(i, 1.0, 2.5);
1000         }
1001 
1002         for(int i = 5; i <= Double.MAX_EXPONENT; i++) {
1003             double d = Math.scalb(2.0, i);
1004 
1005             failures += testTanhCaseWithUlpDiff(d, 1.0, 2.5);
1006         }
1007 
1008         return failures;
1009     }
1010 
1011     public static int testTanhCaseWithTolerance(double input,
1012                                                 double expected,
1013                                                 double tolerance) {
1014         int failures = 0;
1015         failures += Tests.testTolerance("Math.tanh(double",
1016                                         input, Math.tanh(input),
1017                                         expected, tolerance);
1018         failures += Tests.testTolerance("Math.tanh(double",
1019                                         -input, Math.tanh(-input),
1020                                         -expected, tolerance);
1021 
1022         failures += Tests.testTolerance("StrictMath.tanh(double",
1023                                         input, StrictMath.tanh(input),
1024                                         expected, tolerance);
1025         failures += Tests.testTolerance("StrictMath.tanh(double",
1026                                         -input, StrictMath.tanh(-input),
1027                                         -expected, tolerance);
1028         return failures;
1029     }
1030 
1031     public static int testTanhCaseWithUlpDiff(double input,
1032                                               double expected,
1033                                               double ulps) {
1034         int failures = 0;
1035 
1036         failures += Tests.testUlpDiffWithAbsBound("Math.tanh(double)",
1037                                                   input, Math.tanh(input),
1038                                                   expected, ulps, 1.0);
1039         failures += Tests.testUlpDiffWithAbsBound("Math.tanh(double)",
1040                                                   -input, Math.tanh(-input),
1041                                                   -expected, ulps, 1.0);
1042 
1043         failures += Tests.testUlpDiffWithAbsBound("StrictMath.tanh(double)",
1044                                                   input, StrictMath.tanh(input),
1045                                                   expected, ulps, 1.0);
1046         failures += Tests.testUlpDiffWithAbsBound("StrictMath.tanh(double)",
1047                                                   -input, StrictMath.tanh(-input),
1048                                                   -expected, ulps, 1.0);
1049         return failures;
1050     }
1051 
1052 
1053     public static void main(String argv[]) {
1054         int failures = 0;
1055 
1056         failures += testSinh();
1057         failures += testCosh();
1058         failures += testTanh();
1059 
1060         if (failures > 0) {
1061             System.err.println("Testing the hyperbolic functions incurred "
1062                                + failures + " failures.");
1063             throw new RuntimeException();
1064         }
1065     }
1066 
1067 }