You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2021/08/09 16:05:28 UTC

[commons-rng] branch master updated (93b8e71 -> 02ae551)

This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/commons-rng.git.


    from 93b8e71  Sonar fix: Eliminate false-positive of commented-out code.
     new f36d736  Update ZigguratSampler tables.
     new 6b1b257  Add benchmark for ZigguratSamplers with integer look-up tables
     new 2300a7c  Combine conditions
     new dac561f  Add loop frequencies
     new e7494ad  Benchmark int map sampler in the sequential test
     new dc4370b  Add overhang frequencies
     new d8429b3  Add simple overhangs to sequential benchmark
     new 02ae551  Add more simple overhangs performance benchmarks

The 8 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../distribution/ZigguratSamplerPerformance.java   | 1721 +++++++++++++++-----
 .../rng/sampling/distribution/ZigguratSampler.java |  748 +++++----
 .../rng/sampling/distribution/LevySamplerTest.java |    8 +-
 .../sampling/distribution/StableSamplerTest.java   |   52 +-
 .../checkstyle/checkstyle-suppressions.xml         |    1 +
 5 files changed, 1771 insertions(+), 759 deletions(-)

[commons-rng] 01/08: Update ZigguratSampler tables.

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-rng.git

commit f36d7365b241483aee9bd2b3fffaea98c408c087
Author: aherbert <ah...@apache.org>
AuthorDate: Mon Aug 9 11:44:49 2021 +0100

    Update ZigguratSampler tables.
    
    These have been computed using the reference table generation script.
    
    Note: The script was modified to scale up/down using 2^63 in-place of 2^63-1. This matches the scaling performed during sampling.
---
 .../distribution/ZigguratSamplerPerformance.java   | 751 +++++++++++----------
 .../rng/sampling/distribution/ZigguratSampler.java | 736 ++++++++++----------
 .../rng/sampling/distribution/LevySamplerTest.java |   8 +-
 .../sampling/distribution/StableSamplerTest.java   |  52 +-
 4 files changed, 831 insertions(+), 716 deletions(-)

diff --git a/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java b/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java
index 3fc9e1c..6e407cf 100644
--- a/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java
+++ b/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java
@@ -736,20 +736,20 @@ public class ZigguratSamplerPerformance {
      * McFarland (2016) JSCS 86, 1281-1294</a>
      */
     static class ModifiedZigguratNormalizedGaussianSampler implements ContinuousSampler {
+        /** Mask to create an unsigned long from a signed long. */
+        protected static final long MAX_INT64 = 0x7fffffffffffffffL;
+        /** 2^63. */
+        protected static final double TWO_POW_63 = 0x1.0p63;
         /** Maximum i value for early exit. */
         protected static final int I_MAX = 253;
         /** The point where the Gaussian switches from convex to concave. */
         protected static final int J_INFLECTION = 205;
-        /** Mask to create an unsigned long from a signed long. */
-        protected static final long MAX_INT64 = 0x7fffffffffffffffL;
         /** Used for largest deviations of f(x) from y_i. This is negated on purpose. */
-        protected static final long MAX_IE = -2269182951627975918L;
+        protected static final long MAX_IE = -2269182951627976004L;
         /** Used for largest deviations of f(x) from y_i. */
-        protected static final long MIN_IE = 760463704284035181L;
-        /** 2^63. */
-        protected static final double TWO_POW_63 = 0x1.0p63;
+        protected static final long MIN_IE = 760463704284035184L;
         /** Beginning of tail. */
-        protected static final double X_0 = 3.6360066255;
+        protected static final double X_0 = 3.6360066255009455861;
         /** 1/X_0. */
         protected static final double ONE_OVER_X_0 = 1d / X_0;
 
@@ -768,177 +768,203 @@ public class ZigguratSamplerPerformance {
                 250, 250, 249, 249, 249, 248, 248, 248, 247, 247, 247, 246, 246, 245, 244, 244, 243, 242, 240, 2, 2, 3,
                 3, 0, 0, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 1, 0, 0});
         /** The alias inverse PMF. */
-        protected static final long[] IPMF = {9223372036854775807L, 1100243796532604147L, 7866600928978262881L,
-            6788754710654027089L, 9022865200181691852L, 6522434035205505475L, 4723064097359993915L,
-            3360495653216419673L, 2289663232373874393L, 1423968905551925104L, 708364817827802907L, 106102487305606492L,
-            -408333464665790208L, -853239722779020926L, -1242095211825517037L, -1585059631105792592L,
-            -1889943050287164616L, -2162852901990665326L, -2408637386594506662L, -2631196530262949902L,
-            -2833704942520918738L, -3018774289025815052L, -3188573753472182441L, -3344920681707440829L,
-            -3489349705062145773L, -3623166100042174483L, -3747487436868330185L, -3863276422712168700L,
-            -3971367044063122321L, -4072485557029853479L, -4167267476830907467L, -4256271432240150335L,
-            -4339990541927301065L, -4418861817133796561L, -4493273980372371289L, -4563574004462236379L,
-            -4630072609770443287L, -4693048910430993529L, -4752754358862853623L, -4809416110052798111L,
-            -4863239903586974371L, -4914412541515869230L, -4963104028439154501L, -5009469424769141876L,
-            -5053650458856546947L, -5095776932695070785L, -5135967952544950843L, -5174333008451188631L,
-            -5210972924952682065L, -5245980700100453012L, -5279442247516290042L, -5311437055462362013L,
-            -5342038772315636138L, -5371315728843324427L, -5399331404632497705L, -5426144845493682879L,
-            -5451811038474681565L, -5476381248265612057L, -5499903320558330825L, -5522421955752302985L,
-            -5543978956085246988L, -5564613449659052023L, -5584362093436129148L, -5603259257517445975L,
-            -5621337193070977432L, -5638626184974114133L, -5655154691220924683L, -5670949470294749069L,
-            -5686035697601828417L, -5700437072199142976L, -5714175914219797723L, -5727273255295211389L,
-            -5739748920272022600L, -5751621603810396917L, -5762908939773930926L, -5773627565914992314L,
-            -5783793183152402325L, -5793420610475612574L, -5802523835894645221L, -5811116062947594592L,
-            -5819209754516104281L, -5826816672854561136L, -5833947916825296227L, -5840613956570562553L,
-            -5846824665591787384L, -5852589350491064419L, -5857916778480708968L, -5862815203334817577L,
-            -5867292388935689664L, -5871355631762300668L, -5875011781262872391L, -5878267259039068099L,
-            -5881128076579864607L, -5883599852028866964L, -5885687825288587920L, -5887396872144944193L,
-            -5888731517955022366L, -5889695949247708370L, -5890294025706661862L, -5890529289910843690L,
-            -5890404977676009159L, -5889924026487152552L, -5889089083913561497L, -5887902514965187544L,
-            -5886366408898350160L, -5884482585690660648L, -5882252601321067956L, -5879677752995005083L,
-            -5876759083794187244L, -5873497386318817608L, -5869893206505495615L, -5865946846617000703L,
-            -5861658367354170141L, -5857027590486142268L, -5852054100063403979L, -5846737243971479915L,
-            -5841076134082348607L, -5835069647234555080L, -5828716424754558627L, -5822014871949050545L,
-            -5814963157357505615L, -5807559211080035948L, -5799800723447248431L, -5791685142338046612L,
-            -5783209670985131963L, -5774371264582507258L, -5765166627072198898L, -5755592207057629351L,
-            -5745644193442020886L, -5735318510777140130L, -5724610813433637581L, -5713516480385064197L,
-            -5702030608511931905L, -5690148005851000163L, -5677863184109376595L, -5665170350903283020L,
-            -5652063400924584736L, -5638535907000098559L, -5624581109999495711L, -5610191908627545348L,
-            -5595360848093635657L, -5580080108034221525L, -5564341489875517452L, -5548136403221361788L,
-            -5531455851545388194L, -5514290416638313566L, -5496630242181647032L, -5478465016761708394L,
-            -5459783954986630496L, -5440575777891763554L, -5420828692432362328L, -5400530368638759086L,
-            -5379667916699386572L, -5358227861294079939L, -5336196115274289941L, -5313557951078348351L,
-            -5290297970633413513L, -5266400072915204637L, -5241847420213976978L, -5216622401043707762L,
-            -5190706591719514516L, -5164080714589163015L, -5136724594099061292L, -5108617109269271995L,
-            -5079736143458208314L, -5050058530461699570L, -5019559997031867155L, -4988215101008300666L,
-            -4955997165600740840L, -4922878208651982466L, -4888828866780310778L, -4853818314258448763L,
-            -4817814175855136221L, -4780782432601640934L, -4742687321746673837L, -4703491227581398702L,
-            -4663154564978669839L, -4621635653358718847L, -4578890580370737438L, -4534873055659651863L,
-            -4489534251700544707L, -4442822631898778778L, -4394683764809052552L, -4345060121983309848L,
-            -4293890858708851568L, -4241111576153757717L, -4186654061692562932L, -4130446006804691432L,
-            -4072410698657642967L, -4012466683838341666L, -3950527400304957273L, -3886500774061817392L,
-            -3820288777467775968L, -3751786943594814089L, -3680883832433444937L, -3607460442623855428L,
-            -3531389562483238811L, -3452535052936037985L, -3370751053395794721L, -3285881101589156030L,
-            -3197757155301271700L, -3106198503156390075L, -3011010550911843739L, -2911983463883482375L,
-            -2808890647470171482L, -2701487041141041038L, -2589507199690499622L, -2472663129329060997L,
-            -2350641842139723534L, -2223102583769914387L, -2089673683729348624L, -1949948966045216354L,
-            -1803483646855866339L, -1649789631524907106L, -1488330106094837958L, -1318513295725471712L,
-            -1139685236971903433L, -951121376551959675L, -752016768184573709L, -541474585687415681L,
-            -318492605680814263L, -81947227248966622L, 169425512568350963L, 437052607277165029L, 722551297569085274L,
-            1027761939300002045L, 1354787941578333500L, 1706044619204253453L, 2084319374409947591L,
-            2492846399638817506L, 2935400169348911565L, 3416413484613541924L, 3941127949861028145L,
-            4515787798749165735L, 5147892401484995974L, 5846529325380992513L, 6622819682194933019L,
-            7490522659874903812L, 8466869998278641829L, 8216968526368126501L, 4550693915471153825L,
-            7628019504122306461L, 6605080500893076940L, 7121156327637209657L, 2484871780365768829L,
-            7179104797069433749L, 7066086283825115773L, 1516500120794063563L, 216305945442773460L, 6295963418513296140L,
-            2889316805672339623L, -2712587580543026574L, 6562498853519217374L, 7975754821145999232L,
-            -9223372036854775807L, -9223372036854775807L};
+        protected static final long[] IPMF = {9223372036854775408L, 1100243796534090797L, 7866600928998383022L,
+            6788754710675124691L, 9022865200181688296L, 6522434035205502164L, 4723064097360024697L,
+            3360495653216416088L, 2289663232373870755L, 1423968905551920455L, 708364817827797893L, 106102487305601162L,
+            -408333464665794443L, -853239722779025206L, -1242095211825521362L, -1585059631105762155L,
+            -1889943050287169086L, -2162852901990669843L, -2408637386594511193L, -2631196530262954448L,
+            -2833704942520925732L, -3018774289025787439L, -3188573753472222231L, -3344920681707410914L,
+            -3489349705062150768L, -3623166100042179544L, -3747487436868335278L, -3863276422712173808L,
+            -3971367044063130866L, -4072485557029823980L, -4167267476830916554L, -4256271432240159761L,
+            -4339990541927306746L, -4418861817133802326L, -4493273980372377053L, -4563574004462246636L,
+            -4630072609770453867L, -4693048910430964891L, -4752754358862894738L, -4809416110052769505L,
+            -4863239903586985866L, -4914412541515875772L, -4963104028439161008L, -5009469424769119174L,
+            -5053650458856559461L, -5095776932695077750L, -5135967952544929007L, -5174333008451230625L,
+            -5210972924952654441L, -5245980700100460247L, -5279442247516297345L, -5311437055462369316L,
+            -5342038772315650555L, -5371315728843297107L, -5399331404632512666L, -5426144845448965104L,
+            -5451811038519422589L, -5476381248265593008L, -5499903320558339045L, -5522421955752311307L,
+            -5543978956085263616L, -5564613449659060480L, -5584362093436146354L, -5603259257517428627L,
+            -5621337193070986365L, -5638626184974132325L, -5655154691220933854L, -5670949470294763073L,
+            -5686035697601807766L, -5700437072199152453L, -5714175914219812272L, -5727273255295221103L,
+            -5739748920271997489L, -5751621603810411941L, -5762908939773946223L, -5773627565915007849L,
+            -5783793183152377622L, -5793420610475628449L, -5802523835894661300L, -5811116062947570228L,
+            -5819209754516120768L, -5826816672854571802L, -5833947916825278195L, -5840613956570608249L,
+            -5846824665591763395L, -5852589350491075357L, -5857916778480726477L, -5862815203334800430L,
+            -5867292388935742441L, -5871355631762283997L, -5875011781262890819L, -5878267259039093710L,
+            -5881128076579883546L, -5883599852028851382L, -5885687825288565257L, -5887396872144963778L,
+            -5888731517955042223L, -5889695949247728499L, -5890294025706689822L, -5890529289910829504L,
+            -5890404977675987449L, -5889924026487208528L, -5889089083913555992L, -5887902514965209240L,
+            -5886366408898372127L, -5884482585690639756L, -5882252601321090366L, -5879677752995027766L,
+            -5876759083794175305L, -5873497386318840733L, -5869893206505510263L, -5865946846617024340L,
+            -5861658367354159190L, -5857027590486131555L, -5852054100063428398L, -5846737243971504641L,
+            -5841076134082373571L, -5835069647234580384L, -5828716424754549310L, -5822014871949021959L,
+            -5814963157357531601L, -5807559211080072146L, -5799800723447230025L, -5791685142338073347L,
+            -5783209670985158971L, -5774371264582489329L, -5765166627072226519L, -5755592207057667866L,
+            -5745644193442049188L, -5735318510777133844L, -5724610813433666496L, -5713516480340333005L,
+            -5702030608556698118L, -5690148005851018661L, -5677863184109371808L, -5665170350903313433L,
+            -5652063400924580562L, -5638535907000141432L, -5624581109999480439L, -5610191908627599865L,
+            -5595360848093632709L, -5580080108034218849L, -5564341489875550045L, -5548136403221394654L,
+            -5531455851545399204L, -5514290416593586870L, -5496630242226406575L, -5478465016761742826L,
+            -5459783954986665201L, -5440575777891777017L, -5420828692432397919L, -5400530368638773571L,
+            -5379667916699401670L, -5358227861294116825L, -5336196115274292307L, -5313557951078385986L,
+            -5290297970633451489L, -5266400072915222391L, -5241847420214015772L, -5216622401043726607L,
+            -5190706591719533973L, -5164080714589203240L, -5136724594099067134L, -5108617109269313037L,
+            -5079736143458214973L, -5050058530461741430L, -5019559997031891994L, -4988215100963583032L,
+            -4955997165645492083L, -4922878208652041825L, -4888828866780320026L, -4853818314258475851L,
+            -4817814175855179990L, -4780782432601701861L, -4742687321746719241L, -4703491227581444720L,
+            -4663154564978699244L, -4621635653358766431L, -4578890580370785840L, -4534873055659683516L,
+            -4489534251700611902L, -4442822631898829564L, -4394683764809104088L, -4345060121983362610L,
+            -4293890858708922851L, -4241111576153830158L, -4186654061692619033L, -4130446006804747670L,
+            -4072410698657718678L, -4012466683838401105L, -3950527400305017938L, -3886500774061896578L,
+            -3820288777467837180L, -3751786943594897634L, -3680883832433527802L, -3607460442623922090L,
+            -3531389562483324266L, -3452535052891361699L, -3370751053395887939L, -3285881101633968096L,
+            -3197757155301365465L, -3106198503156485339L, -3011010550911937371L, -2911983463883581047L,
+            -2808890647470271789L, -2701487041141150061L, -2589507199690603472L, -2472663129329160218L,
+            -2350641842139870417L, -2223102583770035263L, -2089673683684728595L, -1949948966090106873L,
+            -1803483646855993757L, -1649789631480328207L, -1488330106139747683L, -1318513295725618200L,
+            -1139685236927327128L, -951121376596854700L, -752016768184775899L, -541474585642866346L,
+            -318492605725778472L, -81947227249193332L, 169425512612864612L, 437052607232193594L, 722551297568810077L,
+            1027761939299714316L, 1354787941622770469L, 1706044619203941749L, 2084319374409574060L,
+            2492846399593711370L, 2935400169348532576L, 3416413484613111455L, 3941127949860576155L,
+            4515787798793437894L, 5147892401439714413L, 5846529325380405959L, 6622819682216655291L,
+            7490522659874166085L, 8466869998277892108L, 8216968526387345482L, 4550693915488934669L,
+            7628019504138977223L, 6605080500908005863L, 7121156327650272532L, 2484871780331574356L,
+            7179104797032803433L, 7066086283830045340L, 1516500120817362978L, 216305945438803570L, 6295963418525324512L,
+            2889316805630113239L, -2712587580533804137L, 6562498853538167124L, 7975754821147501243L,
+            -9223372036854775808L, -9223372036854775808L};
         /**
          * The precomputed ziggurat lengths, denoted X_i in the main text. X_i = length of
          * ziggurat layer i.
          */
-        protected static final double[] X = {3.94216628254e-19, 3.72049450041e-19, 3.58270244806e-19, 3.48074762365e-19,
-            3.39901771719e-19, 3.33037783603e-19, 3.27094388176e-19, 3.21835771325e-19, 3.17107585418e-19,
-            3.1280307407e-19, 3.08845206558e-19, 3.05176506241e-19, 3.01752902926e-19, 2.98539834407e-19,
-            2.95509674628e-19, 2.92639979885e-19, 2.899122587e-19, 2.87311087802e-19, 2.84823463271e-19,
-            2.82438315352e-19, 2.80146139647e-19, 2.77938712618e-19, 2.75808869214e-19, 2.73750326983e-19,
-            2.71757545434e-19, 2.69825612475e-19, 2.67950151888e-19, 2.66127247304e-19, 2.6435337928e-19,
-            2.6262537282e-19, 2.60940353352e-19, 2.59295709543e-19, 2.57689061732e-19, 2.56118234977e-19,
-            2.54581235934e-19, 2.53076232924e-19, 2.51601538678e-19, 2.50155595336e-19, 2.48736961354e-19,
-            2.47344300031e-19, 2.45976369429e-19, 2.44632013479e-19, 2.43310154111e-19, 2.42009784271e-19,
-            2.40729961704e-19, 2.39469803409e-19, 2.38228480673e-19, 2.37005214619e-19, 2.35799272207e-19,
-            2.34609962621e-19, 2.33436634011e-19, 2.32278670547e-19, 2.31135489743e-19, 2.30006540027e-19,
-            2.28891298528e-19, 2.27789269059e-19, 2.26699980275e-19, 2.25622983985e-19, 2.24557853607e-19,
-            2.23504182749e-19, 2.22461583905e-19, 2.21429687253e-19, 2.20408139549e-19, 2.19396603103e-19,
-            2.18394754837e-19, 2.17402285409e-19, 2.164188984e-19, 2.15444309566e-19, 2.14478246135e-19,
-            2.13520446164e-19, 2.12570657924e-19, 2.11628639347e-19, 2.10694157491e-19, 2.09766988055e-19,
-            2.08846914916e-19, 2.079337297e-19, 2.0702723138e-19, 2.06127225897e-19, 2.05233525809e-19,
-            2.04345949953e-19, 2.03464323137e-19, 2.02588475842e-19, 2.01718243948e-19, 2.00853468469e-19,
-            1.99993995309e-19, 1.9913967503e-19, 1.9829036263e-19, 1.97445917335e-19, 1.96606202405e-19,
-            1.95771084943e-19, 1.94940435722e-19, 1.9411412902e-19, 1.93292042452e-19, 1.92474056827e-19,
-            1.91660056003e-19, 1.90849926746e-19, 1.90043558606e-19, 1.89240843788e-19, 1.88441677035e-19,
-            1.87645955517e-19, 1.86853578721e-19, 1.8606444835e-19, 1.85278468221e-19, 1.84495544175e-19,
-            1.83715583984e-19, 1.82938497262e-19, 1.82164195388e-19, 1.81392591419e-19, 1.80623600019e-19,
-            1.7985713738e-19, 1.79093121154e-19, 1.78331470384e-19, 1.77572105435e-19, 1.76814947933e-19,
-            1.76059920701e-19, 1.753069477e-19, 1.74555953971e-19, 1.73806865576e-19, 1.73059609547e-19,
-            1.72314113829e-19, 1.71570307233e-19, 1.70828119379e-19, 1.7008748065e-19, 1.69348322146e-19,
-            1.68610575631e-19, 1.67874173493e-19, 1.67139048692e-19, 1.66405134721e-19, 1.6567236556e-19,
-            1.64940675631e-19, 1.64209999755e-19, 1.63480273116e-19, 1.62751431209e-19, 1.62023409806e-19,
-            1.61296144913e-19, 1.60569572726e-19, 1.59843629593e-19, 1.59118251972e-19, 1.58393376391e-19,
-            1.57668939404e-19, 1.56944877552e-19, 1.56221127324e-19, 1.55497625108e-19, 1.54774307158e-19,
-            1.54051109542e-19, 1.53327968107e-19, 1.52604818431e-19, 1.51881595777e-19, 1.51158235054e-19,
-            1.50434670764e-19, 1.49710836959e-19, 1.48986667191e-19, 1.48262094465e-19, 1.47537051186e-19,
-            1.46811469107e-19, 1.46085279278e-19, 1.4535841199e-19, 1.44630796717e-19, 1.43902362058e-19,
-            1.43173035676e-19, 1.42442744238e-19, 1.41711413344e-19, 1.40978967466e-19, 1.40245329873e-19,
-            1.39510422558e-19, 1.38774166165e-19, 1.38036479905e-19, 1.37297281475e-19, 1.36556486972e-19,
-            1.35814010798e-19, 1.35069765568e-19, 1.34323662007e-19, 1.33575608847e-19, 1.32825512715e-19,
-            1.32073278015e-19, 1.31318806805e-19, 1.30561998669e-19, 1.29802750579e-19, 1.29040956749e-19,
-            1.28276508483e-19, 1.2750929401e-19, 1.26739198313e-19, 1.25966102948e-19, 1.25189885844e-19,
-            1.24410421101e-19, 1.23627578765e-19, 1.22841224598e-19, 1.2205121982e-19, 1.21257420848e-19,
-            1.20459679002e-19, 1.19657840201e-19, 1.18851744634e-19, 1.18041226403e-19, 1.17226113142e-19,
-            1.16406225609e-19, 1.15581377245e-19, 1.14751373693e-19, 1.13916012285e-19, 1.13075081485e-19,
-            1.12228360281e-19, 1.11375617531e-19, 1.10516611251e-19, 1.09651087832e-19, 1.08778781199e-19,
-            1.07899411881e-19, 1.07012685997e-19, 1.06118294148e-19, 1.05215910191e-19, 1.043051899e-19,
-            1.0338576948e-19, 1.02457263929e-19, 1.01519265222e-19, 1.00571340295e-19, 9.96130287997e-20,
-            9.86438405995e-20, 9.76632529648e-20, 9.66707074276e-20, 9.56656062409e-20, 9.46473083804e-20,
-            9.36151250173e-20, 9.25683143709e-20, 9.15060758376e-20, 9.04275432677e-20, 8.93317772338e-20,
-            8.82177561023e-20, 8.70843656749e-20, 8.59303871096e-20, 8.47544827642e-20, 8.35551795085e-20,
-            8.23308489336e-20, 8.10796837291e-20, 7.97996692841e-20, 7.84885492861e-20, 7.71437837009e-20,
-            7.57624969795e-20, 7.43414135785e-20, 7.28767768074e-20, 7.13642454435e-20, 6.97987602408e-20,
-            6.81743689448e-20, 6.64839929862e-20, 6.47191103452e-20, 6.28693148131e-20, 6.09216875483e-20,
-            5.88598735756e-20, 5.66626751161e-20, 5.43018136309e-20, 5.17381717445e-20, 4.89150317224e-20,
-            4.57447418908e-20, 4.20788025686e-20, 3.76259867224e-20, 3.16285898059e-20, 0.0};
+        protected static final double[] X = {3.9421662825398133E-19, 3.720494500411901E-19, 3.582702448062868E-19,
+            3.480747623654025E-19, 3.3990177171882136E-19, 3.330377836034014E-19, 3.270943881761755E-19,
+            3.21835771324951E-19, 3.171075854184043E-19, 3.1280307407034065E-19, 3.088452065580402E-19,
+            3.051765062410735E-19, 3.01752902925846E-19, 2.985398344070532E-19, 2.9550967462801797E-19,
+            2.9263997988491663E-19, 2.8991225869977476E-19, 2.873110878022629E-19, 2.8482346327101335E-19,
+            2.824383153519439E-19, 2.801461396472703E-19, 2.7793871261807797E-19, 2.758088692141121E-19,
+            2.737503269830876E-19, 2.7175754543391047E-19, 2.6982561247538484E-19, 2.6795015188771505E-19,
+            2.6612724730440033E-19, 2.6435337927976633E-19, 2.626253728202844E-19, 2.609403533522414E-19,
+            2.5929570954331E-19, 2.5768906173214726E-19, 2.561182349771961E-19, 2.545812359339336E-19,
+            2.530762329237246E-19, 2.51601538677984E-19, 2.501555953364619E-19, 2.487369613540316E-19,
+            2.4734430003079206E-19, 2.4597636942892726E-19, 2.446320134791245E-19, 2.4331015411139206E-19,
+            2.4200978427132955E-19, 2.407299617044588E-19, 2.3946980340903347E-19, 2.3822848067252674E-19,
+            2.37005214619318E-19, 2.357992722074133E-19, 2.346099626206997E-19, 2.3343663401054455E-19,
+            2.322786705467384E-19, 2.3113548974303765E-19, 2.300065400270424E-19, 2.2889129852797606E-19,
+            2.2778926905921897E-19, 2.266999802752732E-19, 2.2562298398527416E-19, 2.245578536072726E-19,
+            2.235041827493391E-19, 2.2246158390513294E-19, 2.214296872529625E-19, 2.2040813954857555E-19,
+            2.19396603102976E-19, 2.183947548374962E-19, 2.1740228540916853E-19, 2.164188984001652E-19,
+            2.1544430956570613E-19, 2.1447824613540345E-19, 2.1352044616350571E-19, 2.1257065792395107E-19,
+            2.1162863934653125E-19, 2.1069415749082026E-19, 2.0976698805483467E-19, 2.0884691491567363E-19,
+            2.0793372969963634E-19, 2.0702723137954107E-19, 2.061272258971713E-19, 2.0523352580895635E-19,
+            2.0434594995315797E-19, 2.0346432313698148E-19, 2.0258847584216418E-19, 2.0171824394771313E-19,
+            2.008534684685753E-19, 1.9999399530912015E-19, 1.9913967503040585E-19, 1.9829036263028144E-19,
+            1.9744591733545175E-19, 1.9660620240469857E-19, 1.9577108494251485E-19, 1.9494043572246307E-19,
+            1.941141290196216E-19, 1.9329204245152935E-19, 1.9247405682708168E-19, 1.9166005600287074E-19,
+            1.9084992674649826E-19, 1.900435586064234E-19, 1.8924084378793725E-19, 1.8844167703488436E-19,
+            1.8764595551677749E-19, 1.868535787209745E-19, 1.8606444834960934E-19, 1.8527846822098793E-19,
+            1.8449554417517928E-19, 1.8371558398354868E-19, 1.8293849726199566E-19, 1.8216419538767393E-19,
+            1.8139259141898448E-19, 1.8062360001864453E-19, 1.7985713737964743E-19, 1.7909312115393845E-19,
+            1.78331470383642E-19, 1.7757210543468428E-19, 1.7681494793266395E-19, 1.760599207008314E-19,
+            1.753069477000441E-19, 1.7455595397057217E-19, 1.7380686557563475E-19, 1.7305960954655264E-19,
+            1.7231411382940904E-19, 1.7157030723311378E-19, 1.7082811937877138E-19, 1.7008748065025788E-19,
+            1.6934832214591352E-19, 1.686105756312635E-19, 1.6787417349268046E-19, 1.6713904869190636E-19,
+            1.6640513472135291E-19, 1.6567236556010242E-19, 1.6494067563053266E-19, 1.6420999975549115E-19,
+            1.6348027311594532E-19, 1.627514312090366E-19, 1.6202340980646725E-19, 1.6129614491314931E-19,
+            1.605695727260459E-19, 1.598436295931348E-19, 1.591182519724249E-19, 1.5839337639095554E-19,
+            1.57668939403708E-19, 1.569448775523589E-19, 1.562211273238026E-19, 1.554976251083707E-19,
+            1.547743071576727E-19, 1.540511095419833E-19, 1.5332796810709688E-19, 1.5260481843056974E-19,
+            1.5188159577726683E-19, 1.5115823505412761E-19, 1.5043467076406199E-19, 1.4971083695888395E-19,
+            1.4898666719118714E-19, 1.4826209446506113E-19, 1.4753705118554365E-19, 1.468114691066983E-19,
+            1.4608527927820112E-19, 1.453584119903145E-19, 1.4463079671711862E-19, 1.4390236205786415E-19,
+            1.4317303567630177E-19, 1.4244274423783481E-19, 1.4171141334433217E-19, 1.4097896746642792E-19,
+            1.4024532987312287E-19, 1.3951042255849034E-19, 1.3877416616527576E-19, 1.3803647990516385E-19,
+            1.3729728147547174E-19, 1.3655648697200824E-19, 1.3581401079782068E-19, 1.35069765567529E-19,
+            1.3432366200692418E-19, 1.3357560884748263E-19, 1.3282551271542047E-19, 1.3207327801488087E-19,
+            1.3131880680481524E-19, 1.3056199866908076E-19, 1.2980275057923788E-19, 1.2904095674948608E-19,
+            1.2827650848312727E-19, 1.2750929400989213E-19, 1.2673919831340482E-19, 1.2596610294799512E-19,
+            1.2518988584399374E-19, 1.2441042110056523E-19, 1.2362757876504165E-19, 1.2284122459762072E-19,
+            1.2205121982017852E-19, 1.2125742084782245E-19, 1.2045967900166973E-19, 1.196578402011802E-19,
+            1.1885174463419555E-19, 1.180412264026409E-19, 1.1722611314162064E-19, 1.164062256093911E-19,
+            1.1558137724540874E-19, 1.1475137369333185E-19, 1.1391601228549047E-19, 1.1307508148492592E-19,
+            1.1222836028063025E-19, 1.1137561753107903E-19, 1.1051661125053526E-19, 1.0965108783189755E-19,
+            1.0877878119905372E-19, 1.0789941188076655E-19, 1.070126859970364E-19, 1.0611829414763286E-19,
+            1.0521591019102928E-19, 1.0430518990027552E-19, 1.0338576948035472E-19, 1.0245726392923699E-19,
+            1.015192652220931E-19, 1.0057134029488235E-19, 9.961302879967281E-20, 9.864384059945991E-20,
+            9.766325296475582E-20, 9.667070742762345E-20, 9.566560624086667E-20, 9.464730838043321E-20,
+            9.361512501732351E-20, 9.256831437088728E-20, 9.150607583763877E-20, 9.042754326772572E-20,
+            8.933177723376368E-20, 8.821775610232788E-20, 8.708436567489232E-20, 8.593038710961216E-20,
+            8.475448276424435E-20, 8.355517950846234E-20, 8.233084893358536E-20, 8.107968372912985E-20,
+            7.979966928413386E-20, 7.848854928607274E-20, 7.714378370093469E-20, 7.576249697946757E-20,
+            7.434141357848533E-20, 7.287677680737843E-20, 7.136424544352537E-20, 6.979876024076107E-20,
+            6.817436894479905E-20, 6.648399298619854E-20, 6.471911034516277E-20, 6.28693148131037E-20,
+            6.092168754828126E-20, 5.885987357557682E-20, 5.666267511609098E-20, 5.430181363089457E-20,
+            5.173817174449422E-20, 4.8915031722398545E-20, 4.57447418907553E-20, 4.2078802568583416E-20,
+            3.762598672240476E-20, 3.162858980588188E-20, 0.0};
         /** Overhang table. Y_i = f(X_i). */
-        protected static final double[] Y = {1.45984107966e-22, 3.00666134279e-22, 4.61297288151e-22, 6.26633500492e-22,
-            7.95945247619e-22, 9.68746550217e-22, 1.14468770024e-21, 1.32350363044e-21, 1.50498576921e-21,
-            1.68896530007e-21, 1.87530253827e-21, 2.06387984237e-21, 2.25459669136e-21, 2.44736615188e-21,
-            2.64211227278e-21, 2.83876811879e-21, 3.03727425675e-21, 3.23757757e-21, 3.43963031579e-21,
-            3.6433893658e-21, 3.84881558689e-21, 4.05587333095e-21, 4.26453001043e-21, 4.47475574223e-21,
-            4.68652304654e-21, 4.89980659028e-21, 5.11458296721e-21, 5.3308305082e-21, 5.5485291167e-21,
-            5.76766012527e-21, 5.98820616992e-21, 6.21015107954e-21, 6.43347977823e-21, 6.65817819857e-21,
-            6.88423320459e-21, 7.1116325228e-21, 7.34036468049e-21, 7.57041895029e-21, 7.80178530014e-21,
-            8.03445434816e-21, 8.26841732173e-21, 8.50366602039e-21, 8.74019278201e-21, 8.97799045203e-21,
-            9.21705235531e-21, 9.45737227039e-21, 9.69894440593e-21, 9.94176337898e-21, 1.01858241951e-20,
-            1.04311222301e-20, 1.0677653213e-20, 1.09254132104e-20, 1.11743986124e-20, 1.14246061187e-20,
-            1.16760327269e-20, 1.19286757204e-20, 1.21825326583e-20, 1.24376013654e-20, 1.2693879923e-20,
-            1.29513666605e-20, 1.32100601473e-20, 1.34699591858e-20, 1.37310628045e-20, 1.39933702514e-20,
-            1.42568809885e-20, 1.4521594686e-20, 1.47875112175e-20, 1.50546306552e-20, 1.53229532653e-20,
-            1.55924795044e-20, 1.58632100153e-20, 1.61351456238e-20, 1.64082873355e-20, 1.66826363327e-20,
-            1.69581939719e-20, 1.72349617811e-20, 1.75129414576e-20, 1.77921348663e-20, 1.80725440373e-20,
-            1.83541711644e-20, 1.86370186038e-20, 1.89210888728e-20, 1.92063846482e-20, 1.94929087658e-20,
-            1.97806642193e-20, 2.00696541597e-20, 2.03598818948e-20, 2.06513508884e-20, 2.09440647607e-20,
-            2.12380272876e-20, 2.15332424009e-20, 2.18297141884e-20, 2.21274468943e-20, 2.24264449191e-20,
-            2.27267128206e-20, 2.30282553143e-20, 2.33310772738e-20, 2.36351837324e-20, 2.39405798832e-20,
-            2.42472710808e-20, 2.45552628422e-20, 2.48645608479e-20, 2.5175170944e-20, 2.54870991431e-20,
-            2.58003516259e-20, 2.61149347436e-20, 2.64308550193e-20, 2.67481191499e-20, 2.70667340088e-20,
-            2.73867066474e-20, 2.77080442982e-20, 2.80307543767e-20, 2.83548444847e-20, 2.86803224123e-20,
-            2.90071961414e-20, 2.93354738484e-20, 2.96651639078e-20, 2.99962748948e-20, 3.03288155897e-20,
-            3.06627949809e-20, 3.09982222687e-20, 3.13351068696e-20, 3.16734584202e-20, 3.20132867816e-20,
-            3.23546020438e-20, 3.26974145302e-20, 3.30417348029e-20, 3.33875736673e-20, 3.37349421775e-20,
-            3.40838516421e-20, 3.44343136293e-20, 3.4786339973e-20, 3.51399427794e-20, 3.54951344328e-20,
-            3.58519276026e-20, 3.62103352501e-20, 3.65703706358e-20, 3.69320473266e-20, 3.7295379204e-20,
-            3.76603804721e-20, 3.80270656658e-20, 3.83954496597e-20, 3.87655476775e-20, 3.91373753011e-20,
-            3.95109484807e-20, 3.98862835454e-20, 4.02633972133e-20, 4.06423066034e-20, 4.10230292468e-20,
-            4.14055830991e-20, 4.1789986553e-20, 4.21762584518e-20, 4.25644181026e-20, 4.29544852916e-20,
-            4.33464802983e-20, 4.3740423912e-20, 4.41363374476e-20, 4.45342427632e-20, 4.49341622781e-20,
-            4.53361189911e-20, 4.5740136501e-20, 4.61462390263e-20, 4.65544514274e-20, 4.69647992292e-20,
-            4.73773086444e-20, 4.77920065987e-20, 4.82089207569e-20, 4.86280795501e-20, 4.90495122048e-20,
-            4.94732487728e-20, 4.98993201633e-20, 5.03277581761e-20, 5.07585955372e-20, 5.11918659356e-20,
-            5.16276040629e-20, 5.20658456539e-20, 5.25066275307e-20, 5.29499876488e-20, 5.33959651452e-20,
-            5.38446003902e-20, 5.42959350421e-20, 5.47500121042e-20, 5.52068759864e-20, 5.566657257e-20,
-            5.61291492763e-20, 5.65946551399e-20, 5.70631408865e-20, 5.75346590156e-20, 5.80092638886e-20,
-            5.8487011823e-20, 5.89679611927e-20, 5.94521725351e-20, 5.99397086661e-20, 6.04306348026e-20,
-            6.09250186942e-20, 6.14229307644e-20, 6.19244442624e-20, 6.24296354262e-20, 6.29385836583e-20,
-            6.34513717154e-20, 6.39680859128e-20, 6.44888163458e-20, 6.5013657129e-20, 6.55427066567e-20,
-            6.60760678847e-20, 6.66138486374e-20, 6.71561619424e-20, 6.7703126396e-20, 6.82548665622e-20,
-            6.88115134113e-20, 6.93732047997e-20, 6.9940085999e-20, 7.05123102793e-20, 7.10900395534e-20,
-            7.16734450906e-20, 7.22627083097e-20, 7.28580216611e-20, 7.3459589613e-20, 7.4067629755e-20,
-            7.46823740371e-20, 7.53040701672e-20, 7.59329831907e-20, 7.65693972825e-20, 7.72136177895e-20,
-            7.78659735664e-20, 7.85268196595e-20, 7.91965404039e-20, 7.9875553017e-20, 8.05643117889e-20,
-            8.12633129964e-20, 8.19731007037e-20, 8.26942736526e-20, 8.34274935088e-20, 8.41734948075e-20,
-            8.49330970528e-20, 8.57072195782e-20, 8.64968999859e-20, 8.73033172957e-20, 8.81278213789e-20,
-            8.89719709282e-20, 8.98375832393e-20, 9.07268006979e-20, 9.16421814841e-20, 9.25868264067e-20,
-            9.35645614803e-20, 9.45802100126e-20, 9.56400155509e-20, 9.67523347705e-20, 9.79288516978e-20,
-            9.91869058575e-20, 1.00554562713e-19, 1.02084073773e-19, 1.03903609932e-19, 1.08420217249e-19};
+        protected static final double[] Y = {1.4598410796619063E-22, 3.0066613427942797E-22, 4.612972881510347E-22,
+            6.266335004923436E-22, 7.959452476188154E-22, 9.687465502170504E-22, 1.144687700237944E-21,
+            1.3235036304379167E-21, 1.504985769205313E-21, 1.6889653000719298E-21, 1.8753025382711626E-21,
+            2.063879842369519E-21, 2.2545966913644708E-21, 2.44736615188018E-21, 2.6421122727763533E-21,
+            2.8387681187879908E-21, 3.0372742567457284E-21, 3.237577569998659E-21, 3.439630315794878E-21,
+            3.64338936579978E-21, 3.848815586891231E-21, 4.0558733309492775E-21, 4.264530010428359E-21,
+            4.474755742230507E-21, 4.686523046535558E-21, 4.899806590277526E-21, 5.114582967210549E-21,
+            5.330830508204617E-21, 5.548529116703176E-21, 5.767660125269048E-21, 5.988206169917846E-21,
+            6.210151079544222E-21, 6.433479778225721E-21, 6.65817819857139E-21, 6.884233204589318E-21,
+            7.11163252279571E-21, 7.340364680490309E-21, 7.570418950288642E-21, 7.801785300137974E-21,
+            8.034454348157002E-21, 8.268417321733312E-21, 8.503666020391502E-21, 8.740192782010952E-21,
+            8.97799045202819E-21, 9.217052355306144E-21, 9.457372270392882E-21, 9.698944405926943E-21,
+            9.941763378975842E-21, 1.0185824195119818E-20, 1.043112223011477E-20, 1.0677653212987396E-20,
+            1.0925413210432004E-20, 1.1174398612392891E-20, 1.1424606118728715E-20, 1.1676032726866302E-20,
+            1.1928675720361027E-20, 1.2182532658289373E-20, 1.2437601365406785E-20, 1.2693879923010674E-20,
+            1.2951366660454145E-20, 1.321006014726146E-20, 1.3469959185800733E-20, 1.3731062804473644E-20,
+            1.3993370251385596E-20, 1.4256880988463136E-20, 1.452159468598837E-20, 1.4787511217522902E-20,
+            1.505463065519617E-20, 1.5322953265335218E-20, 1.5592479504415048E-20, 1.5863210015310328E-20,
+            1.6135145623830982E-20, 1.6408287335525592E-20, 1.6682636332737932E-20, 1.6958193971903124E-20,
+            1.7234961781071113E-20, 1.7512941457646084E-20, 1.7792134866331487E-20, 1.807254403727107E-20,
+            1.8354171164377277E-20, 1.8637018603838945E-20, 1.8921088872801004E-20, 1.9206384648209468E-20,
+            1.9492908765815636E-20, 1.9780664219333857E-20, 2.006965415974784E-20, 2.035988189476086E-20,
+            2.0651350888385696E-20, 2.094406476067054E-20, 2.1238027287557466E-20, 2.1533242400870487E-20,
+            2.1829714188430474E-20, 2.2127446894294597E-20, 2.242644491911827E-20, 2.2726712820637798E-20,
+            2.3028255314272276E-20, 2.3331077273843558E-20, 2.3635183732413286E-20, 2.3940579883236352E-20,
+            2.4247271080830277E-20, 2.455526284216033E-20, 2.4864560847940368E-20, 2.5175170944049622E-20,
+            2.548709914306593E-20, 2.5800351625915997E-20, 2.6114934743643687E-20, 2.6430855019297323E-20,
+            2.674811914993741E-20, 2.7066734008766247E-20, 2.7386706647381193E-20, 2.770804429815356E-20,
+            2.803075437673527E-20, 2.835484448469575E-20, 2.868032241229163E-20, 2.9007196141372126E-20,
+            2.933547384842322E-20, 2.966516390775399E-20, 2.9996274894828624E-20, 3.0328815589748056E-20,
+            3.066279498088529E-20, 3.099822226867876E-20, 3.133510686958861E-20, 3.167345842022056E-20,
+            3.201328678162299E-20, 3.235460204376261E-20, 3.2697414530184806E-20, 3.304173480286495E-20,
+            3.338757366725735E-20, 3.373494217754894E-20, 3.408385164212521E-20, 3.443431362925624E-20,
+            3.4786339973011376E-20, 3.5139942779411164E-20, 3.549513443282617E-20, 3.585192760263246E-20,
+            3.621033525013417E-20, 3.6570370635764384E-20, 3.693204732657588E-20, 3.729537920403425E-20,
+            3.76603804721264E-20, 3.8027065665798284E-20, 3.839544965973665E-20, 3.876554767751017E-20,
+            3.9137375301086406E-20, 3.951094848074217E-20, 3.988628354538543E-20, 4.0263397213308566E-20,
+            4.064230660339354E-20, 4.1023029246790967E-20, 4.140558309909644E-20, 4.178998655304882E-20,
+            4.217625845177682E-20, 4.256441810262176E-20, 4.29544852915662E-20, 4.334648029830012E-20,
+            4.3740423911958146E-20, 4.4136337447563716E-20, 4.4534242763218286E-20, 4.4934162278076256E-20,
+            4.5336118991149025E-20, 4.5740136500984466E-20, 4.614623902627128E-20, 4.655445142742113E-20,
+            4.696479922918509E-20, 4.737730864436494E-20, 4.779200659868417E-20, 4.820892075688811E-20,
+            4.8628079550147814E-20, 4.9049512204847653E-20, 4.9473248772842596E-20, 4.9899320163277674E-20,
+            5.032775817606897E-20, 5.0758595537153414E-20, 5.1191865935622696E-20, 5.162760406286606E-20,
+            5.2065845653856416E-20, 5.2506627530725194E-20, 5.294998764878345E-20, 5.3395965145159426E-20,
+            5.3844600390237576E-20, 5.429593504209936E-20, 5.475001210418387E-20, 5.520687598640507E-20,
+            5.566657256998382E-20, 5.612914927627579E-20, 5.659465513990248E-20, 5.706314088652056E-20,
+            5.753465901559692E-20, 5.800926388859122E-20, 5.848701182298758E-20, 5.89679611926598E-20,
+            5.945217253510347E-20, 5.99397086661226E-20, 6.043063480261893E-20, 6.092501869420053E-20,
+            6.142293076440286E-20, 6.192444426240153E-20, 6.242963542619394E-20, 6.293858365833621E-20,
+            6.345137171544756E-20, 6.396808591283496E-20, 6.448881634575274E-20, 6.501365712899535E-20,
+            6.554270665673171E-20, 6.607606788473072E-20, 6.66138486374042E-20, 6.715616194241298E-20,
+            6.770312639595058E-20, 6.825486656224641E-20, 6.881151341132782E-20, 6.937320479965968E-20,
+            6.994008599895911E-20, 7.05123102792795E-20, 7.109003955339717E-20, 7.16734450906448E-20,
+            7.226270830965578E-20, 7.285802166105734E-20, 7.34595896130358E-20, 7.406762975496755E-20,
+            7.468237403705282E-20, 7.530407016722667E-20, 7.593298319069855E-20, 7.656939728248375E-20,
+            7.721361778948768E-20, 7.786597356641702E-20, 7.852681965945675E-20, 7.919654040385056E-20,
+            7.987555301703797E-20, 8.056431178890163E-20, 8.126331299642618E-20, 8.19731007037063E-20,
+            8.269427365263403E-20, 8.342749350883679E-20, 8.417349480745342E-20, 8.493309705283207E-20,
+            8.57072195782309E-20, 8.64968999859307E-20, 8.730331729565533E-20, 8.81278213788595E-20,
+            8.897197092819667E-20, 8.983758323931406E-20, 9.072680069786954E-20, 9.164218148406354E-20,
+            9.258682640670276E-20, 9.356456148027886E-20, 9.458021001263618E-20, 9.564001555085036E-20,
+            9.675233477050313E-20, 9.792885169780883E-20, 9.918690585753133E-20, 1.0055456271343397E-19,
+            1.0208407377305566E-19, 1.0390360993240711E-19, 1.0842021724855044E-19};
 
         /** Underlying source of randomness. */
         protected final UniformRandomProvider rng;
@@ -1191,16 +1217,16 @@ public class ZigguratSamplerPerformance {
      * McFarland (2016) JSCS 86, 1281-1294</a>
      */
     static class ModifiedZigguratExponentialSampler implements ContinuousSampler {
-        /** Maximum i value for early exit. */
-        private static final int I_MAX = 252;
         /** Mask to create an unsigned long from a signed long. */
         private static final long MAX_INT64 = 0x7fffffffffffffffL;
-        /** Maximum distance value for early exit. */
-        private static final long IE_MAX = 513303011048449572L;
         /** 2^53. */
         private static final double TWO_POW_63 = 0x1.0p63;
+        /** Maximum i value for early exit. */
+        private static final int I_MAX = 252;
+        /** Maximum distance value for early exit. */
+        private static final long IE_MAX = 513303011048449570L;
         /** Beginning of tail. */
-        private static final double X_0 = 7.56927469415;
+        private static final double X_0 = 7.569274694148063;
 
         /** The alias map. An integer in [0, 255] stored as a byte to save space. */
         private static final byte[] MAP = toBytes(new int[] {0, 0, 1, 235, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
@@ -1216,174 +1242,203 @@ public class ZigguratSamplerPerformance {
             247, 246, 246, 246, 245, 245, 244, 244, 243, 243, 242, 241, 241, 240, 239, 237, 3, 3, 4, 4, 6, 0, 0, 0, 0,
             236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 2, 0, 0, 0});
         /** The alias inverse PMF. */
-        private static final long[] IPMF = {9223372036854775328L, 1623796909450838420L, 2664290944894293715L,
-            7387971354164060121L, 6515064486552739054L, 8840508362680717952L, 6099647593382935246L,
-            7673130333659513959L, 6220332867583438265L, 5045979640552813853L, 4075305837223955667L,
-            3258413672162525563L, 2560664887087762661L, 1957224924672899759L, 1429800935350577626L, 964606309710808357L,
-            551043923599587249L, 180827629096890397L, -152619738120023526L, -454588624410291449L, -729385126147774875L,
-            -980551509819446846L, -1211029700667463872L, -1423284293868547154L, -1619396356369050292L,
-            -1801135830956212822L, -1970018048575618008L, -2127348289059705241L, -2274257249303686299L,
-            -2411729520096655228L, -2540626634159182525L, -2661705860113406462L, -2775635634532448735L,
-            -2883008316030465121L, -2984350790383654722L, -3080133339198118434L, -3170777096303091107L,
-            -3256660348483804932L, -3338123885075152741L, -3415475560473282822L, -3488994201966444710L,
-            -3558932970354470759L, -3625522261068041096L, -3688972217741992040L, -3749474917563782729L,
-            -3807206277531056234L, -3862327722496827274L, -3914987649156779787L, -3965322714631865323L,
-            -4013458973776912076L, -4059512885612767084L, -4103592206186241133L, -4145796782586128173L,
-            -4186219260694363437L, -4224945717447258894L, -4262056226866285614L, -4297625367836519694L,
-            -4331722680528537423L, -4364413077437472623L, -4395757214229418223L, -4425811824915119504L,
-            -4454630025296932688L, -4482261588141311280L, -4508753193105271888L, -4534148654077804689L,
-            -4558489126279970065L, -4581813295192216657L, -4604157549138257681L, -4625556137145250418L,
-            -4646041313519109426L, -4665643470413305970L, -4684391259530326642L, -4702311703971761747L,
-            -4719430301145086931L, -4735771117539946355L, -4751356876102103699L, -4766209036859128403L,
-            -4780347871386013331L, -4793792531638892019L, -4806561113635122292L, -4818670716409312756L,
-            -4830137496634465780L, -4840976719260854452L, -4851202804490332660L, -4860829371376460084L,
-            -4869869278311657652L, -4878334660640771092L, -4886236965617427412L, -4893586984900802772L,
-            -4900394884772702964L, -4906670234238885493L, -4912422031164489589L, -4917658726580136309L,
-            -4922388247283532373L, -4926618016851059029L, -4930354975163335189L, -4933605596540651285L,
-            -4936375906575303797L, -4938671497741365845L, -4940497543854575637L, -4941858813449629493L,
-            -4942759682136114997L, -4943204143989086773L, -4943195822025527893L, -4942737977813206357L,
-            -4941833520255033237L, -4940485013586738773L, -4938694684624359381L, -4936464429291795925L,
-            -4933795818458825557L, -4930690103114057941L, -4927148218896868949L, -4923170790008275925L,
-            -4918758132519202261L, -4913910257091645845L, -4908626871126550421L, -4902907380349522964L,
-            -4896750889844289364L, -4890156204540514772L, -4883121829162554452L, -4875645967641803284L,
-            -4867726521994894420L, -4859361090668136340L, -4850546966345097428L, -4841281133215539220L,
-            -4831560263698486164L, -4821380714613453652L, -4810738522790066260L, -4799629400105482131L,
-            -4788048727936313747L, -4775991551010508883L, -4763452570642098131L, -4750426137329511059L,
-            -4736906242696389331L, -4722886510751361491L, -4708360188440098835L, -4693320135461437394L,
-            -4677758813316075410L, -4661668273553512594L, -4645040145179234642L, -4627865621182772242L,
-            -4610135444140937425L, -4591839890849345681L, -4572968755929937937L, -4553511334358205905L,
-            -4533456402849118097L, -4512792200036279121L, -4491506405372581072L, -4469586116675402576L,
-            -4447017826233108176L, -4423787395382268560L, -4399880027458432847L, -4375280239014115151L,
-            -4349971829190464271L, -4323937847117722127L, -4297160557210950158L, -4269621402214950094L,
-            -4241300963840749518L, -4212178920821845518L, -4182234004204468173L, -4151443949668868493L,
-            -4119785446662289613L, -4087234084103201932L, -4053764292396157324L, -4019349281473091724L,
-            -3983960974549676683L, -3947569937258407435L, -3910145301787369227L, -3871654685619016074L,
-            -3832064104425399050L, -3791337878631545353L, -3749438533114317833L, -3706326689447995081L,
-            -3661960950051848712L, -3616297773528535240L, -3569291340409179143L, -3520893408440946503L,
-            -3471053156460654726L, -3419717015797782918L, -3366828488034800645L, -3312327947826472069L,
-            -3256152429334011012L, -3198235394669703364L, -3138506482563184963L, -3076891235255163586L,
-            -3013310801389731586L, -2947681612411375617L, -2879915029671665601L, -2809916959107518656L,
-            -2737587429961872959L, -2662820133571326270L, -2585501917733374398L, -2505512231579382333L,
-            -2422722515205206076L, -2336995527534112187L, -2248184604988688954L, -2156132842510798521L,
-            -2060672187261006776L, -1961622433929382455L, -1858790108950092598L, -1751967229002903349L,
-            -1640929916937143604L, -1525436855617592627L, -1405227557075244850L, -1280020420662660017L,
-            -1149510549536587824L, -1013367289578705710L, -871231448632088621L, -722712146453685035L,
-            -567383236774420522L, -404779231966955560L, -234390647591522471L, -55658667960120229L, 132030985907824093L,
-            329355128892810847L, 537061298001092449L, 755977262693571427L, 987022116608031845L, 1231219266829421544L,
-            1489711711346525930L, 1763780090187560429L, 2054864117341776240L, 2364588157623792755L,
-            2694791916990483702L, 3047567482883492729L, 3425304305830814717L, 3830744187097279873L,
-            4267048975685831301L, 4737884547990035082L, 5247525842198997007L, 5800989391535354004L,
-            6404202162993293978L, 7064218894258529185L, 7789505049452340392L, 8590309807749443504L,
-            7643763810684498323L, 8891950541491447639L, 5457384281016226081L, 9083704440929275131L,
-            7976211653914439517L, 8178631350487107662L, 2821287825726743868L, 6322989683301723979L,
-            4309503753387603546L, 4685170734960182655L, 8404845967535219911L, 7330522972447586582L,
-            1960945799077017972L, 4742910674644930459L, -751799822533465632L, 7023456603741994979L,
-            3843116882594690323L, 3927231442413903597L, -9223372036854775807L, -9223372036854775807L,
-            -9223372036854775807L};
-        /** The precomputed ziggurat lengths, denoted X_i in the main text. */
-        private static final double[] X_I = {8.20662406753e-19, 7.39737323516e-19, 6.91333133779e-19, 6.5647358821e-19,
-            6.29125399598e-19, 6.06572241296e-19, 5.87352761037e-19, 5.70588505285e-19, 5.55709456916e-19,
-            5.42324389037e-19, 5.30152976965e-19, 5.18987392577e-19, 5.0866922618e-19, 4.99074929388e-19,
-            4.90106258944e-19, 4.81683790106e-19, 4.73742386536e-19, 4.66227958072e-19, 4.59095090178e-19,
-            4.52305277907e-19, 4.45825588164e-19, 4.39627631264e-19, 4.33686759671e-19, 4.27981436185e-19,
-            4.22492730271e-19, 4.17203912535e-19, 4.12100125225e-19, 4.07168112259e-19, 4.0239599631e-19,
-            3.97773093429e-19, 3.93289757853e-19, 3.88937251293e-19, 3.84707632187e-19, 3.80593661382e-19,
-            3.76588721385e-19, 3.7268674692e-19, 3.68882164922e-19, 3.65169842488e-19, 3.61545041533e-19,
-            3.58003379153e-19, 3.54540792845e-19, 3.51153509888e-19, 3.478380203e-19, 3.44591052889e-19,
-            3.41409553966e-19, 3.38290668387e-19, 3.35231722623e-19, 3.32230209587e-19, 3.29283775028e-19,
-            3.26390205282e-19, 3.23547416228e-19, 3.20753443311e-19, 3.18006432505e-19, 3.15304632118e-19,
-            3.12646385343e-19, 3.10030123469e-19, 3.07454359701e-19, 3.049176835e-19, 3.02418755411e-19,
-            2.99956302321e-19, 2.97529113107e-19, 2.95136034631e-19, 2.92775968057e-19, 2.90447865454e-19,
-            2.88150726664e-19, 2.85883596399e-19, 2.83645561563e-19, 2.81435748768e-19, 2.79253322026e-19,
-            2.77097480612e-19, 2.74967457073e-19, 2.72862515379e-19, 2.70781949192e-19, 2.68725080264e-19,
-            2.66691256932e-19, 2.64679852713e-19, 2.62690264997e-19, 2.60721913814e-19, 2.58774240685e-19,
-            2.56846707542e-19, 2.54938795718e-19, 2.53050004991e-19, 2.51179852691e-19, 2.49327872862e-19,
-            2.47493615466e-19, 2.45676645638e-19, 2.43876542983e-19, 2.42092900908e-19, 2.40325326001e-19,
-            2.38573437435e-19, 2.36836866406e-19, 2.35115255607e-19, 2.33408258722e-19, 2.31715539953e-19,
-            2.3003677357e-19, 2.28371643478e-19, 2.2671984282e-19, 2.2508107358e-19, 2.23455046227e-19,
-            2.21841479361e-19, 2.20240099382e-19, 2.18650640175e-19, 2.17072842808e-19, 2.15506455249e-19,
-            2.13951232087e-19, 2.12406934276e-19, 2.10873328882e-19, 2.09350188851e-19, 2.07837292773e-19,
-            2.06334424671e-19, 2.04841373792e-19, 2.03357934403e-19, 2.01883905608e-19, 2.00419091156e-19,
-            1.98963299272e-19, 1.97516342486e-19, 1.96078037473e-19, 1.94648204892e-19, 1.93226669243e-19,
-            1.9181325872e-19, 1.90407805074e-19, 1.89010143478e-19, 1.87620112397e-19, 1.86237553469e-19,
-            1.8486231138e-19, 1.83494233754e-19, 1.82133171034e-19, 1.80778976379e-19, 1.79431505561e-19,
-            1.78090616856e-19, 1.76756170954e-19, 1.75428030858e-19, 1.74106061794e-19, 1.7279013112e-19,
-            1.71480108238e-19, 1.7017586451e-19, 1.68877273172e-19, 1.67584209255e-19, 1.66296549505e-19,
-            1.65014172306e-19, 1.63736957602e-19, 1.62464786823e-19, 1.61197542813e-19, 1.59935109756e-19,
-            1.58677373107e-19, 1.57424219521e-19, 1.56175536784e-19, 1.54931213746e-19, 1.5369114025e-19,
-            1.52455207068e-19, 1.51223305837e-19, 1.49995328986e-19, 1.48771169674e-19, 1.47550721726e-19,
-            1.46333879563e-19, 1.4512053814e-19, 1.43910592874e-19, 1.42703939586e-19, 1.41500474425e-19,
-            1.40300093807e-19, 1.39102694344e-19, 1.37908172772e-19, 1.36716425886e-19, 1.35527350466e-19,
-            1.34340843201e-19, 1.3315680062e-19, 1.31975119012e-19, 1.3079569435e-19, 1.29618422208e-19,
-            1.28443197683e-19, 1.27269915307e-19, 1.26098468959e-19, 1.24928751776e-19, 1.23760656057e-19,
-            1.22594073168e-19, 1.21428893439e-19, 1.20265006056e-19, 1.19102298955e-19, 1.17940658704e-19,
-            1.16779970383e-19, 1.15620117456e-19, 1.14460981638e-19, 1.13302442758e-19, 1.12144378607e-19,
-            1.10986664787e-19, 1.0982917454e-19, 1.08671778581e-19, 1.07514344905e-19, 1.06356738599e-19,
-            1.05198821625e-19, 1.04040452605e-19, 1.02881486575e-19, 1.01721774741e-19, 1.00561164199e-19,
-            9.93994976483e-20, 9.82366130767e-20, 9.70723434263e-20, 9.59065162307e-20, 9.47389532242e-20,
-            9.35694699202e-20, 9.23978751546e-20, 9.12239705906e-20, 9.00475501809e-20, 8.88683995826e-20,
-            8.76862955198e-20, 8.65010050861e-20, 8.53122849831e-20, 8.41198806844e-20, 8.29235255165e-20,
-            8.1722939648e-20, 8.05178289728e-20, 7.93078838751e-20, 7.80927778595e-20, 7.68721660284e-20,
-            7.5645683384e-20, 7.44129429302e-20, 7.31735335451e-20, 7.19270175876e-20, 7.06729281977e-20,
-            6.94107662395e-20, 6.81399968293e-20, 6.68600453746e-20, 6.55702930402e-20, 6.42700715334e-20,
-            6.29586570809e-20, 6.16352634381e-20, 6.02990337322e-20, 5.89490308929e-20, 5.75842263599e-20,
-            5.62034866696e-20, 5.48055574135e-20, 5.3389043909e-20, 5.1952387718e-20, 5.04938378663e-20,
-            4.90114152226e-20, 4.75028679334e-20, 4.59656150013e-20, 4.4396673898e-20, 4.27925663021e-20,
-            4.11491932734e-20, 3.94616667626e-20, 3.77240771314e-20, 3.59291640862e-20, 3.40678366911e-20,
-            3.21284476416e-20, 3.00956469164e-20, 2.79484694556e-20, 2.56569130487e-20, 2.31752097568e-20,
-            2.04266952283e-20, 1.72617703302e-20, 1.32818892594e-20, 0.0};
-        /** Overhang table. */
-        private static final double[] Y = {5.59520549511e-23, 1.18025099827e-22, 1.84444233867e-22, 2.54390304667e-22,
-            3.27376943115e-22, 4.03077321327e-22, 4.81254783195e-22, 5.61729148966e-22, 6.44358205404e-22,
-            7.29026623435e-22, 8.15638884563e-22, 9.04114536835e-22, 9.94384884864e-22, 1.0863906046e-21,
-            1.18007997755e-21, 1.27540755348e-21, 1.37233311764e-21, 1.47082087944e-21, 1.57083882574e-21,
-            1.67235819844e-21, 1.7753530675e-21, 1.87979997851e-21, 1.98567765878e-21, 2.09296677041e-21,
-            2.201649701e-21, 2.31171038523e-21, 2.42313415161e-21, 2.53590759014e-21, 2.65001843742e-21,
-            2.76545547637e-21, 2.88220844835e-21, 3.00026797575e-21, 3.11962549361e-21, 3.24027318888e-21,
-            3.36220394642e-21, 3.48541130074e-21, 3.60988939279e-21, 3.7356329311e-21, 3.86263715686e-21,
-            3.99089781236e-21, 4.12041111239e-21, 4.25117371845e-21, 4.38318271516e-21, 4.51643558895e-21,
-            4.65093020852e-21, 4.78666480711e-21, 4.92363796621e-21, 5.06184860075e-21, 5.20129594544e-21,
-            5.34197954236e-21, 5.48389922948e-21, 5.62705513018e-21, 5.77144764362e-21, 5.9170774359e-21,
-            6.06394543192e-21, 6.21205280795e-21, 6.36140098478e-21, 6.51199162141e-21, 6.66382660935e-21,
-            6.81690806729e-21, 6.97123833635e-21, 7.12681997563e-21, 7.28365575824e-21, 7.44174866764e-21,
-            7.60110189437e-21, 7.76171883308e-21, 7.92360307983e-21, 8.08675842978e-21, 8.25118887504e-21,
-            8.41689860281e-21, 8.58389199384e-21, 8.752173621e-21, 8.92174824817e-21, 9.0926208293e-21,
-            9.26479650768e-21, 9.43828061539e-21, 9.61307867302e-21, 9.78919638943e-21, 9.96663966183e-21,
-            1.01454145759e-20, 1.03255274063e-20, 1.05069846171e-20, 1.06897928622e-20, 1.08739589867e-20,
-            1.10594900275e-20, 1.12463932147e-20, 1.14346759725e-20, 1.16243459211e-20, 1.18154108781e-20,
-            1.20078788602e-20, 1.22017580851e-20, 1.23970569735e-20, 1.25937841516e-20, 1.27919484529e-20,
-            1.29915589212e-20, 1.31926248126e-20, 1.33951555991e-20, 1.35991609708e-20, 1.38046508394e-20,
-            1.40116353411e-20, 1.42201248406e-20, 1.44301299338e-20, 1.46416614524e-20, 1.48547304671e-20,
-            1.50693482921e-20, 1.5285526489e-20, 1.55032768718e-20, 1.57226115107e-20, 1.59435427376e-20,
-            1.61660831506e-20, 1.63902456195e-20, 1.6616043291e-20, 1.68434895946e-20, 1.70725982479e-20,
-            1.73033832633e-20, 1.75358589536e-20, 1.77700399393e-20, 1.80059411545e-20, 1.82435778548e-20,
-            1.84829656238e-20, 1.87241203814e-20, 1.89670583912e-20, 1.92117962687e-20, 1.94583509899e-20,
-            1.97067399002e-20, 1.99569807232e-20, 2.02090915706e-20, 2.04630909515e-20, 2.07189977831e-20,
-            2.09768314011e-20, 2.12366115708e-20, 2.14983584983e-20, 2.17620928428e-20, 2.20278357286e-20,
-            2.2295608758e-20, 2.2565434025e-20, 2.28373341287e-20, 2.31113321878e-20, 2.33874518561e-20,
-            2.36657173374e-20, 2.39461534023e-20, 2.42287854051e-20, 2.4513639301e-20, 2.48007416649e-20,
-            2.50901197103e-20, 2.53818013093e-20, 2.56758150136e-20, 2.59721900756e-20, 2.62709564716e-20,
-            2.65721449254e-20, 2.68757869323e-20, 2.71819147857e-20, 2.74905616033e-20, 2.78017613558e-20,
-            2.81155488957e-20, 2.84319599887e-20, 2.87510313451e-20, 2.90728006545e-20, 2.939730662e-20,
-            2.97245889962e-20, 3.00546886272e-20, 3.03876474879e-20, 3.07235087261e-20, 3.10623167078e-20,
-            3.14041170641e-20, 3.17489567409e-20, 3.20968840504e-20, 3.24479487265e-20, 3.28022019823e-20,
-            3.31596965706e-20, 3.35204868483e-20, 3.38846288435e-20, 3.42521803272e-20, 3.46232008885e-20,
-            3.4997752014e-20, 3.53758971719e-20, 3.57577019011e-20, 3.61432339058e-20, 3.65325631548e-20,
-            3.69257619879e-20, 3.73229052281e-20, 3.77240703013e-20, 3.81293373632e-20, 3.85387894342e-20,
-            3.89525125438e-20, 3.93705958834e-20, 3.97931319704e-20, 4.02202168223e-20, 4.06519501444e-20,
-            4.10884355286e-20, 4.15297806682e-20, 4.19760975869e-20, 4.24275028853e-20, 4.28841180055e-20,
-            4.3346069516e-20, 4.38134894182e-20, 4.42865154775e-20, 4.47652915804e-20, 4.52499681207e-20,
-            4.57407024181e-20, 4.62376591717e-20, 4.67410109528e-20, 4.72509387408e-20, 4.77676325071e-20,
-            4.82912918521e-20, 4.88221267023e-20, 4.93603580729e-20, 4.99062189052e-20, 5.04599549866e-20,
-            5.10218259653e-20, 5.15921064692e-20, 5.21710873452e-20, 5.2759077033e-20, 5.33564030933e-20,
-            5.39634139104e-20, 5.45804805963e-20, 5.52079991245e-20, 5.58463927299e-20, 5.64961146142e-20,
-            5.71576510093e-20, 5.7831524655e-20, 5.85182987638e-20, 5.92185815588e-20, 5.99330314883e-20,
-            6.06623632468e-20, 6.14073547584e-20, 6.21688553205e-20, 6.29477951501e-20, 6.37451966432e-20,
-            6.45621877375e-20, 6.54000178819e-20, 6.62600772633e-20, 6.71439201451e-20, 6.80532934473e-20,
-            6.89901720881e-20, 6.99568031586e-20, 7.09557617949e-20, 7.19900227889e-20, 7.30630537391e-20,
-            7.41789382663e-20, 7.53425421342e-20, 7.65597421711e-20, 7.78377498634e-20, 7.9185582674e-20,
-            8.06147755374e-20, 8.21405027698e-20, 8.37834459783e-20, 8.55731292497e-20, 8.75544596696e-20,
-            8.98023880577e-20, 9.24624714212e-20, 9.5919641345e-20, 1.08420217249e-19};
+        private static final long[] IPMF = {9223372036854773904L, 1623796909450835018L, 2664290944894291308L,
+            7387971354164061021L, 6515064486552723158L, 8840508362680718891L, 6099647593382936415L,
+            7673130333659513775L, 6220332867583438096L, 5045979640552813698L, 4075305837223955523L,
+            3258413672162525427L, 2560664887087762532L, 1957224924672899637L, 1429800935350577509L, 964606309710808246L,
+            551043923599587126L, 180827629096890295L, -152619738120023625L, -454588624410291545L, -729385126147774968L,
+            -980551509819446936L, -1211029700667463960L, -1423284293868548440L, -1619396356369050407L,
+            -1801135830956211623L, -1970018048575618087L, -2127348289059705319L, -2274257249303686407L,
+            -2411729520096655303L, -2540626634159180934L, -2661705860113406470L, -2775635634532450566L,
+            -2883008316030465190L, -2984350790383654790L, -3080133339198116454L, -3170777096303091110L,
+            -3256660348483819078L, -3338123885075136262L, -3415475560473299110L, -3488994201966428229L,
+            -3558932970354473157L, -3625522261068041093L, -3688972217741989381L, -3749474917563782629L,
+            -3807206277531056133L, -3862327722496843557L, -3914987649156779685L, -3965322714631865221L,
+            -4013458973776895589L, -4059512885612783333L, -4103592206186241029L, -4145796782586128069L,
+            -4186219260694346949L, -4224945717447275173L, -4262056226866285509L, -4297625367836519557L,
+            -4331722680528537317L, -4364413077437472517L, -4395757214229401700L, -4425811824915135780L,
+            -4454630025296932548L, -4482261588141290436L, -4508753193105288068L, -4534148654077808964L,
+            -4558489126279958148L, -4581813295192216580L, -4604157549138257636L, -4625556137145255269L,
+            -4646041313519104421L, -4665643470413305925L, -4684391259530326597L, -4702311703971761733L,
+            -4719430301145103269L, -4735771117539946308L, -4751356876102087236L, -4766209036859134052L,
+            -4780347871386013380L, -4793792531638892068L, -4806561113635132708L, -4818670716409306532L,
+            -4830137496634465604L, -4840976719260837892L, -4851202804490348868L, -4860829371376459908L,
+            -4869869278311657508L, -4878334660640770948L, -4886236965617427236L, -4893586984900802596L,
+            -4900394884772702724L, -4906670234238885316L, -4912422031164496804L, -4917658726580119812L,
+            -4922388247283532292L, -4926618016851066692L, -4930354975163335236L, -4933605596540651332L,
+            -4936375906575303844L, -4938671497741365892L, -4940497543854575684L, -4941858813449629540L,
+            -4942759682136115044L, -4943204143989086820L, -4943195822025527940L, -4942737977813206404L,
+            -4941833520255033284L, -4940485013586738820L, -4938694684624359428L, -4936464429291795972L,
+            -4933795818458825604L, -4930690103114057988L, -4927148218896864068L, -4923170790008275908L,
+            -4918758132519213508L, -4913910257091645764L, -4908626871126539204L, -4902907380349534020L,
+            -4896750889844272900L, -4890156204540531076L, -4883121829162554372L, -4875645967641781188L,
+            -4867726521994927044L, -4859361090668103364L, -4850546966345113668L, -4841281133215539076L,
+            -4831560263698491972L, -4821380714613447492L, -4810738522790066116L, -4799629400105481988L,
+            -4788048727936307268L, -4775991551010515012L, -4763452570642114308L, -4750426137329494532L,
+            -4736906242696389124L, -4722886510751377669L, -4708360188440088965L, -4693320135461420933L,
+            -4677758813316108101L, -4661668273553489093L, -4645040145179241541L, -4627865621182772101L,
+            -4610135444140930052L, -4591839890849345476L, -4572968755929961540L, -4553511334358205764L,
+            -4533456402849101572L, -4512792200036278980L, -4491506405372580932L, -4469586116675402436L,
+            -4447017826233108036L, -4423787395382284804L, -4399880027458416324L, -4375280239014115077L,
+            -4349971829190472197L, -4323937847117721861L, -4297160557210933573L, -4269621402214949829L,
+            -4241300963840749253L, -4212178920821861701L, -4182234004204451589L, -4151443949668877253L,
+            -4119785446662287621L, -4087234084103201605L, -4053764292396156933L, -4019349281473081925L,
+            -3983960974549692677L, -3947569937258423301L, -3910145301787345669L, -3871654685619032069L,
+            -3832064104425388805L, -3791337878631544901L, -3749438533114327493L, -3706326689447984389L,
+            -3661960950051848261L, -3616297773528534789L, -3569291340409189253L, -3520893408440946053L,
+            -3471053156460654341L, -3419717015797782598L, -3366828488034805510L, -3312327947826460358L,
+            -3256152429334010374L, -3198235394669719110L, -3138506482563172742L, -3076891235255162822L,
+            -3013310801389730758L, -2947681612411374854L, -2879915029671670790L, -2809916959107513734L,
+            -2737587429961866118L, -2662820133571325574L, -2585501917733379974L, -2505512231579385223L,
+            -2422722515205211655L, -2336995527534088455L, -2248184604988727559L, -2156132842510764935L,
+            -2060672187261025415L, -1961622433929371911L, -1858790108950105479L, -1751967229002895623L,
+            -1640929916937142791L, -1525436855617582472L, -1405227557075253256L, -1280020420662649992L,
+            -1149510549536596104L, -1013367289578704904L, -871231448632104200L, -722712146453667848L,
+            -567383236774435977L, -404779231966938249L, -234390647591545737L, -55658667960119305L, 132030985907841399L,
+            329355128892811767L, 537061298001085174L, 755977262693564150L, 987022116608033270L, 1231219266829431286L,
+            1489711711346518517L, 1763780090187553909L, 2054864117341795061L, 2364588157623768948L,
+            2694791916990503284L, 3047567482883476212L, 3425304305830816371L, 3830744187097297907L,
+            4267048975685830386L, 4737884547990017266L, 5247525842198998257L, 5800989391535355377L,
+            6404202162993295344L, 7064218894258540527L, 7789505049452331503L, 8590309807749444846L,
+            7643763810684490059L, 8891950541491446071L, 5457384281016205975L, 9083704440929283969L,
+            7976211653914433372L, 8178631350487117494L, 2821287825726744835L, 6322989683301709657L,
+            4309503753387611426L, 4685170734960170474L, 8404845967535199663L, 7330522972447554153L,
+            1960945799076992020L, 4742910674644898996L, -751799822533509968L, 7023456603741959948L,
+            3843116882594676172L, 3927231442413902976L, -9223372036854775808L, -9223372036854775808L,
+            -9223372036854775808L};
+        /**
+         * The precomputed ziggurat lengths, denoted X_i in the main text. X_i = length of
+         * ziggurat layer i.
+         */
+        private static final double[] X = {8.206624067534882E-19, 7.397373235160728E-19, 6.913331337791529E-19,
+            6.564735882096453E-19, 6.291253995981851E-19, 6.065722412960496E-19, 5.873527610373727E-19,
+            5.705885052853694E-19, 5.557094569162239E-19, 5.423243890374395E-19, 5.301529769650878E-19,
+            5.189873925770806E-19, 5.086692261799833E-19, 4.990749293879647E-19, 4.901062589444954E-19,
+            4.816837901064919E-19, 4.737423865364471E-19, 4.662279580719682E-19, 4.590950901778405E-19,
+            4.523052779065815E-19, 4.458255881635396E-19, 4.396276312636838E-19, 4.336867596710647E-19,
+            4.2798143618469714E-19, 4.224927302706489E-19, 4.172039125346411E-19, 4.1210012522465616E-19,
+            4.0716811225869233E-19, 4.0239599631006903E-19, 3.9777309342877357E-19, 3.93289757853345E-19,
+            3.8893725129310323E-19, 3.8470763218720385E-19, 3.8059366138180143E-19, 3.765887213854473E-19,
+            3.7268674692030177E-19, 3.688821649224816E-19, 3.651698424880007E-19, 3.6154504153287473E-19,
+            3.5800337915318032E-19, 3.545407928453343E-19, 3.5115350988784242E-19, 3.478380203003096E-19,
+            3.4459105288907336E-19, 3.4140955396563316E-19, 3.3829066838741162E-19, 3.3523172262289E-19,
+            3.3223020958685874E-19, 3.292837750280447E-19, 3.263902052820205E-19, 3.2354741622810815E-19,
+            3.207534433108079E-19, 3.180064325047861E-19, 3.1530463211820845E-19, 3.1264638534265134E-19,
+            3.100301234693421E-19, 3.07454359701373E-19, 3.049176835000556E-19, 3.0241875541094565E-19,
+            2.999563023214455E-19, 2.975291131074259E-19, 2.9513603463113224E-19, 2.9277596805684267E-19,
+            2.9044786545442563E-19, 2.8815072666416712E-19, 2.858835963990693E-19, 2.8364556156331615E-19,
+            2.81435748767798E-19, 2.7925332202553125E-19, 2.770974806115288E-19, 2.7496745707320232E-19,
+            2.7286251537873397E-19, 2.7078194919206054E-19, 2.687250802641905E-19, 2.666912569315344E-19,
+            2.646798527127889E-19, 2.6269026499668434E-19, 2.6072191381359757E-19, 2.5877424068465143E-19,
+            2.568467075424817E-19, 2.549387957183548E-19, 2.530500049907748E-19, 2.511798526911271E-19,
+            2.4932787286227806E-19, 2.474936154663866E-19, 2.456766456384867E-19, 2.438765429826784E-19,
+            2.4209290090801527E-19, 2.403253260014054E-19, 2.3857343743505147E-19, 2.368368664061465E-19,
+            2.3511525560671253E-19, 2.3340825872163284E-19, 2.3171553995306794E-19, 2.3003677356958333E-19,
+            2.283716434784348E-19, 2.2671984281957174E-19, 2.250810735800194E-19, 2.234550462273959E-19,
+            2.2184147936140775E-19, 2.2024009938224424E-19, 2.186506401748684E-19, 2.1707284280826716E-19,
+            2.1550645524878675E-19, 2.1395123208673778E-19, 2.124069342755064E-19, 2.1087332888245875E-19,
+            2.0935018885097035E-19, 2.0783729277295508E-19, 2.0633442467130712E-19, 2.0484137379170616E-19,
+            2.0335793440326865E-19, 2.018839056075609E-19, 2.0041909115551697E-19, 1.9896329927183254E-19,
+            1.975163424864309E-19, 1.9607803747261946E-19, 1.9464820489157862E-19, 1.9322666924284314E-19,
+            1.9181325872045647E-19, 1.904078050744948E-19, 1.8901014347767504E-19, 1.8762011239677479E-19,
+            1.8623755346860768E-19, 1.8486231138030984E-19, 1.8349423375370566E-19, 1.8213317103353295E-19,
+            1.8077897637931708E-19, 1.7943150556069476E-19, 1.7809061685599652E-19, 1.7675617095390567E-19,
+            1.7542803085801941E-19, 1.741060617941453E-19, 1.727901311201724E-19, 1.7148010823836362E-19,
+            1.7017586450992059E-19, 1.6887727317167824E-19, 1.6758420925479093E-19, 1.6629654950527621E-19,
+            1.650141723062866E-19, 1.6373695760198277E-19, 1.624647868228856E-19, 1.6119754281258616E-19,
+            1.5993510975569615E-19, 1.586773731069231E-19, 1.5742421952115544E-19, 1.5617553678444595E-19,
+            1.5493121374578016E-19, 1.5369114024951992E-19, 1.524552070684102E-19, 1.5122330583703858E-19,
+            1.499953289856356E-19, 1.4877116967410352E-19, 1.4755072172615974E-19, 1.4633387956347966E-19,
+            1.4512053813972103E-19, 1.439105928743099E-19, 1.4270393958586506E-19, 1.415004744251338E-19,
+            1.4030009380730888E-19, 1.3910269434359025E-19, 1.3790817277185197E-19, 1.3671642588626657E-19,
+            1.3552735046573446E-19, 1.3434084320095729E-19, 1.3315680061998685E-19, 1.3197511901207148E-19,
+            1.3079569434961214E-19, 1.2961842220802957E-19, 1.28443197683331E-19, 1.2726991530715219E-19,
+            1.2609846895903523E-19, 1.2492875177568625E-19, 1.237606560569394E-19, 1.225940731681333E-19,
+            1.2142889343858445E-19, 1.2026500605581765E-19, 1.1910229895518744E-19, 1.1794065870449425E-19,
+            1.1677997038316715E-19, 1.1562011745554883E-19, 1.144609816377787E-19, 1.1330244275772562E-19,
+            1.1214437860737343E-19, 1.109866647870073E-19, 1.0982917454048923E-19, 1.086717785808435E-19,
+            1.0751434490529747E-19, 1.0635673859884002E-19, 1.0519882162526621E-19, 1.0404045260457141E-19,
+            1.0288148657544097E-19, 1.0172177474144965E-19, 1.0056116419943559E-19, 9.939949764834668E-20,
+            9.823661307666745E-20, 9.70723434263201E-20, 9.590651623069063E-20, 9.47389532241542E-20,
+            9.356946992015904E-20, 9.239787515456947E-20, 9.122397059055647E-20, 9.004755018085287E-20,
+            8.886839958264763E-20, 8.768629551976745E-20, 8.650100508607102E-20, 8.531228498314119E-20,
+            8.411988068438521E-20, 8.292352551651342E-20, 8.17229396480345E-20, 8.051782897283921E-20,
+            7.930788387509923E-20, 7.809277785952443E-20, 7.687216602842904E-20, 7.564568338396512E-20,
+            7.441294293017913E-20, 7.317353354509333E-20, 7.192701758763107E-20, 7.067292819766679E-20,
+            6.941076623950036E-20, 6.813999682925642E-20, 6.686004537461023E-20, 6.557029304021008E-20,
+            6.427007153336853E-20, 6.295865708092356E-20, 6.163526343814314E-20, 6.02990337321517E-20,
+            5.894903089285018E-20, 5.758422635988593E-20, 5.62034866695974E-20, 5.480555741349931E-20,
+            5.3389043909003295E-20, 5.1952387717989917E-20, 5.0493837866338355E-20, 4.901141522262949E-20,
+            4.7502867933366117E-20, 4.5965615001265455E-20, 4.4396673897997565E-20, 4.279256630214859E-20,
+            4.1149193273430015E-20, 3.9461666762606287E-20, 3.7724077131401685E-20, 3.592916408620436E-20,
+            3.4067836691100565E-20, 3.2128447641564046E-20, 3.0095646916399994E-20, 2.794846945559833E-20,
+            2.5656913048718645E-20, 2.317520975680391E-20, 2.042669522825129E-20, 1.7261770330213488E-20,
+            1.3281889259442579E-20, 0.0};
+        /** Overhang table. Y_i = f(X_i). */
+        private static final double[] Y = {5.595205495112736E-23, 1.1802509982703313E-22, 1.844442338673583E-22,
+            2.543903046669831E-22, 3.2737694311509334E-22, 4.0307732132706715E-22, 4.812547831949511E-22,
+            5.617291489658331E-22, 6.443582054044353E-22, 7.290266234346368E-22, 8.156388845632194E-22,
+            9.041145368348222E-22, 9.94384884863992E-22, 1.0863906045969114E-21, 1.1800799775461269E-21,
+            1.2754075534831208E-21, 1.372333117637729E-21, 1.4708208794375214E-21, 1.5708388257440445E-21,
+            1.6723581984374566E-21, 1.7753530675030514E-21, 1.8797999785104595E-21, 1.9856776587832504E-21,
+            2.0929667704053244E-21, 2.201649700995824E-21, 2.311710385230618E-21, 2.4231341516125464E-21,
+            2.535907590142089E-21, 2.650018437417054E-21, 2.765455476366039E-21, 2.8822084483468604E-21,
+            3.000267975754771E-21, 3.1196254936130377E-21, 3.240273188880175E-21, 3.3622039464187092E-21,
+            3.485411300740904E-21, 3.6098893927859475E-21, 3.735632931097177E-21, 3.862637156862005E-21,
+            3.990897812355284E-21, 4.120411112391895E-21, 4.251173718448891E-21, 4.383182715163374E-21,
+            4.5164355889510656E-21, 4.6509302085234806E-21, 4.7866648071096E-21, 4.923637966211997E-21,
+            5.061848600747899E-21, 5.201295945443473E-21, 5.341979542364895E-21, 5.483899229483096E-21,
+            5.627055130180635E-21, 5.7714476436191935E-21, 5.917077435895068E-21, 6.063945431917703E-21,
+            6.212052807953168E-21, 6.3614009847804375E-21, 6.511991621413643E-21, 6.6638266093481696E-21,
+            6.816908067292628E-21, 6.971238336352438E-21, 7.126819975634082E-21, 7.283655758242034E-21,
+            7.441748667643017E-21, 7.601101894374635E-21, 7.761718833077541E-21, 7.923603079832257E-21,
+            8.086758429783484E-21, 8.251188875036333E-21, 8.416898602810326E-21, 8.58389199383831E-21,
+            8.752173620998646E-21, 8.921748248170071E-21, 9.09262082929965E-21, 9.264796507675128E-21,
+            9.438280615393829E-21, 9.613078673021033E-21, 9.789196389431416E-21, 9.966639661827884E-21,
+            1.0145414575932636E-20, 1.0325527406345955E-20, 1.0506984617068672E-20, 1.0689792862184811E-20,
+            1.0873958986701341E-20, 1.10594900275424E-20, 1.1246393214695825E-20, 1.1434675972510121E-20,
+            1.1624345921140471E-20, 1.181541087814266E-20, 1.2007878860214202E-20, 1.2201758085082226E-20,
+            1.239705697353804E-20, 1.2593784151618565E-20, 1.2791948452935152E-20, 1.29915589211506E-20,
+            1.3192624812605428E-20, 1.3395155599094805E-20, 1.3599160970797774E-20, 1.3804650839360727E-20,
+            1.4011635341137284E-20, 1.4220124840587164E-20, 1.4430129933836705E-20, 1.46416614524042E-20,
+            1.485473046709328E-20, 1.5069348292058084E-20, 1.5285526489044053E-20, 1.5503276871808626E-20,
+            1.5722611510726402E-20, 1.5943542737583543E-20, 1.6166083150566702E-20, 1.6390245619451956E-20,
+            1.6616043290999594E-20, 1.684348959456108E-20, 1.7072598247904713E-20, 1.7303383263267072E-20,
+            1.7535858953637607E-20, 1.777003993928424E-20, 1.8005941154528286E-20, 1.8243577854777398E-20,
+            1.8482965623825808E-20, 1.8724120381431627E-20, 1.8967058391181452E-20, 1.9211796268653192E-20,
+            1.9458350989888484E-20, 1.9706739900186868E-20, 1.9956980723234356E-20, 2.0209091570579904E-20,
+            2.0463090951473895E-20, 2.0718997783083593E-20, 2.097683140110135E-20, 2.123661157076213E-20,
+            2.1498358498287976E-20, 2.1762092842777868E-20, 2.2027835728562592E-20, 2.229560875804522E-20,
+            2.256543402504904E-20, 2.2837334128696004E-20, 2.311133218784001E-20, 2.3387451856080863E-20,
+            2.366571733738611E-20, 2.394615340234961E-20, 2.422878540511741E-20, 2.451363930101321E-20,
+            2.4800741664897764E-20, 2.5090119710298442E-20, 2.5381801309347597E-20, 2.56758150135705E-20,
+            2.5972190075566336E-20, 2.6270956471628253E-20, 2.6572144925351523E-20, 2.687578693228184E-20,
+            2.718191478565915E-20, 2.7490561603315974E-20, 2.7801761355793055E-20, 2.811554889573917E-20,
+            2.8431959988666534E-20, 2.8751031345137833E-20, 2.907280065446631E-20, 2.9397306620015486E-20,
+            2.9724588996191657E-20, 3.005468862722811E-20, 3.038764748786764E-20, 3.072350872605708E-20,
+            3.1062316707775905E-20, 3.140411706412999E-20, 3.174895674085097E-20, 3.2096884050352357E-20,
+            3.2447948726504914E-20, 3.280220198230601E-20, 3.315969657063137E-20, 3.352048684827223E-20,
+            3.388462884347689E-20, 3.4252180327233346E-20, 3.4623200888548644E-20, 3.4997752014001677E-20,
+            3.537589717186906E-20, 3.5757701901149035E-20, 3.61432339058358E-20, 3.65325631548274E-20,
+            3.692576198788357E-20, 3.732290522808698E-20, 3.7724070301302117E-20, 3.812933736317104E-20,
+            3.8538789434235234E-20, 3.895251254382786E-20, 3.93705958834424E-20, 3.979313197035144E-20,
+            4.022021682232577E-20, 4.0651950144388133E-20, 4.1088435528630944E-20, 4.152978066823271E-20,
+            4.197609758692658E-20, 4.242750288530745E-20, 4.2884118005513604E-20, 4.334606951598745E-20,
+            4.381348941821026E-20, 4.428651547752084E-20, 4.476529158037235E-20, 4.5249968120658306E-20,
+            4.574070241805442E-20, 4.6237659171683015E-20, 4.674101095281837E-20, 4.7250938740823415E-20,
+            4.776763250705122E-20, 4.8291291852069895E-20, 4.8822126702292804E-20, 4.936035807293385E-20,
+            4.990621890518202E-20, 5.045995498662554E-20, 5.1021825965285324E-20, 5.159210646917826E-20,
+            5.2171087345169234E-20, 5.2759077033045284E-20, 5.335640309332586E-20, 5.396341391039951E-20,
+            5.458048059625925E-20, 5.520799912453558E-20, 5.584639272987383E-20, 5.649611461419377E-20,
+            5.715765100929071E-20, 5.783152465495663E-20, 5.851829876379432E-20, 5.921858155879171E-20,
+            5.99330314883387E-20, 6.066236324679689E-20, 6.1407354758435E-20, 6.216885532049976E-20,
+            6.294779515010373E-20, 6.37451966432144E-20, 6.456218773753799E-20, 6.54000178818891E-20,
+            6.626007726330934E-20, 6.714392014514662E-20, 6.80532934473017E-20, 6.8990172088133E-20,
+            6.99568031585645E-20, 7.095576179487843E-20, 7.199002278894508E-20, 7.306305373910546E-20,
+            7.417893826626688E-20, 7.534254213417312E-20, 7.655974217114297E-20, 7.783774986341285E-20,
+            7.918558267402951E-20, 8.06147755373533E-20, 8.214050276981807E-20, 8.378344597828052E-20,
+            8.557312924967816E-20, 8.75544596695901E-20, 8.980238805770688E-20, 9.246247142115109E-20,
+            9.591964134495172E-20, 1.0842021724855044E-19};
 
         /** Underlying source of randomness. */
         protected final UniformRandomProvider rng;
@@ -1407,7 +1462,7 @@ public class ZigguratSamplerPerformance {
                 // This branch is called about 0.984374 times per call into createSample.
                 // Note: Frequencies have been empirically measured for the first call to
                 // createSample; recursion due to retries have been ignored. Frequencies sum to 1.
-                return X_I[i] * (x & MAX_INT64);
+                return X[i] * (x & MAX_INT64);
             }
             // For the first call into createSample:
             // Recursion frequency = 0.000515560
@@ -1485,7 +1540,7 @@ public class ZigguratSamplerPerformance {
          * @return the sample
          */
         protected static double fastPrngSampleX(int j, long ux) {
-            return X_I[j] * TWO_POW_63 + (X_I[j - 1] - X_I[j]) * ux;
+            return X[j] * TWO_POW_63 + (X[j - 1] - X[j]) * ux;
         }
 
         /**
diff --git a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java
index 3edef7a..9c51cd8 100644
--- a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java
+++ b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java
@@ -93,9 +93,9 @@ public abstract class ZigguratSampler implements SharedStateContinuousSampler {
         /** Maximum i value for early exit. */
         private static final int I_MAX = 252;
         /** Maximum distance value for early exit. */
-        private static final long IE_MAX = 513303011048449572L;
+        private static final long IE_MAX = 513303011048449570L;
         /** Beginning of tail. */
-        private static final double X_0 = 7.56927469415;
+        private static final double X_0 = 7.569274694148063;
 
         /** The alias map. An integer in [0, 255] stored as a byte to save space. */
         private static final byte[] MAP = toBytes(new int[] {0, 0, 1, 235, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
@@ -111,174 +111,203 @@ public abstract class ZigguratSampler implements SharedStateContinuousSampler {
             247, 246, 246, 246, 245, 245, 244, 244, 243, 243, 242, 241, 241, 240, 239, 237, 3, 3, 4, 4, 6, 0, 0, 0, 0,
             236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 2, 0, 0, 0});
         /** The alias inverse PMF. */
-        private static final long[] IPMF = {9223372036854775328L, 1623796909450838420L, 2664290944894293715L,
-            7387971354164060121L, 6515064486552739054L, 8840508362680717952L, 6099647593382935246L,
-            7673130333659513959L, 6220332867583438265L, 5045979640552813853L, 4075305837223955667L,
-            3258413672162525563L, 2560664887087762661L, 1957224924672899759L, 1429800935350577626L, 964606309710808357L,
-            551043923599587249L, 180827629096890397L, -152619738120023526L, -454588624410291449L, -729385126147774875L,
-            -980551509819446846L, -1211029700667463872L, -1423284293868547154L, -1619396356369050292L,
-            -1801135830956212822L, -1970018048575618008L, -2127348289059705241L, -2274257249303686299L,
-            -2411729520096655228L, -2540626634159182525L, -2661705860113406462L, -2775635634532448735L,
-            -2883008316030465121L, -2984350790383654722L, -3080133339198118434L, -3170777096303091107L,
-            -3256660348483804932L, -3338123885075152741L, -3415475560473282822L, -3488994201966444710L,
-            -3558932970354470759L, -3625522261068041096L, -3688972217741992040L, -3749474917563782729L,
-            -3807206277531056234L, -3862327722496827274L, -3914987649156779787L, -3965322714631865323L,
-            -4013458973776912076L, -4059512885612767084L, -4103592206186241133L, -4145796782586128173L,
-            -4186219260694363437L, -4224945717447258894L, -4262056226866285614L, -4297625367836519694L,
-            -4331722680528537423L, -4364413077437472623L, -4395757214229418223L, -4425811824915119504L,
-            -4454630025296932688L, -4482261588141311280L, -4508753193105271888L, -4534148654077804689L,
-            -4558489126279970065L, -4581813295192216657L, -4604157549138257681L, -4625556137145250418L,
-            -4646041313519109426L, -4665643470413305970L, -4684391259530326642L, -4702311703971761747L,
-            -4719430301145086931L, -4735771117539946355L, -4751356876102103699L, -4766209036859128403L,
-            -4780347871386013331L, -4793792531638892019L, -4806561113635122292L, -4818670716409312756L,
-            -4830137496634465780L, -4840976719260854452L, -4851202804490332660L, -4860829371376460084L,
-            -4869869278311657652L, -4878334660640771092L, -4886236965617427412L, -4893586984900802772L,
-            -4900394884772702964L, -4906670234238885493L, -4912422031164489589L, -4917658726580136309L,
-            -4922388247283532373L, -4926618016851059029L, -4930354975163335189L, -4933605596540651285L,
-            -4936375906575303797L, -4938671497741365845L, -4940497543854575637L, -4941858813449629493L,
-            -4942759682136114997L, -4943204143989086773L, -4943195822025527893L, -4942737977813206357L,
-            -4941833520255033237L, -4940485013586738773L, -4938694684624359381L, -4936464429291795925L,
-            -4933795818458825557L, -4930690103114057941L, -4927148218896868949L, -4923170790008275925L,
-            -4918758132519202261L, -4913910257091645845L, -4908626871126550421L, -4902907380349522964L,
-            -4896750889844289364L, -4890156204540514772L, -4883121829162554452L, -4875645967641803284L,
-            -4867726521994894420L, -4859361090668136340L, -4850546966345097428L, -4841281133215539220L,
-            -4831560263698486164L, -4821380714613453652L, -4810738522790066260L, -4799629400105482131L,
-            -4788048727936313747L, -4775991551010508883L, -4763452570642098131L, -4750426137329511059L,
-            -4736906242696389331L, -4722886510751361491L, -4708360188440098835L, -4693320135461437394L,
-            -4677758813316075410L, -4661668273553512594L, -4645040145179234642L, -4627865621182772242L,
-            -4610135444140937425L, -4591839890849345681L, -4572968755929937937L, -4553511334358205905L,
-            -4533456402849118097L, -4512792200036279121L, -4491506405372581072L, -4469586116675402576L,
-            -4447017826233108176L, -4423787395382268560L, -4399880027458432847L, -4375280239014115151L,
-            -4349971829190464271L, -4323937847117722127L, -4297160557210950158L, -4269621402214950094L,
-            -4241300963840749518L, -4212178920821845518L, -4182234004204468173L, -4151443949668868493L,
-            -4119785446662289613L, -4087234084103201932L, -4053764292396157324L, -4019349281473091724L,
-            -3983960974549676683L, -3947569937258407435L, -3910145301787369227L, -3871654685619016074L,
-            -3832064104425399050L, -3791337878631545353L, -3749438533114317833L, -3706326689447995081L,
-            -3661960950051848712L, -3616297773528535240L, -3569291340409179143L, -3520893408440946503L,
-            -3471053156460654726L, -3419717015797782918L, -3366828488034800645L, -3312327947826472069L,
-            -3256152429334011012L, -3198235394669703364L, -3138506482563184963L, -3076891235255163586L,
-            -3013310801389731586L, -2947681612411375617L, -2879915029671665601L, -2809916959107518656L,
-            -2737587429961872959L, -2662820133571326270L, -2585501917733374398L, -2505512231579382333L,
-            -2422722515205206076L, -2336995527534112187L, -2248184604988688954L, -2156132842510798521L,
-            -2060672187261006776L, -1961622433929382455L, -1858790108950092598L, -1751967229002903349L,
-            -1640929916937143604L, -1525436855617592627L, -1405227557075244850L, -1280020420662660017L,
-            -1149510549536587824L, -1013367289578705710L, -871231448632088621L, -722712146453685035L,
-            -567383236774420522L, -404779231966955560L, -234390647591522471L, -55658667960120229L, 132030985907824093L,
-            329355128892810847L, 537061298001092449L, 755977262693571427L, 987022116608031845L, 1231219266829421544L,
-            1489711711346525930L, 1763780090187560429L, 2054864117341776240L, 2364588157623792755L,
-            2694791916990483702L, 3047567482883492729L, 3425304305830814717L, 3830744187097279873L,
-            4267048975685831301L, 4737884547990035082L, 5247525842198997007L, 5800989391535354004L,
-            6404202162993293978L, 7064218894258529185L, 7789505049452340392L, 8590309807749443504L,
-            7643763810684498323L, 8891950541491447639L, 5457384281016226081L, 9083704440929275131L,
-            7976211653914439517L, 8178631350487107662L, 2821287825726743868L, 6322989683301723979L,
-            4309503753387603546L, 4685170734960182655L, 8404845967535219911L, 7330522972447586582L,
-            1960945799077017972L, 4742910674644930459L, -751799822533465632L, 7023456603741994979L,
-            3843116882594690323L, 3927231442413903597L, -9223372036854775807L, -9223372036854775807L,
-            -9223372036854775807L};
-        /** The precomputed ziggurat lengths, denoted X_i in the main text. X_i = length of ziggurat layer i. */
-        private static final double[] X = {8.20662406753e-19, 7.39737323516e-19, 6.91333133779e-19, 6.5647358821e-19,
-            6.29125399598e-19, 6.06572241296e-19, 5.87352761037e-19, 5.70588505285e-19, 5.55709456916e-19,
-            5.42324389037e-19, 5.30152976965e-19, 5.18987392577e-19, 5.0866922618e-19, 4.99074929388e-19,
-            4.90106258944e-19, 4.81683790106e-19, 4.73742386536e-19, 4.66227958072e-19, 4.59095090178e-19,
-            4.52305277907e-19, 4.45825588164e-19, 4.39627631264e-19, 4.33686759671e-19, 4.27981436185e-19,
-            4.22492730271e-19, 4.17203912535e-19, 4.12100125225e-19, 4.07168112259e-19, 4.0239599631e-19,
-            3.97773093429e-19, 3.93289757853e-19, 3.88937251293e-19, 3.84707632187e-19, 3.80593661382e-19,
-            3.76588721385e-19, 3.7268674692e-19, 3.68882164922e-19, 3.65169842488e-19, 3.61545041533e-19,
-            3.58003379153e-19, 3.54540792845e-19, 3.51153509888e-19, 3.478380203e-19, 3.44591052889e-19,
-            3.41409553966e-19, 3.38290668387e-19, 3.35231722623e-19, 3.32230209587e-19, 3.29283775028e-19,
-            3.26390205282e-19, 3.23547416228e-19, 3.20753443311e-19, 3.18006432505e-19, 3.15304632118e-19,
-            3.12646385343e-19, 3.10030123469e-19, 3.07454359701e-19, 3.049176835e-19, 3.02418755411e-19,
-            2.99956302321e-19, 2.97529113107e-19, 2.95136034631e-19, 2.92775968057e-19, 2.90447865454e-19,
-            2.88150726664e-19, 2.85883596399e-19, 2.83645561563e-19, 2.81435748768e-19, 2.79253322026e-19,
-            2.77097480612e-19, 2.74967457073e-19, 2.72862515379e-19, 2.70781949192e-19, 2.68725080264e-19,
-            2.66691256932e-19, 2.64679852713e-19, 2.62690264997e-19, 2.60721913814e-19, 2.58774240685e-19,
-            2.56846707542e-19, 2.54938795718e-19, 2.53050004991e-19, 2.51179852691e-19, 2.49327872862e-19,
-            2.47493615466e-19, 2.45676645638e-19, 2.43876542983e-19, 2.42092900908e-19, 2.40325326001e-19,
-            2.38573437435e-19, 2.36836866406e-19, 2.35115255607e-19, 2.33408258722e-19, 2.31715539953e-19,
-            2.3003677357e-19, 2.28371643478e-19, 2.2671984282e-19, 2.2508107358e-19, 2.23455046227e-19,
-            2.21841479361e-19, 2.20240099382e-19, 2.18650640175e-19, 2.17072842808e-19, 2.15506455249e-19,
-            2.13951232087e-19, 2.12406934276e-19, 2.10873328882e-19, 2.09350188851e-19, 2.07837292773e-19,
-            2.06334424671e-19, 2.04841373792e-19, 2.03357934403e-19, 2.01883905608e-19, 2.00419091156e-19,
-            1.98963299272e-19, 1.97516342486e-19, 1.96078037473e-19, 1.94648204892e-19, 1.93226669243e-19,
-            1.9181325872e-19, 1.90407805074e-19, 1.89010143478e-19, 1.87620112397e-19, 1.86237553469e-19,
-            1.8486231138e-19, 1.83494233754e-19, 1.82133171034e-19, 1.80778976379e-19, 1.79431505561e-19,
-            1.78090616856e-19, 1.76756170954e-19, 1.75428030858e-19, 1.74106061794e-19, 1.7279013112e-19,
-            1.71480108238e-19, 1.7017586451e-19, 1.68877273172e-19, 1.67584209255e-19, 1.66296549505e-19,
-            1.65014172306e-19, 1.63736957602e-19, 1.62464786823e-19, 1.61197542813e-19, 1.59935109756e-19,
-            1.58677373107e-19, 1.57424219521e-19, 1.56175536784e-19, 1.54931213746e-19, 1.5369114025e-19,
-            1.52455207068e-19, 1.51223305837e-19, 1.49995328986e-19, 1.48771169674e-19, 1.47550721726e-19,
-            1.46333879563e-19, 1.4512053814e-19, 1.43910592874e-19, 1.42703939586e-19, 1.41500474425e-19,
-            1.40300093807e-19, 1.39102694344e-19, 1.37908172772e-19, 1.36716425886e-19, 1.35527350466e-19,
-            1.34340843201e-19, 1.3315680062e-19, 1.31975119012e-19, 1.3079569435e-19, 1.29618422208e-19,
-            1.28443197683e-19, 1.27269915307e-19, 1.26098468959e-19, 1.24928751776e-19, 1.23760656057e-19,
-            1.22594073168e-19, 1.21428893439e-19, 1.20265006056e-19, 1.19102298955e-19, 1.17940658704e-19,
-            1.16779970383e-19, 1.15620117456e-19, 1.14460981638e-19, 1.13302442758e-19, 1.12144378607e-19,
-            1.10986664787e-19, 1.0982917454e-19, 1.08671778581e-19, 1.07514344905e-19, 1.06356738599e-19,
-            1.05198821625e-19, 1.04040452605e-19, 1.02881486575e-19, 1.01721774741e-19, 1.00561164199e-19,
-            9.93994976483e-20, 9.82366130767e-20, 9.70723434263e-20, 9.59065162307e-20, 9.47389532242e-20,
-            9.35694699202e-20, 9.23978751546e-20, 9.12239705906e-20, 9.00475501809e-20, 8.88683995826e-20,
-            8.76862955198e-20, 8.65010050861e-20, 8.53122849831e-20, 8.41198806844e-20, 8.29235255165e-20,
-            8.1722939648e-20, 8.05178289728e-20, 7.93078838751e-20, 7.80927778595e-20, 7.68721660284e-20,
-            7.5645683384e-20, 7.44129429302e-20, 7.31735335451e-20, 7.19270175876e-20, 7.06729281977e-20,
-            6.94107662395e-20, 6.81399968293e-20, 6.68600453746e-20, 6.55702930402e-20, 6.42700715334e-20,
-            6.29586570809e-20, 6.16352634381e-20, 6.02990337322e-20, 5.89490308929e-20, 5.75842263599e-20,
-            5.62034866696e-20, 5.48055574135e-20, 5.3389043909e-20, 5.1952387718e-20, 5.04938378663e-20,
-            4.90114152226e-20, 4.75028679334e-20, 4.59656150013e-20, 4.4396673898e-20, 4.27925663021e-20,
-            4.11491932734e-20, 3.94616667626e-20, 3.77240771314e-20, 3.59291640862e-20, 3.40678366911e-20,
-            3.21284476416e-20, 3.00956469164e-20, 2.79484694556e-20, 2.56569130487e-20, 2.31752097568e-20,
-            2.04266952283e-20, 1.72617703302e-20, 1.32818892594e-20, 0.0};
+        private static final long[] IPMF = {9223372036854773904L, 1623796909450835018L, 2664290944894291308L,
+            7387971354164061021L, 6515064486552723158L, 8840508362680718891L, 6099647593382936415L,
+            7673130333659513775L, 6220332867583438096L, 5045979640552813698L, 4075305837223955523L,
+            3258413672162525427L, 2560664887087762532L, 1957224924672899637L, 1429800935350577509L, 964606309710808246L,
+            551043923599587126L, 180827629096890295L, -152619738120023625L, -454588624410291545L, -729385126147774968L,
+            -980551509819446936L, -1211029700667463960L, -1423284293868548440L, -1619396356369050407L,
+            -1801135830956211623L, -1970018048575618087L, -2127348289059705319L, -2274257249303686407L,
+            -2411729520096655303L, -2540626634159180934L, -2661705860113406470L, -2775635634532450566L,
+            -2883008316030465190L, -2984350790383654790L, -3080133339198116454L, -3170777096303091110L,
+            -3256660348483819078L, -3338123885075136262L, -3415475560473299110L, -3488994201966428229L,
+            -3558932970354473157L, -3625522261068041093L, -3688972217741989381L, -3749474917563782629L,
+            -3807206277531056133L, -3862327722496843557L, -3914987649156779685L, -3965322714631865221L,
+            -4013458973776895589L, -4059512885612783333L, -4103592206186241029L, -4145796782586128069L,
+            -4186219260694346949L, -4224945717447275173L, -4262056226866285509L, -4297625367836519557L,
+            -4331722680528537317L, -4364413077437472517L, -4395757214229401700L, -4425811824915135780L,
+            -4454630025296932548L, -4482261588141290436L, -4508753193105288068L, -4534148654077808964L,
+            -4558489126279958148L, -4581813295192216580L, -4604157549138257636L, -4625556137145255269L,
+            -4646041313519104421L, -4665643470413305925L, -4684391259530326597L, -4702311703971761733L,
+            -4719430301145103269L, -4735771117539946308L, -4751356876102087236L, -4766209036859134052L,
+            -4780347871386013380L, -4793792531638892068L, -4806561113635132708L, -4818670716409306532L,
+            -4830137496634465604L, -4840976719260837892L, -4851202804490348868L, -4860829371376459908L,
+            -4869869278311657508L, -4878334660640770948L, -4886236965617427236L, -4893586984900802596L,
+            -4900394884772702724L, -4906670234238885316L, -4912422031164496804L, -4917658726580119812L,
+            -4922388247283532292L, -4926618016851066692L, -4930354975163335236L, -4933605596540651332L,
+            -4936375906575303844L, -4938671497741365892L, -4940497543854575684L, -4941858813449629540L,
+            -4942759682136115044L, -4943204143989086820L, -4943195822025527940L, -4942737977813206404L,
+            -4941833520255033284L, -4940485013586738820L, -4938694684624359428L, -4936464429291795972L,
+            -4933795818458825604L, -4930690103114057988L, -4927148218896864068L, -4923170790008275908L,
+            -4918758132519213508L, -4913910257091645764L, -4908626871126539204L, -4902907380349534020L,
+            -4896750889844272900L, -4890156204540531076L, -4883121829162554372L, -4875645967641781188L,
+            -4867726521994927044L, -4859361090668103364L, -4850546966345113668L, -4841281133215539076L,
+            -4831560263698491972L, -4821380714613447492L, -4810738522790066116L, -4799629400105481988L,
+            -4788048727936307268L, -4775991551010515012L, -4763452570642114308L, -4750426137329494532L,
+            -4736906242696389124L, -4722886510751377669L, -4708360188440088965L, -4693320135461420933L,
+            -4677758813316108101L, -4661668273553489093L, -4645040145179241541L, -4627865621182772101L,
+            -4610135444140930052L, -4591839890849345476L, -4572968755929961540L, -4553511334358205764L,
+            -4533456402849101572L, -4512792200036278980L, -4491506405372580932L, -4469586116675402436L,
+            -4447017826233108036L, -4423787395382284804L, -4399880027458416324L, -4375280239014115077L,
+            -4349971829190472197L, -4323937847117721861L, -4297160557210933573L, -4269621402214949829L,
+            -4241300963840749253L, -4212178920821861701L, -4182234004204451589L, -4151443949668877253L,
+            -4119785446662287621L, -4087234084103201605L, -4053764292396156933L, -4019349281473081925L,
+            -3983960974549692677L, -3947569937258423301L, -3910145301787345669L, -3871654685619032069L,
+            -3832064104425388805L, -3791337878631544901L, -3749438533114327493L, -3706326689447984389L,
+            -3661960950051848261L, -3616297773528534789L, -3569291340409189253L, -3520893408440946053L,
+            -3471053156460654341L, -3419717015797782598L, -3366828488034805510L, -3312327947826460358L,
+            -3256152429334010374L, -3198235394669719110L, -3138506482563172742L, -3076891235255162822L,
+            -3013310801389730758L, -2947681612411374854L, -2879915029671670790L, -2809916959107513734L,
+            -2737587429961866118L, -2662820133571325574L, -2585501917733379974L, -2505512231579385223L,
+            -2422722515205211655L, -2336995527534088455L, -2248184604988727559L, -2156132842510764935L,
+            -2060672187261025415L, -1961622433929371911L, -1858790108950105479L, -1751967229002895623L,
+            -1640929916937142791L, -1525436855617582472L, -1405227557075253256L, -1280020420662649992L,
+            -1149510549536596104L, -1013367289578704904L, -871231448632104200L, -722712146453667848L,
+            -567383236774435977L, -404779231966938249L, -234390647591545737L, -55658667960119305L, 132030985907841399L,
+            329355128892811767L, 537061298001085174L, 755977262693564150L, 987022116608033270L, 1231219266829431286L,
+            1489711711346518517L, 1763780090187553909L, 2054864117341795061L, 2364588157623768948L,
+            2694791916990503284L, 3047567482883476212L, 3425304305830816371L, 3830744187097297907L,
+            4267048975685830386L, 4737884547990017266L, 5247525842198998257L, 5800989391535355377L,
+            6404202162993295344L, 7064218894258540527L, 7789505049452331503L, 8590309807749444846L,
+            7643763810684490059L, 8891950541491446071L, 5457384281016205975L, 9083704440929283969L,
+            7976211653914433372L, 8178631350487117494L, 2821287825726744835L, 6322989683301709657L,
+            4309503753387611426L, 4685170734960170474L, 8404845967535199663L, 7330522972447554153L,
+            1960945799076992020L, 4742910674644898996L, -751799822533509968L, 7023456603741959948L,
+            3843116882594676172L, 3927231442413902976L, -9223372036854775808L, -9223372036854775808L,
+            -9223372036854775808L};
+        /**
+         * The precomputed ziggurat lengths, denoted X_i in the main text. X_i = length of
+         * ziggurat layer i.
+         */
+        private static final double[] X = {8.206624067534882E-19, 7.397373235160728E-19, 6.913331337791529E-19,
+            6.564735882096453E-19, 6.291253995981851E-19, 6.065722412960496E-19, 5.873527610373727E-19,
+            5.705885052853694E-19, 5.557094569162239E-19, 5.423243890374395E-19, 5.301529769650878E-19,
+            5.189873925770806E-19, 5.086692261799833E-19, 4.990749293879647E-19, 4.901062589444954E-19,
+            4.816837901064919E-19, 4.737423865364471E-19, 4.662279580719682E-19, 4.590950901778405E-19,
+            4.523052779065815E-19, 4.458255881635396E-19, 4.396276312636838E-19, 4.336867596710647E-19,
+            4.2798143618469714E-19, 4.224927302706489E-19, 4.172039125346411E-19, 4.1210012522465616E-19,
+            4.0716811225869233E-19, 4.0239599631006903E-19, 3.9777309342877357E-19, 3.93289757853345E-19,
+            3.8893725129310323E-19, 3.8470763218720385E-19, 3.8059366138180143E-19, 3.765887213854473E-19,
+            3.7268674692030177E-19, 3.688821649224816E-19, 3.651698424880007E-19, 3.6154504153287473E-19,
+            3.5800337915318032E-19, 3.545407928453343E-19, 3.5115350988784242E-19, 3.478380203003096E-19,
+            3.4459105288907336E-19, 3.4140955396563316E-19, 3.3829066838741162E-19, 3.3523172262289E-19,
+            3.3223020958685874E-19, 3.292837750280447E-19, 3.263902052820205E-19, 3.2354741622810815E-19,
+            3.207534433108079E-19, 3.180064325047861E-19, 3.1530463211820845E-19, 3.1264638534265134E-19,
+            3.100301234693421E-19, 3.07454359701373E-19, 3.049176835000556E-19, 3.0241875541094565E-19,
+            2.999563023214455E-19, 2.975291131074259E-19, 2.9513603463113224E-19, 2.9277596805684267E-19,
+            2.9044786545442563E-19, 2.8815072666416712E-19, 2.858835963990693E-19, 2.8364556156331615E-19,
+            2.81435748767798E-19, 2.7925332202553125E-19, 2.770974806115288E-19, 2.7496745707320232E-19,
+            2.7286251537873397E-19, 2.7078194919206054E-19, 2.687250802641905E-19, 2.666912569315344E-19,
+            2.646798527127889E-19, 2.6269026499668434E-19, 2.6072191381359757E-19, 2.5877424068465143E-19,
+            2.568467075424817E-19, 2.549387957183548E-19, 2.530500049907748E-19, 2.511798526911271E-19,
+            2.4932787286227806E-19, 2.474936154663866E-19, 2.456766456384867E-19, 2.438765429826784E-19,
+            2.4209290090801527E-19, 2.403253260014054E-19, 2.3857343743505147E-19, 2.368368664061465E-19,
+            2.3511525560671253E-19, 2.3340825872163284E-19, 2.3171553995306794E-19, 2.3003677356958333E-19,
+            2.283716434784348E-19, 2.2671984281957174E-19, 2.250810735800194E-19, 2.234550462273959E-19,
+            2.2184147936140775E-19, 2.2024009938224424E-19, 2.186506401748684E-19, 2.1707284280826716E-19,
+            2.1550645524878675E-19, 2.1395123208673778E-19, 2.124069342755064E-19, 2.1087332888245875E-19,
+            2.0935018885097035E-19, 2.0783729277295508E-19, 2.0633442467130712E-19, 2.0484137379170616E-19,
+            2.0335793440326865E-19, 2.018839056075609E-19, 2.0041909115551697E-19, 1.9896329927183254E-19,
+            1.975163424864309E-19, 1.9607803747261946E-19, 1.9464820489157862E-19, 1.9322666924284314E-19,
+            1.9181325872045647E-19, 1.904078050744948E-19, 1.8901014347767504E-19, 1.8762011239677479E-19,
+            1.8623755346860768E-19, 1.8486231138030984E-19, 1.8349423375370566E-19, 1.8213317103353295E-19,
+            1.8077897637931708E-19, 1.7943150556069476E-19, 1.7809061685599652E-19, 1.7675617095390567E-19,
+            1.7542803085801941E-19, 1.741060617941453E-19, 1.727901311201724E-19, 1.7148010823836362E-19,
+            1.7017586450992059E-19, 1.6887727317167824E-19, 1.6758420925479093E-19, 1.6629654950527621E-19,
+            1.650141723062866E-19, 1.6373695760198277E-19, 1.624647868228856E-19, 1.6119754281258616E-19,
+            1.5993510975569615E-19, 1.586773731069231E-19, 1.5742421952115544E-19, 1.5617553678444595E-19,
+            1.5493121374578016E-19, 1.5369114024951992E-19, 1.524552070684102E-19, 1.5122330583703858E-19,
+            1.499953289856356E-19, 1.4877116967410352E-19, 1.4755072172615974E-19, 1.4633387956347966E-19,
+            1.4512053813972103E-19, 1.439105928743099E-19, 1.4270393958586506E-19, 1.415004744251338E-19,
+            1.4030009380730888E-19, 1.3910269434359025E-19, 1.3790817277185197E-19, 1.3671642588626657E-19,
+            1.3552735046573446E-19, 1.3434084320095729E-19, 1.3315680061998685E-19, 1.3197511901207148E-19,
+            1.3079569434961214E-19, 1.2961842220802957E-19, 1.28443197683331E-19, 1.2726991530715219E-19,
+            1.2609846895903523E-19, 1.2492875177568625E-19, 1.237606560569394E-19, 1.225940731681333E-19,
+            1.2142889343858445E-19, 1.2026500605581765E-19, 1.1910229895518744E-19, 1.1794065870449425E-19,
+            1.1677997038316715E-19, 1.1562011745554883E-19, 1.144609816377787E-19, 1.1330244275772562E-19,
+            1.1214437860737343E-19, 1.109866647870073E-19, 1.0982917454048923E-19, 1.086717785808435E-19,
+            1.0751434490529747E-19, 1.0635673859884002E-19, 1.0519882162526621E-19, 1.0404045260457141E-19,
+            1.0288148657544097E-19, 1.0172177474144965E-19, 1.0056116419943559E-19, 9.939949764834668E-20,
+            9.823661307666745E-20, 9.70723434263201E-20, 9.590651623069063E-20, 9.47389532241542E-20,
+            9.356946992015904E-20, 9.239787515456947E-20, 9.122397059055647E-20, 9.004755018085287E-20,
+            8.886839958264763E-20, 8.768629551976745E-20, 8.650100508607102E-20, 8.531228498314119E-20,
+            8.411988068438521E-20, 8.292352551651342E-20, 8.17229396480345E-20, 8.051782897283921E-20,
+            7.930788387509923E-20, 7.809277785952443E-20, 7.687216602842904E-20, 7.564568338396512E-20,
+            7.441294293017913E-20, 7.317353354509333E-20, 7.192701758763107E-20, 7.067292819766679E-20,
+            6.941076623950036E-20, 6.813999682925642E-20, 6.686004537461023E-20, 6.557029304021008E-20,
+            6.427007153336853E-20, 6.295865708092356E-20, 6.163526343814314E-20, 6.02990337321517E-20,
+            5.894903089285018E-20, 5.758422635988593E-20, 5.62034866695974E-20, 5.480555741349931E-20,
+            5.3389043909003295E-20, 5.1952387717989917E-20, 5.0493837866338355E-20, 4.901141522262949E-20,
+            4.7502867933366117E-20, 4.5965615001265455E-20, 4.4396673897997565E-20, 4.279256630214859E-20,
+            4.1149193273430015E-20, 3.9461666762606287E-20, 3.7724077131401685E-20, 3.592916408620436E-20,
+            3.4067836691100565E-20, 3.2128447641564046E-20, 3.0095646916399994E-20, 2.794846945559833E-20,
+            2.5656913048718645E-20, 2.317520975680391E-20, 2.042669522825129E-20, 1.7261770330213488E-20,
+            1.3281889259442579E-20, 0.0};
         /** Overhang table. Y_i = f(X_i). */
-        private static final double[] Y = {5.59520549511e-23, 1.18025099827e-22, 1.84444233867e-22, 2.54390304667e-22,
-            3.27376943115e-22, 4.03077321327e-22, 4.81254783195e-22, 5.61729148966e-22, 6.44358205404e-22,
-            7.29026623435e-22, 8.15638884563e-22, 9.04114536835e-22, 9.94384884864e-22, 1.0863906046e-21,
-            1.18007997755e-21, 1.27540755348e-21, 1.37233311764e-21, 1.47082087944e-21, 1.57083882574e-21,
-            1.67235819844e-21, 1.7753530675e-21, 1.87979997851e-21, 1.98567765878e-21, 2.09296677041e-21,
-            2.201649701e-21, 2.31171038523e-21, 2.42313415161e-21, 2.53590759014e-21, 2.65001843742e-21,
-            2.76545547637e-21, 2.88220844835e-21, 3.00026797575e-21, 3.11962549361e-21, 3.24027318888e-21,
-            3.36220394642e-21, 3.48541130074e-21, 3.60988939279e-21, 3.7356329311e-21, 3.86263715686e-21,
-            3.99089781236e-21, 4.12041111239e-21, 4.25117371845e-21, 4.38318271516e-21, 4.51643558895e-21,
-            4.65093020852e-21, 4.78666480711e-21, 4.92363796621e-21, 5.06184860075e-21, 5.20129594544e-21,
-            5.34197954236e-21, 5.48389922948e-21, 5.62705513018e-21, 5.77144764362e-21, 5.9170774359e-21,
-            6.06394543192e-21, 6.21205280795e-21, 6.36140098478e-21, 6.51199162141e-21, 6.66382660935e-21,
-            6.81690806729e-21, 6.97123833635e-21, 7.12681997563e-21, 7.28365575824e-21, 7.44174866764e-21,
-            7.60110189437e-21, 7.76171883308e-21, 7.92360307983e-21, 8.08675842978e-21, 8.25118887504e-21,
-            8.41689860281e-21, 8.58389199384e-21, 8.752173621e-21, 8.92174824817e-21, 9.0926208293e-21,
-            9.26479650768e-21, 9.43828061539e-21, 9.61307867302e-21, 9.78919638943e-21, 9.96663966183e-21,
-            1.01454145759e-20, 1.03255274063e-20, 1.05069846171e-20, 1.06897928622e-20, 1.08739589867e-20,
-            1.10594900275e-20, 1.12463932147e-20, 1.14346759725e-20, 1.16243459211e-20, 1.18154108781e-20,
-            1.20078788602e-20, 1.22017580851e-20, 1.23970569735e-20, 1.25937841516e-20, 1.27919484529e-20,
-            1.29915589212e-20, 1.31926248126e-20, 1.33951555991e-20, 1.35991609708e-20, 1.38046508394e-20,
-            1.40116353411e-20, 1.42201248406e-20, 1.44301299338e-20, 1.46416614524e-20, 1.48547304671e-20,
-            1.50693482921e-20, 1.5285526489e-20, 1.55032768718e-20, 1.57226115107e-20, 1.59435427376e-20,
-            1.61660831506e-20, 1.63902456195e-20, 1.6616043291e-20, 1.68434895946e-20, 1.70725982479e-20,
-            1.73033832633e-20, 1.75358589536e-20, 1.77700399393e-20, 1.80059411545e-20, 1.82435778548e-20,
-            1.84829656238e-20, 1.87241203814e-20, 1.89670583912e-20, 1.92117962687e-20, 1.94583509899e-20,
-            1.97067399002e-20, 1.99569807232e-20, 2.02090915706e-20, 2.04630909515e-20, 2.07189977831e-20,
-            2.09768314011e-20, 2.12366115708e-20, 2.14983584983e-20, 2.17620928428e-20, 2.20278357286e-20,
-            2.2295608758e-20, 2.2565434025e-20, 2.28373341287e-20, 2.31113321878e-20, 2.33874518561e-20,
-            2.36657173374e-20, 2.39461534023e-20, 2.42287854051e-20, 2.4513639301e-20, 2.48007416649e-20,
-            2.50901197103e-20, 2.53818013093e-20, 2.56758150136e-20, 2.59721900756e-20, 2.62709564716e-20,
-            2.65721449254e-20, 2.68757869323e-20, 2.71819147857e-20, 2.74905616033e-20, 2.78017613558e-20,
-            2.81155488957e-20, 2.84319599887e-20, 2.87510313451e-20, 2.90728006545e-20, 2.939730662e-20,
-            2.97245889962e-20, 3.00546886272e-20, 3.03876474879e-20, 3.07235087261e-20, 3.10623167078e-20,
-            3.14041170641e-20, 3.17489567409e-20, 3.20968840504e-20, 3.24479487265e-20, 3.28022019823e-20,
-            3.31596965706e-20, 3.35204868483e-20, 3.38846288435e-20, 3.42521803272e-20, 3.46232008885e-20,
-            3.4997752014e-20, 3.53758971719e-20, 3.57577019011e-20, 3.61432339058e-20, 3.65325631548e-20,
-            3.69257619879e-20, 3.73229052281e-20, 3.77240703013e-20, 3.81293373632e-20, 3.85387894342e-20,
-            3.89525125438e-20, 3.93705958834e-20, 3.97931319704e-20, 4.02202168223e-20, 4.06519501444e-20,
-            4.10884355286e-20, 4.15297806682e-20, 4.19760975869e-20, 4.24275028853e-20, 4.28841180055e-20,
-            4.3346069516e-20, 4.38134894182e-20, 4.42865154775e-20, 4.47652915804e-20, 4.52499681207e-20,
-            4.57407024181e-20, 4.62376591717e-20, 4.67410109528e-20, 4.72509387408e-20, 4.77676325071e-20,
-            4.82912918521e-20, 4.88221267023e-20, 4.93603580729e-20, 4.99062189052e-20, 5.04599549866e-20,
-            5.10218259653e-20, 5.15921064692e-20, 5.21710873452e-20, 5.2759077033e-20, 5.33564030933e-20,
-            5.39634139104e-20, 5.45804805963e-20, 5.52079991245e-20, 5.58463927299e-20, 5.64961146142e-20,
-            5.71576510093e-20, 5.7831524655e-20, 5.85182987638e-20, 5.92185815588e-20, 5.99330314883e-20,
-            6.06623632468e-20, 6.14073547584e-20, 6.21688553205e-20, 6.29477951501e-20, 6.37451966432e-20,
-            6.45621877375e-20, 6.54000178819e-20, 6.62600772633e-20, 6.71439201451e-20, 6.80532934473e-20,
-            6.89901720881e-20, 6.99568031586e-20, 7.09557617949e-20, 7.19900227889e-20, 7.30630537391e-20,
-            7.41789382663e-20, 7.53425421342e-20, 7.65597421711e-20, 7.78377498634e-20, 7.9185582674e-20,
-            8.06147755374e-20, 8.21405027698e-20, 8.37834459783e-20, 8.55731292497e-20, 8.75544596696e-20,
-            8.98023880577e-20, 9.24624714212e-20, 9.5919641345e-20, 1.08420217249e-19};
+        private static final double[] Y = {5.595205495112736E-23, 1.1802509982703313E-22, 1.844442338673583E-22,
+            2.543903046669831E-22, 3.2737694311509334E-22, 4.0307732132706715E-22, 4.812547831949511E-22,
+            5.617291489658331E-22, 6.443582054044353E-22, 7.290266234346368E-22, 8.156388845632194E-22,
+            9.041145368348222E-22, 9.94384884863992E-22, 1.0863906045969114E-21, 1.1800799775461269E-21,
+            1.2754075534831208E-21, 1.372333117637729E-21, 1.4708208794375214E-21, 1.5708388257440445E-21,
+            1.6723581984374566E-21, 1.7753530675030514E-21, 1.8797999785104595E-21, 1.9856776587832504E-21,
+            2.0929667704053244E-21, 2.201649700995824E-21, 2.311710385230618E-21, 2.4231341516125464E-21,
+            2.535907590142089E-21, 2.650018437417054E-21, 2.765455476366039E-21, 2.8822084483468604E-21,
+            3.000267975754771E-21, 3.1196254936130377E-21, 3.240273188880175E-21, 3.3622039464187092E-21,
+            3.485411300740904E-21, 3.6098893927859475E-21, 3.735632931097177E-21, 3.862637156862005E-21,
+            3.990897812355284E-21, 4.120411112391895E-21, 4.251173718448891E-21, 4.383182715163374E-21,
+            4.5164355889510656E-21, 4.6509302085234806E-21, 4.7866648071096E-21, 4.923637966211997E-21,
+            5.061848600747899E-21, 5.201295945443473E-21, 5.341979542364895E-21, 5.483899229483096E-21,
+            5.627055130180635E-21, 5.7714476436191935E-21, 5.917077435895068E-21, 6.063945431917703E-21,
+            6.212052807953168E-21, 6.3614009847804375E-21, 6.511991621413643E-21, 6.6638266093481696E-21,
+            6.816908067292628E-21, 6.971238336352438E-21, 7.126819975634082E-21, 7.283655758242034E-21,
+            7.441748667643017E-21, 7.601101894374635E-21, 7.761718833077541E-21, 7.923603079832257E-21,
+            8.086758429783484E-21, 8.251188875036333E-21, 8.416898602810326E-21, 8.58389199383831E-21,
+            8.752173620998646E-21, 8.921748248170071E-21, 9.09262082929965E-21, 9.264796507675128E-21,
+            9.438280615393829E-21, 9.613078673021033E-21, 9.789196389431416E-21, 9.966639661827884E-21,
+            1.0145414575932636E-20, 1.0325527406345955E-20, 1.0506984617068672E-20, 1.0689792862184811E-20,
+            1.0873958986701341E-20, 1.10594900275424E-20, 1.1246393214695825E-20, 1.1434675972510121E-20,
+            1.1624345921140471E-20, 1.181541087814266E-20, 1.2007878860214202E-20, 1.2201758085082226E-20,
+            1.239705697353804E-20, 1.2593784151618565E-20, 1.2791948452935152E-20, 1.29915589211506E-20,
+            1.3192624812605428E-20, 1.3395155599094805E-20, 1.3599160970797774E-20, 1.3804650839360727E-20,
+            1.4011635341137284E-20, 1.4220124840587164E-20, 1.4430129933836705E-20, 1.46416614524042E-20,
+            1.485473046709328E-20, 1.5069348292058084E-20, 1.5285526489044053E-20, 1.5503276871808626E-20,
+            1.5722611510726402E-20, 1.5943542737583543E-20, 1.6166083150566702E-20, 1.6390245619451956E-20,
+            1.6616043290999594E-20, 1.684348959456108E-20, 1.7072598247904713E-20, 1.7303383263267072E-20,
+            1.7535858953637607E-20, 1.777003993928424E-20, 1.8005941154528286E-20, 1.8243577854777398E-20,
+            1.8482965623825808E-20, 1.8724120381431627E-20, 1.8967058391181452E-20, 1.9211796268653192E-20,
+            1.9458350989888484E-20, 1.9706739900186868E-20, 1.9956980723234356E-20, 2.0209091570579904E-20,
+            2.0463090951473895E-20, 2.0718997783083593E-20, 2.097683140110135E-20, 2.123661157076213E-20,
+            2.1498358498287976E-20, 2.1762092842777868E-20, 2.2027835728562592E-20, 2.229560875804522E-20,
+            2.256543402504904E-20, 2.2837334128696004E-20, 2.311133218784001E-20, 2.3387451856080863E-20,
+            2.366571733738611E-20, 2.394615340234961E-20, 2.422878540511741E-20, 2.451363930101321E-20,
+            2.4800741664897764E-20, 2.5090119710298442E-20, 2.5381801309347597E-20, 2.56758150135705E-20,
+            2.5972190075566336E-20, 2.6270956471628253E-20, 2.6572144925351523E-20, 2.687578693228184E-20,
+            2.718191478565915E-20, 2.7490561603315974E-20, 2.7801761355793055E-20, 2.811554889573917E-20,
+            2.8431959988666534E-20, 2.8751031345137833E-20, 2.907280065446631E-20, 2.9397306620015486E-20,
+            2.9724588996191657E-20, 3.005468862722811E-20, 3.038764748786764E-20, 3.072350872605708E-20,
+            3.1062316707775905E-20, 3.140411706412999E-20, 3.174895674085097E-20, 3.2096884050352357E-20,
+            3.2447948726504914E-20, 3.280220198230601E-20, 3.315969657063137E-20, 3.352048684827223E-20,
+            3.388462884347689E-20, 3.4252180327233346E-20, 3.4623200888548644E-20, 3.4997752014001677E-20,
+            3.537589717186906E-20, 3.5757701901149035E-20, 3.61432339058358E-20, 3.65325631548274E-20,
+            3.692576198788357E-20, 3.732290522808698E-20, 3.7724070301302117E-20, 3.812933736317104E-20,
+            3.8538789434235234E-20, 3.895251254382786E-20, 3.93705958834424E-20, 3.979313197035144E-20,
+            4.022021682232577E-20, 4.0651950144388133E-20, 4.1088435528630944E-20, 4.152978066823271E-20,
+            4.197609758692658E-20, 4.242750288530745E-20, 4.2884118005513604E-20, 4.334606951598745E-20,
+            4.381348941821026E-20, 4.428651547752084E-20, 4.476529158037235E-20, 4.5249968120658306E-20,
+            4.574070241805442E-20, 4.6237659171683015E-20, 4.674101095281837E-20, 4.7250938740823415E-20,
+            4.776763250705122E-20, 4.8291291852069895E-20, 4.8822126702292804E-20, 4.936035807293385E-20,
+            4.990621890518202E-20, 5.045995498662554E-20, 5.1021825965285324E-20, 5.159210646917826E-20,
+            5.2171087345169234E-20, 5.2759077033045284E-20, 5.335640309332586E-20, 5.396341391039951E-20,
+            5.458048059625925E-20, 5.520799912453558E-20, 5.584639272987383E-20, 5.649611461419377E-20,
+            5.715765100929071E-20, 5.783152465495663E-20, 5.851829876379432E-20, 5.921858155879171E-20,
+            5.99330314883387E-20, 6.066236324679689E-20, 6.1407354758435E-20, 6.216885532049976E-20,
+            6.294779515010373E-20, 6.37451966432144E-20, 6.456218773753799E-20, 6.54000178818891E-20,
+            6.626007726330934E-20, 6.714392014514662E-20, 6.80532934473017E-20, 6.8990172088133E-20,
+            6.99568031585645E-20, 7.095576179487843E-20, 7.199002278894508E-20, 7.306305373910546E-20,
+            7.417893826626688E-20, 7.534254213417312E-20, 7.655974217114297E-20, 7.783774986341285E-20,
+            7.918558267402951E-20, 8.06147755373533E-20, 8.214050276981807E-20, 8.378344597828052E-20,
+            8.557312924967816E-20, 8.75544596695901E-20, 8.980238805770688E-20, 9.246247142115109E-20,
+            9.591964134495172E-20, 1.0842021724855044E-19};
 
         /**
          * Specialisation which multiplies the standard exponential result by a specified mean.
@@ -459,11 +488,11 @@ public abstract class ZigguratSampler implements SharedStateContinuousSampler {
         /** The point where the Gaussian switches from convex to concave. */
         private static final int J_INFLECTION = 205;
         /** Used for largest deviations of f(x) from y_i. This is negated on purpose. */
-        private static final long MAX_IE = -2269182951627975918L;
+        private static final long MAX_IE = -2269182951627976004L;
         /** Used for largest deviations of f(x) from y_i. */
-        private static final long MIN_IE = 760463704284035181L;
+        private static final long MIN_IE = 760463704284035184L;
         /** Beginning of tail. */
-        private static final double X_0 = 3.6360066255;
+        private static final double X_0 = 3.6360066255009455861;
         /** 1/X_0. */
         private static final double ONE_OVER_X_0 = 1d / X_0;
 
@@ -482,174 +511,203 @@ public abstract class ZigguratSampler implements SharedStateContinuousSampler {
                 250, 250, 249, 249, 249, 248, 248, 248, 247, 247, 247, 246, 246, 245, 244, 244, 243, 242, 240, 2, 2, 3,
                 3, 0, 0, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 1, 0, 0});
         /** The alias inverse PMF. */
-        private static final long[] IPMF = {9223372036854775807L, 1100243796532604147L, 7866600928978262881L,
-            6788754710654027089L, 9022865200181691852L, 6522434035205505475L, 4723064097359993915L,
-            3360495653216419673L, 2289663232373874393L, 1423968905551925104L, 708364817827802907L, 106102487305606492L,
-            -408333464665790208L, -853239722779020926L, -1242095211825517037L, -1585059631105792592L,
-            -1889943050287164616L, -2162852901990665326L, -2408637386594506662L, -2631196530262949902L,
-            -2833704942520918738L, -3018774289025815052L, -3188573753472182441L, -3344920681707440829L,
-            -3489349705062145773L, -3623166100042174483L, -3747487436868330185L, -3863276422712168700L,
-            -3971367044063122321L, -4072485557029853479L, -4167267476830907467L, -4256271432240150335L,
-            -4339990541927301065L, -4418861817133796561L, -4493273980372371289L, -4563574004462236379L,
-            -4630072609770443287L, -4693048910430993529L, -4752754358862853623L, -4809416110052798111L,
-            -4863239903586974371L, -4914412541515869230L, -4963104028439154501L, -5009469424769141876L,
-            -5053650458856546947L, -5095776932695070785L, -5135967952544950843L, -5174333008451188631L,
-            -5210972924952682065L, -5245980700100453012L, -5279442247516290042L, -5311437055462362013L,
-            -5342038772315636138L, -5371315728843324427L, -5399331404632497705L, -5426144845493682879L,
-            -5451811038474681565L, -5476381248265612057L, -5499903320558330825L, -5522421955752302985L,
-            -5543978956085246988L, -5564613449659052023L, -5584362093436129148L, -5603259257517445975L,
-            -5621337193070977432L, -5638626184974114133L, -5655154691220924683L, -5670949470294749069L,
-            -5686035697601828417L, -5700437072199142976L, -5714175914219797723L, -5727273255295211389L,
-            -5739748920272022600L, -5751621603810396917L, -5762908939773930926L, -5773627565914992314L,
-            -5783793183152402325L, -5793420610475612574L, -5802523835894645221L, -5811116062947594592L,
-            -5819209754516104281L, -5826816672854561136L, -5833947916825296227L, -5840613956570562553L,
-            -5846824665591787384L, -5852589350491064419L, -5857916778480708968L, -5862815203334817577L,
-            -5867292388935689664L, -5871355631762300668L, -5875011781262872391L, -5878267259039068099L,
-            -5881128076579864607L, -5883599852028866964L, -5885687825288587920L, -5887396872144944193L,
-            -5888731517955022366L, -5889695949247708370L, -5890294025706661862L, -5890529289910843690L,
-            -5890404977676009159L, -5889924026487152552L, -5889089083913561497L, -5887902514965187544L,
-            -5886366408898350160L, -5884482585690660648L, -5882252601321067956L, -5879677752995005083L,
-            -5876759083794187244L, -5873497386318817608L, -5869893206505495615L, -5865946846617000703L,
-            -5861658367354170141L, -5857027590486142268L, -5852054100063403979L, -5846737243971479915L,
-            -5841076134082348607L, -5835069647234555080L, -5828716424754558627L, -5822014871949050545L,
-            -5814963157357505615L, -5807559211080035948L, -5799800723447248431L, -5791685142338046612L,
-            -5783209670985131963L, -5774371264582507258L, -5765166627072198898L, -5755592207057629351L,
-            -5745644193442020886L, -5735318510777140130L, -5724610813433637581L, -5713516480385064197L,
-            -5702030608511931905L, -5690148005851000163L, -5677863184109376595L, -5665170350903283020L,
-            -5652063400924584736L, -5638535907000098559L, -5624581109999495711L, -5610191908627545348L,
-            -5595360848093635657L, -5580080108034221525L, -5564341489875517452L, -5548136403221361788L,
-            -5531455851545388194L, -5514290416638313566L, -5496630242181647032L, -5478465016761708394L,
-            -5459783954986630496L, -5440575777891763554L, -5420828692432362328L, -5400530368638759086L,
-            -5379667916699386572L, -5358227861294079939L, -5336196115274289941L, -5313557951078348351L,
-            -5290297970633413513L, -5266400072915204637L, -5241847420213976978L, -5216622401043707762L,
-            -5190706591719514516L, -5164080714589163015L, -5136724594099061292L, -5108617109269271995L,
-            -5079736143458208314L, -5050058530461699570L, -5019559997031867155L, -4988215101008300666L,
-            -4955997165600740840L, -4922878208651982466L, -4888828866780310778L, -4853818314258448763L,
-            -4817814175855136221L, -4780782432601640934L, -4742687321746673837L, -4703491227581398702L,
-            -4663154564978669839L, -4621635653358718847L, -4578890580370737438L, -4534873055659651863L,
-            -4489534251700544707L, -4442822631898778778L, -4394683764809052552L, -4345060121983309848L,
-            -4293890858708851568L, -4241111576153757717L, -4186654061692562932L, -4130446006804691432L,
-            -4072410698657642967L, -4012466683838341666L, -3950527400304957273L, -3886500774061817392L,
-            -3820288777467775968L, -3751786943594814089L, -3680883832433444937L, -3607460442623855428L,
-            -3531389562483238811L, -3452535052936037985L, -3370751053395794721L, -3285881101589156030L,
-            -3197757155301271700L, -3106198503156390075L, -3011010550911843739L, -2911983463883482375L,
-            -2808890647470171482L, -2701487041141041038L, -2589507199690499622L, -2472663129329060997L,
-            -2350641842139723534L, -2223102583769914387L, -2089673683729348624L, -1949948966045216354L,
-            -1803483646855866339L, -1649789631524907106L, -1488330106094837958L, -1318513295725471712L,
-            -1139685236971903433L, -951121376551959675L, -752016768184573709L, -541474585687415681L,
-            -318492605680814263L, -81947227248966622L, 169425512568350963L, 437052607277165029L, 722551297569085274L,
-            1027761939300002045L, 1354787941578333500L, 1706044619204253453L, 2084319374409947591L,
-            2492846399638817506L, 2935400169348911565L, 3416413484613541924L, 3941127949861028145L,
-            4515787798749165735L, 5147892401484995974L, 5846529325380992513L, 6622819682194933019L,
-            7490522659874903812L, 8466869998278641829L, 8216968526368126501L, 4550693915471153825L,
-            7628019504122306461L, 6605080500893076940L, 7121156327637209657L, 2484871780365768829L,
-            7179104797069433749L, 7066086283825115773L, 1516500120794063563L, 216305945442773460L, 6295963418513296140L,
-            2889316805672339623L, -2712587580543026574L, 6562498853519217374L, 7975754821145999232L,
-            -9223372036854775807L, -9223372036854775807L};
-        /** The precomputed ziggurat lengths, denoted X_i in the main text. X_i = length of ziggurat layer i. */
-        private static final double[] X = {3.94216628254e-19, 3.72049450041e-19, 3.58270244806e-19, 3.48074762365e-19,
-            3.39901771719e-19, 3.33037783603e-19, 3.27094388176e-19, 3.21835771325e-19, 3.17107585418e-19,
-            3.1280307407e-19, 3.08845206558e-19, 3.05176506241e-19, 3.01752902926e-19, 2.98539834407e-19,
-            2.95509674628e-19, 2.92639979885e-19, 2.899122587e-19, 2.87311087802e-19, 2.84823463271e-19,
-            2.82438315352e-19, 2.80146139647e-19, 2.77938712618e-19, 2.75808869214e-19, 2.73750326983e-19,
-            2.71757545434e-19, 2.69825612475e-19, 2.67950151888e-19, 2.66127247304e-19, 2.6435337928e-19,
-            2.6262537282e-19, 2.60940353352e-19, 2.59295709543e-19, 2.57689061732e-19, 2.56118234977e-19,
-            2.54581235934e-19, 2.53076232924e-19, 2.51601538678e-19, 2.50155595336e-19, 2.48736961354e-19,
-            2.47344300031e-19, 2.45976369429e-19, 2.44632013479e-19, 2.43310154111e-19, 2.42009784271e-19,
-            2.40729961704e-19, 2.39469803409e-19, 2.38228480673e-19, 2.37005214619e-19, 2.35799272207e-19,
-            2.34609962621e-19, 2.33436634011e-19, 2.32278670547e-19, 2.31135489743e-19, 2.30006540027e-19,
-            2.28891298528e-19, 2.27789269059e-19, 2.26699980275e-19, 2.25622983985e-19, 2.24557853607e-19,
-            2.23504182749e-19, 2.22461583905e-19, 2.21429687253e-19, 2.20408139549e-19, 2.19396603103e-19,
-            2.18394754837e-19, 2.17402285409e-19, 2.164188984e-19, 2.15444309566e-19, 2.14478246135e-19,
-            2.13520446164e-19, 2.12570657924e-19, 2.11628639347e-19, 2.10694157491e-19, 2.09766988055e-19,
-            2.08846914916e-19, 2.079337297e-19, 2.0702723138e-19, 2.06127225897e-19, 2.05233525809e-19,
-            2.04345949953e-19, 2.03464323137e-19, 2.02588475842e-19, 2.01718243948e-19, 2.00853468469e-19,
-            1.99993995309e-19, 1.9913967503e-19, 1.9829036263e-19, 1.97445917335e-19, 1.96606202405e-19,
-            1.95771084943e-19, 1.94940435722e-19, 1.9411412902e-19, 1.93292042452e-19, 1.92474056827e-19,
-            1.91660056003e-19, 1.90849926746e-19, 1.90043558606e-19, 1.89240843788e-19, 1.88441677035e-19,
-            1.87645955517e-19, 1.86853578721e-19, 1.8606444835e-19, 1.85278468221e-19, 1.84495544175e-19,
-            1.83715583984e-19, 1.82938497262e-19, 1.82164195388e-19, 1.81392591419e-19, 1.80623600019e-19,
-            1.7985713738e-19, 1.79093121154e-19, 1.78331470384e-19, 1.77572105435e-19, 1.76814947933e-19,
-            1.76059920701e-19, 1.753069477e-19, 1.74555953971e-19, 1.73806865576e-19, 1.73059609547e-19,
-            1.72314113829e-19, 1.71570307233e-19, 1.70828119379e-19, 1.7008748065e-19, 1.69348322146e-19,
-            1.68610575631e-19, 1.67874173493e-19, 1.67139048692e-19, 1.66405134721e-19, 1.6567236556e-19,
-            1.64940675631e-19, 1.64209999755e-19, 1.63480273116e-19, 1.62751431209e-19, 1.62023409806e-19,
-            1.61296144913e-19, 1.60569572726e-19, 1.59843629593e-19, 1.59118251972e-19, 1.58393376391e-19,
-            1.57668939404e-19, 1.56944877552e-19, 1.56221127324e-19, 1.55497625108e-19, 1.54774307158e-19,
-            1.54051109542e-19, 1.53327968107e-19, 1.52604818431e-19, 1.51881595777e-19, 1.51158235054e-19,
-            1.50434670764e-19, 1.49710836959e-19, 1.48986667191e-19, 1.48262094465e-19, 1.47537051186e-19,
-            1.46811469107e-19, 1.46085279278e-19, 1.4535841199e-19, 1.44630796717e-19, 1.43902362058e-19,
-            1.43173035676e-19, 1.42442744238e-19, 1.41711413344e-19, 1.40978967466e-19, 1.40245329873e-19,
-            1.39510422558e-19, 1.38774166165e-19, 1.38036479905e-19, 1.37297281475e-19, 1.36556486972e-19,
-            1.35814010798e-19, 1.35069765568e-19, 1.34323662007e-19, 1.33575608847e-19, 1.32825512715e-19,
-            1.32073278015e-19, 1.31318806805e-19, 1.30561998669e-19, 1.29802750579e-19, 1.29040956749e-19,
-            1.28276508483e-19, 1.2750929401e-19, 1.26739198313e-19, 1.25966102948e-19, 1.25189885844e-19,
-            1.24410421101e-19, 1.23627578765e-19, 1.22841224598e-19, 1.2205121982e-19, 1.21257420848e-19,
-            1.20459679002e-19, 1.19657840201e-19, 1.18851744634e-19, 1.18041226403e-19, 1.17226113142e-19,
-            1.16406225609e-19, 1.15581377245e-19, 1.14751373693e-19, 1.13916012285e-19, 1.13075081485e-19,
-            1.12228360281e-19, 1.11375617531e-19, 1.10516611251e-19, 1.09651087832e-19, 1.08778781199e-19,
-            1.07899411881e-19, 1.07012685997e-19, 1.06118294148e-19, 1.05215910191e-19, 1.043051899e-19,
-            1.0338576948e-19, 1.02457263929e-19, 1.01519265222e-19, 1.00571340295e-19, 9.96130287997e-20,
-            9.86438405995e-20, 9.76632529648e-20, 9.66707074276e-20, 9.56656062409e-20, 9.46473083804e-20,
-            9.36151250173e-20, 9.25683143709e-20, 9.15060758376e-20, 9.04275432677e-20, 8.93317772338e-20,
-            8.82177561023e-20, 8.70843656749e-20, 8.59303871096e-20, 8.47544827642e-20, 8.35551795085e-20,
-            8.23308489336e-20, 8.10796837291e-20, 7.97996692841e-20, 7.84885492861e-20, 7.71437837009e-20,
-            7.57624969795e-20, 7.43414135785e-20, 7.28767768074e-20, 7.13642454435e-20, 6.97987602408e-20,
-            6.81743689448e-20, 6.64839929862e-20, 6.47191103452e-20, 6.28693148131e-20, 6.09216875483e-20,
-            5.88598735756e-20, 5.66626751161e-20, 5.43018136309e-20, 5.17381717445e-20, 4.89150317224e-20,
-            4.57447418908e-20, 4.20788025686e-20, 3.76259867224e-20, 3.16285898059e-20, 0.0};
+        private static final long[] IPMF = {9223372036854775408L, 1100243796534090797L, 7866600928998383022L,
+            6788754710675124691L, 9022865200181688296L, 6522434035205502164L, 4723064097360024697L,
+            3360495653216416088L, 2289663232373870755L, 1423968905551920455L, 708364817827797893L, 106102487305601162L,
+            -408333464665794443L, -853239722779025206L, -1242095211825521362L, -1585059631105762155L,
+            -1889943050287169086L, -2162852901990669843L, -2408637386594511193L, -2631196530262954448L,
+            -2833704942520925732L, -3018774289025787439L, -3188573753472222231L, -3344920681707410914L,
+            -3489349705062150768L, -3623166100042179544L, -3747487436868335278L, -3863276422712173808L,
+            -3971367044063130866L, -4072485557029823980L, -4167267476830916554L, -4256271432240159761L,
+            -4339990541927306746L, -4418861817133802326L, -4493273980372377053L, -4563574004462246636L,
+            -4630072609770453867L, -4693048910430964891L, -4752754358862894738L, -4809416110052769505L,
+            -4863239903586985866L, -4914412541515875772L, -4963104028439161008L, -5009469424769119174L,
+            -5053650458856559461L, -5095776932695077750L, -5135967952544929007L, -5174333008451230625L,
+            -5210972924952654441L, -5245980700100460247L, -5279442247516297345L, -5311437055462369316L,
+            -5342038772315650555L, -5371315728843297107L, -5399331404632512666L, -5426144845448965104L,
+            -5451811038519422589L, -5476381248265593008L, -5499903320558339045L, -5522421955752311307L,
+            -5543978956085263616L, -5564613449659060480L, -5584362093436146354L, -5603259257517428627L,
+            -5621337193070986365L, -5638626184974132325L, -5655154691220933854L, -5670949470294763073L,
+            -5686035697601807766L, -5700437072199152453L, -5714175914219812272L, -5727273255295221103L,
+            -5739748920271997489L, -5751621603810411941L, -5762908939773946223L, -5773627565915007849L,
+            -5783793183152377622L, -5793420610475628449L, -5802523835894661300L, -5811116062947570228L,
+            -5819209754516120768L, -5826816672854571802L, -5833947916825278195L, -5840613956570608249L,
+            -5846824665591763395L, -5852589350491075357L, -5857916778480726477L, -5862815203334800430L,
+            -5867292388935742441L, -5871355631762283997L, -5875011781262890819L, -5878267259039093710L,
+            -5881128076579883546L, -5883599852028851382L, -5885687825288565257L, -5887396872144963778L,
+            -5888731517955042223L, -5889695949247728499L, -5890294025706689822L, -5890529289910829504L,
+            -5890404977675987449L, -5889924026487208528L, -5889089083913555992L, -5887902514965209240L,
+            -5886366408898372127L, -5884482585690639756L, -5882252601321090366L, -5879677752995027766L,
+            -5876759083794175305L, -5873497386318840733L, -5869893206505510263L, -5865946846617024340L,
+            -5861658367354159190L, -5857027590486131555L, -5852054100063428398L, -5846737243971504641L,
+            -5841076134082373571L, -5835069647234580384L, -5828716424754549310L, -5822014871949021959L,
+            -5814963157357531601L, -5807559211080072146L, -5799800723447230025L, -5791685142338073347L,
+            -5783209670985158971L, -5774371264582489329L, -5765166627072226519L, -5755592207057667866L,
+            -5745644193442049188L, -5735318510777133844L, -5724610813433666496L, -5713516480340333005L,
+            -5702030608556698118L, -5690148005851018661L, -5677863184109371808L, -5665170350903313433L,
+            -5652063400924580562L, -5638535907000141432L, -5624581109999480439L, -5610191908627599865L,
+            -5595360848093632709L, -5580080108034218849L, -5564341489875550045L, -5548136403221394654L,
+            -5531455851545399204L, -5514290416593586870L, -5496630242226406575L, -5478465016761742826L,
+            -5459783954986665201L, -5440575777891777017L, -5420828692432397919L, -5400530368638773571L,
+            -5379667916699401670L, -5358227861294116825L, -5336196115274292307L, -5313557951078385986L,
+            -5290297970633451489L, -5266400072915222391L, -5241847420214015772L, -5216622401043726607L,
+            -5190706591719533973L, -5164080714589203240L, -5136724594099067134L, -5108617109269313037L,
+            -5079736143458214973L, -5050058530461741430L, -5019559997031891994L, -4988215100963583032L,
+            -4955997165645492083L, -4922878208652041825L, -4888828866780320026L, -4853818314258475851L,
+            -4817814175855179990L, -4780782432601701861L, -4742687321746719241L, -4703491227581444720L,
+            -4663154564978699244L, -4621635653358766431L, -4578890580370785840L, -4534873055659683516L,
+            -4489534251700611902L, -4442822631898829564L, -4394683764809104088L, -4345060121983362610L,
+            -4293890858708922851L, -4241111576153830158L, -4186654061692619033L, -4130446006804747670L,
+            -4072410698657718678L, -4012466683838401105L, -3950527400305017938L, -3886500774061896578L,
+            -3820288777467837180L, -3751786943594897634L, -3680883832433527802L, -3607460442623922090L,
+            -3531389562483324266L, -3452535052891361699L, -3370751053395887939L, -3285881101633968096L,
+            -3197757155301365465L, -3106198503156485339L, -3011010550911937371L, -2911983463883581047L,
+            -2808890647470271789L, -2701487041141150061L, -2589507199690603472L, -2472663129329160218L,
+            -2350641842139870417L, -2223102583770035263L, -2089673683684728595L, -1949948966090106873L,
+            -1803483646855993757L, -1649789631480328207L, -1488330106139747683L, -1318513295725618200L,
+            -1139685236927327128L, -951121376596854700L, -752016768184775899L, -541474585642866346L,
+            -318492605725778472L, -81947227249193332L, 169425512612864612L, 437052607232193594L, 722551297568810077L,
+            1027761939299714316L, 1354787941622770469L, 1706044619203941749L, 2084319374409574060L,
+            2492846399593711370L, 2935400169348532576L, 3416413484613111455L, 3941127949860576155L,
+            4515787798793437894L, 5147892401439714413L, 5846529325380405959L, 6622819682216655291L,
+            7490522659874166085L, 8466869998277892108L, 8216968526387345482L, 4550693915488934669L,
+            7628019504138977223L, 6605080500908005863L, 7121156327650272532L, 2484871780331574356L,
+            7179104797032803433L, 7066086283830045340L, 1516500120817362978L, 216305945438803570L, 6295963418525324512L,
+            2889316805630113239L, -2712587580533804137L, 6562498853538167124L, 7975754821147501243L,
+            -9223372036854775808L, -9223372036854775808L};
+        /**
+         * The precomputed ziggurat lengths, denoted X_i in the main text. X_i = length of
+         * ziggurat layer i.
+         */
+        private static final double[] X = {3.9421662825398133E-19, 3.720494500411901E-19, 3.582702448062868E-19,
+            3.480747623654025E-19, 3.3990177171882136E-19, 3.330377836034014E-19, 3.270943881761755E-19,
+            3.21835771324951E-19, 3.171075854184043E-19, 3.1280307407034065E-19, 3.088452065580402E-19,
+            3.051765062410735E-19, 3.01752902925846E-19, 2.985398344070532E-19, 2.9550967462801797E-19,
+            2.9263997988491663E-19, 2.8991225869977476E-19, 2.873110878022629E-19, 2.8482346327101335E-19,
+            2.824383153519439E-19, 2.801461396472703E-19, 2.7793871261807797E-19, 2.758088692141121E-19,
+            2.737503269830876E-19, 2.7175754543391047E-19, 2.6982561247538484E-19, 2.6795015188771505E-19,
+            2.6612724730440033E-19, 2.6435337927976633E-19, 2.626253728202844E-19, 2.609403533522414E-19,
+            2.5929570954331E-19, 2.5768906173214726E-19, 2.561182349771961E-19, 2.545812359339336E-19,
+            2.530762329237246E-19, 2.51601538677984E-19, 2.501555953364619E-19, 2.487369613540316E-19,
+            2.4734430003079206E-19, 2.4597636942892726E-19, 2.446320134791245E-19, 2.4331015411139206E-19,
+            2.4200978427132955E-19, 2.407299617044588E-19, 2.3946980340903347E-19, 2.3822848067252674E-19,
+            2.37005214619318E-19, 2.357992722074133E-19, 2.346099626206997E-19, 2.3343663401054455E-19,
+            2.322786705467384E-19, 2.3113548974303765E-19, 2.300065400270424E-19, 2.2889129852797606E-19,
+            2.2778926905921897E-19, 2.266999802752732E-19, 2.2562298398527416E-19, 2.245578536072726E-19,
+            2.235041827493391E-19, 2.2246158390513294E-19, 2.214296872529625E-19, 2.2040813954857555E-19,
+            2.19396603102976E-19, 2.183947548374962E-19, 2.1740228540916853E-19, 2.164188984001652E-19,
+            2.1544430956570613E-19, 2.1447824613540345E-19, 2.1352044616350571E-19, 2.1257065792395107E-19,
+            2.1162863934653125E-19, 2.1069415749082026E-19, 2.0976698805483467E-19, 2.0884691491567363E-19,
+            2.0793372969963634E-19, 2.0702723137954107E-19, 2.061272258971713E-19, 2.0523352580895635E-19,
+            2.0434594995315797E-19, 2.0346432313698148E-19, 2.0258847584216418E-19, 2.0171824394771313E-19,
+            2.008534684685753E-19, 1.9999399530912015E-19, 1.9913967503040585E-19, 1.9829036263028144E-19,
+            1.9744591733545175E-19, 1.9660620240469857E-19, 1.9577108494251485E-19, 1.9494043572246307E-19,
+            1.941141290196216E-19, 1.9329204245152935E-19, 1.9247405682708168E-19, 1.9166005600287074E-19,
+            1.9084992674649826E-19, 1.900435586064234E-19, 1.8924084378793725E-19, 1.8844167703488436E-19,
+            1.8764595551677749E-19, 1.868535787209745E-19, 1.8606444834960934E-19, 1.8527846822098793E-19,
+            1.8449554417517928E-19, 1.8371558398354868E-19, 1.8293849726199566E-19, 1.8216419538767393E-19,
+            1.8139259141898448E-19, 1.8062360001864453E-19, 1.7985713737964743E-19, 1.7909312115393845E-19,
+            1.78331470383642E-19, 1.7757210543468428E-19, 1.7681494793266395E-19, 1.760599207008314E-19,
+            1.753069477000441E-19, 1.7455595397057217E-19, 1.7380686557563475E-19, 1.7305960954655264E-19,
+            1.7231411382940904E-19, 1.7157030723311378E-19, 1.7082811937877138E-19, 1.7008748065025788E-19,
+            1.6934832214591352E-19, 1.686105756312635E-19, 1.6787417349268046E-19, 1.6713904869190636E-19,
+            1.6640513472135291E-19, 1.6567236556010242E-19, 1.6494067563053266E-19, 1.6420999975549115E-19,
+            1.6348027311594532E-19, 1.627514312090366E-19, 1.6202340980646725E-19, 1.6129614491314931E-19,
+            1.605695727260459E-19, 1.598436295931348E-19, 1.591182519724249E-19, 1.5839337639095554E-19,
+            1.57668939403708E-19, 1.569448775523589E-19, 1.562211273238026E-19, 1.554976251083707E-19,
+            1.547743071576727E-19, 1.540511095419833E-19, 1.5332796810709688E-19, 1.5260481843056974E-19,
+            1.5188159577726683E-19, 1.5115823505412761E-19, 1.5043467076406199E-19, 1.4971083695888395E-19,
+            1.4898666719118714E-19, 1.4826209446506113E-19, 1.4753705118554365E-19, 1.468114691066983E-19,
+            1.4608527927820112E-19, 1.453584119903145E-19, 1.4463079671711862E-19, 1.4390236205786415E-19,
+            1.4317303567630177E-19, 1.4244274423783481E-19, 1.4171141334433217E-19, 1.4097896746642792E-19,
+            1.4024532987312287E-19, 1.3951042255849034E-19, 1.3877416616527576E-19, 1.3803647990516385E-19,
+            1.3729728147547174E-19, 1.3655648697200824E-19, 1.3581401079782068E-19, 1.35069765567529E-19,
+            1.3432366200692418E-19, 1.3357560884748263E-19, 1.3282551271542047E-19, 1.3207327801488087E-19,
+            1.3131880680481524E-19, 1.3056199866908076E-19, 1.2980275057923788E-19, 1.2904095674948608E-19,
+            1.2827650848312727E-19, 1.2750929400989213E-19, 1.2673919831340482E-19, 1.2596610294799512E-19,
+            1.2518988584399374E-19, 1.2441042110056523E-19, 1.2362757876504165E-19, 1.2284122459762072E-19,
+            1.2205121982017852E-19, 1.2125742084782245E-19, 1.2045967900166973E-19, 1.196578402011802E-19,
+            1.1885174463419555E-19, 1.180412264026409E-19, 1.1722611314162064E-19, 1.164062256093911E-19,
+            1.1558137724540874E-19, 1.1475137369333185E-19, 1.1391601228549047E-19, 1.1307508148492592E-19,
+            1.1222836028063025E-19, 1.1137561753107903E-19, 1.1051661125053526E-19, 1.0965108783189755E-19,
+            1.0877878119905372E-19, 1.0789941188076655E-19, 1.070126859970364E-19, 1.0611829414763286E-19,
+            1.0521591019102928E-19, 1.0430518990027552E-19, 1.0338576948035472E-19, 1.0245726392923699E-19,
+            1.015192652220931E-19, 1.0057134029488235E-19, 9.961302879967281E-20, 9.864384059945991E-20,
+            9.766325296475582E-20, 9.667070742762345E-20, 9.566560624086667E-20, 9.464730838043321E-20,
+            9.361512501732351E-20, 9.256831437088728E-20, 9.150607583763877E-20, 9.042754326772572E-20,
+            8.933177723376368E-20, 8.821775610232788E-20, 8.708436567489232E-20, 8.593038710961216E-20,
+            8.475448276424435E-20, 8.355517950846234E-20, 8.233084893358536E-20, 8.107968372912985E-20,
+            7.979966928413386E-20, 7.848854928607274E-20, 7.714378370093469E-20, 7.576249697946757E-20,
+            7.434141357848533E-20, 7.287677680737843E-20, 7.136424544352537E-20, 6.979876024076107E-20,
+            6.817436894479905E-20, 6.648399298619854E-20, 6.471911034516277E-20, 6.28693148131037E-20,
+            6.092168754828126E-20, 5.885987357557682E-20, 5.666267511609098E-20, 5.430181363089457E-20,
+            5.173817174449422E-20, 4.8915031722398545E-20, 4.57447418907553E-20, 4.2078802568583416E-20,
+            3.762598672240476E-20, 3.162858980588188E-20, 0.0};
         /** Overhang table. Y_i = f(X_i). */
-        private static final double[] Y = {1.45984107966e-22, 3.00666134279e-22, 4.61297288151e-22, 6.26633500492e-22,
-            7.95945247619e-22, 9.68746550217e-22, 1.14468770024e-21, 1.32350363044e-21, 1.50498576921e-21,
-            1.68896530007e-21, 1.87530253827e-21, 2.06387984237e-21, 2.25459669136e-21, 2.44736615188e-21,
-            2.64211227278e-21, 2.83876811879e-21, 3.03727425675e-21, 3.23757757e-21, 3.43963031579e-21,
-            3.6433893658e-21, 3.84881558689e-21, 4.05587333095e-21, 4.26453001043e-21, 4.47475574223e-21,
-            4.68652304654e-21, 4.89980659028e-21, 5.11458296721e-21, 5.3308305082e-21, 5.5485291167e-21,
-            5.76766012527e-21, 5.98820616992e-21, 6.21015107954e-21, 6.43347977823e-21, 6.65817819857e-21,
-            6.88423320459e-21, 7.1116325228e-21, 7.34036468049e-21, 7.57041895029e-21, 7.80178530014e-21,
-            8.03445434816e-21, 8.26841732173e-21, 8.50366602039e-21, 8.74019278201e-21, 8.97799045203e-21,
-            9.21705235531e-21, 9.45737227039e-21, 9.69894440593e-21, 9.94176337898e-21, 1.01858241951e-20,
-            1.04311222301e-20, 1.0677653213e-20, 1.09254132104e-20, 1.11743986124e-20, 1.14246061187e-20,
-            1.16760327269e-20, 1.19286757204e-20, 1.21825326583e-20, 1.24376013654e-20, 1.2693879923e-20,
-            1.29513666605e-20, 1.32100601473e-20, 1.34699591858e-20, 1.37310628045e-20, 1.39933702514e-20,
-            1.42568809885e-20, 1.4521594686e-20, 1.47875112175e-20, 1.50546306552e-20, 1.53229532653e-20,
-            1.55924795044e-20, 1.58632100153e-20, 1.61351456238e-20, 1.64082873355e-20, 1.66826363327e-20,
-            1.69581939719e-20, 1.72349617811e-20, 1.75129414576e-20, 1.77921348663e-20, 1.80725440373e-20,
-            1.83541711644e-20, 1.86370186038e-20, 1.89210888728e-20, 1.92063846482e-20, 1.94929087658e-20,
-            1.97806642193e-20, 2.00696541597e-20, 2.03598818948e-20, 2.06513508884e-20, 2.09440647607e-20,
-            2.12380272876e-20, 2.15332424009e-20, 2.18297141884e-20, 2.21274468943e-20, 2.24264449191e-20,
-            2.27267128206e-20, 2.30282553143e-20, 2.33310772738e-20, 2.36351837324e-20, 2.39405798832e-20,
-            2.42472710808e-20, 2.45552628422e-20, 2.48645608479e-20, 2.5175170944e-20, 2.54870991431e-20,
-            2.58003516259e-20, 2.61149347436e-20, 2.64308550193e-20, 2.67481191499e-20, 2.70667340088e-20,
-            2.73867066474e-20, 2.77080442982e-20, 2.80307543767e-20, 2.83548444847e-20, 2.86803224123e-20,
-            2.90071961414e-20, 2.93354738484e-20, 2.96651639078e-20, 2.99962748948e-20, 3.03288155897e-20,
-            3.06627949809e-20, 3.09982222687e-20, 3.13351068696e-20, 3.16734584202e-20, 3.20132867816e-20,
-            3.23546020438e-20, 3.26974145302e-20, 3.30417348029e-20, 3.33875736673e-20, 3.37349421775e-20,
-            3.40838516421e-20, 3.44343136293e-20, 3.4786339973e-20, 3.51399427794e-20, 3.54951344328e-20,
-            3.58519276026e-20, 3.62103352501e-20, 3.65703706358e-20, 3.69320473266e-20, 3.7295379204e-20,
-            3.76603804721e-20, 3.80270656658e-20, 3.83954496597e-20, 3.87655476775e-20, 3.91373753011e-20,
-            3.95109484807e-20, 3.98862835454e-20, 4.02633972133e-20, 4.06423066034e-20, 4.10230292468e-20,
-            4.14055830991e-20, 4.1789986553e-20, 4.21762584518e-20, 4.25644181026e-20, 4.29544852916e-20,
-            4.33464802983e-20, 4.3740423912e-20, 4.41363374476e-20, 4.45342427632e-20, 4.49341622781e-20,
-            4.53361189911e-20, 4.5740136501e-20, 4.61462390263e-20, 4.65544514274e-20, 4.69647992292e-20,
-            4.73773086444e-20, 4.77920065987e-20, 4.82089207569e-20, 4.86280795501e-20, 4.90495122048e-20,
-            4.94732487728e-20, 4.98993201633e-20, 5.03277581761e-20, 5.07585955372e-20, 5.11918659356e-20,
-            5.16276040629e-20, 5.20658456539e-20, 5.25066275307e-20, 5.29499876488e-20, 5.33959651452e-20,
-            5.38446003902e-20, 5.42959350421e-20, 5.47500121042e-20, 5.52068759864e-20, 5.566657257e-20,
-            5.61291492763e-20, 5.65946551399e-20, 5.70631408865e-20, 5.75346590156e-20, 5.80092638886e-20,
-            5.8487011823e-20, 5.89679611927e-20, 5.94521725351e-20, 5.99397086661e-20, 6.04306348026e-20,
-            6.09250186942e-20, 6.14229307644e-20, 6.19244442624e-20, 6.24296354262e-20, 6.29385836583e-20,
-            6.34513717154e-20, 6.39680859128e-20, 6.44888163458e-20, 6.5013657129e-20, 6.55427066567e-20,
-            6.60760678847e-20, 6.66138486374e-20, 6.71561619424e-20, 6.7703126396e-20, 6.82548665622e-20,
-            6.88115134113e-20, 6.93732047997e-20, 6.9940085999e-20, 7.05123102793e-20, 7.10900395534e-20,
-            7.16734450906e-20, 7.22627083097e-20, 7.28580216611e-20, 7.3459589613e-20, 7.4067629755e-20,
-            7.46823740371e-20, 7.53040701672e-20, 7.59329831907e-20, 7.65693972825e-20, 7.72136177895e-20,
-            7.78659735664e-20, 7.85268196595e-20, 7.91965404039e-20, 7.9875553017e-20, 8.05643117889e-20,
-            8.12633129964e-20, 8.19731007037e-20, 8.26942736526e-20, 8.34274935088e-20, 8.41734948075e-20,
-            8.49330970528e-20, 8.57072195782e-20, 8.64968999859e-20, 8.73033172957e-20, 8.81278213789e-20,
-            8.89719709282e-20, 8.98375832393e-20, 9.07268006979e-20, 9.16421814841e-20, 9.25868264067e-20,
-            9.35645614803e-20, 9.45802100126e-20, 9.56400155509e-20, 9.67523347705e-20, 9.79288516978e-20,
-            9.91869058575e-20, 1.00554562713e-19, 1.02084073773e-19, 1.03903609932e-19, 1.08420217249e-19};
+        private static final double[] Y = {1.4598410796619063E-22, 3.0066613427942797E-22, 4.612972881510347E-22,
+            6.266335004923436E-22, 7.959452476188154E-22, 9.687465502170504E-22, 1.144687700237944E-21,
+            1.3235036304379167E-21, 1.504985769205313E-21, 1.6889653000719298E-21, 1.8753025382711626E-21,
+            2.063879842369519E-21, 2.2545966913644708E-21, 2.44736615188018E-21, 2.6421122727763533E-21,
+            2.8387681187879908E-21, 3.0372742567457284E-21, 3.237577569998659E-21, 3.439630315794878E-21,
+            3.64338936579978E-21, 3.848815586891231E-21, 4.0558733309492775E-21, 4.264530010428359E-21,
+            4.474755742230507E-21, 4.686523046535558E-21, 4.899806590277526E-21, 5.114582967210549E-21,
+            5.330830508204617E-21, 5.548529116703176E-21, 5.767660125269048E-21, 5.988206169917846E-21,
+            6.210151079544222E-21, 6.433479778225721E-21, 6.65817819857139E-21, 6.884233204589318E-21,
+            7.11163252279571E-21, 7.340364680490309E-21, 7.570418950288642E-21, 7.801785300137974E-21,
+            8.034454348157002E-21, 8.268417321733312E-21, 8.503666020391502E-21, 8.740192782010952E-21,
+            8.97799045202819E-21, 9.217052355306144E-21, 9.457372270392882E-21, 9.698944405926943E-21,
+            9.941763378975842E-21, 1.0185824195119818E-20, 1.043112223011477E-20, 1.0677653212987396E-20,
+            1.0925413210432004E-20, 1.1174398612392891E-20, 1.1424606118728715E-20, 1.1676032726866302E-20,
+            1.1928675720361027E-20, 1.2182532658289373E-20, 1.2437601365406785E-20, 1.2693879923010674E-20,
+            1.2951366660454145E-20, 1.321006014726146E-20, 1.3469959185800733E-20, 1.3731062804473644E-20,
+            1.3993370251385596E-20, 1.4256880988463136E-20, 1.452159468598837E-20, 1.4787511217522902E-20,
+            1.505463065519617E-20, 1.5322953265335218E-20, 1.5592479504415048E-20, 1.5863210015310328E-20,
+            1.6135145623830982E-20, 1.6408287335525592E-20, 1.6682636332737932E-20, 1.6958193971903124E-20,
+            1.7234961781071113E-20, 1.7512941457646084E-20, 1.7792134866331487E-20, 1.807254403727107E-20,
+            1.8354171164377277E-20, 1.8637018603838945E-20, 1.8921088872801004E-20, 1.9206384648209468E-20,
+            1.9492908765815636E-20, 1.9780664219333857E-20, 2.006965415974784E-20, 2.035988189476086E-20,
+            2.0651350888385696E-20, 2.094406476067054E-20, 2.1238027287557466E-20, 2.1533242400870487E-20,
+            2.1829714188430474E-20, 2.2127446894294597E-20, 2.242644491911827E-20, 2.2726712820637798E-20,
+            2.3028255314272276E-20, 2.3331077273843558E-20, 2.3635183732413286E-20, 2.3940579883236352E-20,
+            2.4247271080830277E-20, 2.455526284216033E-20, 2.4864560847940368E-20, 2.5175170944049622E-20,
+            2.548709914306593E-20, 2.5800351625915997E-20, 2.6114934743643687E-20, 2.6430855019297323E-20,
+            2.674811914993741E-20, 2.7066734008766247E-20, 2.7386706647381193E-20, 2.770804429815356E-20,
+            2.803075437673527E-20, 2.835484448469575E-20, 2.868032241229163E-20, 2.9007196141372126E-20,
+            2.933547384842322E-20, 2.966516390775399E-20, 2.9996274894828624E-20, 3.0328815589748056E-20,
+            3.066279498088529E-20, 3.099822226867876E-20, 3.133510686958861E-20, 3.167345842022056E-20,
+            3.201328678162299E-20, 3.235460204376261E-20, 3.2697414530184806E-20, 3.304173480286495E-20,
+            3.338757366725735E-20, 3.373494217754894E-20, 3.408385164212521E-20, 3.443431362925624E-20,
+            3.4786339973011376E-20, 3.5139942779411164E-20, 3.549513443282617E-20, 3.585192760263246E-20,
+            3.621033525013417E-20, 3.6570370635764384E-20, 3.693204732657588E-20, 3.729537920403425E-20,
+            3.76603804721264E-20, 3.8027065665798284E-20, 3.839544965973665E-20, 3.876554767751017E-20,
+            3.9137375301086406E-20, 3.951094848074217E-20, 3.988628354538543E-20, 4.0263397213308566E-20,
+            4.064230660339354E-20, 4.1023029246790967E-20, 4.140558309909644E-20, 4.178998655304882E-20,
+            4.217625845177682E-20, 4.256441810262176E-20, 4.29544852915662E-20, 4.334648029830012E-20,
+            4.3740423911958146E-20, 4.4136337447563716E-20, 4.4534242763218286E-20, 4.4934162278076256E-20,
+            4.5336118991149025E-20, 4.5740136500984466E-20, 4.614623902627128E-20, 4.655445142742113E-20,
+            4.696479922918509E-20, 4.737730864436494E-20, 4.779200659868417E-20, 4.820892075688811E-20,
+            4.8628079550147814E-20, 4.9049512204847653E-20, 4.9473248772842596E-20, 4.9899320163277674E-20,
+            5.032775817606897E-20, 5.0758595537153414E-20, 5.1191865935622696E-20, 5.162760406286606E-20,
+            5.2065845653856416E-20, 5.2506627530725194E-20, 5.294998764878345E-20, 5.3395965145159426E-20,
+            5.3844600390237576E-20, 5.429593504209936E-20, 5.475001210418387E-20, 5.520687598640507E-20,
+            5.566657256998382E-20, 5.612914927627579E-20, 5.659465513990248E-20, 5.706314088652056E-20,
+            5.753465901559692E-20, 5.800926388859122E-20, 5.848701182298758E-20, 5.89679611926598E-20,
+            5.945217253510347E-20, 5.99397086661226E-20, 6.043063480261893E-20, 6.092501869420053E-20,
+            6.142293076440286E-20, 6.192444426240153E-20, 6.242963542619394E-20, 6.293858365833621E-20,
+            6.345137171544756E-20, 6.396808591283496E-20, 6.448881634575274E-20, 6.501365712899535E-20,
+            6.554270665673171E-20, 6.607606788473072E-20, 6.66138486374042E-20, 6.715616194241298E-20,
+            6.770312639595058E-20, 6.825486656224641E-20, 6.881151341132782E-20, 6.937320479965968E-20,
+            6.994008599895911E-20, 7.05123102792795E-20, 7.109003955339717E-20, 7.16734450906448E-20,
+            7.226270830965578E-20, 7.285802166105734E-20, 7.34595896130358E-20, 7.406762975496755E-20,
+            7.468237403705282E-20, 7.530407016722667E-20, 7.593298319069855E-20, 7.656939728248375E-20,
+            7.721361778948768E-20, 7.786597356641702E-20, 7.852681965945675E-20, 7.919654040385056E-20,
+            7.987555301703797E-20, 8.056431178890163E-20, 8.126331299642618E-20, 8.19731007037063E-20,
+            8.269427365263403E-20, 8.342749350883679E-20, 8.417349480745342E-20, 8.493309705283207E-20,
+            8.57072195782309E-20, 8.64968999859307E-20, 8.730331729565533E-20, 8.81278213788595E-20,
+            8.897197092819667E-20, 8.983758323931406E-20, 9.072680069786954E-20, 9.164218148406354E-20,
+            9.258682640670276E-20, 9.356456148027886E-20, 9.458021001263618E-20, 9.564001555085036E-20,
+            9.675233477050313E-20, 9.792885169780883E-20, 9.918690585753133E-20, 1.0055456271343397E-19,
+            1.0208407377305566E-19, 1.0390360993240711E-19, 1.0842021724855044E-19};
 
         /** Exponential sampler used for the long tail. */
         private final SharedStateContinuousSampler exponential;
diff --git a/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/LevySamplerTest.java b/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/LevySamplerTest.java
index 907e1b5..0d32410 100644
--- a/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/LevySamplerTest.java
+++ b/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/LevySamplerTest.java
@@ -84,11 +84,11 @@ public class LevySamplerTest {
         // Force the underlying ZigguratSampler.NormalizedGaussian to create a large
         // sample in the tail of the distribution.
         // The first two -1,-1 values enters the tail of the distribution.
-        // Here an exponential is added to 3.6360066255.
-        // The exponential also requires -1,-1 to recurse. Each recursion adds 7.56927469415
+        // Here an exponential is added to 3.6360066255009455861.
+        // The exponential also requires -1,-1 to recurse. Each recursion adds 7.569274694148063
         // to the exponential. A value of 0 stops recursion with a sample of 0.
         // Two exponentials are required: x and y.
-        // The exponential is multiplied by 0.275027001597525 to create x.
+        // The exponential is multiplied by 0.27502700159745347 to create x.
         // The condition 2y >= x^x must be true to return x.
         // Create x = 4 * 7.57 and y = 16 * 7.57
         final long[] sequence = {
@@ -112,7 +112,7 @@ public class LevySamplerTest {
                 }
             }, location, scale);
         // The tail of the zigguart should be approximately s=11.963
-        final double s = 4 * 7.56927469415 * 0.275027001597525 + 3.6360066255;
+        final double s = 4 * 7.569274694148063 * 0.27502700159745347 + 3.6360066255009455861;
         // expected is 1/s^2 = 0.006987
         // So the sampler never achieves the lower bound of zero.
         // It requires an extreme deviate from the Gaussian.
diff --git a/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/StableSamplerTest.java b/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/StableSamplerTest.java
index ca238d3..f56dbc7 100644
--- a/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/StableSamplerTest.java
+++ b/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/StableSamplerTest.java
@@ -59,9 +59,11 @@ public class StableSamplerTest {
      * This is the gap between the 2^53 dyadic rationals in [0, 1). */
     private static final double DU = 0x1.0p-53;
     /** The smallest non-zero sample from the ZigguratSampler.Exponential sampler. */
-    private static final double SMALL_W = 7.39737323516E-19;
+    private static final double SMALL_W = 7.397373235160728E-19;
+    /** A tail sample from the ZigguratSampler.Exponential after 1 recursions of the sample method.  */
+    private static final double TAIL_W = 7.569274694148063;
     /** A largest sample from the ZigguratSampler.Exponential after 4 recursions of the sample method.  */
-    private static final double LARGE_W = 4 * 7.56927469415;
+    private static final double LARGE_W = 4 * TAIL_W;
     /** The smallest value for alpha where 1 - (1-alpha) = alpha. */
     private static final double SMALLEST_ALPHA = 1.0 - nextDown(1.0);
 
@@ -1341,7 +1343,7 @@ public class StableSamplerTest {
         // The value with all bits set generates phi/2 -> pi/4.
         // Add a long to create a big value for w of 5.
         // The parameters create cancellation in the numerator of z to create a negative z.
-        final long[] longs = {Long.MAX_VALUE, 6092639261718834176L};
+        final long[] longs = {Long.MAX_VALUE, 6092639261715210240L};
 
         final double phiby2 = PI_4 - PI_4 * DU;
         final double w = 5.0;
@@ -1502,7 +1504,7 @@ public class StableSamplerTest {
 
         // Add a long to create an ordinary value for w of 1.0.
         // u -> -pi/4
-        final long[] longs1 = {Long.MIN_VALUE + (1 << 10), 1446480648965498882L};
+        final long[] longs1 = {Long.MIN_VALUE + (1 << 10), 1446480648965178882L};
         assertUWSequence(new double[] {
             -PI_4 + PI_4 * DU, 1.0,
         }, longs1);
@@ -1511,7 +1513,7 @@ public class StableSamplerTest {
         Assert.assertTrue("Sampler did not recover", isFinite(x1));
 
         // u -> pi/4
-        final long[] longs2 = {Long.MAX_VALUE, 1446480648965498882L};
+        final long[] longs2 = {Long.MAX_VALUE, 1446480648965178882L};
         assertUWSequence(new double[] {
             PI_4 - PI_4 * DU, 1.0,
         }, longs2);
@@ -1614,11 +1616,11 @@ public class StableSamplerTest {
 
             // Add non extreme exponential deviate to test only extreme u
             // phi/2 -> -pi/4, w=1
-            Long.MIN_VALUE + (1 << 10), 1446480648965498882L,
+            Long.MIN_VALUE + (1 << 10), 1446480648965178882L,
             // phi/2 -> pi/4, w=1
-            Long.MAX_VALUE, 1446480648965498882L,
+            Long.MAX_VALUE, 1446480648965178882L,
             // phi/2=0, w=1
-            0, 1446480648965498882L,
+            0, 1446480648965178882L,
 
             // Add non extreme uniform deviate to test only extreme w
             // phi/2=pi/5, w=0
@@ -1732,15 +1734,15 @@ public class StableSamplerTest {
         // Extremes of the exponential sampler
         Assert.assertEquals(0, ZigguratSampler.Exponential.of(
                 createRngWithSequence(0L)).sample(), 0.0);
-        Assert.assertEquals(7.39737323516E-19, ZigguratSampler.Exponential.of(
+        Assert.assertEquals(SMALL_W, ZigguratSampler.Exponential.of(
                 createRngWithSequence(1)).sample(), 0.0);
         Assert.assertEquals(1.0, ZigguratSampler.Exponential.of(
-                createRngWithSequence(1446480648965498882L)).sample(), 0.0);
+                createRngWithSequence(1446480648965178882L)).sample(), 0.0);
         Assert.assertEquals(5.0, ZigguratSampler.Exponential.of(
-                createRngWithSequence(6092639261718834176L)).sample(), 0.0);
-        Assert.assertEquals(7.56927469415, ZigguratSampler.Exponential.of(
+                createRngWithSequence(6092639261715210240L)).sample(), 0.0);
+        Assert.assertEquals(TAIL_W, ZigguratSampler.Exponential.of(
                 createRngWithSequence(-1, -1, 0)).sample(), 0.0);
-        Assert.assertEquals(3 * 7.56927469415, ZigguratSampler.Exponential.of(
+        Assert.assertEquals(3 * TAIL_W, ZigguratSampler.Exponential.of(
                 createRngWithSequence(-1, -1, -1, -1, -1, -1, 0)).sample(), 1e-14);
     }
 
@@ -1815,17 +1817,17 @@ public class StableSamplerTest {
      * 1 << 10                         d
      * Long.MIN_VALUE >>> 1            pi/5
      * Long.MAX_VALUE                  pi/4 - d
-     * 1                                                   7.39737323516E-19
-     * 1446480648965498882L                                1.0
-     * 6092639261718834176L                                5.0
-     * -1, -1, 0                                           7.56927469415
-     * -1L * 2n, 0                                         n * 7.56927469415  [2]
+     * 1                                                   7.397373235160728E-19
+     * 1446480648965178882L                                1.0
+     * 6092639261715210240L                                5.0
+     * -1, -1, 0                                           7.569274694148063
+     * -1L * 2n, 0                                         n * 7.569274694148063  [2]
      * </pre>
      *
      * <ol>
      * <li>When phi/2=-pi/4 the method will ignore the value and obtain another long value.
      * <li>To create a large value for the exponential sampler requires recursion. Each input
-     * of 2 * -1L will add 7.56927469415 to the total. A long of zero will stop recursion.
+     * of 2 * -1L will add 7.569274694148063 to the total. A long of zero will stop recursion.
      * </ol>
      *
      * @param longs the initial sequence of longs
@@ -1909,7 +1911,7 @@ public class StableSamplerTest {
         // Test alpha passing through 1 when beta!=0 (switch to an alpha=1 sampler)
         for (final double beta : new double[] {0.5, 0.2, 0.1, 0.001}) {
             testSamplerOutputIsContinuousFunction(1 + 8096 * DU, beta, 1.0, beta, 1 - 8096 * DU, beta, 0);
-            testSamplerOutputIsContinuousFunction(1 + 1024 * DU, beta, 1.0, beta, 1 - 1024 * DU, beta, 0);
+            testSamplerOutputIsContinuousFunction(1 + 1024 * DU, beta, 1.0, beta, 1 - 1024 * DU, beta, 1);
             // Not perfect when alpha -> 1
             testSamplerOutputIsContinuousFunction(1 + 128 * DU, beta, 1.0, beta, 1 - 128 * DU, beta, 1);
             testSamplerOutputIsContinuousFunction(1 + 16 * DU, beta, 1.0, beta, 1 - 16 * DU, beta, 4);
@@ -1921,10 +1923,10 @@ public class StableSamplerTest {
         for (final double alpha : new double[] {1.5, 1.2, 1.1, 1.001}) {
             testSamplerOutputIsContinuousFunction(alpha, 8096 * DU, alpha, 0, alpha, -8096 * DU, 0);
             testSamplerOutputIsContinuousFunction(alpha, 1024 * DU, alpha, 0, alpha, -1024 * DU, 0);
-            testSamplerOutputIsContinuousFunction(alpha, 128 * DU, alpha, 0, alpha, -128 * DU, 0);
+            testSamplerOutputIsContinuousFunction(alpha, 128 * DU, alpha, 0, alpha, -128 * DU, 1);
             // Not perfect when beta is very small
-            testSamplerOutputIsContinuousFunction(alpha, 16 * DU, alpha, 0, alpha, -16 * DU, 3);
-            testSamplerOutputIsContinuousFunction(alpha, DU, alpha, 0, alpha, -DU, 2);
+            testSamplerOutputIsContinuousFunction(alpha, 16 * DU, alpha, 0, alpha, -16 * DU, 64);
+            testSamplerOutputIsContinuousFunction(alpha, DU, alpha, 0, alpha, -DU, 4);
         }
 
         // Note: No test for transition to the Cauchy case (alpha=1, beta=0).
@@ -2279,7 +2281,7 @@ public class StableSamplerTest {
         final double w = ZigguratSampler.Exponential.of(rng).sample();
         Assert.assertNotEquals(0.0, w, 0.0);
         // This is the actual value; it is small but not extreme.
-        Assert.assertEquals(0.007391869818499571, w, 0.0);
+        Assert.assertEquals(0.007391869818503967, w, 0.0);
 
         final RandomSource source = RandomSource.XO_RO_SHI_RO_128_SS;
         final long seed = 0x83762b3daf1c43L;
@@ -2405,7 +2407,7 @@ public class StableSamplerTest {
             // phi/2=pi/5, w=large
             x, -1, -1, -1, -1, -1, -1, -1, -1, 0,
             // phi/2=pi/5, w=1
-            x, 1446480648965498882L,
+            x, 1446480648965178882L,
         };
 
         // Validate series

[commons-rng] 07/08: Add simple overhangs to sequential benchmark

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-rng.git

commit d8429b365e7550132009705d0bb769e2e2b0afac
Author: aherbert <ah...@apache.org>
AuthorDate: Mon Aug 9 15:44:51 2021 +0100

    Add simple overhangs to sequential benchmark
---
 .../jmh/sampling/distribution/ZigguratSamplerPerformance.java  | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java b/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java
index 135dc83..17742ee 100644
--- a/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java
+++ b/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java
@@ -59,6 +59,8 @@ public class ZigguratSamplerPerformance {
     private static final String GAUSSIAN_256 = "Gaussian256";
     /** The name for the {@link ZigguratSampler.NormalizedGaussian}. */
     private static final String MOD_GAUSSIAN = "ModGaussian";
+    /** The name for the {@link ModifiedZigguratNormalizedGaussianSamplerSimpleOverhangs}. */
+    private static final String MOD_GAUSSIAN_SIMPLE_OVERHANGS = "ModGaussianSimpleOverhangs";
     /** The name for the {@link ModifiedZigguratNormalizedGaussianSamplerIntMap}. */
     private static final String MOD_GAUSSIAN_INT_MAP = "ModGaussianIntMap";
 
@@ -192,7 +194,7 @@ public class ZigguratSamplerPerformance {
          * The sampler type.
          */
         @Param({GAUSSIAN_128, GAUSSIAN_256, "Exponential", MOD_GAUSSIAN, "ModExponential",
-                "ModGaussian2", "ModGaussianSimpleOverhangs", MOD_GAUSSIAN_INT_MAP,
+                "ModGaussian2", MOD_GAUSSIAN_SIMPLE_OVERHANGS, MOD_GAUSSIAN_INT_MAP,
                 "ModExponential2", "ModExponentialSimpleOverhangs", "ModExponentialIntMap"})
         private String type;
 
@@ -223,7 +225,7 @@ public class ZigguratSamplerPerformance {
                 sampler = ZigguratSampler.Exponential.of(rng);
             } else if ("ModGaussian2".equals(type)) {
                 sampler = new ModifiedZigguratNormalizedGaussianSampler(rng);
-            } else if ("ModGaussianSimpleOverhangs".equals(type)) {
+            } else if (MOD_GAUSSIAN_SIMPLE_OVERHANGS.equals(type)) {
                 sampler = new ModifiedZigguratNormalizedGaussianSamplerSimpleOverhangs(rng);
             } else if (MOD_GAUSSIAN_INT_MAP.equals(type)) {
                 sampler = new ModifiedZigguratNormalizedGaussianSamplerIntMap(rng);
@@ -266,7 +268,7 @@ public class ZigguratSamplerPerformance {
         private String randomSourceName;
 
         /** The sampler type. */
-        @Param({GAUSSIAN_128, GAUSSIAN_256, MOD_GAUSSIAN, MOD_GAUSSIAN_INT_MAP})
+        @Param({GAUSSIAN_128, GAUSSIAN_256, MOD_GAUSSIAN, MOD_GAUSSIAN_SIMPLE_OVERHANGS, MOD_GAUSSIAN_INT_MAP})
         private String type;
 
         /** The size. */
@@ -295,6 +297,8 @@ public class ZigguratSamplerPerformance {
                 s = ZigguratNormalizedGaussianSampler.of(rng);
             } else if (MOD_GAUSSIAN.equals(type)) {
                 s = ZigguratSampler.NormalizedGaussian.of(rng);
+            } else if (MOD_GAUSSIAN_SIMPLE_OVERHANGS.equals(type)) {
+                s = new ModifiedZigguratNormalizedGaussianSamplerSimpleOverhangs(rng);
             } else if (MOD_GAUSSIAN_INT_MAP.equals(type)) {
                 s = new ModifiedZigguratNormalizedGaussianSamplerIntMap(rng);
             } else {

[commons-rng] 03/08: Combine conditions

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-rng.git

commit 2300a7ce68bd8fa041dd11b5f2f8084c34bb763a
Author: aherbert <ah...@apache.org>
AuthorDate: Mon Aug 9 13:20:59 2021 +0100

    Combine conditions
---
 .../apache/commons/rng/sampling/distribution/ZigguratSampler.java   | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java
index 9c51cd8..921d2d8 100644
--- a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java
+++ b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java
@@ -798,10 +798,8 @@ public abstract class ZigguratSampler implements SharedStateContinuousSampler {
                         u1 -= uDiff;
                     }
                     x = fastPrngSampleX(X, j, u1);
-                    if (uDiff > MIN_IE)  {
-                        break;
-                    }
-                    if (fastPrngSampleY(Y, j, Long.MIN_VALUE - (u1 + uDiff)) < Math.exp(-0.5 * x * x)) {
+                    if (uDiff > MIN_IE ||
+                        fastPrngSampleY(Y, j, Long.MIN_VALUE - (u1 + uDiff)) < Math.exp(-0.5 * x * x)) {
                         break;
                     }
                     u1 = randomInt63();

[commons-rng] 04/08: Add loop frequencies

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-rng.git

commit dac561f4318f900fa1380336adff8dcadbad6145
Author: aherbert <ah...@apache.org>
AuthorDate: Mon Aug 9 14:37:38 2021 +0100

    Add loop frequencies
---
 .../org/apache/commons/rng/sampling/distribution/ZigguratSampler.java | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java
index 921d2d8..68a1a3a 100644
--- a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java
+++ b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java
@@ -758,6 +758,7 @@ public abstract class ZigguratSampler implements SharedStateContinuousSampler {
             if (j > J_INFLECTION) {
                 // Convex overhang
                 // Branch frequency: 0.00891413
+                // Loop repeat frequency: 0.389804
                 for (;;) {
                     x = fastPrngSampleX(X, j, u1);
                     final long uDiff = randomInt63() - u1;
@@ -780,6 +781,7 @@ public abstract class ZigguratSampler implements SharedStateContinuousSampler {
                 // Branch frequency: 0.000277067
                 // Note: Although less frequent than the next branch, j == 0 is a subset of
                 // j < J_INFLECTION and must be first.
+                // Loop repeat frequency: 0.0634786
                 do {
                     x = ONE_OVER_X_0 * exponential.sample();
                 } while (exponential.sample() < 0.5 * x * x);
@@ -787,6 +789,7 @@ public abstract class ZigguratSampler implements SharedStateContinuousSampler {
             } else if (j < J_INFLECTION) {
                 // Concave overhang
                 // Branch frequency: 0.00251223
+                // Loop repeat frequency: 0.0123784
                 for (;;) {
                     // U_x <- min(U_1, U_2)
                     // distance <- | U_1 - U_2 |
@@ -807,6 +810,7 @@ public abstract class ZigguratSampler implements SharedStateContinuousSampler {
             } else {
                 // Inflection point
                 // Branch frequency: 0.0000161147
+                // Loop repeat frequency: 0.500213
                 for (;;) {
                     x = fastPrngSampleX(X, j, u1);
                     if (fastPrngSampleY(Y, j, randomInt63()) < Math.exp(-0.5 * x * x)) {

[commons-rng] 05/08: Benchmark int map sampler in the sequential test

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-rng.git

commit e7494adf343a3af45fce2c40a2604aea60155cd5
Author: aherbert <ah...@apache.org>
AuthorDate: Mon Aug 9 14:40:08 2021 +0100

    Benchmark int map sampler in the sequential test
---
 .../sampling/distribution/ZigguratSamplerPerformance.java  | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java b/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java
index 8393d54..135dc83 100644
--- a/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java
+++ b/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java
@@ -59,6 +59,8 @@ public class ZigguratSamplerPerformance {
     private static final String GAUSSIAN_256 = "Gaussian256";
     /** The name for the {@link ZigguratSampler.NormalizedGaussian}. */
     private static final String MOD_GAUSSIAN = "ModGaussian";
+    /** The name for the {@link ModifiedZigguratNormalizedGaussianSamplerIntMap}. */
+    private static final String MOD_GAUSSIAN_INT_MAP = "ModGaussianIntMap";
 
     /**
      * The value.
@@ -190,8 +192,8 @@ public class ZigguratSamplerPerformance {
          * The sampler type.
          */
         @Param({GAUSSIAN_128, GAUSSIAN_256, "Exponential", MOD_GAUSSIAN, "ModExponential",
-                "ModGaussian2", "ModGaussianSimpleOverhangs", "ModGaussianIntMap",
-                "ModExponential2", "ModExponentialSimpleOverhangs", "ModExponentialSimpleOverhangsIntMap"})
+                "ModGaussian2", "ModGaussianSimpleOverhangs", MOD_GAUSSIAN_INT_MAP,
+                "ModExponential2", "ModExponentialSimpleOverhangs", "ModExponentialIntMap"})
         private String type;
 
         /** The sampler. */
@@ -223,13 +225,13 @@ public class ZigguratSamplerPerformance {
                 sampler = new ModifiedZigguratNormalizedGaussianSampler(rng);
             } else if ("ModGaussianSimpleOverhangs".equals(type)) {
                 sampler = new ModifiedZigguratNormalizedGaussianSamplerSimpleOverhangs(rng);
-            } else if ("ModGaussianIntMap".equals(type)) {
+            } else if (MOD_GAUSSIAN_INT_MAP.equals(type)) {
                 sampler = new ModifiedZigguratNormalizedGaussianSamplerIntMap(rng);
             } else if ("ModExponential2".equals(type)) {
                 sampler = new ModifiedZigguratExponentialSampler(rng);
             } else if ("ModExponentialSimpleOverhangs".equals(type)) {
                 sampler = new ModifiedZigguratExponentialSamplerSimpleOverhangs(rng);
-            } else if ("ModExponentialSimpleOverhangsIntMap".equals(type)) {
+            } else if ("ModExponentialIntMap".equals(type)) {
                 sampler = new ModifiedZigguratExponentialSamplerIntMap(rng);
             } else {
                 throwIllegalStateException(type);
@@ -264,7 +266,7 @@ public class ZigguratSamplerPerformance {
         private String randomSourceName;
 
         /** The sampler type. */
-        @Param({GAUSSIAN_128, GAUSSIAN_256, MOD_GAUSSIAN})
+        @Param({GAUSSIAN_128, GAUSSIAN_256, MOD_GAUSSIAN, MOD_GAUSSIAN_INT_MAP})
         private String type;
 
         /** The size. */
@@ -293,6 +295,8 @@ public class ZigguratSamplerPerformance {
                 s = ZigguratNormalizedGaussianSampler.of(rng);
             } else if (MOD_GAUSSIAN.equals(type)) {
                 s = ZigguratSampler.NormalizedGaussian.of(rng);
+            } else if (MOD_GAUSSIAN_INT_MAP.equals(type)) {
+                s = new ModifiedZigguratNormalizedGaussianSamplerIntMap(rng);
             } else {
                 throwIllegalStateException(type);
             }

[commons-rng] 06/08: Add overhang frequencies

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-rng.git

commit dc4370b1931e53f11b01e68dca403e211df8855e
Author: aherbert <ah...@apache.org>
AuthorDate: Mon Aug 9 15:05:03 2021 +0100

    Add overhang frequencies
---
 .../org/apache/commons/rng/sampling/distribution/ZigguratSampler.java   | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java
index 68a1a3a..297e495 100644
--- a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java
+++ b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/ZigguratSampler.java
@@ -768,6 +768,8 @@ public abstract class ZigguratSampler implements SharedStateContinuousSampler {
                     }
                     if (uDiff >= MAX_IE &&
                         // Within maximum distance of f(x) from the triangle hypotenuse.
+                        // Frequency (per upper-right triangle): 0.431497
+                        // Reject frequency: 0.489630
                         // Long.MIN_VALUE is used as an unsigned int with value 2^63:
                         // uy = Long.MIN_VALUE - (ux + uDiff)
                         fastPrngSampleY(Y, j, Long.MIN_VALUE - (u1 + uDiff)) < Math.exp(-0.5 * x * x)) {

[commons-rng] 02/08: Add benchmark for ZigguratSamplers with integer look-up tables

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-rng.git

commit 6b1b257d56bab808dfafd816cd8d3c3f99265b95
Author: aherbert <ah...@apache.org>
AuthorDate: Mon Aug 9 12:29:50 2021 +0100

    Add benchmark for ZigguratSamplers with integer look-up tables
---
 .../distribution/ZigguratSamplerPerformance.java   | 1211 ++++++++++++++++----
 .../checkstyle/checkstyle-suppressions.xml         |    1 +
 2 files changed, 982 insertions(+), 230 deletions(-)

diff --git a/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java b/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java
index 6e407cf..8393d54 100644
--- a/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java
+++ b/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java
@@ -48,6 +48,11 @@ import java.util.concurrent.TimeUnit;
 @State(Scope.Benchmark)
 @Fork(value = 1, jvmArgs = {"-server", "-Xms128M", "-Xmx128M"})
 public class ZigguratSamplerPerformance {
+    /** Mask to create an unsigned long from a signed long. */
+    private static final long MAX_INT64 = 0x7fffffffffffffffL;
+    /** 2^53. */
+    private static final double TWO_POW_63 = 0x1.0p63;
+
     /** The name for the {@link ZigguratNormalizedGaussianSampler}. */
     private static final String GAUSSIAN_128 = "Gaussian128";
     /** The name for a copy of the {@link ZigguratNormalizedGaussianSampler} with a table of size 256. */
@@ -185,8 +190,8 @@ public class ZigguratSamplerPerformance {
          * The sampler type.
          */
         @Param({GAUSSIAN_128, GAUSSIAN_256, "Exponential", MOD_GAUSSIAN, "ModExponential",
-                "ModGaussian2", "ModGaussianSimpleOverhangs",
-                "ModExponential2", "ModExponentialSimpleOverhangs"})
+                "ModGaussian2", "ModGaussianSimpleOverhangs", "ModGaussianIntMap",
+                "ModExponential2", "ModExponentialSimpleOverhangs", "ModExponentialSimpleOverhangsIntMap"})
         private String type;
 
         /** The sampler. */
@@ -218,10 +223,14 @@ public class ZigguratSamplerPerformance {
                 sampler = new ModifiedZigguratNormalizedGaussianSampler(rng);
             } else if ("ModGaussianSimpleOverhangs".equals(type)) {
                 sampler = new ModifiedZigguratNormalizedGaussianSamplerSimpleOverhangs(rng);
+            } else if ("ModGaussianIntMap".equals(type)) {
+                sampler = new ModifiedZigguratNormalizedGaussianSamplerIntMap(rng);
             } else if ("ModExponential2".equals(type)) {
                 sampler = new ModifiedZigguratExponentialSampler(rng);
             } else if ("ModExponentialSimpleOverhangs".equals(type)) {
                 sampler = new ModifiedZigguratExponentialSamplerSimpleOverhangs(rng);
+            } else if ("ModExponentialSimpleOverhangsIntMap".equals(type)) {
+                sampler = new ModifiedZigguratExponentialSamplerIntMap(rng);
             } else {
                 throwIllegalStateException(type);
             }
@@ -736,10 +745,6 @@ public class ZigguratSamplerPerformance {
      * McFarland (2016) JSCS 86, 1281-1294</a>
      */
     static class ModifiedZigguratNormalizedGaussianSampler implements ContinuousSampler {
-        /** Mask to create an unsigned long from a signed long. */
-        protected static final long MAX_INT64 = 0x7fffffffffffffffL;
-        /** 2^63. */
-        protected static final double TWO_POW_63 = 0x1.0p63;
         /** Maximum i value for early exit. */
         protected static final int I_MAX = 253;
         /** The point where the Gaussian switches from convex to concave. */
@@ -1203,7 +1208,7 @@ public class ZigguratSamplerPerformance {
     }
 
     /**
-     * Modified Ziggurat method for sampling from an exponential distribution.
+     * Modified Ziggurat method for sampling from a Gaussian distribution with mean 0 and standard deviation 1.
      *
      * <p>Uses the algorithm from:
      *
@@ -1213,190 +1218,985 @@ public class ZigguratSamplerPerformance {
      * <i>Journal of Statistical Computation and Simulation</i> <b>86</b>, 1281-1294.
      * </blockquote>
      *
+     * <p>This is a copy of {@link ModifiedZigguratNormalizedGaussianSampler} using
+     * an integer map in-place of a byte map look-up table. The underlying exponential
+     * sampler also uses an integer map.
+     *
      * @see <a href="https://www.tandfonline.com/doi/abs/10.1080/00949655.2015.1060234">
      * McFarland (2016) JSCS 86, 1281-1294</a>
      */
-    static class ModifiedZigguratExponentialSampler implements ContinuousSampler {
-        /** Mask to create an unsigned long from a signed long. */
-        private static final long MAX_INT64 = 0x7fffffffffffffffL;
-        /** 2^53. */
-        private static final double TWO_POW_63 = 0x1.0p63;
+    static class ModifiedZigguratNormalizedGaussianSamplerIntMap implements ContinuousSampler {
         /** Maximum i value for early exit. */
-        private static final int I_MAX = 252;
-        /** Maximum distance value for early exit. */
-        private static final long IE_MAX = 513303011048449570L;
+        protected static final int I_MAX = 253;
+        /** The point where the Gaussian switches from convex to concave. */
+        protected static final int J_INFLECTION = 205;
+        /** Used for largest deviations of f(x) from y_i. This is negated on purpose. */
+        protected static final long MAX_IE = -2269182951627976004L;
+        /** Used for largest deviations of f(x) from y_i. */
+        protected static final long MIN_IE = 760463704284035184L;
         /** Beginning of tail. */
-        private static final double X_0 = 7.569274694148063;
+        protected static final double X_0 = 3.6360066255009455861;
+        /** 1/X_0. */
+        protected static final double ONE_OVER_X_0 = 1d / X_0;
 
         /** The alias map. An integer in [0, 255] stored as a byte to save space. */
-        private static final byte[] MAP = toBytes(new int[] {0, 0, 1, 235, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
-            1, 1, 1, 2, 2, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
-            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
-            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
-            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
-            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
-            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
-            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
-            252, 252, 252, 252, 252, 252, 252, 252, 252, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251,
-            251, 250, 250, 250, 250, 250, 250, 250, 249, 249, 249, 249, 249, 249, 248, 248, 248, 248, 247, 247, 247,
-            247, 246, 246, 246, 245, 245, 244, 244, 243, 243, 242, 241, 241, 240, 239, 237, 3, 3, 4, 4, 6, 0, 0, 0, 0,
-            236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 2, 0, 0, 0});
+        protected static final int[] MAP =
+            {0, 0, 239, 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
+                253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
+                253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
+                253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
+                253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
+                253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
+                253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
+                253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
+                253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
+                253, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 251, 251, 251, 251, 251, 251, 251, 250, 250, 250,
+                250, 250, 249, 249, 249, 248, 248, 248, 247, 247, 247, 246, 246, 245, 244, 244, 243, 242, 240, 2, 2, 3,
+                3, 0, 0, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 1, 0, 0};
         /** The alias inverse PMF. */
-        private static final long[] IPMF = {9223372036854773904L, 1623796909450835018L, 2664290944894291308L,
-            7387971354164061021L, 6515064486552723158L, 8840508362680718891L, 6099647593382936415L,
-            7673130333659513775L, 6220332867583438096L, 5045979640552813698L, 4075305837223955523L,
-            3258413672162525427L, 2560664887087762532L, 1957224924672899637L, 1429800935350577509L, 964606309710808246L,
-            551043923599587126L, 180827629096890295L, -152619738120023625L, -454588624410291545L, -729385126147774968L,
-            -980551509819446936L, -1211029700667463960L, -1423284293868548440L, -1619396356369050407L,
-            -1801135830956211623L, -1970018048575618087L, -2127348289059705319L, -2274257249303686407L,
-            -2411729520096655303L, -2540626634159180934L, -2661705860113406470L, -2775635634532450566L,
-            -2883008316030465190L, -2984350790383654790L, -3080133339198116454L, -3170777096303091110L,
-            -3256660348483819078L, -3338123885075136262L, -3415475560473299110L, -3488994201966428229L,
-            -3558932970354473157L, -3625522261068041093L, -3688972217741989381L, -3749474917563782629L,
-            -3807206277531056133L, -3862327722496843557L, -3914987649156779685L, -3965322714631865221L,
-            -4013458973776895589L, -4059512885612783333L, -4103592206186241029L, -4145796782586128069L,
-            -4186219260694346949L, -4224945717447275173L, -4262056226866285509L, -4297625367836519557L,
-            -4331722680528537317L, -4364413077437472517L, -4395757214229401700L, -4425811824915135780L,
-            -4454630025296932548L, -4482261588141290436L, -4508753193105288068L, -4534148654077808964L,
-            -4558489126279958148L, -4581813295192216580L, -4604157549138257636L, -4625556137145255269L,
-            -4646041313519104421L, -4665643470413305925L, -4684391259530326597L, -4702311703971761733L,
-            -4719430301145103269L, -4735771117539946308L, -4751356876102087236L, -4766209036859134052L,
-            -4780347871386013380L, -4793792531638892068L, -4806561113635132708L, -4818670716409306532L,
-            -4830137496634465604L, -4840976719260837892L, -4851202804490348868L, -4860829371376459908L,
-            -4869869278311657508L, -4878334660640770948L, -4886236965617427236L, -4893586984900802596L,
-            -4900394884772702724L, -4906670234238885316L, -4912422031164496804L, -4917658726580119812L,
-            -4922388247283532292L, -4926618016851066692L, -4930354975163335236L, -4933605596540651332L,
-            -4936375906575303844L, -4938671497741365892L, -4940497543854575684L, -4941858813449629540L,
-            -4942759682136115044L, -4943204143989086820L, -4943195822025527940L, -4942737977813206404L,
-            -4941833520255033284L, -4940485013586738820L, -4938694684624359428L, -4936464429291795972L,
-            -4933795818458825604L, -4930690103114057988L, -4927148218896864068L, -4923170790008275908L,
-            -4918758132519213508L, -4913910257091645764L, -4908626871126539204L, -4902907380349534020L,
-            -4896750889844272900L, -4890156204540531076L, -4883121829162554372L, -4875645967641781188L,
-            -4867726521994927044L, -4859361090668103364L, -4850546966345113668L, -4841281133215539076L,
-            -4831560263698491972L, -4821380714613447492L, -4810738522790066116L, -4799629400105481988L,
-            -4788048727936307268L, -4775991551010515012L, -4763452570642114308L, -4750426137329494532L,
-            -4736906242696389124L, -4722886510751377669L, -4708360188440088965L, -4693320135461420933L,
-            -4677758813316108101L, -4661668273553489093L, -4645040145179241541L, -4627865621182772101L,
-            -4610135444140930052L, -4591839890849345476L, -4572968755929961540L, -4553511334358205764L,
-            -4533456402849101572L, -4512792200036278980L, -4491506405372580932L, -4469586116675402436L,
-            -4447017826233108036L, -4423787395382284804L, -4399880027458416324L, -4375280239014115077L,
-            -4349971829190472197L, -4323937847117721861L, -4297160557210933573L, -4269621402214949829L,
-            -4241300963840749253L, -4212178920821861701L, -4182234004204451589L, -4151443949668877253L,
-            -4119785446662287621L, -4087234084103201605L, -4053764292396156933L, -4019349281473081925L,
-            -3983960974549692677L, -3947569937258423301L, -3910145301787345669L, -3871654685619032069L,
-            -3832064104425388805L, -3791337878631544901L, -3749438533114327493L, -3706326689447984389L,
-            -3661960950051848261L, -3616297773528534789L, -3569291340409189253L, -3520893408440946053L,
-            -3471053156460654341L, -3419717015797782598L, -3366828488034805510L, -3312327947826460358L,
-            -3256152429334010374L, -3198235394669719110L, -3138506482563172742L, -3076891235255162822L,
-            -3013310801389730758L, -2947681612411374854L, -2879915029671670790L, -2809916959107513734L,
-            -2737587429961866118L, -2662820133571325574L, -2585501917733379974L, -2505512231579385223L,
-            -2422722515205211655L, -2336995527534088455L, -2248184604988727559L, -2156132842510764935L,
-            -2060672187261025415L, -1961622433929371911L, -1858790108950105479L, -1751967229002895623L,
-            -1640929916937142791L, -1525436855617582472L, -1405227557075253256L, -1280020420662649992L,
-            -1149510549536596104L, -1013367289578704904L, -871231448632104200L, -722712146453667848L,
-            -567383236774435977L, -404779231966938249L, -234390647591545737L, -55658667960119305L, 132030985907841399L,
-            329355128892811767L, 537061298001085174L, 755977262693564150L, 987022116608033270L, 1231219266829431286L,
-            1489711711346518517L, 1763780090187553909L, 2054864117341795061L, 2364588157623768948L,
-            2694791916990503284L, 3047567482883476212L, 3425304305830816371L, 3830744187097297907L,
-            4267048975685830386L, 4737884547990017266L, 5247525842198998257L, 5800989391535355377L,
-            6404202162993295344L, 7064218894258540527L, 7789505049452331503L, 8590309807749444846L,
-            7643763810684490059L, 8891950541491446071L, 5457384281016205975L, 9083704440929283969L,
-            7976211653914433372L, 8178631350487117494L, 2821287825726744835L, 6322989683301709657L,
-            4309503753387611426L, 4685170734960170474L, 8404845967535199663L, 7330522972447554153L,
-            1960945799076992020L, 4742910674644898996L, -751799822533509968L, 7023456603741959948L,
-            3843116882594676172L, 3927231442413902976L, -9223372036854775808L, -9223372036854775808L,
-            -9223372036854775808L};
+        protected static final long[] IPMF = {9223372036854775408L, 1100243796534090797L, 7866600928998383022L,
+            6788754710675124691L, 9022865200181688296L, 6522434035205502164L, 4723064097360024697L,
+            3360495653216416088L, 2289663232373870755L, 1423968905551920455L, 708364817827797893L, 106102487305601162L,
+            -408333464665794443L, -853239722779025206L, -1242095211825521362L, -1585059631105762155L,
+            -1889943050287169086L, -2162852901990669843L, -2408637386594511193L, -2631196530262954448L,
+            -2833704942520925732L, -3018774289025787439L, -3188573753472222231L, -3344920681707410914L,
+            -3489349705062150768L, -3623166100042179544L, -3747487436868335278L, -3863276422712173808L,
+            -3971367044063130866L, -4072485557029823980L, -4167267476830916554L, -4256271432240159761L,
+            -4339990541927306746L, -4418861817133802326L, -4493273980372377053L, -4563574004462246636L,
+            -4630072609770453867L, -4693048910430964891L, -4752754358862894738L, -4809416110052769505L,
+            -4863239903586985866L, -4914412541515875772L, -4963104028439161008L, -5009469424769119174L,
+            -5053650458856559461L, -5095776932695077750L, -5135967952544929007L, -5174333008451230625L,
+            -5210972924952654441L, -5245980700100460247L, -5279442247516297345L, -5311437055462369316L,
+            -5342038772315650555L, -5371315728843297107L, -5399331404632512666L, -5426144845448965104L,
+            -5451811038519422589L, -5476381248265593008L, -5499903320558339045L, -5522421955752311307L,
+            -5543978956085263616L, -5564613449659060480L, -5584362093436146354L, -5603259257517428627L,
+            -5621337193070986365L, -5638626184974132325L, -5655154691220933854L, -5670949470294763073L,
+            -5686035697601807766L, -5700437072199152453L, -5714175914219812272L, -5727273255295221103L,
+            -5739748920271997489L, -5751621603810411941L, -5762908939773946223L, -5773627565915007849L,
+            -5783793183152377622L, -5793420610475628449L, -5802523835894661300L, -5811116062947570228L,
+            -5819209754516120768L, -5826816672854571802L, -5833947916825278195L, -5840613956570608249L,
+            -5846824665591763395L, -5852589350491075357L, -5857916778480726477L, -5862815203334800430L,
+            -5867292388935742441L, -5871355631762283997L, -5875011781262890819L, -5878267259039093710L,
+            -5881128076579883546L, -5883599852028851382L, -5885687825288565257L, -5887396872144963778L,
+            -5888731517955042223L, -5889695949247728499L, -5890294025706689822L, -5890529289910829504L,
+            -5890404977675987449L, -5889924026487208528L, -5889089083913555992L, -5887902514965209240L,
+            -5886366408898372127L, -5884482585690639756L, -5882252601321090366L, -5879677752995027766L,
+            -5876759083794175305L, -5873497386318840733L, -5869893206505510263L, -5865946846617024340L,
+            -5861658367354159190L, -5857027590486131555L, -5852054100063428398L, -5846737243971504641L,
+            -5841076134082373571L, -5835069647234580384L, -5828716424754549310L, -5822014871949021959L,
+            -5814963157357531601L, -5807559211080072146L, -5799800723447230025L, -5791685142338073347L,
+            -5783209670985158971L, -5774371264582489329L, -5765166627072226519L, -5755592207057667866L,
+            -5745644193442049188L, -5735318510777133844L, -5724610813433666496L, -5713516480340333005L,
+            -5702030608556698118L, -5690148005851018661L, -5677863184109371808L, -5665170350903313433L,
+            -5652063400924580562L, -5638535907000141432L, -5624581109999480439L, -5610191908627599865L,
+            -5595360848093632709L, -5580080108034218849L, -5564341489875550045L, -5548136403221394654L,
+            -5531455851545399204L, -5514290416593586870L, -5496630242226406575L, -5478465016761742826L,
+            -5459783954986665201L, -5440575777891777017L, -5420828692432397919L, -5400530368638773571L,
+            -5379667916699401670L, -5358227861294116825L, -5336196115274292307L, -5313557951078385986L,
+            -5290297970633451489L, -5266400072915222391L, -5241847420214015772L, -5216622401043726607L,
+            -5190706591719533973L, -5164080714589203240L, -5136724594099067134L, -5108617109269313037L,
+            -5079736143458214973L, -5050058530461741430L, -5019559997031891994L, -4988215100963583032L,
+            -4955997165645492083L, -4922878208652041825L, -4888828866780320026L, -4853818314258475851L,
+            -4817814175855179990L, -4780782432601701861L, -4742687321746719241L, -4703491227581444720L,
+            -4663154564978699244L, -4621635653358766431L, -4578890580370785840L, -4534873055659683516L,
+            -4489534251700611902L, -4442822631898829564L, -4394683764809104088L, -4345060121983362610L,
+            -4293890858708922851L, -4241111576153830158L, -4186654061692619033L, -4130446006804747670L,
+            -4072410698657718678L, -4012466683838401105L, -3950527400305017938L, -3886500774061896578L,
+            -3820288777467837180L, -3751786943594897634L, -3680883832433527802L, -3607460442623922090L,
+            -3531389562483324266L, -3452535052891361699L, -3370751053395887939L, -3285881101633968096L,
+            -3197757155301365465L, -3106198503156485339L, -3011010550911937371L, -2911983463883581047L,
+            -2808890647470271789L, -2701487041141150061L, -2589507199690603472L, -2472663129329160218L,
+            -2350641842139870417L, -2223102583770035263L, -2089673683684728595L, -1949948966090106873L,
+            -1803483646855993757L, -1649789631480328207L, -1488330106139747683L, -1318513295725618200L,
+            -1139685236927327128L, -951121376596854700L, -752016768184775899L, -541474585642866346L,
+            -318492605725778472L, -81947227249193332L, 169425512612864612L, 437052607232193594L, 722551297568810077L,
+            1027761939299714316L, 1354787941622770469L, 1706044619203941749L, 2084319374409574060L,
+            2492846399593711370L, 2935400169348532576L, 3416413484613111455L, 3941127949860576155L,
+            4515787798793437894L, 5147892401439714413L, 5846529325380405959L, 6622819682216655291L,
+            7490522659874166085L, 8466869998277892108L, 8216968526387345482L, 4550693915488934669L,
+            7628019504138977223L, 6605080500908005863L, 7121156327650272532L, 2484871780331574356L,
+            7179104797032803433L, 7066086283830045340L, 1516500120817362978L, 216305945438803570L, 6295963418525324512L,
+            2889316805630113239L, -2712587580533804137L, 6562498853538167124L, 7975754821147501243L,
+            -9223372036854775808L, -9223372036854775808L};
         /**
          * The precomputed ziggurat lengths, denoted X_i in the main text. X_i = length of
          * ziggurat layer i.
          */
-        private static final double[] X = {8.206624067534882E-19, 7.397373235160728E-19, 6.913331337791529E-19,
-            6.564735882096453E-19, 6.291253995981851E-19, 6.065722412960496E-19, 5.873527610373727E-19,
-            5.705885052853694E-19, 5.557094569162239E-19, 5.423243890374395E-19, 5.301529769650878E-19,
-            5.189873925770806E-19, 5.086692261799833E-19, 4.990749293879647E-19, 4.901062589444954E-19,
-            4.816837901064919E-19, 4.737423865364471E-19, 4.662279580719682E-19, 4.590950901778405E-19,
-            4.523052779065815E-19, 4.458255881635396E-19, 4.396276312636838E-19, 4.336867596710647E-19,
-            4.2798143618469714E-19, 4.224927302706489E-19, 4.172039125346411E-19, 4.1210012522465616E-19,
-            4.0716811225869233E-19, 4.0239599631006903E-19, 3.9777309342877357E-19, 3.93289757853345E-19,
-            3.8893725129310323E-19, 3.8470763218720385E-19, 3.8059366138180143E-19, 3.765887213854473E-19,
-            3.7268674692030177E-19, 3.688821649224816E-19, 3.651698424880007E-19, 3.6154504153287473E-19,
-            3.5800337915318032E-19, 3.545407928453343E-19, 3.5115350988784242E-19, 3.478380203003096E-19,
-            3.4459105288907336E-19, 3.4140955396563316E-19, 3.3829066838741162E-19, 3.3523172262289E-19,
-            3.3223020958685874E-19, 3.292837750280447E-19, 3.263902052820205E-19, 3.2354741622810815E-19,
-            3.207534433108079E-19, 3.180064325047861E-19, 3.1530463211820845E-19, 3.1264638534265134E-19,
-            3.100301234693421E-19, 3.07454359701373E-19, 3.049176835000556E-19, 3.0241875541094565E-19,
-            2.999563023214455E-19, 2.975291131074259E-19, 2.9513603463113224E-19, 2.9277596805684267E-19,
-            2.9044786545442563E-19, 2.8815072666416712E-19, 2.858835963990693E-19, 2.8364556156331615E-19,
-            2.81435748767798E-19, 2.7925332202553125E-19, 2.770974806115288E-19, 2.7496745707320232E-19,
-            2.7286251537873397E-19, 2.7078194919206054E-19, 2.687250802641905E-19, 2.666912569315344E-19,
-            2.646798527127889E-19, 2.6269026499668434E-19, 2.6072191381359757E-19, 2.5877424068465143E-19,
-            2.568467075424817E-19, 2.549387957183548E-19, 2.530500049907748E-19, 2.511798526911271E-19,
-            2.4932787286227806E-19, 2.474936154663866E-19, 2.456766456384867E-19, 2.438765429826784E-19,
-            2.4209290090801527E-19, 2.403253260014054E-19, 2.3857343743505147E-19, 2.368368664061465E-19,
-            2.3511525560671253E-19, 2.3340825872163284E-19, 2.3171553995306794E-19, 2.3003677356958333E-19,
-            2.283716434784348E-19, 2.2671984281957174E-19, 2.250810735800194E-19, 2.234550462273959E-19,
-            2.2184147936140775E-19, 2.2024009938224424E-19, 2.186506401748684E-19, 2.1707284280826716E-19,
-            2.1550645524878675E-19, 2.1395123208673778E-19, 2.124069342755064E-19, 2.1087332888245875E-19,
-            2.0935018885097035E-19, 2.0783729277295508E-19, 2.0633442467130712E-19, 2.0484137379170616E-19,
-            2.0335793440326865E-19, 2.018839056075609E-19, 2.0041909115551697E-19, 1.9896329927183254E-19,
-            1.975163424864309E-19, 1.9607803747261946E-19, 1.9464820489157862E-19, 1.9322666924284314E-19,
-            1.9181325872045647E-19, 1.904078050744948E-19, 1.8901014347767504E-19, 1.8762011239677479E-19,
-            1.8623755346860768E-19, 1.8486231138030984E-19, 1.8349423375370566E-19, 1.8213317103353295E-19,
-            1.8077897637931708E-19, 1.7943150556069476E-19, 1.7809061685599652E-19, 1.7675617095390567E-19,
-            1.7542803085801941E-19, 1.741060617941453E-19, 1.727901311201724E-19, 1.7148010823836362E-19,
-            1.7017586450992059E-19, 1.6887727317167824E-19, 1.6758420925479093E-19, 1.6629654950527621E-19,
-            1.650141723062866E-19, 1.6373695760198277E-19, 1.624647868228856E-19, 1.6119754281258616E-19,
-            1.5993510975569615E-19, 1.586773731069231E-19, 1.5742421952115544E-19, 1.5617553678444595E-19,
-            1.5493121374578016E-19, 1.5369114024951992E-19, 1.524552070684102E-19, 1.5122330583703858E-19,
-            1.499953289856356E-19, 1.4877116967410352E-19, 1.4755072172615974E-19, 1.4633387956347966E-19,
-            1.4512053813972103E-19, 1.439105928743099E-19, 1.4270393958586506E-19, 1.415004744251338E-19,
-            1.4030009380730888E-19, 1.3910269434359025E-19, 1.3790817277185197E-19, 1.3671642588626657E-19,
-            1.3552735046573446E-19, 1.3434084320095729E-19, 1.3315680061998685E-19, 1.3197511901207148E-19,
-            1.3079569434961214E-19, 1.2961842220802957E-19, 1.28443197683331E-19, 1.2726991530715219E-19,
-            1.2609846895903523E-19, 1.2492875177568625E-19, 1.237606560569394E-19, 1.225940731681333E-19,
-            1.2142889343858445E-19, 1.2026500605581765E-19, 1.1910229895518744E-19, 1.1794065870449425E-19,
-            1.1677997038316715E-19, 1.1562011745554883E-19, 1.144609816377787E-19, 1.1330244275772562E-19,
-            1.1214437860737343E-19, 1.109866647870073E-19, 1.0982917454048923E-19, 1.086717785808435E-19,
-            1.0751434490529747E-19, 1.0635673859884002E-19, 1.0519882162526621E-19, 1.0404045260457141E-19,
-            1.0288148657544097E-19, 1.0172177474144965E-19, 1.0056116419943559E-19, 9.939949764834668E-20,
-            9.823661307666745E-20, 9.70723434263201E-20, 9.590651623069063E-20, 9.47389532241542E-20,
-            9.356946992015904E-20, 9.239787515456947E-20, 9.122397059055647E-20, 9.004755018085287E-20,
-            8.886839958264763E-20, 8.768629551976745E-20, 8.650100508607102E-20, 8.531228498314119E-20,
-            8.411988068438521E-20, 8.292352551651342E-20, 8.17229396480345E-20, 8.051782897283921E-20,
-            7.930788387509923E-20, 7.809277785952443E-20, 7.687216602842904E-20, 7.564568338396512E-20,
-            7.441294293017913E-20, 7.317353354509333E-20, 7.192701758763107E-20, 7.067292819766679E-20,
-            6.941076623950036E-20, 6.813999682925642E-20, 6.686004537461023E-20, 6.557029304021008E-20,
-            6.427007153336853E-20, 6.295865708092356E-20, 6.163526343814314E-20, 6.02990337321517E-20,
-            5.894903089285018E-20, 5.758422635988593E-20, 5.62034866695974E-20, 5.480555741349931E-20,
-            5.3389043909003295E-20, 5.1952387717989917E-20, 5.0493837866338355E-20, 4.901141522262949E-20,
-            4.7502867933366117E-20, 4.5965615001265455E-20, 4.4396673897997565E-20, 4.279256630214859E-20,
-            4.1149193273430015E-20, 3.9461666762606287E-20, 3.7724077131401685E-20, 3.592916408620436E-20,
-            3.4067836691100565E-20, 3.2128447641564046E-20, 3.0095646916399994E-20, 2.794846945559833E-20,
-            2.5656913048718645E-20, 2.317520975680391E-20, 2.042669522825129E-20, 1.7261770330213488E-20,
-            1.3281889259442579E-20, 0.0};
-        /** Overhang table. Y_i = f(X_i). */
-        private static final double[] Y = {5.595205495112736E-23, 1.1802509982703313E-22, 1.844442338673583E-22,
-            2.543903046669831E-22, 3.2737694311509334E-22, 4.0307732132706715E-22, 4.812547831949511E-22,
-            5.617291489658331E-22, 6.443582054044353E-22, 7.290266234346368E-22, 8.156388845632194E-22,
-            9.041145368348222E-22, 9.94384884863992E-22, 1.0863906045969114E-21, 1.1800799775461269E-21,
-            1.2754075534831208E-21, 1.372333117637729E-21, 1.4708208794375214E-21, 1.5708388257440445E-21,
-            1.6723581984374566E-21, 1.7753530675030514E-21, 1.8797999785104595E-21, 1.9856776587832504E-21,
-            2.0929667704053244E-21, 2.201649700995824E-21, 2.311710385230618E-21, 2.4231341516125464E-21,
-            2.535907590142089E-21, 2.650018437417054E-21, 2.765455476366039E-21, 2.8822084483468604E-21,
-            3.000267975754771E-21, 3.1196254936130377E-21, 3.240273188880175E-21, 3.3622039464187092E-21,
-            3.485411300740904E-21, 3.6098893927859475E-21, 3.735632931097177E-21, 3.862637156862005E-21,
-            3.990897812355284E-21, 4.120411112391895E-21, 4.251173718448891E-21, 4.383182715163374E-21,
-            4.5164355889510656E-21, 4.6509302085234806E-21, 4.7866648071096E-21, 4.923637966211997E-21,
-            5.061848600747899E-21, 5.201295945443473E-21, 5.341979542364895E-21, 5.483899229483096E-21,
-            5.627055130180635E-21, 5.7714476436191935E-21, 5.917077435895068E-21, 6.063945431917703E-21,
-            6.212052807953168E-21, 6.3614009847804375E-21, 6.511991621413643E-21, 6.6638266093481696E-21,
-            6.816908067292628E-21, 6.971238336352438E-21, 7.126819975634082E-21, 7.283655758242034E-21,
-            7.441748667643017E-21, 7.601101894374635E-21, 7.761718833077541E-21, 7.923603079832257E-21,
-            8.086758429783484E-21, 8.251188875036333E-21, 8.416898602810326E-21, 8.58389199383831E-21,
-            8.752173620998646E-21, 8.921748248170071E-21, 9.09262082929965E-21, 9.264796507675128E-21,
-            9.438280615393829E-21, 9.613078673021033E-21, 9.789196389431416E-21, 9.966639661827884E-21,
-            1.0145414575932636E-20, 1.0325527406345955E-20, 1.0506984617068672E-20, 1.0689792862184811E-20,
-            1.0873958986701341E-20, 1.10594900275424E-20, 1.1246393214695825E-20, 1.1434675972510121E-20,
+        protected static final double[] X = {3.9421662825398133E-19, 3.720494500411901E-19, 3.582702448062868E-19,
+            3.480747623654025E-19, 3.3990177171882136E-19, 3.330377836034014E-19, 3.270943881761755E-19,
+            3.21835771324951E-19, 3.171075854184043E-19, 3.1280307407034065E-19, 3.088452065580402E-19,
+            3.051765062410735E-19, 3.01752902925846E-19, 2.985398344070532E-19, 2.9550967462801797E-19,
+            2.9263997988491663E-19, 2.8991225869977476E-19, 2.873110878022629E-19, 2.8482346327101335E-19,
+            2.824383153519439E-19, 2.801461396472703E-19, 2.7793871261807797E-19, 2.758088692141121E-19,
+            2.737503269830876E-19, 2.7175754543391047E-19, 2.6982561247538484E-19, 2.6795015188771505E-19,
+            2.6612724730440033E-19, 2.6435337927976633E-19, 2.626253728202844E-19, 2.609403533522414E-19,
+            2.5929570954331E-19, 2.5768906173214726E-19, 2.561182349771961E-19, 2.545812359339336E-19,
+            2.530762329237246E-19, 2.51601538677984E-19, 2.501555953364619E-19, 2.487369613540316E-19,
+            2.4734430003079206E-19, 2.4597636942892726E-19, 2.446320134791245E-19, 2.4331015411139206E-19,
+            2.4200978427132955E-19, 2.407299617044588E-19, 2.3946980340903347E-19, 2.3822848067252674E-19,
+            2.37005214619318E-19, 2.357992722074133E-19, 2.346099626206997E-19, 2.3343663401054455E-19,
+            2.322786705467384E-19, 2.3113548974303765E-19, 2.300065400270424E-19, 2.2889129852797606E-19,
+            2.2778926905921897E-19, 2.266999802752732E-19, 2.2562298398527416E-19, 2.245578536072726E-19,
+            2.235041827493391E-19, 2.2246158390513294E-19, 2.214296872529625E-19, 2.2040813954857555E-19,
+            2.19396603102976E-19, 2.183947548374962E-19, 2.1740228540916853E-19, 2.164188984001652E-19,
+            2.1544430956570613E-19, 2.1447824613540345E-19, 2.1352044616350571E-19, 2.1257065792395107E-19,
+            2.1162863934653125E-19, 2.1069415749082026E-19, 2.0976698805483467E-19, 2.0884691491567363E-19,
+            2.0793372969963634E-19, 2.0702723137954107E-19, 2.061272258971713E-19, 2.0523352580895635E-19,
+            2.0434594995315797E-19, 2.0346432313698148E-19, 2.0258847584216418E-19, 2.0171824394771313E-19,
+            2.008534684685753E-19, 1.9999399530912015E-19, 1.9913967503040585E-19, 1.9829036263028144E-19,
+            1.9744591733545175E-19, 1.9660620240469857E-19, 1.9577108494251485E-19, 1.9494043572246307E-19,
+            1.941141290196216E-19, 1.9329204245152935E-19, 1.9247405682708168E-19, 1.9166005600287074E-19,
+            1.9084992674649826E-19, 1.900435586064234E-19, 1.8924084378793725E-19, 1.8844167703488436E-19,
+            1.8764595551677749E-19, 1.868535787209745E-19, 1.8606444834960934E-19, 1.8527846822098793E-19,
+            1.8449554417517928E-19, 1.8371558398354868E-19, 1.8293849726199566E-19, 1.8216419538767393E-19,
+            1.8139259141898448E-19, 1.8062360001864453E-19, 1.7985713737964743E-19, 1.7909312115393845E-19,
+            1.78331470383642E-19, 1.7757210543468428E-19, 1.7681494793266395E-19, 1.760599207008314E-19,
+            1.753069477000441E-19, 1.7455595397057217E-19, 1.7380686557563475E-19, 1.7305960954655264E-19,
+            1.7231411382940904E-19, 1.7157030723311378E-19, 1.7082811937877138E-19, 1.7008748065025788E-19,
+            1.6934832214591352E-19, 1.686105756312635E-19, 1.6787417349268046E-19, 1.6713904869190636E-19,
+            1.6640513472135291E-19, 1.6567236556010242E-19, 1.6494067563053266E-19, 1.6420999975549115E-19,
+            1.6348027311594532E-19, 1.627514312090366E-19, 1.6202340980646725E-19, 1.6129614491314931E-19,
+            1.605695727260459E-19, 1.598436295931348E-19, 1.591182519724249E-19, 1.5839337639095554E-19,
+            1.57668939403708E-19, 1.569448775523589E-19, 1.562211273238026E-19, 1.554976251083707E-19,
+            1.547743071576727E-19, 1.540511095419833E-19, 1.5332796810709688E-19, 1.5260481843056974E-19,
+            1.5188159577726683E-19, 1.5115823505412761E-19, 1.5043467076406199E-19, 1.4971083695888395E-19,
+            1.4898666719118714E-19, 1.4826209446506113E-19, 1.4753705118554365E-19, 1.468114691066983E-19,
+            1.4608527927820112E-19, 1.453584119903145E-19, 1.4463079671711862E-19, 1.4390236205786415E-19,
+            1.4317303567630177E-19, 1.4244274423783481E-19, 1.4171141334433217E-19, 1.4097896746642792E-19,
+            1.4024532987312287E-19, 1.3951042255849034E-19, 1.3877416616527576E-19, 1.3803647990516385E-19,
+            1.3729728147547174E-19, 1.3655648697200824E-19, 1.3581401079782068E-19, 1.35069765567529E-19,
+            1.3432366200692418E-19, 1.3357560884748263E-19, 1.3282551271542047E-19, 1.3207327801488087E-19,
+            1.3131880680481524E-19, 1.3056199866908076E-19, 1.2980275057923788E-19, 1.2904095674948608E-19,
+            1.2827650848312727E-19, 1.2750929400989213E-19, 1.2673919831340482E-19, 1.2596610294799512E-19,
+            1.2518988584399374E-19, 1.2441042110056523E-19, 1.2362757876504165E-19, 1.2284122459762072E-19,
+            1.2205121982017852E-19, 1.2125742084782245E-19, 1.2045967900166973E-19, 1.196578402011802E-19,
+            1.1885174463419555E-19, 1.180412264026409E-19, 1.1722611314162064E-19, 1.164062256093911E-19,
+            1.1558137724540874E-19, 1.1475137369333185E-19, 1.1391601228549047E-19, 1.1307508148492592E-19,
+            1.1222836028063025E-19, 1.1137561753107903E-19, 1.1051661125053526E-19, 1.0965108783189755E-19,
+            1.0877878119905372E-19, 1.0789941188076655E-19, 1.070126859970364E-19, 1.0611829414763286E-19,
+            1.0521591019102928E-19, 1.0430518990027552E-19, 1.0338576948035472E-19, 1.0245726392923699E-19,
+            1.015192652220931E-19, 1.0057134029488235E-19, 9.961302879967281E-20, 9.864384059945991E-20,
+            9.766325296475582E-20, 9.667070742762345E-20, 9.566560624086667E-20, 9.464730838043321E-20,
+            9.361512501732351E-20, 9.256831437088728E-20, 9.150607583763877E-20, 9.042754326772572E-20,
+            8.933177723376368E-20, 8.821775610232788E-20, 8.708436567489232E-20, 8.593038710961216E-20,
+            8.475448276424435E-20, 8.355517950846234E-20, 8.233084893358536E-20, 8.107968372912985E-20,
+            7.979966928413386E-20, 7.848854928607274E-20, 7.714378370093469E-20, 7.576249697946757E-20,
+            7.434141357848533E-20, 7.287677680737843E-20, 7.136424544352537E-20, 6.979876024076107E-20,
+            6.817436894479905E-20, 6.648399298619854E-20, 6.471911034516277E-20, 6.28693148131037E-20,
+            6.092168754828126E-20, 5.885987357557682E-20, 5.666267511609098E-20, 5.430181363089457E-20,
+            5.173817174449422E-20, 4.8915031722398545E-20, 4.57447418907553E-20, 4.2078802568583416E-20,
+            3.762598672240476E-20, 3.162858980588188E-20, 0.0};
+        /** Overhang table. Y_i = f(X_i). */
+        protected static final double[] Y = {1.4598410796619063E-22, 3.0066613427942797E-22, 4.612972881510347E-22,
+            6.266335004923436E-22, 7.959452476188154E-22, 9.687465502170504E-22, 1.144687700237944E-21,
+            1.3235036304379167E-21, 1.504985769205313E-21, 1.6889653000719298E-21, 1.8753025382711626E-21,
+            2.063879842369519E-21, 2.2545966913644708E-21, 2.44736615188018E-21, 2.6421122727763533E-21,
+            2.8387681187879908E-21, 3.0372742567457284E-21, 3.237577569998659E-21, 3.439630315794878E-21,
+            3.64338936579978E-21, 3.848815586891231E-21, 4.0558733309492775E-21, 4.264530010428359E-21,
+            4.474755742230507E-21, 4.686523046535558E-21, 4.899806590277526E-21, 5.114582967210549E-21,
+            5.330830508204617E-21, 5.548529116703176E-21, 5.767660125269048E-21, 5.988206169917846E-21,
+            6.210151079544222E-21, 6.433479778225721E-21, 6.65817819857139E-21, 6.884233204589318E-21,
+            7.11163252279571E-21, 7.340364680490309E-21, 7.570418950288642E-21, 7.801785300137974E-21,
+            8.034454348157002E-21, 8.268417321733312E-21, 8.503666020391502E-21, 8.740192782010952E-21,
+            8.97799045202819E-21, 9.217052355306144E-21, 9.457372270392882E-21, 9.698944405926943E-21,
+            9.941763378975842E-21, 1.0185824195119818E-20, 1.043112223011477E-20, 1.0677653212987396E-20,
+            1.0925413210432004E-20, 1.1174398612392891E-20, 1.1424606118728715E-20, 1.1676032726866302E-20,
+            1.1928675720361027E-20, 1.2182532658289373E-20, 1.2437601365406785E-20, 1.2693879923010674E-20,
+            1.2951366660454145E-20, 1.321006014726146E-20, 1.3469959185800733E-20, 1.3731062804473644E-20,
+            1.3993370251385596E-20, 1.4256880988463136E-20, 1.452159468598837E-20, 1.4787511217522902E-20,
+            1.505463065519617E-20, 1.5322953265335218E-20, 1.5592479504415048E-20, 1.5863210015310328E-20,
+            1.6135145623830982E-20, 1.6408287335525592E-20, 1.6682636332737932E-20, 1.6958193971903124E-20,
+            1.7234961781071113E-20, 1.7512941457646084E-20, 1.7792134866331487E-20, 1.807254403727107E-20,
+            1.8354171164377277E-20, 1.8637018603838945E-20, 1.8921088872801004E-20, 1.9206384648209468E-20,
+            1.9492908765815636E-20, 1.9780664219333857E-20, 2.006965415974784E-20, 2.035988189476086E-20,
+            2.0651350888385696E-20, 2.094406476067054E-20, 2.1238027287557466E-20, 2.1533242400870487E-20,
+            2.1829714188430474E-20, 2.2127446894294597E-20, 2.242644491911827E-20, 2.2726712820637798E-20,
+            2.3028255314272276E-20, 2.3331077273843558E-20, 2.3635183732413286E-20, 2.3940579883236352E-20,
+            2.4247271080830277E-20, 2.455526284216033E-20, 2.4864560847940368E-20, 2.5175170944049622E-20,
+            2.548709914306593E-20, 2.5800351625915997E-20, 2.6114934743643687E-20, 2.6430855019297323E-20,
+            2.674811914993741E-20, 2.7066734008766247E-20, 2.7386706647381193E-20, 2.770804429815356E-20,
+            2.803075437673527E-20, 2.835484448469575E-20, 2.868032241229163E-20, 2.9007196141372126E-20,
+            2.933547384842322E-20, 2.966516390775399E-20, 2.9996274894828624E-20, 3.0328815589748056E-20,
+            3.066279498088529E-20, 3.099822226867876E-20, 3.133510686958861E-20, 3.167345842022056E-20,
+            3.201328678162299E-20, 3.235460204376261E-20, 3.2697414530184806E-20, 3.304173480286495E-20,
+            3.338757366725735E-20, 3.373494217754894E-20, 3.408385164212521E-20, 3.443431362925624E-20,
+            3.4786339973011376E-20, 3.5139942779411164E-20, 3.549513443282617E-20, 3.585192760263246E-20,
+            3.621033525013417E-20, 3.6570370635764384E-20, 3.693204732657588E-20, 3.729537920403425E-20,
+            3.76603804721264E-20, 3.8027065665798284E-20, 3.839544965973665E-20, 3.876554767751017E-20,
+            3.9137375301086406E-20, 3.951094848074217E-20, 3.988628354538543E-20, 4.0263397213308566E-20,
+            4.064230660339354E-20, 4.1023029246790967E-20, 4.140558309909644E-20, 4.178998655304882E-20,
+            4.217625845177682E-20, 4.256441810262176E-20, 4.29544852915662E-20, 4.334648029830012E-20,
+            4.3740423911958146E-20, 4.4136337447563716E-20, 4.4534242763218286E-20, 4.4934162278076256E-20,
+            4.5336118991149025E-20, 4.5740136500984466E-20, 4.614623902627128E-20, 4.655445142742113E-20,
+            4.696479922918509E-20, 4.737730864436494E-20, 4.779200659868417E-20, 4.820892075688811E-20,
+            4.8628079550147814E-20, 4.9049512204847653E-20, 4.9473248772842596E-20, 4.9899320163277674E-20,
+            5.032775817606897E-20, 5.0758595537153414E-20, 5.1191865935622696E-20, 5.162760406286606E-20,
+            5.2065845653856416E-20, 5.2506627530725194E-20, 5.294998764878345E-20, 5.3395965145159426E-20,
+            5.3844600390237576E-20, 5.429593504209936E-20, 5.475001210418387E-20, 5.520687598640507E-20,
+            5.566657256998382E-20, 5.612914927627579E-20, 5.659465513990248E-20, 5.706314088652056E-20,
+            5.753465901559692E-20, 5.800926388859122E-20, 5.848701182298758E-20, 5.89679611926598E-20,
+            5.945217253510347E-20, 5.99397086661226E-20, 6.043063480261893E-20, 6.092501869420053E-20,
+            6.142293076440286E-20, 6.192444426240153E-20, 6.242963542619394E-20, 6.293858365833621E-20,
+            6.345137171544756E-20, 6.396808591283496E-20, 6.448881634575274E-20, 6.501365712899535E-20,
+            6.554270665673171E-20, 6.607606788473072E-20, 6.66138486374042E-20, 6.715616194241298E-20,
+            6.770312639595058E-20, 6.825486656224641E-20, 6.881151341132782E-20, 6.937320479965968E-20,
+            6.994008599895911E-20, 7.05123102792795E-20, 7.109003955339717E-20, 7.16734450906448E-20,
+            7.226270830965578E-20, 7.285802166105734E-20, 7.34595896130358E-20, 7.406762975496755E-20,
+            7.468237403705282E-20, 7.530407016722667E-20, 7.593298319069855E-20, 7.656939728248375E-20,
+            7.721361778948768E-20, 7.786597356641702E-20, 7.852681965945675E-20, 7.919654040385056E-20,
+            7.987555301703797E-20, 8.056431178890163E-20, 8.126331299642618E-20, 8.19731007037063E-20,
+            8.269427365263403E-20, 8.342749350883679E-20, 8.417349480745342E-20, 8.493309705283207E-20,
+            8.57072195782309E-20, 8.64968999859307E-20, 8.730331729565533E-20, 8.81278213788595E-20,
+            8.897197092819667E-20, 8.983758323931406E-20, 9.072680069786954E-20, 9.164218148406354E-20,
+            9.258682640670276E-20, 9.356456148027886E-20, 9.458021001263618E-20, 9.564001555085036E-20,
+            9.675233477050313E-20, 9.792885169780883E-20, 9.918690585753133E-20, 1.0055456271343397E-19,
+            1.0208407377305566E-19, 1.0390360993240711E-19, 1.0842021724855044E-19};
+
+        /** Underlying source of randomness. */
+        protected final UniformRandomProvider rng;
+        /** Exponential sampler used for the long tail. */
+        protected final ContinuousSampler exponential;
+
+        /**
+         * @param rng Generator of uniformly distributed random numbers.
+         */
+        ModifiedZigguratNormalizedGaussianSamplerIntMap(UniformRandomProvider rng) {
+            this.rng = rng;
+            exponential = new ModifiedZigguratExponentialSamplerIntMap(rng);
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public double sample() {
+            final long xx = rng.nextLong();
+            // Float multiplication squashes these last 8 bits, so they can be used to sample i
+            final int i = ((int) xx) & 0xff;
+
+            if (i < I_MAX) {
+                // Early exit.
+                // Branch frequency: 0.988280
+                return X[i] * xx;
+            }
+
+            // Recycle bits then advance RNG:
+            // u1 = RANDOM_INT63();
+            long u1 = xx & MAX_INT64;
+            // Another squashed, recyclable bit
+            // double sign_bit = u1 & 0x100 ? 1. : -1.
+            // Use 2 - 1 or 0 - 1
+            final double signBit = ((u1 >>> 7) & 0x2) - 1.0;
+            final int j = normSampleA();
+            // Four kinds of overhangs:
+            //  j = 0                :  Sample from tail
+            //  0 < j < J_INFLECTION :  Overhang is concave; only sample from Lower-Left triangle
+            //  j = J_INFLECTION     :  Must sample from entire overhang rectangle
+            //  j > J_INFLECTION     :  Overhangs are convex; implicitly accept point in Lower-Left triangle
+            //
+            // Conditional statements are arranged such that the more likely outcomes are first.
+            double x;
+            if (j > J_INFLECTION) {
+                // Convex overhang
+                // Branch frequency: 0.00891413
+                for (;;) {
+                    x = fastPrngSampleX(j, u1);
+                    final long uDiff = randomInt63() - u1;
+                    if (uDiff >= 0) {
+                        // Lower-left triangle
+                        break;
+                    }
+                    if (uDiff >= MAX_IE &&
+                        // Within maximum distance of f(x) from the triangle hypotenuse.
+                        // Long.MIN_VALUE is used as an unsigned int with value 2^63:
+                        // uy = Long.MIN_VALUE - (ux + uDiff)
+                        fastPrngSampleY(j, Long.MIN_VALUE - (u1 + uDiff)) < Math.exp(-0.5 * x * x)) {
+                        break;
+                    }
+                    // uDiff < MAX_IE (upper-right triangle) or rejected as above the curve
+                    u1 = randomInt63();
+                }
+            } else if (j == 0) {
+                // Tail
+                // Branch frequency: 0.000277067
+                do {
+                    x = ONE_OVER_X_0 * exponential.sample();
+                } while (exponential.sample() < 0.5 * x * x);
+                x += X_0;
+            } else if (j < J_INFLECTION) {
+                // Concave overhang
+                // Branch frequency: 0.00251223
+                for (;;) {
+                    // U_x <- min(U_1, U_2)
+                    // distance <- | U_1 - U_2 |
+                    // U_y <- 1 - (U_x + distance)
+                    long uDiff = randomInt63() - u1;
+                    if (uDiff < 0) {
+                        uDiff = -uDiff;
+                        u1 -= uDiff;
+                    }
+                    x = fastPrngSampleX(j, u1);
+                    if (uDiff > MIN_IE)  {
+                        break;
+                    }
+                    if (fastPrngSampleY(j, Long.MIN_VALUE - (u1 + uDiff)) < Math.exp(-0.5 * x * x)) {
+                        break;
+                    }
+                    u1 = randomInt63();
+                }
+            } else {
+                // Inflection point
+                // Branch frequency: 0.0000161147
+                for (;;) {
+                    x = fastPrngSampleX(j, u1);
+                    if (fastPrngSampleY(j, randomInt63()) < Math.exp(-0.5 * x * x)) {
+                        break;
+                    }
+                    u1 = randomInt63();
+                }
+            }
+            return signBit * x;
+        }
+
+        /**
+         * Alias sampling.
+         * See http://scorevoting.net/WarrenSmithPages/homepage/sampling.abs
+         *
+         * @return the alias
+         */
+        protected int normSampleA() {
+            final long x = rng.nextLong();
+            // j <- I(0, 256)
+            final int j = ((int) x) & 0xff;
+            return x >= IPMF[j] ? MAP[j] : j;
+        }
+
+        /**
+         * Return a positive long in {@code [0, 2^63)}.
+         *
+         * @return the long
+         */
+        protected long randomInt63() {
+            return rng.nextLong() & MAX_INT64;
+        }
+
+        /**
+         * Auxilary function to see if rejection sampling is required in the overhang.
+         * See Fig. 2 in the main text.
+         *
+         * @param j j
+         * @param ux ux
+         * @return the sample
+         */
+        protected static double fastPrngSampleX(int j, long ux) {
+            return X[j] * TWO_POW_63 + (X[j - 1] - X[j]) * ux;
+        }
+
+        /**
+         * Auxilary function to see if rejection sampling is required in the overhang.
+         * See Fig. 2 in the main text.
+         *
+         * @param i i
+         * @param uy uy
+         * @return the sample
+         */
+        protected static double fastPrngSampleY(int i, long uy) {
+            return Y[i - 1] * TWO_POW_63 + (Y[i] - Y[i - 1]) * uy;
+        }
+    }
+
+    /**
+     * Modified Ziggurat method for sampling from an exponential distribution.
+     *
+     * <p>Uses the algorithm from:
+     *
+     * <blockquote>
+     * McFarland, C.D. (2016)<br>
+     * "A modified ziggurat algorithm for generating exponentially and normally distributed pseudorandom numbers".<br>
+     * <i>Journal of Statistical Computation and Simulation</i> <b>86</b>, 1281-1294.
+     * </blockquote>
+     *
+     * @see <a href="https://www.tandfonline.com/doi/abs/10.1080/00949655.2015.1060234">
+     * McFarland (2016) JSCS 86, 1281-1294</a>
+     */
+    static class ModifiedZigguratExponentialSampler implements ContinuousSampler {
+        /** Maximum i value for early exit. */
+        private static final int I_MAX = 252;
+        /** Maximum distance value for early exit. */
+        private static final long IE_MAX = 513303011048449570L;
+        /** Beginning of tail. */
+        private static final double X_0 = 7.569274694148063;
+
+        /** The alias map. An integer in [0, 255] stored as a byte to save space. */
+        private static final byte[] MAP = toBytes(new int[] {0, 0, 1, 235, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+            1, 1, 1, 2, 2, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+            252, 252, 252, 252, 252, 252, 252, 252, 252, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251,
+            251, 250, 250, 250, 250, 250, 250, 250, 249, 249, 249, 249, 249, 249, 248, 248, 248, 248, 247, 247, 247,
+            247, 246, 246, 246, 245, 245, 244, 244, 243, 243, 242, 241, 241, 240, 239, 237, 3, 3, 4, 4, 6, 0, 0, 0, 0,
+            236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 2, 0, 0, 0});
+        /** The alias inverse PMF. */
+        private static final long[] IPMF = {9223372036854773904L, 1623796909450835018L, 2664290944894291308L,
+            7387971354164061021L, 6515064486552723158L, 8840508362680718891L, 6099647593382936415L,
+            7673130333659513775L, 6220332867583438096L, 5045979640552813698L, 4075305837223955523L,
+            3258413672162525427L, 2560664887087762532L, 1957224924672899637L, 1429800935350577509L, 964606309710808246L,
+            551043923599587126L, 180827629096890295L, -152619738120023625L, -454588624410291545L, -729385126147774968L,
+            -980551509819446936L, -1211029700667463960L, -1423284293868548440L, -1619396356369050407L,
+            -1801135830956211623L, -1970018048575618087L, -2127348289059705319L, -2274257249303686407L,
+            -2411729520096655303L, -2540626634159180934L, -2661705860113406470L, -2775635634532450566L,
+            -2883008316030465190L, -2984350790383654790L, -3080133339198116454L, -3170777096303091110L,
+            -3256660348483819078L, -3338123885075136262L, -3415475560473299110L, -3488994201966428229L,
+            -3558932970354473157L, -3625522261068041093L, -3688972217741989381L, -3749474917563782629L,
+            -3807206277531056133L, -3862327722496843557L, -3914987649156779685L, -3965322714631865221L,
+            -4013458973776895589L, -4059512885612783333L, -4103592206186241029L, -4145796782586128069L,
+            -4186219260694346949L, -4224945717447275173L, -4262056226866285509L, -4297625367836519557L,
+            -4331722680528537317L, -4364413077437472517L, -4395757214229401700L, -4425811824915135780L,
+            -4454630025296932548L, -4482261588141290436L, -4508753193105288068L, -4534148654077808964L,
+            -4558489126279958148L, -4581813295192216580L, -4604157549138257636L, -4625556137145255269L,
+            -4646041313519104421L, -4665643470413305925L, -4684391259530326597L, -4702311703971761733L,
+            -4719430301145103269L, -4735771117539946308L, -4751356876102087236L, -4766209036859134052L,
+            -4780347871386013380L, -4793792531638892068L, -4806561113635132708L, -4818670716409306532L,
+            -4830137496634465604L, -4840976719260837892L, -4851202804490348868L, -4860829371376459908L,
+            -4869869278311657508L, -4878334660640770948L, -4886236965617427236L, -4893586984900802596L,
+            -4900394884772702724L, -4906670234238885316L, -4912422031164496804L, -4917658726580119812L,
+            -4922388247283532292L, -4926618016851066692L, -4930354975163335236L, -4933605596540651332L,
+            -4936375906575303844L, -4938671497741365892L, -4940497543854575684L, -4941858813449629540L,
+            -4942759682136115044L, -4943204143989086820L, -4943195822025527940L, -4942737977813206404L,
+            -4941833520255033284L, -4940485013586738820L, -4938694684624359428L, -4936464429291795972L,
+            -4933795818458825604L, -4930690103114057988L, -4927148218896864068L, -4923170790008275908L,
+            -4918758132519213508L, -4913910257091645764L, -4908626871126539204L, -4902907380349534020L,
+            -4896750889844272900L, -4890156204540531076L, -4883121829162554372L, -4875645967641781188L,
+            -4867726521994927044L, -4859361090668103364L, -4850546966345113668L, -4841281133215539076L,
+            -4831560263698491972L, -4821380714613447492L, -4810738522790066116L, -4799629400105481988L,
+            -4788048727936307268L, -4775991551010515012L, -4763452570642114308L, -4750426137329494532L,
+            -4736906242696389124L, -4722886510751377669L, -4708360188440088965L, -4693320135461420933L,
+            -4677758813316108101L, -4661668273553489093L, -4645040145179241541L, -4627865621182772101L,
+            -4610135444140930052L, -4591839890849345476L, -4572968755929961540L, -4553511334358205764L,
+            -4533456402849101572L, -4512792200036278980L, -4491506405372580932L, -4469586116675402436L,
+            -4447017826233108036L, -4423787395382284804L, -4399880027458416324L, -4375280239014115077L,
+            -4349971829190472197L, -4323937847117721861L, -4297160557210933573L, -4269621402214949829L,
+            -4241300963840749253L, -4212178920821861701L, -4182234004204451589L, -4151443949668877253L,
+            -4119785446662287621L, -4087234084103201605L, -4053764292396156933L, -4019349281473081925L,
+            -3983960974549692677L, -3947569937258423301L, -3910145301787345669L, -3871654685619032069L,
+            -3832064104425388805L, -3791337878631544901L, -3749438533114327493L, -3706326689447984389L,
+            -3661960950051848261L, -3616297773528534789L, -3569291340409189253L, -3520893408440946053L,
+            -3471053156460654341L, -3419717015797782598L, -3366828488034805510L, -3312327947826460358L,
+            -3256152429334010374L, -3198235394669719110L, -3138506482563172742L, -3076891235255162822L,
+            -3013310801389730758L, -2947681612411374854L, -2879915029671670790L, -2809916959107513734L,
+            -2737587429961866118L, -2662820133571325574L, -2585501917733379974L, -2505512231579385223L,
+            -2422722515205211655L, -2336995527534088455L, -2248184604988727559L, -2156132842510764935L,
+            -2060672187261025415L, -1961622433929371911L, -1858790108950105479L, -1751967229002895623L,
+            -1640929916937142791L, -1525436855617582472L, -1405227557075253256L, -1280020420662649992L,
+            -1149510549536596104L, -1013367289578704904L, -871231448632104200L, -722712146453667848L,
+            -567383236774435977L, -404779231966938249L, -234390647591545737L, -55658667960119305L, 132030985907841399L,
+            329355128892811767L, 537061298001085174L, 755977262693564150L, 987022116608033270L, 1231219266829431286L,
+            1489711711346518517L, 1763780090187553909L, 2054864117341795061L, 2364588157623768948L,
+            2694791916990503284L, 3047567482883476212L, 3425304305830816371L, 3830744187097297907L,
+            4267048975685830386L, 4737884547990017266L, 5247525842198998257L, 5800989391535355377L,
+            6404202162993295344L, 7064218894258540527L, 7789505049452331503L, 8590309807749444846L,
+            7643763810684490059L, 8891950541491446071L, 5457384281016205975L, 9083704440929283969L,
+            7976211653914433372L, 8178631350487117494L, 2821287825726744835L, 6322989683301709657L,
+            4309503753387611426L, 4685170734960170474L, 8404845967535199663L, 7330522972447554153L,
+            1960945799076992020L, 4742910674644898996L, -751799822533509968L, 7023456603741959948L,
+            3843116882594676172L, 3927231442413902976L, -9223372036854775808L, -9223372036854775808L,
+            -9223372036854775808L};
+        /**
+         * The precomputed ziggurat lengths, denoted X_i in the main text. X_i = length of
+         * ziggurat layer i.
+         */
+        private static final double[] X = {8.206624067534882E-19, 7.397373235160728E-19, 6.913331337791529E-19,
+            6.564735882096453E-19, 6.291253995981851E-19, 6.065722412960496E-19, 5.873527610373727E-19,
+            5.705885052853694E-19, 5.557094569162239E-19, 5.423243890374395E-19, 5.301529769650878E-19,
+            5.189873925770806E-19, 5.086692261799833E-19, 4.990749293879647E-19, 4.901062589444954E-19,
+            4.816837901064919E-19, 4.737423865364471E-19, 4.662279580719682E-19, 4.590950901778405E-19,
+            4.523052779065815E-19, 4.458255881635396E-19, 4.396276312636838E-19, 4.336867596710647E-19,
+            4.2798143618469714E-19, 4.224927302706489E-19, 4.172039125346411E-19, 4.1210012522465616E-19,
+            4.0716811225869233E-19, 4.0239599631006903E-19, 3.9777309342877357E-19, 3.93289757853345E-19,
+            3.8893725129310323E-19, 3.8470763218720385E-19, 3.8059366138180143E-19, 3.765887213854473E-19,
+            3.7268674692030177E-19, 3.688821649224816E-19, 3.651698424880007E-19, 3.6154504153287473E-19,
+            3.5800337915318032E-19, 3.545407928453343E-19, 3.5115350988784242E-19, 3.478380203003096E-19,
+            3.4459105288907336E-19, 3.4140955396563316E-19, 3.3829066838741162E-19, 3.3523172262289E-19,
+            3.3223020958685874E-19, 3.292837750280447E-19, 3.263902052820205E-19, 3.2354741622810815E-19,
+            3.207534433108079E-19, 3.180064325047861E-19, 3.1530463211820845E-19, 3.1264638534265134E-19,
+            3.100301234693421E-19, 3.07454359701373E-19, 3.049176835000556E-19, 3.0241875541094565E-19,
+            2.999563023214455E-19, 2.975291131074259E-19, 2.9513603463113224E-19, 2.9277596805684267E-19,
+            2.9044786545442563E-19, 2.8815072666416712E-19, 2.858835963990693E-19, 2.8364556156331615E-19,
+            2.81435748767798E-19, 2.7925332202553125E-19, 2.770974806115288E-19, 2.7496745707320232E-19,
+            2.7286251537873397E-19, 2.7078194919206054E-19, 2.687250802641905E-19, 2.666912569315344E-19,
+            2.646798527127889E-19, 2.6269026499668434E-19, 2.6072191381359757E-19, 2.5877424068465143E-19,
+            2.568467075424817E-19, 2.549387957183548E-19, 2.530500049907748E-19, 2.511798526911271E-19,
+            2.4932787286227806E-19, 2.474936154663866E-19, 2.456766456384867E-19, 2.438765429826784E-19,
+            2.4209290090801527E-19, 2.403253260014054E-19, 2.3857343743505147E-19, 2.368368664061465E-19,
+            2.3511525560671253E-19, 2.3340825872163284E-19, 2.3171553995306794E-19, 2.3003677356958333E-19,
+            2.283716434784348E-19, 2.2671984281957174E-19, 2.250810735800194E-19, 2.234550462273959E-19,
+            2.2184147936140775E-19, 2.2024009938224424E-19, 2.186506401748684E-19, 2.1707284280826716E-19,
+            2.1550645524878675E-19, 2.1395123208673778E-19, 2.124069342755064E-19, 2.1087332888245875E-19,
+            2.0935018885097035E-19, 2.0783729277295508E-19, 2.0633442467130712E-19, 2.0484137379170616E-19,
+            2.0335793440326865E-19, 2.018839056075609E-19, 2.0041909115551697E-19, 1.9896329927183254E-19,
+            1.975163424864309E-19, 1.9607803747261946E-19, 1.9464820489157862E-19, 1.9322666924284314E-19,
+            1.9181325872045647E-19, 1.904078050744948E-19, 1.8901014347767504E-19, 1.8762011239677479E-19,
+            1.8623755346860768E-19, 1.8486231138030984E-19, 1.8349423375370566E-19, 1.8213317103353295E-19,
+            1.8077897637931708E-19, 1.7943150556069476E-19, 1.7809061685599652E-19, 1.7675617095390567E-19,
+            1.7542803085801941E-19, 1.741060617941453E-19, 1.727901311201724E-19, 1.7148010823836362E-19,
+            1.7017586450992059E-19, 1.6887727317167824E-19, 1.6758420925479093E-19, 1.6629654950527621E-19,
+            1.650141723062866E-19, 1.6373695760198277E-19, 1.624647868228856E-19, 1.6119754281258616E-19,
+            1.5993510975569615E-19, 1.586773731069231E-19, 1.5742421952115544E-19, 1.5617553678444595E-19,
+            1.5493121374578016E-19, 1.5369114024951992E-19, 1.524552070684102E-19, 1.5122330583703858E-19,
+            1.499953289856356E-19, 1.4877116967410352E-19, 1.4755072172615974E-19, 1.4633387956347966E-19,
+            1.4512053813972103E-19, 1.439105928743099E-19, 1.4270393958586506E-19, 1.415004744251338E-19,
+            1.4030009380730888E-19, 1.3910269434359025E-19, 1.3790817277185197E-19, 1.3671642588626657E-19,
+            1.3552735046573446E-19, 1.3434084320095729E-19, 1.3315680061998685E-19, 1.3197511901207148E-19,
+            1.3079569434961214E-19, 1.2961842220802957E-19, 1.28443197683331E-19, 1.2726991530715219E-19,
+            1.2609846895903523E-19, 1.2492875177568625E-19, 1.237606560569394E-19, 1.225940731681333E-19,
+            1.2142889343858445E-19, 1.2026500605581765E-19, 1.1910229895518744E-19, 1.1794065870449425E-19,
+            1.1677997038316715E-19, 1.1562011745554883E-19, 1.144609816377787E-19, 1.1330244275772562E-19,
+            1.1214437860737343E-19, 1.109866647870073E-19, 1.0982917454048923E-19, 1.086717785808435E-19,
+            1.0751434490529747E-19, 1.0635673859884002E-19, 1.0519882162526621E-19, 1.0404045260457141E-19,
+            1.0288148657544097E-19, 1.0172177474144965E-19, 1.0056116419943559E-19, 9.939949764834668E-20,
+            9.823661307666745E-20, 9.70723434263201E-20, 9.590651623069063E-20, 9.47389532241542E-20,
+            9.356946992015904E-20, 9.239787515456947E-20, 9.122397059055647E-20, 9.004755018085287E-20,
+            8.886839958264763E-20, 8.768629551976745E-20, 8.650100508607102E-20, 8.531228498314119E-20,
+            8.411988068438521E-20, 8.292352551651342E-20, 8.17229396480345E-20, 8.051782897283921E-20,
+            7.930788387509923E-20, 7.809277785952443E-20, 7.687216602842904E-20, 7.564568338396512E-20,
+            7.441294293017913E-20, 7.317353354509333E-20, 7.192701758763107E-20, 7.067292819766679E-20,
+            6.941076623950036E-20, 6.813999682925642E-20, 6.686004537461023E-20, 6.557029304021008E-20,
+            6.427007153336853E-20, 6.295865708092356E-20, 6.163526343814314E-20, 6.02990337321517E-20,
+            5.894903089285018E-20, 5.758422635988593E-20, 5.62034866695974E-20, 5.480555741349931E-20,
+            5.3389043909003295E-20, 5.1952387717989917E-20, 5.0493837866338355E-20, 4.901141522262949E-20,
+            4.7502867933366117E-20, 4.5965615001265455E-20, 4.4396673897997565E-20, 4.279256630214859E-20,
+            4.1149193273430015E-20, 3.9461666762606287E-20, 3.7724077131401685E-20, 3.592916408620436E-20,
+            3.4067836691100565E-20, 3.2128447641564046E-20, 3.0095646916399994E-20, 2.794846945559833E-20,
+            2.5656913048718645E-20, 2.317520975680391E-20, 2.042669522825129E-20, 1.7261770330213488E-20,
+            1.3281889259442579E-20, 0.0};
+        /** Overhang table. Y_i = f(X_i). */
+        private static final double[] Y = {5.595205495112736E-23, 1.1802509982703313E-22, 1.844442338673583E-22,
+            2.543903046669831E-22, 3.2737694311509334E-22, 4.0307732132706715E-22, 4.812547831949511E-22,
+            5.617291489658331E-22, 6.443582054044353E-22, 7.290266234346368E-22, 8.156388845632194E-22,
+            9.041145368348222E-22, 9.94384884863992E-22, 1.0863906045969114E-21, 1.1800799775461269E-21,
+            1.2754075534831208E-21, 1.372333117637729E-21, 1.4708208794375214E-21, 1.5708388257440445E-21,
+            1.6723581984374566E-21, 1.7753530675030514E-21, 1.8797999785104595E-21, 1.9856776587832504E-21,
+            2.0929667704053244E-21, 2.201649700995824E-21, 2.311710385230618E-21, 2.4231341516125464E-21,
+            2.535907590142089E-21, 2.650018437417054E-21, 2.765455476366039E-21, 2.8822084483468604E-21,
+            3.000267975754771E-21, 3.1196254936130377E-21, 3.240273188880175E-21, 3.3622039464187092E-21,
+            3.485411300740904E-21, 3.6098893927859475E-21, 3.735632931097177E-21, 3.862637156862005E-21,
+            3.990897812355284E-21, 4.120411112391895E-21, 4.251173718448891E-21, 4.383182715163374E-21,
+            4.5164355889510656E-21, 4.6509302085234806E-21, 4.7866648071096E-21, 4.923637966211997E-21,
+            5.061848600747899E-21, 5.201295945443473E-21, 5.341979542364895E-21, 5.483899229483096E-21,
+            5.627055130180635E-21, 5.7714476436191935E-21, 5.917077435895068E-21, 6.063945431917703E-21,
+            6.212052807953168E-21, 6.3614009847804375E-21, 6.511991621413643E-21, 6.6638266093481696E-21,
+            6.816908067292628E-21, 6.971238336352438E-21, 7.126819975634082E-21, 7.283655758242034E-21,
+            7.441748667643017E-21, 7.601101894374635E-21, 7.761718833077541E-21, 7.923603079832257E-21,
+            8.086758429783484E-21, 8.251188875036333E-21, 8.416898602810326E-21, 8.58389199383831E-21,
+            8.752173620998646E-21, 8.921748248170071E-21, 9.09262082929965E-21, 9.264796507675128E-21,
+            9.438280615393829E-21, 9.613078673021033E-21, 9.789196389431416E-21, 9.966639661827884E-21,
+            1.0145414575932636E-20, 1.0325527406345955E-20, 1.0506984617068672E-20, 1.0689792862184811E-20,
+            1.0873958986701341E-20, 1.10594900275424E-20, 1.1246393214695825E-20, 1.1434675972510121E-20,
+            1.1624345921140471E-20, 1.181541087814266E-20, 1.2007878860214202E-20, 1.2201758085082226E-20,
+            1.239705697353804E-20, 1.2593784151618565E-20, 1.2791948452935152E-20, 1.29915589211506E-20,
+            1.3192624812605428E-20, 1.3395155599094805E-20, 1.3599160970797774E-20, 1.3804650839360727E-20,
+            1.4011635341137284E-20, 1.4220124840587164E-20, 1.4430129933836705E-20, 1.46416614524042E-20,
+            1.485473046709328E-20, 1.5069348292058084E-20, 1.5285526489044053E-20, 1.5503276871808626E-20,
+            1.5722611510726402E-20, 1.5943542737583543E-20, 1.6166083150566702E-20, 1.6390245619451956E-20,
+            1.6616043290999594E-20, 1.684348959456108E-20, 1.7072598247904713E-20, 1.7303383263267072E-20,
+            1.7535858953637607E-20, 1.777003993928424E-20, 1.8005941154528286E-20, 1.8243577854777398E-20,
+            1.8482965623825808E-20, 1.8724120381431627E-20, 1.8967058391181452E-20, 1.9211796268653192E-20,
+            1.9458350989888484E-20, 1.9706739900186868E-20, 1.9956980723234356E-20, 2.0209091570579904E-20,
+            2.0463090951473895E-20, 2.0718997783083593E-20, 2.097683140110135E-20, 2.123661157076213E-20,
+            2.1498358498287976E-20, 2.1762092842777868E-20, 2.2027835728562592E-20, 2.229560875804522E-20,
+            2.256543402504904E-20, 2.2837334128696004E-20, 2.311133218784001E-20, 2.3387451856080863E-20,
+            2.366571733738611E-20, 2.394615340234961E-20, 2.422878540511741E-20, 2.451363930101321E-20,
+            2.4800741664897764E-20, 2.5090119710298442E-20, 2.5381801309347597E-20, 2.56758150135705E-20,
+            2.5972190075566336E-20, 2.6270956471628253E-20, 2.6572144925351523E-20, 2.687578693228184E-20,
+            2.718191478565915E-20, 2.7490561603315974E-20, 2.7801761355793055E-20, 2.811554889573917E-20,
+            2.8431959988666534E-20, 2.8751031345137833E-20, 2.907280065446631E-20, 2.9397306620015486E-20,
+            2.9724588996191657E-20, 3.005468862722811E-20, 3.038764748786764E-20, 3.072350872605708E-20,
+            3.1062316707775905E-20, 3.140411706412999E-20, 3.174895674085097E-20, 3.2096884050352357E-20,
+            3.2447948726504914E-20, 3.280220198230601E-20, 3.315969657063137E-20, 3.352048684827223E-20,
+            3.388462884347689E-20, 3.4252180327233346E-20, 3.4623200888548644E-20, 3.4997752014001677E-20,
+            3.537589717186906E-20, 3.5757701901149035E-20, 3.61432339058358E-20, 3.65325631548274E-20,
+            3.692576198788357E-20, 3.732290522808698E-20, 3.7724070301302117E-20, 3.812933736317104E-20,
+            3.8538789434235234E-20, 3.895251254382786E-20, 3.93705958834424E-20, 3.979313197035144E-20,
+            4.022021682232577E-20, 4.0651950144388133E-20, 4.1088435528630944E-20, 4.152978066823271E-20,
+            4.197609758692658E-20, 4.242750288530745E-20, 4.2884118005513604E-20, 4.334606951598745E-20,
+            4.381348941821026E-20, 4.428651547752084E-20, 4.476529158037235E-20, 4.5249968120658306E-20,
+            4.574070241805442E-20, 4.6237659171683015E-20, 4.674101095281837E-20, 4.7250938740823415E-20,
+            4.776763250705122E-20, 4.8291291852069895E-20, 4.8822126702292804E-20, 4.936035807293385E-20,
+            4.990621890518202E-20, 5.045995498662554E-20, 5.1021825965285324E-20, 5.159210646917826E-20,
+            5.2171087345169234E-20, 5.2759077033045284E-20, 5.335640309332586E-20, 5.396341391039951E-20,
+            5.458048059625925E-20, 5.520799912453558E-20, 5.584639272987383E-20, 5.649611461419377E-20,
+            5.715765100929071E-20, 5.783152465495663E-20, 5.851829876379432E-20, 5.921858155879171E-20,
+            5.99330314883387E-20, 6.066236324679689E-20, 6.1407354758435E-20, 6.216885532049976E-20,
+            6.294779515010373E-20, 6.37451966432144E-20, 6.456218773753799E-20, 6.54000178818891E-20,
+            6.626007726330934E-20, 6.714392014514662E-20, 6.80532934473017E-20, 6.8990172088133E-20,
+            6.99568031585645E-20, 7.095576179487843E-20, 7.199002278894508E-20, 7.306305373910546E-20,
+            7.417893826626688E-20, 7.534254213417312E-20, 7.655974217114297E-20, 7.783774986341285E-20,
+            7.918558267402951E-20, 8.06147755373533E-20, 8.214050276981807E-20, 8.378344597828052E-20,
+            8.557312924967816E-20, 8.75544596695901E-20, 8.980238805770688E-20, 9.246247142115109E-20,
+            9.591964134495172E-20, 1.0842021724855044E-19};
+
+        /** Underlying source of randomness. */
+        protected final UniformRandomProvider rng;
+
+        /**
+         * @param rng Generator of uniformly distributed random numbers.
+         */
+        ModifiedZigguratExponentialSampler(UniformRandomProvider rng) {
+            this.rng = rng;
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public double sample() {
+            final long x = rng.nextLong();
+            // Float multiplication squashes these last 8 bits, so they can be used to sample i
+            final int i = ((int) x) & 0xff;
+
+            if (i < I_MAX) {
+                // Early exit.
+                // This branch is called about 0.984374 times per call into createSample.
+                // Note: Frequencies have been empirically measured for the first call to
+                // createSample; recursion due to retries have been ignored. Frequencies sum to 1.
+                return X[i] * (x & MAX_INT64);
+            }
+            // For the first call into createSample:
+            // Recursion frequency = 0.000515560
+            // Overhang frequency  = 0.0151109
+            final int j = expSampleA();
+            return j == 0 ? X_0 + sample() : expOverhang(j);
+        }
+
+        /**
+         * Alias sampling.
+         * See http://scorevoting.net/WarrenSmithPages/homepage/sampling.abs
+         *
+         * @return the alias
+         */
+        protected int expSampleA() {
+            final long x = rng.nextLong();
+            // j <- I(0, 256)
+            final int j = ((int) x) & 0xff;
+            return x >= IPMF[j] ? MAP[j] & 0xff : j;
+        }
+
+        /**
+         * Draws a PRN from overhang.
+         *
+         * @param j Index j (must be {@code > 0})
+         * @return the sample
+         */
+        protected double expOverhang(int j) {
+            // To sample a unit right-triangle:
+            // U_x <- min(U_1, U_2)
+            // distance <- | U_1 - U_2 |
+            // U_y <- 1 - (U_x + distance)
+            long ux = randomInt63();
+            long uDistance = randomInt63() - ux;
+            if (uDistance < 0) {
+                uDistance = -uDistance;
+                ux -= uDistance;
+            }
+            // _FAST_PRNG_SAMPLE_X(xj, ux)
+            final double x = fastPrngSampleX(j, ux);
+            if (uDistance >= IE_MAX) {
+                // Frequency (per call into createSample): 0.0136732
+                // Frequency (per call into expOverhang):  0.904857
+                // Early Exit: x < y - epsilon
+                return x;
+            }
+            // Frequency per call into createSample:
+            // Return    = 0.00143769
+            // Recursion = 1e-8
+            // Frequency per call into expOverhang:
+            // Return    = 0.0951426
+            // Recursion = 6.61774e-07
+
+            // _FAST_PRNG_SAMPLE_Y(j, pow(2, 63) - (ux + uDistance))
+            // Long.MIN_VALUE is used as an unsigned int with value 2^63:
+            // uy = Long.MIN_VALUE - (ux + uDistance)
+            return fastPrngSampleY(j, Long.MIN_VALUE - (ux + uDistance)) <= Math.exp(-x) ? x : expOverhang(j);
+        }
+
+        /**
+         * Return a positive long in {@code [0, 2^63)}.
+         *
+         * @return the long
+         */
+        protected long randomInt63() {
+            return rng.nextLong() & MAX_INT64;
+        }
+
+        /**
+         * Auxilary function to see if rejection sampling is required in the overhang.
+         * See Fig. 2 in the main text.
+         *
+         * @param j j
+         * @param ux ux
+         * @return the sample
+         */
+        protected static double fastPrngSampleX(int j, long ux) {
+            return X[j] * TWO_POW_63 + (X[j - 1] - X[j]) * ux;
+        }
+
+        /**
+         * Auxilary function to see if rejection sampling is required in the overhang.
+         * See Fig. 2 in the main text.
+         *
+         * @param i i
+         * @param uy uy
+         * @return the sample
+         */
+        static double fastPrngSampleY(int i, long uy) {
+            return Y[i - 1] * TWO_POW_63 + (Y[i] - Y[i - 1]) * uy;
+        }
+
+        /**
+         * Helper function to convert {@code int} values to bytes using a narrowing primitive conversion.
+         *
+         * @param values Integer values.
+         * @return the bytes
+         */
+        private static byte[] toBytes(int[] values) {
+            final byte[] bytes = new byte[values.length];
+            for (int i = 0; i < bytes.length; i++) {
+                bytes[i] = (byte) values[i];
+            }
+            return bytes;
+        }
+    }
+
+    /**
+     * Modified Ziggurat method for sampling from an exponential distribution.
+     *
+     * <p>Uses the algorithm from:
+     *
+     * <blockquote>
+     * McFarland, C.D. (2016)<br>
+     * "A modified ziggurat algorithm for generating exponentially and normally distributed pseudorandom numbers".<br>
+     * <i>Journal of Statistical Computation and Simulation</i> <b>86</b>, 1281-1294.
+     * </blockquote>
+     *
+     * <p>This implementation uses simple overhangs and does not exploit the precomputed
+     * distances of the convex overhang.
+     *
+     * @see <a href="https://www.tandfonline.com/doi/abs/10.1080/00949655.2015.1060234">
+     * McFarland (2016) JSCS 86, 1281-1294</a>
+     */
+    static class ModifiedZigguratExponentialSamplerSimpleOverhangs
+        extends ModifiedZigguratExponentialSampler {
+
+        /**
+         * @param rng Generator of uniformly distributed random numbers.
+         */
+        ModifiedZigguratExponentialSamplerSimpleOverhangs(UniformRandomProvider rng) {
+            super(rng);
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        protected double expOverhang(int j) {
+            final double x = fastPrngSampleX(j, randomInt63());
+            return fastPrngSampleY(j, randomInt63()) <= Math.exp(-x) ? x : expOverhang(j);
+        }
+    }
+
+
+    /**
+     * Modified Ziggurat method for sampling from an exponential distribution.
+     *
+     * <p>Uses the algorithm from:
+     *
+     * <blockquote>
+     * McFarland, C.D. (2016)<br>
+     * "A modified ziggurat algorithm for generating exponentially and normally distributed pseudorandom numbers".<br>
+     * <i>Journal of Statistical Computation and Simulation</i> <b>86</b>, 1281-1294.
+     * </blockquote>
+     *
+     * <p>This is a copy of {@link ModifiedZigguratExponentialSampler} using
+     * an integer map in-place of a byte map look-up table.
+     *
+     * @see <a href="https://www.tandfonline.com/doi/abs/10.1080/00949655.2015.1060234">
+     * McFarland (2016) JSCS 86, 1281-1294</a>
+     */
+    static class ModifiedZigguratExponentialSamplerIntMap implements ContinuousSampler {
+        /** Maximum i value for early exit. */
+        private static final int I_MAX = 252;
+        /** Maximum distance value for early exit. */
+        private static final long IE_MAX = 513303011048449570L;
+        /** Beginning of tail. */
+        private static final double X_0 = 7.569274694148063;
+
+        /** The alias map. */
+        private static final int[] MAP = {0, 0, 1, 235, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+            1, 1, 1, 2, 2, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+            252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+            252, 252, 252, 252, 252, 252, 252, 252, 252, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251, 251,
+            251, 250, 250, 250, 250, 250, 250, 250, 249, 249, 249, 249, 249, 249, 248, 248, 248, 248, 247, 247, 247,
+            247, 246, 246, 246, 245, 245, 244, 244, 243, 243, 242, 241, 241, 240, 239, 237, 3, 3, 4, 4, 6, 0, 0, 0, 0,
+            236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 2, 0, 0, 0};
+        /** The alias inverse PMF. */
+        private static final long[] IPMF = {9223372036854773904L, 1623796909450835018L, 2664290944894291308L,
+            7387971354164061021L, 6515064486552723158L, 8840508362680718891L, 6099647593382936415L,
+            7673130333659513775L, 6220332867583438096L, 5045979640552813698L, 4075305837223955523L,
+            3258413672162525427L, 2560664887087762532L, 1957224924672899637L, 1429800935350577509L, 964606309710808246L,
+            551043923599587126L, 180827629096890295L, -152619738120023625L, -454588624410291545L, -729385126147774968L,
+            -980551509819446936L, -1211029700667463960L, -1423284293868548440L, -1619396356369050407L,
+            -1801135830956211623L, -1970018048575618087L, -2127348289059705319L, -2274257249303686407L,
+            -2411729520096655303L, -2540626634159180934L, -2661705860113406470L, -2775635634532450566L,
+            -2883008316030465190L, -2984350790383654790L, -3080133339198116454L, -3170777096303091110L,
+            -3256660348483819078L, -3338123885075136262L, -3415475560473299110L, -3488994201966428229L,
+            -3558932970354473157L, -3625522261068041093L, -3688972217741989381L, -3749474917563782629L,
+            -3807206277531056133L, -3862327722496843557L, -3914987649156779685L, -3965322714631865221L,
+            -4013458973776895589L, -4059512885612783333L, -4103592206186241029L, -4145796782586128069L,
+            -4186219260694346949L, -4224945717447275173L, -4262056226866285509L, -4297625367836519557L,
+            -4331722680528537317L, -4364413077437472517L, -4395757214229401700L, -4425811824915135780L,
+            -4454630025296932548L, -4482261588141290436L, -4508753193105288068L, -4534148654077808964L,
+            -4558489126279958148L, -4581813295192216580L, -4604157549138257636L, -4625556137145255269L,
+            -4646041313519104421L, -4665643470413305925L, -4684391259530326597L, -4702311703971761733L,
+            -4719430301145103269L, -4735771117539946308L, -4751356876102087236L, -4766209036859134052L,
+            -4780347871386013380L, -4793792531638892068L, -4806561113635132708L, -4818670716409306532L,
+            -4830137496634465604L, -4840976719260837892L, -4851202804490348868L, -4860829371376459908L,
+            -4869869278311657508L, -4878334660640770948L, -4886236965617427236L, -4893586984900802596L,
+            -4900394884772702724L, -4906670234238885316L, -4912422031164496804L, -4917658726580119812L,
+            -4922388247283532292L, -4926618016851066692L, -4930354975163335236L, -4933605596540651332L,
+            -4936375906575303844L, -4938671497741365892L, -4940497543854575684L, -4941858813449629540L,
+            -4942759682136115044L, -4943204143989086820L, -4943195822025527940L, -4942737977813206404L,
+            -4941833520255033284L, -4940485013586738820L, -4938694684624359428L, -4936464429291795972L,
+            -4933795818458825604L, -4930690103114057988L, -4927148218896864068L, -4923170790008275908L,
+            -4918758132519213508L, -4913910257091645764L, -4908626871126539204L, -4902907380349534020L,
+            -4896750889844272900L, -4890156204540531076L, -4883121829162554372L, -4875645967641781188L,
+            -4867726521994927044L, -4859361090668103364L, -4850546966345113668L, -4841281133215539076L,
+            -4831560263698491972L, -4821380714613447492L, -4810738522790066116L, -4799629400105481988L,
+            -4788048727936307268L, -4775991551010515012L, -4763452570642114308L, -4750426137329494532L,
+            -4736906242696389124L, -4722886510751377669L, -4708360188440088965L, -4693320135461420933L,
+            -4677758813316108101L, -4661668273553489093L, -4645040145179241541L, -4627865621182772101L,
+            -4610135444140930052L, -4591839890849345476L, -4572968755929961540L, -4553511334358205764L,
+            -4533456402849101572L, -4512792200036278980L, -4491506405372580932L, -4469586116675402436L,
+            -4447017826233108036L, -4423787395382284804L, -4399880027458416324L, -4375280239014115077L,
+            -4349971829190472197L, -4323937847117721861L, -4297160557210933573L, -4269621402214949829L,
+            -4241300963840749253L, -4212178920821861701L, -4182234004204451589L, -4151443949668877253L,
+            -4119785446662287621L, -4087234084103201605L, -4053764292396156933L, -4019349281473081925L,
+            -3983960974549692677L, -3947569937258423301L, -3910145301787345669L, -3871654685619032069L,
+            -3832064104425388805L, -3791337878631544901L, -3749438533114327493L, -3706326689447984389L,
+            -3661960950051848261L, -3616297773528534789L, -3569291340409189253L, -3520893408440946053L,
+            -3471053156460654341L, -3419717015797782598L, -3366828488034805510L, -3312327947826460358L,
+            -3256152429334010374L, -3198235394669719110L, -3138506482563172742L, -3076891235255162822L,
+            -3013310801389730758L, -2947681612411374854L, -2879915029671670790L, -2809916959107513734L,
+            -2737587429961866118L, -2662820133571325574L, -2585501917733379974L, -2505512231579385223L,
+            -2422722515205211655L, -2336995527534088455L, -2248184604988727559L, -2156132842510764935L,
+            -2060672187261025415L, -1961622433929371911L, -1858790108950105479L, -1751967229002895623L,
+            -1640929916937142791L, -1525436855617582472L, -1405227557075253256L, -1280020420662649992L,
+            -1149510549536596104L, -1013367289578704904L, -871231448632104200L, -722712146453667848L,
+            -567383236774435977L, -404779231966938249L, -234390647591545737L, -55658667960119305L, 132030985907841399L,
+            329355128892811767L, 537061298001085174L, 755977262693564150L, 987022116608033270L, 1231219266829431286L,
+            1489711711346518517L, 1763780090187553909L, 2054864117341795061L, 2364588157623768948L,
+            2694791916990503284L, 3047567482883476212L, 3425304305830816371L, 3830744187097297907L,
+            4267048975685830386L, 4737884547990017266L, 5247525842198998257L, 5800989391535355377L,
+            6404202162993295344L, 7064218894258540527L, 7789505049452331503L, 8590309807749444846L,
+            7643763810684490059L, 8891950541491446071L, 5457384281016205975L, 9083704440929283969L,
+            7976211653914433372L, 8178631350487117494L, 2821287825726744835L, 6322989683301709657L,
+            4309503753387611426L, 4685170734960170474L, 8404845967535199663L, 7330522972447554153L,
+            1960945799076992020L, 4742910674644898996L, -751799822533509968L, 7023456603741959948L,
+            3843116882594676172L, 3927231442413902976L, -9223372036854775808L, -9223372036854775808L,
+            -9223372036854775808L};
+        /**
+         * The precomputed ziggurat lengths, denoted X_i in the main text. X_i = length of
+         * ziggurat layer i.
+         */
+        private static final double[] X = {8.206624067534882E-19, 7.397373235160728E-19, 6.913331337791529E-19,
+            6.564735882096453E-19, 6.291253995981851E-19, 6.065722412960496E-19, 5.873527610373727E-19,
+            5.705885052853694E-19, 5.557094569162239E-19, 5.423243890374395E-19, 5.301529769650878E-19,
+            5.189873925770806E-19, 5.086692261799833E-19, 4.990749293879647E-19, 4.901062589444954E-19,
+            4.816837901064919E-19, 4.737423865364471E-19, 4.662279580719682E-19, 4.590950901778405E-19,
+            4.523052779065815E-19, 4.458255881635396E-19, 4.396276312636838E-19, 4.336867596710647E-19,
+            4.2798143618469714E-19, 4.224927302706489E-19, 4.172039125346411E-19, 4.1210012522465616E-19,
+            4.0716811225869233E-19, 4.0239599631006903E-19, 3.9777309342877357E-19, 3.93289757853345E-19,
+            3.8893725129310323E-19, 3.8470763218720385E-19, 3.8059366138180143E-19, 3.765887213854473E-19,
+            3.7268674692030177E-19, 3.688821649224816E-19, 3.651698424880007E-19, 3.6154504153287473E-19,
+            3.5800337915318032E-19, 3.545407928453343E-19, 3.5115350988784242E-19, 3.478380203003096E-19,
+            3.4459105288907336E-19, 3.4140955396563316E-19, 3.3829066838741162E-19, 3.3523172262289E-19,
+            3.3223020958685874E-19, 3.292837750280447E-19, 3.263902052820205E-19, 3.2354741622810815E-19,
+            3.207534433108079E-19, 3.180064325047861E-19, 3.1530463211820845E-19, 3.1264638534265134E-19,
+            3.100301234693421E-19, 3.07454359701373E-19, 3.049176835000556E-19, 3.0241875541094565E-19,
+            2.999563023214455E-19, 2.975291131074259E-19, 2.9513603463113224E-19, 2.9277596805684267E-19,
+            2.9044786545442563E-19, 2.8815072666416712E-19, 2.858835963990693E-19, 2.8364556156331615E-19,
+            2.81435748767798E-19, 2.7925332202553125E-19, 2.770974806115288E-19, 2.7496745707320232E-19,
+            2.7286251537873397E-19, 2.7078194919206054E-19, 2.687250802641905E-19, 2.666912569315344E-19,
+            2.646798527127889E-19, 2.6269026499668434E-19, 2.6072191381359757E-19, 2.5877424068465143E-19,
+            2.568467075424817E-19, 2.549387957183548E-19, 2.530500049907748E-19, 2.511798526911271E-19,
+            2.4932787286227806E-19, 2.474936154663866E-19, 2.456766456384867E-19, 2.438765429826784E-19,
+            2.4209290090801527E-19, 2.403253260014054E-19, 2.3857343743505147E-19, 2.368368664061465E-19,
+            2.3511525560671253E-19, 2.3340825872163284E-19, 2.3171553995306794E-19, 2.3003677356958333E-19,
+            2.283716434784348E-19, 2.2671984281957174E-19, 2.250810735800194E-19, 2.234550462273959E-19,
+            2.2184147936140775E-19, 2.2024009938224424E-19, 2.186506401748684E-19, 2.1707284280826716E-19,
+            2.1550645524878675E-19, 2.1395123208673778E-19, 2.124069342755064E-19, 2.1087332888245875E-19,
+            2.0935018885097035E-19, 2.0783729277295508E-19, 2.0633442467130712E-19, 2.0484137379170616E-19,
+            2.0335793440326865E-19, 2.018839056075609E-19, 2.0041909115551697E-19, 1.9896329927183254E-19,
+            1.975163424864309E-19, 1.9607803747261946E-19, 1.9464820489157862E-19, 1.9322666924284314E-19,
+            1.9181325872045647E-19, 1.904078050744948E-19, 1.8901014347767504E-19, 1.8762011239677479E-19,
+            1.8623755346860768E-19, 1.8486231138030984E-19, 1.8349423375370566E-19, 1.8213317103353295E-19,
+            1.8077897637931708E-19, 1.7943150556069476E-19, 1.7809061685599652E-19, 1.7675617095390567E-19,
+            1.7542803085801941E-19, 1.741060617941453E-19, 1.727901311201724E-19, 1.7148010823836362E-19,
+            1.7017586450992059E-19, 1.6887727317167824E-19, 1.6758420925479093E-19, 1.6629654950527621E-19,
+            1.650141723062866E-19, 1.6373695760198277E-19, 1.624647868228856E-19, 1.6119754281258616E-19,
+            1.5993510975569615E-19, 1.586773731069231E-19, 1.5742421952115544E-19, 1.5617553678444595E-19,
+            1.5493121374578016E-19, 1.5369114024951992E-19, 1.524552070684102E-19, 1.5122330583703858E-19,
+            1.499953289856356E-19, 1.4877116967410352E-19, 1.4755072172615974E-19, 1.4633387956347966E-19,
+            1.4512053813972103E-19, 1.439105928743099E-19, 1.4270393958586506E-19, 1.415004744251338E-19,
+            1.4030009380730888E-19, 1.3910269434359025E-19, 1.3790817277185197E-19, 1.3671642588626657E-19,
+            1.3552735046573446E-19, 1.3434084320095729E-19, 1.3315680061998685E-19, 1.3197511901207148E-19,
+            1.3079569434961214E-19, 1.2961842220802957E-19, 1.28443197683331E-19, 1.2726991530715219E-19,
+            1.2609846895903523E-19, 1.2492875177568625E-19, 1.237606560569394E-19, 1.225940731681333E-19,
+            1.2142889343858445E-19, 1.2026500605581765E-19, 1.1910229895518744E-19, 1.1794065870449425E-19,
+            1.1677997038316715E-19, 1.1562011745554883E-19, 1.144609816377787E-19, 1.1330244275772562E-19,
+            1.1214437860737343E-19, 1.109866647870073E-19, 1.0982917454048923E-19, 1.086717785808435E-19,
+            1.0751434490529747E-19, 1.0635673859884002E-19, 1.0519882162526621E-19, 1.0404045260457141E-19,
+            1.0288148657544097E-19, 1.0172177474144965E-19, 1.0056116419943559E-19, 9.939949764834668E-20,
+            9.823661307666745E-20, 9.70723434263201E-20, 9.590651623069063E-20, 9.47389532241542E-20,
+            9.356946992015904E-20, 9.239787515456947E-20, 9.122397059055647E-20, 9.004755018085287E-20,
+            8.886839958264763E-20, 8.768629551976745E-20, 8.650100508607102E-20, 8.531228498314119E-20,
+            8.411988068438521E-20, 8.292352551651342E-20, 8.17229396480345E-20, 8.051782897283921E-20,
+            7.930788387509923E-20, 7.809277785952443E-20, 7.687216602842904E-20, 7.564568338396512E-20,
+            7.441294293017913E-20, 7.317353354509333E-20, 7.192701758763107E-20, 7.067292819766679E-20,
+            6.941076623950036E-20, 6.813999682925642E-20, 6.686004537461023E-20, 6.557029304021008E-20,
+            6.427007153336853E-20, 6.295865708092356E-20, 6.163526343814314E-20, 6.02990337321517E-20,
+            5.894903089285018E-20, 5.758422635988593E-20, 5.62034866695974E-20, 5.480555741349931E-20,
+            5.3389043909003295E-20, 5.1952387717989917E-20, 5.0493837866338355E-20, 4.901141522262949E-20,
+            4.7502867933366117E-20, 4.5965615001265455E-20, 4.4396673897997565E-20, 4.279256630214859E-20,
+            4.1149193273430015E-20, 3.9461666762606287E-20, 3.7724077131401685E-20, 3.592916408620436E-20,
+            3.4067836691100565E-20, 3.2128447641564046E-20, 3.0095646916399994E-20, 2.794846945559833E-20,
+            2.5656913048718645E-20, 2.317520975680391E-20, 2.042669522825129E-20, 1.7261770330213488E-20,
+            1.3281889259442579E-20, 0.0};
+        /** Overhang table. Y_i = f(X_i). */
+        private static final double[] Y = {5.595205495112736E-23, 1.1802509982703313E-22, 1.844442338673583E-22,
+            2.543903046669831E-22, 3.2737694311509334E-22, 4.0307732132706715E-22, 4.812547831949511E-22,
+            5.617291489658331E-22, 6.443582054044353E-22, 7.290266234346368E-22, 8.156388845632194E-22,
+            9.041145368348222E-22, 9.94384884863992E-22, 1.0863906045969114E-21, 1.1800799775461269E-21,
+            1.2754075534831208E-21, 1.372333117637729E-21, 1.4708208794375214E-21, 1.5708388257440445E-21,
+            1.6723581984374566E-21, 1.7753530675030514E-21, 1.8797999785104595E-21, 1.9856776587832504E-21,
+            2.0929667704053244E-21, 2.201649700995824E-21, 2.311710385230618E-21, 2.4231341516125464E-21,
+            2.535907590142089E-21, 2.650018437417054E-21, 2.765455476366039E-21, 2.8822084483468604E-21,
+            3.000267975754771E-21, 3.1196254936130377E-21, 3.240273188880175E-21, 3.3622039464187092E-21,
+            3.485411300740904E-21, 3.6098893927859475E-21, 3.735632931097177E-21, 3.862637156862005E-21,
+            3.990897812355284E-21, 4.120411112391895E-21, 4.251173718448891E-21, 4.383182715163374E-21,
+            4.5164355889510656E-21, 4.6509302085234806E-21, 4.7866648071096E-21, 4.923637966211997E-21,
+            5.061848600747899E-21, 5.201295945443473E-21, 5.341979542364895E-21, 5.483899229483096E-21,
+            5.627055130180635E-21, 5.7714476436191935E-21, 5.917077435895068E-21, 6.063945431917703E-21,
+            6.212052807953168E-21, 6.3614009847804375E-21, 6.511991621413643E-21, 6.6638266093481696E-21,
+            6.816908067292628E-21, 6.971238336352438E-21, 7.126819975634082E-21, 7.283655758242034E-21,
+            7.441748667643017E-21, 7.601101894374635E-21, 7.761718833077541E-21, 7.923603079832257E-21,
+            8.086758429783484E-21, 8.251188875036333E-21, 8.416898602810326E-21, 8.58389199383831E-21,
+            8.752173620998646E-21, 8.921748248170071E-21, 9.09262082929965E-21, 9.264796507675128E-21,
+            9.438280615393829E-21, 9.613078673021033E-21, 9.789196389431416E-21, 9.966639661827884E-21,
+            1.0145414575932636E-20, 1.0325527406345955E-20, 1.0506984617068672E-20, 1.0689792862184811E-20,
+            1.0873958986701341E-20, 1.10594900275424E-20, 1.1246393214695825E-20, 1.1434675972510121E-20,
             1.1624345921140471E-20, 1.181541087814266E-20, 1.2007878860214202E-20, 1.2201758085082226E-20,
             1.239705697353804E-20, 1.2593784151618565E-20, 1.2791948452935152E-20, 1.29915589211506E-20,
             1.3192624812605428E-20, 1.3395155599094805E-20, 1.3599160970797774E-20, 1.3804650839360727E-20,
@@ -1446,7 +2246,7 @@ public class ZigguratSamplerPerformance {
         /**
          * @param rng Generator of uniformly distributed random numbers.
          */
-        ModifiedZigguratExponentialSampler(UniformRandomProvider rng) {
+        ModifiedZigguratExponentialSamplerIntMap(UniformRandomProvider rng) {
             this.rng = rng;
         }
 
@@ -1481,7 +2281,7 @@ public class ZigguratSamplerPerformance {
             final long x = rng.nextLong();
             // j <- I(0, 256)
             final int j = ((int) x) & 0xff;
-            return x >= IPMF[j] ? MAP[j] & 0xff : j;
+            return x >= IPMF[j] ? MAP[j] : j;
         }
 
         /**
@@ -1554,55 +2354,6 @@ public class ZigguratSamplerPerformance {
         static double fastPrngSampleY(int i, long uy) {
             return Y[i - 1] * TWO_POW_63 + (Y[i] - Y[i - 1]) * uy;
         }
-
-        /**
-         * Helper function to convert {@code int} values to bytes using a narrowing primitive conversion.
-         *
-         * @param values Integer values.
-         * @return the bytes
-         */
-        private static byte[] toBytes(int[] values) {
-            final byte[] bytes = new byte[values.length];
-            for (int i = 0; i < bytes.length; i++) {
-                bytes[i] = (byte) values[i];
-            }
-            return bytes;
-        }
-    }
-
-    /**
-     * Modified Ziggurat method for sampling from an exponential distribution.
-     *
-     * <p>Uses the algorithm from:
-     *
-     * <blockquote>
-     * McFarland, C.D. (2016)<br>
-     * "A modified ziggurat algorithm for generating exponentially and normally distributed pseudorandom numbers".<br>
-     * <i>Journal of Statistical Computation and Simulation</i> <b>86</b>, 1281-1294.
-     * </blockquote>
-     *
-     * <p>This implementation uses simple overhangs and does not exploit the precomputed
-     * distances of the convex overhang.
-     *
-     * @see <a href="https://www.tandfonline.com/doi/abs/10.1080/00949655.2015.1060234">
-     * McFarland (2016) JSCS 86, 1281-1294</a>
-     */
-    static class ModifiedZigguratExponentialSamplerSimpleOverhangs
-        extends ModifiedZigguratExponentialSampler {
-
-        /**
-         * @param rng Generator of uniformly distributed random numbers.
-         */
-        ModifiedZigguratExponentialSamplerSimpleOverhangs(UniformRandomProvider rng) {
-            super(rng);
-        }
-
-        /** {@inheritDoc} */
-        @Override
-        protected double expOverhang(int j) {
-            final double x = fastPrngSampleX(j, randomInt63());
-            return fastPrngSampleY(j, randomInt63()) <= Math.exp(-x) ? x : expOverhang(j);
-        }
     }
 
     /**
diff --git a/src/main/resources/checkstyle/checkstyle-suppressions.xml b/src/main/resources/checkstyle/checkstyle-suppressions.xml
index 0ac768f..6c54013 100644
--- a/src/main/resources/checkstyle/checkstyle-suppressions.xml
+++ b/src/main/resources/checkstyle/checkstyle-suppressions.xml
@@ -33,4 +33,5 @@
   <suppress checks="IllegalCatch" files=".*[/\\]test[/\\].*" />
   <suppress checks="MethodLength" files="(MersenneTwister64|Well44497[ab]|MultiplyWithCarry256)Test" />
   <suppress checks="FileLength" files="[\\/]StableSamplerTest" />
+  <suppress checks="FileLength" files="[\\/]ZigguratSamplerPerformance" />
 </suppressions>

[commons-rng] 08/08: Add more simple overhangs performance benchmarks

Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-rng.git

commit 02ae5512270c4a9d3445680bff664cc9be8630fd
Author: aherbert <ah...@apache.org>
AuthorDate: Mon Aug 9 16:53:00 2021 +0100

    Add more simple overhangs performance benchmarks
    
    Update the names with notes on their implementation.
---
 .../distribution/ZigguratSamplerPerformance.java   | 229 ++++++++++++++++-----
 1 file changed, 181 insertions(+), 48 deletions(-)

diff --git a/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java b/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java
index 17742ee..c80f5b9 100644
--- a/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java
+++ b/commons-rng-examples/examples-jmh/src/main/java/org/apache/commons/rng/examples/jmh/sampling/distribution/ZigguratSamplerPerformance.java
@@ -34,7 +34,6 @@ import org.openjdk.jmh.annotations.Scope;
 import org.openjdk.jmh.annotations.Setup;
 import org.openjdk.jmh.annotations.State;
 import org.openjdk.jmh.annotations.Warmup;
-
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -53,17 +52,43 @@ public class ZigguratSamplerPerformance {
     /** 2^53. */
     private static final double TWO_POW_63 = 0x1.0p63;
 
-    /** The name for the {@link ZigguratNormalizedGaussianSampler}. */
+    // Production versions
+
+    /** The name for a copy of the {@link ZigguratNormalizedGaussianSampler} with a table of size 128.
+     * This matches the version in Commons RNG release v1.1 to 1.3. */
     private static final String GAUSSIAN_128 = "Gaussian128";
-    /** The name for a copy of the {@link ZigguratNormalizedGaussianSampler} with a table of size 256. */
+    /** The name for the {@link ZigguratNormalizedGaussianSampler} (table of size 256).
+     * This is the version in Commons RNG release v1.4+. */
     private static final String GAUSSIAN_256 = "Gaussian256";
     /** The name for the {@link ZigguratSampler.NormalizedGaussian}. */
     private static final String MOD_GAUSSIAN = "ModGaussian";
+    /** The name for the {@link ZigguratSampler.Exponential}. */
+    private static final String MOD_EXPONENTIAL = "ModExponential";
+
+    // Testing versions
+
+    /** The name for the {@link ZigguratExponentialSampler} with a table of size 256.
+     * This is an exponential sampler using Marsaglia's ziggurat method. */
+    private static final String EXPONENTIAL = "Exponential";
+
+    /** The name for the {@link ModifiedZigguratNormalizedGaussianSampler}.
+     * This is a base implementation of McFarland's ziggurat method. */
+    private static final String MOD_GAUSSIAN2 = "ModGaussian2";
     /** The name for the {@link ModifiedZigguratNormalizedGaussianSamplerSimpleOverhangs}. */
     private static final String MOD_GAUSSIAN_SIMPLE_OVERHANGS = "ModGaussianSimpleOverhangs";
+    /** The name for the {@link ModifiedZigguratNormalizedGaussianSamplerSimpleOverhangsRecursive}. */
+    private static final String MOD_GAUSSIAN_SIMPLE_OVERHANGS_RECURSIVE = "ModGaussianSimpleOverhangsRecursive";
     /** The name for the {@link ModifiedZigguratNormalizedGaussianSamplerIntMap}. */
     private static final String MOD_GAUSSIAN_INT_MAP = "ModGaussianIntMap";
 
+    /** The name for the {@link ModifiedZigguratExponetialSampler}.
+     * This is a base implementation of McFarland's ziggurat method. */
+    private static final String MOD_EXPONENTIAL2 = "ModExponential2";
+    /** The name for the {@link ModifiedZigguratExponentialSamplerSimpleOverhangs}. */
+    private static final String MOD_EXPONENTIAL_SIMPLE_OVERHANGS = "ModExponentialSimpleOverhangs";
+    /** The name for the {@link ModifiedZigguratExponentialSamplerIntMap}. */
+    private static final String MOD_EXPONENTIAL_INT_MAP = "ModExponentialIntMap";
+
     /**
      * The value.
      *
@@ -193,9 +218,15 @@ public class ZigguratSamplerPerformance {
         /**
          * The sampler type.
          */
-        @Param({GAUSSIAN_128, GAUSSIAN_256, "Exponential", MOD_GAUSSIAN, "ModExponential",
-                "ModGaussian2", MOD_GAUSSIAN_SIMPLE_OVERHANGS, MOD_GAUSSIAN_INT_MAP,
-                "ModExponential2", "ModExponentialSimpleOverhangs", "ModExponentialIntMap"})
+        @Param({// Production versions
+                GAUSSIAN_128, GAUSSIAN_256, MOD_GAUSSIAN, MOD_EXPONENTIAL,
+                // Experimental Marsaglia exponential ziggurat sampler
+                EXPONENTIAL,
+                // Experimental McFarland Gaussian ziggurat samplers
+                MOD_GAUSSIAN2, MOD_GAUSSIAN_SIMPLE_OVERHANGS, MOD_GAUSSIAN_SIMPLE_OVERHANGS_RECURSIVE,
+                MOD_GAUSSIAN_INT_MAP,
+                // Experimental McFarland Gaussian ziggurat samplers
+                MOD_EXPONENTIAL2, MOD_EXPONENTIAL_SIMPLE_OVERHANGS, MOD_EXPONENTIAL_INT_MAP})
         private String type;
 
         /** The sampler. */
@@ -213,30 +244,43 @@ public class ZigguratSamplerPerformance {
         public void setup() {
             final RandomSource randomSource = RandomSource.valueOf(randomSourceName);
             final UniformRandomProvider rng = randomSource.create();
+            sampler = createSampler(type, rng);
+        }
+
+        /**
+         * Creates the sampler.
+         *
+         * @param type Type of sampler
+         * @param rng RNG
+         * @return the sampler
+         */
+        static ContinuousSampler createSampler(String type, UniformRandomProvider rng) {
             if (GAUSSIAN_128.equals(type)) {
-                sampler = new ZigguratNormalizedGaussianSampler128(rng);
+                return new ZigguratNormalizedGaussianSampler128(rng);
             } else if (GAUSSIAN_256.equals(type)) {
-                sampler = ZigguratNormalizedGaussianSampler.of(rng);
-            } else if ("Exponential".equals(type)) {
-                sampler = new ZigguratExponentialSampler(rng);
+                return ZigguratNormalizedGaussianSampler.of(rng);
             } else if (MOD_GAUSSIAN.equals(type)) {
-                sampler = ZigguratSampler.NormalizedGaussian.of(rng);
-            } else if ("ModExponential".equals(type)) {
-                sampler = ZigguratSampler.Exponential.of(rng);
-            } else if ("ModGaussian2".equals(type)) {
-                sampler = new ModifiedZigguratNormalizedGaussianSampler(rng);
+                return ZigguratSampler.NormalizedGaussian.of(rng);
+            } else if (MOD_EXPONENTIAL.equals(type)) {
+                return ZigguratSampler.Exponential.of(rng);
+            } else if (EXPONENTIAL.equals(type)) {
+                return new ZigguratExponentialSampler(rng);
+            } else if (MOD_GAUSSIAN2.equals(type)) {
+                return new ModifiedZigguratNormalizedGaussianSampler(rng);
             } else if (MOD_GAUSSIAN_SIMPLE_OVERHANGS.equals(type)) {
-                sampler = new ModifiedZigguratNormalizedGaussianSamplerSimpleOverhangs(rng);
+                return new ModifiedZigguratNormalizedGaussianSamplerSimpleOverhangs(rng);
+            } else if (MOD_GAUSSIAN_SIMPLE_OVERHANGS_RECURSIVE.equals(type)) {
+                return new ModifiedZigguratNormalizedGaussianSamplerSimpleOverhangsRecursive(rng);
             } else if (MOD_GAUSSIAN_INT_MAP.equals(type)) {
-                sampler = new ModifiedZigguratNormalizedGaussianSamplerIntMap(rng);
-            } else if ("ModExponential2".equals(type)) {
-                sampler = new ModifiedZigguratExponentialSampler(rng);
-            } else if ("ModExponentialSimpleOverhangs".equals(type)) {
-                sampler = new ModifiedZigguratExponentialSamplerSimpleOverhangs(rng);
-            } else if ("ModExponentialIntMap".equals(type)) {
-                sampler = new ModifiedZigguratExponentialSamplerIntMap(rng);
+                return new ModifiedZigguratNormalizedGaussianSamplerIntMap(rng);
+            } else if (MOD_EXPONENTIAL2.equals(type)) {
+                return new ModifiedZigguratExponentialSampler(rng);
+            } else if (MOD_EXPONENTIAL_SIMPLE_OVERHANGS.equals(type)) {
+                return new ModifiedZigguratExponentialSamplerSimpleOverhangs(rng);
+            } else if (MOD_EXPONENTIAL_INT_MAP.equals(type)) {
+                return new ModifiedZigguratExponentialSamplerIntMap(rng);
             } else {
-                throwIllegalStateException(type);
+                throw new IllegalStateException("Unknown type: " + type);
             }
         }
     }
@@ -268,7 +312,11 @@ public class ZigguratSamplerPerformance {
         private String randomSourceName;
 
         /** The sampler type. */
-        @Param({GAUSSIAN_128, GAUSSIAN_256, MOD_GAUSSIAN, MOD_GAUSSIAN_SIMPLE_OVERHANGS, MOD_GAUSSIAN_INT_MAP})
+        @Param({// Production versions
+                GAUSSIAN_128, GAUSSIAN_256, MOD_GAUSSIAN,
+                // Experimental McFarland Gaussian ziggurat samplers
+                MOD_GAUSSIAN2, MOD_GAUSSIAN_SIMPLE_OVERHANGS, MOD_GAUSSIAN_SIMPLE_OVERHANGS_RECURSIVE,
+                MOD_GAUSSIAN_INT_MAP})
         private String type;
 
         /** The size. */
@@ -290,20 +338,7 @@ public class ZigguratSamplerPerformance {
         public void setup() {
             final RandomSource randomSource = RandomSource.valueOf(randomSourceName);
             final UniformRandomProvider rng = randomSource.create();
-            ContinuousSampler s = null;
-            if (GAUSSIAN_128.equals(type)) {
-                s = new ZigguratNormalizedGaussianSampler128(rng);
-            } else if (GAUSSIAN_256.equals(type)) {
-                s = ZigguratNormalizedGaussianSampler.of(rng);
-            } else if (MOD_GAUSSIAN.equals(type)) {
-                s = ZigguratSampler.NormalizedGaussian.of(rng);
-            } else if (MOD_GAUSSIAN_SIMPLE_OVERHANGS.equals(type)) {
-                s = new ModifiedZigguratNormalizedGaussianSamplerSimpleOverhangs(rng);
-            } else if (MOD_GAUSSIAN_INT_MAP.equals(type)) {
-                s = new ModifiedZigguratNormalizedGaussianSamplerIntMap(rng);
-            } else {
-                throwIllegalStateException(type);
-            }
+            final ContinuousSampler s = Sources.createSampler(type, rng);
             sampler = createSampler(size, s);
         }
 
@@ -749,6 +784,11 @@ public class ZigguratSamplerPerformance {
      * <i>Journal of Statistical Computation and Simulation</i> <b>86</b>, 1281-1294.
      * </blockquote>
      *
+     * <p>This class uses the same tables as the production version
+     * {@link org.apache.commons.rng.sampling.distribution.ZigguratSampler.NormalizedGaussian}
+     * with the overhang sampling matching the reference c implementation. Methods and members
+     * are protected to allow the implementation to be modified in sub-classes.
+     *
      * @see <a href="https://www.tandfonline.com/doi/abs/10.1080/00949655.2015.1060234">
      * McFarland (2016) JSCS 86, 1281-1294</a>
      */
@@ -1024,6 +1064,7 @@ public class ZigguratSamplerPerformance {
             if (j > J_INFLECTION) {
                 // Convex overhang
                 // Branch frequency: 0.00891413
+                // Loop repeat frequency: 0.389804
                 for (;;) {
                     x = fastPrngSampleX(j, u1);
                     final long uDiff = randomInt63() - u1;
@@ -1033,6 +1074,8 @@ public class ZigguratSamplerPerformance {
                     }
                     if (uDiff >= MAX_IE &&
                         // Within maximum distance of f(x) from the triangle hypotenuse.
+                        // Frequency (per upper-right triangle): 0.431497
+                        // Reject frequency: 0.489630
                         // Long.MIN_VALUE is used as an unsigned int with value 2^63:
                         // uy = Long.MIN_VALUE - (ux + uDiff)
                         fastPrngSampleY(j, Long.MIN_VALUE - (u1 + uDiff)) < Math.exp(-0.5 * x * x)) {
@@ -1044,6 +1087,9 @@ public class ZigguratSamplerPerformance {
             } else if (j == 0) {
                 // Tail
                 // Branch frequency: 0.000277067
+                // Note: Although less frequent than the next branch, j == 0 is a subset of
+                // j < J_INFLECTION and must be first.
+                // Loop repeat frequency: 0.0634786
                 do {
                     x = ONE_OVER_X_0 * exponential.sample();
                 } while (exponential.sample() < 0.5 * x * x);
@@ -1051,6 +1097,7 @@ public class ZigguratSamplerPerformance {
             } else if (j < J_INFLECTION) {
                 // Concave overhang
                 // Branch frequency: 0.00251223
+                // Loop repeat frequency: 0.0123784
                 for (;;) {
                     // U_x <- min(U_1, U_2)
                     // distance <- | U_1 - U_2 |
@@ -1061,10 +1108,8 @@ public class ZigguratSamplerPerformance {
                         u1 -= uDiff;
                     }
                     x = fastPrngSampleX(j, u1);
-                    if (uDiff > MIN_IE)  {
-                        break;
-                    }
-                    if (fastPrngSampleY(j, Long.MIN_VALUE - (u1 + uDiff)) < Math.exp(-0.5 * x * x)) {
+                    if (uDiff > MIN_IE ||
+                        fastPrngSampleY(j, Long.MIN_VALUE - (u1 + uDiff)) < Math.exp(-0.5 * x * x)) {
                         break;
                     }
                     u1 = randomInt63();
@@ -1072,6 +1117,7 @@ public class ZigguratSamplerPerformance {
             } else {
                 // Inflection point
                 // Branch frequency: 0.0000161147
+                // Loop repeat frequency: 0.500213
                 for (;;) {
                     x = fastPrngSampleX(j, u1);
                     if (fastPrngSampleY(j, randomInt63()) < Math.exp(-0.5 * x * x)) {
@@ -1156,7 +1202,8 @@ public class ZigguratSamplerPerformance {
      * </blockquote>
      *
      * <p>This implementation uses simple overhangs and does not exploit the precomputed
-     * distances of the concave and convex overhangs.
+     * distances of the concave and convex overhangs. The implementation matches the c-reference
+     * compiled using -DSIMPLE_OVERHANGS.
      *
      * @see <a href="https://www.tandfonline.com/doi/abs/10.1080/00949655.2015.1060234">
      * McFarland (2016) JSCS 86, 1281-1294</a>
@@ -1226,6 +1273,81 @@ public class ZigguratSamplerPerformance {
      * <i>Journal of Statistical Computation and Simulation</i> <b>86</b>, 1281-1294.
      * </blockquote>
      *
+     * <p>This implementation uses simple overhangs and does not exploit the precomputed
+     * distances of the concave and convex overhangs. The implementation uses recursive
+     * calls when samples are rejected.
+     *
+     * @see <a href="https://www.tandfonline.com/doi/abs/10.1080/00949655.2015.1060234">
+     * McFarland (2016) JSCS 86, 1281-1294</a>
+     */
+    static class ModifiedZigguratNormalizedGaussianSamplerSimpleOverhangsRecursive
+        extends ModifiedZigguratNormalizedGaussianSampler {
+
+        /**
+         * @param rng Generator of uniformly distributed random numbers.
+         */
+        ModifiedZigguratNormalizedGaussianSamplerSimpleOverhangsRecursive(UniformRandomProvider rng) {
+            super(rng);
+        }
+
+        /** {@inheritDoc} */
+        @Override
+        public double sample() {
+            final long xx = rng.nextLong();
+            // Float multiplication squashes these last 8 bits, so they can be used to sample i
+            final int i = ((int) xx) & 0xff;
+
+            if (i < I_MAX) {
+                // Early exit.
+                // Branch frequency: 0.988280
+                return X[i] * xx;
+            }
+
+            final int j = normSampleA();
+
+            // Simple overhangs
+            double x;
+            if (j == 0) {
+                // Tail
+
+                // Extract sign bit from recycled bits
+                // Use 2 - 1 or 0 - 1
+                final double signBit = ((xx >>> 7) & 0x2) - 1.0;
+
+                do {
+                    x = ONE_OVER_X_0 * exponential.sample();
+                } while (exponential.sample() < 0.5 * x * x);
+
+                return (x + X_0) * signBit;
+            }
+
+            // Rejection sampling
+
+            x = fastPrngSampleX(j, xx & MAX_INT64);
+            if (fastPrngSampleY(j, randomInt63()) < Math.exp(-0.5 * x * x)) {
+                // Extract sign bit from recycled bits. These are not used in the multiplication
+                // to create x which squashes the final bits.
+                // Use 2 - 1 or 0 - 1
+                final double signBit = ((xx >>> 7) & 0x2) - 1.0;
+                return x * signBit;
+            }
+
+            // Try again.
+            return sample();
+        }
+    }
+
+    /**
+     * Modified Ziggurat method for sampling from a Gaussian distribution with mean 0 and standard deviation 1.
+     *
+     * <p>Uses the algorithm from:
+     *
+     * <blockquote>
+     * McFarland, C.D. (2016)<br>
+     * "A modified ziggurat algorithm for generating exponentially and normally distributed pseudorandom numbers".<br>
+     * <i>Journal of Statistical Computation and Simulation</i> <b>86</b>, 1281-1294.
+     * </blockquote>
+     *
      * <p>This is a copy of {@link ModifiedZigguratNormalizedGaussianSampler} using
      * an integer map in-place of a byte map look-up table. The underlying exponential
      * sampler also uses an integer map.
@@ -1505,6 +1627,7 @@ public class ZigguratSamplerPerformance {
             if (j > J_INFLECTION) {
                 // Convex overhang
                 // Branch frequency: 0.00891413
+                // Loop repeat frequency: 0.389804
                 for (;;) {
                     x = fastPrngSampleX(j, u1);
                     final long uDiff = randomInt63() - u1;
@@ -1514,6 +1637,8 @@ public class ZigguratSamplerPerformance {
                     }
                     if (uDiff >= MAX_IE &&
                         // Within maximum distance of f(x) from the triangle hypotenuse.
+                        // Frequency (per upper-right triangle): 0.431497
+                        // Reject frequency: 0.489630
                         // Long.MIN_VALUE is used as an unsigned int with value 2^63:
                         // uy = Long.MIN_VALUE - (ux + uDiff)
                         fastPrngSampleY(j, Long.MIN_VALUE - (u1 + uDiff)) < Math.exp(-0.5 * x * x)) {
@@ -1525,6 +1650,9 @@ public class ZigguratSamplerPerformance {
             } else if (j == 0) {
                 // Tail
                 // Branch frequency: 0.000277067
+                // Note: Although less frequent than the next branch, j == 0 is a subset of
+                // j < J_INFLECTION and must be first.
+                // Loop repeat frequency: 0.0634786
                 do {
                     x = ONE_OVER_X_0 * exponential.sample();
                 } while (exponential.sample() < 0.5 * x * x);
@@ -1532,6 +1660,7 @@ public class ZigguratSamplerPerformance {
             } else if (j < J_INFLECTION) {
                 // Concave overhang
                 // Branch frequency: 0.00251223
+                // Loop repeat frequency: 0.0123784
                 for (;;) {
                     // U_x <- min(U_1, U_2)
                     // distance <- | U_1 - U_2 |
@@ -1542,10 +1671,8 @@ public class ZigguratSamplerPerformance {
                         u1 -= uDiff;
                     }
                     x = fastPrngSampleX(j, u1);
-                    if (uDiff > MIN_IE)  {
-                        break;
-                    }
-                    if (fastPrngSampleY(j, Long.MIN_VALUE - (u1 + uDiff)) < Math.exp(-0.5 * x * x)) {
+                    if (uDiff > MIN_IE ||
+                        fastPrngSampleY(j, Long.MIN_VALUE - (u1 + uDiff)) < Math.exp(-0.5 * x * x)) {
                         break;
                     }
                     u1 = randomInt63();
@@ -1553,6 +1680,7 @@ public class ZigguratSamplerPerformance {
             } else {
                 // Inflection point
                 // Branch frequency: 0.0000161147
+                // Loop repeat frequency: 0.500213
                 for (;;) {
                     x = fastPrngSampleX(j, u1);
                     if (fastPrngSampleY(j, randomInt63()) < Math.exp(-0.5 * x * x)) {
@@ -1622,6 +1750,11 @@ public class ZigguratSamplerPerformance {
      * <i>Journal of Statistical Computation and Simulation</i> <b>86</b>, 1281-1294.
      * </blockquote>
      *
+     * <p>This class uses the same tables as the production version
+     * {@link org.apache.commons.rng.sampling.distribution.ZigguratSampler.Exponential}
+     * with the overhang sampling matching the reference c implementation. Methods and members
+     * are protected to allow the implementation to be modified in sub-classes.
+     *
      * @see <a href="https://www.tandfonline.com/doi/abs/10.1080/00949655.2015.1060234">
      * McFarland (2016) JSCS 86, 1281-1294</a>
      */