On Sunday, 7 February 2016 at 22:27:40 UTC, Joseph Rushton
Wakeling wrote:
On Monday, 25 January 2016 at 22:06:31 UTC, Era Scarecrow wrote:
What you describe makes sense, but I don't quite follow what
you mean in one particular case:
Technically alloca simply returns the current sp, then adds
to it the number of bytes you requested. This means you have
to run it at the function stack where you want to use it (and
not in a called function, otherwise corruption). So inlined
functions where alloca's data would remain would be a must.
That's the low level assembly language that's generated i'm
referring to; At least based on what i've read and seen for code
output from a compiler to a .s file or similar.
I don't quite follow your remark about inlined functions; do
you mean that the function where the RNG instance is generated
must be inlined? (That would make sense in order to avoid the
internal state being deallocated immediately.)
Assuming alloca moves to the inlined function. Although i had
another idea thrown in my head where the memory would be
pre-allocated and you could just point to it when requested via
an allocator. So assume
@alloca(sizeof(int)) struct RNG {
During instantiation it would know the size ahead of time and
just append that to the end of the structure. That extra padding
space could be handled manually instead.
this(int seed) {
state = cast(void*)(this+1);
}
But this forced type breaking is quite clunky (and obviously the
wrong way to write it).
I recall in C there was suppose to be a way to attach an array
(of unknown size) immediately following a struct by making the
length of the array 0, then accessing it directly. But you'd
still need to guarantee somehow that the access rights are in
place and not referencing other data which you could screw up
(via optimizations or something).
I think there might be more complications here than just
allocating individual RNG instances, though (which can happen
quite early on in the program); what about stuff like random
algorithms (RandomCover, RandomSample) which might be generated
deep in internal loops, passed to other functionality as
rvalues, etc. etc.?
Either they use more stack space, or they act normally after
their call is done and are deallocated normally (automatically,
unless they are passed outside of the scope where they were
generated).
It might be simpler, in practice, to just have the state
refcounted.
I suppose the alternate is an option to skip/throw-away
some numbers that should've been consumed
I'm not sure I follow what you mean here or why you think
this would work? Could you give a concrete example?
void skip(int x) {assert(x>0); while(x--) popfront();}
rnd.take(10).writeln; //loosely based on talk examples
rnd.skip(10); //skips the 'consumed' numbers.
rnd.take(10).writeln; //won't have identical output
I'm afraid that's not really viable :-(
But the problem is, in the general case, you can't anticipate
how many random variates may be popped from your random number
generator inside a function.
True; Perhaps have one RNG for seeding and one RNG for passing,
then reseed after passing the function off, although how far deep
some of this could go with it's deeper copying; I don't know.
Perhaps RNG should be a class outright, which probably removes a
lot of these problems.