diff --git a/src/main/java/com/dynatrace/hash4j/distinctcount/UltraLogLog.java b/src/main/java/com/dynatrace/hash4j/distinctcount/UltraLogLog.java index 03283285..48a05a9d 100644 --- a/src/main/java/com/dynatrace/hash4j/distinctcount/UltraLogLog.java +++ b/src/main/java/com/dynatrace/hash4j/distinctcount/UltraLogLog.java @@ -416,8 +416,7 @@ private static final class MaximumLikelihoodEstimator implements Estimator { // // for a numerical evaluation see // https://www.wolframalpha.com/input?i=sqrt%28ln%282%29%2Fzeta%282%2C5%2F4%29%29 - private static final double INV_SQRT_FISHER_INFORMATION = - 0.7608621002725182046969980445546699052078408464652591074059522646; + private static final double INV_SQRT_FISHER_INFORMATION = 0.7608621002725182; private static final double ML_EQUATION_SOLVER_EPS = 0.001 * INV_SQRT_FISHER_INFORMATION; // 0.1% of theoretical relative error @@ -428,8 +427,7 @@ private static final class MaximumLikelihoodEstimator implements Estimator { // // for a numerical evaluation see // https://www.wolframalpha.com/input?i=3%2F2+*+ln%282%29+*+zeta%283%2C5%2F4%29%2F%28zeta%282%2C5%2F4%29%29%5E2 - private static final double ML_BIAS_CORRECTION_CONSTANT = - 0.4814737652772006629514810906704298203396203932131028763547546717; + private static final double ML_BIAS_CORRECTION_CONSTANT = 0.48147376527720066; // returns contribution to alpha, scaled by 2^64 private static long contribute(int r, int[] b, int p) { @@ -492,12 +490,12 @@ public double estimate(UltraLogLog ultraLogLog) { static final class OptimalFGRAEstimator implements Estimator { - static final double ETA_0 = 4.663135749698441; - static final double ETA_1 = 2.137850286535751; - static final double ETA_2 = 2.7811447941454626; - static final double ETA_3 = 0.9824082439220764; - static final double TAU = 0.8194911850376387; - static final double V = 0.6118931496978426; + static final double ETA_0 = 4.663135422063788; + static final double ETA_1 = 2.1378502137958524; + static final double ETA_2 = 2.781144650979996; + static final double ETA_3 = 0.9824082545153715; + static final double TAU = 0.8194911375910897; + static final double V = 0.6118931496978437; static final double POW_2_TAU = pow(2., TAU); static final double POW_2_MINUS_TAU = pow(2., -TAU); @@ -524,269 +522,269 @@ static double calculateTheoreticalRelativeStandardError(int p) { } static final double[] ESTIMATION_FACTORS = { - 94.59940317105753, - 455.6357508097479, - 2159.47633067634, - 10149.50737889237, - 47499.51084005241, - 221818.67873312163, - 1034754.2279126811, - 4824372.022091801, - 2.2486738498576667E7, - 1.047980404094012E8, - 4.8837154531911695E8, - 2.27579316515324E9, - 1.0604931024655107E10, - 4.9417323383735405E10, - 2.3027603606246478E11, - 1.0730435513524987E12, - 5.000178308875647E12, - 2.329986496461238E13, - 1.0857284075307834E14, - 5.059282619272261E14, - 2.35752686818917E15, - 1.0985614301620942E16, - 5.1190814073112568E16, - 2.3853917967466928E17 + 94.59941722950778, + 455.6358404615186, + 2159.476860400962, + 10149.51036338182, + 47499.52712820488, + 221818.76564766388, + 1034754.6840013304, + 4824374.384717942, + 2.2486750611989766E7, + 1.0479810199493326E8, + 4.8837185623048025E8, + 2.275794725435168E9, + 1.0604938814719946E10, + 4.9417362104242645E10, + 2.30276227770117E11, + 1.0730444972228585E12, + 5.0001829613164E12, + 2.329988778511272E13, + 1.0857295240912981E14, + 5.059288069986326E14, + 2.3575295235667005E15, + 1.0985627213141412E16, + 5.1190876745155888E16, + 2.38539483395717152E17 }; static final double[] REGISTER_CONTRIBUTIONS = { - 0.8484060852397345, - 0.38895826537877115, - 0.5059986013571249, - 0.17873833769198574, - 0.48074231113842836, - 0.22039999321992973, - 0.286719934334865, - 0.10128060494380546, - 0.272408665778737, - 0.12488783845238811, - 0.16246748612446876, - 0.057389819499496945, - 0.15435812382651734, - 0.07076666367111045, - 0.09206086109372673, - 0.032519467908117806, - 0.08746575782796642, - 0.04009934633506583, - 0.052165527684877616, - 0.01842688829220614, - 0.049561750316546825, - 0.02272196388927665, - 0.02955916603768511, - 0.010441444278634157, - 0.028083757066063253, - 0.01287521344292119, - 0.016749457651834092, - 0.0059165582867257505, - 0.01591342932621048, - 0.007295633511635504, - 0.009490942040547306, - 0.0033525689575199494, - 0.009017213484812202, - 0.004134010560062819, - 0.0053779640325944825, - 0.0018997055501242264, - 0.005109529653470475, - 0.0023425029894189064, - 0.003047378965366866, - 0.0010764524825292335, - 0.002895272838296102, - 0.0013273599996205937, - 0.0017267721580652433, - 6.099629213946215E-4, - 0.001640582475626021, - 7.521375966439396E-4, - 9.78461202153218E-4, - 3.456304588587883E-4, - 9.296225294315218E-4, - 4.2619256603108554E-4, - 5.544369705334033E-4, - 1.9584864899296144E-4, - 5.267629394230223E-4, - 2.4149850260197735E-4, - 3.141671367426608E-4, - 1.1097602172856929E-4, - 2.984858752501032E-4, - 1.3684313478791045E-4, - 1.780202170034317E-4, - 6.288364745953644E-5, - 1.691345595068001E-4, - 7.754103374067414E-5, - 1.0087368777819569E-4, - 3.563250021240636E-5, - 9.583870324044556E-5, - 4.393798726469656E-5, - 5.7159243243573585E-5, - 2.019086237330832E-5, - 5.430621078030427E-5, - 2.489709811361428E-5, - 3.238881377433127E-5, - 1.1440985643660703E-5, - 3.0772166458844975E-5, - 1.4107735312149528E-5, - 1.8352854204840335E-5, - 6.4829401576968245E-6, - 1.7436794336501408E-5, - 7.994031863851523E-6, - 1.0399493473609907E-5, - 3.673504573582387E-6, - 9.880415704239646E-6, - 4.5297522264427E-6, - 5.892787209039795E-6, - 2.0815610701125073E-6, - 5.598656072018156E-6, - 2.5667467408713467E-6, - 3.339099272396502E-6, - 1.1794994131128855E-6, - 3.1724322893920124E-6, - 1.4544258719747923E-6, - 1.8920730641376115E-6, - 6.683536147505137E-7, - 1.797632592771347E-6, - 8.241384252626048E-7, - 1.0721275972923483E-6, - 3.787170636831222E-7, - 1.0186136830719034E-6, - 4.6699124175514954E-7, - 6.075122608437811E-7, - 2.1459690074139074E-7, - 5.771890426962716E-7, - 2.64616735721948E-7, - 3.4424181226899694E-7, - 1.2159956395929028E-7, - 3.2705941079050064E-7, - 1.499428909222517E-7, - 1.9506178385544662E-7, - 6.890339004899508E-8, - 1.8532551776613992E-7, - 8.496390251653092E-8, - 1.10530151087912E-7, - 3.9043537704077566E-8, - 1.0501317620635024E-7, - 4.814409463788256E-8, - 6.263099853823858E-8, - 2.2123698636101623E-8, - 5.950485022176909E-8, - 2.728045416758512E-8, - 3.548933878482537E-8, - 1.2536211371284819E-8, - 3.371793262359259E-8, - 1.5458244363870842E-8, - 2.0109741131065348E-8, - 7.103540783595807E-9, - 1.9105988439127425E-8, - 8.759286679951094E-9, - 1.1395018960775247E-8, - 4.025162799966202E-9, - 1.082625077614191E-8, - 4.963377556696614E-9, - 6.45689351594096E-9, - 2.2808253038606898E-9, - 6.134605714922463E-9, - 2.8124569580199258E-9, - 3.6587454588460008E-9, - 1.2924108477736359E-9, - 3.4761237344042517E-9, - 1.5936555400752456E-9, - 2.073197939470036E-9, - 7.323339479861321E-10, - 1.969716845451942E-9, - 9.030317684223642E-10, - 1.1747605141076048E-9, - 4.149709918458438E-10, - 1.1161238056222668E-9, - 5.116955039992654E-10, - 6.656683567123106E-10, - 2.351398901376407E-10, - 6.324423494438382E-10, - 2.899480372329477E-10, - 3.771954843619131E-10, - 1.3324007947640234E-10, - 3.5836824136820584E-10, - 1.64296664008522E-10, - 2.1373471036795443E-10, - 7.549939216389946E-11, - 2.0306640839956248E-10, - 9.309734965594018E-11, - 1.2111101089492876E-10, - 4.278110790325553E-11, - 1.1506590556926544E-10, - 5.27528453804198E-11, - 6.862655548431996E-11, - 2.424156196458913E-11, - 6.520114640735252E-11, - 2.9891964766076615E-11, - 3.8886671681143153E-11, - 1.3736281159710114E-11, - 3.694569187806878E-11, - 1.6938035306585002E-11, - 2.2034811797927628E-11, - 7.783550431866983E-12, - 2.0934971600365387E-11, - 9.597798013354695E-12, - 1.2485844377510246E-11, - 4.410484658912948E-12, - 1.186262900027782E-11, - 5.438513088312147E-12, - 7.075000741965357E-12, - 2.499164757366473E-12, - 6.721860888303071E-12, - 3.0816885884228205E-12, - 4.0089908207546885E-12, - 1.4161310983908962E-12, - 3.808887035128585E-12, - 1.7462134230080132E-12, - 2.27166158521571E-12, - 8.02439007639917E-13, - 2.158274425407386E-12, - 9.894774345950254E-13, - 1.2872183021794324E-12, - 4.546954457209435E-13, - 1.2229684032123849E-12, - 5.60679227792338E-13, - 7.293916348496756E-13, - 2.576494243063289E-13, - 6.929849594884327E-13, - 3.177042603366454E-13, - 4.1330375437322283E-13, - 1.459949213701249E-13, - 3.926742120366818E-13, - 1.8002449891623002E-13, - 2.3419516377399323E-13, - 8.272681812992227E-14, - 2.2250560374709368E-13, - 1.0200939759416105E-13, - 1.3270475807388645E-13, - 4.6876469220125044E-14, - 1.260809652919964E-13, - 5.780278384424677E-14, - 7.51960567061224E-14, - 2.6562164679104723E-14, - 7.144273915469492E-14, - 3.275347074822785E-14, - 4.26092253678056E-14, - 1.505123154917496E-14, - 4.0482438932039044E-14, - 1.855948407166197E-14, - 2.41441661434439E-14, - 8.528656225261955E-15, - 2.2939040149870594E-14, - 1.051657858350517E-14, - 1.3681092620911158E-14, - 4.832692711626445E-15, - 1.299821791569287E-14, - 5.959132520925467E-15, - 7.752278301513157E-15, - 2.7384054683585176E-15, - 7.365332981676317E-15, - 3.3766932962065717E-15, - 4.392764564158709E-15, - 1.5516948741837312E-15, - 4.173505189928762E-15, - 1.91337540768026E-15, - 2.4891238118169875E-15, - 8.792551031572981E-16 + 0.8484061093359406, + 0.38895829052007685, + 0.5059986252327467, + 0.17873835725405993, + 0.48074234060273024, + 0.22040001471443574, + 0.2867199572932749, + 0.10128061935935387, + 0.2724086914332655, + 0.12488785473931466, + 0.16246750447680292, + 0.057389829555353204, + 0.15435814343988866, + 0.0707666752272979, + 0.09206087452057209, + 0.03251947467566813, + 0.08746577181824695, + 0.0400993542020493, + 0.05216553700867983, + 0.018426892732996067, + 0.04956175987398336, + 0.022721969094305374, + 0.029559172293066274, + 0.01044144713836362, + 0.02808376340530896, + 0.012875216815740723, + 0.01674946174724118, + 0.005916560101748389, + 0.015913433441643893, + 0.0072956356627506685, + 0.009490944673308844, + 0.0033525700962450116, + 0.009017216113341773, + 0.004134011914931561, + 0.0053779657012946284, + 0.0018997062578498703, + 0.005109531310944485, + 0.002342503834183061, + 0.00304738001114257, + 0.001076452918957914, + 0.0028952738727082267, + 0.0013273605219527246, + 0.0017267728074345586, + 6.09963188753462E-4, + 0.0016405831157217021, + 7.521379173550258E-4, + 9.78461602292084E-4, + 3.4563062172237723E-4, + 9.2962292270938E-4, + 4.2619276177576713E-4, + 5.544372155028133E-4, + 1.958487477192352E-4, + 5.267631795945699E-4, + 2.4149862146135835E-4, + 3.141672858847145E-4, + 1.1097608132071735E-4, + 2.9848602115777116E-4, + 1.3684320663902123E-4, + 1.7802030736817869E-4, + 6.288368329501905E-5, + 1.6913464774658265E-4, + 7.754107700464113E-5, + 1.0087374230011362E-4, + 3.563252169014952E-5, + 9.583875639268212E-5, + 4.393801322487549E-5, + 5.715927601779108E-5, + 2.0190875207520577E-5, + 5.430624268457414E-5, + 2.4897113642537945E-5, + 3.2388833410757184E-5, + 1.144099329232623E-5, + 3.0772185549154786E-5, + 1.4107744575453657E-5, + 1.8352865935237916E-5, + 6.482944704957522E-6, + 1.7436805727319977E-5, + 7.99403737572986E-6, + 1.0399500462555932E-5, + 3.67350727106242E-6, + 9.880422483694849E-6, + 4.529755498675165E-6, + 5.892791363067244E-6, + 2.081562667074589E-6, + 5.5986600976661345E-6, + 2.5667486794686803E-6, + 3.339101736056405E-6, + 1.1795003568090263E-6, + 3.1724346748254955E-6, + 1.4544270182973653E-6, + 1.8920745223756656E-6, + 6.683541714686068E-7, + 1.7976340035771381E-6, + 8.241391019206623E-7, + 1.072128458850476E-6, + 3.7871739159788393E-7, + 1.0186145159929963E-6, + 4.6699164053601817E-7, + 6.075127690181302E-7, + 2.1459709360913574E-7, + 5.77189533646426E-7, + 2.6461697039041317E-7, + 3.442421115430427E-7, + 1.2159967724530947E-7, + 3.27059699739513E-7, + 1.4994302882644454E-7, + 1.9506195985170504E-7, + 6.890345650764188E-8, + 1.853256875916027E-7, + 8.49639834530526E-8, + 1.1053025444979778E-7, + 3.904357664636507E-8, + 1.0501327589016596E-7, + 4.814414208323267E-8, + 6.263105916717392E-8, + 2.2123721430020238E-8, + 5.9504908663745294E-8, + 2.7280481949286693E-8, + 3.548937430686624E-8, + 1.2536224699555158E-8, + 3.371796684815404E-8, + 1.545826061452554E-8, + 2.0109761920695445E-8, + 7.103548569567803E-9, + 1.910600846054063E-8, + 8.759296176321385E-9, + 1.139503111580109E-8, + 4.0251673442004705E-9, + 1.082626247715867E-8, + 4.963383100969499E-9, + 6.456900615837058E-9, + 2.28082795382416E-9, + 6.134612546958812E-9, + 2.812460192131048E-9, + 3.65874960227048E-9, + 1.292412391857717E-9, + 3.476127720042246E-9, + 1.5936574250689536E-9, + 2.0732003554895977E-9, + 7.323348470132607E-10, + 1.9697191686598677E-9, + 9.030328662369446E-10, + 1.1747619217600795E-9, + 4.1497151491950363E-10, + 1.1161251587553774E-9, + 5.116961428952198E-10, + 6.656691762391315E-10, + 2.351401942661752E-10, + 6.324431369849931E-10, + 2.899484087937328E-10, + 3.771959611450379E-10, + 1.3324025619025952E-10, + 3.5836869940773545E-10, + 1.6429687995368037E-10, + 2.1373498756237659E-10, + 7.549949478033437E-11, + 2.0306667462222755E-10, + 9.309747508122088E-11, + 1.2111117194789844E-10, + 4.2781167456975155E-11, + 1.1506606020637118E-10, + 5.275291818652914E-11, + 6.86266490006118E-11, + 2.424159650745726E-11, + 6.520123617549523E-11, + 2.9892007004129765E-11, + 3.888672595026375E-11, + 1.3736301184893309E-11, + 3.6945743959497274E-11, + 1.693805979747882E-11, + 2.2034843273746723E-11, + 7.783562034953282E-12, + 2.093500180037604E-11, + 9.597812206565218E-12, + 1.248586262365167E-11, + 4.4104913787558985E-12, + 1.186264650299681E-11, + 5.4385213096368525E-12, + 7.075011313669894E-12, + 2.499168647301308E-12, + 6.721871027139603E-12, + 3.081693348317683E-12, + 4.008996942969544E-12, + 1.4161333491633975E-12, + 3.808892905481426E-12, + 1.7462161775917615E-12, + 2.271665129027518E-12, + 8.024403094117999E-13, + 2.1582778227746425E-12, + 9.89479027998621E-13, + 1.2872203525845489E-12, + 4.54696198313039E-13, + 1.2229703685228866E-12, + 5.606801491206791E-13, + 7.293928206826874E-13, + 2.5764985922987735E-13, + 6.92986095905959E-13, + 3.1770479284824887E-13, + 4.1330443990824427E-13, + 1.4599517261737423E-13, + 3.926748688923721E-13, + 1.8002480658009348E-13, + 2.3419555992885186E-13, + 8.272696321778206E-14, + 2.225059832666067E-13, + 1.0200957528418621E-13, + 1.327049869160979E-13, + 4.687655297461429E-14, + 1.2608118449008524E-13, + 5.780288643182276E-14, + 7.519618885068399E-14, + 2.656221301145837E-14, + 7.144286571105751E-14, + 3.2753529955811655E-14, + 4.2609301647742677E-14, + 1.5051259431302017E-14, + 4.0482511975524363E-14, + 1.8559518231526075E-14, + 2.4144210160882415E-14, + 8.528672304925501E-15, + 2.293908229376684E-14, + 1.0516598285774437E-14, + 1.3681118012966618E-14, + 4.832701981970378E-15, + 1.2998242223663023E-14, + 5.959143881034847E-15, + 7.752292944665042E-15, + 2.7384108113817744E-15, + 7.365346997814574E-15, + 3.376699844369893E-15, + 4.392773006047039E-15, + 1.5516979527951759E-15, + 4.173513269314059E-15, + 1.9133791810691354E-15, + 2.4891286772044455E-15, + 8.792568765435867E-16 }; static double smallRangeEstimate(long c0, long c4, long c8, long c10, long m) { diff --git a/src/test/java/com/dynatrace/hash4j/distinctcount/DistinctCounterTest.java b/src/test/java/com/dynatrace/hash4j/distinctcount/DistinctCounterTest.java index 0f855575..5f859de3 100644 --- a/src/test/java/com/dynatrace/hash4j/distinctcount/DistinctCounterTest.java +++ b/src/test/java/com/dynatrace/hash4j/distinctcount/DistinctCounterTest.java @@ -45,8 +45,6 @@ abstract class DistinctCounterTest< protected abstract int getMaxP(); - protected static final double RELATIVE_ERROR = 1e-12; - protected abstract T create(int p); protected abstract T merge(T sketch1, T sketch2); diff --git a/src/test/java/com/dynatrace/hash4j/distinctcount/HyperLogLogTest.java b/src/test/java/com/dynatrace/hash4j/distinctcount/HyperLogLogTest.java index 36c83b2b..0b35ef1d 100644 --- a/src/test/java/com/dynatrace/hash4j/distinctcount/HyperLogLogTest.java +++ b/src/test/java/com/dynatrace/hash4j/distinctcount/HyperLogLogTest.java @@ -18,7 +18,6 @@ import static com.dynatrace.hash4j.distinctcount.HyperLogLog.*; import static com.dynatrace.hash4j.distinctcount.HyperLogLog.CorrectedRawEstimator.sigma; import static com.dynatrace.hash4j.distinctcount.HyperLogLog.CorrectedRawEstimator.tau; -import static com.dynatrace.hash4j.testutils.TestUtils.compareWithMaxRelativeError; import static org.assertj.core.api.Assertions.*; import static org.assertj.core.data.Percentage.withPercentage; @@ -34,13 +33,12 @@ class HyperLogLogTest extends DistinctCounterTest { - private static final double VARIANCE_FACTOR_RAW = 3. * Math.log(2) - 1.; + private static final double VARIANCE_FACTOR_RAW = 3. * StrictMath.log(2) - 1.; - private static final double VARIANCE_FACTOR_MARTINGALE = Math.log(2); + private static final double VARIANCE_FACTOR_MARTINGALE = StrictMath.log(2); // see https://www.wolframalpha.com/input?i=ln%282%29%2Fzeta%282%2C+2%29 - private static final double VARIANCE_FACTOR_ML = - 1.0747566552769260937701392307869745509357687653622079625754435936; + private static final double VARIANCE_FACTOR_ML = 1.074756655276926; @Test void testRelativeStandardErrorAgainstConstants() { @@ -74,9 +72,7 @@ void testRelativeStandardErrorAgainstConstants() { IntStream.range(MIN_P, MAX_P + 1) .mapToDouble(this::calculateTheoreticalRelativeStandardErrorRaw) .toArray(); - assertThat(actual) - .usingElementComparator(compareWithMaxRelativeError(RELATIVE_ERROR)) - .isEqualTo(expected); + assertThat(actual).isEqualTo(expected); } @Override @@ -114,8 +110,8 @@ protected HyperLogLog merge(HyperLogLog sketch1, HyperLogLog sketch2) { * @param p the precision parameter * @return the relative standard error */ - protected double calculateTheoreticalRelativeStandardErrorRaw(int p) { - return Math.sqrt(VARIANCE_FACTOR_RAW / (1 << p)); + protected strictfp double calculateTheoreticalRelativeStandardErrorRaw(int p) { + return StrictMath.sqrt(VARIANCE_FACTOR_RAW / (1 << p)); } protected double calculateTheoreticalRelativeStandardErrorDefault(int p) { @@ -123,13 +119,13 @@ protected double calculateTheoreticalRelativeStandardErrorDefault(int p) { } @Override - protected double calculateTheoreticalRelativeStandardErrorML(int p) { - return Math.sqrt(VARIANCE_FACTOR_ML / (1 << p)); + protected strictfp double calculateTheoreticalRelativeStandardErrorML(int p) { + return StrictMath.sqrt(VARIANCE_FACTOR_ML / (1 << p)); } @Override - protected double calculateTheoreticalRelativeStandardErrorMartingale(int p) { - return Math.sqrt(VARIANCE_FACTOR_MARTINGALE / (1L << p)); + protected strictfp double calculateTheoreticalRelativeStandardErrorMartingale(int p) { + return StrictMath.sqrt(VARIANCE_FACTOR_MARTINGALE / (1L << p)); } @Override @@ -155,7 +151,7 @@ protected double getTheoreticalCompressedMemoryVarianceProduct() { // // for a numerical evaluation see // https://www.wolframalpha.com/input?i=%281%2F2+%2B+int_0%5E1+%281-z%29*ln%281-z%29%2Fln%28z%29+dz%29+%2F+%28ln%282%29+*+zeta%282%2C2%29%29 - return 3.0436599734226085615249901682841889998940943134541648920053615832; + return 3.0436599734226086; } @Override @@ -337,11 +333,9 @@ void testSigmaIterations() { } } - private static final double RELATIVE_ERROR = 1e-10; - - private double calculateEstimationFactor(int p) { + private strictfp double calculateEstimationFactor(int p) { double m = 1 << p; - return m * m / (2. * Math.log(2) * (1. + VARIANCE_FACTOR_RAW / m)); + return m * m / (2. * StrictMath.log(2) * (1. + VARIANCE_FACTOR_RAW / m)); } @Test @@ -350,9 +344,7 @@ void testEstimationFactorsForCorrectedRawEstimator() { for (int p = MIN_P; p <= MAX_P; ++p) { expectedEstimationFactors[p - MIN_P] = calculateEstimationFactor(p); } - assertThat(CorrectedRawEstimator.ESTIMATION_FACTORS) - .usingElementComparator(compareWithMaxRelativeError(RELATIVE_ERROR)) - .isEqualTo(expectedEstimationFactors); + assertThat(CorrectedRawEstimator.ESTIMATION_FACTORS).isEqualTo(expectedEstimationFactors); } @Test @@ -422,4 +414,9 @@ void testLargeDistinctCountEstimation() { 0.06, 0.04); } + + @Test + strictfp void testVarianceFactorML() { + assertThat(VARIANCE_FACTOR_ML).isEqualTo(6 * StrictMath.log(2.) / (Math.PI * Math.PI - 6)); + } } diff --git a/src/test/java/com/dynatrace/hash4j/distinctcount/UltraLogLogTest.java b/src/test/java/com/dynatrace/hash4j/distinctcount/UltraLogLogTest.java index 81f75d97..3579bb4c 100644 --- a/src/test/java/com/dynatrace/hash4j/distinctcount/UltraLogLogTest.java +++ b/src/test/java/com/dynatrace/hash4j/distinctcount/UltraLogLogTest.java @@ -16,9 +16,8 @@ package com.dynatrace.hash4j.distinctcount; import static com.dynatrace.hash4j.distinctcount.UltraLogLog.*; -import static com.dynatrace.hash4j.distinctcount.UltraLogLog.OptimalFGRAEstimator.ETA_0; +import static com.dynatrace.hash4j.distinctcount.UltraLogLog.OptimalFGRAEstimator.*; import static com.dynatrace.hash4j.testutils.TestUtils.compareWithMaxRelativeError; -import static java.lang.Math.*; import static java.lang.Math.sqrt; import static org.assertj.core.api.Assertions.*; @@ -37,43 +36,46 @@ class UltraLogLogTest extends DistinctCounterTest { // see https://www.wolframalpha.com/input?i=ln%282%29%2Fzeta%282%2C+5%2F4%29 - private static final double VARIANCE_FACTOR_ML = - 0.5789111356311075471022417636427943448393849646878849257018607764; + private static final double VARIANCE_FACTOR_ML = 0.5789111356311075; + + private static final double GAMMA_TAU = 1.1430292525408; + + private static final double GAMMA_TWO_TAU = 0.8984962499780026; @Test void testRelativeStandardErrorOfOptimalFGRAEstimatorAgainstConstants() { double[] expected = { - 0.276562187784647, - 0.19555899840231122, - 0.1382810938923235, - 0.09777949920115561, - 0.06914054694616174, - 0.048889749600577806, - 0.03457027347308087, - 0.024444874800288903, - 0.017285136736540436, - 0.012222437400144451, - 0.008642568368270218, - 0.006111218700072226, - 0.004321284184135109, - 0.003055609350036113, - 0.0021606420920675545, - 0.0015278046750180564, - 0.0010803210460337772, - 7.639023375090282E-4, - 5.401605230168886E-4, - 3.819511687545141E-4, - 2.700802615084443E-4, - 1.9097558437725705E-4, - 1.3504013075422215E-4, - 9.548779218862853E-5 + 0.2765621877846472, + 0.1955589984023114, + 0.1382810938923236, + 0.0977794992011557, + 0.0691405469461618, + 0.04888974960057785, + 0.0345702734730809, + 0.024444874800288924, + 0.01728513673654045, + 0.012222437400144462, + 0.008642568368270225, + 0.006111218700072231, + 0.004321284184135112, + 0.0030556093500361155, + 0.002160642092067556, + 0.0015278046750180577, + 0.001080321046033778, + 7.639023375090289E-4, + 5.40160523016889E-4, + 3.8195116875451443E-4, + 2.700802615084445E-4, + 1.9097558437725722E-4, + 1.3504013075422226E-4, + 9.548779218862861E-5 }; double[] actual = IntStream.range(MIN_P, MAX_P + 1) .mapToDouble(OptimalFGRAEstimator::calculateTheoreticalRelativeStandardError) .toArray(); assertThat(actual) - .usingElementComparator(compareWithMaxRelativeError(RELATIVE_ERROR)) + .usingElementComparator(compareWithMaxRelativeError(1e-15)) .isEqualTo(expected); } @@ -202,13 +204,13 @@ protected double calculateTheoreticalRelativeStandardErrorDefault(int p) { } @Override - protected double calculateTheoreticalRelativeStandardErrorML(int p) { - return Math.sqrt(VARIANCE_FACTOR_ML / (1 << p)); + protected strictfp double calculateTheoreticalRelativeStandardErrorML(int p) { + return StrictMath.sqrt(VARIANCE_FACTOR_ML / (1 << p)); } @Override - protected double calculateTheoreticalRelativeStandardErrorMartingale(int p) { - return Math.sqrt(Math.log(2.) * 5. / (8. * (1L << p))); + protected strictfp double calculateTheoreticalRelativeStandardErrorMartingale(int p) { + return StrictMath.sqrt(StrictMath.log(2.) * 5. / (8. * (1L << p))); } @Override @@ -394,56 +396,70 @@ void testLargeDistinctCountEstimation() { 0.03); } - private static double omega0(double tau) { - return pow(7, -tau) - pow(8, -tau); + private static strictfp double omega0(double tau) { + return StrictMath.pow(7, -tau) - StrictMath.pow(8, -tau); } - private static double omega1(double tau) { - return pow(3, -tau) - pow(4, -tau) - pow(7, -tau) + pow(8, -tau); + private static strictfp double omega1(double tau) { + return StrictMath.pow(3, -tau) + - StrictMath.pow(4, -tau) + - StrictMath.pow(7, -tau) + + StrictMath.pow(8, -tau); } - private static double omega2(double tau) { - return pow(5, -tau) - pow(6, -tau) - pow(7, -tau) + pow(8, -tau); + private static strictfp double omega2(double tau) { + return StrictMath.pow(5, -tau) + - StrictMath.pow(6, -tau) + - StrictMath.pow(7, -tau) + + StrictMath.pow(8, -tau); } - private static double omega3(double tau) { + private static strictfp double omega3(double tau) { return 1 - - pow(2, -tau) - - pow(3, -tau) - + pow(4, -tau) - - pow(5, -tau) - + pow(6, -tau) - + pow(7, -tau) - - pow(8, -tau); + - StrictMath.pow(2, -tau) + - StrictMath.pow(3, -tau) + + StrictMath.pow(4, -tau) + - StrictMath.pow(5, -tau) + + StrictMath.pow(6, -tau) + + StrictMath.pow(7, -tau) + - StrictMath.pow(8, -tau); } - private static double calculateEtaPreFactor(double tau) { - return (Math.log(2) / Gamma.gamma(tau)) - / (pow(omega0(tau), 2) / omega0(2 * tau) - + pow(omega1(tau), 2) / omega1(2 * tau) - + pow(omega2(tau), 2) / omega2(2 * tau) - + pow(omega3(tau), 2) / omega3(2 * tau)); + private static strictfp double calculateEtaPreFactor(double tau, double gammaTau) { + return (StrictMath.log(2) / gammaTau) + / (StrictMath.pow(omega0(tau), 2) / omega0(2 * tau) + + StrictMath.pow(omega1(tau), 2) / omega1(2 * tau) + + StrictMath.pow(omega2(tau), 2) / omega2(2 * tau) + + StrictMath.pow(omega3(tau), 2) / omega3(2 * tau)); } - private static double calculateEta0(double tau) { - return calculateEtaPreFactor(tau) * (omega0(tau) / omega0(2 * tau)); + private static strictfp double calculateEta0(double tau, double gammaTau) { + return calculateEtaPreFactor(tau, gammaTau) * (omega0(tau) / omega0(2 * tau)); } - private static double calculateEta1(double tau) { - return calculateEtaPreFactor(tau) * (omega1(tau) / omega1(2 * tau)); + private static strictfp double calculateEta1(double tau, double gammaTau) { + return calculateEtaPreFactor(tau, gammaTau) * (omega1(tau) / omega1(2 * tau)); } - private static double calculateEta2(double tau) { - return calculateEtaPreFactor(tau) * (omega2(tau) / omega2(2 * tau)); + private static strictfp double calculateEta2(double tau, double gammaTau) { + return calculateEtaPreFactor(tau, gammaTau) * (omega2(tau) / omega2(2 * tau)); } - private static double calculateEta3(double tau) { - return calculateEtaPreFactor(tau) * (omega3(tau) / omega3(2 * tau)); + private static strictfp double calculateEta3(double tau, double gammaTau) { + return calculateEtaPreFactor(tau, gammaTau) * (omega3(tau) / omega3(2 * tau)); } - private static double calculateVarianceFactor(double tau) { - return (calculateEtaPreFactor(tau) * (Gamma.gamma(2 * tau) / Gamma.gamma(tau)) - 1) - / pow(tau, 2); + private static strictfp double calculateVarianceFactor( + double tau, double gammaTau, double gammaTwoTau) { + return (calculateEtaPreFactor(tau, gammaTau) * (gammaTwoTau / gammaTau) - 1) // TODO + / StrictMath.pow(tau, 2); + } + + private static strictfp double calculateVarianceFactor(double tau) { + double gammaTau = Gamma.gamma(tau); + double gammaTwoTau = Gamma.gamma(2 * tau); + return (calculateEtaPreFactor(tau, gammaTau) * (gammaTwoTau / gammaTau) - 1) + / StrictMath.pow(tau, 2); } private double[] determineZTestValuesForPhi(int p) { @@ -585,7 +601,7 @@ private static int optimalFGRAEstimatorSigmaNumTermsUntilConvergence(double z) { double expectedResult = OptimalFGRAEstimator.sigma(z); if (z <= 0.) { - assertThat(OptimalFGRAEstimator.ETA_3).isEqualTo(expectedResult); + assertThat(ETA_3).isEqualTo(expectedResult); return numTerms; } if (z >= 1.) { @@ -657,36 +673,36 @@ void testOptimalFGRAEstimatorSigmaConvergence() { @Test void testOptimalFGRAEstimatorEta0() { assertThat(ETA_0) - .usingComparator(compareWithMaxRelativeError(RELATIVE_ERROR)) - .isEqualTo(calculateEta0(OptimalFGRAEstimator.TAU)); + .usingComparator(compareWithMaxRelativeError(1e-15)) + .isEqualTo(calculateEta0(OptimalFGRAEstimator.TAU, GAMMA_TAU)); } @Test void testOptimalFGRAEstimatorEta1() { - assertThat(OptimalFGRAEstimator.ETA_1) - .usingComparator(compareWithMaxRelativeError(RELATIVE_ERROR)) - .isEqualTo(calculateEta1(OptimalFGRAEstimator.TAU)); + assertThat(ETA_1) + .usingComparator(compareWithMaxRelativeError(1e-15)) + .isEqualTo(calculateEta1(OptimalFGRAEstimator.TAU, GAMMA_TAU)); } @Test void testOptimalFGRAEstimatorEta2() { - assertThat(OptimalFGRAEstimator.ETA_2) - .usingComparator(compareWithMaxRelativeError(RELATIVE_ERROR)) - .isEqualTo(calculateEta2(OptimalFGRAEstimator.TAU)); + assertThat(ETA_2) + .usingComparator(compareWithMaxRelativeError(1e-15)) + .isEqualTo(calculateEta2(OptimalFGRAEstimator.TAU, GAMMA_TAU)); } @Test void testOptimalFGRAEstimatorEta3() { - assertThat(OptimalFGRAEstimator.ETA_3) - .usingComparator(compareWithMaxRelativeError(RELATIVE_ERROR)) - .isEqualTo(calculateEta3(OptimalFGRAEstimator.TAU)); + assertThat(ETA_3) + .usingComparator(compareWithMaxRelativeError(1e-15)) + .isEqualTo(calculateEta3(OptimalFGRAEstimator.TAU, GAMMA_TAU)); } @Test void testOptimalFGRAEstimatorVarianceFactor() { assertThat(OptimalFGRAEstimator.V) - .usingComparator(compareWithMaxRelativeError(RELATIVE_ERROR)) - .isEqualTo(calculateVarianceFactor(OptimalFGRAEstimator.TAU)); + .usingComparator(compareWithMaxRelativeError(1e-15)) + .isEqualTo(calculateVarianceFactor(OptimalFGRAEstimator.TAU, GAMMA_TAU, GAMMA_TWO_TAU)); } @Test @@ -702,24 +718,24 @@ void testOptimalFGRAEstimatorTau() { double optimalTau = result.getPoint(); assertThat(OptimalFGRAEstimator.TAU) - .usingComparator(compareWithMaxRelativeError(RELATIVE_ERROR)) + .usingComparator(compareWithMaxRelativeError(1e-6)) .isEqualTo(optimalTau); } - private static double calculateOptimalFGRARegisterContribution(int r) { + private static strictfp double calculateOptimalFGRARegisterContribution(int r) { int q10 = r & 3; int q765432 = (r + 12) >>> 2; final double f; if (q10 == 0) { f = OptimalFGRAEstimator.ETA_0; } else if (q10 == 1) { - f = OptimalFGRAEstimator.ETA_1; + f = ETA_1; } else if (q10 == 2) { - f = OptimalFGRAEstimator.ETA_2; + f = ETA_2; } else { - f = OptimalFGRAEstimator.ETA_3; + f = ETA_3; } - return f * pow(2., -OptimalFGRAEstimator.TAU * q765432); + return f * StrictMath.pow(2., -OptimalFGRAEstimator.TAU * q765432); } @Test @@ -731,11 +747,11 @@ void testOptimalFGRAEstimatorRegisterContributions() { .toArray()); } - private static double calculateEstimationFactor(int p) { + private static strictfp double calculateEstimationFactor(int p) { int m = 1 << p; double biasCorrectionFactor = 1. / (1. + OptimalFGRAEstimator.V * (1. + OptimalFGRAEstimator.TAU) / (2. * m)); - return biasCorrectionFactor * m * Math.pow(m, 1. / OptimalFGRAEstimator.TAU); + return biasCorrectionFactor * m * StrictMath.pow(m, 1. / OptimalFGRAEstimator.TAU); } @Test @@ -816,4 +832,18 @@ void testScaledRegisterStateChangeProbability() { .isZero(); } } + + @Test + void testGammaTau() { + assertThat(GAMMA_TAU) + .usingComparator(compareWithMaxRelativeError(1e-9)) + .isEqualTo(Gamma.gamma(TAU)); + } + + @Test + void testGammaTwoTau() { + assertThat(GAMMA_TWO_TAU) + .usingComparator(compareWithMaxRelativeError(1e-9)) + .isEqualTo(Gamma.gamma(2 * TAU)); + } }