On 12/04/12 21:54, bearophile wrote:
Some comments on the details of your code:

Thanks ever so much for the extensive review.

import std.c.time;

In D there there is also the syntax:
import std.c.time: foo, bar, baz;

That tells the person that reads the code what names are used.

Is this advised for all D modules, or just for stuff using the C standard 
library?

Generally where possible add "const", "pure" and "nothrow" attributes to 
functions/methods every where you can (and in some cases @safe too, if you want):

      final size_t records_remaining() const pure nothrow { return 
recordsRemaining; }
      final size_t records_total() const pure nothrow { return recordsTotal; }

Whether I can do this would depend on whether I put in place a re-initialization function to allow the sampler to be reset with new values, no?

All D variables are initialized (unless you ask them to not be initialized, using "= 
void"), so the first "= 0" is not needed (but initializing D floating point values 
to zero is often necessary):

I want to be _certain_ that value is zero. ;-)

In D there is also the ^^ operator.

Ahh, another thing I once knew but had forgotten since the last time I looked 
at D.

                     for( t=recordsRemaining-1; t>=limit; --t)
                         y2 *= top--/bottom--;

Generally packing mutation of variables inside expressions is quite bad style. 
It makes code less easy to understand and translate, and currently it's not 
defined, just as in C (it will be defined, but it will keep being bad style).

OK.  There's one other that should be a point of concern, where I have

   return currentRecord++;

... in one function; I've added a selectedRecord variable to get round this.

      final size_t select(ref UniformRNG urng)
      {
            assert(_recordsRemaining > 0);
            assert(_sampleRemaining > 0);

            immutable size_t S = skip(urng);
            immutable size_t selectedRecord = _currentRecord + S;

            _sampleRemaining--;
            _recordsRemaining -= (S+1);
            _currentRecord += (S+1);

            return selectedRecord;
      }

Also in D there is (I hope it will not be deprecated) foreach_reverse(), maybe 
to replace this for().

I'll see what I can do with that. There may be a better way of expressing this anyway -- as is it's pretty much a literal transcription of the Pascal-esque pseudo-code in the original research paper describing the algorithm.

     sampling_test_simple!(VitterA!Random,Random)(100,5,urng);

Currently your code doesn't work if you want to use a Xorshift generator.

Ack, enabling that is precisely why I bothered templatizing it in the first place. Can you suggest a fix ... ? I don't understand why as-is it wouldn't work.

----------------------

     sampling_test_aggregate!(VitterA!Random,Random)(100,5,urng,10000000,true);
     writeln();
     sampling_test_aggregate!(VitterD!Random,Random)(100,5,urng,10000000,true);
     writeln();

I suggest to define one enum inside the main(), like this, with underscores 
too, to improve readability, and use it in all the function calls:

     enum int N = 10_000_000;
     samplingTestAggregate!(VitterA!Random, Random)(100, 5, urng, N, true);

Fair enough. I'd forgotten about the underscore notation for large numbers. This stuff I'm not too worried about, because it's only a stupid demo thing, not the important code ... :-)

Thanks again for the careful review, it's been very useful.

Best wishes,

    -- Joe

Reply via email to