Interesting bug with std.random.uniform and dchar

Joseph Rushton Wakeling via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Jun 8 01:47:10 PDT 2014


Hello all,

Here's an interesting little bug that arises when std.random.uniform is called 
using dchar as the variable type:

/****************************************************************************/
import std.conv, std.random, std.stdio, std.string, std.typetuple;

void main()
{
     foreach (C; TypeTuple!(char, wchar, dchar))
     {
         writefln("Testing with %s: [%s, %s]", C.stringof, to!ulong(C.min), 
to!ulong(C.max));
         foreach (immutable _; 0 .. 100)
         {
             auto u = uniform!"[]"(C.min, C.max);

             assert(C.min <= u, format("%s.min = %s, u = %s", C.stringof, 
to!ulong(C.min), to!ulong(u)));
             assert(u <= C.max, format("%s.max = %s, u = %s", C.stringof, 
to!ulong(C.max), to!ulong(u)));
         }
     }
}
/****************************************************************************/

When closed boundaries "[]" are used with uniform, and the min and max of the 
distribution are equal to T.min and T.max (where T is the variable type), the 
integral/char-type uniform() makes use of an optimization, and returns

     std.random.uniform!ResultType(rng);

That is, it uses a specialization of uniform() for the case where one wants a 
random number drawn from all the possible bits of a given integral type.

With char and wchar (8- and 16-bit) this works fine.  However, dchar (32-bit) 
has a .max value that is less than the corresponding number of bits used to 
represent it: dchar.max is 1114111, while its 32 bits are theoretically capable 
of handling values of up to 4294967295.

A second consequence is that uniform!dchar (the all-the-bits specialization) 
will return invalid code points.

I take it this is a consequence of dchar being something of an oddity as a data 
type -- while stored as an "integral-like" value, it doesn't actually make use 
of the full range of values available in its 32 bits (unlike char and wchar 
which make full use of their 8-bit and 16-bit range).

I think it should suffice to forbid uniform!T from accepting dchar parameters 
and to tweak the integral-type uniform()'s internal check to avoid calling that 
specialization with dchar.

Thoughts ... ?

Thanks & best wishes,

     -- Joe


More information about the Digitalmars-d-learn mailing list