Path: csiph.com!eternal-september.org!feeder.eternal-september.org!reader01.eternal-september.org!.POSTED!not-for-mail
From: Tim Rentsch
Newsgroups: comp.lang.c
Subject: Re: Bart, a tcc "issue"
Date: Sun, 10 Nov 2019 07:49:00 -0800
Organization: A noiseless patient Spider
Lines: 64
Message-ID: <864kzbd95f.fsf@linuxsc.com>
References: <86k189ejbd.fsf@linuxsc.com> <87sgmw3ajx.fsf@bsb.me.uk>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Info: reader02.eternal-september.org; posting-host="451385503b6e65ada0ba6f97513c8763"; logging-data="29675"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX183WazJEUpd1Qm7jOysAY6yW0Af4tTUxP4="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:T2J4D0SIGMHUFUqi3tt1OrZwOf0= sha1:vPdfmdQZUhymqbi80+hcy0gTnCw=
Xref: csiph.com comp.lang.c:147907
Ben Bacarisse writes:
> Tim Rentsch writes:
>
>
>> It's interesting -- three different people posted corrections or
>> improvements to the uniform interval code, and all of the revisions
>> have been a little bit off in one way or another. Care is needed to
>> deal with edge cases correctly.
>>
>> int
>> uniform_less_than( unsigned k ){
>> unsigned d, r;
>>
>> if( k-1 > RAND_MAX || k == 0 ) oops_someone_messed_up();
>>
>> d = (RAND_MAX - (k-1)) / k + 1;
>> do r = rand()/d; while( r >= k );
>>
>> return r;
>> }
>>
>> int
>> uniform_on_closed_interval( int a, int b ){
>> if( a > b ) return uniform_on_closed_interval( b, a );
>>
>> return a + uniform_less_than( b + 1u - a );
>> }
>>
>> A good test for a uniform closed-interval RNG is to check that
>> it handles the interval 0..RAND_MAX, including both endpoints,
>> correctly.
>
> Are you considering edge cases in the C standard? If so, one of those
> has RAND_MAX == UINT_MAX.
Ahem. Please review this version:
int
uniform_no_greater_than( unsigned k ){
unsigned r = 0;
assert( k <= RAND_MAX );
if( k > 0 ){
unsigned d = k >= RAND_MAX ? 1 : (RAND_MAX - k) / (k+1) + 1;
do r = rand()/d; while( r > k );
}
return r;
}
int
uniform_on_closed_interval( int a, int b ){
if( a > b ) return uniform_on_closed_interval( b, a );
if( a < 0 ? b > a+RAND_MAX : b-a > RAND_MAX ){
return interval_too_large(), a;
}
return a + uniform_no_greater_than( b - a );
}
The version just previously posted has a problem if k is 0 in
implementations where RAND_MAX == UINT_MAX.