-- Copyright 1993-1998, by the Cecil Project -- Department of Computer Science and Engineering, University of Washington -- See the LICENSE file for license information. (--DOC A `random_stream' is an infinitely-long stream of ints in the range 0 to range-1 inclusive. The initial seed of the random stream can be set upon creation, to generate reproducible random streams. --) include "stream.cecil"; module Random { template object random_stream isa stream[int]; private field range(@:random_stream):int; private var field next_elem(@:random_stream):int := -1; -- for peeks method peek_next(t@:random_stream, at_end:&():int):int { if(t.next_elem = -1, { t.next_elem := get_rand(t); }); t.next_elem % t.range } method next(t@:random_stream, at_end:&():int):int { let var res:int := 0; if(t.next_elem = -1, { res := get_rand(t); }, { res := t.next_elem; t.next_elem := -1; }); res % t.range } -- random streams are infinitely long method is_at_end(@:random_stream):bool { false } -- internal methods prim c_++ { #if VORTEX_SUN4 || VORTEX_SOLARIS || VORTEX_POWERPC extern "C" int random(); extern "C" void srandom(int); #endif }; private method get_rand(t@:random_stream):int (** return_type(int), sends(), does_io, formals_escape(f) **) { prim c_++: " int x = random(); x >>= 2; // convert to 30-bit version #ifdef DISPATCHERS RETURN(asTaggedInt(x)); #else BP(asTaggedInt(x)); #endif " } private method set_seed(t@:random_stream, i:int):void (** return_type(void), sends(), does_io, formals_escape(f,f) **) { prim c_++: " int j = i->asInt(); srandom(j); #ifdef DISPATCHERS RETURN(BASE(void)); #else BP(BASE(void)); #endif " } -- stream constructors method new_rand_stream(i:int):random_stream { concrete object isa random_stream { range := i } } method new_rand_stream(i:int, j:int):random_stream { let s:random_stream := new_rand_stream(i); s.seed := j; s } -- some common uses of random streams method random_vector(len:int, range:int):vector[int] { new_rand_stream(range).next_N(len).as_vector } }; -- end Random