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