LCOV - code coverage report
Current view: top level - util/rng - fd_rng.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 214 214 100.0 %
Date: 2024-11-13 11:58:15 Functions: 6 6 100.0 %

          Line data    Source code
       1             : #include "fd_rng.h"
       2             : #include <math.h> /* FIXME: ELIMINATE DEPENDENCE AS THIS IS NOT GUARANTEED BIT LEVEL IDENTICAL BETWEEN PLATFORMS */
       3             : 
       4             : float
       5        3000 : fd_rng_float_robust( fd_rng_t * rng ) {
       6             : 
       7             :   /* Generate a float as though a continuum rand was generated in [1,2]
       8             :      and then round to nearest even rounded to the closest exactly
       9             :      representable float point value in [1,2].  (This can generate all
      10             :      such representable values in that range.) */
      11             : 
      12        3000 :   ulong u = (ulong)fd_rng_uint( rng );    /* 32-bit uniform rand */
      13        3000 :   ulong m = (u >> 9) + (u & 1UL);         /* [0,2^23] trapezoidal rand */
      14        3000 :   float f = 1.f + ((float)m)*FLT_EPSILON; /* Exact */
      15             : 
      16             :   /* Now apply an exponent to yield the correct final result */
      17             : 
      18        3000 :   return ldexpf( f, -(int)fd_rng_coin_tosses( rng ) );
      19        3000 : }
      20             : 
      21             : float
      22    58838621 : fd_rng_float_exp( fd_rng_t * rng ) {
      23    58838621 :   ulong u = 1UL + (fd_rng_ulong( rng ) >> 1);    /* In (0,2^63] uniform */
      24    58838621 :   float f = ((float)u) * (1.f/(float)(1UL<<63)); /* In uniform (0,1] with reasonably low quant, exact */
      25    58838621 :   return -logf( f );                             /* Convert to exp */
      26    58838621 : }
      27             : 
      28             : #if 0
      29             : /* USE THIS WITH LOGF AT END REPLACED WITH FAST APPROX REJECTION IF NO
      30             :    LIBM.  USE TRANSFORMATION ON CONTINUUM RAND IF WANTING NO QUANT
      31             :    ARTIFACTS.  NEARLY EQUIVALENT CAN USE:
      32             : 
      33             :         F(x) = 1 - exp(-x) = 1 - exp2(-x*log2(e))
      34             :      -> y = x*log2(e), x = y*(1/log2(e))
      35             :         F(y) = 1 - exp2(-y)
      36             :      -> Y = -log2( U )
      37             : 
      38             :    where U is a uniform rand in [0,1].  But U can be generated by:
      39             : 
      40             :         U = (2^-E)( 1 + M )
      41             : 
      42             :    where E is IID integer rand with probability:
      43             : 
      44             :         P(E) = 2^-E for E>0
      45             :              = 0    otherwise
      46             : 
      47             :    and M is an IID uniform rand in [0,1].  Thus:
      48             : 
      49             :      -> Y = E - log2( 1 + M )
      50             : 
      51             :    yielding a variant with minimal tail artifacts.  In single precision:
      52             : 
      53             :       e = fd_rng_coin_tosses( rng );
      54             :       m = fd_rng_uint( rng );        
      55             :       y = e - lg1p( m / 2^32 );
      56             :       return y*(1/log2(e));
      57             : 
      58             :    and for double precision:
      59             : 
      60             :       e = fd_rng_coin_tosses( rng )
      61             :       m = fd_rng_ulong( rng );
      62             :       y = e - lg1p( m / 2^64 );
      63             :       return y*(1/log2(e));
      64             : 
      65             :    Eliminating floating point rep quant artifacts near the origin is
      66             :    much trickier due to the cancellations implied above (but also
      67             :    practically much less important ... they are no worse than the
      68             :    quantization artifacts of the typical generator). */
      69             : 
      70             : float
      71             : fd_rng_float_exp( fd_rng_t * rng ) {
      72             : 
      73             :   for(;;) {
      74             : 
      75             :     /* Generate the 7-bit ziggurat level and a 24-bit trapezoidal rand
      76             :        (e.g. "uniform" rand on [0,2^24] with the endpoints 0 and 2^24
      77             :        half as likely as the other points). */
      78             : 
      79             :     ulong u = (ulong)fd_rng_uint( rng );
      80             : 
      81             :     ulong l = (u >> 1) & (zig_level_cnt-1UL); /* uniform level (level_cnt must be a power-of-2 <= 128) */
      82             :     ulong m = (u >> 8) + (u & 1UL);           /* ~2^24 bit trapezoidal rand */
      83             : 
      84             :     /* Compute a uniform rand as wide as the current ziggurat level
      85             :        (will be closed at both endpoints due to trapezoid rounding
      86             :        above).  If willing to have an additional table, the
      87             :        multiplication by 2^-24 can be eliminated (technically though this
      88             :        is exact and can be done just be playing with with the exponent). */
      89             : 
      90             :     float x = zig_x[l+1UL]*((1.f/(float)(1<<24))*(float)m);
      91             : 
      92             :     /* If this is smaller than the level above this, we can immediately
      93             :        accept this rand.  This occurs the vast majority of the time. */
      94             : 
      95             :     if( FD_LIKELY( x<=zig_x[l] ) ) break; /* Quick accept */
      96             : 
      97             :     /* We can't do a quick acceptance */
      98             : 
      99             :     if( FD_LIKELY( l<(zig_level_cnt-1UL) ) ) {
     100             : 
     101             :       /* We are picking a point uniformly in the l-th ziggurat strip. */
     102             : 
     103             :       float t = zig_y[l];
     104             :       float y = t + (zig_y[l+1UL]-t)*fd_rng_float_c0( rng );
     105             :       if( y < expf(-x) ) break; /* Fundamentally ~50/50 unpredictable */
     106             : 
     107             :     } else {
     108             : 
     109             :       /* We are picking a point uniformly in the ziggurat exponential
     110             :          tail.  Note that x - R is an independent uniform rand between 0
     111             :          and 1.  In finite precision arithmetic, (x-R)==0 will never
     112             :          occur due to the above acceptance check.  Thus, it is safe to
     113             :          compute ln (x-R) to generate an exponentially distributed rand
     114             :          for the tail here. */
     115             : 
     116             :       x = zig_r - logf( x - zig_r );
     117             :       break;
     118             : 
     119             :     }
     120             : 
     121             :     /* Rejected */
     122             :   }
     123             : 
     124             :   return x;
     125             : }
     126             : #endif
     127             : 
     128             : float
     129      202551 : fd_rng_float_norm( fd_rng_t * rng ) {
     130             : 
     131             :   /* BEGIN AUTOGENERATED CODE *****************************************/
     132             : 
     133      202551 :   static float const zig_x[65] = {
     134      202551 :     0.000000000000000000000000000000e+00f /* l= 0 */, 3.455520224239806172095417630130e-01f /* l= 1 */,
     135      202551 :     4.621556810233836948395482607799e-01f /* l= 2 */, 5.450460069613645023634852793126e-01f /* l= 3 */,
     136      202551 :     6.119536252363746848246563170282e-01f /* l= 4 */, 6.693178808991654190761917686547e-01f /* l= 5 */,
     137      202551 :     7.202743599269989995133832427765e-01f /* l= 6 */, 7.666087419009196196129432565591e-01f /* l= 7 */,
     138      202551 :     8.094445383821111665470331153482e-01f /* l= 8 */, 8.495396579691822718460002261676e-01f /* l= 9 */,
     139      202551 :     8.874325556154150376969927394022e-01f /* l=10 */, 9.235214816642028361095943800319e-01f /* l=11 */,
     140      202551 :     9.581106750231991023205452284728e-01f /* l=12 */, 9.914388611066755936521502357017e-01f /* l=13 */,
     141      202551 :     1.023697658831656335945772817730e+00f /* l=14 */, 1.055043930218579828852511204307e+00f /* l=15 */,
     142      202551 :     1.085608336108546385250818444579e+00f /* l=16 */, 1.115501429269408685757483667977e+00f /* l=17 */,
     143      202551 :     1.144818099662757484029536325654e+00f /* l=18 */, 1.173640887904643574190903521082e+00f /* l=19 */,
     144      202551 :     1.202042503654549259546786832420e+00f /* l=20 */, 1.230087774542608308986184340039e+00f /* l=21 */,
     145      202551 :     1.257835180410570578152240628356e+00f /* l=22 */, 1.285338081362219465062293743962e+00f /* l=23 */,
     146      202551 :     1.312645717221077709701594626868e+00f /* l=24 */, 1.339804034974004910067517382100e+00f /* l=25 */,
     147      202551 :     1.366856386251642895349189821275e+00f /* l=26 */, 1.393844126728532207214715510357e+00f /* l=27 */,
     148      202551 :     1.420807142148611732640484106582e+00f /* l=28 */, 1.447784320603175013198252174540e+00f /* l=29 */,
     149      202551 :     1.474813987119431635871430463780e+00f /* l=30 */, 1.501934314168690078094073325765e+00f /* l=31 */,
     150      202551 :     1.529183720117960190352200677832e+00f /* l=32 */, 1.556601266765526946100374472426e+00f /* l=33 */,
     151      202551 :     1.584227066827416976904988055175e+00f /* l=34 */, 1.612102712541159403396816285348e+00f /* l=35 */,
     152      202551 :     1.640271737439234119525742483514e+00f /* l=36 */, 1.668780124881012518812430089898e+00f /* l=37 */,
     153      202551 :     1.697676879240338253859027295434e+00f /* l=38 */, 1.727014678920001637717554499041e+00f /* l=39 */,
     154      202551 :     1.756850634895277701885175913876e+00f /* l=40 */, 1.787247184704316305928380181900e+00f /* l=41 */,
     155      202551 :     1.818273160330322024778176848159e+00f /* l=42 */, 1.850005080182403822074664601072e+00f /* l=43 */,
     156      202551 :     1.882528731753153053690014173682e+00f /* l=44 */, 1.915941134586538274016051519588e+00f /* l=45 */,
     157      202551 :     1.950353006115250048047894682046e+00f /* l=46 */, 1.985891900706324235165341207665e+00f /* l=47 */,
     158      202551 :     2.022706262852767138214066244828e+00f /* l=48 */, 2.060970741899825969985216023161e+00f /* l=49 */,
     159      202551 :     2.100893279890740158706921580922e+00f /* l=50 */, 2.142724743933560004960706124599e+00f /* l=51 */,
     160      202551 :     2.186772297656567175727290730514e+00f /* l=52 */, 2.233418418575520170057252533624e+00f /* l=53 */,
     161      202551 :     2.283148713210882645120378131587e+00f /* l=54 */, 2.336593955757456149034331782666e+00f /* l=55 */,
     162      202551 :     2.394596149760118465339014948157e+00f /* l=56 */, 2.458317361057721973189790776182e+00f /* l=57 */,
     163      202551 :     2.529429815978553923233249078883e+00f /* l=58 */, 2.610473649022010540245164467166e+00f /* l=59 */,
     164      202551 :     2.705599986069530120576243081842e+00f /* l=60 */, 2.822342497323976174845167053107e+00f /* l=61 */,
     165      202551 :     2.976823798790561124028714035106e+00f /* l=62 */, 3.215929245508522913137711141118e+00f /* l=63 */,
     166      202551 :     3.526881360327788386254538322007e+00f /* l=64 */
     167      202551 :   };
     168             : 
     169      202551 :   static float const zig_y[65] = {
     170      202551 :     1.000000000000000000000000000000e+00f /* l= 0 */, 9.420441848916480126344477619149e-01f /* l= 1 */,
     171      202551 :     8.987108451876446194939510037081e-01f /* l= 2 */, 8.619676182560859538047716432718e-01f /* l= 3 */,
     172      202551 :     8.292416921465940136417270556191e-01f /* l= 4 */, 7.993205594629470858670725053052e-01f /* l= 5 */,
     173      202551 :     7.715162251201959925242870874662e-01f /* l= 6 */, 7.453924046791949711084253327176e-01f /* l= 7 */,
     174      202551 :     7.206510565419278137484770940802e-01f /* l= 8 */, 6.970774082324479442845238663651e-01f /* l= 9 */,
     175      202551 :     6.745103421549214010562514620695e-01f /* l=10 */, 6.528251409771071645448889397834e-01f /* l=11 */,
     176      202551 :     6.319228072029464656281239065549e-01f /* l=12 */, 6.117231258029589507463179287594e-01f /* l=13 */,
     177      202551 :     5.921599774953054971587604327077e-01f /* l=14 */, 5.731780673128809060960613119828e-01f /* l=15 */,
     178      202551 :     5.547305771308242055075976573164e-01f /* l=16 */, 5.367774409030761823035174384877e-01f /* l=17 */,
     179      202551 :     5.192840512302357241190831071975e-01f /* l=18 */, 5.022202719018961842071223367068e-01f /* l=19 */,
     180      202551 :     4.855596720803138878681283474581e-01f /* l=20 */, 4.692789240423391189252835808965e-01f /* l=21 */,
     181      202551 :     4.533573236341009112014902027177e-01f /* l=22 */, 4.377764041761660086522593704483e-01f /* l=23 */,
     182      202551 :     4.225196225029520580892660602812e-01f /* l=24 */, 4.075721013736326630086392874830e-01f /* l=25 */,
     183      202551 :     3.929204164392402009802710699526e-01f /* l=26 */, 3.785524188002748156032031823237e-01f /* l=27 */,
     184      202551 :     3.644570862756677649099863736115e-01f /* l=28 */, 3.506243980520670366787892163751e-01f /* l=29 */,
     185      202551 :     3.370452285453843354473546511940e-01f /* l=30 */, 3.237112571905811243399165438861e-01f /* l=31 */,
     186      202551 :     3.106148915554719103920833234156e-01f /* l=32 */, 2.977492017031598617858058342112e-01f /* l=33 */,
     187      202551 :     2.851078641441273595351531267017e-01f /* l=34 */, 2.726851140512668792348013879767e-01f /* l=35 */,
     188      202551 :     2.604757046803618125588395543213e-01f /* l=36 */, 2.484748731607814430951243836465e-01f /* l=37 */,
     189      202551 :     2.366783120090016554051349020882e-01f /* l=38 */, 2.250821458811925040717320800621e-01f /* l=39 */,
     190      202551 :     2.136829132292288532124100927656e-01f /* l=40 */, 2.024775526650522966412917846846e-01f /* l=41 */,
     191      202551 :     1.914633939793006458976280803608e-01f /* l=42 */, 1.806381539102589138648434843870e-01f /* l=43 */,
     192      202551 :     1.699999369289590334732324358735e-01f /* l=44 */, 1.595472415092518358135931233477e-01f /* l=45 */,
     193      202551 :     1.492789726065822738132905095343e-01f /* l=46 */, 1.391944614029269361199806984142e-01f /* l=47 */,
     194      202551 :     1.292934938280917421830808894390e-01f /* l=48 */, 1.195763500012655360156695570628e-01f /* l=49 */,
     195      202551 :     1.100438576497440733127446653439e-01f /* l=50 */, 1.006974639150281902163835620612e-01f /* l=51 */,
     196      202551 :     9.153933202201729600920110732631e-02f /* l=52 */, 8.257247254089309598817534793791e-02f /* l=53 */,
     197      202551 :     7.380092428122808796957937671479e-02f /* l=54 */, 6.523000887995579990570474762657e-02f /* l=55 */,
     198      202551 :     5.686669921543156531844320777935e-02f /* l=56 */, 4.872017206675432561731060171484e-02f /* l=57 */,
     199      202551 :     4.080267659191996105732375653419e-02f /* l=58 */, 3.313098485527892895195507111383e-02f /* l=59 */,
     200      202551 :     2.572902254561226234667566450942e-02f /* l=60 */, 1.863323273948142502092796546354e-02f /* l=61 */,
     201      202551 :     1.190567663419300047354134047123e-02f /* l=62 */, 5.678316641776698130187294149412e-03f /* l=63 */,
     202      202551 :     0.000000000000000000000000000000e+00f /* l=64 */
     203      202551 :   };
     204             : 
     205      202551 :   static ulong const zig_level_cnt = 64;
     206             : 
     207      202551 :   static float const zig_r      = 3.215929245508522913137711141118e+00f;
     208      202551 :   static float const zig_rcp_r  = 3.109521148192654732252473981369e-01f;
     209      202551 :   static float const zig_half_r = 1.607964622754261456568855570559e+00f;
     210      202551 :   static float const zig_tail   = 2.852700996027780249580940719056e+00f;
     211             : 
     212             :   /* END AUTOGENERATED CODE *******************************************/
     213             : 
     214      202551 :   ulong s;
     215      202551 :   float x;
     216             : 
     217      207225 :   for(;;) {
     218             : 
     219             :     /* Generate the sign bit, up to 6-bit ziggurat level and a 24-bit
     220             :        trapezoidal rand (e.g. "uniform" rand on [0,2^24] with the
     221             :        endpoints 0 and 2^24 half as likely as the other points). */
     222             : 
     223      207225 :     ulong u = (ulong)fd_rng_uint( rng ); /* 32-bit rand */
     224             : 
     225      207225 :     /**/  s = (u >> 1) & 1UL;                 /* random sign */
     226      207225 :     ulong l = (u >> 2) & (zig_level_cnt-1UL); /* uniform level (zig_level_cnt must be power-of-2 <= 64) */
     227      207225 :     ulong m = (u >> 8) + (u & 1UL);           /* 24-bit trapezoidal rand */
     228             : 
     229             :     /* Compute a uniform rand as wide as the current ziggurat level */
     230             : 
     231      207225 :     x = zig_x[l+1UL]*((1.f/16777216.f)*(float)m); /* Guaranteed in [0,x[l+1]] */
     232             : 
     233             :     /* If this is <= level above this, we can immediately accept this
     234             :        rand.  This occurs the vast majority of the time. */
     235             : 
     236      207225 :     if( FD_LIKELY( x<=zig_x[l] ) ) break; /* Quick accept */
     237             : 
     238             :     /* We can't do a quick acceptance ... the y rand might matter */
     239             : 
     240       10386 :     float y = fd_rng_float_c( rng ); /* Guaranteed in [0,1] */
     241             : 
     242       10386 :     if( FD_LIKELY( l<(zig_level_cnt-1UL) ) ) {
     243             : 
     244             :       /* We are picking a point uniformly in the l-th ziggurat strip. */
     245             : 
     246       10092 :       y = zig_y[l]*(1.f-y) + zig_y[l+1UL]*y; /* Guaranteed in [y0,y1] */
     247             : 
     248       10092 :     } else {
     249             : 
     250             :       /* We are picking a point uniformly distributed in the ziggurat
     251             :          exponential tail.
     252             : 
     253             :          The simplest way to do this is to transform a new uniform
     254             :          rand into an exponential distribution that joins smoothly to
     255             :          the base of the Ziggurat.
     256             : 
     257             :          We theoretically can do slightly better by noting that x-r
     258             :          is an independent uniform rand in ( r==x[l], x[l+1] ].  Thus,
     259             :          instead of computing a new uniform rand for the tail x and
     260             :          transforming it to the desired exponential rand, we could get
     261             :          an exponential rand via:
     262             : 
     263             :            x' = r - (1/r) ln ( (x-r) / (x[l+1]-r) )
     264             : 
     265             :          which simplifies to:
     266             : 
     267             :            x = (r + (1/r) ln( x[l+1]-r) ) - (1/r) ln ( x-r )
     268             : 
     269             :          The first term is a compile time constant.  The second term
     270             :          doesn't require a new rand but is otherwise the same
     271             :          transformation cost.  x-r is guaranteed greater than 0 given
     272             :          the quick accept test above so the logf will not blow up. */
     273             : 
     274         294 :       x  = zig_tail - zig_rcp_r*logf( x - zig_r );
     275         294 :       y *= expf( zig_r*(zig_half_r - x) );
     276             : 
     277         294 :     }
     278             : 
     279             :     /* FIXME: COULD GET RID OF 0.5 MULTIPLICATION BY USING PDF
     280             :        expf(-x^2), ADJUST TAIL COMP AND SCALING TO UNIT NORM AS PART OF
     281             :        THE SIGN INSERTION. */
     282             : 
     283       10386 :     if( y < expf((-0.5f)*(x*x)) ) break; /* Slow accept, approx 50/50 unpredictable */
     284             : 
     285             :     /* Rejected, try again */
     286       10386 :   }
     287             : 
     288      202551 :   return fd_float_if( (int)s, -x, x ); /* FIXME: LOAD AND MUL BY +/-1?  LOAD AND COPYSIGNF BY +/-1? */
     289      202551 : }
     290             : 
     291             : #if FD_HAS_DOUBLE /* See float variants for details how these work */
     292             : 
     293             : double
     294        3000 : fd_rng_double_robust( fd_rng_t * rng ) {
     295        3000 :   ulong  u = fd_rng_ulong( rng );
     296        3000 :   ulong  m = (u >> 12) + (u & 1UL);
     297        3000 :   double d = 1. + ((double)m)*DBL_EPSILON;
     298        3000 :   return ldexp( d, -(int)fd_rng_coin_tosses( rng ) );
     299        3000 : }
     300             : 
     301             : double
     302      219021 : fd_rng_double_exp( fd_rng_t * rng ) {
     303      219021 :   ulong  u = 1UL + (fd_rng_ulong( rng ) >> 1);
     304      219021 :   double d = ((double)u) * (1./(double)(1UL<<63));
     305      219021 :   return -log( d );
     306      219021 : }
     307             : 
     308             : double
     309     1112136 : fd_rng_double_norm( fd_rng_t * rng ) {
     310             : 
     311             :   /* BEGIN AUTOGENERATED CODE *****************************************/
     312             : 
     313     1112136 :   static double const zig_x[65] = {
     314     1112136 :     0.000000000000000000000000000000e+00, 3.455520224239806172095417630130e-01,
     315     1112136 :     4.621556810233836948395482607799e-01, 5.450460069613645023634852793126e-01,
     316     1112136 :     6.119536252363746848246563170282e-01, 6.693178808991654190761917686547e-01,
     317     1112136 :     7.202743599269989995133832427765e-01, 7.666087419009196196129432565591e-01,
     318     1112136 :     8.094445383821111665470331153482e-01, 8.495396579691822718460002261676e-01,
     319     1112136 :     8.874325556154150376969927394022e-01, 9.235214816642028361095943800319e-01,
     320     1112136 :     9.581106750231991023205452284728e-01, 9.914388611066755936521502357017e-01,
     321     1112136 :     1.023697658831656335945772817730e+00, 1.055043930218579828852511204307e+00,
     322     1112136 :     1.085608336108546385250818444579e+00, 1.115501429269408685757483667977e+00,
     323     1112136 :     1.144818099662757484029536325654e+00, 1.173640887904643574190903521082e+00,
     324     1112136 :     1.202042503654549259546786832420e+00, 1.230087774542608308986184340039e+00,
     325     1112136 :     1.257835180410570578152240628356e+00, 1.285338081362219465062293743962e+00,
     326     1112136 :     1.312645717221077709701594626868e+00, 1.339804034974004910067517382100e+00,
     327     1112136 :     1.366856386251642895349189821275e+00, 1.393844126728532207214715510357e+00,
     328     1112136 :     1.420807142148611732640484106582e+00, 1.447784320603175013198252174540e+00,
     329     1112136 :     1.474813987119431635871430463780e+00, 1.501934314168690078094073325765e+00,
     330     1112136 :     1.529183720117960190352200677832e+00, 1.556601266765526946100374472426e+00,
     331     1112136 :     1.584227066827416976904988055175e+00, 1.612102712541159403396816285348e+00,
     332     1112136 :     1.640271737439234119525742483514e+00, 1.668780124881012518812430089898e+00,
     333     1112136 :     1.697676879240338253859027295434e+00, 1.727014678920001637717554499041e+00,
     334     1112136 :     1.756850634895277701885175913876e+00, 1.787247184704316305928380181900e+00,
     335     1112136 :     1.818273160330322024778176848159e+00, 1.850005080182403822074664601072e+00,
     336     1112136 :     1.882528731753153053690014173682e+00, 1.915941134586538274016051519588e+00,
     337     1112136 :     1.950353006115250048047894682046e+00, 1.985891900706324235165341207665e+00,
     338     1112136 :     2.022706262852767138214066244828e+00, 2.060970741899825969985216023161e+00,
     339     1112136 :     2.100893279890740158706921580922e+00, 2.142724743933560004960706124599e+00,
     340     1112136 :     2.186772297656567175727290730514e+00, 2.233418418575520170057252533624e+00,
     341     1112136 :     2.283148713210882645120378131587e+00, 2.336593955757456149034331782666e+00,
     342     1112136 :     2.394596149760118465339014948157e+00, 2.458317361057721973189790776182e+00,
     343     1112136 :     2.529429815978553923233249078883e+00, 2.610473649022010540245164467166e+00,
     344     1112136 :     2.705599986069530120576243081842e+00, 2.822342497323976174845167053107e+00,
     345     1112136 :     2.976823798790561124028714035106e+00, 3.215929245508522913137711141118e+00,
     346     1112136 :     3.526881360327788386254538322007e+00
     347     1112136 :   };
     348             : 
     349     1112136 :   static double const zig_y[65] = {
     350     1112136 :     1.000000000000000000000000000000e+00, 9.420441848916480126344477619149e-01,
     351     1112136 :     8.987108451876446194939510037081e-01, 8.619676182560859538047716432718e-01,
     352     1112136 :     8.292416921465940136417270556191e-01, 7.993205594629470858670725053052e-01,
     353     1112136 :     7.715162251201959925242870874662e-01, 7.453924046791949711084253327176e-01,
     354     1112136 :     7.206510565419278137484770940802e-01, 6.970774082324479442845238663651e-01,
     355     1112136 :     6.745103421549214010562514620695e-01, 6.528251409771071645448889397834e-01,
     356     1112136 :     6.319228072029464656281239065549e-01, 6.117231258029589507463179287594e-01,
     357     1112136 :     5.921599774953054971587604327077e-01, 5.731780673128809060960613119828e-01,
     358     1112136 :     5.547305771308242055075976573164e-01, 5.367774409030761823035174384877e-01,
     359     1112136 :     5.192840512302357241190831071975e-01, 5.022202719018961842071223367068e-01,
     360     1112136 :     4.855596720803138878681283474581e-01, 4.692789240423391189252835808965e-01,
     361     1112136 :     4.533573236341009112014902027177e-01, 4.377764041761660086522593704483e-01,
     362     1112136 :     4.225196225029520580892660602812e-01, 4.075721013736326630086392874830e-01,
     363     1112136 :     3.929204164392402009802710699526e-01, 3.785524188002748156032031823237e-01,
     364     1112136 :     3.644570862756677649099863736115e-01, 3.506243980520670366787892163751e-01,
     365     1112136 :     3.370452285453843354473546511940e-01, 3.237112571905811243399165438861e-01,
     366     1112136 :     3.106148915554719103920833234156e-01, 2.977492017031598617858058342112e-01,
     367     1112136 :     2.851078641441273595351531267017e-01, 2.726851140512668792348013879767e-01,
     368     1112136 :     2.604757046803618125588395543213e-01, 2.484748731607814430951243836465e-01,
     369     1112136 :     2.366783120090016554051349020882e-01, 2.250821458811925040717320800621e-01,
     370     1112136 :     2.136829132292288532124100927656e-01, 2.024775526650522966412917846846e-01,
     371     1112136 :     1.914633939793006458976280803608e-01, 1.806381539102589138648434843870e-01,
     372     1112136 :     1.699999369289590334732324358735e-01, 1.595472415092518358135931233477e-01,
     373     1112136 :     1.492789726065822738132905095343e-01, 1.391944614029269361199806984142e-01,
     374     1112136 :     1.292934938280917421830808894390e-01, 1.195763500012655360156695570628e-01,
     375     1112136 :     1.100438576497440733127446653439e-01, 1.006974639150281902163835620612e-01,
     376     1112136 :     9.153933202201729600920110732631e-02, 8.257247254089309598817534793791e-02,
     377     1112136 :     7.380092428122808796957937671479e-02, 6.523000887995579990570474762657e-02,
     378     1112136 :     5.686669921543156531844320777935e-02, 4.872017206675432561731060171484e-02,
     379     1112136 :     4.080267659191996105732375653419e-02, 3.313098485527892895195507111383e-02,
     380     1112136 :     2.572902254561226234667566450942e-02, 1.863323273948142502092796546354e-02,
     381     1112136 :     1.190567663419300047354134047123e-02, 5.678316641776698130187294149412e-03,
     382     1112136 :     0.000000000000000000000000000000e+00
     383     1112136 :   };
     384             : 
     385     1112136 :   static ulong const zig_level_cnt = 64;
     386             : 
     387     1112136 :   static double const zig_r      = 3.215929245508522913137711141118e+00;
     388     1112136 :   static double const zig_rcp_r  = 3.109521148192654732252473981369e-01;
     389     1112136 :   static double const zig_half_r = 1.607964622754261456568855570559e+00;
     390     1112136 :   static double const zig_tail   = 2.852700996027780249580940719056e+00;
     391             : 
     392             :   /* END AUTOGENERATED CODE *******************************************/
     393             : 
     394     1112136 :   ulong  s;
     395     1112136 :   double x;
     396             : 
     397     1137048 :   for(;;) {
     398             : 
     399     1137048 :     ulong u = fd_rng_ulong( rng );             /* 64-bit rand */
     400             : 
     401     1137048 :     /**/  s = (u >>  1) & 1UL;
     402     1137048 :     ulong l = (u >>  2) & (zig_level_cnt-1UL); /* uniform level (zig_level_cnt must be power-of-2 <= 512) */
     403     1137048 :     ulong m = (u >> 11) + (u & 1UL);           /* 53-bit trapezoidal rand */
     404             : 
     405     1137048 :     x = zig_x[l+1UL]*((1./9007199254740992.)*(double)m);
     406             : 
     407     1137048 :     if( FD_LIKELY( x<=zig_x[l] ) ) break;
     408             : 
     409       57147 :     double y = fd_rng_double_c( rng );
     410             : 
     411       57147 :     if( FD_LIKELY( l<(zig_level_cnt-1UL) ) ) {
     412       55632 :       y = zig_y[l]*(1.-y) + zig_y[l+1UL]*y;
     413       55632 :     } else {
     414        1515 :       x  = zig_tail - zig_rcp_r*log( x - zig_r );
     415        1515 :       y *= exp( zig_r*(zig_half_r - x) );
     416        1515 :     }
     417             : 
     418       57147 :     if( y < exp((-0.5)*(x*x)) ) break;
     419       57147 :   }
     420             : 
     421     1112136 :   return fd_double_if( (int)s, -x, x );
     422     1112136 : }
     423             : 
     424             : #endif
     425             : 

Generated by: LCOV version 1.14