From 08920e75e7b65f1c3731b94356f7277bb1b12264 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Sat, 27 Jan 2024 09:22:30 +0100 Subject: [PATCH] Move random number related code to src/gnu (#2689) * This patch moves most of the code that is not HOC to the directory gnu. * `Isaac`, `MCellRan4`, `Random123`, `Rand` * In the future this directory will be cleaned to remove gnu stuff and renamed something like 'src/random'. * This way nrn will have an external random library, and a clean hoc_interface. --- cmake/CompilerHelper.cmake | 2 +- cmake/NeuronFileLists.cmake | 13 +-- src/gnu/CMakeLists.txt | 9 ++ src/gnu/Isaac64RNG.cpp | 20 ++++ src/gnu/Isaac64RNG.hpp | 33 ++++++ src/gnu/MCellRan4RNG.cpp | 15 +++ src/gnu/MCellRan4RNG.hpp | 34 ++++++ src/gnu/NrnRandom123RNG.cpp | 0 src/gnu/NrnRandom123RNG.hpp | 28 +++++ src/gnu/Rand.cpp | 19 ++++ src/{ivoc/random1.h => gnu/Rand.hpp} | 14 ++- src/{oc => gnu}/isaac64.cpp | 5 - src/{oc => gnu}/isaac64.h | 7 +- src/{oc => gnu}/mcran4.cpp | 42 +------ src/{oc => gnu}/mcran4.h | 1 + src/gnu/nrnisaac.cpp | 25 ++++ src/gnu/nrnisaac.h | 9 ++ src/{oc => gnu}/nrnran123.cpp | 0 src/{oc => gnu}/nrnran123.h | 0 src/ivoc/ivocrand.cpp | 163 ++++----------------------- src/ivoc/ivocvect.cpp | 2 +- src/nrniv/CMakeLists.txt | 1 - src/oc/hoc_init.cpp | 4 +- src/oc/nrnisaac.cpp | 39 ------- src/oc/nrnisaac.h | 15 --- src/oc/oc_mcran4.cpp | 41 +++++++ src/oc/oc_mcran4.hpp | 5 + src/oc/ocfunc.h | 1 - src/oc/scoprand.cpp | 6 +- 29 files changed, 286 insertions(+), 267 deletions(-) create mode 100644 src/gnu/Isaac64RNG.cpp create mode 100644 src/gnu/Isaac64RNG.hpp create mode 100644 src/gnu/MCellRan4RNG.cpp create mode 100644 src/gnu/MCellRan4RNG.hpp create mode 100644 src/gnu/NrnRandom123RNG.cpp create mode 100644 src/gnu/NrnRandom123RNG.hpp create mode 100644 src/gnu/Rand.cpp rename src/{ivoc/random1.h => gnu/Rand.hpp} (63%) rename src/{oc => gnu}/isaac64.cpp (98%) rename src/{oc => gnu}/isaac64.h (97%) rename src/{oc => gnu}/mcran4.cpp (86%) rename src/{oc => gnu}/mcran4.h (98%) create mode 100644 src/gnu/nrnisaac.cpp create mode 100644 src/gnu/nrnisaac.h rename src/{oc => gnu}/nrnran123.cpp (100%) rename src/{oc => gnu}/nrnran123.h (100%) delete mode 100644 src/oc/nrnisaac.cpp delete mode 100644 src/oc/nrnisaac.h create mode 100644 src/oc/oc_mcran4.cpp create mode 100644 src/oc/oc_mcran4.hpp diff --git a/cmake/CompilerHelper.cmake b/cmake/CompilerHelper.cmake index 54adf1ce31..e50b120351 100644 --- a/cmake/CompilerHelper.cmake +++ b/cmake/CompilerHelper.cmake @@ -51,7 +51,7 @@ if(CMAKE_C_COMPILER_ID MATCHES "PGI" OR CMAKE_C_COMPILER_ID MATCHES "NVHPC") # Random123 does not play nicely with NVHPC 21.11+'s detection of ABM features, see: # https://github.com/BlueBrain/CoreNeuron/issues/724 and # https://github.com/DEShawResearch/random123/issues/6. - list(APPEND NRN_COMPILE_DEFS R123_USE_INTRIN_H=0) + list(APPEND NRN_R123_COMPILE_DEFS R123_USE_INTRIN_H=0) endif() else() set(NRN_HAVE_NVHPC_COMPILER OFF) diff --git a/cmake/NeuronFileLists.cmake b/cmake/NeuronFileLists.cmake index 252f3e9ff6..c1beffb9fd 100644 --- a/cmake/NeuronFileLists.cmake +++ b/cmake/NeuronFileLists.cmake @@ -9,6 +9,9 @@ set(STRUCTURED_HEADER_FILES_TO_INSTALL neuron/container/generic_data_handle.hpp neuron/container/non_owning_soa_identifier.hpp neuron/model_data_fwd.hpp) set(HEADER_FILES_TO_INSTALL + gnu/mcran4.h + gnu/nrnisaac.h + gnu/nrnran123.h nrniv/backtrace_utils.h nrniv/bbsavestate.h nrnmpi/nrnmpidec.h @@ -37,15 +40,12 @@ set(HEADER_FILES_TO_INSTALL oc/hocgetsym.h oc/hoclist.h oc/hocparse.h - oc/mcran4.h oc/mech_api.h oc/memory.hpp oc/nrnapi.h oc/nrnassrt.h - oc/nrnisaac.h oc/nrnmpi.h oc/nrnrandom.h - oc/nrnran123.h oc/oc_ansi.h oc/ocfunc.h oc/ocmisc.h @@ -77,16 +77,10 @@ set(HEADER_FILES_TO_INSTALL # ============================================================================= set(NRN_HEADERS_INCLUDE_LIST) -# ============================================================================= -# Lists of random number related files -# ============================================================================= -set(RAN_FILE_LIST isaac64.cpp mcran4.cpp nrnisaac.cpp nrnran123.cpp) - # ============================================================================= # Files in oc directory # ============================================================================= set(OC_FILE_LIST - ${RAN_FILE_LIST} audit.cpp axis.cpp code.cpp @@ -102,6 +96,7 @@ set(OC_FILE_LIST hoc_oop.cpp list.cpp math.cpp + oc_mcran4.cpp memory.cpp mswinprt.cpp nonlin.cpp diff --git a/src/gnu/CMakeLists.txt b/src/gnu/CMakeLists.txt index 0e9562297c..e16ae608b9 100644 --- a/src/gnu/CMakeLists.txt +++ b/src/gnu/CMakeLists.txt @@ -6,14 +6,23 @@ add_library( Erlang.cpp Geom.cpp HypGeom.cpp + isaac64.cpp + Isaac64RNG.cpp LogNorm.cpp + MCellRan4RNG.cpp + mcran4.cpp MLCG.cpp NegExp.cpp Normal.cpp + nrnisaac.cpp + nrnran123.cpp Poisson.cpp + Rand.cpp Random.cpp RndInt.cpp RNG.cpp Uniform.cpp Weibull.cpp) set_property(TARGET nrngnu PROPERTY POSITION_INDEPENDENT_CODE ON) +target_include_directories(nrngnu SYSTEM PRIVATE "${PROJECT_SOURCE_DIR}/external/Random123/include") +target_compile_definitions(nrngnu PRIVATE ${NRN_R123_COMPILE_DEFS}) diff --git a/src/gnu/Isaac64RNG.cpp b/src/gnu/Isaac64RNG.cpp new file mode 100644 index 0000000000..559c307d4d --- /dev/null +++ b/src/gnu/Isaac64RNG.cpp @@ -0,0 +1,20 @@ +#include "Isaac64RNG.hpp" + +uint32_t Isaac64::cnt_ = 0; + +Isaac64::Isaac64(std::uint32_t seed) { + if (cnt_ == 0) { + cnt_ = 0xffffffff; + } + --cnt_; + seed_ = seed; + if (seed_ == 0) { + seed_ = cnt_; + } + rng_ = nrnisaac_new(); + reset(); +} + +Isaac64::~Isaac64() { + nrnisaac_delete(rng_); +} diff --git a/src/gnu/Isaac64RNG.hpp b/src/gnu/Isaac64RNG.hpp new file mode 100644 index 0000000000..c825c741ca --- /dev/null +++ b/src/gnu/Isaac64RNG.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include "RNG.h" +#include "nrnisaac.h" + +class Isaac64: public RNG { + public: + Isaac64(std::uint32_t seed = 0); + ~Isaac64(); + std::uint32_t asLong() { + return nrnisaac_uint32_pick(rng_); + } + void reset() { + nrnisaac_init(rng_, seed_); + } + double asDouble() { + return nrnisaac_dbl_pick(rng_); + } + std::uint32_t seed() { + return seed_; + } + void seed(std::uint32_t s) { + seed_ = s; + reset(); + } + + private: + std::uint32_t seed_; + void* rng_; + static std::uint32_t cnt_; +}; diff --git a/src/gnu/MCellRan4RNG.cpp b/src/gnu/MCellRan4RNG.cpp new file mode 100644 index 0000000000..43b732cbe1 --- /dev/null +++ b/src/gnu/MCellRan4RNG.cpp @@ -0,0 +1,15 @@ +#include "MCellRan4RNG.hpp" + +MCellRan4::MCellRan4(std::uint32_t ihigh, std::uint32_t ilow) { + ++cnt_; + ilow_ = ilow; + ihigh_ = ihigh; + if (ihigh_ == 0) { + ihigh_ = cnt_; + ihigh_ = (std::uint32_t) asLong(); + } + orig_ = ihigh_; +} +MCellRan4::~MCellRan4() {} + +std::uint32_t MCellRan4::cnt_ = 0; diff --git a/src/gnu/MCellRan4RNG.hpp b/src/gnu/MCellRan4RNG.hpp new file mode 100644 index 0000000000..a4356562a9 --- /dev/null +++ b/src/gnu/MCellRan4RNG.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include "RNG.h" +#include "mcran4.h" + +// The decision that has to be made is whether each generator instance +// should have its own seed or only one seed for all. We choose separate +// seed for each but if arg not present or 0 then seed chosen by system. + +// the addition of ilow > 0 means that value is used for the lowindex +// instead of the mcell_ran4_init global 32 bit lowindex. + +class MCellRan4: public RNG { + public: + MCellRan4(std::uint32_t ihigh = 0, std::uint32_t ilow = 0); + virtual ~MCellRan4(); + virtual std::uint32_t asLong() { + return (std::uint32_t) (ilow_ == 0 ? mcell_iran4(&ihigh_) : nrnRan4int(&ihigh_, ilow_)); + } + virtual void reset() { + ihigh_ = orig_; + } + virtual double asDouble() { + return (ilow_ == 0 ? mcell_ran4a(&ihigh_) : nrnRan4dbl(&ihigh_, ilow_)); + } + std::uint32_t ihigh_; + std::uint32_t orig_; + std::uint32_t ilow_; + + private: + static std::uint32_t cnt_; +}; diff --git a/src/gnu/NrnRandom123RNG.cpp b/src/gnu/NrnRandom123RNG.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/gnu/NrnRandom123RNG.hpp b/src/gnu/NrnRandom123RNG.hpp new file mode 100644 index 0000000000..5e790c939c --- /dev/null +++ b/src/gnu/NrnRandom123RNG.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include + +#include "nrnran123.h" +#include "RNG.h" + +class NrnRandom123: public RNG { + public: + NrnRandom123(std::uint32_t id1, std::uint32_t id2, std::uint32_t id3 = 0); + ~NrnRandom123(); + std::uint32_t asLong() { + return nrnran123_ipick(s_); + } + double asDouble() { + return nrnran123_dblpick(s_); + } + void reset() { + nrnran123_setseq(s_, 0, 0); + } + nrnran123_State* s_; +}; +NrnRandom123::NrnRandom123(std::uint32_t id1, std::uint32_t id2, std::uint32_t id3) { + s_ = nrnran123_newstream3(id1, id2, id3); +} +NrnRandom123::~NrnRandom123() { + nrnran123_deletestream(s_); +} diff --git a/src/gnu/Rand.cpp b/src/gnu/Rand.cpp new file mode 100644 index 0000000000..a3b526de5e --- /dev/null +++ b/src/gnu/Rand.cpp @@ -0,0 +1,19 @@ +#include "Rand.hpp" + +#include "ACG.h" +#include "Normal.h" + +Rand::Rand(unsigned long seed, int size, Object* obj) { + // printf("Rand\n"); + gen = new ACG(seed, size); + rand = new Normal(0., 1., gen); + type_ = 0; + obj_ = obj; +} + +Rand::~Rand() { + // printf("~Rand\n"); + delete gen; + delete rand; +} + diff --git a/src/ivoc/random1.h b/src/gnu/Rand.hpp similarity index 63% rename from src/ivoc/random1.h rename to src/gnu/Rand.hpp index 8fedd8f5b0..f5b47a6a61 100644 --- a/src/ivoc/random1.h +++ b/src/gnu/Rand.hpp @@ -1,14 +1,20 @@ -#ifndef random1_h -#define random1_h +#pragma once #include "RNG.h" #include "Random.h" struct Object; +/* type_: + * 0: ACG + * 1: MLCG + * 2: MCellRan4 + * 3: Isaac64 + * 4: Random123 + */ class Rand { public: - Rand(unsigned long seed = 0, int size = 55, Object* obj = NULL); + Rand(unsigned long seed = 0, int size = 55, Object* obj = nullptr); ~Rand(); RNG* gen; Random* rand; @@ -16,5 +22,3 @@ class Rand { // double* looks like random variable that gets changed on every fadvance Object* obj_; }; - -#endif diff --git a/src/oc/isaac64.cpp b/src/gnu/isaac64.cpp similarity index 98% rename from src/oc/isaac64.cpp rename to src/gnu/isaac64.cpp index 579f52d4f0..b0c6c40317 100644 --- a/src/oc/isaac64.cpp +++ b/src/gnu/isaac64.cpp @@ -1,8 +1,3 @@ -#include <../../nrnconf.h> -#if HAVE_SYS_TYPES_H -#include -#endif - /* ------------------------------------------------------------------------------ isaac64.cpp: A Fast cryptographic random number generator diff --git a/src/oc/isaac64.h b/src/gnu/isaac64.h similarity index 97% rename from src/oc/isaac64.h rename to src/gnu/isaac64.h index 6b13dd72f1..4af3b7586e 100644 --- a/src/oc/isaac64.h +++ b/src/gnu/isaac64.h @@ -1,3 +1,5 @@ +#pragma once + /* ------------------------------------------------------------------------------ isaac64.h: Definitions for a fast cryptographic random number generator @@ -12,10 +14,7 @@ Jenkins, R.J. (1996) ISAAC, in Fast Software Encryption, vol. 1039, ------------------------------------------------------------------------------ */ -#ifndef ISAAC64_H -#define ISAAC64_H -#include #include #define RANDSIZL (4) /* I recommend 8 for crypto, 4 for simulations */ @@ -87,5 +86,3 @@ Macros to get individual random numbers rng->randcnt = RANDMAX - 2, \ DBL64 * (*((ub8*) (((ub4*) (rng->randrsl)) + rng->randcnt))))) - -#endif /* ISAAC64_H */ diff --git a/src/oc/mcran4.cpp b/src/gnu/mcran4.cpp similarity index 86% rename from src/oc/mcran4.cpp rename to src/gnu/mcran4.cpp index 1b303164d6..a9553687f6 100644 --- a/src/oc/mcran4.cpp +++ b/src/gnu/mcran4.cpp @@ -39,17 +39,19 @@ contained the header: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <../../nrnconf.h> #include #include #include #include #include -#include -#include "hocdec.h" +#include "mcran4.h" static uint32_t lowindex = 0; +double mcell_lowindex() { + return static_cast(lowindex); +} + void mcell_ran4_init(uint32_t low) { lowindex = low; } @@ -70,40 +72,6 @@ uint32_t mcell_iran4(uint32_t* high) { return nrnRan4int(high, lowindex); } -/* Hoc interface */ -extern double chkarg(); -extern int use_mcell_ran4_; - - -void hoc_mcran4() { - uint32_t idx; - double* xidx; - double x; - xidx = hoc_pgetarg(1); - idx = (uint32_t) (*xidx); - x = mcell_ran4a(&idx); - *xidx = idx; - hoc_ret(); - hoc_pushx(x); -} -void hoc_mcran4init() { - double prev = (double) lowindex; - if (ifarg(1)) { - uint32_t idx = (uint32_t) chkarg(1, 0., 4294967295.); - mcell_ran4_init(idx); - } - hoc_ret(); - hoc_pushx(prev); -} -void hoc_usemcran4() { - double prev = (double) use_mcell_ran4_; - if (ifarg(1)) { - use_mcell_ran4_ = (int) chkarg(1, 0., 1.); - } - hoc_ret(); - hoc_pushx(prev); -} - uint32_t nrnRan4int(uint32_t* idx1, uint32_t idx2) { uint32_t u, v, w, m, n; /* 64-bit hash */ diff --git a/src/oc/mcran4.h b/src/gnu/mcran4.h similarity index 98% rename from src/oc/mcran4.h rename to src/gnu/mcran4.h index 7d251b4cc1..9d7ff79dd9 100644 --- a/src/oc/mcran4.h +++ b/src/gnu/mcran4.h @@ -1,6 +1,7 @@ #pragma once #include +double mcell_lowindex(); void mcell_ran4_init(uint32_t); double mcell_ran4(uint32_t* idx1, double* x, unsigned int n, double range); double mcell_ran4a(uint32_t* idx1); diff --git a/src/gnu/nrnisaac.cpp b/src/gnu/nrnisaac.cpp new file mode 100644 index 0000000000..f0549a4d9a --- /dev/null +++ b/src/gnu/nrnisaac.cpp @@ -0,0 +1,25 @@ +#include +#include "nrnisaac.h" +#include "isaac64.h" + +using RNG = struct isaac64_state; + +void* nrnisaac_new() { + return new RNG; +} + +void nrnisaac_delete(void* v) { + delete static_cast(v); +} + +void nrnisaac_init(void* v, unsigned long int seed) { + isaac64_init(static_cast(v), seed); +} + +double nrnisaac_dbl_pick(void* v) { + return isaac64_dbl32(static_cast(v)); +} + +std::uint32_t nrnisaac_uint32_pick(void* v) { + return isaac64_uint32(static_cast(v)); +} diff --git a/src/gnu/nrnisaac.h b/src/gnu/nrnisaac.h new file mode 100644 index 0000000000..5322febafe --- /dev/null +++ b/src/gnu/nrnisaac.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +void* nrnisaac_new(); +void nrnisaac_delete(void* rng); +void nrnisaac_init(void* rng, unsigned long int seed); +double nrnisaac_dbl_pick(void* rng); +std::uint32_t nrnisaac_uint32_pick(void* rng); diff --git a/src/oc/nrnran123.cpp b/src/gnu/nrnran123.cpp similarity index 100% rename from src/oc/nrnran123.cpp rename to src/gnu/nrnran123.cpp diff --git a/src/oc/nrnran123.h b/src/gnu/nrnran123.h similarity index 100% rename from src/oc/nrnran123.h rename to src/gnu/nrnran123.h diff --git a/src/ivoc/ivocrand.cpp b/src/ivoc/ivocrand.cpp index fa45403dcc..f250049299 100644 --- a/src/ivoc/ivocrand.cpp +++ b/src/ivoc/ivocrand.cpp @@ -4,7 +4,7 @@ #include #include -#include "random1.h" +#include "Rand.hpp" #include #include "classreg.h" @@ -17,7 +17,6 @@ #include "ocobserv.h" #include -#include #include #include #include @@ -33,6 +32,9 @@ #include #include #include +#include +#include +#include #if HAVE_IV #include "ivoc.h" @@ -59,118 +61,6 @@ class RandomPlay: public Observer, public Resource { using RandomPlayList = std::vector; static RandomPlayList* random_play_list_; -#include - -class NrnRandom123: public RNG { - public: - NrnRandom123(uint32_t id1, uint32_t id2, uint32_t id3 = 0); - virtual ~NrnRandom123(); - virtual uint32_t asLong() { - return nrnran123_ipick(s_); - } - virtual double asDouble() { - return nrnran123_dblpick(s_); - } - virtual void reset() { - nrnran123_setseq(s_, 0, 0); - } - nrnran123_State* s_; -}; -NrnRandom123::NrnRandom123(uint32_t id1, uint32_t id2, uint32_t id3) { - s_ = nrnran123_newstream3(id1, id2, id3); -} -NrnRandom123::~NrnRandom123() { - nrnran123_deletestream(s_); -} - - -// The decision that has to be made is whether each generator instance -// should have its own seed or only one seed for all. We choose separate -// seed for each but if arg not present or 0 then seed chosen by system. - -// the addition of ilow > 0 means that value is used for the lowindex -// instead of the mcell_ran4_init global 32 bit lowindex. - -class MCellRan4: public RNG { - public: - MCellRan4(uint32_t ihigh = 0, uint32_t ilow = 0); - virtual ~MCellRan4(); - virtual uint32_t asLong() { - return (uint32_t) (ilow_ == 0 ? mcell_iran4(&ihigh_) : nrnRan4int(&ihigh_, ilow_)); - } - virtual void reset() { - ihigh_ = orig_; - } - virtual double asDouble() { - return (ilow_ == 0 ? mcell_ran4a(&ihigh_) : nrnRan4dbl(&ihigh_, ilow_)); - } - uint32_t ihigh_; - uint32_t orig_; - uint32_t ilow_; - - private: - static uint32_t cnt_; -}; - -MCellRan4::MCellRan4(uint32_t ihigh, uint32_t ilow) { - ++cnt_; - ilow_ = ilow; - ihigh_ = ihigh; - if (ihigh_ == 0) { - ihigh_ = cnt_; - ihigh_ = (uint32_t) asLong(); - } - orig_ = ihigh_; -} -MCellRan4::~MCellRan4() {} - -uint32_t MCellRan4::cnt_ = 0; - -class Isaac64: public RNG { - public: - Isaac64(uint32_t seed = 0); - virtual ~Isaac64(); - virtual uint32_t asLong() { - return (uint32_t) nrnisaac_uint32_pick(rng_); - } - virtual void reset() { - nrnisaac_init(rng_, seed_); - } - virtual double asDouble() { - return nrnisaac_dbl_pick(rng_); - } - uint32_t seed() { - return seed_; - } - void seed(uint32_t s) { - seed_ = s; - reset(); - } - - private: - uint32_t seed_; - void* rng_; - static uint32_t cnt_; -}; - -Isaac64::Isaac64(uint32_t seed) { - if (cnt_ == 0) { - cnt_ = 0xffffffff; - } - --cnt_; - seed_ = seed; - if (seed_ == 0) { - seed_ = cnt_; - } - rng_ = nrnisaac_new(); - reset(); -} -Isaac64::~Isaac64() { - nrnisaac_delete(rng_); -} - -uint32_t Isaac64::cnt_ = 0; - RandomPlay::RandomPlay(Rand* r, neuron::container::data_handle px) : r_{r} , px_{std::move(px)} { @@ -197,27 +87,6 @@ void RandomPlay::update(Observable*) { list_remove(); } -Rand::Rand(unsigned long seed, int size, Object* obj) { - // printf("Rand\n"); - gen = new ACG(seed, size); - rand = new Normal(0., 1., gen); - type_ = 0; - obj_ = obj; -} - -Rand::~Rand() { - // printf("~Rand\n"); - delete gen; - delete rand; -} - -// constructor for a random number generator based on the RNG class -// from the gnu c++ class library -// defaults to the ACG generator (see below) - -// syntax: -// a = new Rand([seed],[size]) - static void* r_cons(Object* obj) { unsigned long seed = 0; int size = 55; @@ -406,14 +275,22 @@ static double r_Isaac64(void* r) { uint32_t seed1 = 0; - if (ifarg(1)) - seed1 = (uint32_t) (*getarg(1)); - Isaac64* mcr = new Isaac64(seed1); - x->rand->generator(mcr); - delete x->gen; - x->gen = x->rand->generator(); - x->type_ = 3; - return (double) mcr->seed(); + if (ifarg(1)) { + seed1 = static_cast(*getarg(1)); + } + + double seed{}; + try { + Isaac64* mcr = new Isaac64(seed1); + x->rand->generator(mcr); + delete x->gen; + x->gen = x->rand->generator(); + x->type_ = 3; + seed = mcr->seed(); + } catch (const std::bad_alloc& e) { + hoc_execerror("Bad allocation for Isaac64 generator", e.what()); + } + return seed; } // Pick again from the distribution last used diff --git a/src/ivoc/ivocvect.cpp b/src/ivoc/ivocvect.cpp index cc6565bea3..7b9087d328 100644 --- a/src/ivoc/ivocvect.cpp +++ b/src/ivoc/ivocvect.cpp @@ -111,7 +111,7 @@ static double dmaxint_ = 9007199254740992; #include "ivocvect.h" // definition of random numer generator -#include "random1.h" +#include "Rand.hpp" #include #if HAVE_IV diff --git a/src/nrniv/CMakeLists.txt b/src/nrniv/CMakeLists.txt index babfe56cc4..48f1c16531 100644 --- a/src/nrniv/CMakeLists.txt +++ b/src/nrniv/CMakeLists.txt @@ -211,7 +211,6 @@ set(NRN_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/src/parallel ${PROJECT_BINARY_DIR}/src/sundials ${PROJECT_BINARY_DIR}/src/sundials/shared - ${PROJECT_SOURCE_DIR}/external/Random123/include ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/src/gnu ${PROJECT_SOURCE_DIR}/src/nrncvode diff --git a/src/oc/hoc_init.cpp b/src/oc/hoc_init.cpp index 6e022f7047..17675d7753 100644 --- a/src/oc/hoc_init.cpp +++ b/src/oc/hoc_init.cpp @@ -10,6 +10,7 @@ #include "nrn_ansi.h" #include "ocfunc.h" +#include "oc_mcran4.hpp" extern void hoc_nrnmpi_init(); @@ -231,7 +232,6 @@ double hoc_default_dll_loaded_; char* neuron_home; const char* nrn_mech_dll; /* but actually only for NEURON mswin and linux */ int nrn_noauto_dlopen_nrnmech; /* 0 except when binary special. */ -int use_mcell_ran4_; int nrn_xopen_broadcast_; void hoc_init(void) /* install constants and built-ins table */ @@ -255,7 +255,7 @@ void hoc_init(void) /* install constants and built-ins table */ } } - use_mcell_ran4_ = 0; + set_use_mcran4(false); nrn_xopen_broadcast_ = 255; extern void hoc_init_space(void); hoc_init_space(); diff --git a/src/oc/nrnisaac.cpp b/src/oc/nrnisaac.cpp deleted file mode 100644 index 1aa0050339..0000000000 --- a/src/oc/nrnisaac.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include <../../nrnconf.h> -#include -#if HAVE_SYS_TYPES_H -#include -#endif -#include -#include -#include "hocdec.h" - -typedef struct isaac64_state Rng; - -void* nrnisaac_new(void) { - Rng* rng; - rng = (Rng*) hoc_Emalloc(sizeof(Rng)); - hoc_malchk(); - return (void*) rng; -} - -void nrnisaac_delete(void* v) { - free(v); -} - -void nrnisaac_init(void* v, unsigned long int seed) { - isaac64_init((Rng*) v, seed); -} - -double nrnisaac_dbl_pick(void* v) { - Rng* rng = (Rng*) v; - double x = isaac64_dbl32(rng); - /*printf("dbl %d %d %d %d %g\n", sizeof(ub8), sizeof(ub4), sizeof(ub2), sizeof(ub1), x);*/ - return x; -} - -uint32_t nrnisaac_uint32_pick(void* v) { - Rng* rng = (Rng*) v; - double x = isaac64_uint32(rng); - /*printf("uint32 %g\n", x);*/ - return x; -} diff --git a/src/oc/nrnisaac.h b/src/oc/nrnisaac.h deleted file mode 100644 index 053366684c..0000000000 --- a/src/oc/nrnisaac.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef nrnisaac_h -#define nrnisaac_h - -#include <../../nrnconf.h> -#include - - -void* nrnisaac_new(void); -void nrnisaac_delete(void* rng); -void nrnisaac_init(void* rng, unsigned long int seed); -double nrnisaac_dbl_pick(void* rng); -uint32_t nrnisaac_uint32_pick(void* rng); - - -#endif diff --git a/src/oc/oc_mcran4.cpp b/src/oc/oc_mcran4.cpp new file mode 100644 index 0000000000..128ccd7d04 --- /dev/null +++ b/src/oc/oc_mcran4.cpp @@ -0,0 +1,41 @@ +#include "hocdec.h" +#include "mcran4.h" + +int use_mcell_ran4_; + +void set_use_mcran4(bool value) { + use_mcell_ran4_ = value ? 1 : 0; +} + +bool use_mcran4() { + return use_mcell_ran4_ != 0; +} + +void hoc_mcran4() { + uint32_t idx; + double* xidx; + double x; + xidx = hoc_pgetarg(1); + idx = (uint32_t) (*xidx); + x = mcell_ran4a(&idx); + *xidx = idx; + hoc_ret(); + hoc_pushx(x); +} +void hoc_mcran4init() { + double prev = mcell_lowindex(); + if (ifarg(1)) { + uint32_t idx = (uint32_t) chkarg(1, 0., 4294967295.); + mcell_ran4_init(idx); + } + hoc_ret(); + hoc_pushx(prev); +} +void hoc_usemcran4() { + double prev = (double) use_mcell_ran4_; + if (ifarg(1)) { + use_mcell_ran4_ = (int) chkarg(1, 0., 1.); + } + hoc_ret(); + hoc_pushx(prev); +} diff --git a/src/oc/oc_mcran4.hpp b/src/oc/oc_mcran4.hpp new file mode 100644 index 0000000000..d275e3e9bf --- /dev/null +++ b/src/oc/oc_mcran4.hpp @@ -0,0 +1,5 @@ +void set_use_mcran4(bool value); +bool use_mcran4(); +void hoc_mcran4(); +void hoc_mcran4init(); +void hoc_usemcran4(); diff --git a/src/oc/ocfunc.h b/src/oc/ocfunc.h index fca598c0fa..61a620aa44 100644 --- a/src/oc/ocfunc.h +++ b/src/oc/ocfunc.h @@ -32,7 +32,6 @@ extern void hoc_neuronhome(void), hoc_Execerror(void); extern void hoc_sscanf(void), hoc_save_session(void), hoc_print_session(void); extern void hoc_Chdir(void), hoc_getcwd(void), hoc_Symbol_units(void), hoc_stdout(void); extern void hoc_name_declared(void), hoc_unix_mac_pc(void), hoc_show_winio(void); -extern void hoc_usemcran4(void), hoc_mcran4(void), hoc_mcran4init(void); extern void hoc_nrn_load_dll(void), hoc_nrnversion(void), hoc_object_pushed(void); extern void hoc_mallinfo(void); extern void hoc_Setcolor(void); diff --git a/src/oc/scoprand.cpp b/src/oc/scoprand.cpp index 7f08ae8814..70651f5608 100644 --- a/src/oc/scoprand.cpp +++ b/src/oc/scoprand.cpp @@ -23,7 +23,8 @@ static char RCSid[] = "random.cpp,v 1.4 1999/01/04 12:46:49 hines Exp"; #endif #include -#include +#include "oc_mcran4.hpp" +#include "mcran4.h" #include "scoplib.h" static uint32_t value = 1; @@ -58,8 +59,7 @@ static uint32_t value = 1; *--------------------------------------------------------------------------- */ double scop_random(void) { - extern int use_mcell_ran4_; - if (use_mcell_ran4_) { + if (use_mcran4()) { /*perhaps 4 times slower but much higher quality*/ return mcell_ran4a(&value); } else {