From f9433b2a87defb23c26c633105599a73e9d2a1bf Mon Sep 17 00:00:00 2001 From: Patric Mueller Date: Sun, 13 Jan 2019 16:36:55 +0100 Subject: [PATCH] integrate isaac64 into nethack Also removed the float code from isaac64 as they are not used in NetHack. --- include/config.h | 1 + include/extern.h | 3 ++ include/integer.h | 3 ++ include/isaac64.h | 46 +----------------- src/hacklib.c | 26 +++++----- src/isaac64.c | 110 +----------------------------------------- src/rnd.c | 25 ++++++++++ sys/unix/Makefile.src | 11 +++-- 8 files changed, 57 insertions(+), 168 deletions(-) diff --git a/include/config.h b/include/config.h index d59a82af5..3177512e1 100644 --- a/include/config.h +++ b/include/config.h @@ -556,6 +556,7 @@ typedef unsigned char uchar; #endif +#define USE_ISAAC64 /* Use cross-plattform, bundled RNG */ /* End of Section 4 */ diff --git a/include/extern.h b/include/extern.h index d85ad5f8c..9bc4e5a24 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2104,6 +2104,9 @@ E void FDECL(genl_outrip, (winid, int, time_t)); /* ### rnd.c ### */ +#ifdef USE_ISAAC64 +E void FDECL(init_isaac64, (unsigned long)); +#endif E int FDECL(rn2, (int)); E int FDECL(rnl, (int)); E int FDECL(rnd, (int)); diff --git a/include/integer.h b/include/integer.h index 8c9a0cbb0..d340e4177 100644 --- a/include/integer.h +++ b/include/integer.h @@ -36,6 +36,9 @@ typedef int int32; typedef unsigned int uint32; #endif +typedef unsigned long uint32_t; +typedef unsigned long long uint64_t; + #endif /* !C99 */ #endif /* INTEGER_H */ diff --git a/include/isaac64.h b/include/isaac64.h index 5c22253bd..6c9b45b52 100644 --- a/include/isaac64.h +++ b/include/isaac64.h @@ -1,7 +1,7 @@ -/* CC0 (Public domain) - see LICENSE file for details */ +/* CC0 (Public domain) - see http://creativecommons.org/publicdomain/zero/1.0/ for details */ #if !defined(_isaac64_H) # define _isaac64_H (1) -# include +# include @@ -85,47 +85,5 @@ uint64_t isaac64_next_uint(isaac64_ctx *_ctx,uint64_t _n); * To generate cheaper float values that do not have these properties, use * ldexpf((float)isaac64_next_uint64(_ctx),-64); */ -float isaac64_next_float(isaac64_ctx *_ctx); -/** - * isaac64_next_signed_float - Uniform random float in the range (-1,1). - * @_ctx: The ISAAC64 instance to generate the value with. - * Returns a high-quality float uniformly distributed between -1 and 1 - * (exclusive). - * All of the float's mantissa bits are random, e.g., the least significant bit - * may still be non-zero even if the magnitude is less than 0.5, and any - * representable float in the range (-1,1) has a chance to be returned, though - * values very close to zero become increasingly unlikely. - * To generate cheaper float values that do not have these properties, use - * ldexpf((float)isaac64_next_uint64(_ctx),-63)-1; - * though this returns values in the range [-1,1). - */ -float isaac64_next_signed_float(isaac64_ctx *_ctx); -/** - * isaac64_next_double - Uniform random double in the range [0,1). - * @_ctx: The ISAAC64 instance to generate the value with. - * Returns a high-quality double uniformly distributed between 0 (inclusive) - * and 1 (exclusive). - * All of the double's mantissa bits are random, e.g., the least significant - * bit may still be non-zero even if the value is less than 0.5, and any - * representable double in the range [0,1) has a chance to be returned, though - * values very close to zero become increasingly unlikely. - * To generate cheaper double values that do not have these properties, use - * ldexp((double)isaac64_next_uint64(_ctx),-64); - */ -double isaac64_next_double(isaac64_ctx *_ctx); -/** - * isaac64_next_signed_double - Uniform random double in the range (-1,1). - * @_ctx: The ISAAC64 instance to generate the value with. - * Returns a high-quality double uniformly distributed between -1 and 1 - * (exclusive). - * All of the double's mantissa bits are random, e.g., the least significant - * bit may still be non-zero even if the value is less than 0.5, and any - * representable double in the range (-1,1) has a chance to be returned, - * though values very close to zero become increasingly unlikely. - * To generate cheaper double values that do not have these properties, use - * ldexp((double)isaac64_next_uint64(_ctx),-63)-1; - * though this returns values in the range [-1,1). - */ -double isaac64_next_signed_double(isaac64_ctx *_ctx); #endif diff --git a/src/hacklib.c b/src/hacklib.c index 409c34007..74a326efd 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -884,26 +884,30 @@ get_random_seed() static void set_random(unsigned long seed) { +#ifdef USE_ISAAC64 + init_isaac64(seed); +#else /* the types are different enough here that sweeping the different * routine names into one via #defines is even more confusing */ -#ifdef RANDOM /* srandom() from sys/share/random.c */ +# ifdef RANDOM /* srandom() from sys/share/random.c */ srandom((unsigned int) seed); -#else -# if defined(__APPLE__) || defined(BSD) || defined(LINUX) || defined(ULTRIX) \ - || defined(CYGWIN32) /* system srandom() */ -# if defined(BSD) && !defined(POSIX_TYPES) && defined(SUNOS4) - (void) -# endif - srandom((int) seed); # else -# ifdef UNIX /* system srand48() */ +# if defined(__APPLE__) || defined(BSD) || defined(LINUX) || defined(ULTRIX) \ + || defined(CYGWIN32) /* system srandom() */ +# if defined(BSD) && !defined(POSIX_TYPES) && defined(SUNOS4) + (void) +# endif + srandom((int) seed); +# else +# ifdef UNIX /* system srand48() */ srand48((long) seed); -# else /* poor quality system routine */ +# else /* poor quality system routine */ srand((int) seed); +# endif +# endif # endif #endif -#endif } /* diff --git a/src/isaac64.c b/src/isaac64.c index 3a392fc9b..6a0037228 100644 --- a/src/isaac64.c +++ b/src/isaac64.c @@ -1,13 +1,10 @@ /*Written by Timothy B. Terriberry (tterribe@xiph.org) 1999-2009 - CC0 (Public domain) - see LICENSE file for details + CC0 (Public domain) - see http://creativecommons.org/publicdomain/zero/1.0/ for details Based on the public domain ISAAC implementation by Robert J. Jenkins Jr.*/ -#include #include #include -#include #include "isaac64.h" - #define ISAAC64_MASK ((uint64_t)0xFFFFFFFFFFFFFFFFULL) /* Extract ISAAC64_SZ_LOG bits (starting at bit 3). */ @@ -17,7 +14,7 @@ static inline uint32_t lower_bits(uint64_t x) } /* Extract next ISAAC64_SZ_LOG bits (starting at bit ISAAC64_SZ_LOG+2). */ -static inline uint32_t upper_bits(uint32_t y) +static inline uint32_t upper_bits(uint64_t y) { return (y >> (ISAAC64_SZ_LOG+3)) & (ISAAC64_SZ-1); } @@ -150,106 +147,3 @@ uint64_t isaac64_next_uint(isaac64_ctx *_ctx,uint64_t _n){ while(((d+_n-1)&ISAAC64_MASK)64 - ret=ldexpf((float)_bits,_base); -# if FLT_MANT_DIG>129 - while(64-nbits_needed<0){ -# else - if(64-nbits_needed<0){ -# endif - _base-=64; - nbits_needed-=64; - ret+=ldexpf((float)isaac64_next_uint64(_ctx),_base); - } - _bits=isaac64_next_uint64(_ctx)>>(64-nbits_needed); - ret+=ldexpf((float)_bits,_base-nbits_needed); -#else - if(nbits_needed>0){ - _bits=_bits<>(64-nbits_needed); - } -# if FLT_MANT_DIG<64 - else _bits>>=-nbits_needed; -# endif - ret=ldexpf((float)_bits,_base-nbits_needed); -#endif - return ret; -} - -float isaac64_next_float(isaac64_ctx *_ctx){ - return isaac64_float_bits(_ctx,0,0); -} - -float isaac64_next_signed_float(isaac64_ctx *_ctx){ - uint64_t bits; - bits=isaac64_next_uint64(_ctx); - return (1|-((int)bits&1))*isaac64_float_bits(_ctx,bits>>1,-63); -} - -/*Returns a uniform random double. - _bits: An initial set of random bits. - _base: This should be -(the number of bits in _bits), up to -64. - Return: A double uniformly distributed between 0 (inclusive) and 1 - (exclusive). - The average value was measured over 2**32 samples to be - 0.499990992392019273.*/ -static double isaac64_double_bits(isaac64_ctx *_ctx,uint64_t _bits,int _base){ - double ret; - int nbits_needed; - while(!_bits){ - if(_base+DBL_MANT_DIG64 - ret=ldexp((double)_bits,_base); -# if DBL_MANT_DIG>129 - while(64-nbits_needed<0){ -# else - if(64-nbits_needed<0){ -# endif - _base-=64; - nbits_needed-=64; - ret+=ldexp((double)isaac64_next_uint64(_ctx),_base); - } - _bits=isaac64_next_uint64(_ctx)>>(64-nbits_needed); - ret+=ldexp((double)_bits,_base-nbits_needed); -#else - if(nbits_needed>0){ - _bits=_bits<>(64-nbits_needed); - } -# if DBL_MANT_DIG<64 - else _bits>>=-nbits_needed; -# endif - ret=ldexp((double)_bits,_base-nbits_needed); -#endif - return ret; -} - -double isaac64_next_double(isaac64_ctx *_ctx){ - return isaac64_double_bits(_ctx,0,0); -} - -double isaac64_next_signed_double(isaac64_ctx *_ctx){ - uint64_t bits; - bits=isaac64_next_uint64(_ctx); - return (1|-((int)bits&1))*isaac64_double_bits(_ctx,bits>>1,-63); -} diff --git a/src/rnd.c b/src/rnd.c index c3627e854..9745d9ef2 100644 --- a/src/rnd.c +++ b/src/rnd.c @@ -4,6 +4,30 @@ #include "hack.h" +#ifdef USE_ISAAC64 +#include "isaac64.h" + +static isaac64_ctx rng_state; + +void +init_isaac64(unsigned long seed) +{ + unsigned char new_rng_state[sizeof(seed)]; + int i; + for (i=0; i>= 8; + } + + isaac64_init(&rng_state, new_rng_state, sizeof(seed)); +} + +static int +RND(int x) +{ + return (isaac64_next_uint64(&rng_state) % x); +} +#else /* "Rand()"s definition is determined by [OS]conf.h */ #if defined(LINT) && defined(UNIX) /* rand() is long... */ extern int NDECL(rand); @@ -16,6 +40,7 @@ extern int NDECL(rand); #define RND(x) ((int) ((Rand() >> 3) % (x))) #endif #endif /* LINT */ +#endif /* 0 <= rn2(x) < x */ int diff --git a/sys/unix/Makefile.src b/sys/unix/Makefile.src index 5548ed479..c6f25e029 100644 --- a/sys/unix/Makefile.src +++ b/sys/unix/Makefile.src @@ -441,9 +441,9 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \ botl.c cmd.c dbridge.c decl.c detect.c dig.c display.c dlb.c do.c \ do_name.c do_wear.c dog.c dogmove.c dokick.c dothrow.c drawing.c \ dungeon.c eat.c end.c engrave.c exper.c explode.c extralev.c \ - files.c fountain.c hack.c hacklib.c invent.c light.c lock.c \ - mail.c makemon.c mapglyph.c mcastu.c mhitm.c mhitu.c minion.c \ - mklev.c mkmap.c \ + files.c fountain.c hack.c hacklib.c invent.c isaac64.c light.c \ + lock.c mail.c makemon.c mapglyph.c mcastu.c mhitm.c mhitu.c \ + minion.c mklev.c mkmap.c \ mkmaze.c mkobj.c mkroom.c mon.c mondata.c monmove.c monst.c \ mplayer.c mthrowu.c muse.c music.c o_init.c objects.c objnam.c \ options.c pager.c pickup.c pline.c polyself.c potion.c pray.c \ @@ -508,8 +508,8 @@ HOBJ = $(FIRSTOBJ) allmain.o alloc.o apply.o artifact.o attrib.o ball.o \ bones.o botl.o cmd.o dbridge.o decl.o detect.o dig.o display.o dlb.o \ do.o do_name.o do_wear.o dog.o dogmove.o dokick.o dothrow.o \ drawing.o dungeon.o eat.o end.o engrave.o exper.o explode.o \ - extralev.o files.o fountain.o hack.o hacklib.o invent.o light.o \ - lock.o mail.o makemon.o mapglyph.o mcastu.o mhitm.o mhitu.o \ + extralev.o files.o fountain.o hack.o hacklib.o invent.o isaac64.o \ + light.o lock.o mail.o makemon.o mapglyph.o mcastu.o mhitm.o mhitu.o \ minion.o mklev.o mkmap.o \ mkmaze.o mkobj.o mkroom.o mon.o mondata.o monmove.o \ mplayer.o mthrowu.o muse.o music.o o_init.o objnam.o options.o \ @@ -1013,6 +1013,7 @@ fountain.o: fountain.c $(HACK_H) hack.o: hack.c $(HACK_H) hacklib.o: hacklib.c $(HACK_H) invent.o: invent.c $(HACK_H) +isaac64.o: isaac64.c ../include/isaac64.h ../include/integer.h light.o: light.c $(HACK_H) ../include/lev.h lock.o: lock.c $(HACK_H) mail.o: mail.c $(HACK_H) ../include/mail.h