diff --git a/include/rua_internal.h b/include/rua_internal.h index ea5079397..d2119157a 100644 --- a/include/rua_internal.h +++ b/include/rua_internal.h @@ -53,5 +53,6 @@ int QFile_AllocHandle (struct progs_s *pr, QFile *file); QFile *QFile_GetFile (struct progs_s *pr, int handle); void RUA_Input_Init (struct progs_s *pr, int secure); +void RUA_Mersenne_Init (struct progs_s *pr, int secure); #endif//__rua_internal_h diff --git a/libs/ruamoko/Makemodule.am b/libs/ruamoko/Makemodule.am index cc45944b9..08749dfef 100644 --- a/libs/ruamoko/Makemodule.am +++ b/libs/ruamoko/Makemodule.am @@ -36,4 +36,5 @@ libs_ruamoko_libQFruamoko_client_la_DEPENDENCIES= \ $(ruamoko_rua_libs) libs_ruamoko_libQFruamoko_client_la_SOURCES= \ libs/ruamoko/rua_game_init.c \ - libs/ruamoko/rua_input.c + libs/ruamoko/rua_input.c \ + libs/ruamoko/rua_mersenne.c diff --git a/libs/ruamoko/rua_game_init.c b/libs/ruamoko/rua_game_init.c index ba2cb2565..d0b239ddd 100644 --- a/libs/ruamoko/rua_game_init.c +++ b/libs/ruamoko/rua_game_init.c @@ -35,6 +35,7 @@ static void (*init_funcs[])(progs_t *, int) = { RUA_Input_Init, + RUA_Mersenne_Init, }; VISIBLE void diff --git a/libs/ruamoko/rua_mersenne.c b/libs/ruamoko/rua_mersenne.c new file mode 100644 index 000000000..6c503914f --- /dev/null +++ b/libs/ruamoko/rua_mersenne.c @@ -0,0 +1,166 @@ +/* + bi_mersenne.c + + Ruamoko Mersenne Twister api + + Copyright (C) 2021 Bill Currie + + Author: Bill Currie + Date: 2021/12/21 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/mersenne.h" +#include "QF/progs.h" + +#include "rua_internal.h" + +typedef struct { + //FIXME each mtstate_t is 2500 bytes and the map has 1024 elements + //per row, so having only one mtstate_t has an overhead of about 2.5MB + PR_RESMAP (mtstate_t) state_map; +} mtwist_resources_t; + +static mtstate_t * +state_new (mtwist_resources_t *res) +{ + return PR_RESNEW (res->state_map); +} + +static void +state_free (mtwist_resources_t *res, mtstate_t *state) +{ + PR_RESFREE (res->state_map, state); +} + +static void +state_reset (mtwist_resources_t *res) +{ + PR_RESRESET (res->state_map); +} + +static inline mtstate_t * +state_get (mtwist_resources_t *res, int index) +{ + return PR_RESGET(res->state_map, index); +} + +static inline int __attribute__((pure)) +state_index (mtwist_resources_t *res, mtstate_t *state) +{ + return PR_RESINDEX(res->state_map, state); +} + +static void +bi_mtwist_new (progs_t *pr) +{ + mtwist_resources_t *res = PR_Resources_Find (pr, "Mersenne Twister"); + + mtstate_t *mt = state_new (res); + mtwist_seed (mt, P_INT (pr, 0)); + R_INT (pr) = state_index (res, mt); +} + +static mtstate_t * +get_state (progs_t *pr, const char *name, int index) +{ + mtwist_resources_t *res = PR_Resources_Find (pr, "Mersenne Twister"); + mtstate_t *mt = state_get (res, index); + + if (!mt) + PR_RunError (pr, "invalid Mersenne Twister state index passed to %s", + name + 3); + return mt; +} + +static void +bi_mtwist_delete (progs_t *pr) +{ + mtwist_resources_t *res = PR_Resources_Find (pr, "Mersenne Twister"); + mtstate_t *mt = get_state (pr, __FUNCTION__, P_INT (pr, 0)); + state_free (res, mt); +} + +static void +bi_mtwist_seed (progs_t *pr) +{ + mtstate_t *mt = get_state (pr, __FUNCTION__, P_INT (pr, 0)); + mtwist_seed (mt, P_INT (pr, 1)); +} + +static void +bi_mtwist_rand (progs_t *pr) +{ + mtstate_t *mt = get_state (pr, __FUNCTION__, P_INT (pr, 0)); + R_INT (pr) = mtwist_rand (mt); +} + +static void +bi_mtwist_rand_0_1 (progs_t *pr) +{ + mtstate_t *mt = get_state (pr, __FUNCTION__, P_INT (pr, 0)); + R_FLOAT (pr) = mtwist_rand_0_1 (mt); +} + +static void +bi_mtwist_rand_m1_1 (progs_t *pr) +{ + mtstate_t *mt = get_state (pr, __FUNCTION__, P_INT (pr, 0)); + R_FLOAT (pr) = mtwist_rand_m1_1 (mt); +} + +static void +bi_mtwist_clear (progs_t *pr, void *data) +{ + mtwist_resources_t *res = (mtwist_resources_t *) data; + state_reset (res); +} + +#define bi(x) {#x, bi_##x, -1} +static builtin_t builtins[] = { + bi(mtwist_new), + bi(mtwist_delete), + bi(mtwist_seed), + bi(mtwist_rand), + bi(mtwist_rand_0_1), + bi(mtwist_rand_m1_1), + {0} +}; + +void +RUA_Mersenne_Init (progs_t *pr, int secure) +{ + mtwist_resources_t *res = calloc (1, sizeof (mtwist_resources_t)); + + PR_Resources_Register (pr, "Mersenne Twister", res, bi_mtwist_clear); + PR_RegisterBuiltins (pr, builtins); +} diff --git a/ruamoko/include/Makemodule.am b/ruamoko/include/Makemodule.am index 2920ed408..800c8ba89 100644 --- a/ruamoko/include/Makemodule.am +++ b/ruamoko/include/Makemodule.am @@ -5,6 +5,7 @@ ruamoko_include = \ ruamoko/include/infokey.h \ ruamoko/include/input.h \ ruamoko/include/math.h \ + ruamoko/include/mersenne.h \ ruamoko/include/message.h \ ruamoko/include/nq_message.h \ ruamoko/include/physics.h \ diff --git a/ruamoko/include/mersenne.h b/ruamoko/include/mersenne.h new file mode 100644 index 000000000..6f77cd7f5 --- /dev/null +++ b/ruamoko/include/mersenne.h @@ -0,0 +1,15 @@ +#ifndef __ruamoko_mersenne_h +#define __ruamoko_mersenne_h + +typedef struct _mtwist_t mtwist_t; + +mtwist_t *mtwist_new (int seed); +void mtwist_delete (mtwist_t *state); +void mtwist_seed (mtwist_t *state, int seed); +int mtwist_rand (mtwist_t *state); +// includes 0, does not include 1 +float mtwist_rand_0_1 (mtwist_t *state); +// does not include either -1 or 1 +float mtwist_rand_m1_1 (mtwist_t *state); + +#endif//__ruamoko_mersenne_h diff --git a/ruamoko/lib/Makemodule.am b/ruamoko/lib/Makemodule.am index e5218d298..17c657b17 100644 --- a/ruamoko/lib/Makemodule.am +++ b/ruamoko/lib/Makemodule.am @@ -49,6 +49,7 @@ ruamoko_lib_libcsqc_a_src= \ ruamoko/lib/draw.r \ ruamoko/lib/gib.r \ ruamoko/lib/input.r \ + ruamoko/lib/mersenne.r \ ruamoko/lib/key.r ruamoko_lib_common_dep=$(call qcautodep,$(ruamoko_lib_common_src)) diff --git a/ruamoko/lib/mersenne.r b/ruamoko/lib/mersenne.r new file mode 100644 index 000000000..26c217f9b --- /dev/null +++ b/ruamoko/lib/mersenne.r @@ -0,0 +1,8 @@ +#include "mersenne.h" + +mtwist_t *mtwist_new (int seed) = #0; +void mtwist_delete (mtwist_t *state) = #0; +void mtwist_seed (mtwist_t *state, int seed) = #0; +int mtwist_rand (mtwist_t *state) = #0; +float mtwist_rand_0_1 (mtwist_t *state) = #0; +float mtwist_rand_m1_1 (mtwist_t *state) = #0;