From 1f6f497eb4e41568c07e9d461c7278c88a66ec26 Mon Sep 17 00:00:00 2001 From: nrnhines Date: Mon, 12 Aug 2024 06:09:05 -0400 Subject: [PATCH 01/68] remove mention of spatial_method(), node_data(), NODE_DATA, METHOD3 (#3037) --- docs/guide/hoc_chapter_11_old_reference.rst | 2 +- docs/hoc/compilationoptions.rst | 21 +--- docs/python/compilationoptions.rst | 21 +--- src/nrnoc/neuron.h | 2 +- src/nrnoc/treeset.cpp | 101 -------------------- src/oc/mk_hocusr_h.py | 4 +- 6 files changed, 6 insertions(+), 145 deletions(-) diff --git a/docs/guide/hoc_chapter_11_old_reference.rst b/docs/guide/hoc_chapter_11_old_reference.rst index c09930d940..aeeb70bbf0 100644 --- a/docs/guide/hoc_chapter_11_old_reference.rst +++ b/docs/guide/hoc_chapter_11_old_reference.rst @@ -338,7 +338,7 @@ Names introduced by nrnoc .. code:: c++ - node_data disconnect batch_run batch_save + disconnect batch_run batch_save pt3dclear pt3dadd n3d x3d y3d z3d diam3d arc3d define_shape p3dconst spine3d setSpineArea getSpineArea area ri initnrn topology fadvance distance diff --git a/docs/hoc/compilationoptions.rst b/docs/hoc/compilationoptions.rst index 321290c63a..e06db2fceb 100644 --- a/docs/hoc/compilationoptions.rst +++ b/docs/hoc/compilationoptions.rst @@ -3,8 +3,7 @@ Rarely Used Compilation Options The following definitions are found in nrnoc/SRC/options.h and add extra functionality which not everyone may need. The extras come at the cost -of larger memory requirements for node and section structures. METHOD3 is too large -and obscure to benefit most users. +of larger memory requirements for node and section structures. .. code-block:: none @@ -27,21 +26,3 @@ and obscure to benefit most users. * of spine. setSpineArea() tells how much * area/spine to add to the segment. */ #endif - - #define METHOD3 1 /* third order spatially correct method */ - /* testing only, not completely implemented */ - /* not working at this time */ - - #if METHOD3 - spatial_method(i) - no arg, returns current method - i=0 The standard NEURON method with zero area nodes at the ends - of sections. - i=1 conventional method with 1/2 area end nodes - i=2 modified second order method - i=3 third order correct spatial method - Note: i=1-3 don't work under all circumstances. They have been - insufficiently tested and the correctness must be established for - each simulation. - #endif - diff --git a/docs/python/compilationoptions.rst b/docs/python/compilationoptions.rst index 73fb3805dc..e06db2fceb 100755 --- a/docs/python/compilationoptions.rst +++ b/docs/python/compilationoptions.rst @@ -3,8 +3,7 @@ Rarely Used Compilation Options The following definitions are found in nrnoc/SRC/options.h and add extra functionality which not everyone may need. The extras come at the cost -of larger memory requirements for node and section structures. METHOD3 is too large -and obscure to benefit most users. +of larger memory requirements for node and section structures. .. code-block:: none @@ -27,21 +26,3 @@ and obscure to benefit most users. * of spine. setSpineArea() tells how much * area/spine to add to the segment. */ #endif - - #define METHOD3 1 /* third order spatially correct method */ - /* testing only, not completely implemented */ - /* not working at this time */ - - #if METHOD3 - spatial_method(i) - no arg, returns current method - i=0 The standard NEURON method with zero area nodes at the ends - of sections. - i=1 conventional method with 1/2 area end nodes - i=2 modified second order method - i=3 third order correct spatial method - Note: i=1-3 don't work under all circumstances. They have been - insufficiently tested and the correctness must be established for - each simulation. - #endif - diff --git a/src/nrnoc/neuron.h b/src/nrnoc/neuron.h index 665ebe11d1..1fac159bb5 100755 --- a/src/nrnoc/neuron.h +++ b/src/nrnoc/neuron.h @@ -1,6 +1,6 @@ #include "options.h" -extern void node_data(), disconnect(); +extern void disconnect(); extern void batch_run(), batch_save(); extern void pt3dadd(), n3d(), x3d(), y3d(), z3d(), arc3d(), diam3d(); extern void pt3dclear(), pt3dinsert(), pt3dremove(), pt3dchange(); diff --git a/src/nrnoc/treeset.cpp b/src/nrnoc/treeset.cpp index ff8ca8283b..6ca37a4d1d 100644 --- a/src/nrnoc/treeset.cpp +++ b/src/nrnoc/treeset.cpp @@ -1782,107 +1782,6 @@ void v_setup_vectors(void) { } -#define NODE_DATA 0 -#if NODE_DATA -static FILE* fnd; - -#undef P -#undef Pn -#undef Pd -#undef Pg - -#define P fprintf(fnd, -#define Pn P "\n") -#define Pd(arg) P "%d\n", arg) -#define Pg(arg) P "%g\n", arg) - -void node_data_scaffolding(void) { - int i; - Pd(n_memb_func); - /* P "Mechanism names (first two are nullptr) beginning with memb_func[2]\n");*/ - for (i = 2; i < n_memb_func; ++i) { - P "%s", memb_func[i].sym->name); - Pn; - } -} - -void node_data_structure(void) { - int i, j; - nrn_thread_error("node_data_structure"); - Pd(v_node_count); - - Pd(nrn_global_ncell); - /* P "Indices of node parents\n");*/ - for (i = 0; i < v_node_count; ++i) { - Pd(v_parent[i]->v_node_index); - } - /* P "node lists for the membrane mechanisms\n");*/ - for (i = 2; i < n_memb_func; ++i) { - /* P "count, node list for mechanism %s\n", memb_func[i].sym->name);*/ - Pd(memb_list[i].nodecount); - for (j = 0; j < memb_list[i].nodecount; ++j) { - Pd(memb_list[i].nodelist[j]->v_node_index); - } - } -} - -void node_data_values(void) { - int i, j, k; - /* P "data for nodes then for all mechanisms in order of the above structure\n"); */ - for (i = 0; i < v_node_count; ++i) { - Pg(NODEV(v_node[i])); - Pg(NODEA(v_node[i])); - Pg(NODEB(v_node[i])); - Pg(NODEAREA(v_node[i])); - } - for (i = 2; i < n_memb_func; ++i) { - Prop* prop; - int cnt; - double* pd; - if (memb_list[i].nodecount) { - assert(!memb_func[i].hoc_mech); - prop = nrn_mechanism(i, memb_list[i].nodelist[0]); - cnt = prop->param_size; - Pd(cnt); - } - for (j = 0; j < memb_list[i].nodecount; ++j) { - pd = memb_list[i]._data[j]; - for (k = 0; k < cnt; ++k) { - Pg(pd[k]); - } - } - } -} - -void node_data(void) { - fnd = fopen(gargstr(1), "w"); - if (!fnd) { - hoc_execerror("node_data: can't open", gargstr(1)); - } - if (tree_changed) { - setup_topology(); - } - if (v_structure_change) { - v_setup_vectors(); - } - if (diam_changed) { - recalc_diam(); - } - node_data_scaffolding(); - node_data_structure(); - node_data_values(); - fclose(fnd); - hoc_retpushx(1.); -} - -#else -void node_data(void) { - Printf("recalc_diam=%d nrn_area_ri=%d\n", recalc_diam_count_, nrn_area_ri_count_); - hoc_retpushx(0.); -} - -#endif - void nrn_matrix_node_free() { NrnThread* nt; FOR_THREADS(nt) { diff --git a/src/oc/mk_hocusr_h.py b/src/oc/mk_hocusr_h.py index 85bed1b1cf..56f60ff688 100644 --- a/src/oc/mk_hocusr_h.py +++ b/src/oc/mk_hocusr_h.py @@ -49,11 +49,11 @@ def process(type, names): # the pgcc 18.4 compiler prepends with a multiline typedef and several # extern void lines that need to be skipped. Our first relevant line -# contains spatial_method or node_data +# contains disconnect skip = 1 for line in text.splitlines(): - if "spatial_method" in line or "node_data" in line: + if "disconnect" in line: skip = 0 names = line.replace(",", " ").replace(";", " ").split() if not skip and len(names) > 2: From cdabc3cfdbb7ab3aca18804fab4641d91f239104 Mon Sep 17 00:00:00 2001 From: Fernando Pereira Date: Tue, 13 Aug 2024 08:28:52 +0100 Subject: [PATCH 02/68] Add dev docs: py-package build+test (+ note for mac) (#3003) * Document `setup.py` options. * Document pitfall specific to Python 3.13 and Macs. --- docs/dev/setuptools/setuptools.md | 56 +++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/docs/dev/setuptools/setuptools.md b/docs/dev/setuptools/setuptools.md index 56cc37f5e2..ae449e4f7e 100644 --- a/docs/dev/setuptools/setuptools.md +++ b/docs/dev/setuptools/setuptools.md @@ -15,20 +15,64 @@ We use [setup.py](../../../setup.py) in two operational modes : 1) **wheel building** - It boils down to + It boils down to setup.py build_ext bdist_wheel - + We configure the HOC extension along with a CMake configure, build all extensios and collect them for the wheel. This is called via [build_wheels.bash](../../../packaging/python/build_wheels.bash). 2) **CMake build** It boils down to - - setup.py build_ext build - We provide the cmake build folder, in this mode we do not run CMake configure, we build all extensions and make sure they are integrated into the CMake build and install. This is called via CMake in [src/nrnpython/CMakeLists.txt](../../../src/nrnpython/CMakeLists.txt) by passing **--cmake-build-dir** (the folder where we configured NEURON with CMake), along with other CMake options. + setup.py build_ext build + + We provide the cmake build folder, in this mode we do not run CMake configure, we build all extensions and make sure they are integrated into the CMake build and install. This is called via CMake in [src/nrnpython/CMakeLists.txt](../../../src/nrnpython/CMakeLists.txt) by passing **--cmake-build-dir** (the folder where we configured NEURON with CMake), along with other CMake options. ## **Activity Diagram** -![](images/setup-py.png) \ No newline at end of file +![](images/setup-py.png) + + +## Creating a Development Python Package + +`setup.py` can be lanched manually as well to create a dev build package, which can be tested +immediately. It supports several arguments to that the build can be tuned: + +``` + --disable-rx3d Disables Rx3d. Implies CMake -DNRN_ENABLE_RX3D=OFF + --disable-iv Disables IV. Implies CMake -DNRN_ENABLE_INTERVIEWS=OFF + --disable-mpi Disables MPI. Implies -DNRN_ENABLE_MPI=OFF and disabling of neuronmusic + --enable-music Enables neuronmusic + --enable-coreneuron Enables experimental CorenNeuron support + --rx3d-opt-level Sets the rx3d optimization level. Default: 0 (-O0) + --cmake-build-dir Declares one wants to use a specic NEURON build (with CMake), instead + of creating one behind the scenes. Only builds extensions and package. +``` + +A quick build for testing a change to a core component could therefore be: +``` +python setup.py build --disable-rx3d --disable-iv --disable-mpi +``` + +--- +**Mac Note** + +Since the introduction of Mac with Apple silicon, with an Official Python distribution, extension are simultaneously built for arm64 and x86_64. Besides not required for a dev build, it may fail +on older SDKs with `Unsupported architecture` errors. + +To skip that you may set the ARCHFLAGS environment var. Set it to "" (empty) for default architecture: `ARCHFLAGS='' python setup.py ...` + +--- + +### Testing + +Once built, the package may be imported and used normally. You might, however, need to set up +PYTHONPATH accordingly for the import to work: + +``` +export PYTHONPATH="/build/lib.macosx-10.9-x86_64-3.9/:$PYTHONPATH" + +# Run Neuron base tests +python -c "import neuron; neuron.test()" +``` From 61dfd7c00b2ec2617f76e7946b6ac0ebd24b0877 Mon Sep 17 00:00:00 2001 From: Koen van Walstijn <38299796+kbvw@users.noreply.github.com> Date: Tue, 13 Aug 2024 11:58:44 +0200 Subject: [PATCH 03/68] Support `cython>=3` and remove `cython<3` pin. (#3028) * Change Cython language setting to C instead of C++ except for MUSIC --- .github/workflows/coverage.yml | 2 +- .github/workflows/neuron-ci.yml | 2 +- CMakeLists.txt | 6 ------ ci/win_build_cmake.sh | 2 +- ci/win_install_deps.cmd | 10 +++++----- docs/conda_environment.yml | 2 +- docs/install/install_instructions.md | 2 +- nrn_requirements.txt | 2 +- packaging/python/build_requirements.txt | 2 +- setup.py | 4 ++-- share/lib/python/neuron/rxd/geometry3d/surfaces.pyx | 4 +--- 11 files changed, 15 insertions(+), 23 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index cde6c2c8a0..96ee062936 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -58,7 +58,7 @@ jobs: run: | python3 -m venv music-venv source music-venv/bin/activate - python3 -m pip install 'mpi4py<4' "cython<3" 'numpy<2' setuptools + python3 -m pip install 'mpi4py<4' "cython" 'numpy<2' setuptools sudo mkdir -p $MUSIC_INSTALL_DIR sudo chown -R $USER $MUSIC_INSTALL_DIR curl -L -o MUSIC.zip https://github.com/INCF/MUSIC/archive/refs/tags/${MUSIC_VERSION}.zip diff --git a/.github/workflows/neuron-ci.yml b/.github/workflows/neuron-ci.yml index 6f3076290f..abd42d2873 100644 --- a/.github/workflows/neuron-ci.yml +++ b/.github/workflows/neuron-ci.yml @@ -207,7 +207,7 @@ jobs: run: | python3 -m venv music-venv source music-venv/bin/activate - python3 -m pip install 'mpi4py<4' "cython<3" 'numpy<2' setuptools + python3 -m pip install 'mpi4py<4' "cython" 'numpy<2' setuptools sudo mkdir -p $MUSIC_INSTALL_DIR sudo chown -R $USER $MUSIC_INSTALL_DIR curl -L -o MUSIC.zip https://github.com/INCF/MUSIC/archive/refs/tags/${MUSIC_VERSION}.zip diff --git a/CMakeLists.txt b/CMakeLists.txt index c5dee70d64..1b74dbc9a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -325,9 +325,6 @@ if(NRN_ENABLE_RX3D) message(SEND_ERROR "NRN_ENABLE_RX3D requires NRN_ENABLE_PYTHON feature.") else() find_package(Cython REQUIRED) - if(CYTHON_VERSION VERSION_GREATER_EQUAL 3) - message(FATAL_ERROR "Cython 3+ is not supported") - endif() endif() endif() if(MINGW) @@ -382,9 +379,6 @@ if(NRN_ENABLE_MUSIC) message(FATAL "MUSIC requires -DNRN_ENABLE_PYTHON=ON") endif() find_package(Cython REQUIRED) - if(CYTHON_VERSION VERSION_GREATER_EQUAL 3) - message(FATAL_ERROR "Cython 3+ is not supported") - endif() find_package(MUSIC REQUIRED) set(NRN_MUSIC 1) endif() diff --git a/ci/win_build_cmake.sh b/ci/win_build_cmake.sh index c3c84ad37e..fcf5fe419c 100755 --- a/ci/win_build_cmake.sh +++ b/ci/win_build_cmake.sh @@ -10,7 +10,7 @@ export MSYSTEM_PREFIX=/mingw64 export PATH=/mingw64/bin:$PATH # have compatible cython3 -python3 -m pip install "cython<3" +python3 -m pip install "cython" # if BUILD_SOURCESDIRECTORY not available, use te root of the repo if [ -z "$BUILD_SOURCESDIRECTORY" ]; then diff --git a/ci/win_install_deps.cmd b/ci/win_install_deps.cmd index c75e977a10..b27cfba3af 100644 --- a/ci/win_install_deps.cmd +++ b/ci/win_install_deps.cmd @@ -23,11 +23,11 @@ pwsh -command "(Get-Content C:\Python310\Lib\distutils\cygwinccompiler.py) -repl pwsh -command "(Get-Content C:\Python311\Lib\distutils\cygwinccompiler.py) -replace 'msvcr100', 'msvcrt' | Out-File C:\Python311\Lib\distutils\cygwinccompiler.py" :: install numpy -C:\Python38\python.exe -m pip install numpy==1.17.5 "cython < 3" || goto :error -C:\Python39\python.exe -m pip install numpy==1.19.3 "cython < 3" || goto :error -C:\Python310\python.exe -m pip install numpy==1.21.3 "cython < 3" || goto :error -C:\Python311\python.exe -m pip install numpy==1.23.5 "cython < 3" || goto :error -C:\Python312\python.exe -m pip install numpy==1.26.3 "cython < 3" || goto :error +C:\Python38\python.exe -m pip install numpy==1.17.5 "cython" || goto :error +C:\Python39\python.exe -m pip install numpy==1.19.3 "cython" || goto :error +C:\Python310\python.exe -m pip install numpy==1.21.3 "cython" || goto :error +C:\Python311\python.exe -m pip install numpy==1.23.5 "cython" || goto :error +C:\Python312\python.exe -m pip install numpy==1.26.3 "cython" || goto :error :: setuptools 70.2 leads to an error C:\Python312\python.exe -m pip install setuptools==70.1.1 || goto :error diff --git a/docs/conda_environment.yml b/docs/conda_environment.yml index d13bdc8775..6abc60862b 100644 --- a/docs/conda_environment.yml +++ b/docs/conda_environment.yml @@ -9,7 +9,7 @@ dependencies: - cmake - xorg-libxcomposite - ffmpeg - - cython<3 + - cython - pandoc - mpich - pip diff --git a/docs/install/install_instructions.md b/docs/install/install_instructions.md index 209509b371..af7a86583f 100644 --- a/docs/install/install_instructions.md +++ b/docs/install/install_instructions.md @@ -207,7 +207,7 @@ In order to build NEURON from source, the following packages must be available: The following packages are optional (see build options): - Python >=3.8 (for Python interface) -- Cython < 3 (for RXD) +- Cython (for RXD) - MPI (for parallel) - X11 (Linux) or XQuartz (MacOS) (for GUI) diff --git a/nrn_requirements.txt b/nrn_requirements.txt index d78453146a..c28bc995bb 100644 --- a/nrn_requirements.txt +++ b/nrn_requirements.txt @@ -6,7 +6,7 @@ matplotlib # bokeh 3 seems to break docs notebooks bokeh<3 ipython -cython<3 +cython packaging pytest<=8.1.1 # potential bug from 8.2.0 due to parallelism? pytest-cov diff --git a/packaging/python/build_requirements.txt b/packaging/python/build_requirements.txt index 5fe1763173..29d2c1b080 100644 --- a/packaging/python/build_requirements.txt +++ b/packaging/python/build_requirements.txt @@ -1,4 +1,4 @@ -cython<3 +cython packaging numpy==1.17.5;python_version=='3.8' numpy==1.19.3;python_version=='3.9' and platform_machine!='arm64' diff --git a/setup.py b/setup.py index 3d944d1332..d27d995c11 100644 --- a/setup.py +++ b/setup.py @@ -354,7 +354,7 @@ def setup_package(): NRN_COLLECT_DIRS = ["bin", "lib", "include", "share"] docs_require = [] # sphinx, themes, etc - maybe_rxd_reqs = ["numpy<2", "Cython<3"] if Components.RX3D else [] + maybe_rxd_reqs = ["numpy<2", "Cython"] if Components.RX3D else [] maybe_docs = docs_require if "docs" in sys.argv else [] maybe_test_runner = ["pytest-runner"] if "test" in sys.argv else [] @@ -379,7 +379,6 @@ def setup_package(): list, library_dirs=[os.path.join(cmake_build_dir, "lib")], libraries=ext_common_libraries, - language="c++", ) logging.info("Extension common compile flags %s" % str(extension_common_params)) @@ -436,6 +435,7 @@ def setup_package(): "neuronmusic", ["src/neuronmusic/neuronmusic.pyx"], include_dirs=["src/nrnpython", "src/nrnmusic"], + language="c++", **extension_common_params, ) ] diff --git a/share/lib/python/neuron/rxd/geometry3d/surfaces.pyx b/share/lib/python/neuron/rxd/geometry3d/surfaces.pyx index 141adf7899..bf3aac2eb1 100644 --- a/share/lib/python/neuron/rxd/geometry3d/surfaces.pyx +++ b/share/lib/python/neuron/rxd/geometry3d/surfaces.pyx @@ -1,13 +1,11 @@ import os import numpy -import graphicsPrimitives -import neuron -import numpy cimport numpy import itertools import bisect cimport cython +from neuron.rxd.geometry3d import graphicsPrimitives """ The surfaces module From 09d04901bb0b4101ebea2f64ffea7616abf735ad Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Wed, 14 Aug 2024 11:01:09 +0200 Subject: [PATCH 04/68] Use nanobind for python BBS implementation (#3034) --- src/nrnpython/nrnpy_p2h.cpp | 61 +++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/src/nrnpython/nrnpy_p2h.cpp b/src/nrnpython/nrnpy_p2h.cpp index 0d765bb6a5..fddf59ebbe 100644 --- a/src/nrnpython/nrnpy_p2h.cpp +++ b/src/nrnpython/nrnpy_p2h.cpp @@ -1,6 +1,7 @@ #include <../../nrnconf.h> #include + #include #include #include @@ -11,6 +12,10 @@ #include "oc_ansi.h" #include "parse.hpp" + +#include +namespace nb = nanobind; + static void nrnpy_decref_defer(PyObject*); static char* nrnpyerr_str(); static PyObject* nrnpy_pyCallObject(PyObject*, PyObject*); @@ -607,32 +612,31 @@ static int guigetstr(Object* ho, char** cpp) { return 1; } -static PyObject* loads; -static PyObject* dumps; +static nb::callable loads; +static nb::callable dumps; static void setpickle() { if (dumps) { return; } - PyObject* pickle = PyImport_ImportModule("pickle"); - if (pickle) { - Py_INCREF(pickle); - dumps = PyObject_GetAttrString(pickle, "dumps"); - loads = PyObject_GetAttrString(pickle, "loads"); - if (dumps) { - Py_INCREF(dumps); - Py_INCREF(loads); - } - } + nb::module_ pickle = nb::module_::import_("pickle"); + dumps = pickle.attr("dumps"); + loads = pickle.attr("loads"); if (!dumps || !loads) { hoc_execerror("Neither Python cPickle nor pickle are available", 0); } + // We intentionally leak these, because if we don't + // we observe SEGFAULTS during application shutdown. + // Likely because "~nb::callable" runs after the Python + // library cleaned up. + dumps.inc_ref(); + loads.inc_ref(); } // note that *size includes the null terminating character if it exists static std::vector pickle(PyObject* p) { PyObject* arg = PyTuple_Pack(1, p); - PyObject* r = nrnpy_pyCallObject(dumps, arg); + PyObject* r = nrnpy_pyCallObject(dumps.ptr(), arg); Py_XDECREF(arg); if (!r && PyErr_Occurred()) { PyErr_Print(); @@ -656,25 +660,21 @@ static std::vector po2pickle(Object* ho) { } } -static PyObject* unpickle(const char* s, std::size_t len) { - PyObject* ps = PyBytes_FromStringAndSize(s, len); - PyObject* arg = PyTuple_Pack(1, ps); - PyObject* po = nrnpy_pyCallObject(loads, arg); - assert(po); - Py_XDECREF(arg); - Py_XDECREF(ps); - return po; +static nb::object unpickle(const char* s, std::size_t len) { + nb::bytes string(s, len); + nb::list args; + args.append(string); + return loads(*args); } -static PyObject* unpickle(const std::vector& s) { +static nb::object unpickle(const std::vector& s) { return unpickle(s.data(), s.size()); } static Object* pickle2po(const std::vector& s) { setpickle(); - PyObject* po = unpickle(s); - Object* ho = nrnpy_pyobject_in_obj(po); - Py_XDECREF(po); + nb::object po = unpickle(s); + Object* ho = nrnpy_pyobject_in_obj(po.ptr()); return ho; } @@ -750,7 +750,7 @@ std::vector call_picklef(const std::vector& fname, int narg) { setpickle(); PyObject* ps = PyBytes_FromStringAndSize(fname.data(), fname.size()); args = PyTuple_Pack(1, ps); - callable = nrnpy_pyCallObject(loads, args); + callable = nrnpy_pyCallObject(loads.ptr(), args); assert(callable); Py_XDECREF(args); Py_XDECREF(ps); @@ -801,7 +801,8 @@ static PyObject* char2pylist(char* buf, int np, int* cnt, int* displ) { Py_INCREF(Py_None); // 'Fatal Python error: deallocating None' eventually PyList_SetItem(plist, i, Py_None); } else { - PyObject* p = unpickle(buf + displ[i], cnt[i]); + nb::object po = unpickle(buf + displ[i], cnt[i]); + PyObject* p = po.release().ptr(); PyList_SetItem(plist, i, p); } } @@ -874,7 +875,8 @@ static PyObject* py_broadcast(PyObject* psrc, int root) { nrnmpi_char_broadcast(buf.data(), cnt, root); PyObject* pdest = psrc; if (root != nrnmpi_myid) { - pdest = unpickle(buf); + nb::object po = unpickle(buf); + pdest = po.release().ptr(); } else { Py_INCREF(pdest); } @@ -1082,7 +1084,8 @@ static Object* py_alltoall_type(int size, int type) { delete[] sdispl; if (rcnt[0]) { - pdest = unpickle(r); + nb::object po = unpickle(r); + pdest = po.release().ptr(); } else { pdest = Py_None; Py_INCREF(pdest); From e72152896028cc88402ee335da96e8df95597d4f Mon Sep 17 00:00:00 2001 From: MikeG Date: Thu, 15 Aug 2024 11:57:06 +0200 Subject: [PATCH 05/68] Cleanup `PyMemberDef` (#3031) --- src/nrnpython/nrnpy_nrn.cpp | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/src/nrnpython/nrnpy_nrn.cpp b/src/nrnpython/nrnpy_nrn.cpp index 17ff995ffe..5edf14cec7 100644 --- a/src/nrnpython/nrnpy_nrn.cpp +++ b/src/nrnpython/nrnpy_nrn.cpp @@ -699,7 +699,7 @@ static PyObject* NPySecObj_n3d_safe(NPySecObj* self) { static PyObject* NPySecObj_pt3dremove(NPySecObj* self, PyObject* args) { Section* sec = self->sec_; CHECK_SEC_INVALID(sec); - int i0, n; + int i0; if (!PyArg_ParseTuple(args, "i", &i0)) { return NULL; } @@ -1232,8 +1232,6 @@ static long pyseg_hash_safe(PyObject* self) { } static PyObject* pyseg_richcmp(NPySegObj* self, PyObject* other, int op) { - PyObject* pysec; - bool result = false; NPySegObj* seg = (NPySegObj*) self; void* self_ptr = (void*) node_exact(seg->pysec_->sec_, seg->x_); void* other_ptr = (void*) other; @@ -1250,8 +1248,6 @@ static PyObject* pyseg_richcmp_safe(NPySegObj* self, PyObject* other, int op) { static PyObject* pysec_richcmp(NPySecObj* self, PyObject* other, int op) { - PyObject* pysec; - bool result = false; void* self_ptr = (void*) (self->sec_); void* other_ptr = (void*) other; if (PyObject_TypeCheck(other, psection_type)) { @@ -1321,7 +1317,6 @@ static PyObject* NPyMechFunc_name_safe(NPyMechFunc* self) { static PyObject* NPyMechFunc_call(NPyMechFunc* self, PyObject* args) { CHECK_PROP_INVALID(self->pymech_->prop_id_); PyObject* result = NULL; - auto pyseg = self->pymech_->pyseg_; auto& f = self->f_->func; // patterning after fcall @@ -2339,7 +2334,6 @@ static int segment_setattro(NPySegObj* self, PyObject* pyname, PyObject* value) } // printf("segment_setattro %s\n", n); if (strcmp(n, "x") == 0) { - int nseg; double x; if (PyArg_Parse(value, "d", &x) == 1 && x > 0. && x <= 1.) { if (x < 1e-9) { @@ -2924,23 +2918,9 @@ static PyMethodDef NPySegObj_methods[] = { {"volume", (PyCFunction) seg_volume_safe, METH_NOARGS, "Segment volume (um3)"}, {NULL}}; -// I'm guessing Python should change their typedef to get rid of the -// four "deprecated conversion from string constant to 'char*'" warnings. -// Could avoid by casting each to (char*) but probably better to keep the -// warnings. For now we get rid of the warnings by copying the string to -// char array. -static char* cpstr(const char* s) { - char* s2 = new char[strlen(s) + 1]; - strcpy(s2, s); - return s2; -} static PyMemberDef NPySegObj_members[] = { - {cpstr("x"), - T_DOUBLE, - offsetof(NPySegObj, x_), - 0, - cpstr("location in the section (segment containing x)")}, - {cpstr("sec"), T_OBJECT_EX, offsetof(NPySegObj, pysec_), 0, cpstr("Section")}, + {"x", T_DOUBLE, offsetof(NPySegObj, x_), 0, "location in the section (segment containing x)"}, + {"sec", T_OBJECT_EX, offsetof(NPySegObj, pysec_), 0, "Section"}, {NULL}}; static PyMethodDef NPyMechObj_methods[] = { @@ -3014,7 +2994,6 @@ static void rangevars_add(Symbol* sym) { } PyObject* nrnpy_nrn(void) { - int i; PyObject* m; int err = 0; From c918f6b9ff9be32828e882ed51106d8449e7cb6c Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 15 Aug 2024 14:07:01 +0200 Subject: [PATCH 06/68] nanobind: use loads and dumps as callable (#3043) --- src/nrnpython/nrnpy_p2h.cpp | 47 ++++++++++--------------------------- 1 file changed, 12 insertions(+), 35 deletions(-) diff --git a/src/nrnpython/nrnpy_p2h.cpp b/src/nrnpython/nrnpy_p2h.cpp index fddf59ebbe..0164c2b667 100644 --- a/src/nrnpython/nrnpy_p2h.cpp +++ b/src/nrnpython/nrnpy_p2h.cpp @@ -635,19 +635,12 @@ static void setpickle() { // note that *size includes the null terminating character if it exists static std::vector pickle(PyObject* p) { - PyObject* arg = PyTuple_Pack(1, p); - PyObject* r = nrnpy_pyCallObject(dumps.ptr(), arg); - Py_XDECREF(arg); + auto r = nb::borrow(dumps(nb::borrow(p))); if (!r && PyErr_Occurred()) { PyErr_Print(); } assert(r); - assert(PyBytes_Check(r)); - std::size_t size = PyBytes_Size(r); - char* buf = PyBytes_AsString(r); - std::vector ret(buf, buf + size); - Py_XDECREF(r); - return ret; + return std::vector(r.c_str(), r.c_str() + r.size()); } static std::vector po2pickle(Object* ho) { @@ -661,10 +654,7 @@ static std::vector po2pickle(Object* ho) { } static nb::object unpickle(const char* s, std::size_t len) { - nb::bytes string(s, len); - nb::list args; - args.append(string); - return loads(*args); + return loads(nb::bytes(s, len)); } static nb::object unpickle(const std::vector& s) { @@ -743,33 +733,22 @@ std::vector call_picklef(const std::vector& fname, int narg) { // fname is a pickled callable, narg is the number of args on the // hoc stack with types double, char*, hoc Vector, and PythonObject // callable return must be pickleable. - PyObject* args = 0; - PyObject* result = 0; - PyObject* callable; - setpickle(); - PyObject* ps = PyBytes_FromStringAndSize(fname.data(), fname.size()); - args = PyTuple_Pack(1, ps); - callable = nrnpy_pyCallObject(loads.ptr(), args); + nb::bytes ps(fname.data(), fname.size()); + + auto callable = nb::borrow(loads(ps)); assert(callable); - Py_XDECREF(args); - Py_XDECREF(ps); - args = PyTuple_New(narg); + nb::list args{}; for (int i = 0; i < narg; ++i) { - PyObject* arg = nrnpy_hoc_pop("call_picklef"); - if (PyTuple_SetItem(args, narg - 1 - i, arg)) { - assert(0); - } - // Py_XDECREF(arg); + nb::object arg = nb::steal(nrnpy_hoc_pop("call_picklef")); + args.append(arg); } - result = nrnpy_pyCallObject(callable, args); - Py_DECREF(callable); - Py_DECREF(args); + nb::object result = callable(*args); if (!result) { char* mes = nrnpyerr_str(); if (mes) { - Fprintf(stderr, "%s\n", mes); + std::cerr << mes << std::endl; free(mes); hoc_execerror("PyObject method call failed:", NULL); } @@ -777,9 +756,7 @@ std::vector call_picklef(const std::vector& fname, int narg) { PyErr_Print(); } } - auto rs = pickle(result); - Py_XDECREF(result); - return rs; + return pickle(result.ptr()); } #include "nrnmpi.h" From 48440295517b7989f876c54529d46db9d89978f8 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Mon, 26 Aug 2024 11:37:27 +0200 Subject: [PATCH 07/68] Improve wheel-building experience on multi-arch MacOS (#3038) The build_static_readline_osx.bash script is a bit inflexible and cumbersome to use if trying to perform NEURON builds on both arm64 and x86_64; for instance, it installs everything to /opt/nrnwheel, which means that it doesn't really differentiate between arches, so if one wants to build a wheel, one has to remember to (re)install the readline library for the correct arch, otherwise we end up with many warnings about incompatible archs, and eventually the linker complaining about missing symbols. This PR basically improves this by moving the install location to /opt/nrnwheel/[ARCH], where [ARCH] is detected the usual way. This means we can use build_static_readline_osx.bash on either arch, and it won't clobber any existing install of the other arch. One can also specify a custom install location by passing a single argument to build_static_readline_osx.bash. Note that Linux builds should not be affected by any of these changes. --- azure-pipelines.yml | 4 +-- .../python/build_static_readline_osx.bash | 30 +++++++++---------- packaging/python/build_wheels.bash | 2 +- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b7dd958f4a..238988a536 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -148,8 +148,8 @@ stages: export PATH=/usr/local/opt/flex/bin:/usr/local/opt/bison/bin:$PATH export SDKROOT=$(xcrun --sdk macosx --show-sdk-path) export NRN_BUILD_FOR_UPLOAD=1 - sudo mkdir /opt/nrnwheel - sudo tar -zxf $(readlineSF.secureFilePath) --directory /opt/nrnwheel/ + sudo mkdir -p /opt/nrnwheel/$(uname -m) + sudo tar -zxf $(readlineSF.secureFilePath) --directory /opt/nrnwheel/$(uname -m) packaging/python/build_wheels.bash osx $(python.version) coreneuron displayName: 'Build MacOS Wheel' diff --git a/packaging/python/build_static_readline_osx.bash b/packaging/python/build_static_readline_osx.bash index efe0bf09d5..26919f8958 100644 --- a/packaging/python/build_static_readline_osx.bash +++ b/packaging/python/build_static_readline_osx.bash @@ -1,57 +1,55 @@ #!/usr/bin/env bash -set -xe +set -eux # A script to build a static readline library for osx # # PREREQUESITES: # - curl -# - wget # - C/C++ compiler -# - /opt/nrnwheel folder created with access rights (this specific path is kept for consistency wrt `build_wheels.bash`) +# - /opt/nrnwheel/[ARCH] folder created with access rights (this specific path is kept for consistency wrt `build_wheels.bash`) -set -e - -if [[ `uname -s` != 'Darwin' ]]; then +if [[ "$(uname -s)" != 'Darwin' ]]; then echo "Error: this script is for macOS only. readline is already built statically in the linux Docker images" exit 1 fi -NRNWHEEL_DIR=/opt/nrnwheel +ARCH="$(uname -m)" + +NRNWHEEL_DIR="${1:-/opt/nrnwheel/${ARCH}}" if [[ ! -d "$NRNWHEEL_DIR" || ! -x "$NRNWHEEL_DIR" ]]; then - echo "Error: /opt/nrnwheel must exist and be accessible, i.e: sudo mkdir -p /opt/nrnwheel && sudo chown -R $USER /opt/nrnwheel" + echo "Error: ${NRNWHEEL_DIR} must exist and be accessible, i.e: sudo mkdir -p ${NRNWHEEL_DIR} && sudo chown -R ${USER} ${NRNWHEEL_DIR}" exit 1 fi # Set MACOSX_DEPLOYMENT_TARGET based on wheel arch. # For upcoming `universal2` wheels we will consider leveling everything to 11.0. -if [[ `uname -m` == 'arm64' ]]; then +if [[ "${ARCH}" == 'arm64' ]]; then export MACOSX_DEPLOYMENT_TARGET=11.0 # for arm64 we need 11.0 else export MACOSX_DEPLOYMENT_TARGET=10.9 # for x86_64 fi -(wget http://ftpmirror.gnu.org/ncurses/ncurses-6.4.tar.gz \ +(curl -L -o ncurses-6.4.tar.gz http://ftpmirror.gnu.org/ncurses/ncurses-6.4.tar.gz \ && tar -xvzf ncurses-6.4.tar.gz \ && cd ncurses-6.4 \ - && ./configure --prefix=/opt/nrnwheel/ncurses --without-shared CFLAGS="-fPIC" \ + && ./configure --prefix="${NRNWHEEL_DIR}/ncurses" --without-shared CFLAGS="-fPIC" \ && make -j install) (curl -L -o readline-7.0.tar.gz https://ftp.gnu.org/gnu/readline/readline-7.0.tar.gz \ && tar -xvzf readline-7.0.tar.gz \ && cd readline-7.0 \ - && ./configure --prefix=/opt/nrnwheel/readline --disable-shared CFLAGS="-fPIC" \ + && ./configure --prefix="${NRNWHEEL_DIR}/readline" --disable-shared CFLAGS="-fPIC" \ && make -j install) -(cd /opt/nrnwheel/readline/lib \ +(cd "${NRNWHEEL_DIR}/readline/lib" \ && ar -x libreadline.a \ && ar -x ../../ncurses/lib/libncurses.a \ && ar cq libreadline.a *.o \ && rm *.o) -RDL_MINOS=`otool -l /opt/nrnwheel/readline/lib/libreadline.a | grep -e "minos \|version " | uniq | awk '{print $2}'` +RDL_MINOS="$(otool -l "${NRNWHEEL_DIR}/readline/lib/libreadline.a" | grep -e "minos \|version " | uniq | awk '{print $2}')" if [ "$RDL_MINOS" != "$MACOSX_DEPLOYMENT_TARGET" ]; then - echo "Error: /opt/nrnwheel/readline/lib/libreadline.a doesn't match MACOSX_DEPLOYMENT_TARGET ($MACOSX_DEPLOYMENT_TARGET)" + echo "Error: ${NRNWHEEL_DIR}/readline/lib/libreadline.a doesn't match MACOSX_DEPLOYMENT_TARGET ($MACOSX_DEPLOYMENT_TARGET)" exit 1 fi - echo "Done." diff --git a/packaging/python/build_wheels.bash b/packaging/python/build_wheels.bash index 4da4f01f06..9f4eb34ba0 100755 --- a/packaging/python/build_wheels.bash +++ b/packaging/python/build_wheels.bash @@ -160,7 +160,7 @@ build_wheel_osx() { fi fi - python setup.py build_ext --cmake-prefix="/opt/nrnwheel/ncurses;/opt/nrnwheel/readline;/usr/x11" --cmake-defs="$CMAKE_DEFS" $setup_args bdist_wheel + python setup.py build_ext --cmake-prefix="/opt/nrnwheel/$(uname -m)/ncurses;/opt/nrnwheel/$(uname -m)/readline;/usr/x11" --cmake-defs="$CMAKE_DEFS" $setup_args bdist_wheel echo " - Calling delocate-listdeps" delocate-listdeps dist/*.whl From 45a7e6cf5eacf7190f21c070899da75f2db567b5 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Tue, 27 Aug 2024 15:04:04 +0200 Subject: [PATCH 08/68] Remove `ERRCHK` macro (#3056) --- src/oc/fileio.cpp | 12 +++++++----- src/oc/hocdec.h | 2 -- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/oc/fileio.cpp b/src/oc/fileio.cpp index 455d0220a1..8b59284e79 100644 --- a/src/oc/fileio.cpp +++ b/src/oc/fileio.cpp @@ -91,14 +91,16 @@ void wopen(void) /* open file for writing */ else fname = ""; d = 1.; - if (fout != stdout) - ERRCHK(IGNORE(fclose(fout));) + if (fout != stdout) { + IGNORE(fclose(fout)); + } fout = stdout; - if (fname[0] != 0) - ERRCHK(if ((fout = fopen(expand_env_var(fname), "w")) == (FILE*) 0) { + if (fname[0] != 0) { + if ((fout = fopen(expand_env_var(fname), "w")) == nullptr) { d = 0.; fout = stdout; - }) + } + } errno = 0; ret(); pushx(d); diff --git a/src/oc/hocdec.h b/src/oc/hocdec.h index ab4d553bed..a8f5b31826 100644 --- a/src/oc/hocdec.h +++ b/src/oc/hocdec.h @@ -276,8 +276,6 @@ int ilint; #endif using neuron::Sprintf; -#define ERRCHK(c1) c1 - // No longer used because of clang format difficulty // #define IFGUI if (hoc_usegui) { // #define ENDGUI } From 94e41b638652adee0dcbf4506540db8152ca3525 Mon Sep 17 00:00:00 2001 From: Matthias Wolf Date: Thu, 29 Aug 2024 10:24:18 +0200 Subject: [PATCH 09/68] Make OpenMP handling more canonical. (#3050) Future depend on the appropriate OpenMP target, and add the compiler flags separately (so that we can extract them and add them into the mechanism generating Makefile). ADDITIONAL_THREADSAFE_FLAGS has no other reference - a web search shows no usage, either. --- cmake/coreneuron/MakefileBuildOptions.cmake | 8 +++++++- packaging/python/build_wheels.bash | 12 ++++++------ setup.py | 1 - src/coreneuron/CMakeLists.txt | 16 ++++++++++------ 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/cmake/coreneuron/MakefileBuildOptions.cmake b/cmake/coreneuron/MakefileBuildOptions.cmake index 1ab2de8e92..5f7119dddf 100644 --- a/cmake/coreneuron/MakefileBuildOptions.cmake +++ b/cmake/coreneuron/MakefileBuildOptions.cmake @@ -73,13 +73,19 @@ function(coreneuron_process_target target) if(target_imported) # In this case we can extract the full path to the library get_target_property(target_location ${target} LOCATION) - coreneuron_process_library_path(${target_location}) + if(target_location) + coreneuron_process_library_path(${target_location}) + endif() else() # This is probably another of our libraries, like -lcoreneuron-cuda. We might need to add -L # and an RPATH later. set_property(GLOBAL APPEND_STRING PROPERTY CORENRN_LIB_LINK_DEP_FLAGS " -l${target}") endif() endif() + get_target_property(target_flags ${target} INTERFACE_COMPILE_OPTIONS) + if(target_flags) + set_property(GLOBAL APPEND_STRING PROPERTY CORENRN_EXTRA_COMPILE_FLAGS " ${target_flags}") + endif() get_target_property(target_libraries ${target} LINK_LIBRARIES) if(target_libraries) foreach(child_target ${target_libraries}) diff --git a/packaging/python/build_wheels.bash b/packaging/python/build_wheels.bash index 9f4eb34ba0..eeebf32f21 100755 --- a/packaging/python/build_wheels.bash +++ b/packaging/python/build_wheels.bash @@ -71,7 +71,7 @@ build_wheel_linux() { if [ "$2" == "coreneuron" ]; then setup_args="--enable-coreneuron" clone_nmodl_and_add_requirements - CMAKE_DEFS="${CMAKE_DEFS},LINK_AGAINST_PYTHON=OFF" + CMAKE_DEFS="${CMAKE_DEFS},LINK_AGAINST_PYTHON=OFF,CORENRN_ENABLE_OPENMP=ON" fi cat my_requirements.txt @@ -118,17 +118,17 @@ build_wheel_osx() { echo " - Installing build requirements" cp packaging/python/build_requirements.txt my_requirements.txt + CMAKE_DEFS="NRN_MPI_DYNAMIC=$3" + if [ "$USE_STATIC_READLINE" == "1" ]; then + CMAKE_DEFS="$CMAKE_DEFS,NRN_BINARY_DIST_BUILD=ON,NRN_WHEEL_STATIC_READLINE=ON" + fi + if [ "$2" == "coreneuron" ]; then setup_args="--enable-coreneuron" clone_nmodl_and_add_requirements CMAKE_DEFS="${CMAKE_DEFS},LINK_AGAINST_PYTHON=OFF" fi - CMAKE_DEFS="NRN_MPI_DYNAMIC=$3" - if [ "$USE_STATIC_READLINE" == "1" ]; then - CMAKE_DEFS="$CMAKE_DEFS,NRN_BINARY_DIST_BUILD=ON,NRN_WHEEL_STATIC_READLINE=ON" - fi - cat my_requirements.txt pip install -U delocate -r my_requirements.txt pip check diff --git a/setup.py b/setup.py index d27d995c11..bca41a0c2e 100644 --- a/setup.py +++ b/setup.py @@ -406,7 +406,6 @@ def setup_package(): ] + ( [ - "-DCORENRN_ENABLE_OPENMP=ON", # TODO: manylinux portability questions "-DNMODL_ENABLE_PYTHON_BINDINGS=ON", ] if Components.CORENRN diff --git a/src/coreneuron/CMakeLists.txt b/src/coreneuron/CMakeLists.txt index cf4fdf4903..1cf452d23c 100644 --- a/src/coreneuron/CMakeLists.txt +++ b/src/coreneuron/CMakeLists.txt @@ -29,7 +29,7 @@ include(${CODING_CONV_CMAKE}/build-time-copy.cmake) # ============================================================================= # Build options # ============================================================================= -option(CORENRN_ENABLE_OPENMP "Build the CORE NEURON with OpenMP implementation" ON) +option(CORENRN_ENABLE_OPENMP "Build the CORE NEURON with OpenMP implementation" OFF) option(CORENRN_ENABLE_OPENMP_OFFLOAD "Prefer OpenMP target offload to OpenACC" ON) option(CORENRN_ENABLE_TIMEOUT "Enable nrn_timeout implementation" ON) option(CORENRN_ENABLE_REPORTING "Enable use of libsonata for soma reports" OFF) @@ -197,11 +197,7 @@ if(NRN_ENABLE_MPI_DYNAMIC) endif() if(CORENRN_ENABLE_OPENMP) - find_package(OpenMP QUIET) - if(OPENMP_FOUND) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS} ${ADDITIONAL_THREADSAFE_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS} ${ADDITIONAL_THREADSAFE_FLAGS}") - endif() + find_package(OpenMP REQUIRED) endif() list(APPEND CORENRN_COMPILE_DEFS LAYOUT=0) @@ -444,6 +440,14 @@ endif() # https://forums.developer.nvidia.com/t/cannot-dynamically-load-a-shared-library-containing-both-openacc-and-cuda-code/210972 add_library(coreneuron-core STATIC ${CORENEURON_CODE_FILES} ${CORENRN_MPI_OBJ}) add_dependencies(coreneuron-core coreneuron-copy-nrnivmodl-core-dependencies) +if(CORENRN_ENABLE_OPENMP) + # target_link_libraries(coreneuron-core PUBLIC OpenMP::OpenMP_CXX) + target_compile_options(coreneuron-core PUBLIC ${OpenMP_CXX_FLAGS}) + target_link_libraries(coreneuron-core PUBLIC ${OpenMP_CXX_LIB_NAMES}) + # The first line uses a generator expression to arrive at -fopenmp (or equivalent) - this will not + # work with our Makefile generation. Thus specify the flag manually. Enable the first line and + # remove the last two lines below once we get rid of the mechanism building Makefile. +endif() if(CORENRN_ENABLE_GPU) set(coreneuron_cuda_target coreneuron-cuda) add_library(coreneuron-cuda ${COMPILE_LIBRARY_TYPE} ${CORENEURON_CUDA_FILES}) From 29960069f09bc7288137ed2c315812a875268320 Mon Sep 17 00:00:00 2001 From: Koen van Walstijn <38299796+kbvw@users.noreply.github.com> Date: Thu, 29 Aug 2024 10:38:50 +0200 Subject: [PATCH 10/68] Support `numpy>=2` and remove `numpy<2` pin (#3040) * Build wheels with latest numpy and test them with oldest supported numpy * Update oldest supported Python and Numpy versions * Pin `numpy<2` for documentation only The documentation requires an old version of bokeh which isn't compatible with `numpy>=2`. * Cast to `c_long` in RxD on Python side before passing to C++ With Numpy2 there was an inconsistency in the integer types, i.e. the C++ assumed a smaller type than the Python side, on Windows only. Causing SEGFAULT. This fixes the issue by using consistent integer types. --- .github/workflows/coverage.yml | 2 +- .github/workflows/neuron-ci.yml | 2 +- ci/win_build_cmake.sh | 2 +- ci/win_install_deps.cmd | 10 ++++----- ci/win_test_installer.cmd | 19 ++++++++++++++-- docs/install/install_instructions.md | 2 +- nrn_requirements.txt | 2 +- packaging/python/build_requirements.txt | 7 +----- .../python/oldest_numpy_requirements.txt | 5 +++++ packaging/python/test_requirements.txt | 2 ++ packaging/python/test_wheels.sh | 22 ++++++++++++++----- setup.py | 4 ++-- share/lib/python/neuron/rxd/rxd.py | 10 ++++----- share/lib/python/neuron/rxd/species.py | 12 +++++----- test/rxd/conftest.py | 3 ++- 15 files changed, 66 insertions(+), 38 deletions(-) create mode 100644 packaging/python/oldest_numpy_requirements.txt create mode 100644 packaging/python/test_requirements.txt diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 96ee062936..ce0bb21bae 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -58,7 +58,7 @@ jobs: run: | python3 -m venv music-venv source music-venv/bin/activate - python3 -m pip install 'mpi4py<4' "cython" 'numpy<2' setuptools + python3 -m pip install 'mpi4py<4' cython numpy setuptools sudo mkdir -p $MUSIC_INSTALL_DIR sudo chown -R $USER $MUSIC_INSTALL_DIR curl -L -o MUSIC.zip https://github.com/INCF/MUSIC/archive/refs/tags/${MUSIC_VERSION}.zip diff --git a/.github/workflows/neuron-ci.yml b/.github/workflows/neuron-ci.yml index abd42d2873..e3ca977eb4 100644 --- a/.github/workflows/neuron-ci.yml +++ b/.github/workflows/neuron-ci.yml @@ -207,7 +207,7 @@ jobs: run: | python3 -m venv music-venv source music-venv/bin/activate - python3 -m pip install 'mpi4py<4' "cython" 'numpy<2' setuptools + python3 -m pip install 'mpi4py<4' cython numpy setuptools sudo mkdir -p $MUSIC_INSTALL_DIR sudo chown -R $USER $MUSIC_INSTALL_DIR curl -L -o MUSIC.zip https://github.com/INCF/MUSIC/archive/refs/tags/${MUSIC_VERSION}.zip diff --git a/ci/win_build_cmake.sh b/ci/win_build_cmake.sh index fcf5fe419c..ca610acea3 100755 --- a/ci/win_build_cmake.sh +++ b/ci/win_build_cmake.sh @@ -30,7 +30,7 @@ cd $BUILD_SOURCESDIRECTORY/build -DNRN_ENABLE_RX3D=ON \ -DNRN_RX3D_OPT_LEVEL=2 \ -DNRN_BINARY_DIST_BUILD=ON \ - -DPYTHON_EXECUTABLE=/c/Python38/python.exe \ + -DPYTHON_EXECUTABLE=/c/Python39/python.exe \ -DNRN_ENABLE_PYTHON_DYNAMIC=ON \ -DNRN_PYTHON_DYNAMIC='c:/Python38/python.exe;c:/Python39/python.exe;c:/Python310/python.exe;c:/Python311/python.exe;c:/Python312/python.exe' \ -DCMAKE_INSTALL_PREFIX='/c/nrn-install' \ diff --git a/ci/win_install_deps.cmd b/ci/win_install_deps.cmd index b27cfba3af..b30c41c733 100644 --- a/ci/win_install_deps.cmd +++ b/ci/win_install_deps.cmd @@ -23,11 +23,11 @@ pwsh -command "(Get-Content C:\Python310\Lib\distutils\cygwinccompiler.py) -repl pwsh -command "(Get-Content C:\Python311\Lib\distutils\cygwinccompiler.py) -replace 'msvcr100', 'msvcrt' | Out-File C:\Python311\Lib\distutils\cygwinccompiler.py" :: install numpy -C:\Python38\python.exe -m pip install numpy==1.17.5 "cython" || goto :error -C:\Python39\python.exe -m pip install numpy==1.19.3 "cython" || goto :error -C:\Python310\python.exe -m pip install numpy==1.21.3 "cython" || goto :error -C:\Python311\python.exe -m pip install numpy==1.23.5 "cython" || goto :error -C:\Python312\python.exe -m pip install numpy==1.26.3 "cython" || goto :error +C:\Python38\python.exe -m pip install numpy cython || goto :error +C:\Python39\python.exe -m pip install numpy cython || goto :error +C:\Python310\python.exe -m pip install numpy cython || goto :error +C:\Python311\python.exe -m pip install numpy cython || goto :error +C:\Python312\python.exe -m pip install numpy cython || goto :error :: setuptools 70.2 leads to an error C:\Python312\python.exe -m pip install setuptools==70.1.1 || goto :error diff --git a/ci/win_test_installer.cmd b/ci/win_test_installer.cmd index 85255af463..0bf68842ab 100644 --- a/ci/win_test_installer.cmd +++ b/ci/win_test_installer.cmd @@ -21,9 +21,24 @@ C:\Python38\python -c "import neuron; neuron.test(); quit()" || set "errorfound= C:\Python39\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" C:\Python310\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" C:\Python311\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" -:: install numpy dependency -python -m pip install "numpy<2" +C:\Python312\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" + +:: install oldest supported numpy +C:\Python38\python.exe -m pip install -r packaging/python/oldest_numpy_requirements.txt || goto :error +C:\Python39\python.exe -m pip install -r packaging/python/oldest_numpy_requirements.txt || goto :error +C:\Python310\python.exe -m pip install -r packaging/python/oldest_numpy_requirements.txt || goto :error +C:\Python311\python.exe -m pip install -r packaging/python/oldest_numpy_requirements.txt || goto :error +C:\Python312\python.exe -m pip install -r packaging/python/oldest_numpy_requirements.txt || goto :error + +:: test all pythons again +C:\Python38\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" +C:\Python39\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" +C:\Python310\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" +C:\Python311\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" +C:\Python312\python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" + :: run also using whatever is system python +python -m pip install numpy python --version python -c "import neuron; neuron.test(); quit()" || set "errorfound=y" diff --git a/docs/install/install_instructions.md b/docs/install/install_instructions.md index af7a86583f..dcce802840 100644 --- a/docs/install/install_instructions.md +++ b/docs/install/install_instructions.md @@ -482,7 +482,7 @@ share/lib/python/neuron/rxd/geometry3d/surfaces.cpp:14605:41: error: no member n ``` often there's something related to NumPy nearby, e.g. `npy`. -The issue is that certain versions of NEURON (9.0 and earlier) are not +The issue is that certain versions of NEURON (below 9.0) are not compatible with `numpy>=2`. Check the numpy version, e.g., ``` python -c "import numpy; print(numpy.__version__)" diff --git a/nrn_requirements.txt b/nrn_requirements.txt index c28bc995bb..f049602b4e 100644 --- a/nrn_requirements.txt +++ b/nrn_requirements.txt @@ -11,5 +11,5 @@ packaging pytest<=8.1.1 # potential bug from 8.2.0 due to parallelism? pytest-cov mpi4py<4 # MUSIC not compatible with MPI 4 -numpy<2 +numpy find_libpython diff --git a/packaging/python/build_requirements.txt b/packaging/python/build_requirements.txt index 29d2c1b080..71fe06794e 100644 --- a/packaging/python/build_requirements.txt +++ b/packaging/python/build_requirements.txt @@ -1,8 +1,3 @@ cython packaging -numpy==1.17.5;python_version=='3.8' -numpy==1.19.3;python_version=='3.9' and platform_machine!='arm64' -numpy==1.21.3;python_version=='3.9' and platform_machine=='arm64' -numpy==1.21.4;python_version=='3.10' -numpy==1.23.5;python_version=='3.11' -numpy==1.26.0;python_version=='3.12' +numpy diff --git a/packaging/python/oldest_numpy_requirements.txt b/packaging/python/oldest_numpy_requirements.txt new file mode 100644 index 0000000000..4a77e64c2b --- /dev/null +++ b/packaging/python/oldest_numpy_requirements.txt @@ -0,0 +1,5 @@ +numpy==1.20.3;python_version=='3.9' and platform_machine!='arm64' +numpy==1.21.6;python_version=='3.9' and platform_machine=='arm64' +numpy==1.21.6;python_version=='3.10' +numpy==1.23.5;python_version=='3.11' +numpy==1.26.4;python_version=='3.12' diff --git a/packaging/python/test_requirements.txt b/packaging/python/test_requirements.txt new file mode 100644 index 0000000000..6dbabce060 --- /dev/null +++ b/packaging/python/test_requirements.txt @@ -0,0 +1,2 @@ +pytest +setuptools;python_version>='3.12' # From 3.12, no longer installed by default diff --git a/packaging/python/test_wheels.sh b/packaging/python/test_wheels.sh index 1234d57c2d..853d7cbd7e 100755 --- a/packaging/python/test_wheels.sh +++ b/packaging/python/test_wheels.sh @@ -237,6 +237,12 @@ test_wheel () { } +test_wheel_basic_python () { + echo "=========== BASIC PYTHON TESTS ===========" + $python_exe -c "import neuron; neuron.test(); neuron.test_rxd()" +} + + echo "== Testing $python_wheel using $python_exe ($python_ver) ==" @@ -257,10 +263,8 @@ fi $python_exe -m pip install --upgrade pip -# install numpy, pytest and neuron -# we install setuptools because since python 3.12 it is no more installed -# by default -$python_exe -m pip install "numpy<2" pytest setuptools +# install test requirements +$python_exe -m pip install -r packaging/python/test_requirements.txt $python_exe -m pip install $python_wheel $python_exe -m pip show neuron || $python_exe -m pip show neuron-nightly @@ -271,8 +275,14 @@ if echo $compile_options | grep "NRN_ENABLE_CORENEURON=ON" > /dev/null ; then has_coreneuron=true fi -# run tests -test_wheel "${python_exe}" +# run tests with latest NumPy +echo " == Running tests with latest NumPy == " +test_wheel + +# run basic python tests with oldest supported NumPy +echo " == Running basic python tests with oldest supported NumPy == " +$python_exe -m pip install -r packaging/python/oldest_numpy_requirements.txt +test_wheel_basic_python # cleanup if [[ "$use_venv" != "false" ]]; then diff --git a/setup.py b/setup.py index bca41a0c2e..e15b6e5ac0 100644 --- a/setup.py +++ b/setup.py @@ -354,7 +354,7 @@ def setup_package(): NRN_COLLECT_DIRS = ["bin", "lib", "include", "share"] docs_require = [] # sphinx, themes, etc - maybe_rxd_reqs = ["numpy<2", "Cython"] if Components.RX3D else [] + maybe_rxd_reqs = ["numpy", "Cython"] if Components.RX3D else [] maybe_docs = docs_require if "docs" in sys.argv else [] maybe_test_runner = ["pytest-runner"] if "test" in sys.argv else [] @@ -509,7 +509,7 @@ def setup_package(): }, cmdclass=dict(build_ext=CMakeAugmentedBuilder, docs=Docs), install_requires=[ - "numpy>=1.9.3,<2", + "numpy>=1.9.3", "packaging", "find_libpython", "setuptools<=70.3.0", diff --git a/share/lib/python/neuron/rxd/rxd.py b/share/lib/python/neuron/rxd/rxd.py index 0ac5249684..3c0fd18a8e 100644 --- a/share/lib/python/neuron/rxd/rxd.py +++ b/share/lib/python/neuron/rxd/rxd.py @@ -61,7 +61,7 @@ setup_solver.argtypes = [ ndpointer(ctypes.c_double), ctypes.c_int, - numpy.ctypeslib.ndpointer(numpy.int_, flags="contiguous"), + numpy.ctypeslib.ndpointer(ctypes.c_long, flags="contiguous"), ctypes.c_int, ] @@ -630,8 +630,8 @@ def _matrix_to_rxd_sparse(m): return ( n, len(nonzero_i), - numpy.ascontiguousarray(nonzero_i, dtype=numpy.int_), - numpy.ascontiguousarray(nonzero_j, dtype=numpy.int_), + numpy.ascontiguousarray(nonzero_i, dtype=ctypes.c_long), + numpy.ascontiguousarray(nonzero_j, dtype=ctypes.c_long), nonzero_values, ) @@ -709,7 +709,7 @@ def _setup_matrices(): n = len(_node_get_states()) volumes = node._get_data()[0] - zero_volume_indices = (numpy.where(volumes == 0)[0]).astype(numpy.int_) + zero_volume_indices = (numpy.where(volumes == 0)[0]).astype(ctypes.c_long) if species._has_1d: # TODO: initialization is slow. track down why for sr in _species_get_all_species(): @@ -1896,7 +1896,7 @@ def _init(): _setup_matrices() # if species._has_1d and species._1d_submatrix_n(): # volumes = node._get_data()[0] - # zero_volume_indices = (numpy.where(volumes == 0)[0]).astype(numpy.int_) + # zero_volume_indices = (numpy.where(volumes == 0)[0]).astype(ctypes.c_long) # setup_solver(_node_get_states(), len(_node_get_states()), zero_volume_indices, len(zero_volume_indices), h._ref_t, h._ref_dt) clear_rates() _setup_memb_currents() diff --git a/share/lib/python/neuron/rxd/species.py b/share/lib/python/neuron/rxd/species.py index de8a3095b2..bd6e59f610 100644 --- a/share/lib/python/neuron/rxd/species.py +++ b/share/lib/python/neuron/rxd/species.py @@ -60,12 +60,12 @@ ctypes.c_int, ctypes.py_object, ctypes.c_long, - numpy.ctypeslib.ndpointer(dtype=int), - numpy.ctypeslib.ndpointer(dtype=int), + numpy.ctypeslib.ndpointer(dtype=ctypes.c_long), + numpy.ctypeslib.ndpointer(dtype=ctypes.c_long), ctypes.c_long, - numpy.ctypeslib.ndpointer(dtype=int), + numpy.ctypeslib.ndpointer(dtype=ctypes.c_long), ctypes.c_long, - numpy.ctypeslib.ndpointer(dtype=int), + numpy.ctypeslib.ndpointer(dtype=ctypes.c_long), ctypes.c_long, numpy.ctypeslib.ndpointer(dtype=float), ctypes.c_double, @@ -842,7 +842,7 @@ def line_defs(self, nodes, direction, nodes_length): # sort list for parallelization line_defs.sort(key=lambda x: x[1], reverse=True) - line_defs = numpy.asarray(line_defs, dtype=int) + line_defs = numpy.asarray(line_defs, dtype=ctypes.c_long) line_defs = line_defs.reshape(2 * len(line_defs)) return line_defs @@ -862,7 +862,7 @@ def ordered_nodes(self, p_line_defs, direction, neighbors): def create_neighbors_array(self, nodes, nodes_length): self._isalive() - my_array = numpy.zeros((nodes_length, 3), dtype=int) + my_array = numpy.zeros((nodes_length, 3), dtype=ctypes.c_long) for n in nodes: for i, ele in enumerate(n.neighbors[::2]): my_array[n._index, i] = ele if ele is not None else -1 diff --git a/test/rxd/conftest.py b/test/rxd/conftest.py index 1fbe8ee0cc..2a98c9d3f9 100644 --- a/test/rxd/conftest.py +++ b/test/rxd/conftest.py @@ -1,5 +1,6 @@ import os.path as osp import numpy +import ctypes import pytest import gc @@ -81,7 +82,7 @@ def neuron_nosave_instance(neuron_import): rxd.rxd.rxd_include_node_flux1D(0, None, None, None) rxd.species._has_1d = False rxd.species._has_3d = False - rxd.rxd._zero_volume_indices = numpy.ndarray(0, dtype=numpy.int_) + rxd.rxd._zero_volume_indices = numpy.ndarray(0, dtype=ctypes.c_long) rxd.set_solve_type(dimension=1) From 7d518dd8e739435c2668320d234d1814d067a84e Mon Sep 17 00:00:00 2001 From: Fernando Pereira Date: Thu, 29 Aug 2024 12:31:56 +0100 Subject: [PATCH 11/68] Style improvement of INCREF usage. (#3023) This commit makes INCREF usage more consistent. The rules are to INCREF before assignment and as late as possible. --- src/nrnpython/nrnpy_nrn.cpp | 66 +++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/src/nrnpython/nrnpy_nrn.cpp b/src/nrnpython/nrnpy_nrn.cpp index 5edf14cec7..79b2b89011 100644 --- a/src/nrnpython/nrnpy_nrn.cpp +++ b/src/nrnpython/nrnpy_nrn.cpp @@ -316,6 +316,8 @@ static NPyMechObj* new_pymechobj() { // it as "null". So later `a = b` might segfault because copy constructor decrements the // refcount of `a`s nonsense memory. new (&m->prop_id_) neuron::container::non_owning_identifier_without_container; + m->pyseg_ = nullptr; + m->prop_ = nullptr; } return m; @@ -327,8 +329,8 @@ static NPyMechObj* new_pymechobj(NPySegObj* pyseg, Prop* p) { if (!m) { return NULL; } + Py_INCREF(pyseg); m->pyseg_ = pyseg; - Py_INCREF(m->pyseg_); m->prop_ = p; m->prop_id_ = p->id(); m->type_ = p->_type; @@ -441,8 +443,8 @@ static int NPyAllSegOfSecIter_init(NPyAllSegOfSecIter* self, PyObject* args, PyO return -1; } self->allseg_iter_ = 0; - self->pysec_ = pysec; Py_INCREF(pysec); + self->pysec_ = pysec; } return 0; } @@ -510,9 +512,9 @@ static PyObject* NPySegObj_new(PyTypeObject* type, PyObject* args, PyObject* /* self = (NPySegObj*) type->tp_alloc(type, 0); // printf("NPySegObj_new %p\n", self); if (self != NULL) { + Py_INCREF(pysec); self->pysec_ = pysec; self->x_ = x; - Py_INCREF(self->pysec_); } return (PyObject*) self; } @@ -532,8 +534,8 @@ static PyObject* NPyMechObj_new(PyTypeObject* type, PyObject* args, PyObject* /* // ((PyObject*)self)->ob_type->tp_name); if (self != NULL) { new (self) NPyMechObj; + Py_INCREF(pyseg); self->pyseg_ = pyseg; - Py_INCREF(self->pyseg_); } return (PyObject*) self; } @@ -1200,7 +1202,7 @@ static PyObject* pysec_wholetree_safe(NPySecObj* const self) { static PyObject* pysec2cell(NPySecObj* self) { PyObject* result; if (self->cell_weakref_) { - result = PyWeakref_GET_OBJECT(self->cell_weakref_); + result = PyWeakref_GetObject(self->cell_weakref_); Py_INCREF(result); } else if (auto* o = self->sec_->prop->dparam[6].get(); self->sec_->prop && o) { result = nrnpy_ho2po(o); @@ -1357,12 +1359,8 @@ static PyObject* NPyMechObj_is_ion_safe(NPyMechObj* self) { static PyObject* NPyMechObj_segment(NPyMechObj* self) { CHECK_PROP_INVALID(self->prop_id_); - PyObject* result = NULL; - if (self->pyseg_) { - result = (PyObject*) (self->pyseg_); - Py_INCREF(result); - } - return result; + Py_XINCREF(self->pyseg_); + return (PyObject*) self->pyseg_; } static PyObject* NPyMechObj_segment_safe(NPyMechObj* self) { @@ -1370,13 +1368,12 @@ static PyObject* NPyMechObj_segment_safe(NPyMechObj* self) { } static PyObject* NPyMechFunc_mech(NPyMechFunc* self) { - PyObject* result = NULL; - if (self->pymech_) { - CHECK_PROP_INVALID(self->pymech_->prop_id_); - result = (PyObject*) (self->pymech_); - Py_INCREF(result); + auto* pymech = self->pymech_; + if (pymech) { + CHECK_PROP_INVALID(pymech->prop_id_); + Py_INCREF(pymech); } - return result; + return (PyObject*) pymech; } static PyObject* NPyMechFunc_mech_safe(NPyMechFunc* self) { @@ -1423,13 +1420,12 @@ static PyObject* NPyRangeVar_name_safe(NPyRangeVar* self) { } static PyObject* NPyRangeVar_mech(NPyRangeVar* self) { - CHECK_SEC_INVALID(self->pymech_->pyseg_->pysec_->sec_); - PyObject* result = NULL; - if (self->pymech_) { - result = (PyObject*) self->pymech_; - Py_INCREF(result); + auto* pymech = self->pymech_; + if (pymech) { + CHECK_SEC_INVALID(pymech->pyseg_->pysec_->sec_); + Py_INCREF(pymech); } - return result; + return (PyObject*) pymech; } static PyObject* NPyRangeVar_mech_safe(NPyRangeVar* self) { @@ -1472,12 +1468,12 @@ static PyObject* NPySecObj_connect(NPySecObj* self, PyObject* args) { PyErr_SetString(PyExc_ValueError, "child connection end must be 0 or 1"); return NULL; } - Py_INCREF(self); hoc_pushx(childend); hoc_pushx(parentx); nrn_pushsec(self->sec_); nrn_pushsec(parent->sec_); simpleconnectsection(); + Py_INCREF(self); return (PyObject*) self; } @@ -1610,8 +1606,8 @@ static PyObject* allseg(NPySecObj* self) { CHECK_SEC_INVALID(self->sec_); // printf("allseg\n"); NPyAllSegOfSecIter* ai = PyObject_New(NPyAllSegOfSecIter, pallseg_of_sec_iter_type); - ai->pysec_ = self; Py_INCREF(self); + ai->pysec_ = self; ai->allseg_iter_ = -1; return (PyObject*) ai; } @@ -1621,8 +1617,8 @@ static PyObject* allseg_safe(NPySecObj* self) { } static PyObject* allseg_of_sec_iter(NPyAllSegOfSecIter* self) { - Py_INCREF(self); self->allseg_iter_ = -1; + Py_INCREF(self); return (PyObject*) self; } @@ -1642,8 +1638,8 @@ static PyObject* allseg_of_sec_next(NPyAllSegOfSecIter* self) { // error return NULL; } - seg->pysec_ = self->pysec_; Py_INCREF(self->pysec_); + seg->pysec_ = self->pysec_; if (self->allseg_iter_ == -1) { seg->x_ = 0.; } else if (self->allseg_iter_ == n1) { @@ -1671,8 +1667,8 @@ static PyObject* seg_of_sec_next(NPySegOfSecIter* self) { // error return NULL; } - seg->pysec_ = self->pysec_; Py_INCREF(self->pysec_); + seg->pysec_ = self->pysec_; seg->x_ = (double(self->seg_iter_) + 0.5) / ((double) n1); ++self->seg_iter_; return (PyObject*) seg; @@ -1937,8 +1933,8 @@ static NPyRangeVar* rvnew(Symbol* sym, NPySecObj* sec, double x) { } r->pymech_ = new_pymechobj(); r->pymech_->pyseg_ = PyObject_New(NPySegObj, psegment_type); - r->pymech_->pyseg_->pysec_ = sec; Py_INCREF(sec); + r->pymech_->pyseg_->pysec_ = sec; r->pymech_->pyseg_->x_ = 0.5; r->sym_ = sym; r->isptr_ = 0; @@ -2147,8 +2143,8 @@ static PyObject* var_of_mech_iter(NPyMechObj* self) { if (!self->prop_) { return NULL; } + Py_INCREF(self); vmi->pymech_ = self; - Py_INCREF(vmi->pymech_); vmi->msym_ = memb_func[self->prop_->_type].sym; vmi->i_ = 0; return (PyObject*) vmi; @@ -2166,8 +2162,8 @@ static PyObject* var_of_mech_next(NPyVarOfMechIter* self) { Symbol* sym = self->msym_->u.ppsym[self->i_]; self->i_++; NPyRangeVar* r = (NPyRangeVar*) PyObject_New(NPyRangeVar, range_type); + Py_INCREF(self->pymech_); r->pymech_ = self->pymech_; - Py_INCREF(r->pymech_); r->sym_ = sym; r->isptr_ = 0; r->attr_from_sec_ = 0; @@ -2219,8 +2215,8 @@ static PyObject* segment_getattro(NPySegObj* self, PyObject* pyname) { } else if (is_array(*sym)) { NPyRangeVar* r = PyObject_New(NPyRangeVar, range_type); r->pymech_ = new_pymechobj(); + Py_INCREF(self); r->pymech_->pyseg_ = self; - Py_INCREF(r->pymech_->pyseg_); r->sym_ = sym; r->isptr_ = 0; r->attr_from_sec_ = 0; @@ -2247,8 +2243,8 @@ static PyObject* segment_getattro(NPySegObj* self, PyObject* pyname) { if (is_array(*sym)) { NPyRangeVar* r = PyObject_New(NPyRangeVar, range_type); r->pymech_ = new_pymechobj(); - r->pymech_->pyseg_ = self; Py_INCREF(self); + r->pymech_->pyseg_ = self; r->sym_ = sym; r->isptr_ = 1; r->attr_from_sec_ = 0; @@ -2499,8 +2495,8 @@ static PyObject* mech_getattro(NPyMechObj* self, PyObject* pyname) { // printf("mech_getattro sym %s\n", sym->name); if (is_array(*sym)) { NPyRangeVar* r = PyObject_New(NPyRangeVar, range_type); - r->pymech_ = self; Py_INCREF(self); + r->pymech_ = self; r->sym_ = sym; r->isptr_ = isptr; r->attr_from_sec_ = 0; @@ -2542,8 +2538,8 @@ static PyObject* mech_getattro(NPyMechObj* self, PyObject* pyname) { found_func = true; auto& f = funcs[n]; NPyMechFunc* pymf = PyObject_New(NPyMechFunc, pmechfunc_generic_type); - pymf->pymech_ = self; Py_INCREF(self); + pymf->pymech_ = self; pymf->f_ = f; result = (PyObject*) pymf; } From b985a12c0ae0904bbbb43f806e89c67be0529f99 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 29 Aug 2024 13:34:08 +0200 Subject: [PATCH 12/68] Remove dead code related to Python strings. (#3048) At some point Python strings where kept alive and put into a `dlist` for deferred deletion. This was changed in 15b3b3f5. This commit removes leftover dead code. --- src/nrnpython/nrnpy_p2h.cpp | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/src/nrnpython/nrnpy_p2h.cpp b/src/nrnpython/nrnpy_p2h.cpp index 0164c2b667..931fa0a453 100644 --- a/src/nrnpython/nrnpy_p2h.cpp +++ b/src/nrnpython/nrnpy_p2h.cpp @@ -16,12 +16,10 @@ #include namespace nb = nanobind; -static void nrnpy_decref_defer(PyObject*); static char* nrnpyerr_str(); static PyObject* nrnpy_pyCallObject(PyObject*, PyObject*); static PyObject* main_module; static PyObject* main_namespace; -static hoc_List* dlist; struct Py2Nrn final { ~Py2Nrn() { @@ -254,15 +252,12 @@ static void py2n_component(Object* ob, Symbol* sym, int nindex, int isfunc) { PyObject* pn = PyNumber_Float(result); hoc_pushx(PyFloat_AsDouble(pn)); Py_XDECREF(pn); - Py_XDECREF(result); } else if (is_python_string(result)) { char** ts = hoc_temp_charptr(); Py2NRNString str(result, true); *ts = str.c_str(); hoc_pop_defer(); hoc_pushstr(ts); - // how can we defer the result unref til the string is popped - nrnpy_decref_defer(result); } else { // PyObject_Print(result, stdout, 0); on = nrnpy_po2ho(result); @@ -271,8 +266,8 @@ static void py2n_component(Object* ob, Symbol* sym, int nindex, int isfunc) { if (on) { on->refcount--; } - Py_XDECREF(result); } + Py_XDECREF(result); Py_XDECREF(head); Py_DECREF(tail); } @@ -334,17 +329,6 @@ static void hpoasgn(Object* o, int type) { } } -static void nrnpy_decref_defer(PyObject* po) { - if (po) { -#if 0 - PyObject* ps = PyObject_Str(po); - printf("defer %s\n", PyString_AsString(ps)); - Py_DECREF(ps); -#endif - hoc_l_lappendvoid(dlist, (void*) po); - } -} - static PyObject* hoccommand_exec_help1(PyObject* po) { PyObject* r; // PyObject_Print(po, stdout, 0); @@ -1129,5 +1113,4 @@ extern "C" NRN_EXPORT void nrnpython_reg_real(neuron::python::impl_ptrs* ptrs) { nrnpython_reg_real_nrnpython_cpp(ptrs); // call a function in nrnpy_hoc.cpp to register the functions defined there nrnpython_reg_real_nrnpy_hoc_cpp(ptrs); - dlist = hoc_l_newlist(); } From 52f8195e39f37571041cae4bffd43d48e41a4e7a Mon Sep 17 00:00:00 2001 From: MikeG Date: Thu, 29 Aug 2024 16:30:41 +0200 Subject: [PATCH 13/68] Improve header hygiene for `cabcode.h`. (#2948) Moves cabcode related code into a more standard structure. Essentially, functions are declared in headers, and defined in an associated `.cpp` file of the same name. The `.cpp` file includes the header as the first line of code. If a different translation unit (TU) wants to use the function it includes the header the declares that function. Structs and classes that are used in several translation units are defined in headers, while structs and classes that are only used for implementation purposes only are defined in the `.cpp` and not available to other TUs. Explicitly writing out a function declaration (with or without `extern`) to get access to function is discouraged. --- cmake/NeuronFileLists.cmake | 1 + src/nrncvode/netcvode.cpp | 26 ++------- src/nrncvode/occvode.cpp | 16 ++--- src/nrniv/bbsavestate.cpp | 2 +- src/nrniv/impedanc.cpp | 3 - src/nrniv/multisplit.cpp | 20 +++---- src/nrniv/neuronapi.cpp | 3 +- src/nrniv/nrnmenu.cpp | 12 ++-- src/nrniv/spaceplt.cpp | 1 - src/nrnoc/cabcode.cpp | 53 ++++++----------- src/nrnoc/cabcode.h | 113 ++++++++++++++++++++++++++++++++++++ src/nrnoc/cabvars.h | 5 +- src/nrnoc/eion.cpp | 8 +-- src/nrnoc/nrn_ansi.h | 49 +--------------- src/nrnoc/section.h | 2 +- src/nrnoc/treeset.cpp | 12 ++-- src/nrnpython/nrnpy_hoc.cpp | 8 +-- src/nrnpython/nrnpy_nrn.cpp | 14 ++--- src/oc/code.cpp | 11 ++-- src/oc/code.h | 2 +- src/oc/hoc_oop.cpp | 9 +-- 21 files changed, 187 insertions(+), 183 deletions(-) create mode 100644 src/nrnoc/cabcode.h diff --git a/cmake/NeuronFileLists.cmake b/cmake/NeuronFileLists.cmake index 59b8e6c2de..9809bf8f88 100644 --- a/cmake/NeuronFileLists.cmake +++ b/cmake/NeuronFileLists.cmake @@ -17,6 +17,7 @@ set(HEADER_FILES_TO_INSTALL nrniv/neuronapi.h nrnmpi/nrnmpidec.h nrnoc/cabvars.h + nrnoc/cabcode.h nrnoc/md1redef.h nrnoc/md2redef.h nrnoc/membdef.h diff --git a/src/nrncvode/netcvode.cpp b/src/nrncvode/netcvode.cpp index 7a7154d178..b0ad67a1a0 100644 --- a/src/nrncvode/netcvode.cpp +++ b/src/nrncvode/netcvode.cpp @@ -3,13 +3,9 @@ // define to 0 if do not wish use_min_delay_ to ever be 1 #define USE_MIN_DELAY 1 -#include #include -#include -#include -#include +#include "cabcode.h" #include "classreg.h" -#include "nrnoc2iv.h" #include "parse.hpp" #include "cvodeobj.h" #include "hoclist.h" @@ -19,7 +15,6 @@ #include "nrnneosm.h" #include "datapath.h" #include "objcmd.h" -#include "shared/sundialsmath.h" #include "kssingle.h" #include "ocnotify.h" #include "utils/enumerate.h" @@ -44,6 +39,10 @@ #include "utils/formatting.hpp" #include +#include +#include +#include +#include #include #include @@ -56,8 +55,6 @@ typedef void (*ReceiveFunc)(Point_process*, double*, double); #define NVI_SUCCESS 0 #define PP2NT(pp) ((NrnThread*) ((pp)->_vnt)) #define PP2t(pp) (PP2NT(pp)->_t) -#define LOCK(m) /**/ -#define UNLOCK(m) /**/ // classical and when DiscreteEvent::deliver is already in the right thread // via a future thread instance of NrnNetItem with its own tqe. #define POINT_RECEIVE(type, tar, w, f) (*pnt_receive[type])(tar, w, f) @@ -67,8 +64,6 @@ typedef void (*ReceiveFunc)(Point_process*, double*, double); #include "membfunc.h" extern void single_event_run(); -extern void setup_topology(), v_setup_vectors(); -extern int nrn_errno_check(int); extern NetCvode* net_cvode_instance; extern cTemplate** nrn_pnt_template_; extern double t, dt; @@ -76,29 +71,18 @@ extern void nrn_cvfun(double t, double* y, double* ydot); extern void nrn_cleanup_presyn(PreSyn*); #define nt_dt nrn_threads->_dt #define nt_t nrn_threads->_t -extern void nrn_parent_info(Section*); -extern Object* nrn_sec2cell(Section*); -extern int nrn_sec2cell_equals(Section*, Object*); -extern ReceiveFunc* pnt_receive; -extern ReceiveFunc* pnt_receive_init; extern short* nrn_is_artificial_; // should be bool but not using that type in c extern short* nrn_artcell_qindex_; int nrn_use_selfqueue_; void nrn_pending_selfqueue(double tt, NrnThread*); static void all_pending_selfqueue(double tt); static void* pending_selfqueue(NrnThread*); -extern int hoc_araypt(Symbol*, int); -extern int hoc_stacktype(); -void nrn_use_daspk(int); extern int nrn_use_daspk_; int linmod_extra_eqn_count(); extern int nrn_modeltype(); -extern Symlist* hoc_built_in_symlist; -extern Symlist* hoc_top_level_symlist; extern TQueue* net_cvode_instance_event_queue(NrnThread*); extern hoc_Item* net_cvode_instance_psl(); extern std::vector* net_cvode_instance_prl(); -extern void nrn_update_ps2nt(); extern void nrn_use_busywait(int); void* nrn_interthread_enqueue(NrnThread*); extern void (*nrnthread_v_transfer_)(NrnThread*); diff --git a/src/nrncvode/occvode.cpp b/src/nrncvode/occvode.cpp index 889f9fbc69..67e24d1c87 100644 --- a/src/nrncvode/occvode.cpp +++ b/src/nrncvode/occvode.cpp @@ -1,5 +1,6 @@ #include <../../nrnconf.h> -#include +#include "hocdec.h" +#include "cabcode.h" #include "nrn_ansi.h" #include "nrndae_c.h" #include "nrniv_mf.h" @@ -12,16 +13,9 @@ #include "membfunc.h" #include "nonvintblock.h" -#include +#include +#include -extern void setup_topology(), v_setup_vectors(); -extern void recalc_diam(); -extern int nrn_errno_check(int); -// extern double t, dt; -#define nt_dt nrn_threads->_dt -#define nt_t nrn_threads->_t - -extern Symlist* hoc_built_in_symlist; #include "spmatrix.h" extern double* sp13mat; @@ -45,8 +39,6 @@ extern void (*nrn_multisplit_solve_)(); #endif static Symbol* vsym; // for absolute tolerance -#define SETUP 1 -#define USED 2 /* CVODE expects dy/dt = f(y) and solve (I - gamma*J)*x = b with approx to J=df/dy. diff --git a/src/nrniv/bbsavestate.cpp b/src/nrniv/bbsavestate.cpp index 903bd9eb0f..3274dc0011 100644 --- a/src/nrniv/bbsavestate.cpp +++ b/src/nrniv/bbsavestate.cpp @@ -168,6 +168,7 @@ callback to bbss_early when needed. */ #include "bbsavestate.h" +#include "cabcode.h" #include "classreg.h" #include "nrncvode.h" #include "nrnoc2iv.h" @@ -201,7 +202,6 @@ typedef void (*ReceiveFunc)(Point_process*, double*, double); #include "membfunc.h" extern int section_count; extern "C" void nrn_shape_update(); -extern Section* nrn_section_exists(char* name, int index, Object* cell); extern Section** secorder; extern ReceiveFunc* pnt_receive; extern NetCvode* net_cvode_instance; diff --git a/src/nrniv/impedanc.cpp b/src/nrniv/impedanc.cpp index 9b2d7a12d9..d9cbde709d 100644 --- a/src/nrniv/impedanc.cpp +++ b/src/nrniv/impedanc.cpp @@ -8,10 +8,7 @@ #include #include "nrnoc2iv.h" #include "classreg.h" -#include #include "membfunc.h" -extern void setup_topology(); -extern void recalc_diam(); typedef void (*Pfrv4)(int, Node**, double**, Datum**); diff --git a/src/nrniv/multisplit.cpp b/src/nrniv/multisplit.cpp index 3ca23e4dcc..f37e9ac2fe 100644 --- a/src/nrniv/multisplit.cpp +++ b/src/nrniv/multisplit.cpp @@ -1,36 +1,30 @@ #include <../../nrnconf.h> -#include -#include -#include #include -#include +#include "cabcode.h" #include "nrn_ansi.h" #include "nrndae_c.h" #include "nrniv_mf.h" #include #include #include -#include + +#include +#include +#include #include +#include +#include void nrnmpi_multisplit(Section*, double x, int sid, int backbone_style); int nrn_multisplit_active_; -extern void setup_topology(); extern void (*nrn_multisplit_setup_)(); extern void* nrn_multisplit_triang(NrnThread*); extern void* nrn_multisplit_reduce_solve(NrnThread*); extern void* nrn_multisplit_bksub(NrnThread*); extern double t; -void nrn_multisplit_ptr_update(); -void nrnmpi_multisplit_clear(); -void nrn_multisplit_nocap_v(); -void nrn_multisplit_nocap_v_part1(NrnThread*); -void nrn_multisplit_nocap_v_part2(NrnThread*); -void nrn_multisplit_nocap_v_part3(NrnThread*); -void nrn_multisplit_adjust_rhs(NrnThread*); extern void (*nrn_multisplit_solve_)(); static void multisplit_v_setup(); static void multisplit_solve(); diff --git a/src/nrniv/neuronapi.cpp b/src/nrniv/neuronapi.cpp index 3a286c87c0..a2a798ff4f 100644 --- a/src/nrniv/neuronapi.cpp +++ b/src/nrniv/neuronapi.cpp @@ -2,6 +2,7 @@ #include "../../nrnconf.h" #include "hocdec.h" +#include "cabcode.h" #include "nrniv_mf.h" #include "nrnmpi.h" #include "nrnmpiuse.h" @@ -42,8 +43,6 @@ extern "C" void nrnpy_set_pr_etal(int (*cbpr_stdoe)(int, char*), int (*cbpass)() int ivocmain_session(int, const char**, const char**, int start_session); void simpleconnectsection(); extern Object* hoc_newobj1(Symbol*, int); -extern void nrn_change_nseg(Section*, int); -extern Section* section_new(Symbol* sym); extern std::tuple nrn_mpi_setup(int argc, const char** argv); extern "C" { diff --git a/src/nrniv/nrnmenu.cpp b/src/nrniv/nrnmenu.cpp index 78ad7620c3..de66948849 100644 --- a/src/nrniv/nrnmenu.cpp +++ b/src/nrniv/nrnmenu.cpp @@ -1,13 +1,14 @@ #include <../../nrnconf.h> -#include -#include +#include +#include #if HAVE_IV #include "secbrows.h" #include "ivoc.h" #endif +#include "cabcode.h" #include "nrniv_mf.h" #include "nrnoc2iv.h" #include "nrnpy.h" @@ -15,20 +16,16 @@ #include "classreg.h" #include "gui-redirect.h" -typedef void (*ReceiveFunc)(Point_process*, double*, double); extern int hoc_return_type_code; // from nrnoc #include "membfunc.h" #include "parse.hpp" extern Symlist* hoc_built_in_symlist; extern Symbol** pointsym; -extern ReceiveFunc* pnt_receive; extern int nrn_has_net_event_cnt_; extern int* nrn_has_net_event_; extern short* nrn_is_artificial_; -extern int node_index(Section*, double); extern char* pnt_map; -extern void nrn_parent_info(Section*); // to nrnoc void nrnallsectionmenu(); @@ -1272,8 +1269,7 @@ const char* MechanismType::selected() { int MechanismType::internal_type() { return mti_->type_[selected_item()]; } -extern void mech_insert1(Section*, int); -extern void mech_uninsert1(Section*, Symbol*); + void MechanismType::insert(Section* sec) { if (!mti_->is_point_) { mech_insert1(sec, memb_func[mti_->type_[selected_item()]].sym->subtype); diff --git a/src/nrniv/spaceplt.cpp b/src/nrniv/spaceplt.cpp index ebaa05b1c7..e88aac8405 100644 --- a/src/nrniv/spaceplt.cpp +++ b/src/nrniv/spaceplt.cpp @@ -18,7 +18,6 @@ extern int nrn_multisplit_active_; extern int hoc_execerror_messages; -extern int node_index(Section*, double); extern int nrn_shape_changed_; extern int hoc_return_type_code; Object* (*nrnpy_rvp_rxd_to_callable)(Object*) = 0; diff --git a/src/nrnoc/cabcode.cpp b/src/nrnoc/cabcode.cpp index 50e7fe0c79..e829279659 100644 --- a/src/nrnoc/cabcode.cpp +++ b/src/nrnoc/cabcode.cpp @@ -3,13 +3,12 @@ /* /local/src/master/nrn/src/nrnoc/cabcode.cpp,v 1.37 1999/07/08 14:24:59 hines Exp */ #include -#include -#include -#include +#include +#include +#include #define HOC_L_LIST 1 #include "section.h" -#include "nrn_ansi.h" #include "nrniv_mf.h" #include "membfunc.h" #include "parse.hpp" @@ -447,12 +446,6 @@ double nrn_diameter(Node* nd) { return p->param(0); } -void nrn_chk_section(Symbol* s) { - if (s->type != SECTION) { - execerror("Not a SECTION name:", s->name); - } -} - Section* chk_access() { Section* sec = secstack[isecstack]; if (!sec || !sec->prop) { @@ -512,7 +505,7 @@ Section* nrn_noerr_access(void) /* return 0 if no accessed section */ /*sibling and child pointers do not ref sections to avoid mutual references */ /* the sibling list is ordered according to increasing distance from parent */ -void nrn_remove_sibling_list(Section* sec) { +static void nrn_remove_sibling_list(Section* sec) { Section* s; if (sec->parentsec) { if (sec->parentsec->child == sec) { @@ -538,7 +531,7 @@ static double ncp_abs(Section* sec) { return x; } -void nrn_add_sibling_list(Section* sec) { +static void nrn_add_sibling_list(Section* sec) { Section* s; double x; if (sec->parentsec) { @@ -578,7 +571,7 @@ static void reverse_sibling_list(Section* sec) { *pch = 0; } -void disconnect(void) { +void disconnect() { if (ifarg(1)) { hoc_execerror( "disconnect takes no positional arguments and disconnects the HOC currently accessed " @@ -712,7 +705,9 @@ static Section* Sec_access(void) /* section symbol at pc */ hoc_thisobject = 0; hoc_symlist = hoc_top_level_symlist; } - nrn_chk_section(s); + if (s->type != SECTION) { + execerror("Not a SECTION name:", s->name); + } itm = OPSECITM(s)[range_vec_indx(s)]; if (obsav) { hoc_objectdata = hoc_objectdata_restore(odsav); @@ -814,7 +809,7 @@ void* hoc_sec_internal_name2ptr(const char* s, int eflag) { return vp; } -void* hoc_pysec_name2ptr(const char* s, int eflag) { +void* hoc_pysec_name2ptr(const char* s, int /* eflag */) { /* syntax is _pysec. where is the name of a python nrn.Section from (*nrnpy_pysec_name_p_)(sec) @@ -835,14 +830,14 @@ below to keep the stack ok when it is popped at the end of the next statement. */ -void ob_sec_access_push(Item* qsec) { +void ob_sec_access_push(hoc_Item* qsec) { if (!qsec) { hoc_execerror("section in the object was deleted", (char*) 0); } nrn_pushsec(qsec->element.sec); } -void ob_sec_access(void) { +void ob_sec_access() { if (!section_object_seen) { hoc_nopop(); nrn_pushsec(secstack[isecstack]); @@ -1314,9 +1309,6 @@ neuron::container::data_handle nrn_rangepointer(Section* sec, Symbol* s, return dprop(s, indx, sec, i); } -/* return nullptr if failure instead of hoc_execerror - and return pointer to the 0 element if an array -*/ neuron::container::generic_data_handle nrnpy_rangepointer(Section* sec, Symbol* s, double d, @@ -1437,7 +1429,6 @@ int node_index(Section* sec, double x) /* returns nearest index to x */ return i; } -/* return -1 if x at connection end, nnode-1 if at other end */ int node_index_exact(Section* sec, double x) { if (x == 0.) { if (arc0at0(sec)) { @@ -1472,6 +1463,7 @@ double cable_prop_eval(Symbol* sym) { } return 0.; } + double* cable_prop_eval_pointer(Symbol* sym) { Section* sec; sec = nrn_sec_pop(); @@ -1522,6 +1514,7 @@ void nrn_change_nseg(Section* sec, int n) { } } } + void cable_prop_assign(Symbol* sym, double* pd, int op) { Section* sec; sec = nrn_sec_pop(); @@ -1562,12 +1555,10 @@ void cable_prop_assign(Symbol* sym, double* pd, int op) { } } -/* x of parent for this section */ double nrn_connection_position(Section* sec) { return sec->prop->dparam[1].get(); } -/* x=0,1 end connected to parent */ double nrn_section_orientation(Section* sec) { return sec->prop->dparam[3].get(); } @@ -1870,13 +1861,6 @@ int nrn_get_mechtype(const char* mechname) { return s->subtype; } -int nrn_instance_count(int mechtype) { - if (v_structure_change) { - v_setup_vectors(); - } - return memb_list[mechtype].nodecount; -} - #if EXTRACELLULAR /* want to handle vext(0), vext(1) correctly. No associated i_membrane though.*/ /* @@ -1995,7 +1979,6 @@ void forall_section(void) { Inst* savepc = pc; Item *qsec, *first, *last; - extern int hoc_returning; char buf[200]; char** s; int istk; @@ -2106,7 +2089,7 @@ void ismembrane(void) { /* return true if string is an inserted membrane in the hoc_retpushx((double) has_membrane(str, chk_access())); } -const char* secaccessname(void) { +static const char* secaccessname() { return secname(chk_access()); } @@ -2214,9 +2197,9 @@ void pop_section(void) { hoc_retpushx(1.); } -/* turn off section stack fixing (in case of return,continue,break in a section -statement) between exlicit user level push_section,etc and pop_section -*/ +/* turn off section stack fixing (in case of return,continue,break in a section statement) between + * exlicit user level push_section,etc and pop_section + */ void hoc_level_pushsec(Section* sec) { ++skip_secstack_check; diff --git a/src/nrnoc/cabcode.h b/src/nrnoc/cabcode.h new file mode 100644 index 0000000000..8e0dd2e37b --- /dev/null +++ b/src/nrnoc/cabcode.h @@ -0,0 +1,113 @@ +#pragma once + +#include "neuron/container/generic_data_handle.hpp" +#include "options.h" // for EXTRACELLULAR +#include "neuron/container/data_handle.hpp" + +struct Node; +struct Object; +struct Section; +struct Symbol; +struct Prop; +struct hoc_Item; + +double cable_prop_eval(Symbol* sym); + +// section on stack will be popped +double* cable_prop_eval_pointer(Symbol* sym); + +void oc_save_cabcode(int* a1, int* a2); +void oc_restore_cabcode(int* a1, int* a2); + +void nrn_initcode(); +void nrn_pushsec(Section*); +Object* nrn_sec2cell(Section* sec); +int nrn_sec2cell_equals(Section* sec, Object* obj); +void new_sections(Object* ob, Symbol* sym, hoc_Item** pitm, int size); +Section* section_new(Symbol* sym); + +#if USE_PYTHON +struct NPySecObj; +Section* nrnpy_newsection(NPySecObj*); +#endif + +int arc0at0(Section*); +double nrn_ra(Section*); +void cab_alloc(Prop*); +void morph_alloc(Prop* p); +double nrn_diameter(Node* nd); +double section_length(Section* sec); +Section* chk_access(); + +/// return 0 if no accessed section +Section* nrn_noerr_access(); + +void nrn_disconnect(Section* sec); +Section* nrn_sec_pop(); +void ob_sec_access_push(hoc_Item* qsec); +void mech_insert1(Section* sec, int type); +void mech_uninsert1(Section* sec, Symbol* s); +void nrn_rangeconst(Section*, Symbol*, neuron::container::data_handle value, int op); +Prop* nrn_mechanism(int type, Node* nd); + +/// returns prop given mech type, section, and inode error if mech not at this position +Prop* nrn_mechanism_check(int type, Section* sec, int inode); +Prop* hoc_getdata_range(int type); +int nrn_exists(Symbol* s, Node* node); +neuron::container::data_handle nrn_rangepointer(Section* sec, Symbol* s, double d); + +/// return nullptr if failure instead of hoc_execerror and return pointer to the 0 element if an +/// array +neuron::container::generic_data_handle nrnpy_rangepointer(Section*, Symbol*, double, int*, int); + +/// returns nearest index to x +int node_index(Section* sec, double x); + +/// return -1 if x at connection end, nnode-1 if at other end +int node_index_exact(Section* sec, double x); +void nrn_change_nseg(Section* sec, int n); +void cable_prop_assign(Symbol* sym, double* pd, int op); + +/* x of parent for this section */ +double nrn_connection_position(Section*); + +/* x=0,1 end connected to parent */ +double nrn_section_orientation(Section*); + +int nrn_at_beginning(Section* sec); +Section* nrn_trueparent(Section*); +void nrn_parent_info(Section* s); +void setup_topology(); + +/// name of section (for use in error messages) +const char* secname(Section* sec); + +char* hoc_section_pathname(Section* sec); +double nrn_arc_position(Section* sec, Node* node); +const char* sec_and_position(Section* sec, Node* nd); +int segment_limits(double*); + +/// like node_index but give proper node when x is 0 or 1 as well as in between +Node* node_exact(Section* sec, double x); +Node* node_ptr(Section* sec, double x, double* parea); + +/// returns location of property symbol +neuron::container::data_handle dprop(Symbol* s, int indx, Section* sec, short inode); + +/// returns location of property symbol, return nullptr instead of hoc_execerror +neuron::container::generic_data_handle nrnpy_dprop(Symbol* s, + int indx, + Section* sec, + short inode, + int* err); +int has_membrane(char* mechanism_name, Section* sec); + +/// turn off section stack fixing (in case of return, continue, break in a section statement) +/// between explicit user level push_section, etc and pop_section +void hoc_level_pushsec(Section* sec); + +Section* nrn_section_exists(char* name, int indx, Object* cell); + +#if EXTRACELLULAR +double* nrn_vext_pd(Symbol* s, int indx, Node* nd); +#endif diff --git a/src/nrnoc/cabvars.h b/src/nrnoc/cabvars.h index cb3aa81f07..73f26923ae 100644 --- a/src/nrnoc/cabvars.h +++ b/src/nrnoc/cabvars.h @@ -1,5 +1,7 @@ /* /local/src/master/nrn/src/nrnoc/cabvars.h,v 1.5 1999/02/05 18:09:50 hines Exp */ #pragma once +#include "cabcode.h" // to provide cab_alloc, morph_alloc for backward compatibility + #define XMECH 0 @@ -62,9 +64,6 @@ static const char* morph_mech[] = { 0, }; -extern void cab_alloc(Prop*); -extern void morph_alloc(Prop*); - #if 0 first two memb_func NULL_CUR, NULL_ALLOC, NULL_STATE, NULL_INITIALIZE, (Pfri)0, 0, /*Unused*/ diff --git a/src/nrnoc/eion.cpp b/src/nrnoc/eion.cpp index 7933fabe29..c591c541c5 100644 --- a/src/nrnoc/eion.cpp +++ b/src/nrnoc/eion.cpp @@ -1,7 +1,8 @@ #include <../../nrnconf.h> /* /local/src/master/nrn/src/nrnoc/eion.cpp,v 1.10 1998/02/26 16:42:50 hines Exp */ -#include +#include +#include "cabcode.h" #include "section.h" #include "neuron.h" #include "neuron/cache/mechanism_range.hpp" @@ -16,11 +17,6 @@ #undef hoc_retpushx -extern double chkarg(int, double low, double high); - -extern Section* nrn_noerr_access(); - -extern void hoc_register_prop_size(int, int, int); static constexpr auto nparm = 5; static constexpr auto ndparam = 1; diff --git a/src/nrnoc/nrn_ansi.h b/src/nrnoc/nrn_ansi.h index c791b51b14..0aa1701ef0 100644 --- a/src/nrnoc/nrn_ansi.h +++ b/src/nrnoc/nrn_ansi.h @@ -1,10 +1,11 @@ #pragma once #include "hocdec.h" #include "membfunc.h" // nrn_bamech_t +#include "cabcode.h" #include "neuron/container/data_handle.hpp" #include "neuron/container/generic_data_handle.hpp" - #include + struct Extnode; struct hoc_Item; struct HocParmLimits; @@ -24,15 +25,11 @@ extern void hoc_register_dparam_semantics(int, int, const char*); extern void add_nrn_fornetcons(int, int); extern void hoc_register_tolerance(int, HocStateTolerance*, Symbol***); -extern void oc_save_cabcode(int* a1, int* a2); -extern void oc_restore_cabcode(int* a1, int* a2); - extern "C" void modl_reg(void); // nrnmech stuff extern void _nrn_free_fornetcon(void**); extern double nrn_call_mech_func(Symbol*, int narg, Prop*, int type); -extern Prop* nrn_mechanism(int type, Node*); // mod stuff extern void _nrn_free_watch(Datum*, int, int); @@ -52,23 +49,14 @@ extern void hoc_reg_ba(int, nrn_bamech_t, int); return static_cast(p); } -extern void nrn_pushsec(Section*); extern void nrn_popsec(void); -extern Section* chk_access(void); - -extern Node* node_exact(Section*, double); extern int state_discon_allowed_; extern int section_object_seen; extern int nrn_isecstack(void); extern void nrn_secstack(int); -extern void new_sections(Object* ob, Symbol* sym, hoc_Item** pitm, int size); -extern void cable_prop_assign(Symbol* sym, double* pd, int op); -extern void nrn_parent_info(Section* s); extern void nrn_relocate_old_points(Section* oldsec, Node* oldnode, Section* sec, Node* node); -extern int nrn_at_beginning(Section* sec); -extern void mech_insert1(Section*, int); extern void extcell_2d_alloc(Section* sec); extern int nrn_is_ion(int); extern void single_prop_free(Prop*); @@ -77,26 +65,10 @@ extern int can_change_morph(Section*); extern void nrn_area_ri(Section* sec); extern void nrn_diam_change(Section*); extern void sec_free(hoc_Item*); -extern int node_index(Section* sec, double x); extern void extcell_node_create(Node*); extern void extnode_free_elements(Extnode*); -extern const char* sec_and_position(Section* sec, Node* nd); extern void section_order(void); -extern Section* nrn_sec_pop(void); -extern Node* node_ptr(Section* sec, double x, double* parea); -extern double* nrn_vext_pd(Symbol* s, int indx, Node* nd); -neuron::container::generic_data_handle nrnpy_dprop(Symbol* s, - int indx, - Section* sec, - short inode, - int* err); -extern void nrn_disconnect(Section*); -extern void mech_uninsert1(Section* sec, Symbol* s); -extern Object* nrn_sec2cell(Section*); -extern int nrn_sec2cell_equals(Section*, Object*); neuron::container::data_handle dprop(Symbol* s, int indx, Section* sec, short inode); -extern void nrn_initcode(); -extern int segment_limits(double*); extern "C" void nrn_random_play(); extern void fixed_play_continuous(NrnThread*); extern void setup_tree_matrix(neuron::model_sorted_token const& sorted_token, NrnThread& nt); @@ -105,12 +77,10 @@ extern void second_order_cur(NrnThread*); void nrn_update_voltage(neuron::model_sorted_token const& sorted_token, NrnThread& nt); extern void nrn_fixed_step_lastpart(neuron::model_sorted_token const& sorted_token, NrnThread& nt); extern void hoc_register_dparam_size(int, int); -extern void setup_topology(void); extern int nrn_errno_check(int); void long_difus_solve(neuron::model_sorted_token const&, int method, NrnThread& nt); extern void nrn_fihexec(int); extern int special_pnt_call(Object*, Symbol*, int); -extern void ob_sec_access_push(hoc_Item*); extern void nrn_mk_prop_pools(int); extern void SectionList_reg(void); extern void SectionRef_reg(void); @@ -119,8 +89,6 @@ extern void hoc_symbol_tolerance(Symbol*, double); extern void node_destruct(Node**, int); extern void nrn_sec_ref(Section**, Section*); extern void hoc_level_pushsec(Section*); -extern double nrn_ra(Section*); -extern int node_index_exact(Section*, double); void nrn_ba(neuron::model_sorted_token const&, NrnThread&, int); extern void nrn_rhs_ext(NrnThread*); extern void nrn_setup_ext(NrnThread*); @@ -149,28 +117,15 @@ void nrn_rhs(neuron::model_sorted_token const&, NrnThread&); extern void v_setup_vectors(void); extern void section_ref(Section*); extern void section_unref(Section*); -extern const char* secname(Section*); extern const char* nrn_sec2pysecname(Section*); -void nrn_rangeconst(Section*, Symbol*, neuron::container::data_handle value, int op); -extern int nrn_exists(Symbol*, Node*); -neuron::container::data_handle nrn_rangepointer(Section*, Symbol*, double x); -neuron::container::generic_data_handle nrnpy_rangepointer(Section*, Symbol*, double, int*, int); -extern double* cable_prop_eval_pointer(Symbol*); // section on stack will be popped -extern char* hoc_section_pathname(Section*); -extern double nrn_arc_position(Section*, Node*); extern double node_dist(Section*, Node*); // distance of node to parent position -extern double nrn_section_orientation(Section*); -extern double nrn_connection_position(Section*); -extern Section* nrn_trueparent(Section*); extern double topol_distance(Section*, Node*, Section*, Node*, Section**, Node**); -extern int arc0at0(Section*); extern void nrn_clear_mark(void); extern short nrn_increment_mark(Section*); extern short nrn_value_mark(Section*); extern int is_point_process(Object*); extern int nrn_vartype(const Symbol*); // nrnocCONST, DEP, STATE extern void recalc_diam(void); -extern Prop* nrn_mechanism_check(int type, Section* sec, int inode); extern bool nrn_use_fast_imem; void nrn_fast_imem_alloc(); extern void nrn_calc_fast_imem(NrnThread*); diff --git a/src/nrnoc/section.h b/src/nrnoc/section.h index 0f496d1f46..04622aae75 100644 --- a/src/nrnoc/section.h +++ b/src/nrnoc/section.h @@ -23,6 +23,7 @@ d and rhs is calculated from the property list. */ #include "hoclist.h" +#include "cabcode.h" #include "membfunc.h" #include "neuron/container/mechanism_data.hpp" #include "neuron/container/node_data.hpp" @@ -446,7 +447,6 @@ extern hoc_List* section_list; /* Where the Sections live */ extern Section* sec_alloc(); /* Allocates a single section */ extern void node_alloc(Section*, short); /* Allocates node vectors in a section*/ -extern double section_length(Section*), nrn_diameter(Node*); extern Node* nrn_parent_node(Node*); extern Section* nrn_section_alloc(); extern void nrn_section_free(Section*); diff --git a/src/nrnoc/treeset.cpp b/src/nrnoc/treeset.cpp index 6ca37a4d1d..4ee251183a 100644 --- a/src/nrnoc/treeset.cpp +++ b/src/nrnoc/treeset.cpp @@ -1,6 +1,7 @@ #include <../../nrnconf.h> /* /local/src/master/nrn/src/nrnoc/treeset.cpp,v 1.39 1999/07/08 14:25:07 hines Exp */ +#include "cabcode.h" #include "cvodeobj.h" #include "membfunc.h" #include "multisplit.h" @@ -21,10 +22,10 @@ #include "utils/profile/profiler_interface.h" #include "multicore.h" -#include -#include -#include -#include +#include +#include +#include +#include #include #include @@ -35,7 +36,6 @@ int nrn_shape_changed_; /* for notifying Shape class in nrniv */ double* nrn_mech_wtime_; extern double chkarg(int, double low, double high); -extern double nrn_ra(Section*); #if !defined(NRNMPI) || NRNMPI == 0 extern double nrnmpi_wtime(); #endif @@ -45,9 +45,7 @@ extern int* nrn_dparam_ptr_start_; extern int* nrn_dparam_ptr_end_; extern void nrn_define_shape(); -#if 1 || NRNMPI void (*nrn_multisplit_setup_)(); -#endif /* Do not use unless necessary (loops in tree structure) since overhead diff --git a/src/nrnpython/nrnpy_hoc.cpp b/src/nrnpython/nrnpy_hoc.cpp index cb10da5d47..4950c35c7b 100644 --- a/src/nrnpython/nrnpy_hoc.cpp +++ b/src/nrnpython/nrnpy_hoc.cpp @@ -1,3 +1,4 @@ +#include "cabcode.h" #include "ivocvect.h" #include "neuron/container/data_handle.hpp" #include "nrniv_mf.h" @@ -7,7 +8,6 @@ #include "nrnpy_utils.h" #include "nrnpython.h" #include "convert_cxx_exceptions.hpp" -#include #include "nrnwrap_dlfcn.h" #include "ocfile.h" @@ -15,12 +15,10 @@ #include "oclist.h" #include "shapeplt.h" -#include -#include // for PyMemberDef - #include #include #include +#include #include @@ -36,11 +34,9 @@ extern void (*nrnpy_restore_savestate)(int64_t, char*); extern void (*nrnpy_store_savestate)(char** save_data, uint64_t* save_data_size); extern void (*nrnpy_decref)(void* pyobj); extern void lvappendsec_and_ref(void* sl, Section* sec); -extern Section* nrn_noerr_access(); extern void hoc_pushs(Symbol*); extern double* hoc_evalpointer(); extern double cable_prop_eval(Symbol* sym); -extern void nrn_change_nseg(Section*, int); extern Symlist* hoc_top_level_symlist; extern Symlist* hoc_built_in_symlist; extern Inst* hoc_pc; diff --git a/src/nrnpython/nrnpy_nrn.cpp b/src/nrnpython/nrnpy_nrn.cpp index 79b2b89011..83d88cbf2c 100644 --- a/src/nrnpython/nrnpy_nrn.cpp +++ b/src/nrnpython/nrnpy_nrn.cpp @@ -1,9 +1,9 @@ #include "neuron/container/data_handle.hpp" #include "neuron/container/generic_data_handle.hpp" #include "nrn_ansi.h" +#include "cabcode.h" #include "nrnpython.h" #include -#include #include #include #include "nrniv_mf.h" @@ -11,6 +11,7 @@ #include "nrnpy.h" #include "nrnpy_utils.h" #include "convert_cxx_exceptions.hpp" + #ifndef M_PI #define M_PI (3.14159265358979323846) #endif @@ -19,7 +20,12 @@ #include #include +#include #include +#include +#include +#include +#include #include @@ -32,10 +38,7 @@ extern void nrn_pt3dchange2(Section* sec, int i, double x, double y, double z, d extern void nrn_pt3dstyle1(Section* sec, double x, double y, double z); extern void nrn_pt3dstyle0(Section* sec); -extern Symlist* hoc_built_in_symlist; -extern Section* nrn_noerr_access(); extern PyObject* nrn_ptr_richcmp(void* self_ptr, void* other_ptr, int op); -extern int has_membrane(char*, Section*); // used to be static in nrnpy_hoc.cpp extern int hocobj_pushargs(PyObject*, std::vector&); extern void hocobj_pushargs_free_strings(std::vector&); @@ -120,10 +123,7 @@ PyObject* pmech_types; // Python map for name to Mechanism PyObject* rangevars_; // Python map for name to Symbol extern PyTypeObject* hocobject_type; -extern Section* nrnpy_newsection(NPySecObj*); extern void simpleconnectsection(); -extern void nrn_change_nseg(Section*, int); -extern double section_length(Section*); extern short* nrn_is_artificial_; extern cTemplate** nrn_pnt_template_; extern PyObject* nrnpy_forall_safe(PyObject* self, PyObject* args); diff --git a/src/oc/code.cpp b/src/oc/code.cpp index e0a7c9794c..d297dcceaa 100644 --- a/src/oc/code.cpp +++ b/src/oc/code.cpp @@ -2,8 +2,9 @@ /* /local/src/master/nrn/src/oc/code.cpp,v 1.37 1999/07/03 14:20:21 hines Exp */ #include "backtrace_utils.h" -#include +#include "bbslsrv2.h" #include "hoc.h" +#include "cabcode.h" #include "code.h" #include "hocstr.h" #include "parse.hpp" @@ -12,9 +13,6 @@ #include "oc_ansi.h" #include "hocparse.h" #include "equation.h" -#include -#include -#include #include #include "nrnfilewrap.h" #include "utils/enumerate.h" @@ -23,6 +21,10 @@ #include "options.h" #include "section.h" +#include +#include +#include +#include #include #include #include @@ -1828,7 +1830,6 @@ void eval(void) /* evaluate variable on stack */ Object* obsav = 0; Symlist* slsav; double d = 0.0; - extern double cable_prop_eval(Symbol*); Symbol* sym; sym = hoc_spop(); if (sym->cpublic == 2) { diff --git a/src/oc/code.h b/src/oc/code.h index e9906db78f..eab311bae1 100644 --- a/src/oc/code.h +++ b/src/oc/code.h @@ -27,7 +27,7 @@ extern void hoc_arayinstal(void); /* OOP */ extern void hoc_objectvar(void), hoc_object_component(void), hoc_object_eval(void); extern void hoc_object_asgn(void), hoc_objvardecl(void), hoc_cmp_otype(void), hoc_newobj(void); -extern void hoc_asgn_obj_to_str(void), hoc_known_type(void), hoc_push_string(void); +extern void hoc_asgn_obj_to_str(void), hoc_known_type(void); extern void hoc_objectarg(void), hoc_ob_pointer(void), hoc_constobject(void); extern void hoc_push_current_object(void), hoc_newobj_arg(void); extern void hoc_autoobject(void), hocobjret(void), hoc_newobj_ret(void); diff --git a/src/oc/hoc_oop.cpp b/src/oc/hoc_oop.cpp index 4f2ee252b3..6184dc87ce 100644 --- a/src/oc/hoc_oop.cpp +++ b/src/oc/hoc_oop.cpp @@ -1,15 +1,17 @@ #include <../../nrnconf.h> +#include +#include #include "utils/formatting.hpp" -#include -#include -#include + +#include "classreg.h" #include "hocstr.h" #include "parse.hpp" #include "hocparse.h" #include "code.h" +#include "cabcode.h" #include "hocassrt.h" #include "hoclist.h" #include "nrn_ansi.h" @@ -1367,7 +1369,6 @@ void hoc_object_eval(void) { } hoc_pushx(*(nrn_rangepointer(sec, sym, x))); } else if (d_sym->type == VAR && d_sym->subtype == USERPROPERTY) { - extern double cable_prop_eval(Symbol*); hoc_pushx(cable_prop_eval(hoc_spop())); } } From e5e720771676f6b8e02465c1831a2afce71f3da8 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Fri, 30 Aug 2024 14:26:18 +0200 Subject: [PATCH 14/68] Make NOCMODL output formattable. (#3057) For non-threadsafe MOD files, this restores the ability to use `clang-format` to format the files. --- src/nmodl/noccout.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nmodl/noccout.cpp b/src/nmodl/noccout.cpp index 9eb07ab829..31c83e2e73 100644 --- a/src/nmodl/noccout.cpp +++ b/src/nmodl/noccout.cpp @@ -85,12 +85,12 @@ void c_out() { P("#undef PI\n"); P("#define nil 0\n"); P("#define _pval pval\n"); // due to some old models using _pval - P("// clang-format on\n"); + P("// clang-format off\n"); P("#include \"md1redef.h\"\n"); P("#include \"section_fwd.hpp\"\n"); P("#include \"nrniv_mf.h\"\n"); P("#include \"md2redef.h\"\n"); - P("// clang-format off\n"); + P("// clang-format on\n"); P("#include \"neuron/cache/mechanism_range.hpp\"\n"); P("#include \n"); From 24222db916773463a517e51e02f560c23e91fbb4 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Fri, 30 Aug 2024 14:26:51 +0200 Subject: [PATCH 15/68] Reduce redundant VERBATIM usage. (#3058) --- src/nrnoc/vclmp.mod | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/nrnoc/vclmp.mod b/src/nrnoc/vclmp.mod index fa275e34fa..86614dacb1 100755 --- a/src/nrnoc/vclmp.mod +++ b/src/nrnoc/vclmp.mod @@ -157,9 +157,6 @@ PROCEDURE update() { e0 = e vo0 = vo vi0 = vi - VERBATIM - return 0; - ENDVERBATIM } COMMENT From 6704244f9e4dfa99ff4164c32613d36f337a79c4 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Tue, 3 Sep 2024 10:35:59 +0200 Subject: [PATCH 16/68] Create a pointer from `Prop` to `Node`. (#2768) When generating code to call processes from HOC or Python one difficulty can be obtaining the voltage. The voltage is associated with the Node. In the generated code we only have access to the Prop. We don't have access to the voltage via `Memb_list::nodeindices`. When generating code for NRN with NMODL, we don't populate what CoreNEURON calls `v_unused`. --- src/nrnoc/membfunc.cpp | 5 +++++ src/nrnoc/membfunc.h | 1 + src/nrnoc/section.h | 7 +++++-- src/nrnoc/treeset.cpp | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/nrnoc/membfunc.cpp b/src/nrnoc/membfunc.cpp index b6315cb3f5..e858536147 100644 --- a/src/nrnoc/membfunc.cpp +++ b/src/nrnoc/membfunc.cpp @@ -20,6 +20,11 @@ void Memb_func::invoke_initialize(neuron::model_sorted_token const& sorted_token long& _nrn_mechanism_access_alloc_seq(Prop* prop) { return prop->_alloc_seq; } + +Node* _nrn_mechanism_access_node(Prop* prop) { + return prop->node; +} + double& _nrn_mechanism_access_a(Node* node) { return node->a(); } diff --git a/src/nrnoc/membfunc.h b/src/nrnoc/membfunc.h index a3ada08d6d..ad80ed9d7e 100644 --- a/src/nrnoc/membfunc.h +++ b/src/nrnoc/membfunc.h @@ -296,6 +296,7 @@ namespace _get { // See https://github.com/neuronsimulator/nrn/issues/2234 for context of how this might be done // better in future... [[nodiscard]] long& _nrn_mechanism_access_alloc_seq(Prop*); +[[nodiscard]] Node* _nrn_mechanism_access_node(Prop* prop); [[nodiscard]] double& _nrn_mechanism_access_a(Node*); [[nodiscard]] double& _nrn_mechanism_access_b(Node*); [[nodiscard]] double& _nrn_mechanism_access_d(Node*); diff --git a/src/nrnoc/section.h b/src/nrnoc/section.h index 04622aae75..1e26dc8824 100644 --- a/src/nrnoc/section.h +++ b/src/nrnoc/section.h @@ -226,17 +226,20 @@ struct Node { #include "hocdec.h" /* Prop needs Datum and Datum needs Symbol */ #endif + #define PROP_PY_INDEX 10 struct Prop { // Working assumption is that we can safely equate "Prop" with "instance // of a mechanism" apart from a few special cases like CABLESECTION - Prop(short type) - : _type{type} { + Prop(Node* node, short type) + : node(node) + , _type{type} { if (type != CABLESECTION) { m_mech_handle = neuron::container::Mechanism::owning_handle{ neuron::model().mechanism_data(type)}; } } + Node* node; /* The node this property belongs to. */ Prop* next; /* linked list of properties */ short _type; /* type of membrane, e.g. passive, HH, etc. */ int dparam_size; /* for notifying hoc_free_val_array */ diff --git a/src/nrnoc/treeset.cpp b/src/nrnoc/treeset.cpp index 4ee251183a..fb36e8b897 100644 --- a/src/nrnoc/treeset.cpp +++ b/src/nrnoc/treeset.cpp @@ -674,7 +674,7 @@ Prop* prop_alloc(Prop** pp, int type, Node* nd) { nrn_alloc_node_ = nd; // this might be null v_structure_change = 1; current_prop_list = pp; - auto* p = new Prop{static_cast(type)}; + auto* p = new Prop{nd, static_cast(type)}; p->next = *pp; p->ob = nullptr; p->_alloc_seq = -1; From 9373eef94ab5723dc4b1605aaa1edab1c38ee431 Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Tue, 3 Sep 2024 17:23:57 +0200 Subject: [PATCH 17/68] Set the voltage from `_setdata`. (#3066) * Move `_setdata` code in generated file. We'll need access to `v` later. This pushes the definition of `_setdata` further down the generated file; and prints a declaration at the previous location. The declaration is needed to register the function `_hoc_setdata`. * Set the voltage from `_setdata`. In non-VECTORIZED files, the voltage is a static double. When calling `setdata` several other prop related global variables are set. However, not the voltage. This commits fixes the bug and also sets `v` to the voltage of the node associated with the prop provided. --- src/nmodl/nocpout.cpp | 67 +++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/src/nmodl/nocpout.cpp b/src/nmodl/nocpout.cpp index b35308ef03..92c18d6b2d 100644 --- a/src/nmodl/nocpout.cpp +++ b/src/nmodl/nocpout.cpp @@ -428,35 +428,10 @@ extern void nrn_promote(Prop*, int, int);\n\ defs_list, "double get_loc_point_process(void*); return (get_loc_point_process(_vptr));\n}\n"); } - /* function to set up _p and _ppvar */ - Lappendstr(defs_list, "extern void _nrn_setdata_reg(int, void(*)(Prop*));\n"); - Lappendstr(defs_list, "static void _setdata(Prop* _prop) {\n"); - if (!point_process) { - Lappendstr(defs_list, "_extcall_prop = _prop;\n"); - Lappendstr(defs_list, "_prop_id = _nrn_get_prop_id(_prop);\n"); - } - if (!vectorize) { - Lappendstr(defs_list, - "neuron::legacy::set_globals_from_prop(_prop, _ml_real, _ml, _iml);\n" - "_ppvar = _nrn_mechanism_access_dparam(_prop);\n"); - } - Lappendstr(defs_list, "}\n"); - if (point_process) { - Lappendstr(defs_list, "static void _hoc_setdata(void* _vptr) { Prop* _prop;\n"); - Lappendstr(defs_list, "_prop = ((Point_process*)_vptr)->_prop;\n"); - } else { - Lappendstr(defs_list, - "static void _hoc_setdata() {\n Prop *_prop, *hoc_getdata_range(int);\n"); - Sprintf(buf, "_prop = hoc_getdata_range(_mechtype);\n"); - Lappendstr(defs_list, buf); - } - Lappendstr(defs_list, " _setdata(_prop);\n"); - if (point_process) { - Lappendstr(defs_list, "}\n"); - } else { - Lappendstr(defs_list, "hoc_retpushx(1.);\n}\n"); - } + std::string hoc_setdata_arg = point_process ? "void*" : ""; + Sprintf(buf, "static void _hoc_setdata(%s);\n", hoc_setdata_arg.c_str()); + Lappendstr(defs_list, buf); /* functions */ Lappendstr(defs_list, "/* connect user functions to hoc names */\n"); @@ -755,6 +730,42 @@ extern void nrn_promote(Prop*, int, int);\n\ } } + /* function to set up _p and _ppvar */ + Lappendstr(defs_list, "extern void _nrn_setdata_reg(int, void(*)(Prop*));\n"); + Lappendstr(defs_list, "static void _setdata(Prop* _prop) {\n"); + if (!point_process) { + Lappendstr(defs_list, "_extcall_prop = _prop;\n"); + Lappendstr(defs_list, "_prop_id = _nrn_get_prop_id(_prop);\n"); + } + if (!vectorize) { + Lappendstr(defs_list, + "neuron::legacy::set_globals_from_prop(_prop, _ml_real, _ml, _iml);\n" + "_ppvar = _nrn_mechanism_access_dparam(_prop);\n"); + if (!artificial_cell) { + Lappendstr(defs_list, + "Node * _node = _nrn_mechanism_access_node(_prop);\n" + "v = _nrn_mechanism_access_voltage(_node);\n"); + } + } + Lappendstr(defs_list, "}\n"); + + if (point_process) { + Lappendstr(defs_list, "static void _hoc_setdata(void* _vptr) { Prop* _prop;\n"); + Lappendstr(defs_list, "_prop = ((Point_process*)_vptr)->_prop;\n"); + } else { + Lappendstr(defs_list, + "static void _hoc_setdata() {\n Prop *_prop, *hoc_getdata_range(int);\n"); + Sprintf(buf, "_prop = hoc_getdata_range(_mechtype);\n"); + Lappendstr(defs_list, buf); + } + Lappendstr(defs_list, " _setdata(_prop);\n"); + if (point_process) { + Lappendstr(defs_list, "}\n"); + } else { + Lappendstr(defs_list, "hoc_retpushx(1.);\n}\n"); + } + + /******** what normally goes into cabvars.h structures */ /*declaration of the range variables names to HOC */ From 1d812c87a33ce9c215840b67925113dd4e9c63fb Mon Sep 17 00:00:00 2001 From: MikeG Date: Wed, 4 Sep 2024 20:43:23 +0200 Subject: [PATCH 18/68] Remove `redef.h`. (#3065) The file `redef.h` contained numerous macro definitions of the form: ``` #define call hoc_call ``` This refactoring removes the need for these macros by renaming the identifiers, e.g. `call` was replaced with `hoc_call`. The file `redef.h` is removed entirely. --- src/ivoc/checkpnt.cpp | 67 ++++--- src/nrniv/glinerec.cpp | 2 +- src/oc/axis.cpp | 59 +++--- src/oc/code.cpp | 329 ++++++++++++++++--------------- src/oc/code.h | 24 ++- src/oc/code2.cpp | 47 +++-- src/oc/debug.cpp | 84 ++++---- src/oc/equation.h | 9 +- src/oc/fileio.cpp | 123 ++++++------ src/oc/ftime.cpp | 3 +- src/oc/functabl.cpp | 4 +- src/oc/hoc.cpp | 261 ++++++++++++------------- src/oc/hoc.h | 1 - src/oc/hoc_init.cpp | 38 ++-- src/oc/hoc_oop.cpp | 76 ++++---- src/oc/hocgetsym.h | 2 +- src/oc/hocparse.h | 4 +- src/oc/math.cpp | 17 +- src/oc/mswinprt.cpp | 16 +- src/oc/nonlin.cpp | 85 ++++---- src/oc/oc_ansi.h | 2 +- src/oc/parse.ypp | 434 ++++++++++++++++++++--------------------- src/oc/plot.cpp | 15 +- src/oc/plt.cpp | 25 +-- src/oc/redef.h | 127 ------------ src/oc/symbol.cpp | 45 +++-- src/oc/xred.cpp | 14 +- 27 files changed, 890 insertions(+), 1023 deletions(-) delete mode 100644 src/oc/redef.h diff --git a/src/ivoc/checkpnt.cpp b/src/ivoc/checkpnt.cpp index 4ff1749d85..695d1aab7d 100644 --- a/src/ivoc/checkpnt.cpp +++ b/src/ivoc/checkpnt.cpp @@ -97,7 +97,6 @@ data depending on type. eg for VAR && NOTUSER it is #endif #include "checkpnt.h" -#include "redef.h" #include "hoclist.h" #include "parse.hpp" #include "code.h" @@ -109,55 +108,55 @@ static struct HocInst { Pfrv pi; const char* signature; } hoc_inst_[] = {{0, 0}, // 0 - {nopop, 0}, - {eval, 0}, - {add, 0}, + {hoc_nopop, 0}, + {hoc_eval, 0}, + {hoc_add, 0}, {hoc_sub, 0}, - {mul, 0}, + {hoc_mul, 0}, {hoc_div, 0}, {hoc_negate, nullptr}, - {power, 0}, + {hoc_power, 0}, {hoc_assign, nullptr}, - {bltin, "s"}, // requires change - {varpush, "s"}, // 10 - {constpush, "s"}, - {pushzero, 0}, - {print, 0}, - {varread, "s"}, - {prexpr, 0}, - {prstr, 0}, - {gt, 0}, + {hoc_bltin, "s"}, // requires change + {hoc_varpush, "s"}, // 10 + {hoc_constpush, "s"}, + {hoc_pushzero, 0}, + {hoc_print, 0}, + {hoc_varread, "s"}, + {hoc_prexpr, 0}, + {hoc_prstr, 0}, + {hoc_gt, 0}, {hoc_lt, nullptr}, {hoc_eq, nullptr}, // 20 - {ge, 0}, - {le, 0}, - {ne, 0}, + {hoc_ge, 0}, + {hoc_le, 0}, + {hoc_ne, 0}, {hoc_and, 0}, {hoc_or, 0}, {hoc_not, 0}, - {ifcode, "iii"}, - {forcode, "iii"}, - {shortfor, "ii"}, - {call, "si"}, // 30 + {hoc_ifcode, "iii"}, + {hoc_forcode, "iii"}, + {hoc_shortfor, "ii"}, + {hoc_call, "si"}, // 30 {hoc_arg, "i"}, - {argassign, "i"}, - {funcret, 0}, - {procret, 0}, + {hoc_argassign, "i"}, + {hoc_funcret, 0}, + {hoc_procret, 0}, {hoc_stringarg, "i"}, {hoc_push_string, "s"}, - {Break, 0}, - {Continue, 0}, - {Stop, 0}, - {assstr, 0}, // 40 + {hoc_Break, 0}, + {hoc_Continue, 0}, + {hoc_Stop, 0}, + {hoc_assstr, 0}, // 40 {hoc_evalpointer, 0}, {hoc_newline, 0}, {hoc_delete_symbol, "s"}, {hoc_cyclic, 0}, - {dep_make, 0}, - {eqn_name, 0}, - {eqn_init, 0}, - {eqn_lhs, 0}, // 50 - {eqn_rhs, 0}, + {hoc_dep_make, 0}, + {hoc_eqn_name, 0}, + {hoc_eqn_init, 0}, + {hoc_eqn_lhs, 0}, // 50 + {hoc_eqn_rhs, 0}, {hoc_objectvar, "s"}, {hoc_object_component, "siis"}, {hoc_object_eval, 0}, diff --git a/src/nrniv/glinerec.cpp b/src/nrniv/glinerec.cpp index f224b658b2..17b2b0233e 100644 --- a/src/nrniv/glinerec.cpp +++ b/src/nrniv/glinerec.cpp @@ -80,7 +80,7 @@ void GLineRecord::fill_pd1() { rangevarevalpointer(); pd = hoc_pxpop(); hoc_pushx(*pd); - } else if (pc1->pf == varpush) { + } else if (pc1->pf == hoc_varpush) { Symbol* sym = hoc_pc->sym; if (strcmp(sym->name, "t") == 0) { saw_t_ = true; diff --git a/src/oc/axis.cpp b/src/oc/axis.cpp index e55889bb4a..ea8d4e90dd 100644 --- a/src/oc/axis.cpp +++ b/src/oc/axis.cpp @@ -134,7 +134,6 @@ axis.cpp,v #include #include #include -#include "hoc.h" #include "gui-redirect.h" #define CLIP 1e9 @@ -201,8 +200,8 @@ static void close_regraph(void) { static void do_regraph(void) { int i; for (i = 0; i < regraph_index; i++) { - if (regraph_color[i] != color) { - set_color(regraph_color[i]); + if (regraph_color[i] != hoc_color) { + hoc_set_color(regraph_color[i]); } PLOT(regraph_narg[i], regraph_mode[i], regraph_x[i], *regraph_y[i]); } @@ -211,7 +210,7 @@ static void save_regraph_item(int narg, int mode, double x) { regraph_narg[regraph_index] = narg; regraph_mode[regraph_index] = mode; regraph_x[regraph_index] = x; - regraph_color[regraph_index] = color; + regraph_color[regraph_index] = hoc_color; if (narg == 1 && regraph_index < max_regraph_index) { regraph_y[regraph_index] = &ystart; regraph_index++; @@ -282,7 +281,7 @@ static int PLOT(int narg, int mode, double x, double y) { x = xorg + xscale * x; y = yorg + yscale * y; if (x <= xhigh && x >= xlow && y <= yhigh && y >= ylow) { - plt(mode, x, y); + hoc_plt(mode, x, y); } else if (mode > 0) { lastmode = 1; ok = 0; @@ -349,19 +348,19 @@ void hoc_axis(void) { y0 = yorg; if (!ifarg(1)) { - plt(1, XORG, y0); + hoc_plt(1, XORG, y0); for (x = xstart; x <= xstop + 1e-10; x = x + (xstop - xstart) / xinc) { i = xorg + xscale * x; - plt(2, i, y0); - plt(2, i, y0 + 10.); - plt(1, i, y0); + hoc_plt(2, i, y0); + hoc_plt(2, i, y0 + 10.); + hoc_plt(1, i, y0); } - plt(1, x0, YORG); + hoc_plt(1, x0, YORG); for (y = ystart; y <= ystop + 1e-10; y = y + (ystop - ystart) / yinc) { j = yorg + yscale * y; - plt(2, x0, j); - plt(2, x0 + 10., j); - plt(1, x0, j); + hoc_plt(2, x0, j); + hoc_plt(2, x0 + 10., j); + hoc_plt(1, x0, j); } width = WIDTH; @@ -376,9 +375,9 @@ void hoc_axis(void) { offset = width * (int) strlen(s) / 2; if (i == x0 && y0 != YORG) offset = -width / 2; - plt(1, i - offset, y0 - 1.5 * height); - plt(-2, 0., 0.); - plprint(s); + hoc_plt(1, i - offset, y0 - 1.5 * height); + hoc_plt(-2, 0., 0.); + hoc_plprint(s); } for (y = ystart; y <= ystop + 1e-10; y = y + (ystop - ystart) / yinc) { @@ -389,13 +388,13 @@ void hoc_axis(void) { offset = width * (int) strlen(s) + width; j = yorg + yscale * y; if (j == y0 && x0 != XORG) - plt(1, x0 - offset, j + 2.); + hoc_plt(1, x0 - offset, j + 2.); else - plt(1, x0 - offset, j - 6.); - plt(-2, 0., 0.); - plprint(s); + hoc_plt(1, x0 - offset, j - 6.); + hoc_plt(-2, 0., 0.); + hoc_plprint(s); } - plt(-1, 0., 0.); + hoc_plt(-1, 0., 0.); } Ret(1.); } @@ -543,13 +542,13 @@ static void plotflush(int contin) { for (i = 0; i < NPARAM; i++) { parsav[i] = param[i]; } - savcolor = color; + savcolor = hoc_color; for (g = glist_head; g != (Grph*) 0; g = g->g_next) { for (i = 0; i < NPARAM; i++) { param[i] = g->g_param[i]; } - if (color != g->g_color) { - IGNORE(set_color(g->g_color)); + if (hoc_color != g->g_color) { + IGNORE(hoc_set_color(g->g_color)); } IGNORE(PLOT(1, 1, 0., 0.)); for (i = 0; i < pcnt; i++) { @@ -562,8 +561,8 @@ static void plotflush(int contin) { for (i = 0; i < NPARAM; i++) { param[i] = parsav[i]; } - if (savcolor != color) { - IGNORE(set_color(savcolor)); + if (savcolor != hoc_color) { + IGNORE(hoc_set_color(savcolor)); } if (contin == 2 && pcnt > 0) { lx[0] = lx[pcnt - 1]; @@ -585,19 +584,19 @@ static void do_setup(void) { for (i = 0; i < NPARAM; i++) { parsav[i] = param[i]; } - savcolor = color; + savcolor = hoc_color; for (g = glist_head; g != (Grph*) 0; g = g->g_next) { hoc_run_stmt(g->g_setup); for (i = 0; i < NPARAM; i++) { g->g_param[i] = param[i]; } - g->g_color = color; + g->g_color = hoc_color; } for (i = 0; i < NPARAM; i++) { param[i] = parsav[i]; } - if (savcolor != color) { - IGNORE(set_color(savcolor)); + if (savcolor != hoc_color) { + IGNORE(hoc_set_color(savcolor)); } initialized = 1; } diff --git a/src/oc/code.cpp b/src/oc/code.cpp index d297dcceaa..05c157b61d 100644 --- a/src/oc/code.cpp +++ b/src/oc/code.cpp @@ -3,7 +3,6 @@ #include "backtrace_utils.h" #include "bbslsrv2.h" -#include "hoc.h" #include "cabcode.h" #include "code.h" #include "hocstr.h" @@ -75,12 +74,12 @@ using StackDatum = std::variant stack{}; #define NPROG 50000 -Inst* prog; /* the machine */ -Inst* progp; /* next free spot for code generation */ -Inst* pc; /* program counter during execution */ -Inst* progbase; /* start of current subprogram */ -Inst* prog_parse_recover; /* start after parse error */ -int hoc_returning; /* 1 if return stmt seen, 2 if break, 3 if continue */ +Inst* hoc_prog; /* the machine */ +Inst* hoc_progp; /* next free spot for code generation */ +Inst* hoc_pc; /* program counter during execution */ +Inst* hoc_progbase; /* start of current subprogram */ +Inst* hoc_prog_parse_recover; /* start after parse error */ +int hoc_returning; /* 1 if return stmt seen, 2 if break, 3 if continue */ /* 4 if stop */ namespace nrn::oc { struct frame { /* proc/func call stack frame */ @@ -424,7 +423,7 @@ void hoc_init_space() { hoc_nstack = 1000; } stack.reserve(hoc_nstack); - progp = progbase = prog = (Inst*) emalloc(sizeof(Inst) * NPROG); + hoc_progp = hoc_progbase = hoc_prog = (Inst*) emalloc(sizeof(Inst) * NPROG); fp = frame = (Frame*) emalloc(sizeof(Frame) * hoc_nframe); framelast = frame + hoc_nframe; hoc_temp_obj_pool_ = (Object**) emalloc(sizeof(Object*) * TOBJ_POOL_SIZE); @@ -462,7 +461,7 @@ void hoc_prstack() { } void hoc_on_init_register(Pfrv pf) { - /* modules that may have to be cleaned up after an execerror */ + /* modules that may have to be cleaned up after an hoc_execerror */ if (maxinitfcns < MAXINITFCNS) { initfcns[maxinitfcns++] = pf; } else { @@ -479,8 +478,8 @@ void hoc_initcode() { fprintf(stderr, "errno set %d times on last execution\n", hoc_errno_count); } hoc_errno_count = 0; - prog_parse_recover = progbase = prog; - progp = progbase; + hoc_prog_parse_recover = hoc_progbase = hoc_prog; + hoc_progp = hoc_progbase; hoc_unref_defer(); frame_objauto_recover_on_err(frame); @@ -494,9 +493,9 @@ void hoc_initcode() { tobj_count = 0; } fp = frame; - free_list(&p_symlist); + hoc_free_list(&hoc_p_symlist); hoc_returning = 0; - do_equation = 0; + hoc_do_equation = 0; for (i = 0; i < maxinitfcns; ++i) { (*initfcns[i])(); } @@ -520,17 +519,17 @@ void oc_save_code(Inst** a1, Symlist** a10, Inst** a11, int* a12) { - *a1 = progbase; - *a2 = progp; + *a1 = hoc_progbase; + *a2 = hoc_progp; a3 = stack.size(); *a4 = fp; *a5 = hoc_returning; - *a6 = do_equation; + *a6 = hoc_do_equation; *a7 = pc; *a8 = rframe; a9 = rstack; - *a10 = p_symlist; - *a11 = prog_parse_recover; + *a10 = hoc_p_symlist; + *a11 = hoc_prog_parse_recover; *a12 = tobj_count; } @@ -546,8 +545,8 @@ void oc_restore_code(Inst** a1, Symlist** a10, Inst** a11, int* a12) { - progbase = *a1; - progp = *a2; + hoc_progbase = *a1; + hoc_progp = *a2; frame_objauto_recover_on_err(*a4); if (tobj_count > *a12) { stack_obtmp_recover_on_err(*a12); @@ -563,12 +562,12 @@ void oc_restore_code(Inst** a1, stack.resize(a3); fp = *a4; hoc_returning = *a5; - do_equation = *a6; + hoc_do_equation = *a6; pc = *a7; rframe = *a8; rstack = a9; - p_symlist = *a10; - prog_parse_recover = *a11; + hoc_p_symlist = *a10; + hoc_prog_parse_recover = *a11; } int hoc_strgets_need(void) { @@ -621,16 +620,16 @@ int hoc_ParseExec(int yystart) { if (yystart) { sframe = rframe; sfp = fp; - sprogbase = progbase; - sprogp = progp; - spc = pc, sprog_parse_recover = prog_parse_recover; + sprogbase = hoc_progbase; + sprogp = hoc_progp; + spc = pc, sprog_parse_recover = hoc_prog_parse_recover; sstackp = stack.size(); sstack = rstack; - sp_symlist = p_symlist; + sp_symlist = hoc_p_symlist; rframe = fp; rstack = stack.size(); - progbase = progp; - p_symlist = (Symlist*) 0; + hoc_progbase = hoc_progp; + hoc_p_symlist = (Symlist*) 0; rinitcode(); } if (hoc_in_yyparse) { @@ -651,16 +650,16 @@ int hoc_ParseExec(int yystart) { if (yystart) { rframe = sframe; // restore the old value fp = sfp; - progbase = sprogbase; - progp = sprogp; + hoc_progbase = sprogbase; + hoc_progp = sprogp; pc = spc; - prog_parse_recover = sprog_parse_recover; + hoc_prog_parse_recover = sprog_parse_recover; if (sstackp > stack.size()) { hoc_execerror("hoc_ParseExec cannot summon entries from nowhere", nullptr); } stack.resize(sstackp); rstack = sstack; - p_symlist = sp_symlist; + hoc_p_symlist = sp_symlist; } return yret; @@ -671,18 +670,18 @@ int hoc_xopen_run(Symbol* sp, const char* str) { /*recursively parse and execute /* without executing. Note str must be a 'list'*/ int n = 0; Frame *sframe = rframe, *sfp = fp; - Inst *sprogbase = progbase, *sprogp = progp, *spc = pc, - *sprog_parse_recover = prog_parse_recover; - Symlist* sp_symlist = p_symlist; + Inst *sprogbase = hoc_progbase, *sprogp = hoc_progp, *spc = pc, + *sprog_parse_recover = hoc_prog_parse_recover; + Symlist* sp_symlist = hoc_p_symlist; std::size_t sstack{rstack}, sstackp{stack.size()}; rframe = fp; rstack = stack.size(); - progbase = progp; - p_symlist = (Symlist*) 0; + hoc_progbase = hoc_progp; + hoc_p_symlist = (Symlist*) 0; if (sp == (Symbol*) 0) { for (rinitcode(); hoc_yyparse(); rinitcode()) - execute(progbase); + hoc_execute(hoc_progbase); } else { int savpipeflag; rinitcode(); @@ -690,25 +689,25 @@ int hoc_xopen_run(Symbol* sp, const char* str) { /*recursively parse and execute hoc_pipeflag = 2; parsestr = str; if (!hoc_yyparse()) { - execerror("Nothing to parse", (char*) 0); + hoc_execerror("Nothing to parse", (char*) 0); } - n = (int) (progp - progbase); + n = (int) (hoc_progp - hoc_progbase); hoc_pipeflag = savpipeflag; hoc_define(sp); rinitcode(); } rframe = sframe; fp = sfp; - progbase = sprogbase; - progp = sprogp; + hoc_progbase = sprogbase; + hoc_progp = sprogp; pc = spc; - prog_parse_recover = sprog_parse_recover; + hoc_prog_parse_recover = sprog_parse_recover; if (sstackp > stack.size()) { hoc_execerror("hoc_xopen_run cannot summon entries from nowhere", nullptr); } stack.resize(sstackp); rstack = sstack; - p_symlist = sp_symlist; + hoc_p_symlist = sp_symlist; return n; } @@ -999,16 +998,16 @@ void hoc_varpush() { #define relative(pc) (pc + (pc)->i) -void forcode(void) { +void hoc_forcode(void) { double d; Inst* savepc = pc; /* loop body */ int isec; isec = nrn_isecstack(); - execute(savepc + 3); /* condition */ + hoc_execute(savepc + 3); /* condition */ d = hoc_xpop(); while (d) { - execute(relative(savepc)); /* body */ + hoc_execute(relative(savepc)); /* body */ if (hoc_returning) { nrn_secstack(isec); } @@ -1020,9 +1019,9 @@ void forcode(void) { break; } else /* continue */ hoc_returning = 0; - if ((savepc + 2)->i) /* diff between while and for */ - execute(relative(savepc + 2)); /* increment */ - execute(savepc + 3); + if ((savepc + 2)->i) /* diff between while and for */ + hoc_execute(relative(savepc + 2)); /* increment */ + hoc_execute(savepc + 3); d = hoc_xpop(); } if (!hoc_returning) @@ -1045,7 +1044,7 @@ void hoc_shortfor(void) { case VAR: if (!is_array(*sym)) { if (sym->subtype == USERINT) { - execerror("integer iteration variable", sym->name); + hoc_execerror("integer iteration variable", sym->name); } else if (sym->subtype == USERDOUBLE) { pval = sym->u.pval; } else { @@ -1054,22 +1053,22 @@ void hoc_shortfor(void) { break; } else { if (sym->subtype == USERINT) - execerror("integer iteration variable", sym->name); + hoc_execerror("integer iteration variable", sym->name); else if (sym->subtype == USERDOUBLE) - pval = sym->u.pval + araypt(sym, SYMBOL); + pval = sym->u.pval + hoc_araypt(sym, SYMBOL); else - pval = OPVAL(sym) + araypt(sym, OBJECTVAR); + pval = OPVAL(sym) + hoc_araypt(sym, OBJECTVAR); } break; case AUTO: { pval = &(cast(fp->argn[sym->u.u_auto])); } break; default: - execerror("for loop non-variable", sym->name); + hoc_execerror("for loop non-variable", sym->name); } isec = nrn_isecstack(); for (*pval = begin; *pval <= end; *pval += 1.) { - execute(relative(savepc)); + hoc_execute(relative(savepc)); if (hoc_returning) { nrn_secstack(isec); } @@ -1088,7 +1087,7 @@ void hoc_shortfor(void) { void hoc_iterator(void) { /* pc is ITERATOR symbol, argcount, stmtbegin, stmtend */ - /* for testing execute stmt once */ + /* for testing hoc_execute stmt once */ Symbol* sym; int argcount; Inst *stmtbegin, *stmtend; @@ -1105,7 +1104,7 @@ void hoc_iterator_object(Symbol* sym, int argcount, Inst* beginpc, Inst* endpc, fp++; if (fp >= framelast) { fp--; - execerror(sym->name, "call nested too deeply, increase with -NFRAME framesize option"); + hoc_execerror(sym->name, "call nested too deeply, increase with -NFRAME framesize option"); } fp->sp = sym; fp->nargs = argcount; @@ -1166,7 +1165,7 @@ void hoc_iterator_stmt() { pcsav = pc; isec = nrn_isecstack(); - execute(iter_f->iter_stmt_begin); + hoc_execute(iter_f->iter_stmt_begin); pc = pcsav; hoc_objectdata = hoc_objectdata_restore(obdsav); hoc_thisobject = obsav; @@ -1181,7 +1180,7 @@ void hoc_iterator_stmt() { hoc_execerror("return from within an iterator statement not allowed.", "Set a flag and use break."); case 2: /* break means return from iter */ - procret(); + hoc_procret(); break; case 3: /* continue means go on from iter as though nothing happened*/ hoc_returning = 0; @@ -1205,7 +1204,7 @@ static void for_segment2(Symbol* sym, int mode) { case VAR: if (!is_array(*sym)) { if (sym->subtype == USERINT) { - execerror("integer iteration variable", sym->name); + hoc_execerror("integer iteration variable", sym->name); } else if (sym->subtype == USERDOUBLE) { pval = sym->u.pval; } else { @@ -1214,11 +1213,11 @@ static void for_segment2(Symbol* sym, int mode) { break; } else { if (sym->subtype == USERINT) - execerror("integer iteration variable", sym->name); + hoc_execerror("integer iteration variable", sym->name); else if (sym->subtype == USERDOUBLE) - pval = sym->u.pval + araypt(sym, SYMBOL); + pval = sym->u.pval + hoc_araypt(sym, SYMBOL); else - pval = OPVAL(sym) + araypt(sym, OBJECTVAR); + pval = OPVAL(sym) + hoc_araypt(sym, OBJECTVAR); } break; case AUTO: { @@ -1227,7 +1226,7 @@ static void for_segment2(Symbol* sym, int mode) { pval = &(cast(entry)); } break; default: - execerror("for loop non-variable", sym->name); + hoc_execerror("for loop non-variable", sym->name); } imax = segment_limits(&dx); { @@ -1246,7 +1245,7 @@ static void for_segment2(Symbol* sym, int mode) { } *pval = 1.; } - execute(relative(savepc)); + hoc_execute(relative(savepc)); if (hoc_returning) { nrn_secstack(isec); } @@ -1283,31 +1282,31 @@ void for_segment1(void) { for_segment2(sym, mode); } -void ifcode(void) { +void hoc_ifcode(void) { double d; Inst* savepc = pc; /* then part */ - execute(savepc + 3); /* condition */ + hoc_execute(savepc + 3); /* condition */ d = hoc_xpop(); if (d) - execute(relative(savepc)); + hoc_execute(relative(savepc)); else if ((savepc + 1)->i) /* else part? */ - execute(relative(savepc + 1)); + hoc_execute(relative(savepc + 1)); if (!hoc_returning) pc = relative(savepc + 2); /* next stmt */ } -void Break(void) /* break statement */ +void hoc_Break(void) /* break statement */ { hoc_returning = 2; } -void Continue(void) /* continue statement */ +void hoc_Continue(void) /* continue statement */ { hoc_returning = 3; } -void Stop(void) /* stop statement */ +void hoc_Stop(void) /* stop statement */ { hoc_returning = 4; } @@ -1317,18 +1316,18 @@ void hoc_define(Symbol* sp) { /* put func/proc in symbol table */ if (sp->u.u_proc->defn.in != STOP) free((char*) sp->u.u_proc->defn.in); - free_list(&(sp->u.u_proc->list)); - sp->u.u_proc->list = p_symlist; - p_symlist = (Symlist*) 0; - sp->u.u_proc->size = (unsigned) (progp - progbase); - sp->u.u_proc->defn.in = (Inst*) emalloc((unsigned) (progp - progbase) * sizeof(Inst)); + hoc_free_list(&(sp->u.u_proc->list)); + sp->u.u_proc->list = hoc_p_symlist; + hoc_p_symlist = (Symlist*) 0; + sp->u.u_proc->size = (unsigned) (hoc_progp - hoc_progbase); + sp->u.u_proc->defn.in = (Inst*) emalloc((unsigned) (hoc_progp - hoc_progbase) * sizeof(Inst)); newinst = sp->u.u_proc->defn.in; - for (inst = progbase; inst != progp;) + for (inst = hoc_progbase; inst != hoc_progp;) *newinst++ = *inst++; - progp = progbase; /* next code starts here */ + hoc_progp = hoc_progbase; /* next code starts here */ } -// print the call sequence on an execerror +// print the call sequence on an hoc_execerror void frame_debug() { Frame* f; int i, j; @@ -1378,7 +1377,7 @@ void frame_debug() { void hoc_push_frame(Symbol* sp, int narg) { /* helpful for explicit function calls */ if (++fp >= framelast) { --fp; - execerror(sp->name, "call nested too deeply, increase with -NFRAME framesize option"); + hoc_execerror(sp->name, "call nested too deeply, increase with -NFRAME framesize option"); } fp->sp = sp; fp->nargs = narg; @@ -1386,7 +1385,7 @@ void hoc_push_frame(Symbol* sp, int narg) { /* helpful for explicit function cal fp->ob = hoc_thisobject; } -void pop_frame(void) { +void hoc_pop_frame(void) { int i; frameobj_clean(fp); for (i = 0; i < fp->nargs; i++) { @@ -1403,7 +1402,7 @@ void hoc_call() { /* for function */ if (++fp >= framelast) { --fp; - execerror(sp->name, "call nested too deeply, increase with -NFRAME framesize option"); + hoc_execerror(sp->name, "call nested too deeply, increase with -NFRAME framesize option"); } fp->sp = sp; fp->nargs = pc[1].i; @@ -1441,18 +1440,18 @@ void hoc_call() { hoc_thisobject = 0; hoc_symlist = hoc_top_level_symlist; - execute(sp->u.u_proc->defn.in); + hoc_execute(sp->u.u_proc->defn.in); hoc_objectdata = hoc_objectdata_restore(odsav); hoc_thisobject = obsav; hoc_symlist = slsav; } else { - execute(sp->u.u_proc->defn.in); + hoc_execute(sp->u.u_proc->defn.in); } /* the autoobject pointers were unreffed at the ret() */ } else { - execerror(sp->name, "undefined function"); + hoc_execerror(sp->name, "undefined function"); } if (hoc_returning) { nrn_secstack(isec); @@ -1518,23 +1517,23 @@ void hoc_ret() { hoc_returning = 1; } -void funcret(void) /* return from a function */ +void hoc_funcret(void) /* return from a function */ { double d; if (fp->sp->type != FUNCTION) - execerror(fp->sp->name, "(proc or iterator) returns value"); + hoc_execerror(fp->sp->name, "(proc or iterator) returns value"); d = hoc_xpop(); /* preserve function return value */ - ret(); + hoc_ret(); hoc_pushx(d); } -void procret(void) /* return from a procedure */ +void hoc_procret(void) /* return from a procedure */ { if (fp->sp->type == FUNCTION) - execerror(fp->sp->name, "(func) returns no value"); + hoc_execerror(fp->sp->name, "(func) returns no value"); if (fp->sp->type == HOCOBJFUNCTION) - execerror(fp->sp->name, "(obfunc) returns no value"); - ret(); + hoc_execerror(fp->sp->name, "(obfunc) returns no value"); + hoc_ret(); hoc_pushx(0.); /*will be popped immediately; necessary because caller may have compiled it as a function*/ } @@ -1543,7 +1542,7 @@ void hocobjret(void) /* return from a hoc level obfunc */ { Object** d; if (fp->sp->type != HOCOBJFUNCTION) - execerror(fp->sp->name, "objfunc returns objref"); + hoc_execerror(fp->sp->name, "objfunc returns objref"); d = hoc_objpop(); /* preserve function return value */ Object* o = *d; // safe to deref here even if d points to localobj on stack. if (o) { @@ -1552,7 +1551,7 @@ void hocobjret(void) /* return from a hoc level obfunc */ // d may point to an Object* on the stack, ie. localobj name. // if so, d after ret() would point outside the stack, // so it cannot be dereferenced without a sanitizer error on the mac. - ret(); + hoc_ret(); /*make a temp and ref it in case autoobj returned since ret would have unreffed it*/ hoc_push_object(o); @@ -1571,7 +1570,7 @@ void hoc_Numarg(void) { } else { narg = f->nargs; } - ret(); + hoc_ret(); hoc_pushx((double) narg); } @@ -1579,7 +1578,7 @@ void hoc_Argtype() { int narg, iarg, type, itype = 0; Frame* f = fp - 1; if (f == frame) { - execerror("argtype can only be called in a func or proc", 0); + hoc_execerror("argtype can only be called in a func or proc", 0); } iarg = (int) chkarg(1, -1000., 100000.); if (iarg > f->nargs || iarg < 1) { @@ -1687,7 +1686,7 @@ double hoc_opasgn(int op, double dest, double src) { } } -void argassign(void) /* store top of stack in argument */ +void hoc_argassign(void) /* store top of stack in argument */ { double d; int i, op; @@ -1755,7 +1754,7 @@ void hoc_argrefarg(void) { hoc_pushpx(pd); } -void bltin(void) /* evaluate built-in on top of stack */ +void hoc_bltin(void) /* evaluate built-in on top of stack */ { double d; d = hoc_xpop(); @@ -1771,7 +1770,7 @@ Symbol* hoc_get_symbol(const char* var) { hoc_run_stmt(prc); last = (Inst*) prc->u.u_proc->defn.in + prc->u.u_proc->size - 1; - if (last[-2].pf == eval) { + if (last[-2].pf == hoc_eval) { sym = last[-3].sym; } else if (last[-3].pf == rangepoint || last[-3].pf == rangevareval) { sym = last[-2].sym; @@ -1780,7 +1779,7 @@ Symbol* hoc_get_symbol(const char* var) { } else { sym = (Symbol*) 0; } - free_list(&sl); + hoc_free_list(&sl); return sym; } @@ -1824,7 +1823,7 @@ void hoc_autoobject(void) { /* AUTOOBJ symbol at pc+1. */ hoc_pushobj(&(cast(fp->argn[obs->u.u_auto]))); } -void eval(void) /* evaluate variable on stack */ +void hoc_eval(void) /* evaluate variable on stack */ { Objectdata* odsav; Object* obsav = 0; @@ -1843,12 +1842,12 @@ void eval(void) /* evaluate variable on stack */ } switch (sym->type) { case UNDEF: - execerror("undefined variable", sym->name); + hoc_execerror("undefined variable", sym->name); case VAR: if (!is_array(*sym)) { - if (do_equation && sym->s_varn > 0 && hoc_access[sym->s_varn] == 0) { - hoc_access[sym->s_varn] = var_access; - var_access = sym->s_varn; + if (hoc_do_equation && sym->s_varn > 0 && hoc_access[sym->s_varn] == 0) { + hoc_access[sym->s_varn] = hoc_var_access; + hoc_var_access = sym->s_varn; } switch (sym->subtype) { case USERDOUBLE: @@ -1870,16 +1869,16 @@ void eval(void) /* evaluate variable on stack */ } else { switch (sym->subtype) { case USERDOUBLE: - d = (sym->u.pval)[araypt(sym, SYMBOL)]; + d = (sym->u.pval)[hoc_araypt(sym, SYMBOL)]; break; case USERINT: - d = (sym->u.pvalint)[araypt(sym, SYMBOL)]; + d = (sym->u.pvalint)[hoc_araypt(sym, SYMBOL)]; break; case USERFLOAT: - d = (sym->u.pvalfloat)[araypt(sym, SYMBOL)]; + d = (sym->u.pvalfloat)[hoc_araypt(sym, SYMBOL)]; break; default: - d = (OPVAL(sym))[araypt(sym, OBJECTVAR)]; + d = (OPVAL(sym))[hoc_araypt(sym, OBJECTVAR)]; break; } } @@ -1888,7 +1887,7 @@ void eval(void) /* evaluate variable on stack */ d = cast(fp->argn[sym->u.u_auto]); break; default: - execerror("attempt to evaluate a non-variable", sym->name); + hoc_execerror("attempt to evaluate a non-variable", sym->name); } if (obsav) { @@ -1919,7 +1918,7 @@ void hoc_evalpointer() { } switch (sym->type) { case UNDEF: - execerror("undefined variable", sym->name); + hoc_execerror("undefined variable", sym->name); case VAR: if (!is_array(*sym)) { switch (sym->subtype) { @@ -1928,7 +1927,7 @@ void hoc_evalpointer() { break; case USERINT: case USERFLOAT: - execerror("can use pointer only to doubles", sym->name); + hoc_execerror("can use pointer only to doubles", sym->name); break; case USERPROPERTY: d = cable_prop_eval_pointer(sym); @@ -1940,14 +1939,14 @@ void hoc_evalpointer() { } else { switch (sym->subtype) { case USERDOUBLE: - d = sym->u.pval + araypt(sym, SYMBOL); + d = sym->u.pval + hoc_araypt(sym, SYMBOL); break; case USERINT: case USERFLOAT: - execerror("can use pointer only to doubles", sym->name); + hoc_execerror("can use pointer only to doubles", sym->name); break; default: - d = OPVAL(sym) + araypt(sym, OBJECTVAR); + d = OPVAL(sym) + hoc_araypt(sym, OBJECTVAR); break; } } @@ -1956,7 +1955,7 @@ void hoc_evalpointer() { d = &(cast(fp->argn[sym->u.u_auto])); } break; default: - execerror("attempt to evaluate pointer to a non-variable", sym->name); + hoc_execerror("attempt to evaluate pointer to a non-variable", sym->name); } if (obsav) { hoc_objectdata = hoc_objectdata_restore(odsav); @@ -1966,7 +1965,7 @@ void hoc_evalpointer() { hoc_pushpx(d); } -void add(void) /* add top two elems on stack */ +void hoc_add(void) /* add top two elems on stack */ { double d1, d2; d2 = hoc_xpop(); @@ -1984,7 +1983,7 @@ void hoc_sub(void) /* subtract top two elems on stack */ hoc_pushx(d1); } -void mul(void) /* multiply top two elems on stack */ +void hoc_mul(void) /* multiply top two elems on stack */ { double d1, d2; d2 = hoc_xpop(); @@ -1998,7 +1997,7 @@ void hoc_div(void) /* divide top two elems on stack */ double d1, d2; d2 = hoc_xpop(); if (d2 == 0.0) - execerror("division by zero", (char*) 0); + hoc_execerror("division by zero", (char*) 0); d1 = hoc_xpop(); d1 /= d2; hoc_pushx(d1); @@ -2010,7 +2009,7 @@ void hoc_cyclic(void) /* the modulus function */ double r, q; d2 = hoc_xpop(); if (d2 <= 0.) - execerror("a%b, b<=0", (char*) 0); + hoc_execerror("a%b, b<=0", (char*) 0); d1 = hoc_xpop(); r = d1; if (r >= d2) { @@ -2036,7 +2035,7 @@ void hoc_negate() { hoc_pushx(-d); } -void gt(void) { +void hoc_gt(void) { double d1, d2; d2 = hoc_xpop(); d1 = hoc_xpop(); @@ -2052,7 +2051,7 @@ void hoc_lt() { hoc_pushx(d1); } -void ge(void) { +void hoc_ge(void) { double d1, d2; d2 = hoc_xpop(); d1 = hoc_xpop(); @@ -2060,7 +2059,7 @@ void ge(void) { hoc_pushx(d1); } -void le(void) { +void hoc_le(void) { double d1, d2; d2 = hoc_xpop(); d1 = hoc_xpop(); @@ -2151,7 +2150,7 @@ void hoc_power() { double d1, d2; d2 = hoc_xpop(); d1 = hoc_xpop(); - d1 = Pow(d1, d2); + d1 = hoc_Pow(d1, d2); hoc_pushx(d1); } @@ -2213,28 +2212,28 @@ void hoc_assign() { int ind; switch (sym->subtype) { case USERDOUBLE: - ind = araypt(sym, SYMBOL); + ind = hoc_araypt(sym, SYMBOL); if (op) { d2 = hoc_opasgn(op, (sym->u.pval)[ind], d2); } (sym->u.pval)[ind] = d2; break; case USERINT: - ind = araypt(sym, SYMBOL); + ind = hoc_araypt(sym, SYMBOL); if (op) { d2 = hoc_opasgn(op, (double) ((sym->u.pvalint)[ind]), d2); } (sym->u.pvalint)[ind] = (int) (d2 + hoc_epsilon); break; case USERFLOAT: - ind = araypt(sym, SYMBOL); + ind = hoc_araypt(sym, SYMBOL); if (op) { d2 = hoc_opasgn(op, (double) ((sym->u.pvalfloat)[ind]), d2); } (sym->u.pvalfloat)[ind] = (float) d2; break; default: - ind = araypt(sym, OBJECTVAR); + ind = hoc_araypt(sym, OBJECTVAR); if (op) { d2 = hoc_opasgn(op, (OPVAL(sym))[ind], d2); } @@ -2250,7 +2249,7 @@ void hoc_assign() { fp->argn[sym->u.u_auto] = d2; break; default: - execerror("assignment to non-variable", sym->name); + hoc_execerror("assignment to non-variable", sym->name); } if (obsav) { hoc_objectdata = hoc_objectdata_restore(odsav); @@ -2269,7 +2268,7 @@ void hoc_assign_str(char** cpp, const char* buf) { } } -void assstr(void) { /* assign string on top to stack - 1 */ +void hoc_assstr(void) { /* assign string on top to stack - 1 */ char **ps1, **ps2; ps1 = hoc_strpop(); @@ -2371,14 +2370,14 @@ int hoc_araypt(Symbol* sp, int type) { } // pop top value from stack, print it -void print() { +void hoc_print() { nrnpy_pr("\t"); - prexpr(); + hoc_prexpr(); nrnpy_pr("\n"); } // print numeric value -void prexpr() { +void hoc_prexpr() { static HocStr* s; char* ss; Object** pob; @@ -2403,10 +2402,10 @@ void prexpr() { default: hoc_execerror("Don't know how to print this type\n", nullptr); } - plprint(s->buf); + hoc_plprint(s->buf); } -void prstr(void) /* print string value */ +void hoc_prstr(void) /* print string value */ { static HocStr* s; char** cpp; @@ -2415,7 +2414,7 @@ void prstr(void) /* print string value */ cpp = hoc_strpop(); hocstr_resize(s, strlen(*cpp) + 10); std::snprintf(s->buf, s->size + 1, "%s", *cpp); - plprint(s->buf); + hoc_plprint(s->buf); } /*-----------------------------------------------------------------*/ @@ -2451,28 +2450,28 @@ list. */ void hoc_newline(void) /* print newline */ { - plprint("\n"); + hoc_plprint("\n"); } -void varread(void) /* read into variable */ +void hoc_varread(void) /* read into variable */ { double d = 0.0; - extern NrnFILEWrap* fin; + extern NrnFILEWrap* hoc_fin; Symbol* var = (pc++)->sym; assert(var->cpublic != 2); if (!((var->type == VAR || var->type == UNDEF) && !is_array(*var) && var->subtype == NOTUSER)) { - execerror(var->name, "is not a scalar variable"); + hoc_execerror(var->name, "is not a scalar variable"); } Again: - switch (nrn_fw_fscanf(fin, "%lf", OPVAL(var))) { + switch (nrn_fw_fscanf(hoc_fin, "%lf", OPVAL(var))) { case EOF: if (hoc_moreinput()) goto Again; d = *(OPVAL(var)) = 0.0; break; case 0: - execerror("non-number read into", var->name); + hoc_execerror("non-number read into", var->name); break; default: d = 1.0; @@ -2484,64 +2483,64 @@ void varread(void) /* read into variable */ static Inst* codechk(void) { - if (progp >= prog + NPROG - 1) - execerror("procedure too big", (char*) 0); - if (zzdebug) - debugzz(progp); - return progp++; + if (hoc_progp >= hoc_prog + NPROG - 1) + hoc_execerror("procedure too big", (char*) 0); + if (hoc_zzdebug) + debugzz(hoc_progp); + return hoc_progp++; } -Inst* Code(Pfrv f) { /* install one instruction or operand */ - progp->pf = f; +Inst* hoc_Code(Pfrv f) { /* install one instruction or operand */ + hoc_progp->pf = f; return codechk(); } -Inst* codei(int f) { - progp->pf = NULL; /* zero high order bits to avoid debugzz problem */ - progp->i = f; +Inst* hoc_codei(int f) { + hoc_progp->pf = NULL; /* zero high order bits to avoid debugzz problem */ + hoc_progp->i = f; return codechk(); } Inst* hoc_codeptr(void* vp) { - progp->ptr = vp; + hoc_progp->ptr = vp; return codechk(); } -void codesym(Symbol* f) { - progp->sym = f; +void hoc_codesym(Symbol* f) { + hoc_progp->sym = f; IGNORE(codechk()); } -void codein(Inst* f) { - progp->in = f; +void hoc_codein(Inst* f) { + hoc_progp->in = f; IGNORE(codechk()); } -void insertcode(Inst* begin, Inst* end, Pfrv f) { +void hoc_insertcode(Inst* begin, Inst* end, Pfrv f) { Inst* i; for (i = end - 1; i != begin; i--) { *i = *(i - 1); } begin->pf = f; - if (zzdebug) { + if (hoc_zzdebug) { Inst* p; printf("insert code: what follows is the entire code so far\n"); - for (p = prog; p < progp; ++p) { + for (p = hoc_prog; p < hoc_progp; ++p) { debugzz(p); } printf("end of insert code debugging\n"); } } -void execute(Inst* p) /* run the machine */ +void hoc_execute(Inst* p) /* run the machine */ { Inst* pcsav; BBSPOLL for (pc = p; pc->in != STOP && !hoc_returning;) { if (hoc_intset) - execerror("interrupted", (char*) 0); + hoc_execerror("interrupted", (char*) 0); /* (*((pc++)->pf))(); DEC 5000 increments pc after the return!*/ pcsav = pc++; (*((pcsav)->pf))(); diff --git a/src/oc/code.h b/src/oc/code.h index eab311bae1..5b3a164ae7 100644 --- a/src/oc/code.h +++ b/src/oc/code.h @@ -1,25 +1,29 @@ #pragma once -#include "redef.h" -extern void nopop(void); +extern void hoc_nopop(void); extern void edit(void); -extern void eval(void); +extern void hoc_eval(void); void hoc_negate(); -extern void add(void), hoc_sub(void), mul(void), hoc_div(void), hoc_cyclic(void), power(void); +extern void hoc_add(void), hoc_sub(void), hoc_mul(void), hoc_div(void), hoc_cyclic(void), + hoc_power(void); void hoc_assign(); -extern void bltin(void), varpush(void), constpush(void), print(void), varread(void); -extern void prexpr(void), prstr(void), assstr(void), pushzero(void); +extern void hoc_bltin(void), hoc_varpush(void), hoc_constpush(void), hoc_print(void), + hoc_varread(void); +extern void hoc_prexpr(void), hoc_prstr(void), hoc_assstr(void), hoc_pushzero(void); extern void hoc_chk_sym_has_ndim(), hoc_chk_sym_has_ndim1(), hoc_chk_sym_has_ndim2(); void hoc_eq(); void hoc_lt(); -extern void gt(void), ge(void), le(void), ne(void), hoc_and(void), hoc_or(void), hoc_not(void); +extern void hoc_gt(void), hoc_ge(void), hoc_le(void), hoc_ne(void), hoc_and(void), hoc_or(void), + hoc_not(void); void hoc_arg(); -extern void ifcode(void), forcode(void), shortfor(void), call(void), argassign(void); +extern void hoc_ifcode(void), hoc_forcode(void), hoc_shortfor(void), hoc_call(void), + hoc_argassign(void); extern void hoc_argrefasgn(void), hoc_argref(void), hoc_iterator(void), hoc_iterator_stmt(void); -extern void funcret(void), procret(void), Break(void), Continue(void), Stop(void); -extern void debug(void), hoc_evalpointer(void); +extern void hoc_funcret(void), hoc_procret(void), hoc_Break(void), hoc_Continue(void), + hoc_Stop(void); +extern void hoc_debug(void), hoc_evalpointer(void); extern void hoc_newline(void), hoc_delete_symbol(void), hoc_stringarg(void), hoc_push_string(void); extern void hoc_argrefarg(void); extern void hoc_arayinstal(void); diff --git a/src/oc/code2.cpp b/src/oc/code2.cpp index 91e93fa1fb..7f158c6910 100644 --- a/src/oc/code2.cpp +++ b/src/oc/code2.cpp @@ -1,7 +1,6 @@ #include <../../nrnconf.h> /* /local/src/master/nrn/src/oc/code2.cpp,v 1.12 1999/06/08 17:48:26 hines Exp */ -#include "hoc.h" #include "hocstr.h" #include "parse.hpp" #include "hocparse.h" @@ -94,8 +93,8 @@ void hoc_Symbol_limits(void) { } assert(sym); hoc_symbol_limits(sym, *getarg(2), *getarg(3)); - ret(); - pushx(1.); + hoc_ret(); + hoc_pushx(1.); } void hoc_symbol_limits(Symbol* sym, float low, float high) { @@ -232,8 +231,8 @@ void hoc_Strcmp(void) { char *s1, *s2; s1 = gargstr(1); s2 = gargstr(2); - ret(); - pushx((double) strcmp(s1, s2)); + hoc_ret(); + hoc_pushx((double) strcmp(s1, s2)); } static int hoc_vsscanf(const char* buf); @@ -241,8 +240,8 @@ static int hoc_vsscanf(const char* buf); void hoc_sscanf(void) { int n; n = hoc_vsscanf(gargstr(1)); - ret(); - pushx((double) n); + hoc_ret(); + hoc_pushx((double) n); } static int hoc_vsscanf(const char* buf) { @@ -454,7 +453,7 @@ static int hoc_vsscanf(const char* buf) { return n; } -void System(void) { +void hoc_System(void) { extern int hoc_plttext; static char stdoutfile[] = "/systmp.tmp"; double d; @@ -472,7 +471,7 @@ void System(void) { hoc_execerror("Internal error in System(): can't open", stdoutfile); } while (fgets(st->buf, 255, fp) == st->buf) { - plprint(st->buf); + hoc_plprint(st->buf); } #endif hocstr_delete(st); @@ -505,17 +504,17 @@ void System(void) { d = (double) system(gargstr(1)); } errno = 0; - ret(); - pushx(d); + hoc_ret(); + hoc_pushx(d); } -void Xred(void) /* read with prompt string and default and limits */ +void hoc_Xred(void) /* read with prompt string and default and limits */ { double d; - d = xred(gargstr(1), *getarg(2), *getarg(3), *getarg(4)); - ret(); - pushx(d); + d = hoc_xred(gargstr(1), *getarg(2), *getarg(3), *getarg(4)); + hoc_ret(); + hoc_pushx(d); } static struct { /* symbol types */ @@ -589,15 +588,15 @@ static void symdebug(const char* s, Symlist* list) /* for debugging display the } } -void symbols(void) /* display the types above */ +void hoc_symbols(void) /* display the types above */ { int i, j; Symbol* sp; - if (zzdebug == 0) + if (hoc_zzdebug == 0) for (i = 0; type_sym[i].t_type != 0; i++) { Printf("\n%s\n", type_sym[i].name); - for (sp = symlist->first; sp != (Symbol*) 0; sp = sp->next) + for (sp = hoc_symlist->first; sp != (Symbol*) 0; sp = sp->next) if (sp->type == type_sym[i].t_type) { Printf("\t%s", sp->name); switch (sp->type) { @@ -615,11 +614,11 @@ void symbols(void) /* display the types above */ Printf("\n"); } else { - symdebug("p_symlist", p_symlist); - symdebug("symlist", symlist); + symdebug("p_symlist", hoc_p_symlist); + symdebug("symlist", hoc_symlist); } - ret(); - pushx(0.); + hoc_ret(); + hoc_pushx(0.); } double chkarg(int arg, double low, double high) /* argument checking for user functions */ @@ -757,6 +756,6 @@ void hoc_name_declared(void) { x = (s->subtype == USERPROPERTY) ? 8 : x; } } - ret(); - pushx((double) x); + hoc_ret(); + hoc_pushx((double) x); } diff --git a/src/oc/debug.cpp b/src/oc/debug.cpp index ea36b8f7eb..81cf005677 100644 --- a/src/oc/debug.cpp +++ b/src/oc/debug.cpp @@ -1,19 +1,20 @@ #include <../../nrnconf.h> /* /local/src/master/nrn/src/oc/debug.cpp,v 1.7 1996/04/09 16:39:14 hines Exp */ -#include "hoc.h" +#include "hocdec.h" #include "code.h" #include "equation.h" #include -int zzdebug; + +int hoc_zzdebug; #define prcod(c1, c2) else if (p->pf == c1) Printf("%p %p %s", p, p->pf, c2) -void debug(void) /* print the machine */ +void hoc_debug(void) /* print the machine */ { - if (zzdebug == 0) - zzdebug = 1; + if (hoc_zzdebug == 0) + hoc_zzdebug = 1; else - zzdebug = 0; + hoc_zzdebug = 0; } /* running copy of calls to execute */ @@ -22,61 +23,60 @@ void debugzz(Inst* p) { { if (p->in == STOP) Printf("STOP\n"); - prcod(nopop, "POP\n"); - prcod(eval, "EVAL\n"); - prcod(add, "ADD\n"); + prcod(hoc_nopop, "POP\n"); + prcod(hoc_eval, "EVAL\n"); + prcod(hoc_add, "ADD\n"); prcod(hoc_sub, "SUB\n"); - prcod(mul, "MUL\n"); + prcod(hoc_mul, "MUL\n"); prcod(hoc_div, "DIV\n"); prcod(hoc_negate, "NEGATE\n"); - prcod(power, "POWER\n"); + prcod(hoc_power, "POWER\n"); prcod(hoc_assign, "ASSIGN\n"); - prcod(bltin, "BLTIN\n"); - prcod(varpush, "VARPUSH\n"); - prcod(constpush, "CONSTPUSH\n"); - prcod(pushzero, "PUSHZERO\n"); - prcod(print, "PRINT\n"); - prcod(varread, "VARREAD\n"); - prcod(prexpr, "PREXPR\n"); - prcod(prstr, "PRSTR\n"); - prcod(gt, "GT\n"); + prcod(hoc_bltin, "BLTIN\n"); + prcod(hoc_varpush, "VARPUSH\n"); + prcod(hoc_constpush, "CONSTPUSH\n"); + prcod(hoc_pushzero, "PUSHZERO\n"); + prcod(hoc_print, "PRINT\n"); + prcod(hoc_varread, "VARREAD\n"); + prcod(hoc_prexpr, "PREXPR\n"); + prcod(hoc_prstr, "PRSTR\n"); + prcod(hoc_gt, "GT\n"); prcod(hoc_lt, "LT\n"); prcod(hoc_eq, "EQ\n"); - prcod(ge, "GE\n"); - prcod(le, "LE\n"); - prcod(ne, "NE\n"); + prcod(hoc_ge, "GE\n"); + prcod(hoc_le, "LE\n"); + prcod(hoc_ne, "NE\n"); prcod(hoc_and, "AND\n"); prcod(hoc_or, "OR\n"); prcod(hoc_not, "NOT\n"); - prcod(ifcode, "IFCODE\n"); - prcod(forcode, "FORCODE\n"); - prcod(shortfor, "SHORTFOR\n"); - prcod(call, "CALL\n"); + prcod(hoc_ifcode, "IFCODE\n"); + prcod(hoc_forcode, "FORCODE\n"); + prcod(hoc_shortfor, "SHORTFOR\n"); + prcod(hoc_call, "CALL\n"); prcod(hoc_arg, "ARG\n"); - prcod(argassign, "ARGASSIGN\n"); - prcod(funcret, "FUNCRET\n"); - prcod(procret, "PROCRET\n"); + prcod(hoc_argassign, "ARGASSIGN\n"); + prcod(hoc_funcret, "FUNCRET\n"); + prcod(hoc_procret, "PROCRET\n"); prcod(hocobjret, "HOCOBJRET\n"); prcod(hoc_iterator_stmt, "hoc_iterator_stmt\n"); prcod(hoc_iterator, "hoc_iterator\n"); prcod(hoc_argrefasgn, "ARGREFASSIGN\n"); prcod(hoc_argref, "ARGREF\n"); prcod(hoc_stringarg, "STRINGARG\n"); - prcod(hoc_push_string, "push_string\n"); - prcod(Break, "Break\n"); - prcod(Continue, "Continue\n"); - prcod(Stop, "Stop()\n"); - prcod(assstr, "assstr\n"); + prcod(hoc_Break, "Break\n"); + prcod(hoc_Continue, "Continue\n"); + prcod(hoc_Stop, "Stop()\n"); + prcod(hoc_assstr, "assstr\n"); prcod(hoc_evalpointer, "evalpointer\n"); prcod(hoc_newline, "newline\n"); prcod(hoc_delete_symbol, "delete_symbol\n"); prcod(hoc_cyclic, "cyclic\n"); - prcod(dep_make, "DEPENDENT\n"); - prcod(eqn_name, "EQUATION\n"); - prcod(eqn_init, "eqn_init()\n"); - prcod(eqn_lhs, "eqn_lhs()\n"); - prcod(eqn_rhs, "eqn_rhs()\n"); + prcod(hoc_dep_make, "DEPENDENT\n"); + prcod(hoc_eqn_name, "EQUATION\n"); + prcod(hoc_eqn_init, "eqn_init()\n"); + prcod(hoc_eqn_lhs, "eqn_lhs()\n"); + prcod(hoc_eqn_rhs, "eqn_rhs()\n"); /*OOP*/ prcod(hoc_push_current_object, "hoc_push_current_object\n"); prcod(hoc_objectvar, "objectvar\n"); @@ -125,8 +125,8 @@ void debugzz(Inst* p) { Printf("relative %d\n", p->i); else { offset = (size_t) (p->in) - (size_t) p; - if (offset > (size_t) prog - (size_t) p && - offset < (size_t) (&prog[2000]) - (size_t) p) + if (offset > (size_t) hoc_prog - (size_t) p && + offset < (size_t) (&hoc_prog[2000]) - (size_t) p) Printf("relative %ld\n", p->in - p); else if (p->sym->name != (char*) 0) { if (p->sym->name[0] == '\0') { diff --git a/src/oc/equation.h b/src/oc/equation.h index c5f54f17af..746a17fc1c 100644 --- a/src/oc/equation.h +++ b/src/oc/equation.h @@ -37,7 +37,8 @@ NEURON 5.3 2002/06/04 */ -extern int do_equation; /* switch for determining access to dep vars */ -extern int* hoc_access; /* links to next accessed variables */ -extern int var_access; /* variable number as pointer into access array */ -extern void eqn_name(void), eqn_init(void), eqn_lhs(void), eqn_rhs(void), dep_make(void); +extern int hoc_do_equation; /* switch for determining access to dep vars */ +extern int* hoc_access; /* links to next accessed variables */ +extern int hoc_var_access; /* variable number as pointer into access array */ +extern void hoc_eqn_name(void), hoc_eqn_init(void), hoc_eqn_lhs(void), hoc_eqn_rhs(void), + hoc_dep_make(void); diff --git a/src/oc/fileio.cpp b/src/oc/fileio.cpp index 8b59284e79..e577129480 100644 --- a/src/oc/fileio.cpp +++ b/src/oc/fileio.cpp @@ -7,7 +7,6 @@ #ifdef HAVE_UNISTD_H #include #endif -#include "hoc.h" #include "ocmisc.h" #include "hocstr.h" #include "hoclist.h" @@ -19,8 +18,8 @@ extern char* neuron_home; -NrnFILEWrap* frin; -FILE* fout; +NrnFILEWrap* hoc_frin; +FILE* hoc_fout; void hoc_stdout(void) { static int prev = -1; @@ -49,11 +48,11 @@ void hoc_stdout(void) { close(prev); prev = -1; } - ret(); - pushx((double) fileno(stdout)); + hoc_ret(); + hoc_pushx((double) fileno(stdout)); } -void ropen(void) /* open file for reading */ +void hoc_ropen(void) /* open file for reading */ { double d; const char* fname; @@ -63,25 +62,25 @@ void ropen(void) /* open file for reading */ else fname = ""; d = 1.; - if (!nrn_fw_eq(frin, stdin)) - IGNORE(nrn_fw_fclose(frin)); - frin = nrn_fw_set_stdin(); + if (!nrn_fw_eq(hoc_frin, stdin)) + IGNORE(nrn_fw_fclose(hoc_frin)); + hoc_frin = nrn_fw_set_stdin(); if (fname[0] != 0) { - if ((frin = nrn_fw_fopen(fname, "r")) == (NrnFILEWrap*) 0) { + if ((hoc_frin = nrn_fw_fopen(fname, "r")) == (NrnFILEWrap*) 0) { const char* retry; retry = expand_env_var(fname); - if ((frin = nrn_fw_fopen(retry, "r")) == (NrnFILEWrap*) 0) { + if ((hoc_frin = nrn_fw_fopen(retry, "r")) == (NrnFILEWrap*) 0) { d = 0.; - frin = nrn_fw_set_stdin(); + hoc_frin = nrn_fw_set_stdin(); } } } errno = 0; - ret(); - pushx(d); + hoc_ret(); + hoc_pushx(d); } -void wopen(void) /* open file for writing */ +void hoc_wopen(void) /* open file for writing */ { const char* fname; double d; @@ -91,19 +90,19 @@ void wopen(void) /* open file for writing */ else fname = ""; d = 1.; - if (fout != stdout) { - IGNORE(fclose(fout)); + if (hoc_fout != stdout) { + IGNORE(fclose(hoc_fout)); } - fout = stdout; + hoc_fout = stdout; if (fname[0] != 0) { - if ((fout = fopen(expand_env_var(fname), "w")) == nullptr) { + if ((hoc_fout = fopen(expand_env_var(fname), "w")) == nullptr) { d = 0.; - fout = stdout; + hoc_fout = stdout; } } errno = 0; - ret(); - pushx(d); + hoc_ret(); + hoc_pushx(d); } const char* expand_env_var(const char* s) { @@ -225,39 +224,39 @@ int hoc_xopen1(const char* name, const char* rcs) { return 0; } -void xopen(void) /* read and execute a hoc program */ +void hoc_xopen(void) /* read and execute a hoc program */ { if (ifarg(2)) { hoc_xopen1(gargstr(1), gargstr(2)); } else { hoc_xopen1(gargstr(1), 0); } - ret(); - pushx(1.); + hoc_ret(); + hoc_pushx(1.); } -void Fprint(void) /* fprintf function */ +void hoc_Fprint(void) /* fprintf function */ { char* buf; double d; hoc_sprint1(&buf, 1); - d = (double) fprintf(fout, "%s", buf); - ret(); - pushx(d); + d = (double) fprintf(hoc_fout, "%s", buf); + hoc_ret(); + hoc_pushx(d); } -void PRintf(void) /* printf function */ +void hoc_PRintf(void) /* printf function */ { char* buf; double d; hoc_sprint1(&buf, 1); d = (int) strlen(buf); - plprint(buf); + hoc_plprint(buf); fflush(stdout); - ret(); - pushx(d); + hoc_ret(); + hoc_pushx(d); } @@ -269,8 +268,8 @@ void hoc_Sprint(void) /* sprintf_function */ cpp = hoc_pgargstr(1); hoc_sprint1(&buf, 2); hoc_assign_str(cpp, buf); - ret(); - pushx(1.); + hoc_ret(); + hoc_pushx(1.); } double hoc_scan(FILE* fi) { @@ -279,7 +278,7 @@ double hoc_scan(FILE* fi) { for (;;) { if (fscanf(fi, "%255s", fs) == EOF) { - execerror("EOF in fscan", (char*) 0); + hoc_execerror("EOF in fscan", (char*) 0); } if (fs[0] == 'i' || fs[0] == 'n' || fs[0] == 'I' || fs[0] == 'N') { continue; @@ -301,7 +300,7 @@ double hoc_fw_scan(NrnFILEWrap* fi) { for (;;) { if (nrn_fw_fscanf(fi, "%255s", fs) == EOF) { - execerror("EOF in fscan", (char*) 0); + hoc_execerror("EOF in fscan", (char*) 0); } if (fs[0] == 'i' || fs[0] == 'n' || fs[0] == 'I' || fs[0] == 'N') { continue; @@ -315,19 +314,19 @@ double hoc_fw_scan(NrnFILEWrap* fi) { return d; } -void Fscan(void) /* read a number from input file */ +void hoc_Fscan(void) /* read a number from input file */ { double d; NrnFILEWrap* fi; - if (nrn_fw_eq(frin, stdin)) { - fi = fin; + if (nrn_fw_eq(hoc_frin, stdin)) { + fi = hoc_fin; } else { - fi = frin; + fi = hoc_frin; } d = hoc_fw_scan(fi); - ret(); - pushx(d); + hoc_ret(); + hoc_pushx(d); } void hoc_Getstr(void) /* read a line (or word) from input file */ @@ -336,10 +335,10 @@ void hoc_Getstr(void) /* read a line (or word) from input file */ char** cpp; NrnFILEWrap* fi; int word = 0; - if (nrn_fw_eq(frin, stdin)) { - fi = fin; + if (nrn_fw_eq(hoc_frin, stdin)) { + fi = hoc_fin; } else { - fi = frin; + fi = hoc_frin; } cpp = hoc_pgargstr(1); if (ifarg(2)) { @@ -348,16 +347,16 @@ void hoc_Getstr(void) /* read a line (or word) from input file */ if (word) { buf = hoc_tmpbuf->buf; if (nrn_fw_fscanf(fi, "%s", buf) != 1) { - execerror("EOF in getstr", (char*) 0); + hoc_execerror("EOF in getstr", (char*) 0); } } else { if ((buf = fgets_unlimited(hoc_tmpbuf, fi)) == (char*) 0) { - execerror("EOF in getstr", (char*) 0); + hoc_execerror("EOF in getstr", (char*) 0); } } hoc_assign_str(cpp, buf); - ret(); - pushx((double) strlen(buf)); + hoc_ret(); + hoc_pushx((double) strlen(buf)); } void hoc_sprint1(char** ppbuf, int argn) { /* convert args to right type for conversion */ @@ -538,18 +537,18 @@ static void hoc_load(const char* stype) { void hoc_load_proc(void) { hoc_load("proc"); - ret(); - pushx(1.); + hoc_ret(); + hoc_pushx(1.); } void hoc_load_func(void) { hoc_load("func"); - ret(); - pushx(1.); + hoc_ret(); + hoc_pushx(1.); } void hoc_load_template(void) { hoc_load("begintemplate"); - ret(); - pushx(1.); + hoc_ret(); + hoc_pushx(1.); } void hoc_load_file(void) { @@ -562,8 +561,8 @@ void hoc_load_file(void) { if (!ifarg(iarg + 1) || !hoc_lookup(gargstr(iarg + 1))) { i = hoc_Load_file(i, gargstr(iarg)); } - ret(); - pushx((double) i); + hoc_ret(); + hoc_pushx((double) i); } static constexpr auto hoc_load_file_size_ = 1024; @@ -737,8 +736,8 @@ void hoc_machine_name(void) { gethostname(buf, 20); hoc_assign_str(hoc_pgargstr(1), buf); #endif - ret(); - pushx(0.); + hoc_ret(); + hoc_pushx(0.); } int hoc_chdir(const char* path) { @@ -747,8 +746,8 @@ int hoc_chdir(const char* path) { void hoc_Chdir(void) { int i = hoc_chdir(gargstr(1)); - ret(); - pushx((double) i); + hoc_ret(); + hoc_pushx((double) i); } int nrn_is_python_extension; diff --git a/src/oc/ftime.cpp b/src/oc/ftime.cpp index 7a6daac9fb..731038e899 100644 --- a/src/oc/ftime.cpp +++ b/src/oc/ftime.cpp @@ -1,6 +1,7 @@ -#include "hoc.h" +#include "oc_ansi.h" #include + static double start_time = 0.; double nrn_time() { diff --git a/src/oc/functabl.cpp b/src/oc/functabl.cpp index cb4f430419..c8aa452989 100644 --- a/src/oc/functabl.cpp +++ b/src/oc/functabl.cpp @@ -1,5 +1,7 @@ #include <../../nrnconf.h> -#include "hoc.h" + +#include "hocdec.h" +#include "oc_ansi.h" struct TableArg { int nsize; diff --git a/src/oc/hoc.cpp b/src/oc/hoc.cpp index bde25d2c8e..407054e561 100644 --- a/src/oc/hoc.cpp +++ b/src/oc/hoc.cpp @@ -3,7 +3,6 @@ #endif #include <../../nrnconf.h> -#include "hoc.h" #include "hocstr.h" #include "equation.h" #include @@ -112,7 +111,7 @@ extern void add_history(const char*); #endif int nrn_nobanner_; -int pipeflag; +int hoc_pipeflag; int hoc_usegui; #if 1 /* no longer necessary to distinguish signed from unsigned since EOF @@ -132,8 +131,8 @@ int hoc_usegui; HocStr* hoc_tmpbuf; HocStr* hoc_cbufstr; const char* hoc_promptstr; -static CHAR* cbuf; -CHAR* ctp; +static CHAR* hoc_cbuf; +CHAR* hoc_ctp; int hoc_ictp; extern const char* RCS_hoc_version; @@ -146,18 +145,18 @@ extern int hoc_print_first_instance; used to be a FILE* but had fopen problems when 128K cores on BG/P tried to fopen the same file for reading at once. */ -NrnFILEWrap* fin; /* input file pointer */ +NrnFILEWrap* hoc_fin; /* input file pointer */ #include const char* progname; /* for error messages */ -int lineno; +int hoc_lineno; #if HAVE_EXECINFO_H #include #endif #include int hoc_intset; /* safer interrupt handling */ -int indef; +int hoc_indef; const char* infile; /* input file name */ extern size_t hoc_xopen_file_size_; extern char* hoc_xopen_file_; @@ -205,13 +204,13 @@ int getnb(void) /* get next non-white character */ int c; /*EMPTY*/ - while ((c = Getc(fin)) == ' ' || c == '\t') { + while ((c = Getc(hoc_fin)) == ' ' || c == '\t') { ; } return c; } -/* yylex modified to return -3 when at end of cbuf. The parser can +/* yylex modified to return -3 when at end of hoc_cbuf. The parser can return and take up where it left off later. Supported by modification of bison.simple to allow event driven programming. */ @@ -228,10 +227,10 @@ static int eos; static char* optarray(char* buf) { int c; - if ((c = Getc(fin)) == '[') { + if ((c = Getc(hoc_fin)) == '[') { char* s = buf + strlen(buf); *s++ = c; - while (isdigit(c = Getc(fin)) && (s - buf) < 200) { + while (isdigit(c = Getc(hoc_fin)) && (s - buf) < 200) { *s++ = c; } if (c == ']') { @@ -239,10 +238,10 @@ static char* optarray(char* buf) { *s = '\0'; } else { *s = '\0'; - acterror(buf, " not literal name[int]"); + hoc_acterror(buf, " not literal name[int]"); } } else { - unGetc(c, fin); + unGetc(c, hoc_fin); } return buf; } @@ -266,12 +265,12 @@ int yylex(void) /* hoc6 */ } if (c == '/' && follow('*', 1, 0)) /* comment */ { - while ((c = Getc(fin)) != '*' || follow('/', 0, 1)) { + while ((c = Getc(hoc_fin)) != '*' || follow('/', 0, 1)) { if (c == EOF) return (0); /* if (c == YYNEEDMORE) {*/ if (eos) { - acterror("comment not complete", " in cbuf"); + hoc_acterror("comment not complete", " in hoc_cbuf"); } } goto restart; @@ -280,35 +279,35 @@ int yylex(void) /* hoc6 */ { char* npt; double d; - IGNORE(unGetc(c, fin)); - npt = (char*) ctp; + IGNORE(unGetc(c, hoc_fin)); + npt = (char*) hoc_ctp; /*EMPTY*/ - while (isdigit(c = Getc(fin))) { + while (isdigit(c = Getc(hoc_fin))) { ; } if (c == '.') { /*EMPTY*/ - while (isdigit(c = Getc(fin))) { + while (isdigit(c = Getc(hoc_fin))) { ; } } if (*npt == '.' && !isdigit(npt[1])) { - IGNORE(unGetc(c, fin)); + IGNORE(unGetc(c, hoc_fin)); return (int) (*npt); } if (c == 'E' || c == 'e') { - if (isdigit(c = Getc(fin)) || c == '+' || c == '-') { + if (isdigit(c = Getc(hoc_fin)) || c == '+' || c == '-') { /*EMPTY*/ - while (isdigit(c = Getc(fin))) { + while (isdigit(c = Getc(hoc_fin))) { ; } } } - IGNORE(unGetc(c, fin)); + IGNORE(unGetc(c, hoc_fin)); IGNORE(sscanf(npt, "%lf", &d)); if (d == 0.) return NUMZERO; - yylval.sym = install("", NUMBER, d, &p_symlist); + yylval.sym = hoc_install("", NUMBER, d, &hoc_p_symlist); return NUMBER; } if (isalpha(c) || c == '_') { @@ -320,8 +319,8 @@ int yylex(void) /* hoc6 */ hoc_execerror("Name too long:", sbuf); } *p++ = c; - } while ((c = Getc(fin)) != EOF && (isalnum(c) || c == '_')); - IGNORE(unGetc(c, fin)); + } while ((c = Getc(hoc_fin)) != EOF && (isalnum(c) || c == '_')); + IGNORE(unGetc(c, hoc_fin)); *p = '\0'; if (strncmp(sbuf, "__nrnsec_0x", 11) == 0) { yylval.ptr = hoc_sec_internal_name2ptr(sbuf, 1); @@ -349,8 +348,8 @@ int yylex(void) /* hoc6 */ if (nrn_parsing_pysec_) { yylval.ptr = hoc_pysec_name2ptr(optarray(sbuf), 1); if (nrn_parsing_pysec_ > (void*) 1) { /* there will be a second part */ - c = Getc(fin); - unGetc(c, fin); + c = Getc(hoc_fin); + unGetc(c, hoc_fin); if (c != '.') { /* so there must be a . */ nrn_parsing_pysec_ = NULL; hoc_acterror( @@ -366,8 +365,8 @@ int yylex(void) /* hoc6 */ return PYSECNAME; } } - if ((s = lookup(sbuf)) == 0) - s = install(sbuf, UNDEF, 0.0, &symlist); + if ((s = hoc_lookup(sbuf)) == 0) + s = hoc_install(sbuf, UNDEF, 0.0, &hoc_symlist); yylval.sym = s; return s->type == UNDEF ? VAR : s->type; } @@ -384,11 +383,11 @@ int yylex(void) /* hoc6 */ yylval.narg = 0; return retval; } - while (isdigit(c = Getc(fin))) + while (isdigit(c = Getc(hoc_fin))) n = 10 * n + c - '0'; - IGNORE(unGetc(c, fin)); + IGNORE(unGetc(c, hoc_fin)); if (n == 0) - acterror("strange $...", (char*) 0); + hoc_acterror("strange $...", (char*) 0); yylval.narg = n; return retval; } @@ -400,9 +399,9 @@ int yylex(void) /* hoc6 */ if (!sbuf) { sbuf = hocstr_create(256); } - for (p = sbuf->buf; (c = Getc(fin)) != '"'; p++) { + for (p = sbuf->buf; (c = Getc(hoc_fin)) != '"'; p++) { if (c == '\n' || c == EOF || c == YYNEEDMORE) - acterror("missing quote", ""); + hoc_acterror("missing quote", ""); n = p - sbuf->buf; if (n >= sbuf->size - 1) { hocstr_resize(sbuf, n + 200); @@ -411,7 +410,7 @@ int yylex(void) /* hoc6 */ *p = backslash(c); } *p = 0; - yylval.sym = install("", CSTRING, 0.0, &p_symlist); + yylval.sym = hoc_install("", CSTRING, 0.0, &hoc_p_symlist); (yylval.sym)->u.cstr = (char*) emalloc((unsigned) (strlen(sbuf->buf) + 1)); Strcpy((yylval.sym)->u.cstr, sbuf->buf); @@ -445,7 +444,7 @@ int yylex(void) /* hoc6 */ if (follow('=', EQ, '=') == EQ) { return EQ; } - if (do_equation) { + if (hoc_do_equation) { return EQNEQ; } yylval.narg = 0; @@ -469,8 +468,8 @@ int yylex(void) /* hoc6 */ return '\n'; case '/': if (follow('/', 1, 0)) { - while (*ctp) { - ++ctp; + while (*hoc_ctp) { + ++hoc_ctp; } return '\n'; } else if (follow('=', 1, 0)) { @@ -488,7 +487,7 @@ static int backslash(int c) { /* get next char with \'s interpreted */ static char transtab[] = "b\bf\fn\nr\rt\t"; if (c != '\\') return c; - c = Getc(fin); + c = Getc(hoc_fin); if (islower(c) && strchr(transtab, c)) return strchr(transtab, c)[1]; return c; @@ -496,21 +495,21 @@ static int backslash(int c) { /* get next char with \'s interpreted */ static int follow(int expect, int ifyes, int ifno) /* look ahead for >=, etc. */ { - int c = Getc(fin); + int c = Getc(hoc_fin); if (c == expect) return ifyes; - IGNORE(unGetc(c, fin)); + IGNORE(unGetc(c, hoc_fin)); return ifno; } -void arayinstal(void) /* allocate storage for arrays */ +void hoc_arayinstal(void) /* allocate storage for arrays */ { int i, nsub; Symbol* sp; - nsub = (pc++)->i; - sp = spop(); + nsub = (hoc_pc++)->i; + sp = hoc_spop(); hoc_freearay(sp); sp->type = VAR; @@ -527,7 +526,7 @@ void arayinstal(void) /* allocate storage for arrays */ int hoc_arayinfo_install(Symbol* sp, int nsub) { double total, subscpt; int i; - free_arrayinfo(sp->arayinfo); + hoc_free_arrayinfo(sp->arayinfo); sp->arayinfo = (Arrayinfo*) emalloc((unsigned) (sizeof(Arrayinfo) + nsub * sizeof(int))); /*printf("emalloc arrayinfo at %lx\n", sp->arayinfo);*/ sp->arayinfo->a_varn = (unsigned*) 0; @@ -535,9 +534,9 @@ int hoc_arayinfo_install(Symbol* sp, int nsub) { sp->arayinfo->refcount = 1; total = 1.; while (nsub) { - subscpt = floor(xpop() + EPS); + subscpt = floor(hoc_xpop() + EPS); if (subscpt <= 0.) - execerror("subscript < 1", sp->name); + hoc_execerror("subscript < 1", sp->name); total = total * subscpt; sp->arayinfo->sub[--nsub] = (int) subscpt; } @@ -551,11 +550,11 @@ int hoc_arayinfo_install(Symbol* sp, int nsub) { */ free((char*) sp->arayinfo); sp->arayinfo = (Arrayinfo*) 0; - execerror(sp->name, ":total subscript too large"); + hoc_execerror(sp->name, ":total subscript too large"); } if (OPARINFO(sp)) { /* probably never get here */ - free_arrayinfo(OPARINFO(sp)); + hoc_free_arrayinfo(OPARINFO(sp)); } OPARINFO(sp) = sp->arayinfo; ++sp->arayinfo->refcount; @@ -569,13 +568,13 @@ void hoc_freearay(Symbol* sp) { hoc_free_val_array(OPVAL(sp), hoc_total_array(sp)); sp->type = UNDEF; } - free_arrayinfo(*pa); - free_arrayinfo(sp->arayinfo); + hoc_free_arrayinfo(*pa); + hoc_free_arrayinfo(sp->arayinfo); sp->arayinfo = (Arrayinfo*) 0; *pa = (Arrayinfo*) 0; } -void free_arrayinfo(Arrayinfo* a) { +void hoc_free_arrayinfo(Arrayinfo* a) { if (a != (Arrayinfo*) 0) { if ((--a->refcount) <= 0) { if (a->a_varn != (unsigned*) 0) @@ -586,9 +585,9 @@ void free_arrayinfo(Arrayinfo* a) { } } -void defnonly(const char* s) { /* warn if illegal definition */ - if (!indef) - acterror(s, "used outside definition"); +void hoc_defnonly(const char* s) { /* warn if illegal definition */ + if (!hoc_indef) + hoc_acterror(s, "used outside definition"); } /* messages can turned off but the user had better check the return @@ -599,8 +598,8 @@ void hoc_show_errmess_always(void) { double x; x = chkarg(1, 0., 1.); debug_message_ = (int) x; - ret(); - pushx(x); + hoc_ret(); + hoc_pushx(x); } int hoc_execerror_messages; @@ -664,7 +663,7 @@ void onintr(int /* sig */) /* catch interrupt */ /*ARGSUSED*/ stoprun = 1; if (hoc_intset++) - execerror("interrupted", (char*) 0); + hoc_execerror("interrupted", (char*) 0); IGNORE(signal(SIGINT, onintr)); } @@ -672,8 +671,8 @@ static int coredump; void hoc_coredump_on_error(void) { coredump = 1; - ret(); - pushx(1.); + hoc_ret(); + hoc_pushx(1.); } void print_bt() { @@ -742,7 +741,7 @@ void fpecatch(int /* sig */) /* catch floating point exceptions */ abort(); } signal(SIGFPE, fpecatch); - execerror("Floating point exception.", (char*) 0); + hoc_execerror("Floating point exception.", (char*) 0); } __attribute__((noreturn)) void sigsegvcatch(int /* sig */) /* segmentation violation probably due to @@ -754,7 +753,7 @@ __attribute__((noreturn)) void sigsegvcatch(int /* sig */) /* segmentation viola if (coredump) { abort(); } - execerror("Aborting.", (char*) 0); + hoc_execerror("Aborting.", (char*) 0); } #if HAVE_SIGBUS @@ -765,7 +764,7 @@ __attribute__((noreturn)) void sigbuscatch(int /* sig */) { if (coredump) { abort(); } - execerror("Aborting. ", "See $NEURONHOME/lib/help/oc.help"); + hoc_execerror("Aborting. ", "See $NEURONHOME/lib/help/oc.help"); } #endif @@ -780,8 +779,8 @@ int hoc_main1_inited_; /* has got to be called first. oc can only be event driven after this returns */ void hoc_main1_init(const char* pname, const char** envp) { - extern NrnFILEWrap* frin; - extern FILE* fout; + extern NrnFILEWrap* hoc_frin; + extern FILE* hoc_fout; if (!hoc_xopen_file_) { hoc_xopen_file_size_ = 200; @@ -791,7 +790,7 @@ void hoc_main1_init(const char* pname, const char** envp) { hoc_promptstr = "oc>"; yystart = 1; - lineno = 0; + hoc_lineno = 0; if (hoc_main1_inited_) { return; } @@ -810,10 +809,10 @@ void hoc_main1_init(const char* pname, const char** envp) { } hoc_tmpbuf = hocstr_create(TMPBUFSIZE); hoc_cbufstr = hocstr_create(CBUFSIZE); - cbuf = hoc_cbufstr->buf; - ctp = cbuf; - frin = nrn_fw_set_stdin(); - fout = stdout; + hoc_cbuf = hoc_cbufstr->buf; + hoc_ctp = hoc_cbuf; + hoc_frin = nrn_fw_set_stdin(); + hoc_fout = stdout; if (!nrn_is_cable()) { Fprintf(stderr, "OC INTERPRETER %s %s\n", RCS_hoc_version, RCS_hoc_date); Fprintf(stderr, @@ -1038,15 +1037,15 @@ static const char* double_at2space(const char* infile) { #endif /*MINGW*/ int hoc_moreinput() { - if (pipeflag) { - pipeflag = 0; + if (hoc_pipeflag) { + hoc_pipeflag = 0; return 1; } #if defined(WIN32) /* like mswin, do not need a '-' after hoc files, but ^D works */ if (gargc == 0 && cygonce == 0) { cygonce = 1; - fin = nrn_fw_set_stdin(); + hoc_fin = nrn_fw_set_stdin(); infile = 0; hoc_xopen_file_[0] = 0; #if defined(USE_PYTHON) @@ -1056,10 +1055,10 @@ int hoc_moreinput() { #endif } #endif // WIN32 - if (fin && !nrn_fw_eq(fin, stdin)) { - IGNORE(nrn_fw_fclose(fin)); + if (hoc_fin && !nrn_fw_eq(hoc_fin, stdin)) { + IGNORE(nrn_fw_fclose(hoc_fin)); } - fin = nrn_fw_set_stdin(); + hoc_fin = nrn_fw_set_stdin(); infile = 0; hoc_xopen_file_[0] = 0; if (gargc-- <= 0) { @@ -1085,7 +1084,7 @@ int hoc_moreinput() { it back */ infile = double_at2space(infile); #endif - lineno = 0; + hoc_lineno = 0; #if defined(USE_PYTHON) if (use_python_interpreter) { /* deal only with .hoc files. The hoc files are intended @@ -1098,7 +1097,7 @@ int hoc_moreinput() { } #endif if (strcmp(infile, "-") == 0) { - fin = nrn_fw_set_stdin(); + hoc_fin = nrn_fw_set_stdin(); infile = 0; hoc_xopen_file_[0] = 0; } else if (strcmp(infile, "-parallel") == 0) { @@ -1118,7 +1117,7 @@ int hoc_moreinput() { std::snprintf(hs->buf, hs->size + 1, "%s\n", infile); /* now infile is a hoc statement */ hpfi = hoc_print_first_instance; - fin = (NrnFILEWrap*) 0; + hoc_fin = (NrnFILEWrap*) 0; hoc_print_first_instance = 0; // This is processing HOC code via -c on the commandline. That HOC code could include // nrnpython(...), so the Python interpreter needs to be configured appropriately for @@ -1141,7 +1140,7 @@ int hoc_moreinput() { hoc_execerror("Python error", infile); } return hoc_moreinput(); - } else if ((fin = nrn_fw_fopen(infile, "r")) == (NrnFILEWrap*) 0) { + } else if ((hoc_fin = nrn_fw_fopen(infile, "r")) == (NrnFILEWrap*) 0) { Fprintf(stderr, "%d %s: can't open %s\n", nrnmpi_myid_world, progname, infile); #if NRNMPI if (nrnmpi_numprocs_world > 1) { @@ -1300,14 +1299,14 @@ static int hoc_run1() { static const char* nrn_inputbufptr; static void nrn_inputbuf_getline(void) { CHAR* cp; - cp = ctp = cbuf = hoc_cbufstr->buf; + cp = hoc_ctp = hoc_cbuf = hoc_cbufstr->buf; while (*nrn_inputbufptr) { *cp++ = *nrn_inputbufptr++; if (cp[-1] == '\n') { break; } } - if (cp != ctp) { + if (cp != hoc_ctp) { if (cp[-1] != '\n') { *cp++ = '\n'; } @@ -1318,15 +1317,15 @@ static void nrn_inputbuf_getline(void) { // used by ocjump.cpp void oc_save_input_info(const char** i1, int* i2, int* i3, NrnFILEWrap** i4) { *i1 = nrn_inputbufptr; - *i2 = pipeflag; - *i3 = lineno; - *i4 = fin; + *i2 = hoc_pipeflag; + *i3 = hoc_lineno; + *i4 = hoc_fin; } void oc_restore_input_info(const char* i1, int i2, int i3, NrnFILEWrap* i4) { nrn_inputbufptr = i1; - pipeflag = i2; - lineno = i3; - fin = i4; + hoc_pipeflag = i2; + hoc_lineno = i3; + hoc_fin = i4; } int hoc_oc(const char* buf) { @@ -1370,7 +1369,7 @@ int hoc_oc(const char* buf, std::ostream& os) { return 0; } -void warning(const char* s, const char* t) /* print warning message */ +void hoc_warning(const char* s, const char* t) /* print warning message */ { CHAR* cp; char id[10]; @@ -1386,44 +1385,44 @@ void warning(const char* s, const char* t) /* print warning message */ Fprintf(stderr, "%s%s: %s\n", id, progname, s); } if (hoc_xopen_file_ && hoc_xopen_file_[0]) { - Fprintf(stderr, "%s in %s near line %d\n", id, hoc_xopen_file_, lineno); + Fprintf(stderr, "%s in %s near line %d\n", id, hoc_xopen_file_, hoc_lineno); } else { - Fprintf(stderr, "%s near line %d\n", id, lineno); + Fprintf(stderr, "%s near line %d\n", id, hoc_lineno); } - n = strlen(cbuf); - for (cp = cbuf; cp < (cbuf + n); ++cp) { + n = strlen(hoc_cbuf); + for (cp = hoc_cbuf; cp < (hoc_cbuf + n); ++cp) { if (!isprint((int) (*cp)) && !isspace((int) (*cp))) { Fprintf(stderr, "%scharacter \\%03o at position %ld is not printable\n", id, ((int) (*cp) & 0xff), - cp - cbuf); + cp - hoc_cbuf); break; } } - Fprintf(stderr, "%s %s", id, cbuf); + Fprintf(stderr, "%s %s", id, hoc_cbuf); if (nrnmpi_numprocs_world > 0) { - for (cp = cbuf; cp != ctp; cp++) { + for (cp = hoc_cbuf; cp != hoc_ctp; cp++) { Fprintf(stderr, " "); } Fprintf(stderr, "^\n"); } - ctp = cbuf; - *ctp = '\0'; + hoc_ctp = hoc_cbuf; + *hoc_ctp = '\0'; } static int Getc(NrnFILEWrap* fp) { /*ARGSUSED*/ - if (*ctp) { + if (*hoc_ctp) { ++hoc_ictp; - return *ctp++; + return *hoc_ctp++; } #if 0 /* don't allow parser to block. Actually partial statements were never allowed anyway */ - if (!pipeflag && nrn_fw_eq(fp,stdin)) { + if (!hoc_pipeflag && nrn_fw_eq(fp,stdin)) { eos = 1; return 0; } @@ -1432,13 +1431,13 @@ allowed anyway */ if (hoc_get_line() == EOF) { return EOF; } - return *ctp++; + return *hoc_ctp++; } static void unGetc(int c, NrnFILEWrap* fp) { /*ARGSUSED*/ - if (c != EOF && c && ctp != cbuf) { - *(--ctp) = c; + if (c != EOF && c && hoc_ctp != hoc_cbuf) { + *(--hoc_ctp) = c; } } @@ -1458,8 +1457,8 @@ int hoc_yyparse(void) { instead of blocking in yylex. If so another call to yyparse will take up exactly where it left off. This makes it easier to support event driven processing. - Maybe it's time to redo the get_line process which fills cbuf with - the next line to read. A real event driven program would fill cbuf + Maybe it's time to redo the get_line process which fills hoc_cbuf with + the next line to read. A real event driven program would fill hoc_cbuf and then call yyparse() directly. yyparse() returns 0 : end of file '\n' : ready to execute a command @@ -1628,27 +1627,27 @@ static CHAR* fgets_unlimited_nltrans(HocStr* bufstr, NrnFILEWrap* f, int nltrans return (CHAR*) 0; } -int hoc_get_line(void) { /* supports re-entry. fill cbuf with next line */ - if (*ctp) { +int hoc_get_line(void) { /* supports re-entry. fill hoc_cbuf with next line */ + if (*hoc_ctp) { hoc_execerror("Internal error:", "Not finished with previous input line"); } - ctp = cbuf = hoc_cbufstr->buf; - *ctp = '\0'; - if (pipeflag == 3) { + hoc_ctp = hoc_cbuf = hoc_cbufstr->buf; + *hoc_ctp = '\0'; + if (hoc_pipeflag == 3) { nrn_inputbuf_getline(); - if (*ctp == '\0') { + if (*hoc_ctp == '\0') { return EOF; } - } else if (pipeflag) { + } else if (hoc_pipeflag) { if (hoc_strgets_need() > hoc_cbufstr->size) { hocstr_resize(hoc_cbufstr, hoc_strgets_need() + 100); } - if (hoc_strgets(cbuf, CBUFSIZE - 1) == (char*) 0) { + if (hoc_strgets(hoc_cbuf, CBUFSIZE - 1) == (char*) 0) { return EOF; } } else { #if READLINE - if (nrn_fw_eq(fin, stdin) && nrn_istty_) { + if (nrn_fw_eq(hoc_fin, stdin) && nrn_istty_) { char* line; int n; #if INTERVIEWS @@ -1693,47 +1692,47 @@ int hoc_get_line(void) { /* supports re-entry. fill cbuf with next line */ } if (n >= hoc_cbufstr->size - 3) { hocstr_resize(hoc_cbufstr, n + 100); - ctp = cbuf = hoc_cbufstr->buf; + hoc_ctp = hoc_cbuf = hoc_cbufstr->buf; } - strcpy(cbuf, line); - cbuf[n] = '\n'; - cbuf[n + 1] = '\0'; + strcpy(hoc_cbuf, line); + hoc_cbuf[n] = '\n'; + hoc_cbuf[n + 1] = '\0'; if (line && *line) { add_history(line); } free(line); - hoc_audit_command(cbuf); + hoc_audit_command(hoc_cbuf); } else { fflush(stdout); - if (hoc_fgets_unlimited(hoc_cbufstr, fin) == (CHAR*) 0) { + if (hoc_fgets_unlimited(hoc_cbufstr, hoc_fin) == (CHAR*) 0) { return EOF; } } #else // READLINE #if INTERVIEWS - if (nrn_fw_eq(fin, stdin) && hoc_interviews && !hoc_in_yyparse) { + if (nrn_fw_eq(hoc_fin, stdin) && hoc_interviews && !hoc_in_yyparse) { run_til_stdin()); } #endif // INTERVIEWS #if defined(WIN32) - if (nrn_fw_eq(fin, stdin)) { - if (gets(cbuf) == (char*) 0) { + if (nrn_fw_eq(hoc_fin, stdin)) { + if (gets(hoc_cbuf) == (char*) 0) { /*DebugMessage("gets returned NULL\n");*/ return EOF; } - strcat(cbuf, "\n"); + strcat(hoc_cbuf, "\n"); } else #endif // WIN32 { - if (hoc_fgets_unlimited(hoc_cbufstr, fin) == (char*) 0) { + if (hoc_fgets_unlimited(hoc_cbufstr, hoc_fin) == (char*) 0) { return EOF; } } #endif // READLINE } errno = 0; - lineno++; - ctp = cbuf = hoc_cbufstr->buf; + hoc_lineno++; + hoc_ctp = hoc_cbuf = hoc_cbufstr->buf; hoc_ictp = 0; return 1; } @@ -1741,7 +1740,7 @@ int hoc_get_line(void) { /* supports re-entry. fill cbuf with next line */ void hoc_help(void) { #if INTERVIEWS if (hoc_interviews) { - ivoc_help(cbuf); + ivoc_help(hoc_cbuf); } else #endif { @@ -1749,5 +1748,5 @@ void hoc_help(void) { hoc_warning("Help only available from version with ivoc library", 0); } } - ctp = cbuf + strlen(cbuf) - 1; + hoc_ctp = hoc_cbuf + strlen(hoc_cbuf) - 1; } diff --git a/src/oc/hoc.h b/src/oc/hoc.h index b28db7ee01..01597cd1dc 100755 --- a/src/oc/hoc.h +++ b/src/oc/hoc.h @@ -1,3 +1,2 @@ #pragma once -#include "redef.h" #include "hocdec.h" diff --git a/src/oc/hoc_init.cpp b/src/oc/hoc_init.cpp index b04281f334..719d712590 100644 --- a/src/oc/hoc_init.cpp +++ b/src/oc/hoc_init.cpp @@ -1,9 +1,7 @@ #include <../../nrnconf.h> /* /local/src/master/nrn/src/oc/hoc_init.cpp,v 1.25 1999/11/08 17:48:58 hines Exp */ -#include "hoc.h" #include "parse.hpp" -#include #include "equation.h" #include "nrnunits.h" @@ -12,6 +10,8 @@ #include "oc_mcran4.hpp" +#include + extern void hoc_nrnmpi_init(); #if PVM @@ -87,11 +87,11 @@ static struct { /* Built-ins */ {"cos", cos}, {"atan", atan}, {"tanh", tanh}, - {"log", Log}, /* checks argument */ - {"log10", Log10}, /* checks argument */ - {"exp", hoc1_Exp}, /* checks argument */ - {"sqrt", Sqrt}, /* checks argument */ - {"int", integer}, + {"log", hoc_Log}, /* checks argument */ + {"log10", hoc_Log10}, /* checks argument */ + {"exp", hoc1_Exp}, /* checks argument */ + {"sqrt", hoc_Sqrt}, /* checks argument */ + {"int", hoc_integer}, {"abs", fabs}, {"erf", erf}, {"erfc", erfc}, @@ -252,32 +252,32 @@ void hoc_init(void) /* install constants and built-ins table */ extern void hoc_init_space(void); hoc_init_space(); for (i = 0; keywords[i].name; i++) - IGNORE(install(keywords[i].name, keywords[i].kval, 0.0, &symlist)); + IGNORE(hoc_install(keywords[i].name, keywords[i].kval, 0.0, &hoc_symlist)); for (i = 0; consts[i].name; i++) { - s = install(consts[i].name, UNDEF, consts[i].cval, &symlist); + s = hoc_install(consts[i].name, UNDEF, consts[i].cval, &hoc_symlist); s->type = VAR; s->u.pval = &consts[i].cval; s->subtype = USERDOUBLE; } for (i = 0; builtins[i].name; i++) { - s = install(builtins[i].name, BLTIN, 0.0, &symlist); + s = hoc_install(builtins[i].name, BLTIN, 0.0, &hoc_symlist); s->u.ptr = builtins[i].func; } for (i = 0; fun_bltin[i].name; i++) { - s = install(fun_bltin[i].name, FUN_BLTIN, 0.0, &symlist); + s = hoc_install(fun_bltin[i].name, FUN_BLTIN, 0.0, &hoc_symlist); s->u.u_proc->defn.pf = fun_bltin[i].fun_blt; s->u.u_proc->nauto = 0; s->u.u_proc->nobjauto = 0; } for (i = 0; strfun_bltin[i].name; i++) { - s = install(strfun_bltin[i].name, FUN_BLTIN, 0.0, &symlist); + s = hoc_install(strfun_bltin[i].name, FUN_BLTIN, 0.0, &hoc_symlist); s->type = STRINGFUNC; s->u.u_proc->defn.pf = strfun_bltin[i].strfun_blt; s->u.u_proc->nauto = 0; s->u.u_proc->nobjauto = 0; } for (i = 0; objfun_bltin[i].name; i++) { - s = install(objfun_bltin[i].name, FUN_BLTIN, 0.0, &symlist); + s = hoc_install(objfun_bltin[i].name, FUN_BLTIN, 0.0, &hoc_symlist); s->type = OBJECTFUNC; s->u.u_proc->defn.pf = objfun_bltin[i].objfun_blt; s->u.u_proc->nauto = 0; @@ -289,20 +289,20 @@ void hoc_init(void) /* install constants and built-ins table */ hoc_install_var("hoc_cross_y_", &hoc_cross_y_); hoc_install_var("default_dll_loaded_", &hoc_default_dll_loaded_); - s = install("xopen_broadcast_", UNDEF, 0.0, &hoc_symlist); + s = hoc_install("xopen_broadcast_", UNDEF, 0.0, &hoc_symlist); s->type = VAR; s->subtype = USERINT; s->u.pvalint = &nrn_xopen_broadcast_; /* initialize pointers ( why doesn't Vax do this?) */ hoc_access = (int*) 0; - spinit(); + hoc_spinit(); hoc_class_registration(); - hoc_built_in_symlist = symlist; - symlist = (Symlist*) 0; + hoc_built_in_symlist = hoc_symlist; + hoc_symlist = (Symlist*) 0; /* start symlist and top level the same list */ - hoc_top_level_symlist = symlist = (Symlist*) emalloc(sizeof(Symlist)); - symlist->first = symlist->last = (Symbol*) 0; + hoc_top_level_symlist = hoc_symlist = (Symlist*) emalloc(sizeof(Symlist)); + hoc_symlist->first = hoc_symlist->last = (Symbol*) 0; hoc_install_hoc_obj(); } diff --git a/src/oc/hoc_oop.cpp b/src/oc/hoc_oop.cpp index 6184dc87ce..d75011831a 100644 --- a/src/oc/hoc_oop.cpp +++ b/src/oc/hoc_oop.cpp @@ -253,7 +253,7 @@ void hoc_object_push(void) { hoc_objectdata = hoc_top_level_data; } hoc_ret(); - pushx(0.); + hoc_pushx(0.); } void hoc_object_pushed(void) { @@ -280,7 +280,7 @@ void hoc_object_pop(void) { hoc_objectdata = hoc_top_level_data; } hoc_ret(); - pushx(0.); + hoc_pushx(0.); } /*-----------------------------------------------*/ int hoc_resize_toplevel(int more) { @@ -378,7 +378,7 @@ void hoc_exec_cmd(void) { /* execute string from top level or within an object c hocstr_delete(hs); } hoc_ret(); - pushx((double) (err)); + hoc_pushx((double) (err)); } /* call a function within the context of an object. Args must be on stack */ @@ -557,7 +557,7 @@ Object* hoc_newobj1(Symbol* sym, int narg) { hoc_construct_point(ob, narg); } if (ob->ctemplate->init) { - call_ob_proc(ob, ob->ctemplate->init, narg); + hoc_call_ob_proc(ob, ob->ctemplate->init, narg); } else { for (i = 0; i < narg; ++i) { hoc_nopop(); @@ -624,7 +624,7 @@ static void call_constructor(Object* ob, Symbol* sym, int narg) { obsav = hoc_thisobject; pcsav = pc; - push_frame(sym, narg); + hoc_push_frame(sym, narg); ob->u.this_pointer = neuron::oc::invoke_method_that_may_throw( [ob]() -> std::string { std::string rval{hoc_object_name(ob)}; @@ -633,7 +633,7 @@ static void call_constructor(Object* ob, Symbol* sym, int narg) { }, ob->ctemplate->constructor, ob); - pop_frame(); + hoc_pop_frame(); pc = pcsav; hoc_symlist = slsav; @@ -652,7 +652,7 @@ Object* nrn_get_gui_redirect_obj() { return gui_redirect_obj_; } -void call_ob_proc(Object* ob, Symbol* sym, int narg) { +void hoc_call_ob_proc(Object* ob, Symbol* sym, int narg) { Inst *pcsav, callcode[4]; Symlist* slsav; Objectdata* obdsav; @@ -666,7 +666,7 @@ void call_ob_proc(Object* ob, Symbol* sym, int narg) { if (ob->ctemplate->sym->subtype & CPLUSOBJECT) { hoc_thisobject = ob; gui_redirect_obj_ = ob; - push_frame(sym, narg); + hoc_push_frame(sym, narg); hoc_thisobject = obsav; auto const error_prefix_generator = [ob, sym]() { std::string rval{hoc_object_name(ob)}; @@ -701,7 +701,7 @@ void call_ob_proc(Object* ob, Symbol* sym, int narg) { } else if (ob->ctemplate->is_point_ && special_pnt_call(ob, sym, narg)) { ; /*empty since special_pnt_call did the work for get_loc, has_loc, and loc*/ } else { - callcode[0].pf = call; + callcode[0].pf = hoc_call; callcode[1].sym = sym; callcode[2].i = narg; callcode[3].in = STOP; @@ -709,7 +709,7 @@ void call_ob_proc(Object* ob, Symbol* sym, int narg) { hoc_objectdata = ob->u.dataspace; hoc_thisobject = ob; hoc_symlist = ob->ctemplate->symtable; - execute(callcode); + hoc_execute(callcode); if (sym->type == PROCEDURE) { hoc_nopop(); } @@ -820,7 +820,7 @@ void hoc_objectvar(void) { /* object variable symbol at pc+1. */ } obp = OPOBJ(obs); if (is_array(*obs)) { - hoc_pushobj(obp + araypt(obs, OBJECTVAR)); + hoc_pushobj(obp + hoc_araypt(obs, OBJECTVAR)); } else { hoc_pushobj(obp); } @@ -897,13 +897,13 @@ void hoc_object_id(void) { if (ifarg(2) && chkarg(2, 0., 1.) == 1.) { hoc_ret(); if (ob) { - pushx((double) ob->index); + hoc_pushx((double) ob->index); } else { - pushx(-1.); + hoc_pushx(-1.); } } else { hoc_ret(); - pushx((double) ((size_t) ob)); + hoc_pushx((double) ((size_t) ob)); } } @@ -944,7 +944,7 @@ static void range_suffix(Symbol* sym, int nindex, int narg) { hoc_push_ndim(nindex); } if (narg) { // push back the arc length - pushx(x); + hoc_pushx(x); } } hoc_pushi(narg); @@ -1038,8 +1038,8 @@ void hoc_object_component() { hoc_execerror_fmt("Cannot assign to a PythonObject function call '{}'", sym0->name); } - pushi(nindex); - pushs(sym0); + hoc_pushi(nindex); + hoc_pushs(sym0); hoc_push_object(obp); /* note obp is now on stack twice */ /* hpoasgn will pop both */ @@ -1084,7 +1084,7 @@ void hoc_object_component() { if (!is_array(*sym) || OPARINFO(sym)->nsub != nindex) { hoc_execerror_fmt("'{}' not right number of subscripts", sym->name); } - nindex = araypt(sym, OBJECTVAR); + nindex = hoc_araypt(sym, OBJECTVAR); } hoc_pop_defer(); hoc_pushobj(OPOBJ(sym) + nindex); @@ -1141,7 +1141,7 @@ void hoc_object_component() { sym->name); } } - nindex = araypt(sym, OBJECTVAR); + nindex = hoc_araypt(sym, OBJECTVAR); } hoc_pop_defer(); /*finally get rid of symbol */ hoc_pushpx(OPVAL(sym) + nindex); @@ -1162,7 +1162,7 @@ void hoc_object_component() { hoc_execerror_fmt("'{}' is a function not a {}-dim array", sym->name, nindex); } double d = 0.; - call_ob_proc(obp, sym, nindex); + hoc_call_ob_proc(obp, sym, nindex); if (hoc_returning) { break; } @@ -1184,7 +1184,7 @@ void hoc_object_component() { hoc_execerror_fmt("'{}' is a function not a {}-dim array", sym->name, nindex); } } - call_ob_proc(obp, sym, nindex); + hoc_call_ob_proc(obp, sym, nindex); if (hoc_returning) { break; } @@ -1202,7 +1202,7 @@ void hoc_object_component() { } case STRFUNCTION: { char** d; - call_ob_proc(obp, sym, nindex); + hoc_call_ob_proc(obp, sym, nindex); if (hoc_returning) { break; } @@ -1265,7 +1265,7 @@ void hoc_object_component() { if (!hoc_stack_type_is_ndim()) { hoc_push_ndim(nindex); } - nindex = araypt(sym, OBJECTVAR); + nindex = hoc_araypt(sym, OBJECTVAR); } hoc_pop_defer(); if (connect_obsec_) { @@ -1725,26 +1725,26 @@ void hoc_external_var(Symbol* s) { void hoc_ob_check(int type) { int t; - t = ipop(); + t = hoc_ipop(); if (type == -1) { if (t == OBJECTVAR) { /* don't bother to check */ - Code(hoc_cmp_otype); - codei(0); + hoc_Code(hoc_cmp_otype); + hoc_codei(0); } } else if (type) { if (t == OBJECTVAR) { /* must check dynamically */ #if PDEBUG printf("dymnamic checking of type=%d\n", type); #endif - Code(hoc_cmp_otype); - codei(type); + hoc_Code(hoc_cmp_otype); + hoc_codei(type); } else if (type != t) { /* static check */ hoc_execerror("Type mismatch", (char*) 0); } } else { if (t != OBJECTVAR) { - Code(hoc_known_type); - codei(t); + hoc_Code(hoc_known_type); + hoc_codei(t); } } } @@ -1910,9 +1910,9 @@ printf("unreffing %s with refcount %d\n", hoc_object_name(obj), obj->refcount); --obj->refcount; if (obj->ctemplate->unref) { int i = obj->refcount; - pushx((double) i); + hoc_pushx((double) i); ++obj->unref_recurse_cnt; - call_ob_proc(obj, obj->ctemplate->unref, 1); + hoc_call_ob_proc(obj, obj->ctemplate->unref, 1); --obj->unref_recurse_cnt; } if (obj->refcount <= 0 && obj->unref_recurse_cnt == 0) { @@ -1964,11 +1964,11 @@ static void free_objectdata(Objectdata* od, cTemplate* ctemplate) { case VAR: /*printf("free_objectdata %s\n", s->name);*/ hoc_free_val_array(OPVAL(s), hoc_total_array(s)); - free_arrayinfo(OPARINFO(s)); + hoc_free_arrayinfo(OPARINFO(s)); break; case STRING: hoc_free_pstring(OPSTR(s)); - free_arrayinfo(OPARINFO(s)); + hoc_free_arrayinfo(OPARINFO(s)); break; case OBJECTVAR: objp = OPOBJ(s); @@ -1978,7 +1978,7 @@ static void free_objectdata(Objectdata* od, cTemplate* ctemplate) { hoc_dec_refcount(objp + i); } } - free_arrayinfo(OPARINFO(s)); + hoc_free_arrayinfo(OPARINFO(s)); free(objp); break; case SECTION: @@ -1987,7 +1987,7 @@ static void free_objectdata(Objectdata* od, cTemplate* ctemplate) { sec_free(*(OPSECITM(s) + i)); } free(OPSECITM(s)); - free_arrayinfo(OPARINFO(s)); + hoc_free_arrayinfo(OPARINFO(s)); break; } } @@ -2025,7 +2025,7 @@ void hoc_allobjects(void) { hoc_allobjects1(hoc_top_level_symlist, 0); } hoc_ret(); - pushx((double) n); + hoc_pushx((double) n); } void hoc_allobjects1(Symlist* sl, int nspace) { @@ -2072,7 +2072,7 @@ static void hoc_list_allobjref(Symlist*, Objectdata*, int); void hoc_allobjectvars(void) { hoc_list_allobjref(hoc_top_level_symlist, hoc_top_level_data, 0); hoc_ret(); - pushx(0.); + hoc_pushx(0.); } static void hoc_list_allobjref(Symlist* sl, Objectdata* data, int depth) { diff --git a/src/oc/hocgetsym.h b/src/oc/hocgetsym.h index 30069ca3b9..166b8b632d 100644 --- a/src/oc/hocgetsym.h +++ b/src/oc/hocgetsym.h @@ -1,6 +1,6 @@ #pragma once -#include "hoc.h" +#include "hocdec.h" typedef struct Psym { Symbol* sym; diff --git a/src/oc/hocparse.h b/src/oc/hocparse.h index 1c0e04837e..244aebbefe 100644 --- a/src/oc/hocparse.h +++ b/src/oc/hocparse.h @@ -1,9 +1,7 @@ #pragma once -#include "hoc.h" +#include "hocdec.h" - -/* do not know why this is not in parse.hpp */ extern int yyparse(void); extern int yylex(void); diff --git a/src/oc/math.cpp b/src/oc/math.cpp index 38b73b26fa..a568087679 100644 --- a/src/oc/math.cpp +++ b/src/oc/math.cpp @@ -1,3 +1,4 @@ +#include "oc_ansi.h" #ifndef __INTEL_LLVM_COMPILER #pragma STDC FENV_ACCESS ON #endif @@ -6,13 +7,13 @@ /* a fake change */ /* /local/src/master/nrn/src/oc/math.cpp,v 1.6 1999/07/16 13:43:10 hines Exp */ -#include "hoc.h" #include "nrnmpiuse.h" #include "ocfunc.h" + #include #include -#include -#include +#include +#include #define EPS hoc_epsilon @@ -50,12 +51,12 @@ void hoc_atan2(void) { hoc_pushx(d); } -double Log(double x) { +double hoc_Log(double x) { clear_fe_except(); return errcheck(log(x), "log"); } -double Log10(double x) { +double hoc_Log10(double x) { clear_fe_except(); return errcheck(log10(x), "log10"); } @@ -95,17 +96,17 @@ double hoc1_Exp(double x) { return errcheck(exp(x), "exp"); } -double Sqrt(double x) { +double hoc_Sqrt(double x) { clear_fe_except(); return errcheck(sqrt(x), "sqrt"); } -double Pow(double x, double y) { +double hoc_Pow(double x, double y) { clear_fe_except(); return errcheck(pow(x, y), "exponentiation"); } -double integer(double x) { +double hoc_integer(double x) { if (x < 0) { return (double) (long) (x - EPS); } else { diff --git a/src/oc/mswinprt.cpp b/src/oc/mswinprt.cpp index 29dbdc9571..3dfa805a3c 100644 --- a/src/oc/mswinprt.cpp +++ b/src/oc/mswinprt.cpp @@ -142,8 +142,8 @@ void hoc_win_exec(void) { i = (int) chkarg(2, -1000, 1000); } i = WinExec(gargstr(1), i); - ret(); - pushx((double) i); + hoc_ret(); + hoc_pushx((double) i); } void hoc_winio_show(int b) {} @@ -154,17 +154,17 @@ int getpid() { void hoc_Plt() { TRY_GUI_REDIRECT_DOUBLE("plt", NULL); - ret(); - pushx(0.); + hoc_ret(); + hoc_pushx(0.); } void hoc_Setcolor() { TRY_GUI_REDIRECT_DOUBLE("setcolor", NULL); - ret(); - pushx(0.); + hoc_ret(); + hoc_pushx(0.); } void hoc_Lw() { - ret(); - pushx(0.); + hoc_ret(); + hoc_pushx(0.); } #endif // MINGW diff --git a/src/oc/nonlin.cpp b/src/oc/nonlin.cpp index 19a02361d6..467ac07349 100644 --- a/src/oc/nonlin.cpp +++ b/src/oc/nonlin.cpp @@ -1,7 +1,6 @@ #include <../../nrnconf.h> #include #include -#include "hoc.h" #include "parse.hpp" #include "hocparse.h" #include "equation.h" @@ -9,9 +8,9 @@ #include "code.h" -int do_equation; /* switch for determining access to dep vars */ -int* hoc_access; /* links to next accessed variables */ -int var_access; /* variable number as pointer into access array */ +int hoc_do_equation; /* switch for determining access to dep vars */ +int* hoc_access; /* links to next accessed variables */ +int hoc_var_access; /* variable number as pointer into access array */ static double** varble; /* pointer to symbol values */ @@ -19,13 +18,13 @@ typedef struct elm* Elm; #define diag(s) hoc_execerror(s, (char*) 0); -void dep_make(void) /* tag the variable as dependent with a variable number */ +void hoc_dep_make(void) /* tag the variable as dependent with a variable number */ { #if !OCSMALL Symbol* sym; unsigned* numpt = 0; - sym = spop(); + sym = hoc_spop(); switch (sym->type) { case UNDEF: hoc_execerror(sym->name, "undefined in dep_make"); @@ -34,7 +33,7 @@ void dep_make(void) /* tag the variable as dependent with a variable number */ *(OPVAL(sym)) = 0.; case VAR: if (sym->subtype != NOTUSER) { - execerror(sym->name, "can't be a dependent variable"); + hoc_execerror(sym->name, "can't be a dependent variable"); } if (!is_array(*sym)) { numpt = &(sym->s_varn); @@ -49,15 +48,15 @@ void dep_make(void) /* tag the variable as dependent with a variable number */ aray->a_varn = (unsigned*) ecalloc((unsigned) total, sizeof(unsigned)); sym->s_varn = (unsigned) total; /* set_varble() uses this */ } - numpt = &((aray->a_varn)[araypt(sym, OBJECTVAR)]); + numpt = &((aray->a_varn)[hoc_araypt(sym, OBJECTVAR)]); } break; default: - execerror(sym->name, "can't be a dependent variable"); + hoc_execerror(sym->name, "can't be a dependent variable"); } if (*numpt > 0) - execerror(sym->name, "made dependent twice"); + hoc_execerror(sym->name, "made dependent twice"); *numpt = ++neqn; #endif } @@ -69,7 +68,7 @@ void init_access(void) /* zero the access array */ if (hoc_access != (int*) 0) free((char*) hoc_access); hoc_access = (int*) ecalloc((neqn + 1), sizeof(int)); - var_access = -1; + hoc_var_access = -1; #endif } @@ -79,7 +78,7 @@ static void eqn_side(int lhs); static unsigned row; static unsigned maxeqn; -void eqn_name(void) /* save row number for lhs and/or rhs */ +void hoc_eqn_name(void) /* save row number for lhs and/or rhs */ { #if !OCSMALL @@ -89,13 +88,13 @@ void eqn_name(void) /* save row number for lhs and/or rhs */ set_varble(); } init_access(); - do_equation = 1; - eval(); - do_equation = 0; - if (var_access < 1) - execerror("illegal equation name", (pc - 2)->sym->name); - row = var_access; - nopop(); + hoc_do_equation = 1; + hoc_eval(); + hoc_do_equation = 0; + if (hoc_var_access < 1) + hoc_execerror("illegal equation name", (hoc_pc - 2)->sym->name); + row = hoc_var_access; + hoc_nopop(); #endif } @@ -103,7 +102,7 @@ static void set_varble(void) { /* set up varble array by searching for tags */ #if !OCSMALL Symbol* sp; - for (sp = symlist->first; sp != (Symbol*) 0; sp = sp->next) { + for (sp = hoc_symlist->first; sp != (Symbol*) 0; sp = sp->next) { if (sp->s_varn != 0) { if (sp->type == VAR) { if (!is_array(*sp)) { @@ -123,14 +122,14 @@ static void set_varble(void) { /* set up varble array by searching for tags */ static double Delta = .001; /* variable variation */ -void eqinit(void) /* built in function to initialize equation solver */ +void hoc_eqinit(void) /* built in function to initialize equation solver */ { #if !OCSMALL Symbol* sp; if (ifarg(1)) Delta = *getarg(1); - for (sp = symlist->first; sp != (Symbol*) 0; sp = sp->next) { + for (sp = hoc_symlist->first; sp != (Symbol*) 0; sp = sp->next) { if (sp->s_varn != 0) { if (is_array(*sp)) { if (OPARINFO(sp)->a_varn != (unsigned*) 0) @@ -142,11 +141,11 @@ void eqinit(void) /* built in function to initialize equation solver */ neqn = 0; eqn_space(); #endif - ret(); - pushx(0.); + hoc_ret(); + hoc_pushx(0.); } -void eqn_init(void) /* initialize equation row */ +void hoc_eqn_init(void) /* initialize equation row */ { #if !OCSMALL struct elm* el; @@ -157,12 +156,12 @@ void eqn_init(void) /* initialize equation row */ #endif } -void eqn_lhs(void) /* add terms to left hand side */ +void hoc_eqn_lhs(void) /* add terms to left hand side */ { eqn_side(1); } -void eqn_rhs(void) /* add terms to right hand side */ +void hoc_eqn_rhs(void) /* add terms to right hand side */ { eqn_side(0); } @@ -173,33 +172,33 @@ static void eqn_side(int lhs) { int i; struct elm* el; double f0, f1; - Inst* savepc = pc; + Inst* savepc = hoc_pc; init_access(); - do_equation = 1; - execute(savepc); - do_equation = 0; + hoc_do_equation = 1; + hoc_execute(savepc); + hoc_do_equation = 0; if (lhs) { - f0 = xpop(); + f0 = hoc_xpop(); } else { - f0 = -xpop(); + f0 = -hoc_xpop(); } rhs[row] -= f0; - for (i = var_access; i > 0; i = hoc_access[i]) { + for (i = hoc_var_access; i > 0; i = hoc_access[i]) { *varble[i] += Delta; - execute(savepc); + hoc_execute(savepc); *varble[i] -= Delta; if (lhs) { - f1 = xpop(); + f1 = hoc_xpop(); } else { - f1 = -xpop(); + f1 = -hoc_xpop(); } el = getelm((struct elm*) 0, row, (unsigned) i); el->value += (f1 - f0) / Delta; } - pc++; + hoc_pc++; #endif } @@ -247,11 +246,11 @@ void hoc_Prmat(void) { #if !OCSMALL prmat(); #endif - ret(); - pushx(1.); + hoc_ret(); + hoc_pushx(1.); } -void solve(void) { +void hoc_solve(void) { #if !OCSMALL /* Sum is a measure of the dependent variable accuracy and how well the equations are solved */ @@ -281,6 +280,6 @@ void solve(void) { #else double sum = 0; #endif - ret(); - pushx(sum); + hoc_ret(); + hoc_pushx(sum); } diff --git a/src/oc/oc_ansi.h b/src/oc/oc_ansi.h index afebcfd105..0279449376 100644 --- a/src/oc/oc_ansi.h +++ b/src/oc/oc_ansi.h @@ -345,7 +345,7 @@ void hoc_last_init(); void hoc_obj_notify(Object*); int ivoc_list_count(Object*); Object* ivoc_list_item(Object*, int); -double hoc_func_table(void* functable, int n, double* args); +double hoc_func_table(void* vpft, int n, double* args); void hoc_spec_table(void** pfunctable, int n); void* hoc_sec_internal_name2ptr(const char* s, int eflag); void* hoc_pysec_name2ptr(const char* s, int eflag); diff --git a/src/oc/parse.ypp b/src/oc/parse.ypp index 12a7f3e735..715715f58d 100755 --- a/src/oc/parse.ypp +++ b/src/oc/parse.ypp @@ -1,11 +1,15 @@ /* /local/src/master/nrn/src/oc/parse.y,v 1.29 1998/11/27 13:11:48 hines Exp */ +%code requires{ +union Inst; +struct Symbol; +} + %{ #include <../../nrnconf.h> /* changes as of 2-jan-89 */ /* version 7.2.1 2-jan-89 short form of the for statement */ -#include "hoc.h" #include "hocdec.h" #include "ocmisc.h" #include "hocparse.h" @@ -17,9 +21,9 @@ void* nrn_parsing_pysec_; #if LINT Inst *inlint; -#define code inlint = Code +#define code inlint = hoc_Code #else -#define code Code +#define code hoc_Code #endif #define paction(arg) fprintf(stderr, "%s\n", arg) @@ -60,12 +64,12 @@ if (!(ierr++)){pusherr(&ierr);yyerror(arg);} --yyssp; --yyvsp; YYERROR if (!(ierr++)){pusherr(&ierr);yyerror(arg);} YYERROR #endif -#define code2(c1,c2) code(c1); codein(c2) -#define code3(c1,c2,c3) code(c1); codesym(c2); code(c3) +#define code2(c1,c2) code(c1); hoc_codein(c2) +#define code3(c1,c2,c3) code(c1); hoc_codesym(c2); code(c3) #define relative(ip1,ip2,offset) ((ip1-ip2) - offset) #define CHECK 1 /* check syntactically the consistency of arrays */ #define NOCHECK 0 /* don't check syntactically. For object components */ -#define PN pushi(NUMBER) /* for type checking. expressions are usually numbers */ +#define PN hoc_pushi(NUMBER) /* for type checking. expressions are usually numbers */ #define TPD hoc_ob_check(NUMBER); #define TPDYNAM hoc_ob_check(0); @@ -139,17 +143,17 @@ list: /* nothing */ | list '\n' { return '\n';} | list defn '\n' { return '\n';} | list asgn '\n' - { hoc_ob_check(-1); code2(nopop, STOP); return 1; } + { hoc_ob_check(-1); code2(hoc_nopop, STOP); return 1; } | list stmt '\n' - { codein(STOP); return 1; } + { hoc_codein(STOP); return 1; } | list expr '\n' - { TPDYNAM; code2(print, STOP); return 1; } + { TPDYNAM; code2(hoc_print, STOP); return 1; } | list DEBUG '\n' - { debug(); return '\n';} + { hoc_debug(); return '\n';} | list EDIT '\n' { return 'e';} | list string1 '\n' - {code(prstr); code2(hoc_newline, STOP); return 1; } + {code(hoc_prstr); code2(hoc_newline, STOP); return 1; } /* OOP */ | list template '\n' { return '\n';} @@ -170,27 +174,27 @@ goto yynewstate; } ; asgn: varname ROP expr - {Symbol *s; TPD; s = spop(); + {Symbol *s; TPD; s = hoc_spop(); hoc_obvar_declare(s, VAR, 1); - code3(varpush, s, hoc_assign); codei($2); PN;} + code3(hoc_varpush, s, hoc_assign); hoc_codei($2); PN;} | ARG ROP expr - { TPD; defnonly("$"); argcode(argassign, $1); codei($2); $$=$3; PN;} + { TPD; hoc_defnonly("$"); argcode(hoc_argassign, $1); hoc_codei($2); $$=$3; PN;} | ARGREF argrefdim ROP expr - { TPD; defnonly("$&"); argrefcode(hoc_argrefasgn, $1, $2); codei($3); $$=$4; PN;} + { TPD; hoc_defnonly("$&"); argrefcode(hoc_argrefasgn, $1, $2); hoc_codei($3); $$=$4; PN;} /* NEWCABLE */ | rangevar ROP expr - { TPD; code(range_const); codesym(spop()); codei($2); PN;} + { TPD; code(range_const); hoc_codesym(hoc_spop()); hoc_codei($2); PN;} /* END NEWCABLE */ /* OOP */ |ob1 ROP NEW anyname '(' arglist ')' { Inst* p; hoc_opasgn_invalid($2); - code(hoc_newobj); codesym(hoc_which_template($4)); codei($6); - p = (Inst*)spop(); + code(hoc_newobj); hoc_codesym(hoc_which_template($4)); hoc_codei($6); + p = (Inst*)hoc_spop(); if (p) { p->i += 2; } } | ob1 ROP expr - {Inst* p; TPDYNAM; code(hoc_object_asgn); codei($2); - p = (Inst*)spop(); + {Inst* p; TPDYNAM; code(hoc_object_asgn); hoc_codei($2); + p = (Inst*)hoc_spop(); if (p) { p->i += 2; } } /* END OOP */ @@ -200,53 +204,53 @@ asgn: varname ROP expr /* OOP */ rangeobj: rangeobj1 - { code(sec_access_push); codesym((Symbol *)0);} + { code(sec_access_push); hoc_codesym((Symbol *)0);} | section '.' rangeobj1 ; -rangeobj1: RANGEOBJ {pushs($1); pushi(CHECK);} wholearray +rangeobj1: RANGEOBJ {hoc_pushs($1); hoc_pushi(CHECK);} wholearray { $$ = $3;} ; -object: OBJECTVAR {pushi(OBJECTVAR);pushs($1); pushi(CHECK);} wholearray - {$$ = $3; code(hoc_objectvar); spop(); codesym($1);} +object: OBJECTVAR {hoc_pushi(OBJECTVAR);hoc_pushs($1); hoc_pushi(CHECK);} wholearray + {$$ = $3; code(hoc_objectvar); hoc_spop(); hoc_codesym($1);} | OBJECTARG - {defnonly("$o"); $$ = argcode(hoc_objectarg, $1); pushi(OBJECTVAR);} + {hoc_defnonly("$o"); $$ = argcode(hoc_objectarg, $1); hoc_pushi(OBJECTVAR);} | AUTOOBJ - {$$ = code(hoc_autoobject); codesym($1); pushi(OBJECTVAR);} + {$$ = code(hoc_autoobject); hoc_codesym($1); hoc_pushi(OBJECTVAR);} | TEMPLATE '[' expr ']' - {TPD; $$ = $3; code(hoc_constobject); codesym($1); pushi(OBJECTVAR);} + {TPD; $$ = $3; code(hoc_constobject); hoc_codesym($1); hoc_pushi(OBJECTVAR);} | OBJECTFUNC begin '(' arglist ')' - { $$ = $2; code(call); codesym($1); codei($4); - code(hoc_known_type); codei(OBJECTVAR); pushi(OBJECTVAR);} + { $$ = $2; code(hoc_call); hoc_codesym($1); hoc_codei($4); + code(hoc_known_type); hoc_codei(OBJECTVAR); hoc_pushi(OBJECTVAR);} | HOCOBJFUNCTION begin '(' arglist ')' - { $$ = $2; code(call); codesym($1); codei($4); - code(hoc_known_type); codei(OBJECTVAR); pushi(OBJECTVAR);} + { $$ = $2; code(hoc_call); hoc_codesym($1); hoc_codei($4); + code(hoc_known_type); hoc_codei(OBJECTVAR); hoc_pushi(OBJECTVAR);} | rangeobj - { code(rangeobjevalmiddle); codesym(spop()); pushi(OBJECTVAR);} + { code(rangeobjevalmiddle); hoc_codesym(hoc_spop()); hoc_pushi(OBJECTVAR);} | rangeobj '(' expr ')' - {TPD; code(rangeobjeval); codesym(spop()); pushi(OBJECTVAR);} + {TPD; code(rangeobjeval); hoc_codesym(hoc_spop()); hoc_pushi(OBJECTVAR);} ; -ob: ob1 { spop(); } +ob: ob1 { hoc_spop(); } ; -ob1: object { pushs((Symbol*)0); } - | ob1 '.' anyname {pushs($3);pushi(NOCHECK);} wholearray func_or_range_array_case +ob1: object { hoc_pushs((Symbol*)0); } + | ob1 '.' anyname {hoc_pushs($3);hoc_pushi(NOCHECK);} wholearray func_or_range_array_case {int isfunc; Inst* p; - isfunc = ipop(); - code(hoc_object_component); codesym(spop()); codei(ipop()); - codei($6); - codei(0); codesym(0); - p = codei(isfunc); /* for USE_PYTHON */ - spop(); - pushs((Symbol*)p); /* in case assigning to a PythonObject we will want to update isfunc to 2 */ + isfunc = hoc_ipop(); + code(hoc_object_component); hoc_codesym(hoc_spop()); hoc_codei(hoc_ipop()); + hoc_codei($6); + hoc_codei(0); hoc_codesym(0); + p = hoc_codei(isfunc); /* for USE_PYTHON */ + hoc_spop(); + hoc_pushs((Symbol*)p); /* in case assigning to a PythonObject we will want to update isfunc to 2 */ } | OBJECTVAR error {myerr("object syntax is o1.o2.o3.");} ; func_or_range_array_case: /* nothing */ - {$$ = 0; pushi(0);} + {$$ = 0; hoc_pushi(0);} | '(' arglist ')' - {$$ = $2; pushi(1);} + {$$ = $2; hoc_pushi(1);} ; template: BEGINTEMPLATE anyname {hoc_begintemplate($2);} | publiclist @@ -258,20 +262,20 @@ objvarlist: OBJVARDECL begin objvarlst1 {$$ = $2;} ; objvarlst1: obvarname - {code(hoc_objvardecl); codesym($1); codei(0);} + {code(hoc_objvardecl); hoc_codesym($1); hoc_codei(0);} | obvarname numdimen - {code(hoc_objvardecl); codesym($1); codei($2);} + {code(hoc_objvardecl); hoc_codesym($1); hoc_codei($2);} | objvarlst1 ',' obvarname - {code(hoc_objvardecl); codesym($3); codei(0);} + {code(hoc_objvardecl); hoc_codesym($3); hoc_codei(0);} | objvarlst1 ',' obvarname numdimen - {code(hoc_objvardecl); codesym($3); codei($4);} + {code(hoc_objvardecl); hoc_codesym($3); hoc_codei($4);} ; obvarname: anyname { Symbol* s; s = hoc_decl($1); if (s->type != UNDEF && s->type != OBJECTVAR) { - acterror(s->name, " already declared"); + hoc_acterror(s->name, " already declared"); } $$ = s; } @@ -289,10 +293,10 @@ externallist: EXTERNALDECL VAR /* END OOP */ strnasgn: string2 ROP string1 - {hoc_opasgn_invalid($2); code(assstr);} + {hoc_opasgn_invalid($2); code(hoc_assstr);} | ob1 ROP string1 - {Inst* p = (Inst*) spop(); pushi(STRING); TPDYNAM; code(hoc_object_asgn); - hoc_opasgn_invalid($2); codei($2); hoc_ob_check(-1); code(nopop); + {Inst* p = (Inst*) hoc_spop(); hoc_pushi(STRING); TPDYNAM; code(hoc_object_asgn); + hoc_opasgn_invalid($2); hoc_codei($2); hoc_ob_check(-1); code(hoc_nopop); if (p) { p->i += 2; } } | string2 ROP ob @@ -302,15 +306,15 @@ strnasgn: string2 ROP string1 string1: string2 | CSTRING - {$$ = code(hoc_push_string); codesym($1);} + {$$ = code(hoc_push_string); hoc_codesym($1);} | STRINGFUNC begin '(' arglist ')' - { $$ = $2; code(call); codesym($1); codei($4);} + { $$ = $2; code(hoc_call); hoc_codesym($1); hoc_codei($4);} ; string2: STRING - {$$ = code(hoc_push_string); codesym($1);} + {$$ = code(hoc_push_string); hoc_codesym($1);} | STRINGARG - {defnonly("$s"); $$ = argcode(hoc_stringarg, $1);} + {hoc_defnonly("$s"); $$ = argcode(hoc_stringarg, $1);} ; strlist: STRDEF begin string @@ -325,13 +329,13 @@ string: anyname OPSTR(s) = (char**)emalloc(sizeof(char*)); *OPSTR(s) = 0; }else if (s->type != STRING) { - acterror(s->name, " already declared"); + hoc_acterror(s->name, " already declared"); } hoc_assign_str(OPSTR(s), ""); } ; stmt: expr - { code(nopop); hoc_ob_check(-1); /*don't check*/} + { code(hoc_nopop); hoc_ob_check(-1); /*don't check*/} | strlist | doublelist /* OOP */ @@ -339,38 +343,38 @@ stmt: expr /* END OOP */ | strnasgn | string1 - { code(nopop); } + { code(hoc_nopop); } | parseDELETE delsym { $$ = $2;} | RETURN begin - { defnonly("return"); $$=$2; code(procret); } + { hoc_defnonly("return"); $$=$2; code(hoc_procret); } | RETURN expr - { if (indef == 3) { + { if (hoc_indef == 3) { TPDYNAM; $$ = $2; code(hocobjret); }else{ - TPD; defnonly("return"); $$=$2; - code(funcret); + TPD; hoc_defnonly("return"); $$=$2; + code(hoc_funcret); } } | RETURN NEW anyname '(' arglist ')' - {$$ = code(hoc_newobj_ret); codesym(hoc_which_template($3)); codei($5); + {$$ = code(hoc_newobj_ret); hoc_codesym(hoc_which_template($3)); hoc_codei($5); code(hocobjret); } | ITERSTMT begin - { if (indef != 2) { -acterror("iterator_statement used outside an iterator declaration", 0); + { if (hoc_indef != 2) { +hoc_acterror("iterator_statement used outside an iterator declaration", 0); } code(hoc_iterator_stmt); } | BREAK begin - { code(Break); $$ = $2; } + { code(hoc_Break); $$ = $2; } | STOPSTMT begin - { code(Stop); $$ = $2; } + { code(hoc_Stop); $$ = $2; } | CONTINUE begin - { code(Continue); $$ = $2; } + { code(hoc_Continue); $$ = $2; } | PROCEDURE begin '(' arglist ')' - { $$ = $2; code(call); codesym($1); codei($4); code(nopop); } + { $$ = $2; code(hoc_call); hoc_codesym($1); hoc_codei($4); code(hoc_nopop); } | PRINT prlist { $$ = $2; code(hoc_newline); } | FOR begin iterator stmt end @@ -389,12 +393,12 @@ if (0){YYERROR;} #endif } | FOR varname - { Symbol *s; $$ = Code(varpush); codesym(s = spop()); + { Symbol *s; $$ = hoc_Code(hoc_varpush); hoc_codesym(s = hoc_spop()); hoc_obvar_declare(s, VAR, 1); } ROP expr ',' expr {TPD; TPD; hoc_opasgn_invalid($4); - $$ = code(shortfor); codei(0); codei(0);} + $$ = code(hoc_shortfor); hoc_codei(0); hoc_codei(0);} stmt end { $$ = $2; ($8)[1].i = relative($9, $8, 1); /* body */ ($8)[2].i = relative($10, $8, 2); /* exit */ @@ -427,7 +431,7 @@ if (0){YYERROR;} | CONNECTKEYWORD section_or_ob ',' section '(' expr ')' { TPD; $$ = $2; code(simpleconnectsection);} | SETPOINTERKEYWORD rangevar '(' expr ')' ',' pointer - { TPD; $$ = $2; code(connectpointer); codesym(spop());} + { TPD; $$ = $2; code(connectpointer); hoc_codesym(hoc_spop());} | SETPOINTERKEYWORD begin {code(nrn_cppp);} ob ',' pointer { $$ = $2; code(connect_point_process_pointer); hoc_ob_check(-1);} @@ -437,75 +441,75 @@ if (0){YYERROR;} { $$ = $2; hoc_ob_check(SECTION); code(sec_access_object);} | INSERTKEYWORD anyname { Symbol* s = $2; - $$ = Code(mech_access); + $$ = hoc_Code(mech_access); if (s->type != MECHANISM) { s = hoc_table_lookup(s->name, hoc_built_in_symlist); if (!s || s->type != MECHANISM) { - acterror($2->name, "is not a MECHANISM"); + hoc_acterror($2->name, "is not a MECHANISM"); } } - codesym(s);} + hoc_codesym(s);} | UNINSERTKEYWORD MECHANISM - { $$ = Code(mech_uninsert); codesym($2);} + { $$ = hoc_Code(mech_uninsert); hoc_codesym($2);} | section stmt { code(sec_access_pop);} | ob stmt end { code(sec_access_pop); hoc_ob_check(-1); - insertcode($2, $3, ob_sec_access);} + hoc_insertcode($2, $3, ob_sec_access);} | rangevar '(' expr ':' expr ')' ROP expr ':' expr - { TPD; TPD; TPD; TPD; code(range_interpolate); codesym(spop()); - codei($7); + { TPD; TPD; TPD; TPD; code(range_interpolate); hoc_codesym(hoc_spop()); + hoc_codei($7); } | rangevar '(' expr ')' ROP expr - { TPD; TPD; code(range_interpolate_single); codesym(spop()); - codei($5); + { TPD; TPD; code(range_interpolate_single); hoc_codesym(hoc_spop()); + hoc_codei($5); } | FOR '(' varname ')' - {Symbol *s; code(varpush); codesym(s = spop()); + {Symbol *s; code(hoc_varpush); hoc_codesym(s = hoc_spop()); hoc_obvar_declare(s, VAR, 1); - $$ = code(for_segment); codei(0); codei(0);} + $$ = code(for_segment); hoc_codei(0); hoc_codei(0);} stmt end { $$ = $3; ($5)[1].i = relative($6, $5, 1); /* body */ ($5)[2].i = relative($7, $5, 2); /* exit */ } | FOR '(' varname ',' - {Symbol *s; code(varpush); codesym(s = spop()); + {Symbol *s; code(hoc_varpush); hoc_codesym(s = hoc_spop()); hoc_obvar_declare(s, VAR, 1);} expr ')' - { TPD; $$ = code(for_segment1); codei(0); codei(0);} + { TPD; $$ = code(for_segment1); hoc_codei(0); hoc_codei(0);} stmt end { $$ = $3; ($8)[1].i = relative($9, $8, 1); /* body */ ($8)[2].i = relative($10, $8, 2); /* exit */ } | FORALL begin - { code(hoc_push_string); codesym((Symbol*)0); - $$ = code(forall_section); codei(0); codei(0);} + { code(hoc_push_string); hoc_codesym((Symbol*)0); + $$ = code(forall_section); hoc_codei(0); hoc_codei(0);} stmt end { $$ = $2; ($3)[1].i = relative($4, $3, 1); /* body */ ($3)[2].i = relative($5, $3, 2); /* exit */ } | FORSEC begin string1 - { $$ = code(forall_section); codei(0); codei(0);} + { $$ = code(forall_section); hoc_codei(0); hoc_codei(0);} stmt end { $$ = $2; ($4)[1].i = relative($5, $4, 1); /* body */ ($4)[2].i = relative($6, $4, 2); /* exit */ } | IFSEC begin string1 - { $$ = code(hoc_ifsec); codei(0); codei(0);} + { $$ = code(hoc_ifsec); hoc_codei(0); hoc_codei(0);} stmt end { $$ = $2; ($4)[1].i = relative($5, $4, 1); /* body */ ($4)[2].i = relative($6, $4, 2); /* exit */ } | FORSEC begin ob {hoc_ob_check(-1); - $$ = code(forall_sectionlist); codei(0); codei(0); } + $$ = code(forall_sectionlist); hoc_codei(0); hoc_codei(0); } stmt end { $$ = $2; ($4)[1].i = relative($5, $4, 1); /* body */ ($4)[2].i = relative($6, $4, 2); /* exit */ } | IFSEC begin ob { hoc_ob_check(-1); - $$ = code(hoc_ifseclist); codei(0); codei(0); + $$ = code(hoc_ifseclist); hoc_codei(0); hoc_codei(0); } stmt end @@ -517,17 +521,17 @@ if (0){YYERROR;} iterator: ITERATOR '(' arglist ')' { - code(hoc_iterator); codesym($1); codei($3); - $$ = progp; codein(STOP); codein(STOP); + code(hoc_iterator); hoc_codesym($1); hoc_codei($3); + $$ = hoc_progp; hoc_codein(STOP); hoc_codein(STOP); } | {code(hoc_push_current_object);} ob - {codei(ITERATOR); - $$ = progp; codein(STOP); codein(STOP); + {hoc_codei(ITERATOR); + $$ = hoc_progp; hoc_codein(STOP); hoc_codein(STOP); } ; /* NEWCABLE */ -section: SECTION {pushs($1); pushi(CHECK);} wholearray - {code(sec_access_push); codesym(spop()); $$ = $3;} +section: SECTION {hoc_pushs($1); hoc_pushi(CHECK);} wholearray + {code(sec_access_push); hoc_codesym(hoc_spop()); $$ = $3;} | INTERNALSECTIONNAME { $$ = code(hoc_sec_internal_push); @@ -551,44 +555,40 @@ pysec1: PYSECNAME ; section_or_ob: section '(' expr ')' {TPD;} - | {$$ = progp; code(connect_obsec_syntax);} ob + | {$$ = hoc_progp; code(connect_obsec_syntax);} ob { -#if 0 - acterror("Sorry. The \"connect ob.sec...\" syntax ", - "is not implemented"); -#endif hoc_ob_check(SECTION); code(ob_sec_access); } ; sectiondecl: sectionname - { code(add_section); codesym($1); codei(0);} + { code(add_section); hoc_codesym($1); hoc_codei(0);} | sectionname numdimen - { code(add_section); codesym($1); codei($2);} + { code(add_section); hoc_codesym($1); hoc_codei($2);} | sectiondecl ',' sectionname - {code(add_section); codesym($3); codei(0);} + {code(add_section); hoc_codesym($3); hoc_codei(0);} | sectiondecl ',' sectionname numdimen - { code(add_section); codesym($3); codei($4);} + { code(add_section); hoc_codesym($3); hoc_codei($4);} ; sectionname:anyname { Symbol* s; s = hoc_decl($1); if (s->type != UNDEF && s->type != SECTION) - acterror(s->name, " already declared"); + hoc_acterror(s->name, " already declared"); } ; rangevar: rangevar1 - { code(sec_access_push); codesym((Symbol *)0);} + { code(sec_access_push); hoc_codesym((Symbol *)0);} | section '.' rangevar1 ; -rangevar1: RANGEVAR {pushs($1); pushi(CHECK);} wholearray +rangevar1: RANGEVAR {hoc_pushs($1); hoc_pushi(CHECK);} wholearray {$$ = $3;} ; pointer: varname /*leave pointer on stack*/ - { code3(varpush, spop(), hoc_evalpointer);} + { code3(hoc_varpush, hoc_spop(), hoc_evalpointer);} | rangevar '(' expr ')' - { TPD; code(rangevarevalpointer); codesym(spop());} + { TPD; code(rangevarevalpointer); hoc_codesym(hoc_spop());} | ob {hoc_ipop(); code(hoc_ob_pointer);} | rangevar error {myerr("rangevariable needs explicit arc position,eg. v(.5)");} @@ -601,41 +601,41 @@ pointer: varname /*leave pointer on stack*/ for_init: FOR '(' stmt ';' { $$ = $3;} | FOR '(' ';' - { $$ = progp; } + { $$ = hoc_progp; } ; for_st: /* nothing */ - { $$ = code(forcode); codei(0); codei(0); codei(0); } + { $$ = code(hoc_forcode); hoc_codei(0); hoc_codei(0); hoc_codei(0); } ; for_cond: expr - { TPD; $$ = $1; codein(STOP);} + { TPD; $$ = $1; hoc_codein(STOP);} ; for_inc: ';' stmt ')' - { $$ = $2; codein(STOP);} + { $$ = $2; hoc_codein(STOP);} | ';' ')' - { $$ = progp; codein(STOP);} + { $$ = hoc_progp; hoc_codein(STOP);} ; cond: '(' expr ')' - { TPD; codein(STOP); $$ = $2;} + { TPD; hoc_codein(STOP); $$ = $2;} ; while: WHILE for_st { $$ = $2; } ; if: IF - { $$=code(ifcode); codei(0); codei(0); codei(0); } + { $$=code(hoc_ifcode); hoc_codei(0); hoc_codei(0); hoc_codei(0); } ; begin: /* nothing */ - { $$ = progp; } + { $$ = hoc_progp; } ; end: /* nothing */ - { codein(STOP); $$ = progp; } + { hoc_codein(STOP); $$ = hoc_progp; } ; stmtlist: /* nothing */ - { $$ = progp; prog_error = $$; } + { $$ = hoc_progp; prog_error = $$; } | stmtlist '\n' { - prog_parse_recover = progp; + hoc_prog_parse_recover = hoc_progp; prog_error = $$; - if (fin && nrn_fw_eq(fin, stdin) && !pipeflag) + if (hoc_fin && nrn_fw_eq(hoc_fin, stdin) && !hoc_pipeflag) { int i; Printf(">"); for (i = 0; i < ntab; i++) @@ -649,20 +649,20 @@ stmtlist: /* nothing */ ; expr: NUMBER - { $$ = code(constpush); codesym($1); PN;} + { $$ = code(hoc_constpush); hoc_codesym($1); PN;} | NUMZERO - { $$ = code(pushzero); PN;} + { $$ = code(hoc_pushzero); PN;} | varname - { code3(varpush, spop(), eval); PN;} + { code3(hoc_varpush, hoc_spop(), hoc_eval); PN;} | ARG - { defnonly("$"); $$ = argcode(hoc_arg, $1); PN;} + { hoc_defnonly("$"); $$ = argcode(hoc_arg, $1); PN;} | ARGREF argrefdim - { defnonly("$&"); $$ = argrefcode(hoc_argref, $1, $2); PN;} + { hoc_defnonly("$&"); $$ = argrefcode(hoc_argref, $1, $2); PN;} /* NEWCABLE */ | rangevar - {code(rangepoint); codesym(spop()); PN;} + {code(rangepoint); hoc_codesym(hoc_spop()); PN;} | rangevar '(' expr ')' - { TPD; code(rangevareval); codesym(spop()); PN;} + { TPD; code(rangevareval); hoc_codesym(hoc_spop()); PN;} /* END NEWCABLE */ /* OOP */ | ob @@ -670,43 +670,43 @@ expr: NUMBER /* END OOP */ | asgn | function begin '(' arglist ')' - { $$ = $2; code(call); codesym($1); codei($4); PN;} + { $$ = $2; code(hoc_call); hoc_codesym($1); hoc_codei($4); PN;} | varname '(' arglist ')' /* error will be flagged at runtime */ - { code(call); codesym(spop()); codei($3); PN;} + { code(hoc_call); hoc_codesym(hoc_spop()); hoc_codei($3); PN;} | READ '(' varname ')' - { $$=$3; code(varread); codesym(spop()); PN;} + { $$=$3; code(hoc_varread); hoc_codesym(hoc_spop()); PN;} | BLTIN '(' expr ')' - { TPD; $$ = $3; code(bltin); codesym($1); PN;} + { TPD; $$ = $3; code(hoc_bltin); hoc_codesym($1); PN;} | '(' expr ')' { $$ = $2; } | '(' error {myerr("syntax error in expression");} | expr '+' expr - { TPD; TPD; code(add); PN; } + { TPD; TPD; code(hoc_add); PN; } | expr '-' expr { TPD; TPD;code(hoc_sub); PN;} | expr '*' expr - { TPD; TPD; code(mul); PN;} + { TPD; TPD; code(hoc_mul); PN;} | expr '/' expr { TPD; TPD; code(hoc_div); PN;} | expr '%' expr { TPD; TPD; code(hoc_cyclic); PN;} | expr '^' expr - { TPD; TPD; code(power); PN;} + { TPD; TPD; code(hoc_power); PN;} | '-' expr %prec UNARYMINUS { TPD; $$ = $2; code(hoc_negate); PN;} | expr GT expr - { TPD; TPD; code(gt); PN;} + { TPD; TPD; code(hoc_gt); PN;} | expr GE expr - { TPD; TPD; code(ge); PN;} + { TPD; TPD; code(hoc_ge); PN;} | expr LT expr { TPD; TPD; code(hoc_lt); PN;} | expr LE expr - { TPD; TPD; code(le); PN;} + { TPD; TPD; code(hoc_le); PN;} | expr EQ expr { hoc_ob_check(-1); hoc_ob_check(-1); code(hoc_eq); PN;} | expr NE expr - { hoc_ob_check(-1); hoc_ob_check(-1); code(ne); PN;} + { hoc_ob_check(-1); hoc_ob_check(-1); code(hoc_ne); PN;} | expr AND expr { TPD; TPD; code(hoc_and); PN;} | expr OR expr @@ -720,15 +720,15 @@ function: FUNCTION | STRFUNCTION ; doublelist: parseDOUBLE begin newarray - {Symbol *s; code(varpush); codesym(s=spop()); $$ = $2; - code(arayinstal); codei($3); hoc_obvar_declare(s, VAR, 0);} + {Symbol *s; code(hoc_varpush); hoc_codesym(s=hoc_spop()); $$ = $2; + code(hoc_arayinstal); hoc_codei($3); hoc_obvar_declare(s, VAR, 0);} | doublelist ',' newarray - {Symbol *s; code(varpush); codesym(s = spop()); - code(arayinstal); codei($3); hoc_obvar_declare(s, VAR, 0);} + {Symbol *s; code(hoc_varpush); hoc_codesym(s = hoc_spop()); + code(hoc_arayinstal); hoc_codei($3); hoc_obvar_declare(s, VAR, 0);} ; newarray: newname numdimen - {pushs($1); $$ = $2;} + {hoc_pushs($1); $$ = $2;} ; numdimen: '[' expr ']' { TPD; $$ = 1; } @@ -739,19 +739,19 @@ newname: ckvar ; varname: AUTO begin - { pushs($1); $$ = $2; } + { hoc_pushs($1); $$ = $2; } | VAR begin { if ($1->subtype == USERPROPERTY) { - code(sec_access_push); codesym((Symbol *)0); + code(sec_access_push); hoc_codesym((Symbol *)0); } - pushs($1); pushi(CHECK); + hoc_pushs($1); hoc_pushi(CHECK); } wholearray {$$ = $2;} | section '.' VAR { if ($3->subtype != USERPROPERTY) { - acterror($3->name, "not a section variable"); + hoc_acterror($3->name, "not a section variable"); } - $$ = $1; pushs($3); + $$ = $1; hoc_pushs($3); } ; @@ -763,22 +763,22 @@ wholearray:begin array /* using execution stack to get Symbol from array */ /* numindices, checkflag=1, arraysym -> arraysym */ /* numindices, checkflag=0, arraysym -> arraysym numindices*/ { - int ndim = ipop(); - int chk = ipop(); - Symbol* sym = spop(); + int ndim = hoc_ipop(); + int chk = hoc_ipop(); + Symbol* sym = hoc_spop(); if (chk) { if (!is_array(*sym)) { if (ndim) { - acterror(sym->name, "not an array variable"); + hoc_acterror(sym->name, "not an array variable"); } }else{ if ( ndim == 0 ) { /*fake index list with all 0's*/ ndim = sym->arayinfo->nsub; for (int i=0; iarayinfo->nsub) { - acterror("wrong # of subscripts",sym->name); + hoc_acterror("wrong # of subscripts",sym->name); } // Need to dynamically catch error when ndim (now at compile // time) differs from symbol ndim at execution time. @@ -799,70 +799,70 @@ wholearray:begin array /* using execution stack to get Symbol from array */ code(hoc_chk_sym_has_ndim2); } else { // general case code(hoc_chk_sym_has_ndim); - codei(ndim); + hoc_codei(ndim); } - codesym(sym); + hoc_codesym(sym); } }else { - pushi(ndim); /* must check dynamically */ + hoc_pushi(ndim); /* must check dynamically */ } - pushs(sym); + hoc_pushs(sym); } ; argrefdim: array { - $$ = ipop(); + $$ = hoc_ipop(); } ; array: /* Nothing */ - { pushi(0); } + { hoc_pushi(0); } | array '[' expr ']' - { TPD;pushi(ipop() + 1); } + { TPD;hoc_pushi(hoc_ipop() + 1); } ; prlist: expr - { TPDYNAM; code(prexpr);} + { TPDYNAM; code(hoc_prexpr);} | string1 - { code(prstr); } + { code(hoc_prstr); } | prlist ',' expr - { TPDYNAM; code(prexpr);} + { TPDYNAM; code(hoc_prexpr);} | prlist ',' string1 - { code(prstr); } + { code(hoc_prstr); } ; delsym: VAR - { $$ = code(hoc_delete_symbol); codesym($1); } + { $$ = code(hoc_delete_symbol); hoc_codesym($1); } ; defn: FUNC procname - {$2->type=FUNCTION; indef=1; } + {$2->type=FUNCTION; hoc_indef=1; } '(' ')' procstmt - { code(procret); hoc_define($2); + { code(hoc_procret); hoc_define($2); $2->u.u_proc->nobjauto = $6 - localcnt; - $2->u.u_proc->nauto=$6; indef=0; } + $2->u.u_proc->nauto=$6; hoc_indef=0; } | parsePROC procname - { $2->type=PROCEDURE; indef=1; } + { $2->type=PROCEDURE; hoc_indef=1; } '(' ')' procstmt - { code(procret); hoc_define($2); + { code(hoc_procret); hoc_define($2); $2->u.u_proc->nobjauto = $6 - localcnt; - $2->u.u_proc->nauto=$6; indef=0; } + $2->u.u_proc->nauto=$6; hoc_indef=0; } | ITERKEYWORD procname - { $2->type = ITERATOR; indef=2; } + { $2->type = ITERATOR; hoc_indef=2; } '(' ')' procstmt - {code(procret); hoc_define($2); + {code(hoc_procret); hoc_define($2); $2->u.u_proc->nobjauto = $6 - localcnt; - $2->u.u_proc->nauto = $6; indef = 0; } + $2->u.u_proc->nauto = $6; hoc_indef = 0; } | HOCOBJFUNC procname - { $2->type=HOCOBJFUNCTION; indef=3; } + { $2->type=HOCOBJFUNCTION; hoc_indef=3; } '(' ')' procstmt - { code(procret); hoc_define($2); + { code(hoc_procret); hoc_define($2); $2->u.u_proc->nobjauto = $6 - localcnt; - $2->u.u_proc->nauto=$6; indef=0; } + $2->u.u_proc->nauto=$6; hoc_indef=0; } ; procname: ckvar { Symbol *s; s=yylval.sym; - if(s->type != UNDEF) acterror(s->name, "already defined"); + if(s->type != UNDEF) hoc_acterror(s->name, "already defined"); /* avoid valgrind uninitialized variable error for nautoobj */ s->u.u_proc = (Proc *)ecalloc(1, sizeof(Proc)); s->u.u_proc->defn.in = STOP; @@ -894,37 +894,37 @@ arglist2: string1 | '&' pointer | NEW anyname '(' arglist ')' { - code(hoc_newobj_arg); codesym(hoc_which_template($2)); codei($4); + code(hoc_newobj_arg); hoc_codesym(hoc_which_template($2)); hoc_codei($4); } ; eqn_list: DEPENDENT dep_list { $$ = $2; } | EQUATION varname ':' - {code3(varpush, spop(), eqn_name); - do_equation = 1; } + {code3(hoc_varpush, hoc_spop(), hoc_eqn_name); + hoc_do_equation = 1; } equation - { $$ = $2; do_equation = 0; } + { $$ = $2; hoc_do_equation = 0; } ; dep_list: varname - {Symbol *s; code3(varpush,s= spop(), dep_make); hoc_obvar_declare(s, VAR, 0);} + {Symbol *s; code3(hoc_varpush,s= hoc_spop(), hoc_dep_make); hoc_obvar_declare(s, VAR, 0);} | dep_list ',' varname - {Symbol *s; code3(varpush, s=spop(), dep_make); hoc_obvar_declare(s, VAR, 0);} + {Symbol *s; code3(hoc_varpush, s=hoc_spop(), hoc_dep_make); hoc_obvar_declare(s, VAR, 0);} ; equation: lhs EQNEQ | EQNEQ rhs | ':' - { code(eqn_init); } + { code(hoc_eqn_init); } lhs EQNEQ rhs ; lhs: - { code(eqn_lhs); } + { code(hoc_eqn_lhs); } expr - { codein(STOP); TPD; } + { hoc_codein(STOP); TPD; } ; rhs: - { code(eqn_rhs); } + { code(hoc_eqn_rhs); } expr - { codein(STOP); TPD; } + { hoc_codein(STOP); TPD; } ; local: /* nothing */ { $$ = 0; localcnt = $$;} @@ -934,17 +934,17 @@ local1: LOCAL anyname { Symbol *sp; $$ = 1; localcnt = $$; - sp = install($2->name, AUTO, 0.0, &p_symlist); + sp = hoc_install($2->name, AUTO, 0.0, &hoc_p_symlist); sp->u.u_auto = $$; } | local1 ',' anyname { Symbol *sp; $$ = $1 + 1; localcnt = $$; - if (hoc_table_lookup($3->name, p_symlist)) { - acterror($3->name, "already declared local"); + if (hoc_table_lookup($3->name, hoc_p_symlist)) { + hoc_acterror($3->name, "already declared local"); } - sp = install($3->name, AUTO, 0.0, &p_symlist); + sp = hoc_install($3->name, AUTO, 0.0, &hoc_p_symlist); sp->u.u_auto = $$; } ; @@ -956,20 +956,20 @@ local2: LOCALOBJ anyname { Symbol *sp; $$ = 1; - if (hoc_table_lookup($2->name, p_symlist)) { - acterror($2->name, "already declared local"); + if (hoc_table_lookup($2->name, hoc_p_symlist)) { + hoc_acterror($2->name, "already declared local"); } - sp = install($2->name, AUTOOBJ, 0.0, &p_symlist); + sp = hoc_install($2->name, AUTOOBJ, 0.0, &hoc_p_symlist); sp->u.u_auto = $$ + localcnt; } | local2 ',' anyname { Symbol *sp; $$ = $1 + 1; - if (hoc_table_lookup($3->name, p_symlist)) { - acterror($3->name, "already declared local"); + if (hoc_table_lookup($3->name, hoc_p_symlist)) { + hoc_acterror($3->name, "already declared local"); } - sp = install($3->name, AUTOOBJ, 0.0, &p_symlist); + sp = hoc_install($3->name, AUTOOBJ, 0.0, &hoc_p_symlist); sp->u.u_auto = $$ + localcnt; } ; @@ -977,7 +977,7 @@ ckvar: VAR { Symbol* s; s = hoc_decl($1); if (s->subtype != NOTUSER) - acterror("can't redeclare user variable", s->name); + hoc_acterror("can't redeclare user variable", s->name); $$ = s; } ; @@ -991,18 +991,18 @@ anyname: STRING|VAR|UNDEF|FUNCTION|PROCEDURE|FUN_BLTIN|SECTION|RANGEVAR static void yyerror(const char* s) /* called for yacc syntax error */ { - execerror(s, (char *)0); + hoc_execerror(s, (char *)0); } -void acterror(const char* s, const char*t) /* recover from action error while parsing */ +void hoc_acterror(const char* s, const char*t) /* recover from action error while parsing */ { - execerror(s,t); + hoc_execerror(s,t); } static Inst* argrefcode(Pfrv pfrv, int i, int j){ Inst* in; in = argcode(pfrv, i); - codei(j); + hoc_codei(j); return in; } @@ -1011,21 +1011,21 @@ static Inst* argcode(Pfrv pfrv, int i) { if (i == 0) { Symbol* si = hoc_lookup("i"); if (si->type != AUTO) { - acterror("arg index used and i is not a LOCAL variable", 0); + hoc_acterror("arg index used and i is not a LOCAL variable", 0); } - in = code3(varpush, si, eval); - Code(pfrv); - codei(0); + in = code3(hoc_varpush, si, hoc_eval); + hoc_Code(pfrv); + hoc_codei(0); }else{ - in = Code(pfrv); - codei(i); + in = hoc_Code(pfrv); + hoc_codei(i); } return in; } static void hoc_opasgn_invalid(int op) { if (op) { - acterror("Invalid assignment operator.", "Only '=' allowed. "); + hoc_acterror("Invalid assignment operator.", "Only '=' allowed. "); } } diff --git a/src/oc/plot.cpp b/src/oc/plot.cpp index aecd9b9b99..a0bffdcec6 100644 --- a/src/oc/plot.cpp +++ b/src/oc/plot.cpp @@ -1,6 +1,7 @@ #include <../../nrnconf.h> -#include "hoc.h" +#include "hocdec.h" +#include "oc_ansi.h" /*LINTLIBRARY*/ #undef IGNORE @@ -91,7 +92,7 @@ static void hoc_x11plot(int, double, double); static void hard_text_preamble(); -void plprint(const char* s) { +void hoc_plprint(const char* s) { char buf[128]; if (text && s[strlen(s) - 1] == '\n') { @@ -121,8 +122,8 @@ void plprint(const char* s) { IGNORE(fflush(hpdev)); } if (text && s == buf) { - plt(1, xlast, ylast - 20); - plt(-2, 0., 0.); + hoc_plt(1, xlast, ylast - 20); + hoc_plt(-2, 0., 0.); } } @@ -182,7 +183,7 @@ void hoc_close_plot(void) { #endif } -void plt(int mode, double x, double y) { +void hoc_plt(int mode, double x, double y) { if (x < 0.) x = 0.; if (x > 1000.) @@ -341,7 +342,7 @@ static void hardplot_file(const char* s) { } void Fig_file(const char* s, int dev) { - plt(-1, 0., 0.); + hoc_plt(-1, 0., 0.); hardplot_file(s); if (!hpdev) return; @@ -543,7 +544,7 @@ void vtplot(int mode, double x, double y) { } #endif /*VT*/ -int set_color(int c) { +int hoc_set_color(int c) { hoc_color = c; #if SUNCORE set_line_index(c); diff --git a/src/oc/plt.cpp b/src/oc/plt.cpp index b3cf4e6f27..08088dd9cd 100644 --- a/src/oc/plt.cpp +++ b/src/oc/plt.cpp @@ -1,17 +1,12 @@ #include <../../nrnconf.h> -#define FIG \ - 1 /* version 7.1.1 12/8/88 \ -added plots in fig format \ -*/ -#include "hoc.h" #include "gui-redirect.h" extern void Fig_file(const char*, int); #ifndef MINGW -void Plt(void) { +void hoc_Plt(void) { TRY_GUI_REDIRECT_DOUBLE("plt", NULL); int mode; double x, y; @@ -28,17 +23,17 @@ void Plt(void) { } else { x = y = 0.; } - plt(mode, x, y); - ret(); - pushx(1.); + hoc_plt(mode, x, y); + hoc_ret(); + hoc_pushx(1.); } -void Setcolor(void) { +void hoc_Setcolor(void) { TRY_GUI_REDIRECT_DOUBLE("setcolor", NULL); double i; - i = set_color((int) *getarg(1)); - ret(); - pushx(i); + i = hoc_set_color((int) *getarg(1)); + hoc_ret(); + hoc_pushx(i); } void hoc_Lw(void) { @@ -57,8 +52,8 @@ void hoc_Lw(void) { } else { Fig_file((char*) 0, dev); } - ret(); - pushx(0.); + hoc_ret(); + hoc_pushx(0.); } #endif /*!defined(MINGW)*/ diff --git a/src/oc/redef.h b/src/oc/redef.h deleted file mode 100644 index 526d4b1f6c..0000000000 --- a/src/oc/redef.h +++ /dev/null @@ -1,127 +0,0 @@ -/* /local/src/master/nrn/src/oc/redef.h,v 1.3 1994/10/28 15:18:01 hines Exp */ - -#pragma once - -#define Break hoc_Break -#define Continue hoc_Continue -#define Exp hoc_Exp -#define Fprint hoc_Fprint -#define Fscan hoc_Fscan -#define Log hoc_Log -#define Log10 hoc_Log10 -#define Plt hoc_Plt -#define plt hoc_plt -#define color hoc_color -#define Setcolor hoc_Setcolor -#define set_color hoc_set_color -#define Pow hoc_Pow -#define PRintf hoc_PRintf -#define Sqrt hoc_Sqrt -#define System hoc_System -#define Xred hoc_Xred -#define acterror hoc_acterror -#define add hoc_add -#define arayinstal hoc_arayinstal -#define free_arrayinfo hoc_free_arrayinfo -#define araypt hoc_araypt -#define argassign hoc_argassign -#define assstr hoc_assstr -#define bltin hoc_bltin -#define call hoc_call -#define call_ob_proc hoc_call_ob_proc -#define cbuf hoc_cbuf -#define Code hoc_Code -#define codei hoc_codei -#define codesym hoc_codesym -#define codein hoc_codein -#define constpush hoc_constpush -#define pushzero hoc_pushzero -#define ctp hoc_ctp -#define debug hoc_debug -#define debugzz hoc_debugzz -#define defnonly hoc_defnonly -#define dep_make hoc_dep_make -#define do_equation hoc_do_equation -#define eqinit hoc_eqinit -#define eqn_init hoc_eqn_init -#define eqn_lhs hoc_eqn_lhs -#define eqn_name hoc_eqn_name -#define eqn_rhs hoc_eqn_rhs -#define eqn_side hoc_eqn_side -#define errcheck hoc_errcheck -#define eval hoc_eval -#define execerror hoc_execerror -#define execute hoc_execute -#define fin hoc_fin -#define follow hoc_follow -#define forcode hoc_forcode -#define shortfor hoc_shortfor -#define fout hoc_fout -#define fpecatch hoc_fpecatch -#define free_list hoc_free_list -#define frin hoc_frin -#define funcret hoc_funcret -#define gargstr hoc_gargstr -#define getarg hoc_getarg -#define gargc hoc_gargc -#define gargv hoc_gargv -#define ge hoc_ge -#define getnb hoc_getnb -#define gt hoc_gt -#define ifcode hoc_ifcode -#define indef hoc_indef -#define infile hoc_infile -#define init_access hoc_init_access -#define initcode hoc_initcode -#define insertcode hoc_insertcode -#define install hoc_install -#define integer hoc_integer -#define intset hoc_intset -#define ired hoc_ired -#define xred hoc_xred -#define sred hoc_sred -#define le hoc_le -#define lineno hoc_lineno -#define lookup hoc_lookup -#define mul hoc_mul -#define ne hoc_ne -#define onintr hoc_onintr -#define p_symlist hoc_p_symlist -#define parserror hoc_parserror -#define pc hoc_pc -#define pipeflag hoc_pipeflag -#define pipegetc hoc_pipegetc -#define pipeungetc hoc_pipeungetc -#define xpop hoc_xpop -#define spop hoc_spop -#define ipop hoc_ipop -#define nopop hoc_nopop -#define power hoc_power -#define prexpr hoc_prexpr -#define print hoc_print -#define plprint hoc_plprint -#define procret hoc_procret -#define prog hoc_prog -#define prog_parse_recover hoc_prog_parse_recover -#define progbase hoc_progbase -#define progname hoc_progname -#define progp hoc_progp -#define prstr hoc_prstr -#define pushx hoc_pushx -#define pushs hoc_pushs -#define pushi hoc_pushi -#define push_frame hoc_push_frame -#define pop_frame hoc_pop_frame -#define ret hoc_ret -#define ropen hoc_ropen -#define solve hoc_solve -#define spinit hoc_spinit -#define symbols hoc_symbols -#define symlist hoc_symlist -#define var_access hoc_var_access -#define varpush hoc_varpush -#define varread hoc_varread -#define warning hoc_warning -#define wopen hoc_wopen -#define xopen hoc_xopen -#define zzdebug hoc_zzdebug diff --git a/src/oc/symbol.cpp b/src/oc/symbol.cpp index 605a7ba2a6..5c68322626 100644 --- a/src/oc/symbol.cpp +++ b/src/oc/symbol.cpp @@ -2,7 +2,6 @@ /* /local/src/master/nrn/src/oc/symbol.cpp,v 1.9 1999/02/25 18:01:58 hines Exp */ /* version 7.2.1 2-jan-89 */ -#include "hoc.h" #include "hocdec.h" #include "hoclist.h" #include "nrncore_write/utils/nrncore_utils.h" @@ -10,9 +9,9 @@ #include "ocnotify.h" #include "parse.hpp" -#include -#include -#include +#include +#include +#include #if HAVE_MALLOC_H #include @@ -30,11 +29,11 @@ Symlist* hoc_top_level_symlist = nullptr; /* all user names seen at top-level (non-public names inside templates do not appear here) */ extern Objectdata* hoc_top_level_data; -Symlist* symlist = nullptr; /* the current user symbol table: linked list */ -Symlist* p_symlist = nullptr; /* current proc, func, or temp table */ - /* containing constants, strings, and auto */ - /* variables. Discarding these lists at */ - /* appropriate times prevents storage leakage. */ +Symlist* hoc_symlist = nullptr; /* the current user symbol table: linked list */ +Symlist* hoc_p_symlist = nullptr; /* current proc, func, or temp table */ + /* containing constants, strings, and auto */ + /* variables. Discarding these lists at */ + /* appropriate times prevents storage leakage. */ void print_symlist(const char* s, Symlist* tab) { Printf("%s\n", s); @@ -55,15 +54,15 @@ Symbol* hoc_table_lookup(const char* s, Symlist* tab) /* find s in specific tabl return nullptr; } -Symbol* lookup(const char* s) /* find s in symbol table */ - /* look in p_symlist then built_in_symlist then symlist */ +Symbol* hoc_lookup(const char* s) /* find s in symbol table */ + /* look in p_symlist then built_in_symlist then symlist */ { Symbol* sp; - if ((sp = hoc_table_lookup(s, p_symlist)) != nullptr) { + if ((sp = hoc_table_lookup(s, hoc_p_symlist)) != nullptr) { return sp; } - if ((sp = hoc_table_lookup(s, symlist)) != nullptr) { + if ((sp = hoc_table_lookup(s, hoc_symlist)) != nullptr) { return sp; } if ((sp = hoc_table_lookup(s, hoc_built_in_symlist)) != nullptr) { @@ -73,11 +72,11 @@ Symbol* lookup(const char* s) /* find s in symbol table */ return nullptr; /* nullptr ==> not found */ } -Symbol* install(/* install s in the list symbol table */ - const char* s, - int t, - double d, - Symlist** list) { +Symbol* hoc_install(/* install s in the list symbol table */ + const char* s, + int t, + double d, + Symlist** list) { Symbol* sp = (Symbol*) emalloc(sizeof(Symbol)); sp->name = (char*) emalloc((unsigned) (strlen(s) + 1)); /* +1 for '\0' */ Strcpy(sp->name, s); @@ -120,7 +119,7 @@ Symbol* install(/* install s in the list symbol table */ } Symbol* hoc_install_var(const char* name, double* pval) { - Symbol* s = hoc_install(name, UNDEF, 0., &symlist); + Symbol* s = hoc_install(name, UNDEF, 0., &hoc_symlist); s->type = VAR; s->u.pval = pval; s->subtype = USERDOUBLE; @@ -180,7 +179,7 @@ void hoc_free_symspace(Symbol* s1) { /* frees symbol space. Marks it UNDEF */ if (s1->u.u_proc != nullptr) { if (s1->u.u_proc->defn.in != STOP) free((char*) s1->u.u_proc->defn.in); - free_list(&(s1->u.u_proc->list)); + hoc_free_list(&(s1->u.u_proc->list)); free((char*) s1->u.u_proc); } break; @@ -189,7 +188,7 @@ void hoc_free_symspace(Symbol* s1) { /* frees symbol space. Marks it UNDEF */ break; case TEMPLATE: hoc_free_allobjects(s1->u.ctemplate, hoc_top_level_symlist, hoc_top_level_data); - free_list(&(s1->u.ctemplate->symtable)); + hoc_free_list(&(s1->u.ctemplate->symtable)); { hoc_List* l = s1->u.ctemplate->olist; if (l->next == l) { @@ -227,7 +226,7 @@ void hoc_free_symspace(Symbol* s1) { /* frees symbol space. Marks it UNDEF */ s1->type); } if (s1->arayinfo != nullptr) { - free_arrayinfo(s1->arayinfo); + hoc_free_arrayinfo(s1->arayinfo); s1->arayinfo = nullptr; } } @@ -250,7 +249,7 @@ void sym_extra_alloc(Symbol* sym) { } } -void free_list(Symlist** list) { /* free the space in a symbol table */ +void hoc_free_list(Symlist** list) { /* free the space in a symbol table */ if (!*list) { return; } diff --git a/src/oc/xred.cpp b/src/oc/xred.cpp index 5dfbbf1c59..8a9145d390 100644 --- a/src/oc/xred.cpp +++ b/src/oc/xred.cpp @@ -1,4 +1,6 @@ #include <../../nrnconf.h> + +#include "hocdec.h" /* /local/src/master/nrn/src/oc/xred.cpp,v 1.3 1996/02/16 16:19:33 hines Exp */ /* xred.cpp,v @@ -48,12 +50,11 @@ xred.cpp,v * */ -#include "hoc.h" - +#include /* input a n integer in range > min and < max */ -int ired(const char* prompt, int defalt, int min, int max) { - return ((int) xred(prompt, (double) defalt, (double) min, (double) max)); +int hoc_ired(const char* prompt, int defalt, int min, int max) { + return ((int) hoc_xred(prompt, (double) defalt, (double) min, (double) max)); } /* input a double number in range > min and < max program loops til proper number is typed in by user @@ -61,8 +62,7 @@ int ired(const char* prompt, int defalt, int min, int max) { default is used if user types RETURN key input is freeform as scanf can make it. */ -#include -double xred(const char* prompt, double defalt, double min, double max) { +double hoc_xred(const char* prompt, double defalt, double min, double max) { #if !OCSMALL char istr[80], c[2]; double input; @@ -112,7 +112,7 @@ void hoc_Sred(void) { #else double x = 0.; #endif - ret(); + hoc_ret(); hoc_pushx(x); } #if !OCSMALL From 8e3de330520b91a08fe36e6f51f6e6a78dfa004c Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Tue, 10 Sep 2024 16:11:45 +0200 Subject: [PATCH 19/68] Update `fmt@11`. (#3072) --- external/fmt | 2 +- external/nmodl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/external/fmt b/external/fmt index e69e5f977d..0c9fce2ffe 160000 --- a/external/fmt +++ b/external/fmt @@ -1 +1 @@ -Subproject commit e69e5f977d458f2650bb346dadf2ad30c5320281 +Subproject commit 0c9fce2ffefecfdce794e1859584e25877b7b592 diff --git a/external/nmodl b/external/nmodl index 7910146791..e6250014dd 160000 --- a/external/nmodl +++ b/external/nmodl @@ -1 +1 @@ -Subproject commit 79101467912f9690b6c40a1d3eed7315e3ea9bc4 +Subproject commit e6250014dd2c5ae5d9cb30af6920668835b31137 From edbfb3af0a54d2261f379b2441c4e5a4e205614d Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Wed, 11 Sep 2024 11:08:16 +0200 Subject: [PATCH 20/68] Suppress unsigned-integer-overflow for fmt. (#3077) Makes full use of unsigned integer math, including overflow behaviour. Hence, the sanitizer should ignore all unsigned integer overflows for anything fmt related. --- .sanitizers/undefined.supp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.sanitizers/undefined.supp b/.sanitizers/undefined.supp index 1e7ab0b39a..e8af6013cd 100644 --- a/.sanitizers/undefined.supp +++ b/.sanitizers/undefined.supp @@ -31,6 +31,7 @@ unsigned-integer-overflow:_philox4x32bumpkey(r123array2x32) unsigned-integer-overflow:coreneuron::nrnran123_deletestream(coreneuron::nrnran123_State*, bool) unsigned-integer-overflow:coreneuron::nrnran123_newstream3(unsigned int, unsigned int, unsigned int, bool) unsigned-integer-overflow:Py_INCREF(_object*) +unsigned-integer-overflow:fmt::* vptr:NetCon::disconnect(ivObservable*) vptr:ObjObservable::object() -vptr:PreSyn::disconnect(ivObservable*) \ No newline at end of file +vptr:PreSyn::disconnect(ivObservable*) From b8299b9ec94a96931cf5afd1098b36b77e326c6b Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Wed, 11 Sep 2024 12:33:15 +0200 Subject: [PATCH 21/68] Use Printf/Fprintf instead of std::cout, std::cerr (#3073) * Use Printf/Fprintf instead of std::cout, std::cerr This way this is possible to redirect the flux for matlab and jupyter * Fix formatting * Add missing std::endl * Fix formatting * Add a missing include * Add new missing include * Missing header * Missing header * Missing header * try again? * inithoc is special * Fix formatting * try * Who cares --------- Co-authored-by: Nicolas Cornu Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- src/ivoc/ivoc.cpp | 6 +-- src/ivoc/ivocmain.cpp | 4 +- src/ivoc/strfun.cpp | 7 ++- src/neuron/container/soa_identifier.hpp | 17 +++++-- src/nrniv/memory_usage.cpp | 5 +- .../nrncore_write/utils/nrncore_utils.cpp | 2 +- src/nrniv/nrnpy.cpp | 46 ++++++++++++------- src/nrnmpi/memory_usage.cpp | 5 +- src/nrnmpi/nrnmpi_dynam.cpp | 7 ++- src/nrnoc/init.cpp | 8 +++- src/nrnoc/treeset.cpp | 4 +- src/nrnpython/nrnpy_p2h.cpp | 2 +- src/nrnpython/nrnpython.cpp | 2 +- src/oc/hoc.cpp | 10 ++-- src/oc/hoc_oop.cpp | 3 +- 15 files changed, 84 insertions(+), 44 deletions(-) diff --git a/src/ivoc/ivoc.cpp b/src/ivoc/ivoc.cpp index 1f4c1d7e92..790401759d 100644 --- a/src/ivoc/ivoc.cpp +++ b/src/ivoc/ivoc.cpp @@ -373,12 +373,12 @@ int Oc::run(const char* buf, bool show_err_mes) { err = hoc_oc(buf); } catch (std::exception const& e) { if (show_err_mes) { - std::cerr << "Oc::run: caught exception"; + Fprintf(stderr, "Oc::run: caught exception"); std::string_view what{e.what()}; if (!what.empty()) { - std::cerr << ": " << what; + Fprintf(stderr, fmt::format(": {}", what).c_str()); } - std::cerr << std::endl; + Fprintf(stderr, "\n"); } err = 1; } diff --git a/src/ivoc/ivocmain.cpp b/src/ivoc/ivocmain.cpp index e26e686253..3c57815cd5 100644 --- a/src/ivoc/ivocmain.cpp +++ b/src/ivoc/ivocmain.cpp @@ -42,6 +42,8 @@ void iv_display_scale(float); #include #endif +#include + #if 1 void pr_profile(); #define PR_PROFILE pr_profile(); @@ -312,7 +314,7 @@ void hoc_nrnmpi_init() { nrnmpi_stubs(); auto const pmes = nrnmpi_load(); if (!pmes.empty()) { - std::cout << pmes << std::endl; + Printf(fmt::format("{}\n", pmes).c_str()); } #endif diff --git a/src/ivoc/strfun.cpp b/src/ivoc/strfun.cpp index cb5375eb82..91114a9aef 100644 --- a/src/ivoc/strfun.cpp +++ b/src/ivoc/strfun.cpp @@ -14,6 +14,9 @@ #if HAVE_IV #include #endif + +#include + extern Objectdata* hoc_top_level_data; extern Symlist* hoc_built_in_symlist; extern int nrn_is_artificial(int); @@ -55,7 +58,7 @@ static double l_head(void*) { result = sm.prefix().str(); } } catch (const std::regex_error& e) { - std::cerr << e.what() << std::endl; + Fprintf(stderr, fmt::format("{}\n", e.what()).c_str()); } char** head = hoc_pgargstr(3); hoc_assign_str(head, result.c_str()); @@ -81,7 +84,7 @@ static double l_tail(void*) { result = sm.suffix().str(); } } catch (const std::regex_error& e) { - std::cerr << e.what() << std::endl; + Fprintf(stderr, fmt::format("{}\n", e.what()).c_str()); } char** tail = hoc_pgargstr(3); hoc_assign_str(tail, result.c_str()); diff --git a/src/neuron/container/soa_identifier.hpp b/src/neuron/container/soa_identifier.hpp index 0402e3a0aa..8a1f7331e2 100644 --- a/src/neuron/container/soa_identifier.hpp +++ b/src/neuron/container/soa_identifier.hpp @@ -11,6 +11,10 @@ #include #include +#include + +#include "hocdec.h" + namespace neuron::container { /** * @brief A non-owning permutation-stable identifier for a entry in a container. @@ -164,11 +168,14 @@ struct owning_identifier { // auto const read_only_token = node_data.issue_frozen_token(); // list_of_nodes.pop_back(); // which tries to delete a row from a container in read-only mode. - std::cerr << "neuron::container::owning_identifier<" - << cxx_demangle(typeid(Storage).name()) - << "> destructor could not delete from the underlying storage: " << e.what() - << " [" << cxx_demangle(typeid(e).name()) - << "]. This is not recoverable, aborting." << std::endl; + Fprintf(stderr, + fmt::format( + "neuron::container::owning_identifier<{}> destructor could not delete from " + "the underlying storage: {} [{}]. This is not recoverable, aborting.\n", + cxx_demangle(typeid(Storage).name()), + e.what(), + cxx_demangle(typeid(e).name())) + .c_str()); terminate = true; } if (terminate) { diff --git a/src/nrniv/memory_usage.cpp b/src/nrniv/memory_usage.cpp index a7b6766dc5..49361bbd67 100644 --- a/src/nrniv/memory_usage.cpp +++ b/src/nrniv/memory_usage.cpp @@ -2,6 +2,9 @@ #include #include #include "oc_ansi.h" +#include "hocdec.h" + +#include namespace neuron::container { ModelMemoryUsage memory_usage(const Model& model) { @@ -134,7 +137,7 @@ std::string format_memory_usage(const MemoryUsage& usage) { void print_memory_usage(MemoryUsage const& memory_usage) { - std::cout << format_memory_usage(memory_usage) << "\n"; + Printf(fmt::format("{}\n", format_memory_usage(memory_usage)).c_str()); } } // namespace neuron::container diff --git a/src/nrniv/nrncore_write/utils/nrncore_utils.cpp b/src/nrniv/nrncore_write/utils/nrncore_utils.cpp index 8e4e2d4082..eae0925cfb 100644 --- a/src/nrniv/nrncore_write/utils/nrncore_utils.cpp +++ b/src/nrniv/nrncore_write/utils/nrncore_utils.cpp @@ -105,7 +105,7 @@ void nrnbbcore_register_mapping() { int nlfp = vector_capacity(lfp); if (nsec != nseg) { - std::cout << "Error: Section and Segment mapping vectors should have same size!\n"; + Printf("Error: Section and Segment mapping vectors should have same size!\n"); abort(); } diff --git a/src/nrniv/nrnpy.cpp b/src/nrniv/nrnpy.cpp index 9ce27f4dcd..be8b723df4 100644 --- a/src/nrniv/nrnpy.cpp +++ b/src/nrniv/nrnpy.cpp @@ -163,8 +163,9 @@ static void set_nrnpylib() { line.remove_prefix(prefix.size()); line.remove_suffix(suffix.size()); if (!glob_var.empty() && glob_var != line) { - std::cout << "WARNING: overriding " << env_var << '=' << glob_var << " with " - << line << std::endl; + Printf(fmt::format( + "WARNING: overriding {} = {} with {}\n", env_var, glob_var, line) + .c_str()); } glob_var = line; } @@ -216,13 +217,15 @@ void nrnpython_reg() { try { set_nrnpylib(); } catch (std::exception const& e) { - std::cerr << "Could not determine Python library details: " << e.what() - << std::endl; + Fprintf(stderr, + fmt::format("Could not determine Python library details: {}\n", e.what()) + .c_str()); exit(1); } handle = dlopen(nrnpy_pylib.c_str(), RTLD_NOW | RTLD_GLOBAL); if (!handle) { - std::cerr << "Could not dlopen NRN_PYLIB: " << nrnpy_pylib << std::endl; + Fprintf(stderr, + fmt::format("Could not dlopen NRN_PYLIB: {}\n", nrnpy_pylib).c_str()); #if DARWIN nrn_possible_mismatched_arch(nrnpy_pylib.c_str()); #endif @@ -260,8 +263,12 @@ static nrnpython_reg_real_t load_nrnpython() { pyversion = std::to_string(pv10 / factor) + "." + std::to_string(pv10 % factor); } else { if (nrnpy_pylib.empty() || nrnpy_pyversion.empty()) { - std::cerr << "Do not know what Python to load [nrnpy_pylib=" << nrnpy_pylib - << " nrnpy_pyversion=" << nrnpy_pyversion << ']' << std::endl; + Fprintf( + stderr, + fmt::format("Do not know what Python to load [nrnpy_pylib={} nrnpy_pyversion={}]\n", + nrnpy_pylib, + nrnpy_pyversion) + .c_str()); return nullptr; } pyversion = nrnpy_pyversion; @@ -272,15 +279,18 @@ static nrnpython_reg_real_t load_nrnpython() { auto const iter = std::find(supported_versions.begin(), supported_versions.end(), pyversion); if (iter == supported_versions.end()) { - std::cerr << "Python " << pyversion - << " is not supported by this NEURON installation (supported:"; + Fprintf( + stderr, + fmt::format("Python {} is not supported by this NEURON installation (supported:", + pyversion) + .c_str()); for (auto const& good_ver: supported_versions) { - std::cerr << ' ' << good_ver; + Fprintf(stderr, fmt::format(" {}", good_ver).c_str()); } - std::cerr << "). If you are seeing this message, your environment probably contains " - "NRN_PYLIB, NRN_PYTHONEXE and NRN_PYTHONVERSION settings that are " - "incompatible with this NEURON. Try unsetting them." - << std::endl; + Fprintf(stderr, + "). If you are seeing this message, your environment probably contains " + "NRN_PYLIB, NRN_PYTHONEXE and NRN_PYTHONVERSION settings that are " + "incompatible with this NEURON. Try unsetting them.\n"); return nullptr; } } @@ -296,13 +306,15 @@ static nrnpython_reg_real_t load_nrnpython() { #endif auto* const handle = dlopen(name.c_str(), RTLD_NOW); if (!handle) { - std::cerr << "Could not load " << name << std::endl; - std::cerr << "nrn_is_python_extension=" << nrn_is_python_extension << std::endl; + Fprintf(stderr, fmt::format("Could not load {}\n", name).c_str()); + Fprintf(stderr, + fmt::format("nrn_is_python_extension={}\n", nrn_is_python_extension).c_str()); return nullptr; } auto* const reg = reinterpret_cast(dlsym(handle, "nrnpython_reg_real")); if (!reg) { - std::cerr << "Could not load registration function from " << name << std::endl; + Fprintf(stderr, + fmt::format("Could not load registration function from {}\n", name).c_str()); } return reg; } diff --git a/src/nrnmpi/memory_usage.cpp b/src/nrnmpi/memory_usage.cpp index 0583c693b7..42c4479305 100644 --- a/src/nrnmpi/memory_usage.cpp +++ b/src/nrnmpi/memory_usage.cpp @@ -14,6 +14,9 @@ #include +#include "hocdec.h" +#include + #include "neuron/container/memory_usage.hpp" static void sum_reduce_memory_usage(void* invec, void* inoutvec, int* len_, MPI_Datatype*) { @@ -44,7 +47,7 @@ void nrnmpi_memory_stats(neuron::container::MemoryStats& stats, void nrnmpi_print_memory_stats(neuron::container::MemoryStats const& memory_stats) { if (nrnmpi_myid_world == 0) { - std::cout << format_memory_usage(memory_stats.total) << "\n"; + Printf(fmt::format("{}\n", format_memory_usage(memory_stats.total)).c_str()); } } #endif diff --git a/src/nrnmpi/nrnmpi_dynam.cpp b/src/nrnmpi/nrnmpi_dynam.cpp index 8ae0e4222f..56da507e88 100644 --- a/src/nrnmpi/nrnmpi_dynam.cpp +++ b/src/nrnmpi/nrnmpi_dynam.cpp @@ -17,6 +17,9 @@ #include "nrnmpi.h" +#include "hocdec.h" +#include + extern char* cxx_char_alloc(size_t); extern std::string corenrn_mpi_library; @@ -173,7 +176,7 @@ std::string nrnmpi_load() { return true; }; if (!promote_to_global("libnrniv.so") && !promote_to_global("libnrniv-without-nvidia.so")) { - std::cerr << error << " to RTLD_GLOBAL" << std::endl; + Fprintf(stderr, fmt::format("{} to RTLD_GLOBAL\n", error).c_str()); } } #endif @@ -258,7 +261,7 @@ std::string nrnmpi_load() { void nrnmpi_load_or_exit() { auto const err = nrnmpi_load(); if (!err.empty()) { - std::cout << err << std::endl; + Printf(fmt::format("{}\n", err).c_str()); std::exit(1); } } diff --git a/src/nrnoc/init.cpp b/src/nrnoc/init.cpp index d8b55e061c..f233507f70 100644 --- a/src/nrnoc/init.cpp +++ b/src/nrnoc/init.cpp @@ -239,8 +239,12 @@ void* nrn_realpath_dlopen(const char* relpath, int flags) { } catch (const std::filesystem::filesystem_error& e) { handle = dlopen(relpath, flags); if (!handle) { - std::cerr << "std::filesystem::absolute failed (" << e.what() - << ") and dlopen failed with '" << relpath << "'" << std::endl; + Fprintf( + stderr, + fmt::format("std::filesystem::absolute failed ({}) and dlopen failed with '{}'\n", + e.what(), + relpath) + .c_str()); #if DARWIN nrn_possible_mismatched_arch(relpath); #endif diff --git a/src/nrnoc/treeset.cpp b/src/nrnoc/treeset.cpp index fb36e8b897..2a1c0abf97 100644 --- a/src/nrnoc/treeset.cpp +++ b/src/nrnoc/treeset.cpp @@ -30,6 +30,8 @@ #include #include +#include + extern spREAL* spGetElement(char*, int, int); int nrn_shape_changed_; /* for notifying Shape class in nrniv */ @@ -2168,7 +2170,7 @@ static void nrn_sort_node_data(neuron::container::Node::storage::frozen_token_ty // objects. In this case we can figure out which the missing entries are and permute them to // the end of the global vectors. auto missing_elements = node_data_size - global_i; - std::cout << "permuting " << missing_elements << " 'lost' Nodes to the end\n"; + Printf(fmt::format("permuting {} 'lost' Nodes to the end\n", missing_elements).c_str()); // There are `missing_elements` integers from the range [0 .. node_data_size-1] whose values // in `node_data_permutation` are still std::numeric_limits::max(). for (auto global_row = 0ul; global_row < node_data_size; ++global_row) { diff --git a/src/nrnpython/nrnpy_p2h.cpp b/src/nrnpython/nrnpy_p2h.cpp index 931fa0a453..da2083877a 100644 --- a/src/nrnpython/nrnpy_p2h.cpp +++ b/src/nrnpython/nrnpy_p2h.cpp @@ -732,7 +732,7 @@ std::vector call_picklef(const std::vector& fname, int narg) { if (!result) { char* mes = nrnpyerr_str(); if (mes) { - std::cerr << mes << std::endl; + Fprintf(stderr, fmt::format("{}\n", mes).c_str()); free(mes); hoc_execerror("PyObject method call failed:", NULL); } diff --git a/src/nrnpython/nrnpython.cpp b/src/nrnpython/nrnpython.cpp index 1cc4afd638..41fb8c4c30 100644 --- a/src/nrnpython/nrnpython.cpp +++ b/src/nrnpython/nrnpython.cpp @@ -124,7 +124,7 @@ int nrnpy_pyrun(const char* fname) { if (fp) { nrnpython_set_path(fname); } else { - std::cerr << "Could not open " << fname << std::endl; + Fprintf(stderr, fmt::format("Could not open {}\n", fname).c_str()); return 0; } fclose(fp); diff --git a/src/oc/hoc.cpp b/src/oc/hoc.cpp index 407054e561..615ee6711e 100644 --- a/src/oc/hoc.cpp +++ b/src/oc/hoc.cpp @@ -32,6 +32,8 @@ #include #include +#include + /* for eliminating "ignoreing return value" warnings. */ int nrnignore; @@ -928,7 +930,7 @@ int hoc_main1(int argc, const char** argv, const char** envp) { } return exit_status; } catch (std::exception const& e) { - std::cerr << "hoc_main1 caught exception: " << e.what() << std::endl; + Fprintf(stderr, fmt::format("hoc_main1 caught exception: {}\n", e.what()).c_str()); nrn_exit(1); } } @@ -1250,12 +1252,12 @@ static int hoc_run1() { } } catch (std::exception const& e) { hoc_fin = sav_fin; - std::cerr << "hoc_run1: caught exception"; + Fprintf(stderr, "hoc_run1: caught exception"); std::string_view what{e.what()}; if (!what.empty()) { - std::cerr << ": " << what; + Fprintf(stderr, fmt::format(": {}", what).c_str()); } - std::cerr << std::endl; + Fprintf(stderr, "\n"); // Exit if we're not in interactive mode if (!nrn_fw_eq(hoc_fin, stdin)) { return EXIT_FAILURE; diff --git a/src/oc/hoc_oop.cpp b/src/oc/hoc_oop.cpp index d75011831a..350b1bbc70 100644 --- a/src/oc/hoc_oop.cpp +++ b/src/oc/hoc_oop.cpp @@ -20,7 +20,6 @@ #include "nrnfilewrap.h" #include "ocfunc.h" - #define PDEBUG 0 Symbol* nrnpy_pyobj_sym_{}; @@ -1060,7 +1059,7 @@ void hoc_object_component() { auto err = fmt::format("'{}' not a public member of '{}'", sym0->name, obp->ctemplate->sym->name); - std::cerr << err << std::endl; + Fprintf(stderr, fmt::format("{}\n", err).c_str()); hoc_execerror(err.c_str(), nullptr); } *ptid = obp->ctemplate->id; From ecbcd45ab2cfe614d155707892869e03ecfb264e Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 12 Sep 2024 14:55:11 +0200 Subject: [PATCH 22/68] Use fmt as backend for Printf/Fprintf (#3074) * Move Fprintf and Printf in utils/logger.hpp * Make sections.c a c++ file * Remove nrnpy_pr for only Printf (same function) * Use fmt::ptr everywhere this is needed --- src/ivoc/ivocmain.cpp | 2 +- src/ivoc/ivocvect.cpp | 2 + src/ivoc/matrix.cpp | 2 + src/ivoc/strfun.cpp | 2 +- src/neuron/container/soa_identifier.hpp | 2 +- src/nrncvode/cvodeobj.cpp | 14 ++-- src/nrncvode/netcvode.cpp | 13 ++-- src/nrncvode/tqueue.cpp | 7 +- src/nrniv/multisplit.cpp | 13 ++-- .../callbacks/nrncore_callbacks.cpp | 1 - src/nrnmpi/memory_usage.cpp | 3 +- src/nrnmpi/nrnmpi_dynam.cpp | 3 +- src/nrnpython/nrnpy_hoc.cpp | 4 +- src/oc/axis.cpp | 2 + src/oc/code.cpp | 4 +- src/oc/code2.cpp | 2 + src/oc/debug.cpp | 4 +- src/oc/fileio.cpp | 74 +------------------ src/oc/hoc.cpp | 2 +- src/oc/hocdec.h | 2 - src/oc/oc_ansi.h | 2 - src/oc/parse.ypp | 2 + src/oc/plot.cpp | 4 +- src/oc/symbol.cpp | 4 +- src/parallel/bbssrv2mpi.cpp | 2 + src/utils/logger.hpp | 25 +++++++ test/api/CMakeLists.txt | 2 +- test/api/{sections.c => sections.cpp} | 2 +- 28 files changed, 89 insertions(+), 112 deletions(-) create mode 100644 src/utils/logger.hpp rename test/api/{sections.c => sections.cpp} (98%) diff --git a/src/ivoc/ivocmain.cpp b/src/ivoc/ivocmain.cpp index 3c57815cd5..226b37cf11 100644 --- a/src/ivoc/ivocmain.cpp +++ b/src/ivoc/ivocmain.cpp @@ -42,7 +42,7 @@ void iv_display_scale(float); #include #endif -#include +#include "utils/logger.hpp" #if 1 void pr_profile(); diff --git a/src/ivoc/ivocvect.cpp b/src/ivoc/ivocvect.cpp index a938593d06..1ffb1eba95 100644 --- a/src/ivoc/ivocvect.cpp +++ b/src/ivoc/ivocvect.cpp @@ -36,6 +36,8 @@ #include "gui-redirect.h" +#include "utils/logger.hpp" + #ifndef PI #ifndef M_PI #define M_PI 3.14159265358979323846 diff --git a/src/ivoc/matrix.cpp b/src/ivoc/matrix.cpp index 3c66406403..90b0aeef1e 100644 --- a/src/ivoc/matrix.cpp +++ b/src/ivoc/matrix.cpp @@ -8,6 +8,8 @@ #include "parse.hpp" #include "ivocvect.h" +#include "utils/logger.hpp" + #define EPS hoc_epsilon Symbol* nrn_matrix_sym; // also used in oc/hoc_oop.cpp diff --git a/src/ivoc/strfun.cpp b/src/ivoc/strfun.cpp index 91114a9aef..21b78dee78 100644 --- a/src/ivoc/strfun.cpp +++ b/src/ivoc/strfun.cpp @@ -15,7 +15,7 @@ #include #endif -#include +#include "utils/logger.hpp" extern Objectdata* hoc_top_level_data; extern Symlist* hoc_built_in_symlist; diff --git a/src/neuron/container/soa_identifier.hpp b/src/neuron/container/soa_identifier.hpp index 8a1f7331e2..6b8ed98d42 100644 --- a/src/neuron/container/soa_identifier.hpp +++ b/src/neuron/container/soa_identifier.hpp @@ -11,7 +11,7 @@ #include #include -#include +#include "utils/logger.hpp" #include "hocdec.h" diff --git a/src/nrncvode/cvodeobj.cpp b/src/nrncvode/cvodeobj.cpp index e99619d7fb..5c662ec4b7 100644 --- a/src/nrncvode/cvodeobj.cpp +++ b/src/nrncvode/cvodeobj.cpp @@ -1066,7 +1066,7 @@ int Cvode::cvode_init(double) { // printf("CVodeReInit\n"); if (err != SUCCESS) { Printf("Cvode %p %s CVReInit error %d\n", - this, + fmt::ptr(this), secname(ctd_[0].v_node_[ctd_[0].rootnodecount_]->sec), err); return err; @@ -1082,7 +1082,7 @@ int Cvode::cvode_init(double) { CVodeMalloc(mem_, pf_, t0_, y_, CV_SV, &ncv_->rtol_, atolnvec_); if (err != SUCCESS) { Printf("Cvode %p %s CVodeMalloc error %d\n", - this, + fmt::ptr(this), secname(ctd_[0].v_node_[ctd_[0].rootnodecount_]->sec), err); return err; @@ -1302,7 +1302,7 @@ int Cvode::cvode_advance_tn(neuron::model_sorted_token const& sorted_token) { #if PRINT_EVENT if (net_cvode_instance->print_event_ > 1) { Printf("Cvode::cvode_advance_tn %p %d initialize_=%d tstop=%.20g t_=%.20g to ", - this, + fmt::ptr(this), nth_ ? nth_->id : 0, initialize_, tstop_, @@ -1322,7 +1322,7 @@ int Cvode::cvode_advance_tn(neuron::model_sorted_token const& sorted_token) { #endif if (err < 0) { Printf("CVode %p %s advance_tn failed, err=%d.\n", - this, + fmt::ptr(this), secname(ctd_[0].v_node_[ctd_[0].rootnodecount_]->sec), err); pf_(t_, y_, nullptr, &opaque); @@ -1344,7 +1344,7 @@ int Cvode::cvode_interpolate(double tout) { #if PRINT_EVENT if (net_cvode_instance->print_event_ > 1) { Printf("Cvode::cvode_interpolate %p %d initialize_%d t=%.20g to ", - this, + fmt::ptr(this), nth_ ? nth_->id : 0, initialize_, t_); @@ -1365,7 +1365,7 @@ int Cvode::cvode_interpolate(double tout) { #endif if (err < 0) { Printf("CVode %p %s interpolate failed, err=%d.\n", - this, + fmt::ptr(this), secname(ctd_[0].v_node_[ctd_[0].rootnodecount_]->sec), err); return err; @@ -1409,7 +1409,7 @@ N_Vector Cvode::acorvec() { void Cvode::statistics() { #if 1 Printf("\nCvode instance %p %s statistics : %d %s states\n", - this, + fmt::ptr(this), secname(ctd_[0].v_node_[ctd_[0].rootnodecount_]->sec), neq_, (use_daspk_ ? "IDA" : "CVode")); diff --git a/src/nrncvode/netcvode.cpp b/src/nrncvode/netcvode.cpp index b0ad67a1a0..27d7e9bbf0 100644 --- a/src/nrncvode/netcvode.cpp +++ b/src/nrncvode/netcvode.cpp @@ -3493,7 +3493,7 @@ void NetCvode::local_retreat(double t, Cvode* cv) { if (print_event_) { Printf("microstep local retreat from %g (cvode_%p is at %g) for event onset=%g\n", cv->tqitem_->t_, - cv, + fmt::ptr(cv), cv->t_, t); } @@ -3502,7 +3502,10 @@ void NetCvode::local_retreat(double t, Cvode* cv) { tq->move(cv->tqitem_, t); #if PRINT_EVENT if (print_event_ > 1) { - Printf("after target solve time for %p is %g , dt=%g\n", cv, cv->time(), nt_dt); + Printf("after target solve time for %p is %g , dt=%g\n", + fmt::ptr(cv), + cv->time(), + nt_dt); } #endif } else { @@ -3519,7 +3522,7 @@ void NetCvode::retreat(double t, Cvode* cv) { if (print_event_) { Printf("microstep retreat from %g (cvode_%p is at %g) for event onset=%g\n", tq ? cv->tqitem_->t_ : cv->t_, - cv, + fmt::ptr(cv), cv->t_, t); } @@ -3530,7 +3533,7 @@ void NetCvode::retreat(double t, Cvode* cv) { } #if PRINT_EVENT if (print_event_ > 1) { - Printf("after target solve time for %p is %g , dt=%g\n", cv, cv->time(), dt); + Printf("after target solve time for %p is %g , dt=%g\n", fmt::ptr(cv), cv->time(), dt); } #endif } @@ -5577,7 +5580,7 @@ static int trajec_buffered(NrnThread& nt, if (err) { Fprintf(stderr, "Pointer %p of PlayRecord type %d ignored because not a Range Variable", - static_cast(pd), + fmt::ptr(static_cast(pd)), pr->type()); } } diff --git a/src/nrncvode/tqueue.cpp b/src/nrncvode/tqueue.cpp index 9010ae6c43..ffc7c8e2ef 100644 --- a/src/nrncvode/tqueue.cpp +++ b/src/nrncvode/tqueue.cpp @@ -48,7 +48,12 @@ static void prnt(const TQItem* b, int level) { for (i = 0; i < level; ++i) { Printf(" "); } - Printf("%g %c %d Q=%p D=%p\n", b->t_, b->data_ ? 'x' : 'o', b->cnt_, b, b->data_); + Printf("%g %c %d Q=%p D=%p\n", + b->t_, + b->data_ ? 'x' : 'o', + b->cnt_, + fmt::ptr(b), + fmt::ptr(b->data_)); } TQueue::TQueue(TQItemPool* tp, int mkmut) { diff --git a/src/nrniv/multisplit.cpp b/src/nrniv/multisplit.cpp index f37e9ac2fe..f9b9531d78 100644 --- a/src/nrniv/multisplit.cpp +++ b/src/nrniv/multisplit.cpp @@ -1872,20 +1872,23 @@ void MultiSplitControl::prstruct() { m.tag_); if (m.nnode_) { Printf(" nodeindex=%p nodeindex_buffer = %p\n", - m.nodeindex_, - nodeindex_buffer_); + fmt::ptr(m.nodeindex_), + fmt::ptr(nodeindex_buffer_)); } } Printf(" ndbsize=%d i nodeindex_buffer_=%p nodeindex_rthost_=%p\n", ndbsize, - nodeindex_buffer_, - nodeindex_rthost_); + fmt::ptr(nodeindex_buffer_), + fmt::ptr(nodeindex_rthost_)); if (ndbsize) { for (int i = 0; i < ndbsize; ++i) { Printf(" %d %d %d\n", i, nodeindex_buffer_[i], nodeindex_rthost_[i]); } } - Printf(" tbsize=%d trecvbuf_=%p tsendbuf_=%p\n", tbsize, trecvbuf_, tsendbuf_); + Printf(" tbsize=%d trecvbuf_=%p tsendbuf_=%p\n", + tbsize, + fmt::ptr(trecvbuf_), + fmt::ptr(tsendbuf_)); Printf("\n"); } } diff --git a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp index 62bb7f1a14..158ae0c028 100644 --- a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp +++ b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp @@ -1018,7 +1018,6 @@ static void set_info(TQItem* tqi, Fprintf(stderr, "WARNING: CVode.event(...) for delivery at time step nearest %g discarded. " "CoreNEURON cannot presently handle interpreter events (rank %d, thread %d).\n", - nrnmpi_myid, tdeliver, nrnmpi_myid, tid); diff --git a/src/nrnmpi/memory_usage.cpp b/src/nrnmpi/memory_usage.cpp index 42c4479305..084a572939 100644 --- a/src/nrnmpi/memory_usage.cpp +++ b/src/nrnmpi/memory_usage.cpp @@ -14,8 +14,7 @@ #include -#include "hocdec.h" -#include +#include "utils/logger.hpp" #include "neuron/container/memory_usage.hpp" diff --git a/src/nrnmpi/nrnmpi_dynam.cpp b/src/nrnmpi/nrnmpi_dynam.cpp index 56da507e88..0f8eb4d8f0 100644 --- a/src/nrnmpi/nrnmpi_dynam.cpp +++ b/src/nrnmpi/nrnmpi_dynam.cpp @@ -17,8 +17,7 @@ #include "nrnmpi.h" -#include "hocdec.h" -#include +#include "utils/logger.hpp" extern char* cxx_char_alloc(size_t); extern std::string corenrn_mpi_library; diff --git a/src/nrnpython/nrnpy_hoc.cpp b/src/nrnpython/nrnpy_hoc.cpp index 4950c35c7b..d81ddbe05f 100644 --- a/src/nrnpython/nrnpy_hoc.cpp +++ b/src/nrnpython/nrnpy_hoc.cpp @@ -381,7 +381,7 @@ int hocobj_pushargs(PyObject* args, std::vector& s2free) { Py2NRNString str(po, /* disable_release */ true); if (str.err()) { // Since Python error has been set, need to clear, or hoc_execerror - // printing with nrnpy_pr will generate a + // printing with Printf will generate a // Exception ignored on calling ctypes callback function. // So get the message, clear, and make the message // part of the execerror. @@ -399,7 +399,7 @@ int hocobj_pushargs(PyObject* args, std::vector& s2free) { // the object which can raise an error for nrn.Section, nrn.Segment, // etc. if the internal Section is invalid (Section.prop == NULL). // That, in consequence, will generate an - // Exception ignored on calling ctypes callback function: #include "gui-redirect.h" +#include "utils/logger.hpp" + #define CLIP 1e9 #define XS 500. #define YS 400. diff --git a/src/oc/code.cpp b/src/oc/code.cpp index 05c157b61d..d112fb7bb3 100644 --- a/src/oc/code.cpp +++ b/src/oc/code.cpp @@ -2371,9 +2371,9 @@ int hoc_araypt(Symbol* sp, int type) { // pop top value from stack, print it void hoc_print() { - nrnpy_pr("\t"); + Printf("\t"); hoc_prexpr(); - nrnpy_pr("\n"); + Printf("\n"); } // print numeric value diff --git a/src/oc/code2.cpp b/src/oc/code2.cpp index 7f158c6910..679c396cdb 100644 --- a/src/oc/code2.cpp +++ b/src/oc/code2.cpp @@ -14,6 +14,8 @@ #include "nrnfilewrap.h" #include +#include "utils/logger.hpp" + int units_on_flag_; diff --git a/src/oc/debug.cpp b/src/oc/debug.cpp index 81cf005677..2f8aeb5626 100644 --- a/src/oc/debug.cpp +++ b/src/oc/debug.cpp @@ -5,9 +5,11 @@ #include "equation.h" #include +#include "utils/logger.hpp" + int hoc_zzdebug; -#define prcod(c1, c2) else if (p->pf == c1) Printf("%p %p %s", p, p->pf, c2) +#define prcod(c1, c2) else if (p->pf == c1) Printf("%p %p %s", fmt::ptr(p), fmt::ptr(p->pf), c2) void hoc_debug(void) /* print the machine */ { diff --git a/src/oc/fileio.cpp b/src/oc/fileio.cpp index e577129480..140b53eed0 100644 --- a/src/oc/fileio.cpp +++ b/src/oc/fileio.cpp @@ -15,7 +15,6 @@ #include #include "nrnfilewrap.h" - extern char* neuron_home; NrnFILEWrap* hoc_frin; @@ -751,7 +750,7 @@ void hoc_Chdir(void) { } int nrn_is_python_extension; -static int (*nrnpy_pr_stdoe_callback)(int, char*); +int (*nrnpy_pr_stdoe_callback)(int, char*); static int (*nrnpy_pass_callback)(); extern "C" void nrnpy_set_pr_etal(int (*cbpr_stdoe)(int, char*), int (*cbpass)()) { @@ -762,78 +761,9 @@ extern "C" void nrnpy_set_pr_etal(int (*cbpr_stdoe)(int, char*), int (*cbpass)() void nrnpy_pass() { if (nrnpy_pass_callback) { if ((*nrnpy_pass_callback)() != 1) { - hoc_execerror("nrnpy_pass", 0); - } - } -} - -static int vnrnpy_pr_stdoe(FILE* stream, const char* fmt, va_list ap) { - int size = 0; - char* p = NULL; - - if (!nrnpy_pr_stdoe_callback || (stream != stderr && stream != stdout)) { - size = vfprintf(stream, fmt, ap); - return size; - } - - /* Determine required size */ - va_list apc; -#ifndef va_copy -#if defined(__GNUC__) || defined(__clang__) -#define va_copy(dest, src) __builtin_va_copy(dest, src) -#else -#define va_copy(dest, src) (dest = src) -#endif -#endif - va_copy(apc, ap); - size = vsnprintf(p, size, fmt, apc); - va_end(apc); - - if (size < 0) - return 0; - - size++; /* For '\0' */ - p = static_cast(malloc(size)); - if (p == NULL) - return 0; - - size = vsnprintf(p, size, fmt, ap); - if (size < 0) { - free(p); - return 0; - } - - // if any non-ascii translate to '?' or nrnpy_pr will raise an exception. - if (stream == stderr) { - for (int i = 0; p[i] != '\0'; ++i) { - if (!isascii((unsigned char) p[i])) { - p[i] = '?'; - } + hoc_execerror("nrnpy_pass", nullptr); } } - - (*nrnpy_pr_stdoe_callback)((stream == stderr) ? 2 : 1, p); - - free(p); - return size; -} - -int nrnpy_pr(const char* fmt, ...) { - int n; - va_list ap; - va_start(ap, fmt); - n = vnrnpy_pr_stdoe(stdout, fmt, ap); - va_end(ap); - return n; -} - -int Fprintf(FILE* stream, const char* fmt, ...) { - int n; - va_list ap; - va_start(ap, fmt); - n = vnrnpy_pr_stdoe(stream, fmt, ap); - va_end(ap); - return n; } /** printf style specification of hoc_execerror message. (512 char limit) **/ diff --git a/src/oc/hoc.cpp b/src/oc/hoc.cpp index 615ee6711e..fee82add88 100644 --- a/src/oc/hoc.cpp +++ b/src/oc/hoc.cpp @@ -32,7 +32,7 @@ #include #include -#include +#include "utils/logger.hpp" /* for eliminating "ignoreing return value" warnings. */ int nrnignore; diff --git a/src/oc/hocdec.h b/src/oc/hocdec.h index a8f5b31826..eb328950f0 100644 --- a/src/oc/hocdec.h +++ b/src/oc/hocdec.h @@ -263,7 +263,6 @@ int ilint; #define Strncat cplint = strncat #define Strcpy cplint = strcpy #define Strncpy cplint = strncpy -#define Printf ilint = printf #else #undef IGNORE #define IGNORE(arg) arg @@ -272,7 +271,6 @@ int ilint; #define Strncat strncat #define Strcpy strcpy #define Strncpy strncpy -#define Printf nrnpy_pr #endif using neuron::Sprintf; diff --git a/src/oc/oc_ansi.h b/src/oc/oc_ansi.h index 0279449376..0b95fc8732 100644 --- a/src/oc/oc_ansi.h +++ b/src/oc/oc_ansi.h @@ -419,8 +419,6 @@ int hoc_pid(); int hoc_ired(const char*, int, int, int); double hoc_xred(const char*, double, double, double); int hoc_sred(const char*, char*, char*); -int nrnpy_pr(const char* fmt, ...); -int Fprintf(std::FILE*, const char* fmt, ...); void nrnpy_pass(); void hoc_free_allobjects(cTemplate*, Symlist*, Objectdata*); int nrn_is_cable(); diff --git a/src/oc/parse.ypp b/src/oc/parse.ypp index 715715f58d..9a6a8a6d36 100755 --- a/src/oc/parse.ypp +++ b/src/oc/parse.ypp @@ -17,6 +17,8 @@ struct Symbol; #include "equation.h" #include "nrnfilewrap.h" +#include "utils/logger.hpp" + void* nrn_parsing_pysec_; #if LINT diff --git a/src/oc/plot.cpp b/src/oc/plot.cpp index a0bffdcec6..8ded28119a 100644 --- a/src/oc/plot.cpp +++ b/src/oc/plot.cpp @@ -3,6 +3,8 @@ #include "hocdec.h" #include "oc_ansi.h" +#include "utils/logger.hpp" + /*LINTLIBRARY*/ #undef IGNORE #if LINT @@ -114,7 +116,7 @@ void hoc_plprint(const char* s) { #endif } else if (!text) { - nrnpy_pr("%s", s); + Printf("%s", s); } if (hardplot && hpdev && text && strlen(s)) { hard_text_preamble(); diff --git a/src/oc/symbol.cpp b/src/oc/symbol.cpp index 5c68322626..e606dc6cb0 100644 --- a/src/oc/symbol.cpp +++ b/src/oc/symbol.cpp @@ -23,6 +23,8 @@ #include #endif +#include "utils/logger.hpp" + Symlist* hoc_built_in_symlist = nullptr; /* keywords, built-in functions, all name linked into hoc. Look in this list last */ Symlist* hoc_top_level_symlist = nullptr; /* all user names seen at top-level @@ -39,7 +41,7 @@ void print_symlist(const char* s, Symlist* tab) { Printf("%s\n", s); if (tab) for (Symbol* sp = tab->first; sp != nullptr; sp = sp->next) { - Printf("%s %p\n", sp->name, sp); + Printf("%s %p\n", sp->name, fmt::ptr(sp)); } } diff --git a/src/parallel/bbssrv2mpi.cpp b/src/parallel/bbssrv2mpi.cpp index 3da195fac7..1d2d4b6822 100644 --- a/src/parallel/bbssrv2mpi.cpp +++ b/src/parallel/bbssrv2mpi.cpp @@ -9,6 +9,8 @@ #include "bbsimpl.h" #include "hocdec.h" //Printf +#include "utils/logger.hpp" + void nrnbbs_context_wait(); BBSDirectServer* BBSDirectServer::server_; diff --git a/src/utils/logger.hpp b/src/utils/logger.hpp new file mode 100644 index 0000000000..9a10e182c6 --- /dev/null +++ b/src/utils/logger.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +extern int (*nrnpy_pr_stdoe_callback)(int, char*); + +template +int Fprintf(FILE* stream, const char* fmt, Args... args) { + if (nrnpy_pr_stdoe_callback && (stream == stdout || stream == stderr)) { + std::string message = fmt::sprintf(fmt, std::forward(args)...); + nrnpy_pr_stdoe_callback(stream == stdout ? 1 : 2, message.data()); + return message.size(); + } + return fmt::fprintf(stream, fmt, args...); +} + +template +int Printf(const char* fmt, Args... args) { + if (nrnpy_pr_stdoe_callback) { + std::string message = fmt::sprintf(fmt, std::forward(args)...); + nrnpy_pr_stdoe_callback(1, message.data()); + return message.size(); + } + return fmt::printf(fmt, args...); +} diff --git a/test/api/CMakeLists.txt b/test/api/CMakeLists.txt index 2ebc7d9105..52ffa5be18 100644 --- a/test/api/CMakeLists.txt +++ b/test/api/CMakeLists.txt @@ -1,4 +1,4 @@ -foreach(api_test_file hh_sim.cpp netcon.cpp sections.c vclamp.cpp) +foreach(api_test_file hh_sim.cpp netcon.cpp sections.cpp vclamp.cpp) string(REPLACE "." "_" api_test_name "${api_test_file}") add_executable(${api_test_name} ${api_test_file}) cpp_cc_configure_sanitizers(TARGET ${api_test_name}) diff --git a/test/api/sections.c b/test/api/sections.cpp similarity index 98% rename from test/api/sections.c rename to test/api/sections.cpp index 1571bbcc6c..fbf1c4e3e8 100644 --- a/test/api/sections.c +++ b/test/api/sections.cpp @@ -5,7 +5,7 @@ #include #include -void modl_reg(){}; +extern "C" void modl_reg(){}; int main(void) { static const char* argv[] = {"sections", "-nogui", "-nopython", NULL}; From 36ba22961fecce7c41772a52ac4e570bc47334a3 Mon Sep 17 00:00:00 2001 From: Robert A McDougal Date: Thu, 12 Sep 2024 12:41:08 -0400 Subject: [PATCH 23/68] remove outdated comment (#3079) rxd hasn't used scipy in years, so the comment is inaccurate. However, keeping track of contours is not inherently related to rxd, so I'm not sure that there is a better place for this dictionary than at the top level. --- share/lib/python/neuron/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/share/lib/python/neuron/__init__.py b/share/lib/python/neuron/__init__.py index 36bca6d407..4226d7fbdc 100644 --- a/share/lib/python/neuron/__init__.py +++ b/share/lib/python/neuron/__init__.py @@ -748,8 +748,6 @@ def _modelview_mechanism_docstrings(dmech, tree): tree.append(line, dmech.location, 0) -# TODO: put this someplace else -# can't be in rxd because that would break things if no scipy _sec_db = {} From e67effdd7700fb2819a673530cde2d729f5ba9ba Mon Sep 17 00:00:00 2001 From: nrnhines Date: Mon, 16 Sep 2024 08:56:42 -0400 Subject: [PATCH 24/68] Fix h.Vector[0] : TypeError: type 'hoc.Vector' is not subscriptable (#2862) * hoc.HocClass is metaclass. type(h.Vector) is Supports h.File[index], etc via hocclass_getitem * PyType_GetName only since python3.11 * Cursed fallback code for PyType_FromMetaclass for < 3.12 * Comment about hocclass alignment suggested by chatgpt. --------- Co-authored-by: Pramod Kumbhar Co-authored-by: Luc Grosheintz --- src/nrnpython/CMakeLists.txt | 1 + src/nrnpython/nrn_metaclass.cpp | 75 ++++++++++ src/nrnpython/nrnpy_hoc.cpp | 130 ++++++++++++++++-- .../hoctests/tests/test_hoc_class_instance.py | 50 +++++++ 4 files changed, 243 insertions(+), 13 deletions(-) create mode 100644 src/nrnpython/nrn_metaclass.cpp create mode 100644 test/hoctests/tests/test_hoc_class_instance.py diff --git a/src/nrnpython/CMakeLists.txt b/src/nrnpython/CMakeLists.txt index c1e16afbff..92f28c651f 100644 --- a/src/nrnpython/CMakeLists.txt +++ b/src/nrnpython/CMakeLists.txt @@ -18,6 +18,7 @@ set(nrnpython_lib_list) set(NRNPYTHON_FILES_LIST nrnpython.cpp nrnpy_hoc.cpp + nrn_metaclass.cpp nrnpy_nrn.cpp nrnpy_p2h.cpp grids.cpp diff --git a/src/nrnpython/nrn_metaclass.cpp b/src/nrnpython/nrn_metaclass.cpp new file mode 100644 index 0000000000..c37f3c5746 --- /dev/null +++ b/src/nrnpython/nrn_metaclass.cpp @@ -0,0 +1,75 @@ +// Derived from +// https://github.com/python/cpython/pull/93012#issuecomment-1138876646 + +#include + +PyObject* nrn_type_from_metaclass(PyTypeObject* metaclass, + PyObject* mod, + PyType_Spec* spec, + PyObject* base) { +#if PY_VERSION_HEX >= 0x030C0000 + // Life is good, PyType_FromMetaclass() is available + PyObject* result = PyType_FromMetaclass(metaclass, mod, spec, base); + if (!result) { + // fail("nanobind::detail::nb_type_new(\"%s\"): type construction failed!", t->name); + return result; + } +#else + /* The fallback code below is cursed. It provides an alternative when + PyType_FromMetaclass() is not available we are furthermore *not* + targeting the stable ABI interface. It calls PyType_FromSpec() to create + a tentative type, copies its contents into a larger type with a + different metaclass, then lets the original type expire. */ + + PyObject* temp = PyType_FromSpecWithBases(spec, base); // since 3.3 + Py_XINCREF(temp); + PyHeapTypeObject* temp_ht = (PyHeapTypeObject*) temp; + PyTypeObject* temp_tp = &temp_ht->ht_type; + + Py_INCREF(temp_ht->ht_name); + Py_INCREF(temp_ht->ht_qualname); + Py_INCREF(temp_tp->tp_base); + Py_XINCREF(temp_ht->ht_slots); + + PyObject* result = PyType_GenericAlloc(metaclass, 0); + if (!temp || !result) { + // fail("nanobind::detail::nb_type_new(\"%s\"): type construction failed!", t->name); + return nullptr; + } + PyHeapTypeObject* ht = (PyHeapTypeObject*) result; + PyTypeObject* tp = &ht->ht_type; + + memcpy(ht, temp_ht, sizeof(PyHeapTypeObject)); + + tp->ob_base.ob_base.ob_type = metaclass; + tp->ob_base.ob_base.ob_refcnt = 1; + tp->ob_base.ob_size = 0; + tp->tp_as_async = &ht->as_async; + tp->tp_as_number = &ht->as_number; + tp->tp_as_sequence = &ht->as_sequence; + tp->tp_as_mapping = &ht->as_mapping; + tp->tp_as_buffer = &ht->as_buffer; + tp->tp_name = strdup(spec->name); // name_copy; + tp->tp_flags = spec->flags | Py_TPFLAGS_HEAPTYPE; + + tp->tp_dict = tp->tp_bases = tp->tp_mro = tp->tp_cache = tp->tp_subclasses = tp->tp_weaklist = + nullptr; + ht->ht_cached_keys = nullptr; + tp->tp_version_tag = 0; + + PyType_Ready(tp); + Py_DECREF(temp); + + // PyType_FromMetaclass consistently sets the __module__ to 'hoc' (never 'neuron.hoc') + // So rather than use PyModule_GetName or PyObject_GetAttrString(mod, "__name__") just + // explicitly set to 'hoc' + PyObject* module_name = PyUnicode_FromString("hoc"); + if (PyObject_SetAttrString(result, "__module__", module_name) < 0) { + Py_DECREF(module_name); + return nullptr; + } + Py_DECREF(module_name); +#endif + + return result; +} diff --git a/src/nrnpython/nrnpy_hoc.cpp b/src/nrnpython/nrnpy_hoc.cpp index d81ddbe05f..b6eb51a9b9 100644 --- a/src/nrnpython/nrnpy_hoc.cpp +++ b/src/nrnpython/nrnpy_hoc.cpp @@ -130,6 +130,61 @@ PyTypeObject* hocobject_type; static PyObject* hocobj_call(PyHocObject* self, PyObject* args, PyObject* kwrds); +typedef struct { + PyTypeObject head; + Symbol* sym; +} hocclass; + +static int hocclass_init(hocclass* cls, PyObject* args, PyObject* kwds) { + if (PyType_Type.tp_init((PyObject*) cls, args, kwds) < 0) { + return -1; + } + return 0; +} + +static PyObject* pytype_getname(PyTypeObject* pto) { +#if PY_VERSION_HEX >= 0x030B0000 // since python-3.11 + return PyType_GetName(pto); +#else + return PyObject_GetAttrString((PyObject*) pto, "__name__"); +#endif +} + +static PyObject* hocclass_getitem(PyObject* self, Py_ssize_t ix) { + hocclass* hclass = (hocclass*) self; + Symbol* sym = hclass->sym; + assert(sym); + + assert(sym->type == TEMPLATE); + hoc_Item *q, *ql = sym->u.ctemplate->olist; + Object* ob; + ITERATE(q, ql) { + ob = OBJ(q); + if (ob->index == ix) { + return nrnpy_ho2po(ob); + } + } + char e[200]; + Sprintf(e, "%s[%ld] instance does not exist", sym->name, ix); + PyErr_SetString(PyExc_IndexError, e); + return NULL; +} + +// Note use of slots was informed by nanobind (search for nb_meta) + +static PyType_Slot hocclass_slots[] = {{Py_tp_base, nullptr}, // &PyType_Type : not obvious why it + // must be set at runtime + {Py_tp_init, (void*) hocclass_init}, + {Py_sq_item, (void*) hocclass_getitem}, + {0, NULL}}; + +static PyType_Spec hocclass_spec = {"hoc.HocClass", + 0, // .basicsize fill later + 0, // .itemsize + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE, + hocclass_slots}; + + bool nrn_chk_data_handle(const neuron::container::data_handle& pd) { if (pd) { return true; @@ -919,7 +974,6 @@ static PyObject* hocobj_getsec(Symbol* sym) { // leave pointer on stack ready for get/set final static void eval_component(PyHocObject* po, int ix) { - int j; hoc_push_object(po->ho_); hocobj_pushtop(po, 0, ix); component(po); @@ -2263,7 +2317,6 @@ static PyObject* setpointer(PyObject* self, PyObject* args) { PyObject *ref, *name, *pp; if (PyArg_ParseTuple(args, "O!OO", hocobject_type, &ref, &name, &pp) == 1) { PyHocObject* href = (PyHocObject*) ref; - double** ppd = 0; if (href->type_ != PyHoc::HocScalarPtr) { goto done; } @@ -2960,7 +3013,7 @@ static PyObject* hocpickle_reduce_safe(PyObject* self, PyObject* args) { static PyObject* hocpickle_setstate(PyObject* self, PyObject* args) { BYTEHEADER int version = -1; - int size = -1; + int size = 0; PyObject* rawdata = NULL; PyObject* endian_data; PyHocObject* pho = (PyHocObject*) self; @@ -3002,7 +3055,7 @@ static PyObject* hocpickle_setstate(PyObject* self, PyObject* args) { Py_DECREF(rawdata); return NULL; } - if (len != size * sizeof(double)) { + if (len != Py_ssize_t(size * sizeof(double))) { PyErr_SetString(PyExc_ValueError, "buffer size does not match array size"); Py_DECREF(rawdata); return NULL; @@ -3331,6 +3384,11 @@ static PyType_Spec obj_spec_from_name(const char* name) { }; } +extern PyObject* nrn_type_from_metaclass(PyTypeObject* meta, + PyObject* mod, + PyType_Spec* spec, + PyObject* bases); + extern "C" NRN_EXPORT PyObject* nrnpy_hoc() { PyObject* m; PyObject* bases; @@ -3357,12 +3415,50 @@ extern "C" NRN_EXPORT PyObject* nrnpy_hoc() { } m = PyModule_Create(&hocmodule); assert(m); + Symbol* s = NULL; spec = obj_spec_from_name("hoc.HocObject"); - hocobject_type = (PyTypeObject*) PyType_FromSpec(&spec); - if (PyType_Ready(hocobject_type) < 0) - goto fail; - PyModule_AddObject(m, "HocObject", (PyObject*) hocobject_type); + hocobject_type = (PyTypeObject*) nrn_type_from_metaclass(&PyType_Type, m, &spec, nullptr); + if (hocobject_type == NULL) { + return NULL; + } + if (PyModule_AddObject(m, "HocObject", (PyObject*) hocobject_type) < 0) { + return NULL; + } + + hocclass_slots[0].pfunc = (PyObject*) &PyType_Type; + // I have no idea what is going on here. If use + // hocclass_spec.basicsize = sizeof(hocclass); + // then get error + // TypeError: tp_basicsize for type 'hoc.HocClass' (424) is + // too small for base 'type' (920) + +#if 1 + hocclass_spec.basicsize = PyType_Type.tp_basicsize + sizeof(Symbol*); + // and what about alignment? + // recommended by chatgpt + size_t alignment = alignof(Symbol*); + size_t remainder = hocclass_spec.basicsize % alignment; + if (remainder != 0) { + hocclass_spec.basicsize += alignment - remainder; + // printf("aligned hocclass_spec.basicsize = %d\n", hocclass_spec.basicsize); + } +#else + // chatgpt agrees that the following suggestion + // https://github.com/neuronsimulator/nrn/pull/2862/files#r1749797713 + // is equivalent to the '#if 1' fragment above. However the above + // may "ensures portability and correctness across different architectures." + hocclass_spec.basicsize = PyType_Type.tp_basicsize + sizeof(hocclass) - sizeof(PyTypeObject); +#endif + + PyObject* custom_hocclass = PyType_FromSpec(&hocclass_spec); + if (custom_hocclass == NULL) { + return NULL; + } + if (PyModule_AddObject(m, "HocClass", custom_hocclass) < 0) { + return NULL; + } + bases = PyTuple_Pack(1, hocobject_type); Py_INCREF(bases); @@ -3370,12 +3466,20 @@ extern "C" NRN_EXPORT PyObject* nrnpy_hoc() { // TODO: obj_spec_from_name needs a hoc. prepended exposed_py_type_names.push_back(std::string("hoc.") + name); spec = obj_spec_from_name(exposed_py_type_names.back().c_str()); - pto = (PyTypeObject*) PyType_FromSpecWithBases(&spec, bases); - sym_to_type_map[hoc_lookup(name)] = pto; - type_to_sym_map[pto] = hoc_lookup(name); - if (PyType_Ready(pto) < 0) + pto = (PyTypeObject*) + nrn_type_from_metaclass((PyTypeObject*) custom_hocclass, m, &spec, bases); + hocclass* hclass = (hocclass*) pto; + hclass->sym = hoc_lookup(name); + // printf("%s hocclass pto->tp_basicsize = %zd sizeof(*pto)=%zd\n", + // hclass->sym->name, pto->tp_basicsize, sizeof(*pto)); + sym_to_type_map[hclass->sym] = pto; + type_to_sym_map[pto] = hclass->sym; + if (PyType_Ready(pto) < 0) { goto fail; - PyModule_AddObject(m, name, (PyObject*) pto); + } + if (PyModule_AddObject(m, name, (PyObject*) pto) < 0) { + return NULL; + } } Py_DECREF(bases); diff --git a/test/hoctests/tests/test_hoc_class_instance.py b/test/hoctests/tests/test_hoc_class_instance.py new file mode 100644 index 0000000000..e7e85e9087 --- /dev/null +++ b/test/hoctests/tests/test_hoc_class_instance.py @@ -0,0 +1,50 @@ +from neuron import h +import neuron +import re + +h( + """ +begintemplate A +proc init() { + x = 2 +} +endtemplate A +""" +) + + +def extract_index(s): + match = re.search(r"\[(\d+)\]", s) + if match: + return int(match.group(1)) + else: + raise ValueError("String does not match the expected format") + + +def test1(): + v = h.Vector() + assert type(v) is h.Vector + assert type(type(v)) is neuron.hoc.HocClass + assert type(type(type(v))) is type + assert type(neuron.hoc.HocObject) is type + assert type(h.sin) is neuron.hoc.HocObject + assert type(h) is neuron.hoc.HocObject + assert bool(v) is False + vstr = "h." + str(v) + print(vstr) + exec(vstr + ".resize(10)") + assert len(v) == 10 + assert bool(v) is True + ix = extract_index(str(v)) + assert h.Vector[ix] == v + assert type(v).__module__ == "hoc" + + +def test2(): + a = h.A() + assert h.A[0] == a + + +if __name__ == "__main__": + test1() + test2() From 91090b4762710ae236704d7f08426d30e840e28c Mon Sep 17 00:00:00 2001 From: nrnhines Date: Mon, 16 Sep 2024 16:55:52 -0400 Subject: [PATCH 25/68] CellBuild topology page easily crashes when deleting sections with continuous create on (#3005) * almost complete coverage of secref.cpp --- share/lib/hoc/celbild/celset.hoc | 18 +++- share/lib/hoc/celbild/celtopol.hoc | 10 ++- src/nrnoc/secref.cpp | 17 +++- test/hoctests/tests/test_secref.py | 138 +++++++++++++++++++++++++++++ 4 files changed, 176 insertions(+), 7 deletions(-) create mode 100644 test/hoctests/tests/test_secref.py diff --git a/share/lib/hoc/celbild/celset.hoc b/share/lib/hoc/celbild/celset.hoc index c13aedc87c..fb4fa31896 100755 --- a/share/lib/hoc/celbild/celset.hoc +++ b/share/lib/hoc/celbild/celset.hoc @@ -1,5 +1,6 @@ begintemplate SNList // Like a Section List public name, name_, list, differ, name_differ, add, del_all, ml, geo, geobox +public remove public domainparms, is_subset public export, sectionlist objref list, this, ml, geo, geobox, domainparms, sectionlist @@ -14,6 +15,15 @@ proc init() { name_differ = 0 } func is_subset() { return 1 } + +proc remove() {local i + for (i = list.count - 1; i >= 0; i = i-1) { + if (list.o(i) == $o1) { + list.remove(i) + } + } +} + proc add() { if ($o1.sets.index(this) == -1) { // only add if not already in list list.append($o1) @@ -70,7 +80,7 @@ endtemplate SDIDispListItem begintemplate SectionSubsets public topol, hbox, g, update, snlist, save_data, showsel, bild, pr public consist, esub, cexport, dpi, have_domainparm, xmlwrite -public domain_iter, delsdi, neuroml +public domain_iter, delsdi, neuroml, remove objref g, this, snlist, tobj, tobj1, tobj2, bild, smap, imap objref hb1, hb2, vb1, vb2, vb3, dk1, dk2 objref sdidisplist, nil, dpi @@ -93,6 +103,12 @@ proc init() { dk1.flip_to(0) } +proc remove() {local i + for i = 0, snlist.count-1 { + snlist.o(i).remove($o1) + } +} + func have_domainparm() {local i for i = 0, snlist.count-1 { if (object_id(snlist.object(i).domainparms) != 0) { diff --git a/share/lib/hoc/celbild/celtopol.hoc b/share/lib/hoc/celbild/celtopol.hoc index bedb38e70e..57c9b32b0c 100755 --- a/share/lib/hoc/celbild/celtopol.hoc +++ b/share/lib/hoc/celbild/celtopol.hoc @@ -479,7 +479,10 @@ proc del() {local i //if only one section and it is selected then delete it if (slist.count == 1) { if (slist.object(0).selected == 1) { - if (etop) slist.object(0).export_rm() + if (etop) { + bild.subsets.remove(slist.object(0)) + slist.object(0).export_rm() + } slist.remove(0) } } @@ -494,7 +497,10 @@ proc del() {local i for (i=slist.count-1; i >= 1; i -=1) {// can't delete root tobj = slist.object(i) if (tobj.selected == 1) { - if (etop) tobj.export_rm() + if (etop) { + bild.subsets.remove(tobj) + tobj.export_rm() + } slist.remove(i) } } diff --git a/src/nrnoc/secref.cpp b/src/nrnoc/secref.cpp index a0ec032b91..87071ed2a8 100644 --- a/src/nrnoc/secref.cpp +++ b/src/nrnoc/secref.cpp @@ -73,6 +73,15 @@ static double s_unname(void* v) { #endif pitm = sec2pitm(sec); *pitm = (hoc_Item*) 0; + auto* ob = sec->prop->dparam[6].get(); + if (ob) { + // Avoid use of freed memory in CellBuild when making a section + // after deleting a section when continuous create is on. + // CellBuild repeatedly creates a single CellBuildTopology[0].dummy + // section and then unnames and renamed it at the top level. + ob->secelm_ = nullptr; + sec->prop->dparam[6] = static_cast(nullptr); + } sec->prop->dparam[0] = static_cast(nullptr); return 1.; } @@ -169,6 +178,10 @@ static double s_rename(void* v) { hoc_objectdata = obdsav; return 0; } + if (sec->prop->dparam[0].get()) { + Printf("Item %d of second list arg, %s, must first be unnamed\n", i, secname(sec)); + return 0; + } qsec = sec->prop->dparam[8].get(); sec->prop->dparam[0] = sym; sec->prop->dparam[5] = i; @@ -231,13 +244,11 @@ int nrn_secref_nchild(Section* sec) { } static double s_nchild(void* v) { - int n; hoc_return_type_code = 1; /* integer */ return (double) nrn_secref_nchild((Section*) v); } static double s_has_parent(void* v) { - int n; Section* sec = (Section*) v; hoc_return_type_code = 2; /* boolean */ if (!sec->prop) { @@ -247,7 +258,6 @@ static double s_has_parent(void* v) { } static double s_has_trueparent(void* v) { - int n; Section* sec = (Section*) v; hoc_return_type_code = 2; /* boolean */ if (!sec->prop) { @@ -257,7 +267,6 @@ static double s_has_trueparent(void* v) { } static double s_exists(void* v) { - int n; hoc_return_type_code = 2; /* boolean */ Section* sec = (Section*) v; return (double) (sec->prop != (Prop*) 0); diff --git a/test/hoctests/tests/test_secref.py b/test/hoctests/tests/test_secref.py new file mode 100644 index 0000000000..2fdf7c605f --- /dev/null +++ b/test/hoctests/tests/test_secref.py @@ -0,0 +1,138 @@ +from neuron import h +from neuron.expect_hocerr import expect_err, set_quiet + +set_quiet(0) + +# SectionRef unname and rename are undocumented but used in implementation +# of CellBuild + +h("create a") +sr = h.SectionRef(sec=h.a) +assert sr.sec.name() == "a" +assert sr.rename("b") == 0 # must first be unnamed +sr.unname() +expect_err("sr.unname()") # already unnamed +h("foo = 1") +assert sr.rename("foo") == 0 # already exists +sr.rename("b") +assert sr.sec.name() == "b" +h.delete_section(sec=h.b) +assert sr.rename("c") == 0 + +h("create a, b[3]") +sr = h.SectionRef(sec=h.a) +sr.unname() +sr.rename("b") # no longer an array and the old 3 are deleted +assert sr.sec.name() == "b" +h.delete_section(sec=h.b) + +# rename a bunch as an array +h("create a, b, c, d") +sr = None # let's start over at 0 +sr = [h.SectionRef(sec=i) for i in h.allsec()] +assert len(sr) == 4 + +# the ones to rename into a new array +lst = h.List() +for i in [0, 2, 3]: + lst.append(sr[i]) +sr[0].unname() +assert sr[0].rename("x", lst) == 0 # have not unnamed c and d +for i in lst: + i.unname() +assert sr[0].rename("x", lst) == 1 +h.topology() +print("cover a deleted section message") +h.delete_section(sec=h.x[1]) +sr[0].unname() +assert sr[0].rename("y", lst) == 0 +h.topology() + + +# cleanup +def cleanup(): + for sec in h.allsec(): + h.delete_section(sec=sec) + + +cleanup() + +# Python sections cannot be unnamed or renamed +a = h.Section("a") +sr = h.SectionRef(sec=a) +assert sr.unname() == 0 +assert a.name() == "a" +assert sr.rename("b") == 0 +assert a.name() == "a" +cleanup() + + +# remaining "documented" methods +sr = None +lst = None +h("create a, a1, a2, a3") +h.a1.connect(h.a(0)) +h.a2.connect(h.a(0.5)) +h.a3.connect(h.a(1)) +h.topology() +sr = [h.SectionRef(sec=sec) for sec in h.allsec()] +assert sr[0].nchild() == 3 +assert sr[0].has_parent() is False +assert sr[0].has_trueparent() is False +assert sr[1].has_parent() is True +assert sr[1].has_trueparent() is False +assert sr[2].has_parent() is True +assert sr[2].has_trueparent() is True + +assert sr[0].is_cas(sec=sr[0].sec) is True +assert sr[1].is_cas(sec=sr[0].sec) is False + +assert sr[1].parent == sr[0].sec +assert sr[2].trueparent == sr[0].sec +assert sr[2].root == sr[0].sec +for i in range(sr[0].nchild()): + assert sr[0].child[i] == sr[i + 1].sec + +# can only get to these lines via hoc? (when implementation uses nrn_inpython) +# May want to eliminate the nrn_inpython fragments for complete coverage +# I believe hoc_execerror would work also in the python context. +assert h("%s.child[3] print secname()" % sr[0]) == False +assert h("%s.child[1][1] print secname()" % sr[0]) == False +assert h("%s.child print secname()" % sr[0]) == False +assert h("%s.parent print secname()" % sr[0]) == False +assert h("%s.trueparent print secname()" % sr[0]) == False + + +h.topology() + +h.delete_section(sec=sr[0].sec) +expect_err("sr[0].nchild()") +expect_err("sr[0].has_parent()") +expect_err("sr[0].has_trueparent()") +expect_err("sr[0].is_cas()") +expect_err("sr[1].parent") +expect_err("sr[2].trueparent") +assert sr[2].root == sr[2].sec +expect_err("sr[1].child[5]") + +h("create soma") +sr = h.SectionRef(sec=h.soma) +assert sr.exists() is True +h.delete_section(sec=h.soma) +assert sr.exists() is False + +h( + """ +begintemplate Cell +public soma +create soma +endtemplate Cell +""" +) + +cell = h.Cell() +sr = h.SectionRef(sec=cell.soma) +print(sr.sec) +sr.unname() + +h("create c") # fix segfault From c14d2e6e28cd4a29aee07e91ee5345a63e0b416e Mon Sep 17 00:00:00 2001 From: nrnhines Date: Tue, 17 Sep 2024 06:47:11 -0400 Subject: [PATCH 26/68] fix the -Wall warnings for containers (#3070) * Fix -Wall from container (netpar.cpp -Wall free) * cabcode.cpp -Wall free --------- Co-authored-by: Luc Grosheintz --- .../utils/profile/profiler_interface.h | 4 ++++ src/neuron/container/soa_container.hpp | 4 ++-- src/neuron/model_data.hpp | 12 +++++----- src/nrniv/netpar.cpp | 2 +- src/nrnoc/cabcode.cpp | 23 +++++++------------ 5 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/coreneuron/utils/profile/profiler_interface.h b/src/coreneuron/utils/profile/profiler_interface.h index ce628c6cce..08e9a46fb0 100644 --- a/src/coreneuron/utils/profile/profiler_interface.h +++ b/src/coreneuron/utils/profile/profiler_interface.h @@ -48,8 +48,10 @@ namespace detail { */ template struct Instrumentor { +#ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-value" +#endif // __clang__ /*! \fn phase_begin * \brief Activate the collection of profiling data within a code region. * @@ -147,7 +149,9 @@ struct Instrumentor { inline static void finalize_profile() { std::initializer_list{(TProfilerImpl::finalize_profile(), 0)...}; } +#ifdef __clang__ #pragma clang diagnostic pop +#endif // __clang__ private: /*! diff --git a/src/neuron/container/soa_container.hpp b/src/neuron/container/soa_container.hpp index c176281f26..57e8990572 100644 --- a/src/neuron/container/soa_container.hpp +++ b/src/neuron/container/soa_container.hpp @@ -463,7 +463,7 @@ struct field_data { */ template Callable for_each_vector(Callable callable) { - for (auto i = 0; i < m_storage.size(); ++i) { + for (std::size_t i = 0; i < m_storage.size(); ++i) { callable(m_tag, m_storage[i], i, m_array_dims[i]); } if constexpr (might_reallocate == may_cause_reallocation::Yes) { @@ -480,7 +480,7 @@ struct field_data { */ template Callable for_each_vector(Callable callable) const { - for (auto i = 0; i < m_storage.size(); ++i) { + for (std::size_t i = 0; i < m_storage.size(); ++i) { callable(m_tag, m_storage[i], i, m_array_dims[i]); } diff --git a/src/neuron/model_data.hpp b/src/neuron/model_data.hpp index 8909aa01cc..4f35a64d5f 100644 --- a/src/neuron/model_data.hpp +++ b/src/neuron/model_data.hpp @@ -35,7 +35,7 @@ struct Model { */ template void apply_to_mechanisms(Callable const& callable) { - for (auto type = 0; type < m_mech_data.size(); ++type) { + for (std::size_t type = 0; type < m_mech_data.size(); ++type) { if (!m_mech_data[type]) { continue; } @@ -45,7 +45,7 @@ struct Model { template void apply_to_mechanisms(Callable const& callable) const { - for (auto type = 0; type < m_mech_data.size(); ++type) { + for (std::size_t type = 0; type < m_mech_data.size(); ++type) { if (!m_mech_data[type]) { continue; } @@ -77,10 +77,10 @@ struct Model { /** @brief Destroy the structure holding the data of a particular mechanism. */ void delete_mechanism(int type) { - if (type >= m_mech_data.size() || !m_mech_data[type]) { + if (type < 0 || std::size_t(type) >= m_mech_data.size() || !m_mech_data[type]) { return; } - if (auto const size = m_mech_data[type]->size(); size > 0) { + if (std::size_t const size = m_mech_data[type]->size(); size > 0) { throw std::runtime_error("delete_mechanism(" + std::to_string(type) + "): refusing to delete storage that still hosts " + std::to_string(size) + " instances"); @@ -105,7 +105,7 @@ struct Model { } [[nodiscard]] bool is_valid_mechanism(int type) const { - return 0 <= type && type < mechanism_storage_size() && m_mech_data[type]; + return 0 <= type && std::size_t(type) < mechanism_storage_size() && m_mech_data[type]; } /** @@ -124,7 +124,7 @@ struct Model { private: container::Mechanism::storage& mechanism_data_impl(int type) const { - if (type < 0 || type >= m_mech_data.size()) { + if (type < 0 || std::size_t(type) >= m_mech_data.size()) { throw std::runtime_error("mechanism_data(" + std::to_string(type) + "): type out of range"); } diff --git a/src/nrniv/netpar.cpp b/src/nrniv/netpar.cpp index 7951ab2945..01dd711394 100644 --- a/src/nrniv/netpar.cpp +++ b/src/nrniv/netpar.cpp @@ -314,7 +314,7 @@ void NetParEvent::savestate_restore(double tt, NetCvode* nc) { if (ithread_ == 0) { // npe_->pr("savestate_restore", tt, nc); for (int i = 0; i < nrn_nthread; ++i) - if (npe_ + i) { + if (i < n_npe_) { nc->event(tt, npe_ + i, nrn_threads + i); } } diff --git a/src/nrnoc/cabcode.cpp b/src/nrnoc/cabcode.cpp index e829279659..fe6de4e3a2 100644 --- a/src/nrnoc/cabcode.cpp +++ b/src/nrnoc/cabcode.cpp @@ -1569,7 +1569,6 @@ int nrn_at_beginning(Section* sec) { } static void nrn_rootnode_alloc(Section* sec) { - Extnode* nde; sec->parentnode = new Node{}; sec->parentnode->sec_node_index_ = 0; sec->parentnode->sec = sec; @@ -1873,7 +1872,7 @@ double* nrn_vext_pd(Symbol* s, int indx, Node* nd) { if (s->u.rng.type != EXTRACELL) { return (double*) 0; } - if (s->u.rng.index != neuron::extracellular::vext_pseudoindex()) { + if (std::size_t(s->u.rng.index) != neuron::extracellular::vext_pseudoindex()) { return nullptr; } zero = 0.; @@ -1905,7 +1904,8 @@ neuron::container::generic_data_handle dprop_impl(Prop* m, short inode) { #if EXTRACELLULAR // old comment: this does not handle vext(0) and vext(1) properly at this time - if (m->_type == EXTRACELL && s->u.rng.index == neuron::extracellular::vext_pseudoindex()) { + if (m->_type == EXTRACELL && + std::size_t(s->u.rng.index) == neuron::extracellular::vext_pseudoindex()) { return neuron::container::data_handle{neuron::container::do_not_search, sec->pnode[inode]->extnode->v + indx}; } @@ -1933,7 +1933,7 @@ neuron::container::data_handle dprop(Symbol* s, int indx, Section* sec, auto* const m = nrn_mechanism_check(s->u.rng.type, sec, inode); try { return neuron::container::data_handle{dprop_impl(m, s, indx, sec, inode)}; - } catch (VoidPointerError e) { + } catch (const VoidPointerError& e) { hoc_execerror(e.what(), nullptr); } } @@ -1952,7 +1952,7 @@ neuron::container::generic_data_handle nrnpy_dprop(Symbol* s, } try { return dprop_impl(m, s, indx, sec, inode); - } catch (VoidPointerError e) { + } catch (const VoidPointerError& e) { *err = 2; } return {}; @@ -2082,17 +2082,10 @@ int has_membrane(char* mechanism_name, Section* sec) { void ismembrane(void) { /* return true if string is an inserted membrane in the access section */ - char* str; - Prop* p; - - str = gargstr(1); + char* str = gargstr(1); hoc_retpushx((double) has_membrane(str, chk_access())); } -static const char* secaccessname() { - return secname(chk_access()); -} - void sectionname(void) { char** cpp; @@ -2259,7 +2252,7 @@ Section* nrn_section_exists(char* name, int indx, Object* cell) { } else { obd = hoc_top_level_data; } - if (indx < hoc_total_array_data(sym, obd)) { + if (indx >= 0 && std::size_t(indx) < hoc_total_array_data(sym, obd)) { itm = *(obd[sym->u.oboff].psecitm + indx); if (itm) { sec = itm->element.sec; @@ -2274,7 +2267,7 @@ void section_exists(void) { int iarg, indx; Section* sec; Object* obj; - char *str, *cp, buf[100]; + char *str, buf[100]; obj = nullptr; sec = (Section*) 0; From 4d749f114710f7c9fd3a9175df0c6e7841ab5f47 Mon Sep 17 00:00:00 2001 From: nrnhines Date: Tue, 17 Sep 2024 14:47:27 -0400 Subject: [PATCH 27/68] Don't look for KSChan channel __doc__ string with ModelView. (#3075) * Python test that pops up ModelView with KSChan. --- share/lib/python/neuron/__init__.py | 9 +++++---- test/hoctests/tests/test_mview.py | 8 ++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 test/hoctests/tests/test_mview.py diff --git a/share/lib/python/neuron/__init__.py b/share/lib/python/neuron/__init__.py index 4226d7fbdc..f84021c4da 100644 --- a/share/lib/python/neuron/__init__.py +++ b/share/lib/python/neuron/__init__.py @@ -742,10 +742,11 @@ def nrn_dll(printpath=False): def _modelview_mechanism_docstrings(dmech, tree): if dmech.name not in ("Ra", "capacitance"): - docs = getattr(h, dmech.name).__doc__ - if docs.strip(): - for line in docs.split("\n"): - tree.append(line, dmech.location, 0) + if hasattr(nrn, dmech.name): # KSChan not listed (and has no __doc__) + docs = getattr(h, dmech.name).__doc__ + if docs.strip(): + for line in docs.split("\n"): + tree.append(line, dmech.location, 0) _sec_db = {} diff --git a/test/hoctests/tests/test_mview.py b/test/hoctests/tests/test_mview.py new file mode 100644 index 0000000000..18a39c7db2 --- /dev/null +++ b/test/hoctests/tests/test_mview.py @@ -0,0 +1,8 @@ +# see PR #3075 +# Don't look for KSChan channel __doc__ string with ModelView. + +from neuron import h, gui + +h.load_file(h.neuronhome() + "/demo/dynclamp.hoc") +h.load_file("mview.hoc") +h.mview() From e462814e58383100d43785e84af9380b91d5e98e Mon Sep 17 00:00:00 2001 From: Fernando Pereira Date: Thu, 19 Sep 2024 16:28:01 +0100 Subject: [PATCH 28/68] Fix reference counting in `seg_from_sec_x`. (#3039) ### Context Following #3023, we noticed that there might be extraneous call to INCREF, given it's done on an object returned by `tp_alloc`, which should return a new reference. New references have their ref count to 1 and therefore it should not require any additional reference increment. ### Bug Reproducer ~$ nrniv -python ```python from neuron import h h("create soma") h("objref nc, nil") h('soma nc = new NetCon(&v(0.5), nil)') seg = h.nc.preseg() ``` Exit the interpreter and observe ``` Fatal Python error: bool_dealloc: deallocating True or False: bug likely caused by a refcount error in a C extension ``` ### Scope - Replace the code by the single function `newpysechelp(sec)` which seems to do just the right thing. - Added unit test ### Testing Two python unit tests added: - test_seg_from_sec_x_ref_python - test_seg_from_sec_x_ref_hocpy For debug-ability it might be worth to add the following snippet to `seg_from_sec_x` ``` auto* psec = sec->prop->dparam[PROP_PY_INDEX].get(); fprintf(stderr, "In seg_from_sec_x. Pysec=%p\n", psec); ``` We will see along the lines of ``` In seg_from_sec_x. Pysec=0x7fa081736150 In seg_from_sec_x. Pysec=0x0 ``` ensuring the we are exercising both cases. After dropping the original section, the pure-python code end up with the same number of references as the hoc-python code. --- src/nrnpython/nrnpy_nrn.cpp | 15 +----- test/unit_tests/hoc_python/test_refcounts.py | 55 ++++++++++++++++++++ 2 files changed, 57 insertions(+), 13 deletions(-) create mode 100644 test/unit_tests/hoc_python/test_refcounts.py diff --git a/src/nrnpython/nrnpy_nrn.cpp b/src/nrnpython/nrnpy_nrn.cpp index 83d88cbf2c..9a7154175a 100644 --- a/src/nrnpython/nrnpy_nrn.cpp +++ b/src/nrnpython/nrnpy_nrn.cpp @@ -1881,20 +1881,9 @@ static PyObject* mech_of_segment_iter_safe(NPySegObj* self) { static Object* seg_from_sec_x(Section* sec, double x) { auto pyseg = nb::steal((PyObject*) PyObject_New(NPySegObj, psegment_type)); auto* pseg = (NPySegObj*) pyseg.ptr(); - auto* pysec = static_cast(sec->prop->dparam[PROP_PY_INDEX].get()); - if (pysec) { - pseg->pysec_ = pysec; - Py_INCREF(pysec); - } else { - pysec = (NPySecObj*) psection_type->tp_alloc(psection_type, 0); - pysec->sec_ = sec; - pysec->name_ = 0; - pysec->cell_weakref_ = 0; - Py_INCREF(pysec); - pseg->pysec_ = pysec; - } + pseg->pysec_ = newpysechelp(sec); // newpysechelp() already increfs pseg->x_ = x; - return nrnpy_pyobject_in_obj(pyseg.ptr()); + return nrnpy_pyobject_in_obj((PyObject*) pseg); } static Object** pp_get_segment(void* vptr) { diff --git a/test/unit_tests/hoc_python/test_refcounts.py b/test/unit_tests/hoc_python/test_refcounts.py new file mode 100644 index 0000000000..005537e005 --- /dev/null +++ b/test/unit_tests/hoc_python/test_refcounts.py @@ -0,0 +1,55 @@ +from neuron import h, nrn +import gc +import sys + + +def test_seg_from_sec_x_ref_python(): + """ + A reproducer of calling `seg_from_sec_x` with a Python Section + """ + soma1 = nrn.Section("soma1") + nc1 = h.NetCon(soma1(0.5)._ref_v, None) + seg1 = nc1.preseg() + del soma1 + + assert sys.getrefcount(seg1) == 2 + # It is unclear why we get 3 ref-counts when we use plain python. With nrniv we get 2. + # At least it is consistent with the test below and we assert that the section + # really gets deleted (in hoc) + assert sys.getrefcount(seg1.sec) == 3 # seg->pysec_ + 1 + + del seg1 # NOTE: section fully destroyed together with segment + gc.collect() + + h("n_sections=0") + h("forall { n_sections+=1 }") + h('soma_is_valid=section_exists("soma1")') + assert h.n_sections == 0 + assert not h.soma_is_valid + + +def test_seg_from_sec_x_ref_hocpy(): + """A reproducer of calling `seg_from_sec_x` without a Python Section + + Without the fix we would get one extra ref to sec and possibly (upon interpreter exit): + "Fatal Python error: bool_dealloc: "deallocating True or False: bug likely caused by a + refcount error in a C extension" + """ + h("create soma") + h("objref nc") + h("objref nil") + h("soma nc = new NetCon(&v(0.5), nil)") + nc = h.nc + seg = nc.preseg() # uses `seg_from_sec_x` + + assert sys.getrefcount(seg) == 2 + assert sys.getrefcount(seg.sec) == 3 # seg->pysec_ + 1 + + del seg # NOTE: section py wrapper destroyed with segment, hoc-level section kept + gc.collect() + + h("n_sections=0") + h("forall { n_sections+=1 }") + h('soma_is_valid=section_exists("soma")') + assert h.n_sections == 1 + assert h.soma_is_valid From 592867672121645d396995d2fecca7875c59b552 Mon Sep 17 00:00:00 2001 From: wthun <43437733+wthun@users.noreply.github.com> Date: Fri, 20 Sep 2024 16:02:54 +0200 Subject: [PATCH 29/68] Increase max number of ions per compartment (#3055) * increased maximum number of ions per compartment by using std::bitset for bitvector comparisons * max_ion initialized to 256 in eion.cpp --------- Co-authored-by: Luc Grosheintz --- src/nrnoc/eion.cpp | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/src/nrnoc/eion.cpp b/src/nrnoc/eion.cpp index c591c541c5..4c841f4c2c 100644 --- a/src/nrnoc/eion.cpp +++ b/src/nrnoc/eion.cpp @@ -15,6 +15,10 @@ #include #include +#include +#include +#include + #undef hoc_retpushx @@ -60,7 +64,7 @@ double nrn_ion_charge(Symbol* sym) { void ion_register(void) { /* hoc level registration of ion name. Return -1 if name already - in use and not an ion; and the mechanism subtype otherwise. + in use and not an ion; and the mechanism subtype otherwise. */ char* name; Symbol* s; @@ -397,7 +401,11 @@ The argument `i` specifies which concentration is being written to. It's 0 for exterior; and 1 for interior. */ void nrn_check_conc_write(Prop* p_ok, Prop* pion, int i) { - static long *chk_conc_, *ion_bit_, size_; + const int max_ions = 256; + static long size_; + + static std::vector> chk_conc_, ion_bit_; + Prop* p; int flag, j, k; if (i == 1) { @@ -405,30 +413,26 @@ void nrn_check_conc_write(Prop* p_ok, Prop* pion, int i) { } else { flag = 0400; } - /* an embarassing hack */ - /* up to 32 possible ions */ - /* continuously compute a bitmap that allows determination - of which models WRITE which ion concentrations */ + + /* Create a vector holding std::bitset to track which ions + are being written to the membrane */ if (n_memb_func > size_) { - if (!chk_conc_) { - chk_conc_ = (long*) ecalloc(2 * n_memb_func, sizeof(long)); - ion_bit_ = (long*) ecalloc(n_memb_func, sizeof(long)); - } else { - chk_conc_ = (long*) erealloc(chk_conc_, 2 * n_memb_func * sizeof(long)); - ion_bit_ = (long*) erealloc(ion_bit_, n_memb_func * sizeof(long)); - for (j = size_; j < n_memb_func; ++j) { - chk_conc_[2 * j] = 0; - chk_conc_[2 * j + 1] = 0; - ion_bit_[j] = 0; - } + chk_conc_.resize(2 * n_memb_func); + ion_bit_.resize(n_memb_func); + + for (j = size_; j < n_memb_func; ++j) { + chk_conc_[2 * j].reset(); + chk_conc_[2 * j + 1].reset(); + ion_bit_[j].reset(); } + size_ = n_memb_func; } for (k = 0, j = 0; j < n_memb_func; ++j) { if (nrn_is_ion(j)) { ion_bit_[j] = (1 << k); ++k; - assert(k < sizeof(long) * 8); + assert(k < max_ions); } } @@ -439,7 +443,8 @@ void nrn_check_conc_write(Prop* p_ok, Prop* pion, int i) { if (p == p_ok) { continue; } - if (chk_conc_[2 * p->_type + i] & ion_bit_[pion->_type]) { + auto rst = chk_conc_[2 * p->_type + i] & ion_bit_[pion->_type]; + if (rst.any()) { char buf[300]; Sprintf(buf, "%.*s%c is being written at the same location by %s and %s", From 80a2c019fab74d74c1a368d8ab72a37e9f7f26fd Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Mon, 23 Sep 2024 16:29:31 +0000 Subject: [PATCH 30/68] Stop auto-formatting PRs. (#3087) Unfortunately, the auto-fromatting breaks running the CI. Leading to a workflow that requires pulling creating fake change and pushing again. Formatting is handled by Tristan's nice tool: ./external/coding-conventions/bin/format --- .github/workflows/formatting.yml | 51 -------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 .github/workflows/formatting.yml diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml deleted file mode 100644 index 434bef743d..0000000000 --- a/.github/workflows/formatting.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: Check formatting - -concurrency: - # Don't cancel on master, creating a PR when a push workflow is already going will cancel the push workflow in favour of the PR workflow - group: ${{ github.workflow }}-${{ github.ref == 'refs/heads/master' && github.run_id || github.event.number && github.head_ref || github.ref_name }} - cancel-in-progress: true - -on: - merge_group: - push: - branches: - - release/** - pull_request: - branches: - - master - - release/** - -jobs: - all: - name: C/C++, CMake and Python - runs-on: ubuntu-22.04 - timeout-minutes: 5 - steps: - - uses: actions/checkout@v4 - - name: Update submodule - working-directory: ${{runner.workspace}}/nrn - run: git submodule update --init external/coding-conventions - - name: Check formatting - working-directory: ${{runner.workspace}}/nrn - run: external/coding-conventions/bin/format -v --dry-run - - # If formatting fails, apply formatting and push changes. - # This will trigger another workflow run, which will cancel the current one. - - name: Apply formatting - working-directory: ${{runner.workspace}}/nrn - if: failure() && github.event_name == 'pull_request' - run: | - # Checkout PR - gh pr checkout ${{ github.event.pull_request.number }} - - # Apply formatting - external/coding-conventions/bin/format -v - - # Commit & push changes - git config --global user.name "github-actions[bot]" - git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add -u :/ - git commit -a -m "Fix formatting" - git push - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From d4ec2673c7936f07b746b64b66f359d545b2a5e0 Mon Sep 17 00:00:00 2001 From: Pramod Kumbhar Date: Mon, 23 Sep 2024 20:35:42 +0200 Subject: [PATCH 31/68] Do not link to libpython on MacOS with Anaconda Python (#3088) - Anaconda distribution on MacOS ship binary with static libpython and that causes segfault - See details in https://github.com/neuronsimulator/nrn/issues/2358#issuecomment-2368515786 Fixes #2358 --- cmake/PythonHelper.cmake | 9 +++++++++ docs/install/install_instructions.md | 10 ++++++++++ src/nrnpython/CMakeLists.txt | 5 ++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/cmake/PythonHelper.cmake b/cmake/PythonHelper.cmake index b4afd4ca4e..2e87b9cca7 100644 --- a/cmake/PythonHelper.cmake +++ b/cmake/PythonHelper.cmake @@ -178,6 +178,15 @@ function(nrn_find_python) PARENT_SCOPE) endfunction() +# Check if Python from Conda is being used on MacOS +if(NRN_MACOS_BUILD) + string(FIND "${PYTHON_EXECUTABLE}" "/anaconda" anaconda_found) + string(FIND "${PYTHON_EXECUTABLE}" "/miniconda" miniconda_found) + if(anaconda_found GREATER -1 OR miniconda_found GREATER -1) + set(NRN_WITH_MACOS_CONDA_PYTHON TRUE) + endif() +endif() + # For each Python in NRN_PYTHON_EXECUTABLES, find its version number, its include directory, and its # library path. Store those in the new lists NRN_PYTHON_VERSIONS, NRN_PYTHON_INCLUDES and # NRN_PYTHON_LIBRARIES. Set NRN_PYTHON_COUNT to be the length of those lists, and diff --git a/docs/install/install_instructions.md b/docs/install/install_instructions.md index dcce802840..a5024dd9df 100644 --- a/docs/install/install_instructions.md +++ b/docs/install/install_instructions.md @@ -493,3 +493,13 @@ If it prints `2.0` or higher, try installing an older version: pip install "numpy<2" ``` (mind the quotes.) Then delete the build directory, reconfigure and compile. If the error persists, carefully check which version of Python NEURON picked up by checking the output of the CMake configure command and make sure that that exact version of Python doesn't pick up an incompatible version of Numpy. + + +* **NEURON segfaults when using the Anaconda Python distribution. What can I do?** + +Some Anaconda distributions (e.g., macOS) ship Python binaries with `libpython` statically linked, +which has caused issues in NEURON and other packages (see discussion [here](https://github.com/neuronsimulator/nrn/issues/2358)). + +On the macOS platform, NEURON attempts to detect the use of Anaconda Python by checking for the `/anaconda` +prefix in the Python binary path. An alternative solution is to build NEURON with the dynamic Python +option enabled, using the CMake flag `-DNRN_ENABLE_PYTHON_DYNAMIC=ON`. diff --git a/src/nrnpython/CMakeLists.txt b/src/nrnpython/CMakeLists.txt index 92f28c651f..1a9696de9d 100644 --- a/src/nrnpython/CMakeLists.txt +++ b/src/nrnpython/CMakeLists.txt @@ -69,7 +69,10 @@ else() set_property(TARGET nrnpython PROPERTY POSITION_INDEPENDENT_CODE ON) target_include_directories(nrnpython PUBLIC ${INCLUDE_DIRS}) target_include_directories(nrnpython PUBLIC "${NRN_DEFAULT_PYTHON_INCLUDES}") - target_link_libraries(nrnpython ${NRN_DEFAULT_PYTHON_LIBRARIES}) + # see nrn/issues/2358 + if(NOT NRN_WITH_MACOS_CONDA_PYTHON) + target_link_libraries(nrnpython ${NRN_DEFAULT_PYTHON_LIBRARIES}) + endif() target_link_libraries(nrnpython fmt::fmt) target_include_directories(nrnpython PUBLIC ${PROJECT_SOURCE_DIR}/${NRN_3RDPARTY_DIR}/eigen) target_include_directories(nrnpython PUBLIC ${PROJECT_BINARY_DIR}/src/nrniv/oc_generated) From 0c3bfddda000848dc902eb5fc761d902a3a4278b Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Tue, 24 Sep 2024 12:47:13 +0200 Subject: [PATCH 32/68] Remove XDR option and PortablePointer (#3084) --- src/ivoc/checkpnt.cpp | 151 ++++++------------------------------------ 1 file changed, 22 insertions(+), 129 deletions(-) diff --git a/src/ivoc/checkpnt.cpp b/src/ivoc/checkpnt.cpp index 695d1aab7d..d9af9d045d 100644 --- a/src/ivoc/checkpnt.cpp +++ b/src/ivoc/checkpnt.cpp @@ -86,15 +86,10 @@ data depending on type. eg for VAR && NOTUSER it is */ -#define HAVE_XDR 0 - #include #include #include "oc2iv.h" #include "ocfunc.h" -#if HAVE_XDR -#include -#endif #include "checkpnt.h" #include "hoclist.h" @@ -207,46 +202,6 @@ implementTable(Symbols, Symbol*, int) declareTable(Objects, Object*, int) implementTable(Objects, Object*, int) -class PortablePointer { - public: - PortablePointer(); - PortablePointer(void* address, int type, unsigned long size = 1); - virtual ~PortablePointer(); - void set(void* address, int type, unsigned long size = 1); - void size(unsigned long s) { - size_ = s; - } - unsigned long size() { - return size_; - } - void* address() { - return address_; - } - int type() { - return type_; - } - - private: - void* address_; - int type_; - unsigned long size_; -}; - -PortablePointer::PortablePointer() { - address_ = NULL; - type_ = 0; - size_ = 0; -} -PortablePointer::PortablePointer(void* address, int type, unsigned long s) { - set(address, type, s); -} -void PortablePointer::set(void* address, int type, unsigned long s) { - address_ = address; - type_ = type; - size_ = s; -} -PortablePointer::~PortablePointer() {} - class OcCheckpoint { public: OcCheckpoint(); @@ -260,7 +215,6 @@ class OcCheckpoint { bool pass2(); bool make_sym_table(); bool build_map(); - PortablePointer* find(void*); bool func(Symbol*); @@ -295,9 +249,6 @@ class OcCheckpoint { Objects* otable_; bool (OcCheckpoint::*func_)(Symbol*); Symbols* stable_; -#if HAVE_XDR - XDR xdrs_; -#endif Objectdata* objectdata_; }; @@ -432,22 +383,6 @@ OcCheckpoint::~OcCheckpoint() { } } -#if HAVE_XDR -#define USEXDR 1 -#else -#define USEXDR 0 -#endif - -#undef DEBUG - -#if USEXDR -#define DEBUG \ - if (0) \ - fprintf -#else -#define DEBUG fprintf -#endif - bool OcCheckpoint::write(const char* fname) { bool b; int i; @@ -457,9 +392,6 @@ bool OcCheckpoint::write(const char* fname) { return false; } fprintf(f_, "NEURON Checkpoint\n"); -#if USEXDR - xdrstdio_create(&xdrs_, f_, XDR_ENCODE); -#endif b = make_sym_table(); func_ = &OcCheckpoint::sym_out; b = (b && pass1()); @@ -480,9 +412,6 @@ bool OcCheckpoint::write(const char* fname) { b = b && pass1(); i = -1; b = (b && xdr(i)); -#if USEXDR - xdr_destroy(&xdrs_); -#endif fclose(f_); return b; } @@ -496,7 +425,7 @@ bool OcCheckpoint::make_sym_table() { if (!b) { printf("make_sym_table failed on first pass1\n"); } - DEBUG(f_, "#symbols=%d\n", cnt_); + fprintf(f_, "#symbols=%d\n", cnt_); b = (b && xdr(cnt_)); if (stable_) { delete stable_; @@ -531,7 +460,7 @@ bool OcCheckpoint::sym_table_install(Symbol* s) { bool OcCheckpoint::sym_out(Symbol* s) { int val; stable_->find(val, s); - DEBUG(f_, "%d %s %d %d\n", val, s->name, s->type, s->subtype); + fprintf(f_, "%d %s %d %d\n", val, s->name, s->type, s->subtype); int l1 = strlen(s->name); bool b = xdr(val) && xdr(s->name, l1) && xdr(s->type) && xdr(s->subtype) && xdr(s->cpublic) && xdr(s->s_varn) && xdr(s->defined_on_the_fly); @@ -576,9 +505,6 @@ bool OcCheckpoint::pass2() { bool OcCheckpoint::build_map() { return false; } -PortablePointer* find(void*) { - return NULL; -} bool OcCheckpoint::func(Symbol* s) { if (func_) { return (this->*func_)(s); @@ -592,7 +518,7 @@ bool OcCheckpoint::symlist(Symlist* sl) { for (Symbol* s = sl->first; s; s = s->next) { ++i; } - DEBUG(f_, "symboltable size %d\n", i); + fprintf(f_, "symboltable size %d\n", i); if (!xdr(i)) { return false; } @@ -633,8 +559,8 @@ bool OcCheckpoint::sym_instructions(Symbol* s) { return false; } if (p->size) { - DEBUG(f_, "instructions for %d |%s|\n", val, s->name); - DEBUG(f_, "size %lu\n", p->size); + fprintf(f_, "instructions for %d |%s|\n", val, s->name); + fprintf(f_, "size %lu\n", p->size); bool b = xdr(val) && xdr(p->size); if (!b) { printf("failed in sym_intructions\n"); @@ -654,7 +580,7 @@ bool OcCheckpoint::instlist(unsigned long size, Inst* in) { short val; int sval; if (in[i].in == STOP) { - DEBUG(f_, " STOP\n"); + fprintf(f_, " STOP\n"); val = 0; if (!xdr(val)) { printf("instlist failed 1\n"); @@ -663,7 +589,7 @@ bool OcCheckpoint::instlist(unsigned long size, Inst* in) { continue; } if (inst_table_->find(val, (VPfri) in[i].pf)) { - DEBUG(f_, " %d\n", val); + fprintf(f_, " %d\n", val); if (!xdr(val)) { printf("instlist failed 2\n"); return false; @@ -680,13 +606,13 @@ bool OcCheckpoint::instlist(unsigned long size, Inst* in) { i); return false; } - // DEBUG(f_, " %d |%s|\n", sval, in[i].sym->name); + // fprintf(f_, " %d |%s|\n", sval, in[i].sym->name); if (!xdr(sval)) { printf("instlist failed 3\n"); return false; } } else { - DEBUG(f_, " 0 SYMBOL0\n"); + fprintf(f_, " 0 SYMBOL0\n"); sval = 0; if (!xdr(sval)) { printf("instlist failed 4\n"); @@ -695,7 +621,7 @@ bool OcCheckpoint::instlist(unsigned long size, Inst* in) { } break; case 'i': - DEBUG(f_, " %i\n", in[i].i); + fprintf(f_, " %i\n", in[i].i); if (!xdr(in[i].i)) { printf("instlist failed 5\n"); return false; @@ -720,7 +646,7 @@ bool OcCheckpoint::ctemplate(Symbol* s) { int ti; bool b; b = stable_->find(ti, s); - DEBUG(f_, "%d %d %s\n", ti, t->count, s->name); + fprintf(f_, "%d %d %s\n", ti, t->count, s->name); b = b && xdr(ti); // b = b && xdr(t->count); hoc_Item* q; @@ -807,16 +733,16 @@ long OcCheckpoint::arrayinfo(Symbol* s, Objectdata* od) { } long n = long(hoc_total_array_data(s, od)); if (!as) { // not an array - DEBUG(f_, "0\n"); + fprintf(f_, "0\n"); int i = 0; xdr(i); } else if (od && as == ao) { // same as original - DEBUG(f_, "-1\n"); + fprintf(f_, "-1\n"); int i = -1; xdr(i); } else { int v = ao->a_varn ? 1 : 0; - DEBUG(f_, "%d %d %d", ao->nsub, ao->refcount, v); + fprintf(f_, "%d %d %d", ao->nsub, ao->refcount, v); if (v) { printf("checkpoint of equation array vars not implemented: %s\n", s->name); return -1; @@ -825,10 +751,10 @@ long OcCheckpoint::arrayinfo(Symbol* s, Objectdata* od) { // xdr(ao->refcount); // xdr(v); for (int i = 0; i < ao->nsub; ++i) { - DEBUG(f_, " %d", ao->sub[i]); + fprintf(f_, " %d", ao->sub[i]); xdr(ao->sub[i]); } - DEBUG(f_, "\n"); + fprintf(f_, "\n"); } return n; } @@ -843,43 +769,34 @@ bool OcCheckpoint::sym_values(Symbol* s) { stable_->find(sp, s); if ((s->type == VAR && s->subtype == NOTUSER) || s->type == OBJECTVAR || s->type == STRING || s->type == SECTION) { - DEBUG(f_, "%d %s\n", sp, s->name); + fprintf(f_, "%d %s\n", sp, s->name); b = xdr(sp); long n = arrayinfo(s, objectdata_); if (n == -1) { return false; } - // DEBUG(f_, " %ld\n", n); + // fprintf(f_, " %ld\n", n); // b = b && xdr(n); for (long i = 0; i < n; ++i) { Objectdata od = objectdata_[s->u.oboff]; if (s->type == VAR) { double d = od.pval[i]; - DEBUG(f_, " %g\n", d); + fprintf(f_, " %g\n", d); b = b && xdr(d); } else if (s->type == OBJECTVAR) { Object* ob = od.pobj[i]; if (ob == NULL) { - DEBUG(f_, " 0\n"); + fprintf(f_, " 0\n"); int i = 0; b = b && xdr(i); } else { -#if 0 - int t; - stable_->find(t, ob->ctemplate->sym); - DEBUG(f_, " %d %d %s\n", t, ob->index, - ob->ctemplate->sym->name); - b = b && xdr(t); - b = b && xdr(ob->index); -#else int oid; b = b && otable_->find(oid, ob); b = b && xdr(oid); -#endif } } else if (s->type == STRING) { char* cp = od.ppstr[i]; - DEBUG(f_, " |%s|\n", cp); + fprintf(f_, " |%s|\n", cp); b = b && xdr(cp, strlen(cp)); // }else if (s->type == SECTION) { } @@ -888,23 +805,6 @@ bool OcCheckpoint::sym_values(Symbol* s) { return true; } -#if USEXDR && 0 -bool OcCheckpoint::xdr(int& i) { - return xdr_int(&xdrs_, &i); -} -bool OcCheckpoint::xdr(char*& i, int size) { - return xdr_string(&xdrs_, &i, size); -} -bool OcCheckpoint::xdr(short& i) { - return xdr_short(&xdrs_, &i); -} -bool OcCheckpoint::xdr(unsigned int& i) { - return xdr_u_int(&xdrs_, &i); -} -bool OcCheckpoint::xdr(unsigned long& i) { - return xdr_u_long(&xdrs_, &i); -} -#else bool OcCheckpoint::xdr(int& i) { fprintf(f_, "%d\n", i); return true; @@ -936,7 +836,7 @@ bool OcCheckpoint::xdr(double& i) { fprintf(f_, "%g\n", i); return true; } -#endif + bool OcCheckpoint::xdr(Object*& o) { int i; bool b; @@ -1230,13 +1130,6 @@ bool OcReadChkPnt::objectdata() { switch (sym->type) { case VAR: n = arrayinfo(sym, od); -#if 0 - Get(i); //not necessary but if present don't forget others - if (i != n) { - printf("inconsistent array size %d %d\n", i, n); - returnf false; - } -#endif odp = od + sym->u.oboff; if (od != hoc_top_level_data || builtin_size_ <= sym->u.oboff) { odp->pval = new double[n]; From 956ae0103356a4ab66d4c70efb4c4e0ddb9cb887 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Tue, 24 Sep 2024 16:06:21 +0200 Subject: [PATCH 33/68] Replace IVOS/Table by std::map (#3083) --- src/ivoc/checkpnt.cpp | 161 +++++++++++++++++++----------------------- 1 file changed, 71 insertions(+), 90 deletions(-) diff --git a/src/ivoc/checkpnt.cpp b/src/ivoc/checkpnt.cpp index d9af9d045d..77006fa5e4 100644 --- a/src/ivoc/checkpnt.cpp +++ b/src/ivoc/checkpnt.cpp @@ -1,5 +1,7 @@ #include <../../nrnconf.h> #if HAVE_IV // to end of file +#include +#include /* @@ -192,20 +194,12 @@ static struct HocInst { {0, 0}}; #define VPfri void* -declareTable(InstTable, VPfri, short) -implementTable(InstTable, VPfri, short) -static InstTable* inst_table_; - -declareTable(Symbols, Symbol*, int) -implementTable(Symbols, Symbol*, int) - -declareTable(Objects, Object*, int) -implementTable(Objects, Object*, int) +static std::map* inst_table_; class OcCheckpoint { public: OcCheckpoint(); - virtual ~OcCheckpoint(); + virtual ~OcCheckpoint() = default; bool write(const char*); @@ -246,9 +240,9 @@ class OcCheckpoint { private: int cnt_; int nobj_; - Objects* otable_; - bool (OcCheckpoint::*func_)(Symbol*); - Symbols* stable_; + std::unique_ptr> otable_{}; + bool (OcCheckpoint::*func_)(Symbol*) = nullptr; + std::unique_ptr> stable_{}; Objectdata* objectdata_; }; @@ -359,30 +353,14 @@ int hoc_readcheckpoint(char* fname) { } OcCheckpoint::OcCheckpoint() { - func_ = NULL; - stable_ = NULL; - otable_ = NULL; if (!inst_table_) { - short i; - for (i = 1; hoc_inst_[i].pi; ++i) { - ; - } - inst_table_ = new InstTable(2 * i); - for (i = 1; hoc_inst_[i].pi; ++i) { - inst_table_->insert((VPfri) hoc_inst_[i].pi, i); + inst_table_ = new std::map{}; + for (int i = 1; hoc_inst_[i].pi; ++i) { + inst_table_->emplace((VPfri) hoc_inst_[i].pi, i); } } } -OcCheckpoint::~OcCheckpoint() { - if (stable_) { - delete stable_; - } - if (otable_) { - delete otable_; - } -} - bool OcCheckpoint::write(const char* fname) { bool b; int i; @@ -427,10 +405,7 @@ bool OcCheckpoint::make_sym_table() { } fprintf(f_, "#symbols=%d\n", cnt_); b = (b && xdr(cnt_)); - if (stable_) { - delete stable_; - } - stable_ = new Symbols(2 * cnt_); + stable_ = std::make_unique>(); cnt_ = 1; func_ = &OcCheckpoint::sym_table_install; if (!b) { @@ -453,13 +428,13 @@ bool OcCheckpoint::sym_count(Symbol* s) { } bool OcCheckpoint::sym_table_install(Symbol* s) { - stable_->insert(s, cnt_); + stable_->emplace(s, cnt_); ++cnt_; return true; } bool OcCheckpoint::sym_out(Symbol* s) { - int val; - stable_->find(val, s); + auto it = stable_->find(s); + int val = it != stable_->end() ? it->second : 0; fprintf(f_, "%d %s %d %d\n", val, s->name, s->type, s->subtype); int l1 = strlen(s->name); bool b = xdr(val) && xdr(s->name, l1) && xdr(s->type) && xdr(s->subtype) && xdr(s->cpublic) && @@ -553,11 +528,12 @@ bool OcCheckpoint::symbol(Symbol* s) { bool OcCheckpoint::sym_instructions(Symbol* s) { Proc* p = s->u.u_proc; if (s->type == FUNCTION || s->type == PROCEDURE) { - int val; - if (!stable_->find(val, s)) { + auto it = stable_->find(s); + if (it == stable_->end()) { printf("couldn't find %s in table\n", s->name); return false; } + int val = it->second; if (p->size) { fprintf(f_, "instructions for %d |%s|\n", val, s->name); fprintf(f_, "size %lu\n", p->size); @@ -577,18 +553,17 @@ bool OcCheckpoint::sym_instructions(Symbol* s) { } bool OcCheckpoint::instlist(unsigned long size, Inst* in) { for (unsigned long i = 0; i < size; ++i) { - short val; - int sval; if (in[i].in == STOP) { fprintf(f_, " STOP\n"); - val = 0; - if (!xdr(val)) { + int sval = 0; + if (!xdr(sval)) { printf("instlist failed 1\n"); return false; } continue; } - if (inst_table_->find(val, (VPfri) in[i].pf)) { + if (auto it = inst_table_->find((VPfri) in[i].pf); it != inst_table_->end()) { + auto val = it->second; fprintf(f_, " %d\n", val); if (!xdr(val)) { printf("instlist failed 2\n"); @@ -600,12 +575,14 @@ bool OcCheckpoint::instlist(unsigned long size, Inst* in) { switch (s[j]) { case 's': if (in[i].sym) { - if (!stable_->find(sval, in[i].sym)) { + auto it = stable_->find(in[i].sym); + if (it == stable_->end()) { printf("couldn't find |%s| in table at instruction index %ld\n", in[i].sym->name, i); return false; } + auto sval = it->second; // fprintf(f_, " %d |%s|\n", sval, in[i].sym->name); if (!xdr(sval)) { printf("instlist failed 3\n"); @@ -613,7 +590,7 @@ bool OcCheckpoint::instlist(unsigned long size, Inst* in) { } } else { fprintf(f_, " 0 SYMBOL0\n"); - sval = 0; + int sval = 0; if (!xdr(sval)) { printf("instlist failed 4\n"); return false; @@ -643,17 +620,19 @@ bool OcCheckpoint::ctemplate(Symbol* s) { cTemplate* t = s->u.ctemplate; if (func_ == &OcCheckpoint::sym_values) { Objectdata* saveod = objectdata_; - int ti; - bool b; - b = stable_->find(ti, s); + auto it = stable_->find(s); + bool b = it != stable_->end(); + auto ti = b ? it->second : 0; fprintf(f_, "%d %d %s\n", ti, t->count, s->name); b = b && xdr(ti); // b = b && xdr(t->count); hoc_Item* q; ITERATE(q, t->olist) { Object* ob = OBJ(q); - int oid; - b = b && otable_->find(oid, ob); + auto it = otable_->find(ob); + bool found = it != otable_->end(); + b = b && found; + int oid = found ? it->second : 0; b = b && xdr(oid); if (t->constructor) { if (t->checkpoint) { @@ -677,42 +656,42 @@ bool OcCheckpoint::ctemplate(Symbol* s) { } } bool OcCheckpoint::object() { - bool b; - int i; - if (otable_) { - delete otable_; - } - b = xdr(nobj_); - otable_ = new Objects(2 * nobj_ + 1); + bool b = xdr(nobj_); + otable_ = std::make_unique>(); nobj_ = 0; func_ = &OcCheckpoint::objects; b = pass1(); - i = -1; + int i = -1; b = b && xdr(i); return b; } bool OcCheckpoint::objects(Symbol* s) { - bool b = true; - if (s->type == TEMPLATE) { - int sid; - b = b && stable_->find(sid, s); - b = b && xdr(sid); - cTemplate* t = s->u.ctemplate; + if (s->type != TEMPLATE) { + return true; + } + + auto it = stable_->find(s); + bool b = it != stable_->end(); + int sid = b ? it->second : 0; + b = b && xdr(sid); + cTemplate* t = s->u.ctemplate; #undef init - if (t->init) { - b = b && stable_->find(sid, t->init); - } else { - sid = 0; - } - b = b && xdr(sid); - b = b && xdr(t->index) && xdr(t->count) && xdr(t->id); - hoc_Item* q; - ITERATE(q, t->olist) { - Object* ob = OBJ(q); - ++nobj_; - otable_->insert(ob, nobj_); // 0 is null object - b = b && xdr(nobj_) && xdr(ob->refcount) && xdr(ob->index); - } + if (t->init) { + auto it2 = stable_->find(t->init); + bool b2 = it2 != stable_->end(); + b = b && b2; + sid = b2 ? it2->second : sid; + } else { + sid = 0; + } + b = b && xdr(sid); + b = b && xdr(t->index) && xdr(t->count) && xdr(t->id); + hoc_Item* q; + ITERATE(q, t->olist) { + Object* ob = OBJ(q); + ++nobj_; + otable_->emplace(ob, nobj_); // 0 is null object + b = b && xdr(nobj_) && xdr(ob->refcount) && xdr(ob->index); } return b; } @@ -764,9 +743,10 @@ bool OcCheckpoint::proc(Proc*) { } bool OcCheckpoint::sym_values(Symbol* s) { - int sp; bool b; - stable_->find(sp, s); + auto it = stable_->find(s); + int sp = it != stable_->end() ? it->second : 0; + if ((s->type == VAR && s->subtype == NOTUSER) || s->type == OBJECTVAR || s->type == STRING || s->type == SECTION) { fprintf(f_, "%d %s\n", sp, s->name); @@ -790,8 +770,10 @@ bool OcCheckpoint::sym_values(Symbol* s) { int i = 0; b = b && xdr(i); } else { - int oid; - b = b && otable_->find(oid, ob); + auto it = otable_->find(ob); + bool found = it != otable_->end(); + int oid = found ? it->second : 0; + b = b && found; b = b && xdr(oid); } } else if (s->type == STRING) { @@ -838,11 +820,10 @@ bool OcCheckpoint::xdr(double& i) { } bool OcCheckpoint::xdr(Object*& o) { - int i; - bool b; - b = otable_->find(i, o); - b = b && xdr(i); - return b; + auto it = otable_->find(o); + bool b = it != otable_->end(); + int i = b ? it->second : 0; + return b && xdr(i); } #undef Chk From dc9d4c91b013a68bee3ff746d5ff143055552044 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Tue, 24 Sep 2024 17:44:13 +0200 Subject: [PATCH 34/68] Remove feature checkpoint (#3092) This feature has never been completed and is replaced by SaveState. --- cmake/NeuronFileLists.cmake | 1 - docs/guide/hoc_chapter_11_old_reference.rst | 2 +- docs/hoc/simctrl/programmatic.rst | 31 - docs/python/simctrl/programmatic.rst | 30 - share/lib/helpdict | 1 - src/ivoc/checkpnt.cpp | 1265 ------------------- src/ivoc/checkpnt.h | 18 - src/ivoc/graph.cpp | 2 +- src/ivoc/grglyph.cpp | 2 +- src/ivoc/ivocrand.cpp | 2 +- src/ivoc/ivocvect.cpp | 2 +- src/ivoc/matrix.cpp | 2 +- src/ivoc/mlinedit.cpp | 2 +- src/ivoc/mymath.cpp | 2 +- src/ivoc/ocbox.cpp | 4 +- src/ivoc/ocdeck.cpp | 2 +- src/ivoc/ocfile.cpp | 2 +- src/ivoc/oclist.cpp | 32 +- src/ivoc/ocnoiv1.cpp | 9 - src/ivoc/ocpointer.cpp | 2 +- src/ivoc/ocptrvector.cpp | 2 +- src/ivoc/octimer.cpp | 2 +- src/ivoc/pwman.cpp | 2 +- src/ivoc/strfun.cpp | 2 +- src/ivoc/symchoos.cpp | 2 +- src/ivoc/xmenu.cpp | 2 +- src/nrncvode/cvodeobj.cpp | 2 +- src/nrncvode/netcvode.cpp | 2 +- src/nrniv/bbsavestate.cpp | 2 +- src/nrniv/finithnd.cpp | 2 +- src/nrniv/impedanc.cpp | 2 +- src/nrniv/kschan.cpp | 8 +- src/nrniv/linmod1.cpp | 2 +- src/nrniv/nmodlrandom.cpp | 1 - src/nrniv/nrnmenu.cpp | 4 +- src/nrniv/nrnpy.cpp | 2 +- src/nrniv/nrnste.cpp | 2 +- src/nrniv/ppshape.cpp | 2 +- src/nrniv/savstate.cpp | 2 +- src/nrniv/secbrows.cpp | 2 +- src/nrniv/shape.cpp | 2 +- src/nrniv/shapeplt.cpp | 2 +- src/nrniv/spaceplt.cpp | 2 +- src/nrnoc/init.cpp | 3 +- src/nrnoc/seclist.cpp | 3 +- src/nrnoc/secref.cpp | 3 +- src/nrnpython/nrnpy_p2h.cpp | 2 +- src/oc/classreg.h | 1 - src/oc/hoc.cpp | 15 - src/oc/hoc_init.cpp | 1 - src/oc/hoc_oop.cpp | 6 +- src/oc/hocdec.h | 1 - src/oc/ocfunc.h | 2 +- src/parallel/ocbbs.cpp | 2 +- test/unit_tests/oc/hoc_interpreter.cpp | 1 - 55 files changed, 47 insertions(+), 1459 deletions(-) delete mode 100644 src/ivoc/checkpnt.cpp delete mode 100644 src/ivoc/checkpnt.h diff --git a/cmake/NeuronFileLists.cmake b/cmake/NeuronFileLists.cmake index 9809bf8f88..ca4fbcdbfa 100644 --- a/cmake/NeuronFileLists.cmake +++ b/cmake/NeuronFileLists.cmake @@ -149,7 +149,6 @@ set(IVOC_FILE_LIST axis.cpp bndedval.cpp cbwidget.cpp - checkpnt.cpp epsprint.cpp fourier.cpp gifimage.cpp diff --git a/docs/guide/hoc_chapter_11_old_reference.rst b/docs/guide/hoc_chapter_11_old_reference.rst index aeeb70bbf0..790d095e8f 100644 --- a/docs/guide/hoc_chapter_11_old_reference.rst +++ b/docs/guide/hoc_chapter_11_old_reference.rst @@ -310,7 +310,7 @@ Keywords string_dialog doEvents doNotify numarg hoc_pointer_ execute execute1 load_proc load_func load_template machine_name saveaudit retrieveaudit coredump_on_error - checkpoint quit object_push object_pop pwman_place + quit object_push object_pop pwman_place show_errmess_always numprocs myproc psync settext secname diff --git a/docs/hoc/simctrl/programmatic.rst b/docs/hoc/simctrl/programmatic.rst index 3cec92a87b..4f3d46e59e 100644 --- a/docs/hoc/simctrl/programmatic.rst +++ b/docs/hoc/simctrl/programmatic.rst @@ -346,37 +346,6 @@ Functions ---- -.. hoc:function:: checkpoint - - Syntax: - :samp:`checkpoint("{filename}")` - - Description: - saves the current state of the system in a portable file to - allow one to take up where you left off -- possibly on another - machine. Returning to this state is accomplished by running the - program with the checkpoint file as the first argument. - If the checkpoint file is inconsistent with the executable the - program prints an error message and exits. - - At this time many portions of the computer state are left out of the - checkpoint file, i.e. it is not as complete as a core dump. - Some things that ARE included are: - all interpreter symbols with definitions and values, - all hoc instructions, - all neuron state/parameters with mechanisms. - Many aspects of the GUI are not included. - - .. warning:: - There is not enough implementation at this time to make this - facility useful. Use the :hoc:class:`SaveState` class instead. - - - - ----- - - .. _hoc_finithnd: diff --git a/docs/python/simctrl/programmatic.rst b/docs/python/simctrl/programmatic.rst index ce082d8498..1f4646da54 100755 --- a/docs/python/simctrl/programmatic.rst +++ b/docs/python/simctrl/programmatic.rst @@ -345,36 +345,6 @@ Functions It is cleared at the beginning of a run or when continuing a run. ----- - -.. function:: checkpoint - - Syntax: - :samp:`h.checkpoint("{filename}")` - - Description: - saves the current state of the system in a portable file to - allow one to take up where you left off -- possibly on another - machine. Returning to this state is accomplished by running the - program with the checkpoint file as the first argument. - If the checkpoint file is inconsistent with the executable the - program prints an error message and exits. - - At this time many portions of the computer state are left out of the - checkpoint file, i.e. it is not as complete as a core dump. - Some things that ARE included are: - all interpreter symbols with definitions and values, - all hoc instructions, - all neuron state/parameters with mechanisms. - Many aspects of the GUI are not included. - - .. warning:: - There is not enough implementation at this time to make this - facility useful. Use the :class:`SaveState` class instead. - - - - ---- .. _finithnd: diff --git a/share/lib/helpdict b/share/lib/helpdict index fbfaf1a699..aa978a7a17 100755 --- a/share/lib/helpdict +++ b/share/lib/helpdict @@ -80,7 +80,6 @@ Changeparmfromlist Extras RunFitter StandardRunTools GUI Reference 449 neuron/st ChangeText Graph LookAndFeel GUI Reference 18 neuron/agui/gui.html#ChangeText Channels ModelDescriptionIssues CVode classes neuron neuron.exe Reference 258 neuron/neuron/classes/cvode.html#Channels chdir functions general neuron.exe Reference 177 neuron/general/function/0fun.html#chdir -checkpoint functions general neuron.exe Reference 179 neuron/general/function/checkpnt.html#checkpoint child SectionRef classes neuron neuron.exe Reference 320 neuron/neuron/classes/secref.html#child children SectionList classes neuron neuron.exe Reference 317 neuron/neuron/classes/seclist.html#children chooser File classes general neuron.exe Reference 32 neuron/general/classes/file.html#chooser diff --git a/src/ivoc/checkpnt.cpp b/src/ivoc/checkpnt.cpp deleted file mode 100644 index 77006fa5e4..0000000000 --- a/src/ivoc/checkpnt.cpp +++ /dev/null @@ -1,1265 +0,0 @@ -#include <../../nrnconf.h> -#if HAVE_IV // to end of file -#include -#include - -/* - -strategy: - -symbols - hoc_built_in_symlist - hoc_top_level_symlist - symlists for each template - object data -linked-function pointers - -procedures - symbol pointers and linked function pointers used here - -nrnoc - mostly data but also pointers in the dparam. - because of setpointer (eg, pre-synaptic potential, these can - be pointers to any object data or nrnoc data. - - -bottom line: - extremely important to have generic method for pointers to any - location of an allocated block. - -two pass: - allocate all blocks - make pointer map - fill pointers - -two kinds of pointers - ownership -- responsible for allocating the space - observer -map - key address size type - -This was my initial thought. The incremental implementation has -evolved considerably with many ad hoc aspects and false starts. - -assume usage of compatible executeable. This means the same hoc_built_in_symlist -for writing and reading the checkpoint. For now we save this symlist in the -checkpoint and on reading check to make sure it is the same as the one -in memory. If so I think we have prima facie evidence that the instruction -list is consistent. ie add() -inst_table-> int ---> int -hoc_inst[]-> add(). -the hoc_inst[] contains the signature of an instruction that tells what -(if anything)is expected on the execution list. -All other built-in functions are accessed through their symbols. -In fact all symbols are transmitted via - sym -stable_-> int -----> int -symplist[]-> sym - -Here is the format of the checkpoint file (no leading blanks in file): - -total number of symbols -hoc_built-in-symlist (in recursive symbol and table format) -hoc_top_level_symlist (in recursive symbol and table format) -instructions for all FUNC/PROC symbols --1 -Objectdata (VAR with NOTUSER subtype, OBJECTVAR, STRING) and local data --1 -ivoc,nrnoc, nrniv stuff (to be implemented) - - -The recursive symbol and table format is -symtable size -symbolinteger type subtype -symbolname - if the symbol is of a type that itself has a symbol table then we recurse - -instructions for all ... is a -1 terminated list of -symbolinteger -size -instructionintegers mingled with - signature info consisting of symbolinteger, integer, etc - -Objectdata etc is -1 terminated list of -symbolinteger -data depending on type. eg for VAR && NOTUSER it is - arrayinfo - values for all elements in the array - and for OBJECTVAR it is - arrayinfo - Objectdata recursion for all elements in the array - objectref to the objects for all elements in the array - -*/ - -#include -#include -#include "oc2iv.h" -#include "ocfunc.h" -#include "checkpnt.h" - -#include "hoclist.h" -#include "parse.hpp" -#include "code.h" -#include "equation.h" -int hoc_readcheckpoint(char*); -extern int hoc_resize_toplevel(int); - -static struct HocInst { - Pfrv pi; - const char* signature; -} hoc_inst_[] = {{0, 0}, // 0 - {hoc_nopop, 0}, - {hoc_eval, 0}, - {hoc_add, 0}, - {hoc_sub, 0}, - {hoc_mul, 0}, - {hoc_div, 0}, - {hoc_negate, nullptr}, - {hoc_power, 0}, - {hoc_assign, nullptr}, - {hoc_bltin, "s"}, // requires change - {hoc_varpush, "s"}, // 10 - {hoc_constpush, "s"}, - {hoc_pushzero, 0}, - {hoc_print, 0}, - {hoc_varread, "s"}, - {hoc_prexpr, 0}, - {hoc_prstr, 0}, - {hoc_gt, 0}, - {hoc_lt, nullptr}, - {hoc_eq, nullptr}, // 20 - {hoc_ge, 0}, - {hoc_le, 0}, - {hoc_ne, 0}, - {hoc_and, 0}, - {hoc_or, 0}, - {hoc_not, 0}, - {hoc_ifcode, "iii"}, - {hoc_forcode, "iii"}, - {hoc_shortfor, "ii"}, - {hoc_call, "si"}, // 30 - {hoc_arg, "i"}, - {hoc_argassign, "i"}, - {hoc_funcret, 0}, - {hoc_procret, 0}, - {hoc_stringarg, "i"}, - {hoc_push_string, "s"}, - {hoc_Break, 0}, - {hoc_Continue, 0}, - {hoc_Stop, 0}, - {hoc_assstr, 0}, // 40 - {hoc_evalpointer, 0}, - {hoc_newline, 0}, - {hoc_delete_symbol, "s"}, - {hoc_cyclic, 0}, - {hoc_dep_make, 0}, - {hoc_eqn_name, 0}, - {hoc_eqn_init, 0}, - {hoc_eqn_lhs, 0}, // 50 - {hoc_eqn_rhs, 0}, - {hoc_objectvar, "s"}, - {hoc_object_component, "siis"}, - {hoc_object_eval, 0}, - {hoc_object_asgn, 0}, - {hoc_objvardecl, "si"}, - {hoc_cmp_otype, "i"}, - {hoc_newobj, "si"}, - {hoc_asgn_obj_to_str, 0}, - {hoc_known_type, "i"}, // 60 - {hoc_push_string, "s"}, - {hoc_objectarg, "i"}, - {hoc_ob_pointer, 0}, - {connectsection, 0}, - {simpleconnectsection, 0}, - {connectpointer, "s"}, - {add_section, "si"}, - {range_const, "s"}, - {range_interpolate, "s"}, - {range_interpolate_single, "s"}, // 70 - {rangevareval, "s"}, - {rangepoint, "s"}, - {sec_access, "s"}, - {ob_sec_access, 0}, - {mech_access, "s"}, - {for_segment, "ii"}, - {sec_access_push, "s"}, - {sec_access_pop, 0}, - {forall_section, "ii"}, - {hoc_ifsec, "ii"}, // 80 - {hoc_ifseclist, "ii"}, - {forall_sectionlist, "ii"}, - {connect_point_process_pointer, 0}, - {nrn_cppp, 0}, - {rangevarevalpointer, "s"}, - {sec_access_object, 0}, - {mech_uninsert, "s"}, - {hoc_arayinstal, "i"}, - {0, 0}}; - -#define VPfri void* -static std::map* inst_table_; - -class OcCheckpoint { - public: - OcCheckpoint(); - virtual ~OcCheckpoint() = default; - - bool write(const char*); - - private: - friend class Checkpoint; - bool pass1(); - bool pass2(); - bool make_sym_table(); - bool build_map(); - - bool func(Symbol*); - - bool sym_count(Symbol*); - bool sym_table_install(Symbol*); - bool sym_out(Symbol*); - bool sym_instructions(Symbol*); - bool sym_values(Symbol*); - bool objects(Symbol*); - - bool symlist(Symlist*); - bool symbol(Symbol*); - bool proc(Proc*); - bool instlist(unsigned long, Inst*); - bool datum(Datum*); - bool ctemplate(Symbol*); - bool object(); - bool objectdata(Objectdata*); - long arrayinfo(Symbol* s, Objectdata*); - bool xdr(int&); - bool xdr(long&); - bool xdr(char*&, int); - bool xdr(short&); - bool xdr(unsigned int&); - bool xdr(unsigned long&); - bool xdr(double&); - bool xdr(Object*&); - - private: - int cnt_; - int nobj_; - std::unique_ptr> otable_{}; - bool (OcCheckpoint::*func_)(Symbol*) = nullptr; - std::unique_ptr> stable_{}; - Objectdata* objectdata_; -}; - -class OcReadChkPnt { - public: - OcReadChkPnt(); - virtual ~OcReadChkPnt(); - - bool read(); - - private: - friend class Checkpoint; - bool symbols(); - bool symtable(); - bool symbol(); - bool instructions(); - bool objects(); - bool objectdata(); - - long arrayinfo(Symbol* s, Objectdata*); - - bool get(int&); - bool get(long&); - bool get(char*&); - bool get(double&); - bool get(Object*&); - - private: - bool lookup_; - int builtin_size_; - int lineno_; - int id_; - int nsym_; - Symbol** psym_; - long nobj_; - Object** pobj_; - Symlist* symtable_; -}; - -static bool out_; -static FILE* f_; -static OcCheckpoint* cp_; -static OcReadChkPnt* rdckpt_; -static Checkpoint* ckpt_; - -Checkpoint* Checkpoint::instance() { - if (!ckpt_) { - ckpt_ = new Checkpoint(); - } - return ckpt_; -} - -Checkpoint::Checkpoint() {} -Checkpoint::~Checkpoint() {} -bool Checkpoint::out() { - return out_; -} -bool Checkpoint::xdr(long& i) { - if (out()) { - return cp_->xdr(i); - } else { - return rdckpt_->get(i); - } -} -bool Checkpoint::xdr(Object*& o) { - if (out()) { - return cp_->xdr(o); - } else { - return rdckpt_->get(o); - } -} - -void hoc_checkpoint() { - if (!cp_) { - cp_ = new OcCheckpoint(); - } - bool b; - b = cp_->write(gargstr(1)); - hoc_ret(); - hoc_pushx(double(b)); -} - -int hoc_readcheckpoint(char* fname) { - f_ = fopen(fname, "r"); - if (!f_) { - return 0; - } - char buf[256]; - if (fgets(buf, 256, f_) == 0) { - printf("checkpoint read from file %s failed.\n", fname); - return 2; - } - if (strcmp(buf, "NEURON Checkpoint\n") != 0) { - fclose(f_); - return 0; - } - rdckpt_ = new OcReadChkPnt(); - bool b; - b = rdckpt_->read(); - int rval = 1; - if (!b) { - printf("checkpoint read from file %s failed.\n", fname); - rval = 2; - } - delete rdckpt_; - rdckpt_ = NULL; - return rval; -} - -OcCheckpoint::OcCheckpoint() { - if (!inst_table_) { - inst_table_ = new std::map{}; - for (int i = 1; hoc_inst_[i].pi; ++i) { - inst_table_->emplace((VPfri) hoc_inst_[i].pi, i); - } - } -} - -bool OcCheckpoint::write(const char* fname) { - bool b; - int i; - out_ = 1; - f_ = fopen(fname, "w"); - if (!f_) { - return false; - } - fprintf(f_, "NEURON Checkpoint\n"); - b = make_sym_table(); - func_ = &OcCheckpoint::sym_out; - b = (b && pass1()); - func_ = &OcCheckpoint::sym_instructions; - b = (b && pass1()); - i = -1; - b = (b && xdr(i)); - - // printf("nobj_ = %d\n", nobj_); - b = b && object(); - - func_ = &OcCheckpoint::sym_values; - objectdata_ = hoc_top_level_data; - int size = hoc_resize_toplevel(0); - b = b && xdr(size); - i = 0; - b = b && xdr(i); - b = b && pass1(); - i = -1; - b = (b && xdr(i)); - fclose(f_); - return b; -} - -bool OcCheckpoint::make_sym_table() { - bool b; - cnt_ = 1; - nobj_ = 0; - func_ = &OcCheckpoint::sym_count; - b = pass1(); - if (!b) { - printf("make_sym_table failed on first pass1\n"); - } - fprintf(f_, "#symbols=%d\n", cnt_); - b = (b && xdr(cnt_)); - stable_ = std::make_unique>(); - cnt_ = 1; - func_ = &OcCheckpoint::sym_table_install; - if (!b) { - printf("make_sym_table failed before second pass1\n"); - } - b = (b && pass1()); - if (!b) { - printf("make_sym_table failed on second pass1\n"); - } - func_ = NULL; - return b; -} - -bool OcCheckpoint::sym_count(Symbol* s) { - ++cnt_; - if (s->type == TEMPLATE) { - nobj_ += s->u.ctemplate->count; - } - return true; -} - -bool OcCheckpoint::sym_table_install(Symbol* s) { - stable_->emplace(s, cnt_); - ++cnt_; - return true; -} -bool OcCheckpoint::sym_out(Symbol* s) { - auto it = stable_->find(s); - int val = it != stable_->end() ? it->second : 0; - fprintf(f_, "%d %s %d %d\n", val, s->name, s->type, s->subtype); - int l1 = strlen(s->name); - bool b = xdr(val) && xdr(s->name, l1) && xdr(s->type) && xdr(s->subtype) && xdr(s->cpublic) && - xdr(s->s_varn) && xdr(s->defined_on_the_fly); - switch (s->type) { - case VAR: - if (s->subtype == NOTUSER) { - b = b && xdr(s->u.oboff); - } - arrayinfo(s, NULL); - break; - case STRING: - case OBJECTVAR: - b = b && xdr(s->u.oboff); - arrayinfo(s, NULL); - break; - case TEMPLATE: { - cTemplate* t = s->u.ctemplate; - if (!t->constructor) { - b = b && xdr(t->dataspace_size) && xdr(t->id); - } - break; - } - case NUMBER: - b = b && xdr(*s->u.pnum); - break; - case CSTRING: - b = b && xdr(s->u.cstr, strlen(s->u.cstr)); - break; - } - if (!b) { - printf("failed in sym_table_install\n"); - } - return b; -} - -bool OcCheckpoint::pass1() { - return symlist(hoc_built_in_symlist) && symlist(hoc_top_level_symlist); -} -bool OcCheckpoint::pass2() { - return false; -} -bool OcCheckpoint::build_map() { - return false; -} -bool OcCheckpoint::func(Symbol* s) { - if (func_) { - return (this->*func_)(s); - } - return true; -} -bool OcCheckpoint::symlist(Symlist* sl) { - if (func_ == &OcCheckpoint::sym_out) { - int i = 0; - if (sl) - for (Symbol* s = sl->first; s; s = s->next) { - ++i; - } - fprintf(f_, "symboltable size %d\n", i); - if (!xdr(i)) { - return false; - } - } - if (sl) - for (Symbol* s = sl->first; s; s = s->next) { - if (!symbol(s)) { - printf("symlist failed\n"); - return false; - } - } - return true; -} -bool OcCheckpoint::symbol(Symbol* s) { - if (!func(s)) { - return false; - } - bool b = true; - switch (s->type) { - case TEMPLATE: - b = ctemplate(s); - break; - case FUNCTION: - case PROCEDURE: - b = symlist(s->u.u_proc->list); - break; - } - if (!b) - printf("symbol failed\n"); - return b; -} -bool OcCheckpoint::sym_instructions(Symbol* s) { - Proc* p = s->u.u_proc; - if (s->type == FUNCTION || s->type == PROCEDURE) { - auto it = stable_->find(s); - if (it == stable_->end()) { - printf("couldn't find %s in table\n", s->name); - return false; - } - int val = it->second; - if (p->size) { - fprintf(f_, "instructions for %d |%s|\n", val, s->name); - fprintf(f_, "size %lu\n", p->size); - bool b = xdr(val) && xdr(p->size); - if (!b) { - printf("failed in sym_intructions\n"); - return false; - } - b = instlist(p->size, p->defn.in); - if (!b) { - printf("instlist failed for %s\n", s->name); - } - return b; - } - } - return true; -} -bool OcCheckpoint::instlist(unsigned long size, Inst* in) { - for (unsigned long i = 0; i < size; ++i) { - if (in[i].in == STOP) { - fprintf(f_, " STOP\n"); - int sval = 0; - if (!xdr(sval)) { - printf("instlist failed 1\n"); - return false; - } - continue; - } - if (auto it = inst_table_->find((VPfri) in[i].pf); it != inst_table_->end()) { - auto val = it->second; - fprintf(f_, " %d\n", val); - if (!xdr(val)) { - printf("instlist failed 2\n"); - return false; - } - const char* s = hoc_inst_[val].signature; - for (int j = 0; s && s[j]; ++j) { - ++i; - switch (s[j]) { - case 's': - if (in[i].sym) { - auto it = stable_->find(in[i].sym); - if (it == stable_->end()) { - printf("couldn't find |%s| in table at instruction index %ld\n", - in[i].sym->name, - i); - return false; - } - auto sval = it->second; - // fprintf(f_, " %d |%s|\n", sval, in[i].sym->name); - if (!xdr(sval)) { - printf("instlist failed 3\n"); - return false; - } - } else { - fprintf(f_, " 0 SYMBOL0\n"); - int sval = 0; - if (!xdr(sval)) { - printf("instlist failed 4\n"); - return false; - } - } - break; - case 'i': - fprintf(f_, " %i\n", in[i].i); - if (!xdr(in[i].i)) { - printf("instlist failed 5\n"); - return false; - } - break; - } - } - } else { - printf("OcCheckpoint::instlist failed at i = %lu\n", i); - return false; - } - } - return true; -} -bool OcCheckpoint::datum(Datum*) { - return false; -} -bool OcCheckpoint::ctemplate(Symbol* s) { - cTemplate* t = s->u.ctemplate; - if (func_ == &OcCheckpoint::sym_values) { - Objectdata* saveod = objectdata_; - auto it = stable_->find(s); - bool b = it != stable_->end(); - auto ti = b ? it->second : 0; - fprintf(f_, "%d %d %s\n", ti, t->count, s->name); - b = b && xdr(ti); - // b = b && xdr(t->count); - hoc_Item* q; - ITERATE(q, t->olist) { - Object* ob = OBJ(q); - auto it = otable_->find(ob); - bool found = it != otable_->end(); - b = b && found; - int oid = found ? it->second : 0; - b = b && xdr(oid); - if (t->constructor) { - if (t->checkpoint) { - b = b && (t->checkpoint)(&ob->u.this_pointer); - } else { - printf("No checkpoint available for %s\n", hoc_object_name(ob)); - b = false; - } - } else { - objectdata_ = ob->u.dataspace; - b = b && symlist(t->symtable); - } - if (!b) { - break; - } - } - objectdata_ = saveod; - return b; - } else { - return symlist(t->symtable); - } -} -bool OcCheckpoint::object() { - bool b = xdr(nobj_); - otable_ = std::make_unique>(); - nobj_ = 0; - func_ = &OcCheckpoint::objects; - b = pass1(); - int i = -1; - b = b && xdr(i); - return b; -} -bool OcCheckpoint::objects(Symbol* s) { - if (s->type != TEMPLATE) { - return true; - } - - auto it = stable_->find(s); - bool b = it != stable_->end(); - int sid = b ? it->second : 0; - b = b && xdr(sid); - cTemplate* t = s->u.ctemplate; -#undef init - if (t->init) { - auto it2 = stable_->find(t->init); - bool b2 = it2 != stable_->end(); - b = b && b2; - sid = b2 ? it2->second : sid; - } else { - sid = 0; - } - b = b && xdr(sid); - b = b && xdr(t->index) && xdr(t->count) && xdr(t->id); - hoc_Item* q; - ITERATE(q, t->olist) { - Object* ob = OBJ(q); - ++nobj_; - otable_->emplace(ob, nobj_); // 0 is null object - b = b && xdr(nobj_) && xdr(ob->refcount) && xdr(ob->index); - } - return b; -} - -bool OcCheckpoint::objectdata(Objectdata*) { - return false; -} -#undef sub -long OcCheckpoint::arrayinfo(Symbol* s, Objectdata* od) { - Arrayinfo* ao; - Arrayinfo* as; - - as = s->arayinfo; - if (od) { - ao = od[s->u.oboff + 1].arayinfo; - } else { - ao = as; - } - long n = long(hoc_total_array_data(s, od)); - if (!as) { // not an array - fprintf(f_, "0\n"); - int i = 0; - xdr(i); - } else if (od && as == ao) { // same as original - fprintf(f_, "-1\n"); - int i = -1; - xdr(i); - } else { - int v = ao->a_varn ? 1 : 0; - fprintf(f_, "%d %d %d", ao->nsub, ao->refcount, v); - if (v) { - printf("checkpoint of equation array vars not implemented: %s\n", s->name); - return -1; - } - xdr(ao->nsub); - // xdr(ao->refcount); - // xdr(v); - for (int i = 0; i < ao->nsub; ++i) { - fprintf(f_, " %d", ao->sub[i]); - xdr(ao->sub[i]); - } - fprintf(f_, "\n"); - } - return n; -} - -bool OcCheckpoint::proc(Proc*) { - return false; -} - -bool OcCheckpoint::sym_values(Symbol* s) { - bool b; - auto it = stable_->find(s); - int sp = it != stable_->end() ? it->second : 0; - - if ((s->type == VAR && s->subtype == NOTUSER) || s->type == OBJECTVAR || s->type == STRING || - s->type == SECTION) { - fprintf(f_, "%d %s\n", sp, s->name); - b = xdr(sp); - long n = arrayinfo(s, objectdata_); - if (n == -1) { - return false; - } - // fprintf(f_, " %ld\n", n); - // b = b && xdr(n); - for (long i = 0; i < n; ++i) { - Objectdata od = objectdata_[s->u.oboff]; - if (s->type == VAR) { - double d = od.pval[i]; - fprintf(f_, " %g\n", d); - b = b && xdr(d); - } else if (s->type == OBJECTVAR) { - Object* ob = od.pobj[i]; - if (ob == NULL) { - fprintf(f_, " 0\n"); - int i = 0; - b = b && xdr(i); - } else { - auto it = otable_->find(ob); - bool found = it != otable_->end(); - int oid = found ? it->second : 0; - b = b && found; - b = b && xdr(oid); - } - } else if (s->type == STRING) { - char* cp = od.ppstr[i]; - fprintf(f_, " |%s|\n", cp); - b = b && xdr(cp, strlen(cp)); - // }else if (s->type == SECTION) { - } - } - } - return true; -} - -bool OcCheckpoint::xdr(int& i) { - fprintf(f_, "%d\n", i); - return true; -} -bool OcCheckpoint::xdr(long& i) { - fprintf(f_, "%ld\n", i); - return true; -} -bool OcCheckpoint::xdr(char*& s, int) { - fprintf(f_, "%s\n", s); - return true; -} -bool OcCheckpoint::xdr(short& i) { - int j = i; - fprintf(f_, "%d\n", j); - return true; -} -bool OcCheckpoint::xdr(unsigned int& i) { - int j = i; - fprintf(f_, "%d\n", j); - return true; -} -bool OcCheckpoint::xdr(unsigned long& i) { - long j = i; - fprintf(f_, "%ld\n", j); - return true; -} -bool OcCheckpoint::xdr(double& i) { - fprintf(f_, "%g\n", i); - return true; -} - -bool OcCheckpoint::xdr(Object*& o) { - auto it = otable_->find(o); - bool b = it != otable_->end(); - int i = b ? it->second : 0; - return b && xdr(i); -} - -#undef Chk -#define Chk(arg1, arg2) \ - if (!(arg1)) { \ - printf("%s line %d\n", arg2, lineno_); \ - return false; \ - } -#undef Get -#define Get(arg) \ - if (!get(arg)) { \ - return false; \ - } - -OcReadChkPnt::OcReadChkPnt() { - builtin_size_ = hoc_resize_toplevel(0); -} - -OcReadChkPnt::~OcReadChkPnt() { - delete[] psym_; - delete[] pobj_; -} - -bool OcReadChkPnt::read() { - int size; - out_ = 0; - lineno_ = 1; - id_ = 1; - Chk(symbols(), "OcReadChkPnt::symbols() read failure"); - printf("finished with symbols at lineno = %d\n", lineno_); - Chk(instructions(), "OcReadChkPnt::instructions() read failure"); - printf("finished with instructions at lineno = %d\n", lineno_); - Chk(objects(), "OcReadChkPnt::objects() read failure"); - printf("finished with objects at lineno = %d\n", lineno_); - Get(size); - if (size != hoc_resize_toplevel(size - builtin_size_)) { - printf("top_level_data not right size\n"); - return false; - } - Chk(objectdata(), "OcReadChkPnt::objectdata() read failure"); - printf("finished with objectdata at lineno = %d\n", lineno_); - return true; -} - -bool OcReadChkPnt::symbols() { - Get(nsym_); - psym_ = new Symbol*[nsym_]; - for (int i = 0; i < nsym_; ++i) { - psym_[i] = 0; - } - lookup_ = true; - symtable_ = hoc_built_in_symlist; - Chk(symtable(), "built_in_symlist failure"); - lookup_ = false; - symtable_ = hoc_top_level_symlist; - if (symtable_->first != NULL) { - printf("Some user symbols are already defined at the top level\n"); - return false; - } - Chk(symtable(), "top_level_symlist failure"); - return true; -} -bool OcReadChkPnt::symtable() { - int size; - Get(size); - for (int i = 0; i < size; ++i) { - Chk(symbol(), "symbol read failure"); - } - return true; -} -bool OcReadChkPnt::symbol() { - int id, type, subtype, i; - char buf[2048], *name = buf; - - Get(id); - if (id != id_) { - printf("expected symbol id = %d but file id was %d\n", id_, id); - return false; - } - ++id_; - Get(name); - Get(type); - Get(subtype); - - Symbol* sym; - if (lookup_) { - sym = hoc_table_lookup(name, symtable_); - if (!sym || sym->type != type || sym->subtype != subtype) { - printf("%s not a built-in\n", name); - return false; - } - } else { - sym = hoc_install(name, (type == VAR) ? UNDEF : type, 0.0, &symtable_); - sym->type = type; - sym->subtype = subtype; - } - - psym_[id] = sym; - Get(i); - sym->cpublic = i; - Get(i); - sym->s_varn = i; - Get(i); - sym->defined_on_the_fly = i; - switch (type) { - case VAR: { - if (subtype == NOTUSER) { - Get(i); - if (lookup_ && i != sym->u.oboff) { - printf("bad u.oboff field for built-in VAR\n"); - return false; - } else { - sym->u.oboff = i; - } - } - arrayinfo(sym, NULL); - } break; - case OBJECTVAR: - case STRING: - Get(i); - sym->u.oboff = i; - arrayinfo(sym, NULL); - break; - case CSTRING: - sym->u.cstr = NULL; - Get(sym->u.cstr); - break; - case NUMBER: - sym->u.pnum = new double; - Get(*sym->u.pnum); - break; - case TEMPLATE: { - cTemplate* t; - int dsize, id; - Symlist* slsave = symtable_; - if (!lookup_) { - Get(dsize); - Get(id); - t = new cTemplate; - sym->u.ctemplate = t; - t->sym = sym; - t->dataspace_size = dsize; - t->constructor = 0; - t->destructor = 0; - t->steer = 0; - t->id = id; - symtable_ = NULL; - Chk(symtable(), ""); - t->symtable = symtable_; - } else { - // these don't have a dataspace - t = sym->u.ctemplate; - symtable_ = t->symtable; - Chk(symtable(), ""); - } - symtable_ = slsave; - } break; - case FUNCTION: - case PROCEDURE: { - Symlist* slsave = symtable_; - symtable_ = sym->u.u_proc->list; - Chk(symtable(), ""); - sym->u.u_proc->list = symtable_; - symtable_ = slsave; - } break; - } - return true; -} -bool OcReadChkPnt::instructions() { - int sid, size, i, iid; - Symbol* sym; - const char* signature; - for (;;) { - Get(sid); - if (sid == -1) { - break; - } - sym = psym_[sid]; - if (!sym || (sym->type != FUNCTION && sym->type != PROCEDURE)) { - printf("not a PROC or FUNC\n"); - return false; - } - Get(size); - sym->u.u_proc->size = size; - Inst* lin; - sym->u.u_proc->defn.in = lin = new Inst[size]; - for (i = 0; i < size;) { - Get(iid); - lin[i++].pf = hoc_inst_[iid].pi; - signature = hoc_inst_[iid].signature; - if (signature) - for (const char* cp = signature; *cp; ++cp) { - Get(iid); - switch (*cp) { - case 's': - lin[i++].sym = psym_[iid]; - break; - case 'i': - lin[i++].i = iid; - break; - } - } - } - } - - return true; -} -bool OcReadChkPnt::objects() { - int sid; - long i, n, iob = 0; - Symbol* sym; - Get(nobj_); - pobj_ = new Object*[nobj_ + 1]; - pobj_[0] = NULL; - for (;;) { - Get(sid); - if (sid == -1) { - break; - } - sym = psym_[sid]; - if (sym->type != TEMPLATE) { - printf("not a template\n"); - return false; - } - cTemplate* t = sym->u.ctemplate; - Get(sid); -#undef init - t->init = psym_[sid]; - Get(t->index); - Get(n); - t->count = int(n); - if (t->constructor && !t->checkpoint && t->count > 0) { - printf("Objects for a built-in template without checkpoint: %s\n", sym->name); - return false; - } - t->olist = hoc_l_newlist(); - Get(t->id); - for (i = 0; i < n; ++i) { - int fiob; // not really needed - Get(fiob); - Object* pob = new Object; - pobj_[++iob] = pob; - if (fiob != iob) { - printf("object indexes out of sync\n"); - } - pob->itm_me = hoc_l_lappendobj(t->olist, pob); - pob->ctemplate = t; - Get(pob->refcount); - Get(pob->index); - if (t->constructor) { - // have to set this up later - pob->u.this_pointer = NULL; - } else { - pob->u.dataspace = new Objectdata[t->dataspace_size]; - } - } - } - if (iob != nobj_) { - printf("objects read != objects expected\n"); - return false; - } - return true; -} -bool OcReadChkPnt::objectdata() { - int sid; - long n, i; - Symbol* sym; - double d; - int oid; - Objectdata *od, *odp; - Get(oid); - if (oid == 0) { - od = hoc_top_level_data; - } else if (oid == -1) { - return true; - } else { - od = pobj_[oid]->u.dataspace; - } - for (;;) { - Get(sid); - if (sid == -1) { - break; - } - sym = psym_[sid]; - switch (sym->type) { - case VAR: - n = arrayinfo(sym, od); - odp = od + sym->u.oboff; - if (od != hoc_top_level_data || builtin_size_ <= sym->u.oboff) { - odp->pval = new double[n]; - } - for (i = 0; i < n; ++i) { - Get(d); - odp->pval[i] = d; - } - break; - case OBJECTVAR: - n = arrayinfo(sym, od); - odp = od + sym->u.oboff; - odp->pobj = new Object*[n]; - for (i = 0; i < n; ++i) { - int iob; - Get(iob); - odp->pobj[i] = pobj_[iob]; - } - break; - case STRING: - n = arrayinfo(sym, od); - od[sym->u.oboff].ppstr = new char*[n]; - for (i = 0; i < n; ++i) { - od[sym->u.oboff].ppstr[i] = NULL; - Get(od[sym->u.oboff].ppstr[i]); - } - break; - case TEMPLATE: { - cTemplate* t = sym->u.ctemplate; - if (t->constructor) { - for (long j = 0; j < t->count; ++j) { - int iob; - Object* ob; - Get(iob); - ob = pobj_[iob]; - if (!(*t->checkpoint)(&ob->u.this_pointer)) { - printf("failed reading data for %s\n", hoc_object_name(ob)); - return false; - } - } - } else { - for (long j = 0; j < t->count; ++j) { - objectdata(); - } - } - } break; - default: - return false; - } - } - return true; -} -long OcReadChkPnt::arrayinfo(Symbol* s, Objectdata* od) { - int nsub; - Get(nsub); - if (lookup_) { - int i; - for (i = 0; i < nsub; ++i) { - Get(i); - } - } - Arrayinfo** ap; - if (od == NULL) { - ap = &s->arayinfo; - } else { - ap = &od[s->u.oboff + 1].arayinfo; - } - if (nsub == 0) { - *ap = NULL; - return 1; - } - if (nsub == -1) { - *ap = s->arayinfo; - if (*ap) { - (*ap)->refcount++; - } - return long(hoc_total_array_data(s, NULL)); - } - Arrayinfo* a = (Arrayinfo*) hoc_Emalloc(sizeof(Arrayinfo) + nsub * sizeof(int)); - if (!a) { - return -1; - } - *ap = a; - a->refcount = 1; - a->a_varn = NULL; - a->nsub = nsub; - - long n = 1; - for (int i = 0; i < nsub; ++i) { - int sub; - Get(sub); - a->sub[i] = sub; - n *= sub; - } - return n; -} -bool OcReadChkPnt::get(int& i) { - ++lineno_; - char buf[200]; - if (!fgets(buf, 200, f_) || (sscanf(buf, "%d", &i) != 1)) { - printf("error reading integer at line %d\n", lineno_); - return false; - } - - return true; -} -bool OcReadChkPnt::get(double& i) { - ++lineno_; - char buf[200]; - if (!fgets(buf, 200, f_) || (sscanf(buf, "%lf", &i) != 1)) { - printf("error reading double at line %d\n", lineno_); - return false; - } - - return true; -} -bool OcReadChkPnt::get(long& i) { - int j; - Get(j); - i = j; - return true; -} - -bool OcReadChkPnt::get(char*& s) { - ++lineno_; - if (s) { - if (!fgets(s, 2048, f_)) { - printf("error reading string at line %d\n", lineno_); - return false; - } - s[strlen(s) - 1] = '\0'; - } else { - char buf[256]; - if (!fgets(buf, 256, f_)) { - printf("error reading string at line %d\n", lineno_); - return false; - } - buf[strlen(buf) - 1] = '\0'; - s = new char[strlen(buf) + 1]; - strcpy(s, buf); - } - return true; -} - - -bool OcReadChkPnt::get(Object*& o) { - long i; - Get(i); - o = pobj_[i]; - return true; -} -#endif diff --git a/src/ivoc/checkpnt.h b/src/ivoc/checkpnt.h deleted file mode 100644 index 224e2d05e4..0000000000 --- a/src/ivoc/checkpnt.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#define CKPT(arg1, arg2) \ - if (!arg1.xdr(arg2)) { \ - return false; \ - } - -class Checkpoint { - public: - Checkpoint(); - virtual ~Checkpoint(); - - static Checkpoint* instance(); - - bool out(); // true means to file, false means from file - bool xdr(long&); - bool xdr(Object*&); -}; diff --git a/src/ivoc/graph.cpp b/src/ivoc/graph.cpp index 86a7f38973..aef2b933d9 100644 --- a/src/ivoc/graph.cpp +++ b/src/ivoc/graph.cpp @@ -1226,7 +1226,7 @@ static void gr_destruct(void* v) { } void Graph_reg() { // printf("Graph_reg\n"); - class2oc("Graph", gr_cons, gr_destruct, gr_members, NULL, NULL, NULL); + class2oc("Graph", gr_cons, gr_destruct, gr_members, NULL, NULL); #if HAVE_IV if (hoc_usegui) { colors = new ColorPalette(); diff --git a/src/ivoc/grglyph.cpp b/src/ivoc/grglyph.cpp index d505958115..2c5bc94e6d 100644 --- a/src/ivoc/grglyph.cpp +++ b/src/ivoc/grglyph.cpp @@ -213,7 +213,7 @@ static void destruct(void* v) { } void GrGlyph_reg() { - class2oc("Glyph", cons, destruct, members, NULL, objmembers, NULL); + class2oc("Glyph", cons, destruct, members, objmembers, NULL); sggl_ = hoc_lookup("Glyph"); } diff --git a/src/ivoc/ivocrand.cpp b/src/ivoc/ivocrand.cpp index f250049299..183fb5d72c 100644 --- a/src/ivoc/ivocrand.cpp +++ b/src/ivoc/ivocrand.cpp @@ -511,7 +511,7 @@ static Member_func r_members[] = {{"ACG", r_ACG}, {nullptr, nullptr}}; void Random_reg() { - class2oc("Random", r_cons, r_destruct, r_members, NULL, NULL, NULL); + class2oc("Random", r_cons, r_destruct, r_members, NULL, NULL); random_play_list_ = new RandomPlayList; } diff --git a/src/ivoc/ivocvect.cpp b/src/ivoc/ivocvect.cpp index 1ffb1eba95..9681a6b270 100644 --- a/src/ivoc/ivocvect.cpp +++ b/src/ivoc/ivocvect.cpp @@ -3843,7 +3843,7 @@ static void steer_x(void* v) { } void Vector_reg() { - class2oc("Vector", v_cons, v_destruct, v_members, NULL, v_retobj_members, v_retstr_members); + class2oc("Vector", v_cons, v_destruct, v_members, v_retobj_members, v_retstr_members); svec_ = hoc_lookup("Vector"); // now make the x variable an actual double Symbol* sv = hoc_lookup("Vector"); diff --git a/src/ivoc/matrix.cpp b/src/ivoc/matrix.cpp index 90b0aeef1e..8fa098d61d 100644 --- a/src/ivoc/matrix.cpp +++ b/src/ivoc/matrix.cpp @@ -732,7 +732,7 @@ void Matrix_reg(); #endif void Matrix_reg() { - class2oc("Matrix", m_cons, m_destruct, m_members, NULL, m_retobj_members, NULL); + class2oc("Matrix", m_cons, m_destruct, m_members, m_retobj_members, NULL); nrn_matrix_sym = hoc_lookup("Matrix"); // now make the x variable an actual double Symbol* sx = hoc_table_lookup("x", nrn_matrix_sym->u.ctemplate->symtable); diff --git a/src/ivoc/mlinedit.cpp b/src/ivoc/mlinedit.cpp index ae3a555c12..489719af73 100644 --- a/src/ivoc/mlinedit.cpp +++ b/src/ivoc/mlinedit.cpp @@ -141,7 +141,7 @@ static void destruct(void* v) { } void TextEditor_reg() { - class2oc("TextEditor", cons, destruct, members, NULL, NULL, retstr_members); + class2oc("TextEditor", cons, destruct, members, NULL, retstr_members); } #if HAVE_IV diff --git a/src/ivoc/mymath.cpp b/src/ivoc/mymath.cpp index 46180d18a1..13586a43ad 100644 --- a/src/ivoc/mymath.cpp +++ b/src/ivoc/mymath.cpp @@ -73,7 +73,7 @@ static void* cons(Object*) { static void destruct(void*) {} void GUIMath_reg() { - class2oc("GUIMath", cons, destruct, members, NULL, NULL, NULL); + class2oc("GUIMath", cons, destruct, members, NULL, NULL); } double MyMath::anint(double x) { diff --git a/src/ivoc/ocbox.cpp b/src/ivoc/ocbox.cpp index 5ca1d4d572..61a1320a96 100644 --- a/src/ivoc/ocbox.cpp +++ b/src/ivoc/ocbox.cpp @@ -429,11 +429,11 @@ static Member_func members[] = {{"intercept", intercept}, // #if HAVE {0, 0}}; void HBox_reg() { - class2oc("HBox", hcons, destruct, members, NULL, NULL, NULL); + class2oc("HBox", hcons, destruct, members, NULL, NULL); } void VBox_reg() { - class2oc("VBox", vcons, destruct, members, NULL, NULL, NULL); + class2oc("VBox", vcons, destruct, members, NULL, NULL); } #if HAVE_IV OcGlyphContainer::OcGlyphContainer() diff --git a/src/ivoc/ocdeck.cpp b/src/ivoc/ocdeck.cpp index 55b42f3c9f..be5d6f32db 100644 --- a/src/ivoc/ocdeck.cpp +++ b/src/ivoc/ocdeck.cpp @@ -239,7 +239,7 @@ static Member_func members[] = {{"flip_to", flip_to}, {0, 0}}; void OcDeck_reg() { - class2oc("Deck", cons, destruct, members, NULL, NULL, NULL); + class2oc("Deck", cons, destruct, members, NULL, NULL); } #if HAVE_IV OcDeck::OcDeck() diff --git a/src/ivoc/ocfile.cpp b/src/ivoc/ocfile.cpp index fc7c9ae5d2..fcad2b14ff 100644 --- a/src/ivoc/ocfile.cpp +++ b/src/ivoc/ocfile.cpp @@ -299,7 +299,7 @@ Member_func f_members[] = {{"ropen", f_ropen}, static Member_ret_str_func f_retstr_members[] = {{"getname", f_get_name}, {"dir", f_dir}, {0, 0}}; void OcFile_reg() { - class2oc("File", f_cons, f_destruct, f_members, NULL, NULL, f_retstr_members); + class2oc("File", f_cons, f_destruct, f_members, NULL, f_retstr_members); file_class_sym_ = hoc_lookup("File"); } diff --git a/src/ivoc/oclist.cpp b/src/ivoc/oclist.cpp index c8c5b78485..b19e129966 100644 --- a/src/ivoc/oclist.cpp +++ b/src/ivoc/oclist.cpp @@ -11,7 +11,6 @@ #include #include #include "ocglyph.h" -#include "checkpnt.h" #include "apwindow.h" #include "ocbrowsr.h" #include "objcmd.h" @@ -453,38 +452,9 @@ OcList::~OcList() { remove_all(); } -static int l_chkpt(void** vp) { -#if HAVE_IV - OcList* o; - Checkpoint& chk = *Checkpoint::instance(); - if (chk.out()) { - long cnt; - o = (OcList*) (*vp); - cnt = o->count(); - CKPT(chk, cnt); - for (long i = 0; i < cnt; ++i) { - Object* item = o->object(i); - CKPT(chk, item); - } - } else { - long cnt; - CKPT(chk, cnt); - o = new OcList(cnt); - o->ref(); - for (long i = 0; i < cnt; ++i) { - Object* item; - CKPT(chk, item); - o->append(item); - } - *vp = (void*) o; - } -#endif - return 1; -} - void OcList_reg() { // printf("Oclist_reg\n"); - class2oc("List", l_cons, l_destruct, l_members, l_chkpt, l_retobj_members, NULL); + class2oc("List", l_cons, l_destruct, l_members, l_retobj_members, NULL); list_class_sym_ = hoc_lookup("List"); } diff --git a/src/ivoc/ocnoiv1.cpp b/src/ivoc/ocnoiv1.cpp index ccbe2820ed..d3ceae4d2d 100644 --- a/src/ivoc/ocnoiv1.cpp +++ b/src/ivoc/ocnoiv1.cpp @@ -13,9 +13,6 @@ extern "C" void nrn_shape_update(); void ivoc_help(const char*) {} void ivoc_cleanup() {} -int hoc_readcheckpoint(char*) { - return 0; -} void hoc_notify_iv() { nrn_shape_update(); @@ -109,12 +106,6 @@ void hoc_string_dialog() { hoc_pushx(0.); } } -void hoc_checkpoint() { - // not redirecting checkpoint because not a GUI function - // neuron::python::methods.try_gui_helper("checkpoint", nullptr); - hoc_ret(); - hoc_pushx(0.); -} void hoc_pwman_place() { neuron::python::methods.try_gui_helper("pwman_place", nullptr); hoc_ret(); diff --git a/src/ivoc/ocpointer.cpp b/src/ivoc/ocpointer.cpp index a1cc1b04f9..afe3451316 100644 --- a/src/ivoc/ocpointer.cpp +++ b/src/ivoc/ocpointer.cpp @@ -108,7 +108,7 @@ static void steer_val(void* v) { } void OcPointer_reg() { - class2oc("Pointer", cons, destruct, members, NULL, NULL, s_memb); + class2oc("Pointer", cons, destruct, members, NULL, s_memb); // now make the val variable an actual double Symbol* sv = hoc_lookup("Pointer"); Symbol* sx = hoc_table_lookup("val", sv->u.ctemplate->symtable); diff --git a/src/ivoc/ocptrvector.cpp b/src/ivoc/ocptrvector.cpp index a0c991bea3..d624bce5d9 100644 --- a/src/ivoc/ocptrvector.cpp +++ b/src/ivoc/ocptrvector.cpp @@ -222,6 +222,6 @@ static void destruct(void* v) { } void OcPtrVector_reg() { - class2oc("PtrVector", cons, destruct, members, 0, 0, retstr_members); + class2oc("PtrVector", cons, destruct, members, 0, retstr_members); pv_class_sym_ = hoc_lookup("PtrVector"); } diff --git a/src/ivoc/octimer.cpp b/src/ivoc/octimer.cpp index cf506ef125..560394f2a4 100644 --- a/src/ivoc/octimer.cpp +++ b/src/ivoc/octimer.cpp @@ -99,7 +99,7 @@ static void t_destruct(void* v) { Member_func t_members[] = {{"seconds", t_seconds}, {"start", t_start}, {"end", t_stop}, {0, 0}}; void OcTimer_reg() { - class2oc("Timer", t_cons, t_destruct, t_members, NULL, NULL, NULL); + class2oc("Timer", t_cons, t_destruct, t_members, NULL, NULL); } #if HAVE_IV OcTimer::OcTimer(const char* cmd) { diff --git a/src/ivoc/pwman.cpp b/src/ivoc/pwman.cpp index 8489000cb6..29335af77f 100644 --- a/src/ivoc/pwman.cpp +++ b/src/ivoc/pwman.cpp @@ -801,7 +801,7 @@ static Member_ret_obj_func retobj_members[] = {{"group", pwman_group}, {0, 0}}; static Member_ret_str_func s_memb[] = {{"name", pwman_name}, {0, 0}}; void PWManager_reg() { - class2oc("PWManager", pwman_cons, pwman_destruct, members, NULL, retobj_members, s_memb); + class2oc("PWManager", pwman_cons, pwman_destruct, members, retobj_members, s_memb); } #if HAVE_IV // almost to end of file diff --git a/src/ivoc/strfun.cpp b/src/ivoc/strfun.cpp index 21b78dee78..721dae09ec 100644 --- a/src/ivoc/strfun.cpp +++ b/src/ivoc/strfun.cpp @@ -379,7 +379,7 @@ static void* l_cons(Object*) { } void StringFunctions_reg() { - class2oc("StringFunctions", l_cons, nullptr, l_members, nullptr, l_obj_members, nullptr); + class2oc("StringFunctions", l_cons, nullptr, l_members, l_obj_members, nullptr); } diff --git a/src/ivoc/symchoos.cpp b/src/ivoc/symchoos.cpp index e42125502b..f3fe138876 100644 --- a/src/ivoc/symchoos.cpp +++ b/src/ivoc/symchoos.cpp @@ -209,7 +209,7 @@ static double text(void* v) { } static Member_func members[] = {{"run", srun}, {"text", text}, {0, 0}}; void SymChooser_reg() { - class2oc("SymChooser", scons, sdestruct, members, NULL, NULL, NULL); + class2oc("SymChooser", scons, sdestruct, members, NULL, NULL); } #if HAVE_IV diff --git a/src/ivoc/xmenu.cpp b/src/ivoc/xmenu.cpp index 681914436b..9c91e93fd8 100644 --- a/src/ivoc/xmenu.cpp +++ b/src/ivoc/xmenu.cpp @@ -3127,5 +3127,5 @@ static double vfe_default(void* v) { } static Member_func vfe_members[] = {{"default", vfe_default}, {0, 0}}; void ValueFieldEditor_reg() { - class2oc("ValueFieldEditor", vfe_cons, vfe_destruct, vfe_members, NULL, NULL, NULL); + class2oc("ValueFieldEditor", vfe_cons, vfe_destruct, vfe_members, NULL, NULL); } diff --git a/src/nrncvode/cvodeobj.cpp b/src/nrncvode/cvodeobj.cpp index 5c662ec4b7..d7fc1660ed 100644 --- a/src/nrncvode/cvodeobj.cpp +++ b/src/nrncvode/cvodeobj.cpp @@ -653,7 +653,7 @@ static void destruct(void* v) { #endif } void Cvode_reg() { - class2oc("CVode", cons, destruct, members, NULL, omembers, NULL); + class2oc("CVode", cons, destruct, members, omembers, NULL); net_cvode_instance = new NetCvode(1); Daspk::dteps_ = 1e-9; // change with cvode.dae_init_dteps(newval) } diff --git a/src/nrncvode/netcvode.cpp b/src/nrncvode/netcvode.cpp index 27d7e9bbf0..b64feb7494 100644 --- a/src/nrncvode/netcvode.cpp +++ b/src/nrncvode/netcvode.cpp @@ -848,7 +848,7 @@ static void destruct(void* v) { } void NetCon_reg() { - class2oc("NetCon", cons, destruct, members, NULL, omembers, NULL); + class2oc("NetCon", cons, destruct, members, omembers, NULL); Symbol* nc = hoc_lookup("NetCon"); nc->u.ctemplate->steer = steer_val; Symbol* s; diff --git a/src/nrniv/bbsavestate.cpp b/src/nrniv/bbsavestate.cpp index 3274dc0011..0dc6614710 100644 --- a/src/nrniv/bbsavestate.cpp +++ b/src/nrniv/bbsavestate.cpp @@ -1011,7 +1011,7 @@ static Member_func members[] = {{"save", save}, {0, 0}}; void BBSaveState_reg() { - class2oc("BBSaveState", cons, destruct, members, NULL, NULL, NULL); + class2oc("BBSaveState", cons, destruct, members, NULL, NULL); } // from savstate.cpp diff --git a/src/nrniv/finithnd.cpp b/src/nrniv/finithnd.cpp index 0bf58a2e32..d29e0b4864 100644 --- a/src/nrniv/finithnd.cpp +++ b/src/nrniv/finithnd.cpp @@ -89,7 +89,7 @@ static void finithnd_destruct(void* v) { } void FInitializeHandler_reg() { - class2oc("FInitializeHandler", finithnd_cons, finithnd_destruct, members, NULL, NULL, NULL); + class2oc("FInitializeHandler", finithnd_cons, finithnd_destruct, members, NULL, NULL); } std::vector FInitialHandler::fihlist_[4]; diff --git a/src/nrniv/impedanc.cpp b/src/nrniv/impedanc.cpp index d9cbde709d..8d1621a8ec 100644 --- a/src/nrniv/impedanc.cpp +++ b/src/nrniv/impedanc.cpp @@ -147,7 +147,7 @@ static Member_func members[] = {{"compute", compute}, {0, 0}}; void Impedance_reg() { - class2oc("Impedance", cons, destruct, members, nullptr, nullptr, nullptr); + class2oc("Impedance", cons, destruct, members, nullptr, nullptr); } Imp::~Imp() { diff --git a/src/nrniv/kschan.cpp b/src/nrniv/kschan.cpp index adb7906249..a5c8fc8a86 100644 --- a/src/nrniv/kschan.cpp +++ b/src/nrniv/kschan.cpp @@ -799,10 +799,10 @@ static void* kst_cons(Object* o) { static void kst_destruct(void*) {} void KSChan_reg() { - class2oc("KSChan", ks_cons, ks_destruct, ks_dmem, NULL, ks_omem, ks_smem); - class2oc("KSGate", ksg_cons, ksg_destruct, ksg_dmem, NULL, ksg_omem, ksg_smem); - class2oc("KSState", kss_cons, kss_destruct, kss_dmem, NULL, kss_omem, kss_smem); - class2oc("KSTrans", kst_cons, kst_destruct, kst_dmem, NULL, kst_omem, kst_smem); + class2oc("KSChan", ks_cons, ks_destruct, ks_dmem, ks_omem, ks_smem); + class2oc("KSGate", ksg_cons, ksg_destruct, ksg_dmem, ksg_omem, ksg_smem); + class2oc("KSState", kss_cons, kss_destruct, kss_dmem, kss_omem, kss_smem); + class2oc("KSTrans", kst_cons, kst_destruct, kst_dmem, kst_omem, kst_smem); ksstate_sym = hoc_lookup("KSState"); ksgate_sym = hoc_lookup("KSGate"); kstrans_sym = hoc_lookup("KSTrans"); diff --git a/src/nrniv/linmod1.cpp b/src/nrniv/linmod1.cpp index 813299a8e8..2df98917fe 100644 --- a/src/nrniv/linmod1.cpp +++ b/src/nrniv/linmod1.cpp @@ -61,7 +61,7 @@ static void destruct(void* v) { } void LinearMechanism_reg() { - class2oc("LinearMechanism", cons, destruct, members, NULL, NULL, NULL); + class2oc("LinearMechanism", cons, destruct, members, NULL, NULL); } LinearMechanism::LinearMechanism() { diff --git a/src/nrniv/nmodlrandom.cpp b/src/nrniv/nmodlrandom.cpp index 8432c64e78..66be7a9dc1 100644 --- a/src/nrniv/nmodlrandom.cpp +++ b/src/nrniv/nmodlrandom.cpp @@ -104,7 +104,6 @@ void NMODLRandom_reg() { nmodlrandom_cons, nmodlrandom_destruct, members, - nullptr, retobj_members, nullptr); if (!nmodlrandom_sym) { diff --git a/src/nrniv/nrnmenu.cpp b/src/nrniv/nrnmenu.cpp index de66948849..f4103033cb 100644 --- a/src/nrniv/nrnmenu.cpp +++ b/src/nrniv/nrnmenu.cpp @@ -669,7 +669,7 @@ static Member_func ms_members[] = {{"panel", ms_panel}, {0, 0}}; void MechanismStandard_reg() { - class2oc("MechanismStandard", ms_cons, ms_destruct, ms_members, NULL, NULL, NULL); + class2oc("MechanismStandard", ms_cons, ms_destruct, ms_members, NULL, NULL); ms_class_sym_ = hoc_lookup("MechanismStandard"); } @@ -1130,7 +1130,7 @@ static Member_ret_obj_func mt_retobj_members[] = {{"pp_begin", mt_pp_begin}, static Member_ret_str_func mt_retstr_func[] = {{"code", mt_code}, {"file", mt_file}, {0, 0}}; void MechanismType_reg() { class2oc( - "MechanismType", mt_cons, mt_destruct, mt_members, NULL, mt_retobj_members, mt_retstr_func); + "MechanismType", mt_cons, mt_destruct, mt_members, mt_retobj_members, mt_retstr_func); mt_class_sym_ = hoc_lookup("MechanismType"); } diff --git a/src/nrniv/nrnpy.cpp b/src/nrniv/nrnpy.cpp index be8b723df4..9176a63858 100644 --- a/src/nrniv/nrnpy.cpp +++ b/src/nrniv/nrnpy.cpp @@ -251,7 +251,7 @@ void nrnpython_reg() { #endif // Stub implementation of PythonObject if Python support was not enabled, or a nrnpython library // could not be loaded. - class2oc("PythonObject", p_cons, p_destruct, p_members, nullptr, nullptr, nullptr); + class2oc("PythonObject", p_cons, p_destruct, p_members, nullptr, nullptr); } #ifdef NRNPYTHON_DYNAMICLOAD // to end of file diff --git a/src/nrniv/nrnste.cpp b/src/nrniv/nrnste.cpp index 639137a90e..52a30bfaa0 100644 --- a/src/nrniv/nrnste.cpp +++ b/src/nrniv/nrnste.cpp @@ -65,7 +65,7 @@ static void ste_destruct(void* v) { } void StateTransitionEvent_reg() { - class2oc("StateTransitionEvent", ste_cons, ste_destruct, members, NULL, NULL, NULL); + class2oc("StateTransitionEvent", ste_cons, ste_destruct, members, NULL, NULL); } StateTransitionEvent::StateTransitionEvent(int nstate, Point_process* pnt) diff --git a/src/nrniv/ppshape.cpp b/src/nrniv/ppshape.cpp index 1aaee148fe..a87937ed12 100644 --- a/src/nrniv/ppshape.cpp +++ b/src/nrniv/ppshape.cpp @@ -54,7 +54,7 @@ static void pp_destruct(void* v) { void PPShape_reg() { // printf("PPShape_reg\n"); - class2oc("PPShape", pp_cons, pp_destruct, pp_members, NULL, NULL, NULL); + class2oc("PPShape", pp_cons, pp_destruct, pp_members, NULL, NULL); } #if HAVE_IV // to end of file diff --git a/src/nrniv/savstate.cpp b/src/nrniv/savstate.cpp index 50b1175c5d..647e5688e2 100644 --- a/src/nrniv/savstate.cpp +++ b/src/nrniv/savstate.cpp @@ -1277,5 +1277,5 @@ static Member_func members[] = {{"save", save}, {0, 0}}; void SaveState_reg() { - class2oc("SaveState", cons, destruct, members, NULL, NULL, NULL); + class2oc("SaveState", cons, destruct, members, NULL, NULL); } diff --git a/src/nrniv/secbrows.cpp b/src/nrniv/secbrows.cpp index 10516f7884..a74ecfd39e 100644 --- a/src/nrniv/secbrows.cpp +++ b/src/nrniv/secbrows.cpp @@ -96,7 +96,7 @@ static void sb_destruct(void* v) { #endif } void SectionBrowser_reg() { - class2oc("SectionBrowser", sb_cons, sb_destruct, sb_members, NULL, NULL, NULL); + class2oc("SectionBrowser", sb_cons, sb_destruct, sb_members, NULL, NULL); } #if HAVE_IV diff --git a/src/nrniv/shape.cpp b/src/nrniv/shape.cpp index cf6e32851e..96eddef0a9 100644 --- a/src/nrniv/shape.cpp +++ b/src/nrniv/shape.cpp @@ -605,7 +605,7 @@ static void sh_destruct(void* v) { } void Shape_reg() { // printf("Shape_reg\n"); - class2oc("Shape", sh_cons, sh_destruct, sh_members, NULL, retobj_members, NULL); + class2oc("Shape", sh_cons, sh_destruct, sh_members, retobj_members, NULL); } #if HAVE_IV diff --git a/src/nrniv/shapeplt.cpp b/src/nrniv/shapeplt.cpp index 9505a130d8..a35516da96 100644 --- a/src/nrniv/shapeplt.cpp +++ b/src/nrniv/shapeplt.cpp @@ -426,7 +426,7 @@ static void sh_destruct(void* v) { } void PlotShape_reg() { // printf("PlotShape_reg\n"); - class2oc("PlotShape", sh_cons, sh_destruct, sh_members, NULL, retobj_members, NULL); + class2oc("PlotShape", sh_cons, sh_destruct, sh_members, retobj_members, NULL); } void* ShapePlotData::varobj() const { diff --git a/src/nrniv/spaceplt.cpp b/src/nrniv/spaceplt.cpp index e88aac8405..1978cafdfb 100644 --- a/src/nrniv/spaceplt.cpp +++ b/src/nrniv/spaceplt.cpp @@ -291,7 +291,7 @@ static void s_destruct(void* v) { void RangeVarPlot_reg() { // printf("RangeVarPlot_reg\n"); - class2oc("RangeVarPlot", s_cons, s_destruct, s_members, NULL, rvp_retobj_members, NULL); + class2oc("RangeVarPlot", s_cons, s_destruct, s_members, rvp_retobj_members, NULL); } #if HAVE_IV diff --git a/src/nrnoc/init.cpp b/src/nrnoc/init.cpp index f233507f70..267eac5c55 100644 --- a/src/nrnoc/init.cpp +++ b/src/nrnoc/init.cpp @@ -1025,7 +1025,6 @@ extern void class2oc_base(const char*, void* (*cons)(Object*), void (*destruct)(void*), Member_func*, - int (*checkpoint)(void**), Member_ret_obj_func*, Member_ret_str_func*); @@ -1045,7 +1044,7 @@ int point_register_mech(const char** m, Symlist* sl; Symbol *s, *s2; nrn_load_name_check(m[1]); - class2oc_base(m[1], constructor, destructor, fmember, nullptr, nullptr, nullptr); + class2oc_base(m[1], constructor, destructor, fmember, nullptr, nullptr); s = hoc_lookup(m[1]); sl = hoc_symlist; hoc_symlist = s->u.ctemplate->symtable; diff --git a/src/nrnoc/seclist.cpp b/src/nrnoc/seclist.cpp index 2568a5b9cd..584612113f 100644 --- a/src/nrnoc/seclist.cpp +++ b/src/nrnoc/seclist.cpp @@ -259,14 +259,13 @@ extern void class2oc(const char*, void* (*cons)(Object*), void (*destruct)(void*), Member_func*, - int (*checkpoint)(void**), Member_ret_obj_func*, Member_ret_str_func*); void SectionList_reg(void) { /* printf("SectionList_reg\n");*/ - class2oc("SectionList", constructor, destructor, members, nullptr, nullptr, nullptr); + class2oc("SectionList", constructor, destructor, members, nullptr, nullptr); } #define relative(pc) (pc + (pc)->i) diff --git a/src/nrnoc/secref.cpp b/src/nrnoc/secref.cpp index 87071ed2a8..7b1f5dd793 100644 --- a/src/nrnoc/secref.cpp +++ b/src/nrnoc/secref.cpp @@ -366,7 +366,6 @@ extern void class2oc(const char*, void* (*cons)(Object*), void (*destruct)(void*), Member_func*, - int (*checkpoint)(void**), Member_ret_obj_func*, Member_ret_str_func*); @@ -374,7 +373,7 @@ extern void class2oc(const char*, void SectionRef_reg(void) { Symbol *s, *sr; - class2oc("SectionRef", cons, destruct, members, nullptr, nullptr, nullptr); + class2oc("SectionRef", cons, destruct, members, nullptr, nullptr); /* now make the sec variable an actual SECTIONREF */ sr = hoc_lookup("SectionRef"); s = hoc_table_lookup("sec", sr->u.ctemplate->symtable); diff --git a/src/nrnpython/nrnpy_p2h.cpp b/src/nrnpython/nrnpy_p2h.cpp index da2083877a..07ac58daba 100644 --- a/src/nrnpython/nrnpy_p2h.cpp +++ b/src/nrnpython/nrnpy_p2h.cpp @@ -1084,7 +1084,7 @@ void nrnpython_reg_real_nrnpy_hoc_cpp(neuron::python::impl_ptrs* ptrs); */ extern "C" NRN_EXPORT void nrnpython_reg_real(neuron::python::impl_ptrs* ptrs) { assert(ptrs); - class2oc("PythonObject", p_cons, p_destruct, p_members, nullptr, nullptr, nullptr); + class2oc("PythonObject", p_cons, p_destruct, p_members, nullptr, nullptr); nrnpy_pyobj_sym_ = hoc_lookup("PythonObject"); assert(nrnpy_pyobj_sym_); ptrs->callable_with_args = callable_with_args; diff --git a/src/oc/classreg.h b/src/oc/classreg.h index 4a1893c4af..00ee7e9a55 100644 --- a/src/oc/classreg.h +++ b/src/oc/classreg.h @@ -7,6 +7,5 @@ extern void class2oc(const char*, void* (*cons)(Object*), void (*destruct)(void*), Member_func*, - int (*checkpoint)(void**), Member_ret_obj_func*, Member_ret_str_func*); diff --git a/src/oc/hoc.cpp b/src/oc/hoc.cpp index fee82add88..6eded05477 100644 --- a/src/oc/hoc.cpp +++ b/src/oc/hoc.cpp @@ -891,21 +891,6 @@ int hoc_main1(int argc, const char** argv, const char** envp) { gargv += 2; gargc -= 2; } - if (argc > 1 && argv[1][0] != '-') { - /* first file may be a checkpoint file */ - extern int hoc_readcheckpoint(char*); - switch (hoc_readcheckpoint(const_cast(argv[1]))) { - case 1: - ++gargv; - --gargc; - break; - case 2: - nrn_exit(1); - break; - default: - break; - } - } if (gargc == 1) /* fake an argument list */ { diff --git a/src/oc/hoc_init.cpp b/src/oc/hoc_init.cpp index 719d712590..bfcd5a9342 100644 --- a/src/oc/hoc_init.cpp +++ b/src/oc/hoc_init.cpp @@ -170,7 +170,6 @@ static struct { /* Builtin functions with multiple or variable args */ {"saveaudit", hoc_Saveaudit}, {"retrieveaudit", hoc_Retrieveaudit}, {"coredump_on_error", hoc_coredump_on_error}, - {"checkpoint", hoc_checkpoint}, {"quit", hoc_quit}, {"object_push", hoc_object_push}, {"object_pop", hoc_object_pop}, diff --git a/src/oc/hoc_oop.cpp b/src/oc/hoc_oop.cpp index 350b1bbc70..ce2a68b531 100644 --- a/src/oc/hoc_oop.cpp +++ b/src/oc/hoc_oop.cpp @@ -1547,7 +1547,6 @@ void hoc_begintemplate(Symbol* t1) { t->u.ctemplate->destructor = 0; t->u.ctemplate->is_point_ = 0; t->u.ctemplate->steer = 0; - t->u.ctemplate->checkpoint = 0; t->u.ctemplate->id = ++template_id; pushtemplatei(icntobjectdata); pushtemplateodata(hoc_objectdata); @@ -1600,7 +1599,6 @@ void class2oc_base(const char* name, void* (*cons)(Object*), void (*destruct)(void*), Member_func* m, - int (*checkpoint)(void**), Member_ret_obj_func* mobjret, Member_ret_str_func* strret) { extern int hoc_main1_inited_; @@ -1622,7 +1620,6 @@ void class2oc_base(const char* name, t->constructor = cons; t->destructor = destruct; t->steer = 0; - t->checkpoint = checkpoint; if (m) for (i = 0; m[i].name; ++i) { @@ -1650,10 +1647,9 @@ void class2oc(const char* name, void* (*cons)(Object*), void (*destruct)(void*), Member_func* m, - int (*checkpoint)(void**), Member_ret_obj_func* mobjret, Member_ret_str_func* strret) { - class2oc_base(name, cons, destruct, m, checkpoint, mobjret, strret); + class2oc_base(name, cons, destruct, m, mobjret, strret); py_exposed_classes.push_back(name); } diff --git a/src/oc/hocdec.h b/src/oc/hocdec.h index eb328950f0..c0b31ae6af 100644 --- a/src/oc/hocdec.h +++ b/src/oc/hocdec.h @@ -158,7 +158,6 @@ struct cTemplate { void* (*constructor)(struct Object*); void (*destructor)(void*); void (*steer)(void*); /* normally nullptr */ - int (*checkpoint)(void**); }; union Objectdata { diff --git a/src/oc/ocfunc.h b/src/oc/ocfunc.h index dabc840dc0..b30006011a 100644 --- a/src/oc/ocfunc.h +++ b/src/oc/ocfunc.h @@ -25,7 +25,7 @@ extern void hoc_single_event_run(void), hoc_notify_iv(void), nrniv_bind_thread(v extern void hoc_pointer(void), hoc_Numarg(void), hoc_Argtype(void), hoc_exec_cmd(void); extern void hoc_load_proc(void), hoc_load_func(void), hoc_load_template(void), hoc_load_file(void); extern void hoc_xcheckbox(void), hoc_xstatebutton(void), hoc_Symbol_limits(void); -extern void hoc_coredump_on_error(void), hoc_checkpoint(void), hoc_quit(void); +extern void hoc_coredump_on_error(void), hoc_quit(void); extern void hoc_object_push(void), hoc_object_pop(void), hoc_pwman_place(void); extern void hoc_show_errmess_always(void), hoc_execute1(void), hoc_secname(void); extern void hoc_neuronhome(void), hoc_Execerror(void); diff --git a/src/parallel/ocbbs.cpp b/src/parallel/ocbbs.cpp index 36e6e33f29..2091a345e4 100644 --- a/src/parallel/ocbbs.cpp +++ b/src/parallel/ocbbs.cpp @@ -1136,7 +1136,7 @@ static void destruct(void* v) { } void ParallelContext_reg() { - class2oc("ParallelContext", cons, destruct, members, nullptr, retobj_members, retstr_members); + class2oc("ParallelContext", cons, destruct, members, retobj_members, retstr_members); } // A BBS message is something to execute. diff --git a/test/unit_tests/oc/hoc_interpreter.cpp b/test/unit_tests/oc/hoc_interpreter.cpp index 36f03aaaea..3e334bfcb1 100644 --- a/test/unit_tests/oc/hoc_interpreter.cpp +++ b/test/unit_tests/oc/hoc_interpreter.cpp @@ -145,7 +145,6 @@ SCENARIO("Test calling code from HOC that throws exceptions", "[NEURON][hoc_inte throwing_util_constructor, throwing_util_destructor, throwing_util_members, - nullptr /* checkpoint */, throwing_util_ret_obj_members, throwing_util_ret_str_members); registered = true; From 2bfcab3ac7b1f070c5c9916083f9903fbc0a58e0 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Wed, 25 Sep 2024 04:25:52 +0200 Subject: [PATCH 35/68] Fix lexer for ONTOLOGY parsing (#3091) - nocmodl was not raising a syntax error for the unclosed safe CURIE USEION na READ ena WRITE ina REPRESENTS [CHEBI:29101 - Fix lexer rule to correctly handle this Co-authored-by: Pramod S Kumbhar --- src/nmodl/lex.lpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/nmodl/lex.lpp b/src/nmodl/lex.lpp index 4ec229210f..344020effc 100755 --- a/src/nmodl/lex.lpp +++ b/src/nmodl/lex.lpp @@ -179,6 +179,12 @@ REPRESENTS { return s->type; } +[ \t] {/*ignore spacing characters*/;} + +. { + diag("Invalid ONTOLOGY syntax: expected 'name' or '[name]'", nullptr); +} + {D}+ { /*INTEGER*/ yylval.qp = putintoken(yytext, INTEGER); /* Numbers are not looked for */ return INTEGER; From 3e4537053a07f008509585a3a8f0251b1a284093 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Wed, 25 Sep 2024 16:08:27 +0200 Subject: [PATCH 36/68] Mark RXD test as skip on Ubuntu 22+ (#3080) --- test/rxd/3d/test_multi_gridding_mix.py | 33 +++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/test/rxd/3d/test_multi_gridding_mix.py b/test/rxd/3d/test_multi_gridding_mix.py index 2f7746b4dd..20d9e689a9 100644 --- a/test/rxd/3d/test_multi_gridding_mix.py +++ b/test/rxd/3d/test_multi_gridding_mix.py @@ -1,10 +1,41 @@ -from neuron.units import µm, mM, ms, mV +import platform import sys +import pytest +from packaging.version import Version + +from neuron.units import µm, mM, ms, mV + sys.path.append("..") from testutils import compare_data, tol +def check_platform_is_problematic(): + """ + Check whether the current platform is problematic so tests are skipped. + """ + if platform.system() == "Linux": + # `freedesktop_os_release` is only defined in 3.10+ + if hasattr(platform, "freedesktop_os_release"): + try: + flavor = platform.freedesktop_os_release() + return flavor["ID"] == "ubuntu" and Version( + flavor["VERSION_ID"] + ) > Version("22") + except OSError: + # we cannot determine the flavor reliably (no /etc/os-release file) + return True + else: + # we cannot determine the flavor reliably (<3.10) + return True + else: + return False + + +@pytest.mark.skipif( + check_platform_is_problematic(), + reason="See https://github.com/neuronsimulator/nrn-build-ci/issues/66", +) def test_multi_gridding_mix(neuron_instance): h, rxd, data, save_path = neuron_instance axon = h.Section(name="axon") From 93c7d2c22ffaa8e64f99be084b7f43f1c99ccad3 Mon Sep 17 00:00:00 2001 From: Pramod Kumbhar Date: Wed, 25 Sep 2024 19:34:08 +0200 Subject: [PATCH 37/68] Remove toggling of TABLE from hh.mod (CoreNEURON + NMODL compatibility) (#3093) - We were commenting TABLE statement from hh.mod as TABLE statement was not supported in mod2c. - NMODL on CoreNEURON side supports TABLE statements also on GPU side. - Hence, we can remove the CMake toggling logic for TABLE. - Also update the references for tests in ringtest and testcorenrn repos fixes #1764 --- CMakeLists.txt | 9 +- src/coreneuron/mechanism/mech/modfile/hh.mod | 2 +- test/CMakeLists.txt | 6 +- test/api/hh_sim.cpp | 6 - test/api/netcon.cpp | 9 - test/external/CMakeLists.txt | 4 +- .../connect_dend/cell3soma.core.dat.ref | 203 ------------------ 7 files changed, 6 insertions(+), 233 deletions(-) delete mode 100644 test/hoc_tests/connect_dend/cell3soma.core.dat.ref diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b74dbc9a4..87d423a7b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -747,22 +747,17 @@ add_custom_target( # ============================================================================= if(NRN_ENABLE_CORENEURON OR NRN_ENABLE_MOD_COMPATIBILITY) set(GLOBAL_VAR_TOGGLE_COMMAND "'s/ GLOBAL minf/ RANGE minf/'") - set(TABLE_VAR_TOGGLE_COMMAND "'s/ TABLE minf/ :TABLE minf/'") else() set(GLOBAL_VAR_TOGGLE_COMMAND "'s/ RANGE minf/ GLOBAL minf/'") - set(TABLE_VAR_TOGGLE_COMMAND "'s/ :TABLE minf/ TABLE minf/'") endif() separate_arguments(GLOBAL_VAR_TOGGLE_COMMAND UNIX_COMMAND "${GLOBAL_VAR_TOGGLE_COMMAND}") -separate_arguments(TABLE_VAR_TOGGLE_COMMAND UNIX_COMMAND "${TABLE_VAR_TOGGLE_COMMAND}") add_custom_target( hh_update COMMAND sed ${GLOBAL_VAR_TOGGLE_COMMAND} ${CMAKE_SOURCE_DIR}/src/nrnoc/hh.mod > ${CMAKE_BINARY_DIR}/hh.mod.1 - COMMAND sed ${TABLE_VAR_TOGGLE_COMMAND} ${CMAKE_BINARY_DIR}/hh.mod.1 > - ${CMAKE_BINARY_DIR}/hh.mod.2 - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/hh.mod.2 + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BINARY_DIR}/hh.mod.1 ${CMAKE_SOURCE_DIR}/src/nrnoc/hh.mod - COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/hh.mod.1 ${CMAKE_BINARY_DIR}/hh.mod.2 + COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/hh.mod.1 COMMENT "Update hh.mod for CoreNEURON compatibility" VERBATIM) add_dependencies(nrniv_lib hh_update) diff --git a/src/coreneuron/mechanism/mech/modfile/hh.mod b/src/coreneuron/mechanism/mech/modfile/hh.mod index 053a15f43f..bbb336197c 100644 --- a/src/coreneuron/mechanism/mech/modfile/hh.mod +++ b/src/coreneuron/mechanism/mech/modfile/hh.mod @@ -90,7 +90,7 @@ DERIVATIVE states { PROCEDURE rates(v(mV)) { :Computes rate and other constants at current v. :Call once from HOC to initialize inf at resting v. LOCAL alpha, beta, sum, q10 -: TABLE minf, mtau, hinf, htau, ninf, ntau DEPEND celsius FROM -100 TO 100 WITH 200 + TABLE minf, mtau, hinf, htau, ninf, ntau DEPEND celsius FROM -100 TO 100 WITH 200 UNITSOFF q10 = 3^((celsius - 6.3)/10) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7af63ec56c..c6efbaa74c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -100,11 +100,7 @@ list(APPEND TESTS ringtest) # Add small hoc test # ============================================================================= set(HOCTEST_DIR ${PROJECT_SOURCE_DIR}/test/hoc_tests/connect_dend) -if(NRN_ENABLE_CORENEURON OR NRN_ENABLE_MOD_COMPATIBILITY) - set(REF_FILE cell3soma.core.dat.ref) -else() - set(REF_FILE cell3soma.dat.ref) -endif() +set(REF_FILE cell3soma.dat.ref) add_test( connect_dend ${CMAKE_COMMAND} diff --git a/test/api/hh_sim.cpp b/test/api/hh_sim.cpp index 0dd548c637..b0ab735ce0 100644 --- a/test/api/hh_sim.cpp +++ b/test/api/hh_sim.cpp @@ -16,15 +16,9 @@ using std::endl; using std::ofstream; constexpr std::array EXPECTED_V{ -#ifndef CORENEURON_ENABLED -0x1.04p+6, -0x1.b254ad82e20edp+5, -0x1.24a52af1ab463p+6, -#else - -0x1.04p+6, - -0x1.b0c75635b5bdbp+5, - -0x1.24a84bedb7246p+6, -#endif }; extern "C" void modl_reg(){/* No modl_reg */}; diff --git a/test/api/netcon.cpp b/test/api/netcon.cpp index 87cfd567d5..674ae6d0ec 100644 --- a/test/api/netcon.cpp +++ b/test/api/netcon.cpp @@ -12,21 +12,12 @@ using std::endl; using std::ofstream; constexpr std::array EXPECTED_V{ -#ifndef CORENEURON_ENABLED -0x1.04p+6, -0x1.085a63d029bc3p+6, -0x1.112a5e95eb67cp+6, -0x1.1795abaec26c1p+6, -0x1.0422351f3f9dcp+6, -0x1.03e5317ac368cp+6, -#else - -0x1.04p+6, - -0x1.085a703d657a7p+6, - -0x1.112d0039e9c38p+6, - -0x1.17974aa201b7bp+6, - -0x1.041fdf57a182bp+6, - -0x1.03e58fad20b92p+6, -#endif }; extern "C" void modl_reg(){/* No modl_reg */}; diff --git a/test/external/CMakeLists.txt b/test/external/CMakeLists.txt index 5dcf1a4bce..243a3ab904 100644 --- a/test/external/CMakeLists.txt +++ b/test/external/CMakeLists.txt @@ -7,13 +7,13 @@ include(FetchContent) FetchContent_Declare( ringtest GIT_REPOSITORY https://github.com/neuronsimulator/ringtest - GIT_TAG 4ede4751c68f72a9884c6af4f94f65ff638054a8 + GIT_TAG 7d1aee72939f6dfcb2a14db4c7b00725d9e485fa SOURCE_DIR ${PROJECT_SOURCE_DIR}/external/tests/ringtest) FetchContent_Declare( testcorenrn GIT_REPOSITORY https://github.com/neuronsimulator/testcorenrn - GIT_TAG 014aab9bee60a2bdd44b28a784c88092d2f6b92b + GIT_TAG e53831b3963af8be412e16807a85157e4413f307 SOURCE_DIR ${PROJECT_SOURCE_DIR}/external/tests/testcorenrn) FetchContent_Declare( diff --git a/test/hoc_tests/connect_dend/cell3soma.core.dat.ref b/test/hoc_tests/connect_dend/cell3soma.core.dat.ref deleted file mode 100644 index b0d38144b5..0000000000 --- a/test/hoc_tests/connect_dend/cell3soma.core.dat.ref +++ /dev/null @@ -1,203 +0,0 @@ -t soma.v(0.5) -201 2 - 0 -65 - 0.025 -65.025 - 0.05 -65.0671 - 0.075 -65.1203 - 0.1 -65.1809 - 0.125 -65.2462 - 0.15 -65.3146 - 0.175 -65.3848 - 0.2 -65.4561 - 0.225 -65.5279 - 0.25 -65.5998 - 0.275 -65.6714 - 0.3 -65.7427 - 0.325 -65.8134 - 0.35 -65.8835 - 0.375 -65.9528 - 0.4 -66.0213 - 0.425 -66.0889 - 0.45 -66.1555 - 0.475 -66.2213 - 0.5 -66.286 - 0.525 -66.3497 - 0.55 -66.4124 - 0.575 -66.4741 - 0.6 -66.5348 - 0.625 -66.5944 - 0.65 -66.6529 - 0.675 -66.7104 - 0.7 -66.7669 - 0.725 -66.8223 - 0.75 -66.8766 - 0.775 -66.93 - 0.8 -66.9823 - 0.825 -67.0335 - 0.85 -67.0838 - 0.875 -67.1331 - 0.9 -67.1813 - 0.925 -67.2286 - 0.95 -67.2749 - 0.975 -67.3203 - 1 -67.3647 - 1.025 -67.4081 - 1.05 -67.4507 - 1.075 -67.4923 - 1.1 -67.5331 - 1.125 -67.573 - 1.15 -67.612 - 1.175 -67.6502 - 1.2 -67.6875 - 1.225 -67.724 - 1.25 -67.7597 - 1.275 -67.7946 - 1.3 -67.8287 - 1.325 -67.8621 - 1.35 -67.8947 - 1.375 -67.9265 - 1.4 -67.9577 - 1.425 -67.9881 - 1.45 -68.0178 - 1.475 -68.0469 - 1.5 -68.0753 - 1.525 -68.103 - 1.55 -68.1301 - 1.575 -68.1565 - 1.6 -68.1823 - 1.625 -68.2076 - 1.65 -68.2322 - 1.675 -68.2563 - 1.7 -68.2797 - 1.725 -68.3027 - 1.75 -68.325 - 1.775 -68.3469 - 1.8 -68.3682 - 1.825 -68.389 - 1.85 -68.4093 - 1.875 -68.4291 - 1.9 -68.4485 - 1.925 -68.4673 - 1.95 -68.4858 - 1.975 -68.5037 - 2 -68.5212 - 2.025 -68.5383 - 2.05 -68.555 - 2.075 -68.5712 - 2.1 -68.5871 - 2.125 -68.6026 - 2.15 -68.6176 - 2.175 -68.6323 - 2.2 -68.6467 - 2.225 -68.6606 - 2.25 -68.6743 - 2.275 -68.6875 - 2.3 -68.7005 - 2.325 -68.7131 - 2.35 -68.7254 - 2.375 -68.7374 - 2.4 -68.749 - 2.425 -68.7604 - 2.45 -68.7715 - 2.475 -68.7823 - 2.5 -68.7928 - 2.525 -68.803 - 2.55 -68.813 - 2.575 -68.8227 - 2.6 -68.8321 - 2.625 -68.8413 - 2.65 -68.8503 - 2.675 -68.859 - 2.7 -68.8675 - 2.725 -68.8758 - 2.75 -68.8838 - 2.775 -68.8916 - 2.8 -68.8992 - 2.825 -68.9066 - 2.85 -68.9139 - 2.875 -68.9209 - 2.9 -68.9277 - 2.925 -68.9343 - 2.95 -68.9407 - 2.975 -68.947 - 3 -68.9531 - 3.025 -68.959 - 3.05 -68.9648 - 3.075 -68.9703 - 3.1 -68.9758 - 3.125 -68.981 - 3.15 -68.9862 - 3.175 -68.9911 - 3.2 -68.996 - 3.225 -69.0007 - 3.25 -69.0052 - 3.275 -69.0096 - 3.3 -69.0139 - 3.325 -69.0181 - 3.35 -69.0221 - 3.375 -69.026 - 3.4 -69.0298 - 3.425 -69.0335 - 3.45 -69.037 - 3.475 -69.0405 - 3.5 -69.0438 - 3.525 -69.0471 - 3.55 -69.0502 - 3.575 -69.0532 - 3.6 -69.0562 - 3.625 -69.059 - 3.65 -69.0617 - 3.675 -69.0644 - 3.7 -69.067 - 3.725 -69.0694 - 3.75 -69.0718 - 3.775 -69.0741 - 3.8 -69.0764 - 3.825 -69.0785 - 3.85 -69.0806 - 3.875 -69.0826 - 3.9 -69.0845 - 3.925 -69.0864 - 3.95 -69.0882 - 3.975 -69.0899 - 4 -69.0916 - 4.025 -69.0932 - 4.05 -69.0947 - 4.075 -69.0962 - 4.1 -69.0976 - 4.125 -69.0989 - 4.15 -69.1002 - 4.175 -69.1015 - 4.2 -69.1027 - 4.225 -69.1038 - 4.25 -69.1049 - 4.275 -69.1059 - 4.3 -69.1069 - 4.325 -69.1078 - 4.35 -69.1087 - 4.375 -69.1096 - 4.4 -69.1104 - 4.425 -69.1112 - 4.45 -69.1119 - 4.475 -69.1126 - 4.5 -69.1132 - 4.525 -69.1138 - 4.55 -69.1144 - 4.575 -69.1149 - 4.6 -69.1154 - 4.625 -69.1159 - 4.65 -69.1163 - 4.675 -69.1167 - 4.7 -69.117 - 4.725 -69.1174 - 4.75 -69.1177 - 4.775 -69.118 - 4.8 -69.1182 - 4.825 -69.1184 - 4.85 -69.1186 - 4.875 -69.1188 - 4.9 -69.1189 - 4.925 -69.119 - 4.95 -69.1191 - 4.975 -69.1192 - 5 -69.1192 From 95cc05b38b96e256f95af583fea4124777161843 Mon Sep 17 00:00:00 2001 From: nrnhines Date: Mon, 30 Sep 2024 17:54:39 -0400 Subject: [PATCH 38/68] Test for PR 3055 (#3081) # fix a few problems with PR 3055. * For bitset single bit, first reset, then set the bit. * Add another mod file to neurondemo that WRITE cai. * Replace // LCOV_EXCL_END with // LCOV_EXCL_STOP --------- Co-authored-by: wthun Co-authored-by: Luc Grosheintz --- share/demo/release/capmpr.mod | 90 ++++++++++++++++++++ src/ivoc/apwindow.cpp | 2 +- src/ivoc/pwman.cpp | 2 +- src/nrnoc/eion.cpp | 7 +- src/sundials/cvodes/cvodes.c | 2 +- test/hoctests/tests/test_eion_cover.py | 62 ++++++++++++++ test/hoctests/tests/test_neurondemo.py | 113 +++++++++++++++++++++++++ 7 files changed, 272 insertions(+), 6 deletions(-) create mode 100644 share/demo/release/capmpr.mod create mode 100644 test/hoctests/tests/test_eion_cover.py diff --git a/share/demo/release/capmpr.mod b/share/demo/release/capmpr.mod new file mode 100644 index 0000000000..40abd43d13 --- /dev/null +++ b/share/demo/release/capmpr.mod @@ -0,0 +1,90 @@ +: capump.mod plus a "reservoir" used to initialize cai to desired concentrations + +UNITS { + (mM) = (milli/liter) + (mA) = (milliamp) + (um) = (micron) + (mol) = (1) + PI = (pi) (1) + FARADAY = (faraday) (coulomb) +} + +NEURON { + SUFFIX capmpr + USEION ca READ cao, cai WRITE cai, ica + GLOBAL k1, k2, k3, k4 + GLOBAL car, tau +} + +STATE { + pump (mol/cm2) + pumpca (mol/cm2) + cai (mM) +} + +PARAMETER { + car = 5e-5 (mM) : ca in reservoir, used to initialize cai to desired concentrations + tau = 1e9 (ms) : rate of equilibration between cai and car + + k1 = 5e8 (/mM-s) + k2 = .25e6 (/s) + k3 = .5e3 (/s) + k4 = 5e0 (/mM-s) + + pumpdens = 3e-14 (mol/cm2) +} + +CONSTANT { + volo = 1 (liter) +} + +ASSIGNED { + diam (um) + cao (mM) + + ica (mA/cm2) + ipump (mA/cm2) + ipump_last (mA/cm2) + voli (um3) + area1 (um2) + c1 (1+8 um5/ms) + c2 (1-10 um2/ms) + c3 (1-10 um2/ms) + c4 (1+8 um5/ms) +} + +BREAKPOINT { + SOLVE pmp METHOD sparse + ipump_last = ipump + ica = ipump +} + +KINETIC pmp { + COMPARTMENT voli {cai} + COMPARTMENT (1e10)*area1 {pump pumpca} + COMPARTMENT volo*(1e15) {cao car} + + ~ car <-> cai (1(um3)/tau,1(um3)/tau) + ~ cai + pump <-> pumpca (c1,c2) + ~ pumpca <-> pump + cao (c3,c4) + + : note that forward flux here is the outward flux + ipump = (1e-4)*2*FARADAY*(f_flux - b_flux)/area1 + + : ipump_last vs ipump needed because of STEADYSTATE calculation + ~ cai << (-(ica - ipump_last)*area1/(2*FARADAY)*(1e4)) + + CONSERVE pump + pumpca = (1e10)*area1*pumpdens +} + +INITIAL { + :cylindrical coordinates; actually vol and area1/unit length + voli = PI*(diam/2)^2 * 1(um) + area1 = 2*PI*(diam/2) * 1(um) + c1 = (1e7)*area1 * k1 + c2 = (1e7)*area1 * k2 + c3 = (1e7)*area1 * k3 + c4 = (1e7)*area1 * k4 + + SOLVE pmp STEADYSTATE sparse +} diff --git a/src/ivoc/apwindow.cpp b/src/ivoc/apwindow.cpp index 71c07bcf36..e5afea2fc2 100644 --- a/src/ivoc/apwindow.cpp +++ b/src/ivoc/apwindow.cpp @@ -415,7 +415,7 @@ bool PrintableWindow::receive(const Event& e) { reconfigured(); notify(); break; - // LCOV_EXCL_END + // LCOV_EXCL_STOP case MapNotify: if (xplace_) { if (xtop() != xtop_ || xleft() != xleft_) { diff --git a/src/ivoc/pwman.cpp b/src/ivoc/pwman.cpp index 29335af77f..d0ec316a47 100644 --- a/src/ivoc/pwman.cpp +++ b/src/ivoc/pwman.cpp @@ -1477,7 +1477,7 @@ void PrintableWindow::reconfigured() { xmove(x, y); } } -// LCOV_EXCL_END +// LCOV_EXCL_STOP void ViewWindow::reconfigured() { if (!pixres) { diff --git a/src/nrnoc/eion.cpp b/src/nrnoc/eion.cpp index 4c841f4c2c..e8e7657b7e 100644 --- a/src/nrnoc/eion.cpp +++ b/src/nrnoc/eion.cpp @@ -430,9 +430,10 @@ void nrn_check_conc_write(Prop* p_ok, Prop* pion, int i) { } for (k = 0, j = 0; j < n_memb_func; ++j) { if (nrn_is_ion(j)) { - ion_bit_[j] = (1 << k); - ++k; assert(k < max_ions); + ion_bit_[j].reset(); + ion_bit_[j].set(k); + ++k; } } @@ -640,7 +641,7 @@ void second_order_cur(NrnThread* nt) { extern int secondorder; NrnThreadMembList* tml; Memb_list* ml; - int j, i, i2; + int i, i2; constexpr auto c = 3; constexpr auto dc = 4; if (secondorder == 2) { diff --git a/src/sundials/cvodes/cvodes.c b/src/sundials/cvodes/cvodes.c index 8fee9feabb..48a96db636 100755 --- a/src/sundials/cvodes/cvodes.c +++ b/src/sundials/cvodes/cvodes.c @@ -3285,7 +3285,7 @@ static int CVStep(CVodeMem cv_mem) dsm = CVStgrUpdateDsm(cv_mem, dsm, dsmS); } } - // LCOV_EXCL_END + // LCOV_EXCL_STOP /* Everything went fine; exit loop */ break; diff --git a/test/hoctests/tests/test_eion_cover.py b/test/hoctests/tests/test_eion_cover.py new file mode 100644 index 0000000000..73e96aa35c --- /dev/null +++ b/test/hoctests/tests/test_eion_cover.py @@ -0,0 +1,62 @@ +from neuron import h +from neuron.expect_hocerr import expect_err, set_quiet + +set_quiet(0) +from math import isclose + + +def test_nernst(): + assert h.nernst(1, 1, 0) == 0.0 + assert h.nernst(-1, 1, 1) == 1e6 + assert h.nernst(1, -1, 1) == -1e6 + + s = h.Section() + s.insert("hh") + assert isclose(h.nernst("ena", sec=s), 63.55150321937486) + assert isclose(h.nernst("ena", 0.5, sec=s), 63.55150321937486) + assert isclose(h.nernst("nai", sec=s), 17.554820246530547) + assert isclose(h.nernst("nao", sec=s), 79.7501757545304) + expect_err('h.nernst("ina", sec=s)') + + del s + locals() + + +def test_ghk(): + assert isclose(h.ghk(-10, 0.1, 10, 2), -2828.3285716150644) + assert isclose(h.ghk(1e-6, 0.1, 10, 2), -1910.40949510667) + + +def test_ion_style(): + expect_err('h.ion_style("foo")') + + +def test_second_order_cur(): + s = h.Section() + s.insert("hh") + h.secondorder = 2 + h.finitialize(-65) + h.fadvance() + assert isclose(s(0.5).ina, -0.001220053188847315) + h.secondorder = 0 + h.finitialize(-65) + h.fadvance() + assert isclose(s(0.5).ina, -0.0012200571764654333) + + +def test_ion_charge(): + assert h.ion_charge("na_ion") == 1 + expect_err('h.ion_charge("na") == 1') + + +def test_eion_cover(): + test_nernst() + test_ghk() + test_ion_style() + test_second_order_cur() + test_ion_charge() + + +if __name__ == "__main__": + test_eion_cover() + h.topology() diff --git a/test/hoctests/tests/test_neurondemo.py b/test/hoctests/tests/test_neurondemo.py index b3c8d6bcbf..78f88f861e 100644 --- a/test/hoctests/tests/test_neurondemo.py +++ b/test/hoctests/tests/test_neurondemo.py @@ -13,6 +13,7 @@ dir_path = os.path.dirname(os.path.realpath(__file__)) chk = Chk(os.path.join(dir_path, "test_neurondemo.json")) + # Run a command with input into stdin def run(cmd, input): p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, text=True) @@ -47,6 +48,7 @@ def run(cmd, input): quit() """ + # run neurondemo and return the stdout lines between ZZZbegin and ZZZend def neurondemo(extra, input): input = extra + input @@ -172,3 +174,114 @@ def neurondemo(extra, input): chk(key, rich_data) chk.save() + +################################################ +# test_many_ions.py copied below and removed to fix a CI coverage test failure: +# libgcov profiling error:/home/...demo/release/x86_64/mod_func.gcda:overwriting +# an existing profile data with a different timestamp. +# I was unable to reproduce the coverage test failure on my linux desktop by +# experimenting with parallel runs of the distinct tests. Nevertheless, +# CI coverage is successful when the use of the neurondemo shared library is +# serialized into this file. +# I'd rather keep the file and run from here via something like +# run("python test_many_ions.py", "") +# but cmake installs each hoctest file in a separate folder and "python" may not +# be the name of the program we need to run. +########################### +# Test when large number of ion mechanisms exist. + +# Strategy is to create a large number of ion mechanisms before loading +# the neurondemo mod file shared library which will create the ca ion +# along with several mechanisms that write to cai. + +from neuron import h, load_mechanisms +from platform import machine +import sys +import io + + +# return True if name exists in h +def exists(name): + try: + exec("h.%s" % name) + except: + return False + return True + + +# use up a large number of mechanism indices for ions. And want to test beyond +# 1000 which requires change to max_ions in nrn/src/nrnoc/eion.cpp +nion = 250 +ion_indices = [int(h.ion_register("ca%d" % i, 2)) for i in range(1, nion + 1)] +# gain some confidence they exist +assert exists("ca%d_ion" % nion) +assert (ion_indices[-1] - ion_indices[0]) == (nion - 1) +mt = h.MechanismType(0) +assert mt.count() > nion + +# this test depends on the ca ion not existing at this point +assert exists("ca_ion") is False + +# load neurondemo mod files. That will create ca_ion and provide two +# mod files that write cai +# Following Aborts prior to PR#3055 with +# eion.cpp:431: void nrn_check_conc_write(Prop*, Prop*, int): Assertion `k < sizeof(long) * 8' failed. +nrnmechlibpath = "%s/demo/release" % h.neuronhome() +print(nrnmechlibpath) +assert load_mechanisms(nrnmechlibpath) + +# ca_ion now exists and has a mechanism index > nion +assert exists("ca_ion") +mt = h.MechanismType(0) # new mechanisms do not appear in old MechanismType +mt.select("ca_ion") +assert mt.selected() > nion + + +# return stderr output resulting from sec.insert(mechname) +def mech_insert(sec, mechname): + # capture stderr + old_stderr = sys.stderr + sys.stderr = mystderr = io.StringIO() + + sec.insert(mechname) + + sys.stderr = old_stderr + return mystderr.getvalue() + + +# test if can use the high mechanism index cadifpmp (with USEION ... WRITE cai) along with the high mechanims index ca_ion +s = h.Section() +s.insert("cadifpmp") +h.finitialize(-65) +# The ion_style tells whether cai or cao is being written +istyle = int(h.ion_style("ca_ion", sec=s)) +assert istyle & 0o200 # writing cai +assert (istyle & 0o400) == 0 # not writing ca0 +# unfortunately, at present, uninserting does not turn off that bit +s.uninsert("cadifpmp") +assert s.has_membrane("cadifpmp") is False +assert int(h.ion_style("ca_ion", sec=s)) & 0o200 +# nevertheless, on reinsertion, there is no warning, so can't test the +# warning without a second mechanism that WRITE cai +assert mech_insert(s, "cadifpmp") == "" +assert s.has_membrane("cadifpmp") +# uninsert again and insert another mechanism that writes. +s.uninsert("cadifpmp") +assert mech_insert(s, "capmpr") == "" # no warning +assert mech_insert(s, "cadifpmp") != "" # now there is a warning. + +# more serious test +# several sections with alternating cadifpmp and capmpr +del s +secs = [h.Section() for i in range(5)] +for i, s in enumerate(secs): + if i % 2: + assert mech_insert(s, "capmpr") == "" + else: + assert mech_insert(s, "cadifpmp") == "" + +# warnings due to multiple mechanisms at same location that WRITE cai +assert mech_insert(secs[2], "capmpr") != "" +assert mech_insert(secs[3], "cadifpmp") != "" + +############################################ From 3fcec76409f2bbf25a0931cdb87f21b4cb2020f0 Mon Sep 17 00:00:00 2001 From: nrnhines Date: Tue, 1 Oct 2024 10:37:28 -0400 Subject: [PATCH 39/68] no limit on number of ion mechanisms (#3089) * replaces bitset by map of sets. --- src/nrnoc/eion.cpp | 80 +++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/nrnoc/eion.cpp b/src/nrnoc/eion.cpp index e8e7657b7e..6dece3efb8 100644 --- a/src/nrnoc/eion.cpp +++ b/src/nrnoc/eion.cpp @@ -15,9 +15,8 @@ #include #include -#include -#include -#include +#include +#include #undef hoc_retpushx @@ -394,17 +393,37 @@ double nrn_nernst_coef(int type) { /* It is generally an error for two models to WRITE the same concentration. -This functions checks that there's no write conflict; and warns if it detects -one. It also sets respective write flag in the style of the ion. +nrn_check_conc_write checks that there's no write conflict; and warns if it +detects one. It also sets respective write flag in the style of the ion. The argument `i` specifies which concentration is being written to. It's 0 for exterior; and 1 for interior. */ -void nrn_check_conc_write(Prop* p_ok, Prop* pion, int i) { - const int max_ions = 256; - static long size_; - static std::vector> chk_conc_, ion_bit_; +// Each mechanism type index that writes a concentration has a set of ion +// type indices it writes to. +// ionconctype is coded as iontype*2 + i where i=1 for interior +// So number of distinct ion mechanisms is essentially unlimited, max_int/2. +static std::map> mechtype2ionconctype; + +static void add_mechtype2ionconctype(int mechtype, int iontype, int i) { + auto& set_of_ionconctypes = mechtype2ionconctype[mechtype]; + set_of_ionconctypes.insert(2 * iontype + i); // unique though inserting for each instance. +} + +static bool mech_uses_ionconctype(int mechtype, int iontype, int i) { + if (auto search = mechtype2ionconctype.find(mechtype); search != mechtype2ionconctype.end()) { + auto& set_of_ionconctypes = search->second; + return set_of_ionconctypes.count(2 * iontype + i) == 1; + } + return false; +} + +void nrn_check_conc_write(Prop* pmech, Prop* pion, int i) { + // Would be less redundant to generate the "database" at + // mechanism registration time. But NMODL presently gives us this info + // only at each mechanism instance allocation. + add_mechtype2ionconctype(pmech->_type, pion->_type, i); Prop* p; int flag, j, k; @@ -414,51 +433,32 @@ void nrn_check_conc_write(Prop* p_ok, Prop* pion, int i) { flag = 0400; } - /* Create a vector holding std::bitset to track which ions - are being written to the membrane */ - if (n_memb_func > size_) { - chk_conc_.resize(2 * n_memb_func); - ion_bit_.resize(n_memb_func); - - for (j = size_; j < n_memb_func; ++j) { - chk_conc_[2 * j].reset(); - chk_conc_[2 * j + 1].reset(); - ion_bit_[j].reset(); - } - - size_ = n_memb_func; - } - for (k = 0, j = 0; j < n_memb_func; ++j) { - if (nrn_is_ion(j)) { - assert(k < max_ions); - ion_bit_[j].reset(); - ion_bit_[j].set(k); - ++k; - } - } - - chk_conc_[2 * p_ok->_type + i] |= ion_bit_[pion->_type]; - if (pion->dparam[iontype_index_dparam].get() & flag) { - /* now comes the hard part. Is the possibility in fact actual.*/ + auto ii = pion->dparam[iontype_index_dparam].get(); + if (ii & flag) { + // Is the possibility in fact actual. Unfortunately, uninserting the + // mechanism that writes a concentration does not reset the flag bit. + // So search the node property list for another mechanism that also + // writes this ion concentration. (that is needed anyway to + // fill out the warning message.) + + // the pion in the node property list is before mechanisms that use the ion for (p = pion->next; p; p = p->next) { - if (p == p_ok) { + if (p == pmech) { continue; } - auto rst = chk_conc_[2 * p->_type + i] & ion_bit_[pion->_type]; - if (rst.any()) { + if (mech_uses_ionconctype(p->_type, pion->_type, i)) { char buf[300]; Sprintf(buf, "%.*s%c is being written at the same location by %s and %s", (int) strlen(memb_func[pion->_type].sym->name) - 4, memb_func[pion->_type].sym->name, ((i == 1) ? 'i' : 'o'), - memb_func[p_ok->_type].sym->name, + memb_func[pmech->_type].sym->name, memb_func[p->_type].sym->name); hoc_warning(buf, (char*) 0); } } } - auto ii = pion->dparam[iontype_index_dparam].get(); ii |= flag; pion->dparam[iontype_index_dparam] = ii; } From 6ce617967d199b899aae22cc2743e49391b22d15 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Wed, 2 Oct 2024 10:58:34 +0200 Subject: [PATCH 40/68] Use ftpmirror.gnu.org as requested by gnu.org (#3107) --- .github/workflows/neuron-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/neuron-ci.yml b/.github/workflows/neuron-ci.yml index e3ca977eb4..dfe8a9327c 100644 --- a/.github/workflows/neuron-ci.yml +++ b/.github/workflows/neuron-ci.yml @@ -188,12 +188,12 @@ jobs: python -m pip install --upgrade pip -r nrn_requirements.txt - name: Install a new automake - # A new automake is needed for python 3.12 because it generate a python script + # A automake >= 1.16.5 is needed for python 3.12 because it generates a python script # called py-compile and the original one is not supporting this version of python # Once ubuntu got a newer version of automake we can remove this part. if: matrix.config.music == 'ON' && startsWith(matrix.os, 'ubuntu') run: | - curl -L -o automake.tar.xz https://ftp.gnu.org/gnu/automake/automake-1.16.5.tar.xz + curl -L -o automake.tar.xz https://ftpmirror.gnu.org/gnu/automake/automake-1.16.5.tar.xz tar -xf automake.tar.xz cd automake-1.16.5/ ./configure --prefix=/usr/ From a2b8b350a609ff02a97576a9d3fcc86fccfca8a3 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Wed, 2 Oct 2024 11:05:32 +0200 Subject: [PATCH 41/68] Fix: remove deprecated test methods (#3105) --- share/lib/python/neuron/tests/test_neuron.py | 3 +-- share/lib/python/neuron/tests/test_rxd.py | 3 +-- share/lib/python/neuron/tests/test_vector.py | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/share/lib/python/neuron/tests/test_neuron.py b/share/lib/python/neuron/tests/test_neuron.py index 6c49934f30..d300aa3c26 100644 --- a/share/lib/python/neuron/tests/test_neuron.py +++ b/share/lib/python/neuron/tests/test_neuron.py @@ -294,8 +294,7 @@ def suite(): ] except: pass - suite = unittest.makeSuite(NeuronTestCase, "test") - return suite + return unittest.defaultTestLoader.loadTestsFromTestCase(NeuronTestCase) if __name__ == "__main__": diff --git a/share/lib/python/neuron/tests/test_rxd.py b/share/lib/python/neuron/tests/test_rxd.py index 964bd53738..db85696c90 100644 --- a/share/lib/python/neuron/tests/test_rxd.py +++ b/share/lib/python/neuron/tests/test_rxd.py @@ -798,8 +798,7 @@ def test_ecs_diffusion_variable_step_fine(self): def suite(): - suite = unittest.makeSuite(RxDTestCase, "test") - return suite + return unittest.defaultTestLoader.loadTestsFromTestCase(RxDTestCase) def test(): diff --git a/share/lib/python/neuron/tests/test_vector.py b/share/lib/python/neuron/tests/test_vector.py index ee92f0bb27..17ed26bd42 100644 --- a/share/lib/python/neuron/tests/test_vector.py +++ b/share/lib/python/neuron/tests/test_vector.py @@ -156,8 +156,7 @@ def testErrorHandling(self): def suite(): - suite = unittest.makeSuite(VectorTestCase, "test") - return suite + return unittest.defaultTestLoader.loadTestsFromTestCase(VectorTestCase) if __name__ == "__main__": From 5b49b24f25afdea1ec751ba0be523bddde91ede1 Mon Sep 17 00:00:00 2001 From: Koen van Walstijn <38299796+kbvw@users.noreply.github.com> Date: Wed, 2 Oct 2024 20:58:00 +0200 Subject: [PATCH 42/68] Make notebooks work with `bokeh>=3` and remove `bokeh<3` pin (#3061) * Register `h.Vector` serialization function with Bokeh in notebooks * Unpin `bokeh<3` in documentation requirements and remove from main requirements * Unpin `numpy<2` in documentation requirements * Move serializer registration to `__init__.py` --- docs/docs_requirements.txt | 5 ++--- nrn_requirements.txt | 2 -- share/lib/python/neuron/__init__.py | 10 ++++++++++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/docs_requirements.txt b/docs/docs_requirements.txt index 6571d22ac2..cd4982ca08 100644 --- a/docs/docs_requirements.txt +++ b/docs/docs_requirements.txt @@ -5,12 +5,11 @@ jupyter nbconvert myst_parser matplotlib -# bokeh 3 seems to break docs notebooks -bokeh<3 +bokeh # do not check import of next line ipython plotnine -numpy<2 +numpy plotly nbsphinx jinja2 diff --git a/nrn_requirements.txt b/nrn_requirements.txt index f049602b4e..1de5573095 100644 --- a/nrn_requirements.txt +++ b/nrn_requirements.txt @@ -3,8 +3,6 @@ setuptools_scm setuptools<=70.3.0 scikit-build matplotlib -# bokeh 3 seems to break docs notebooks -bokeh<3 ipython cython packaging diff --git a/share/lib/python/neuron/__init__.py b/share/lib/python/neuron/__init__.py index f84021c4da..7ea748288c 100644 --- a/share/lib/python/neuron/__init__.py +++ b/share/lib/python/neuron/__init__.py @@ -1835,3 +1835,13 @@ def _mview_html_tree(hlist, inside_mechanisms_in_use=0): if _get_ipython() is not None: html_formatter = _get_ipython().display_formatter.formatters["text/html"] html_formatter.for_type(hoc.HocObject, _hocobj_html) + +# in case Bokeh is installed, register a serialization function for hoc.Vector +try: + from bokeh.core.serialization import Serializer + + Serializer.register( + h.Vector, lambda obj, serializer: [serializer.encode(item) for item in obj] + ) +except ImportError: + pass From deb82e1590ba0301dd89b673e88ec6ba4ff07eba Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 3 Oct 2024 16:22:55 +0200 Subject: [PATCH 43/68] sonar: stop reporting error from C++20 (#3111) Co-authored-by: Nicolas Cornu --- sonar-project.properties | 1 + 1 file changed, 1 insertion(+) create mode 100644 sonar-project.properties diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000000..8122af33fa --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1 @@ +sonar.cfamily.reportingCppStandardOverride=c++17 From 90f2ec24a63731a5c27e53dd74638682b3edb08e Mon Sep 17 00:00:00 2001 From: Pramod Kumbhar Date: Thu, 3 Oct 2024 17:14:23 +0200 Subject: [PATCH 44/68] Update docs about possible MOD files compilation errors with >=9.0 (#3106) - Add a table with all models and MOD files so that it would be easy for users to find the changed mod file. - Change the sphinx version to >= 9.0 - Add a link in the top-level README fixes #1876 --- README.md | 7 +- bin/nrnivmodl.in | 14 +- docs/guide/porting_mechanisms_to_cpp.rst | 498 +++++++++++++++++++---- docs/index.rst | 8 +- docs/rst_substitutions.txt | 4 +- 5 files changed, 444 insertions(+), 87 deletions(-) diff --git a/README.md b/README.md index f6cba70ead..cbcc195fee 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,16 @@ Linux and Mac you can install the official Python 3 wheel with: pip3 install neuron ``` -If you want to build the latest version from source, we support **CMake** as build system. **Autotools** build system has been removed after 8.0 release. +If you want to build the latest version from source, we support **CMake** as build system. See detailed installation instructions: [docs/install/install_instructions.md](docs/install/install_instructions.md). It is possible to install the Linux Python wheels on Windows via the Windows Subsystem for Linux (WSL) - check the installation instructions above. +> [!NOTE] +> **About NEURON >= 9.0**: If you are experiencing compilation errors while using +> `nrnivmodl` with NEURON >=9.0, but not with previous 8.x releases, see +> [Adapting MOD files for C++ with NEURON >= 9.0](docs/guide/porting_mechanisms_to_cpp.rst). + ## Documentation * See documentation section of the [NEURON website](https://neuron.yale.edu/neuron/docs) diff --git a/bin/nrnivmodl.in b/bin/nrnivmodl.in index 2dc1d5aaf4..ce34ff95fe 100755 --- a/bin/nrnivmodl.in +++ b/bin/nrnivmodl.in @@ -274,5 +274,15 @@ if [ "$LinkCoreNEURON" = true ] ; then fi fi -make -j 4 -f "${bindir}/nrnmech_makefile" "ROOT=${prefix}" "MODOBJFILES=$MODOBJS" "UserLDFLAGS=$UserLDFLAGS" "UserINCFLAGS=$UserINCFLAGS" "LinkCoreNEURON=$LinkCoreNEURON" "UserNMODLBIN=$UserNMODLBIN" "UserNMODLFLAGS=$UserNMODLFLAGS" special && -echo "Successfully created $MODSUBDIR/special" +set +e + +make -j 4 -f "${bindir}/nrnmech_makefile" "ROOT=${prefix}" "MODOBJFILES=$MODOBJS" "UserLDFLAGS=$UserLDFLAGS" "UserINCFLAGS=$UserINCFLAGS" "LinkCoreNEURON=$LinkCoreNEURON" "UserNMODLBIN=$UserNMODLBIN" "UserNMODLFLAGS=$UserNMODLFLAGS" special + + MAKE_STATUS=$? + + if [ $MAKE_STATUS -eq 0 ]; then + echo "Successfully created $MODSUBDIR/special" + else + printf "\nNOTE: If you are encountering MOD file compilation errors only with NEURON version 9.0 or later\n" + printf "refer to the C++ migration guide at https://nrn.readthedocs.io/en/9.0.0/guide/porting_mechanisms_to_cpp.html\n\n" + fi diff --git a/docs/guide/porting_mechanisms_to_cpp.rst b/docs/guide/porting_mechanisms_to_cpp.rst index 4f813bd2df..c3d97a1c25 100644 --- a/docs/guide/porting_mechanisms_to_cpp.rst +++ b/docs/guide/porting_mechanisms_to_cpp.rst @@ -5,6 +5,11 @@ Adapting MOD files for C++ with |neuron_with_cpp_mechanisms| ============================================================ +.. attention:: + This guide only applies if you have MOD files with VERBATIM blocks that fail + to compile with |neuron_with_cpp_mechanisms| but work with older versions of + NEURON. If this is not your case, you can skip this guide. + In older versions of NEURON, MOD files containing NMODL code were translated into C code before being compiled and executed by NEURON. Starting with |neuron_with_cpp_mechanisms|, NMODL code is translated into C++ @@ -37,87 +42,418 @@ macros described in :ref:`verbatim` may prove useful. An updated version may already be available! The following models were updated in ModelDB in preparation for - |neuron_with_cpp_mechanisms| and may serve as useful references: - `2487 `_, - `2730 `_, - `2733 `_, - `3658 `_, - `7399 `_, - `7400 `_, - `8284 `_, - `9889 `_, - `12631 `_, - `26997 `_, - `35358 `_, - `37819 `_, - `51781 `_, - `52034 `_, - `64229 `_, - `64296 `_, - `87585 `_, - `93321 `_, - `97868 `_, - `97874 `_, - `97917 `_, - `105507 `_, - `106891 `_, - `113732 `_, - `116094 `_, - `116830 `_, - `116838 `_, - `116862 `_, - `123815 `_, - `136095 `_, - `136310 `_, - `137845 `_, - `138379 `_, - `139421 `_, - `140881 `_, - `141505 `_, - `144538 `_, - `144549 `_, - `144586 `_, - `146949 `_, - `149000 `_, - `149739 `_, - `150240 `_, - `150245 `_, - `150551 `_, - `150556 `_, - `150691 `_, - `151126 `_, - `151282 `_, - `153280 `_, - `154732 `_, - `155568 `_, - `155601 `_, - `155602 `_, - `156780 `_, - `157157 `_, - `168874 `_, - `181967 `_, - `182129 `_, - `183300 `_, - `185355 `_, - `185858 `_, - `186768 `_, - `187604 `_, - `189154 `_, - `194897 `_, - `195615 `_, - `223031 `_, - `225080 `_, - `231427 `_, - `232097 `_, - `239177 `_, - `241165 `_, - `241240 `_, - `244262 `_, - `244848 `_, - `247968 `_, - `249463 `_, - `256388 `_ and - `259366 `_. + |neuron_with_cpp_mechanisms| and may serve as useful references. You can see + updated MOD files in the `Changed Mod Files` column. You can just apply the changes + to your MOD files, or you can use the updated MOD files directly from the GitHub repository. + +.. list-table:: + :header-rows: 1 + + * - ModelDB Id + - Model Name + - GitHub Repository + - Pull Request + - Changed Mod Files + * - `2487 `_ + - Olfactory Mitral Cell (Davison et al 2000) + - `ModelDBRepository/2487 `_ + - `pull/1 `_ + - cadecay.mod + * - `2730 `_ + - Olfactory Bulb Network (Davison et al 2003) + - `ModelDBRepository/2730 `_ + - `pull/1 `_ + - cadecay.mod + * - `2733 `_ + - Olfactory Mitral Cell (Bhalla, Bower 1993) + - `ModelDBRepository/2733 `_ + - `pull/1 `_ + - cadecay.mod + * - `3658 `_ + - Glutamate diffusion ...lar glomerulus (Saftenku 2005) + - `ModelDBRepository/3658 `_ + - `pull/1 `_ + - glubbfbm.mod glubes2.mod glubes23.mod glubes3.mod glubes4.mod glubes5.mod glubes6.mod glures23.mod + * - `7399 `_ + - Feedforward heteroas...with HH dynamics (Lytton 1998) + - `ModelDBRepository/7399 `_ + - `pull/1 `_ + - matrix.mod snsarr.inc vecst.mod + * - `7400 `_ + - Hippocampus temporo-...gram shift model (Lytton 1999) + - `ModelDBRepository/7400 `_ + - `pull/1 `_ + - matrix.mod vecst.mod + * - `8284 `_ + - Febrile seizure-indu...ations to Ih (Chen et al 2001) + - `ModelDBRepository/8284 `_ + - `pull/1 `_ + - hyperde1.mod hyperde2.mod hyperde3.mod hyperso.mod ichan.mod + * - `9889 `_ + - Thalamic quiescence ...e seizures (Lytton et al 1997) + - `ModelDBRepository/9889 `_ + - `pull/1 `_ + - rand.mod + * - `12631 `_ + - Computer model of cl...n thalamic slice (Lytton 1997) + - `ModelDBRepository/12631 `_ + - `pull/2 `_ + - rand.mod + * - `26997 `_ + - Gamma oscillations i... networks (Wang, Buzsaki 1996) + - `ModelDBRepository/26997 `_ + - `pull/1 `_ + - vecst.mod + * - `35358 `_ + - CA3 pyramidal cell: ...ub model (Pinsky, Rinzel 1994) + - `ModelDBRepository/35358 `_ + - `pull/2 `_ + - matrix.mod vecst.mod + * - `37819 `_ + - Thalamocortical augm...response (Bazhenov et al 1998) + - `ModelDBRepository/37819 `_ + - `pull/1 `_ + - matrix.mod pointer.inc ppsav.inc vecst.mod + * - `51781 `_ + - Dentate gyrus networ...model (Santhakumar et al 2005) + - `ModelDBRepository/51781 `_ + - `pull/1 `_ + - hyperde3.mod ichan2.mod + * - `52034 `_ + - Cortical network mod...leptogenesis (Bush et al 1999) + - `ModelDBRepository/52034 `_ + - `pull/1 `_ + - holt_rnd.mod precall.mod snsarr.inc + * - `64229 `_ + - Parallel network sim...h NEURON (Migliore et al 2006) + - `ModelDBRepository/64229 `_ + - `pull/1 `_ + - parbulbNet/cadecay.mod + * - `64296 `_ + - Dynamical model of o...al cell (Rubin, Cleland 2006) + - `ModelDBRepository/64296 `_ + - `pull/1 `_ + - cadecay.mod + * - `87585 `_ + - Sodium channel mutat...eizures + (Barela et al. 2006) + - `ModelDBRepository/87585 `_ + - `pull/1 `_ + - ichanR859C1.mod ichanWT2005.mod + * - `93321 `_ + - Activity dependent c...euron model (Liu et al. 1998) + - `ModelDBRepository/93321 `_ + - `pull/1 `_ + - cadecay.mod + * - `97868 `_ + - NEURON interfaces to...gorithm (Neymotin et al. 2008) + - `ModelDBRepository/97868 `_ + - `pull/2 `_ + - MySQL.mod spud.mod vecst.mod + * - `97874 `_ + - Neural Query System ...NEURON Simulator (Lytton 2006) + - `ModelDBRepository/97874 `_ + - `pull/2 `_ + - NQS/vecst.mod modeldb/vecst.mod + * - `97917 `_ + - Cell splitting in ne...ng scaling (Hines et al. 2008) + - `ModelDBRepository/97917 `_ + - `pull/2 `_ + - nrntraub/mod/rand.mod nrntraub/mod/ri.mod pardentategyrus/hyperde3.mod pardentategyrus/ichan2.mod + * - `105507 `_ + - Tonic-clonic transit...tion (Lytton and Omurtag 2007) + - `ModelDBRepository/105507 `_ + - `pull/2 `_ + - intf\_.mod misc.mod stats.mod vecst.mod + * - `106891 `_ + - JitCon: Just in time... networks (Lytton et al. 2008) + - `ModelDBRepository/106891 `_ + - `pull/3 `_ + - jitcon.mod misc.h misc.mod stats.mod vecst.mod + * - `113732 `_ + - MEG of Somatosensory Neocortex (Jones et al. 2007) + - `ModelDBRepository/113732 `_ + - `pull/1 `_ + - precall.mod presyn.inc + * - `116094 `_ + - Lateral dendrodendit...ctory Bulb (David et al. 2008) + - `ModelDBRepository/116094 `_ + - `pull/1 `_ + - LongDendrite/cadecay.mod ShortDendrite/cadecay.mod + * - `116830 `_ + - Broadening of activi...tructures (Lytton et al. 2008) + - `ModelDBRepository/116830 `_ + - `pull/1 `_ + - intf.mod misc.mod stats.mod vecst.mod + * - `116838 `_ + - The virtual slice setup (Lytton et al. 2008) + - `ModelDBRepository/116838 `_ + - `pull/1 `_ + - intf\_.mod misc.h misc.mod stats.mod vecst.mod + * - `116862 `_ + - Thalamic interneuron...rtment model (Zhu et al. 1999) + - `ModelDBRepository/116862 `_ + - `pull/1 `_ + - clampex.mod misc.h vecst.mod + * - `123815 `_ + - Encoding and retriev...rcuit (Cutsuridis et al. 2009) + - `ModelDBRepository/123815 `_ + - `pull/1 `_ + - burststim2.mod ichan2.mod regn_stim.mod + * - `136095 `_ + - Synaptic information...columns (Neymotin et al. 2010) + - `ModelDBRepository/136095 `_ + - `pull/1 `_ + - clampex.mod field.mod infot.mod intf\_.mod intfsw.mod misc.h misc.mod netrand.inc pregencv.mod stats.mod updown.mod vecst.mod + * - `136310 `_ + - Modeling local field...otentials (Bedard et al. 2004) + - `ModelDBRepository/136310 `_ + - `pull/1 `_ + - ImpedanceFM.mod + * - `137845 `_ + - Spike exchange metho...rcomputer (Hines et al., 2011) + - `ModelDBRepository/137845 `_ + - `pull/1 `_ + - invlfire.mod + * - `138379 `_ + - Emergence of physiol...lations (Neymotin et al. 2011) + - `ModelDBRepository/138379 `_ + - `pull/1 `_ + - intf6\_.mod misc.h misc.mod stats.mod vecst.mod + * - `139421 `_ + - Ketamine disrupts th...pocampus (Neymotin et al 2011) + - `ModelDBRepository/139421 `_ + - `pull/1 `_ + - misc.h misc.mod stats.mod vecst.mod wrap.mod + * - `140881 `_ + - Computational Surgery (Lytton et al. 2011) + - `ModelDBRepository/140881 `_ + - `pull/1 `_ + - intf6\_.mod misc.h misc.mod stats.mod vecst.mod + * - `141505 `_ + - Prosthetic electrost...ortical simulation (Kerr 2012) + - `ModelDBRepository/141505 `_ + - `pull/1 `_ + - infot.mod intf6\_.mod intfsw.mod misc.h misc.mod staley.mod stats.mod vecst.mod + * - `144538 `_ + - Reinforcement learni...ement (Chadderdon et al. 2012) + - `ModelDBRepository/144538 `_ + - `pull/1 `_ + - infot.mod intf6\_.mod intfsw.mod misc.h misc.mod stats.mod updown.mod vecst.mod + * - `144549 `_ + - Hopfield and Brody m...d, Brody 2000) (NEURON+python) + - `ModelDBRepository/144549 `_ + - `pull/1 `_ + - misc.h misc.mod stats.mod vecst.mod + * - `144586 `_ + - Boolean network-base...sis network (Mai and Liu 2009) + - `ModelDBRepository/144586 `_ + - `pull/1 `_ + - bnet.mod misc.h misc.mod stats.mod vecst.mod + * - `146949 `_ + - Motor cortex microci...pping (Chadderdon et al. 2014) + - `ModelDBRepository/146949 `_ + - `pull/1 `_ + - infot.mod intf6.mod intfsw.mod matrix.mod misc.h misc.mod staley.mod stats.mod vecst.mod + * - `149000 `_ + - Using Strahler`s ana...c models (Marasco et al, 2013) + - `ModelDBRepository/149000 `_ + - `pull/1 `_ + - pj.mod + * - `149739 `_ + - A two-layer biophysi...dulation (Li and Cleland 2013) + - `ModelDBRepository/149739 `_ + - `pull/1 `_ + - cadecay.mod cadecay2.mod + * - `150240 `_ + - A Model Circuit of T...vergence (Behuret et al. 2013) + - `ModelDBRepository/150240 `_ + - `pull/1 `_ + - RandomGenerator.mod + * - `150245 `_ + - Sensorimotor cortex ...eaching (Neymotin et al. 2013) + - `ModelDBRepository/150245 `_ + - `pull/1 `_ + - infot.mod intf6\_.mod misc.h misc.mod stats.mod vecst.mod + * - `150551 `_ + - Calcium waves and mG...rons (Ashhad & Narayanan 2013) + - `ModelDBRepository/150551 `_ + - `pull/1 `_ + - Calamp.mod + * - `150556 `_ + - Single compartment D...MPA (Biddell and Johnson 2013) + - `ModelDBRepository/150556 `_ + - `pull/1 `_ + - KBNetStim.mod + * - `150691 `_ + - Model of arrhythmias...twork (Casaleggio et al. 2014) + - `ModelDBRepository/150691 `_ + - `pull/1 `_ + - Readme halfgapm1.mod halfgapspk.mod + * - `151126 `_ + - Effects of increasin... network (Bianchi et al. 2014) + - `ModelDBRepository/151126 `_ + - `pull/1 `_ + - burststim2.mod ichan2.mod regn_stim.mod + * - `151282 `_ + - Ih tunes oscillation...3 model (Neymotin et al. 2013) + - `ModelDBRepository/151282 `_ + - `pull/1 `_ + - misc.h misc.mod stats.mod vecst.mod + * - `153280 `_ + - Parvalbumin-positive...amidal cells (Lee et al. 2014) + - `ModelDBRepository/153280 `_ + - `pull/1 `_ + - ch_Kdrfast.mod mynetstim.mod repeatconn.mod + * - `154732 `_ + - Spine head calcium i...ell model (Graham et al. 2014) + - `ModelDBRepository/154732 `_ + - `pull/1 `_ + - burststim2.mod + * - `155568 `_ + - Dentate gyrus network model (Tejada et al 2014) + - `ModelDBRepository/155568 `_ + - `pull/1 `_ + - hyperde3.mod ichan2.mod + * - `155601 `_ + - Basket cell extrasyn...tions (Proddutur et al., 2013) + - `ModelDBRepository/155601 `_ + - `pull/1 `_ + - hyperde3.mod ichan2.mod + * - `155602 `_ + - Status epilepticus a...c inhibition (Yu J et al 2013) + - `ModelDBRepository/155602 `_ + - `pull/1 `_ + - hyperde3.mod ichan2.mod + * - `156780 `_ + - Microcircuits of L5 ...midal cells (Hay & Segev 2015) + - `ModelDBRepository/156780 `_ + - `pull/1 `_ + - ProbAMPANMDA2.mod ProbUDFsyn2.mod + * - `157157 `_ + - CA1 pyramidal neuron...cles (Saudargiene et al. 2015) + - `ModelDBRepository/157157 `_ + - `pull/1 `_ + - burststim2.mod regn_stim.mod + * - `168874 `_ + - Neuronal dendrite ca...e model (Neymotin et al, 2015) + - `ModelDBRepository/168874 `_ + - `pull/4 `_ + - misc.h misc.mod stats.mod vecst.mod + * - `181967 `_ + - Long time windows fr...op (Cutsuridis & Poirazi 2015) + - `ModelDBRepository/181967 `_ + - `pull/1 `_ + - burststim.mod hyperde3.mod ichan2.mod regn_stim.mod + * - `182129 `_ + - Computational modeli...signaling (Lupascu et al 2020) + - `ModelDBRepository/182129 `_ + - `pull/1 `_ + - ProbGABAAB_EMS_GEPH_g.mod + * - `183300 `_ + - Mitral cell activity...ory bulb NN (Short et al 2016) + - `ModelDBRepository/183300 `_ + - `pull/1 `_ + - cadecay.mod cadecay2.mod thetastim.mod vecstim.mod + * - `185355 `_ + - Dentate gyrus networ...g in epilepsy (Yim et al 2015) + - `ModelDBRepository/185355 `_ + - `pull/2 `_ + - HCN.mod ichan2.mod netstim125.mod netstimbox.mod + * - `185858 `_ + - Ca+/HCN channel-depe...eocortex (Neymotin et al 2016) + - `ModelDBRepository/185858 `_ + - `pull/1 `_ + - misc.h misc.mod vecst.mod + * - `186768 `_ + - CA3 Network Model of...Activity (Sanjay et. al, 2015) + - `ModelDBRepository/186768 `_ + - `pull/1 `_ + - misc.h misc.mod stats.mod vecst.mod wrap.mod + * - `187604 `_ + - Hippocampal CA1 NN w...ork clamp (Bezaire et al 2016) + - `ModelDBRepository/187604 `_ + - `pull/2 `_ + - fastconn.mod mynetstim.mod repeatconn.mod sgate.mod + * - `189154 `_ + - Multitarget pharmaco...ia in M1 (Neymotin et al 2016) + - `ModelDBRepository/189154 `_ + - `pull/1 `_ + - misc.h misc.mod stats.mod vecst.mod + * - `194897 `_ + - Motor system model w...l arm (Dura-Bernal et al 2017) + - `ModelDBRepository/194897 `_ + - `pull/2 `_ + - izhi2007.mod nsloc.mod vecevent.mod + * - `195615 `_ + - Computer models of c...ynamics (Neymotin et al. 2017) + - `ModelDBRepository/195615 `_ + - `pull/1 `_ + - misc.h misc.mod vecst.mod + * - `223031 `_ + - Interneuron Specific...l (Guet-McCreight et al, 2016) + - `ModelDBRepository/223031 `_ + - `pull/1 `_ + - S1/ingauss.mod S2/ingauss.mod SD/ingauss.mod SDprox1/ingauss.mod SDprox2/ingauss.mod + * - `225080 `_ + - CA1 pyr cell: Inhibi...ssion (Grienberger et al 2017) + - `ModelDBRepository/225080 `_ + - `pull/1 `_ + - pr.mod vecevent.mod + * - `231427 `_ + - Shaping NMDA spikes ...on on L5PC (Doron et al. 2017) + - `ModelDBRepository/231427 `_ + - `pull/2 `_ + - ProbAMPA.mod ProbUDFsyn2_lark.mod + * - `232097 `_ + - 2D model of olfactor...llations (Li and Cleland 2017) + - `ModelDBRepository/232097 `_ + - `pull/1 `_ + - cadecay.mod cadecay2.mod + * - `239177 `_ + - Phase response theor...(Tikidji-Hamburyan et al 2019) + - `ModelDBRepository/239177 `_ + - `pull/1 `_ + - PIR-Inetwork/innp.mod PIR-Inetwork/vecevent.mod + * - `241165 `_ + - Biophysically realis...imulation (Aberra et al. 2018) + - `ModelDBRepository/241165 `_ + - `pull/1 `_ + - mechanisms/ProbAMPANMDA_EMS.mod mechanisms/ProbGABAAB_EMS.mod + * - `241240 `_ + - Role of afferent-hai...regularity (Holmes et al 2017) + - `ModelDBRepository/241240 `_ + - `pull/1 `_ + - afhcsyn_i0.mod hc1.mod random.mod ribbon1.mod + * - `244262 `_ + - Deconstruction of co...ic DBS (Kumaravelu et al 2018) + - `ModelDBRepository/244262 `_ + - `pull/1 `_ + - rand.mod ri.mod + * - `244848 `_ + - Active dendrites sha...urons (Basak & Narayanan 2018) + - `ModelDBRepository/244848 `_ + - `pull/2 `_ + - apamp.mod + * - `247968 `_ + - Gamma genesis in the...ral amygdala (Feng et al 2019) + - `ModelDBRepository/247968 `_ + - `pull/1 `_ + - Gfluct_new_exc.mod Gfluct_new_inh.mod vecevent.mod + * - `249463 `_ + - Layer V pyramidal ce...cs (Mäki-Marttunen et al 2019) + - `ModelDBRepository/249463 `_ + - `pull/1 `_ + - almog/ProbAMPANMDA2.mod almog/ProbUDFsyn2.mod hay/ProbAMPANMDA2.mod hay/ProbUDFsyn2.mod + * - `256388 `_ + - The APP in C-termina...n firing (Pousinha et al 2019) + - `ModelDBRepository/256388 `_ + - `pull/1 `_ + - burststim2.mod ichan2.mod regn_stim.mod + * - `259366 `_ + - Cycle skipping in IN...dji-Hamburyan & Canavier 2020) + - `ModelDBRepository/259366 `_ + - `pull/1 `_ + - innp.mod .. Does this need some more qualification? Are there non-VERBATIM diff --git a/docs/index.rst b/docs/index.rst index f56c3fdcdd..da56b07a7a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -145,7 +145,6 @@ Installation .. raw:: html - | +.. admonition:: About NEURON >= 9.0 + :class: tip + + If you are experiencing compilation errors while using `nrnivmodl` with NEURON >=9.0, + but not with previous 8.x releases, please see :ref:`porting-mechanisms-to-cpp`. + We have provide comprehensive instructions for adapting legacy MOD files that include `VERBATIM` blocks, + or you might find already updated MOD files in the ModelDB GitHub repositories. See also the NEURON documentation `index `_ and the `NEURON forum `_. diff --git a/docs/rst_substitutions.txt b/docs/rst_substitutions.txt index 3ccdc57f3d..4470b28a44 100644 --- a/docs/rst_substitutions.txt +++ b/docs/rst_substitutions.txt @@ -1,2 +1,2 @@ -.. |neuron_with_cpp_mechanisms| replace:: NEURON 9.0[.dev] -.. |neuron_with_soa_data| replace:: NEURON 9.0[.dev] \ No newline at end of file +.. |neuron_with_cpp_mechanisms| replace:: NEURON >= 9.0 +.. |neuron_with_soa_data| replace:: NEURON >= 9.0 \ No newline at end of file From 682a2370de83cf627a1bd6d2494cda7550dd1708 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Thu, 3 Oct 2024 17:15:16 +0200 Subject: [PATCH 45/68] Remove unused int_asbuffer (#3112) It was removed more than 4 years ago from numpy. It was also not doing anything. --- share/lib/python/neuron/nonvint_block_supervisor.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/share/lib/python/neuron/nonvint_block_supervisor.py b/share/lib/python/neuron/nonvint_block_supervisor.py index 48d84bc565..34ee2470f0 100644 --- a/share/lib/python/neuron/nonvint_block_supervisor.py +++ b/share/lib/python/neuron/nonvint_block_supervisor.py @@ -1,15 +1,10 @@ -import sys import ctypes -import neuron +import traceback import numpy +import neuron from neuron import h -import traceback # reducing the indirection improves performance -try: - _numpy_core_multiarray_int_asbuffer = numpy.core.multiarray.int_asbuffer -except: - pass _ctypes_addressof = ctypes.addressof _numpy_array = numpy.array _numpy_frombuffer = numpy.frombuffer From 2c5594a0cacf4dfa9f010ae3dd903c56e8247eb3 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Thu, 3 Oct 2024 17:22:03 +0200 Subject: [PATCH 46/68] Remove mention of `CORENRN_ENABLE_NMODL` option (#3113) It was removed in #2247 --- cmake/NeuronTestHelper.cmake | 1 - docs/cmake_doc/options.rst | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cmake/NeuronTestHelper.cmake b/cmake/NeuronTestHelper.cmake index 405a5d7736..2e6a208b6a 100644 --- a/cmake/NeuronTestHelper.cmake +++ b/cmake/NeuronTestHelper.cmake @@ -282,7 +282,6 @@ function(nrn_add_test) set(feature_mod_compatibility_enabled OFF) endif() set(feature_gpu_enabled ${CORENRN_ENABLE_GPU}) - set(feature_nmodl_enabled ${CORENRN_ENABLE_NMODL}) # Check REQUIRES set(requires_coreneuron OFF) foreach(required_feature ${NRN_ADD_TEST_REQUIRES}) diff --git a/docs/cmake_doc/options.rst b/docs/cmake_doc/options.rst index 7a1ef1e449..087b477ab1 100644 --- a/docs/cmake_doc/options.rst +++ b/docs/cmake_doc/options.rst @@ -396,8 +396,8 @@ Other CoreNEURON options: ------------------------- There are 20 or so cmake arguments specific to a CoreNEURON build that are listed in https://github.com/neuronsimulator/nrn/blob/master/src/coreneuron/CMakeLists.txt. - The ones of particular interest that can be used on the NEURON - CMake configure line are `CORENRN_ENABLE_NMODL` and `CORENRN_ENABLE_GPU`. + The one of particular interest that can be used on the NEURON + CMake configure line is `CORENRN_ENABLE_GPU`. NMODL options ============= From 6ae8035ea01820b7612f49fdc78c7bbcfff26009 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 3 Oct 2024 17:36:45 +0200 Subject: [PATCH 47/68] nanobind: use gil_scoped_acquire (#3099) --- src/nrnpython/nrnpy_hoc.cpp | 4 ++-- src/nrnpython/nrnpy_p2h.cpp | 24 ++++++++++++------------ src/nrnpython/nrnpy_utils.h | 16 ---------------- src/nrnpython/nrnpython.cpp | 9 ++++++--- 4 files changed, 20 insertions(+), 33 deletions(-) diff --git a/src/nrnpython/nrnpy_hoc.cpp b/src/nrnpython/nrnpy_hoc.cpp index b6eb51a9b9..311139567c 100644 --- a/src/nrnpython/nrnpy_hoc.cpp +++ b/src/nrnpython/nrnpy_hoc.cpp @@ -2903,7 +2903,7 @@ static Object* rvp_rxd_to_callable_(Object* obj) { extern "C" NRN_EXPORT PyObject* get_plotshape_data(PyObject* sp) { - PyLockGIL lock; + nanobind::gil_scoped_acquire lock{}; PyHocObject* pho = (PyHocObject*) sp; ShapePlotInterface* spi; if (!is_obj_type(pho->ho_, "PlotShape")) { @@ -3404,7 +3404,7 @@ extern "C" NRN_EXPORT PyObject* nrnpy_hoc() { nrnpy_nrncore_enable_value_p_ = nrncore_enable_value; nrnpy_nrncore_file_mode_value_p_ = nrncore_file_mode_value; nrnpy_rvp_rxd_to_callable = rvp_rxd_to_callable_; - PyLockGIL lock; + nanobind::gil_scoped_acquire lock{}; char endian_character = 0; diff --git a/src/nrnpython/nrnpy_p2h.cpp b/src/nrnpython/nrnpy_p2h.cpp index 07ac58daba..f84cb29bcf 100644 --- a/src/nrnpython/nrnpy_p2h.cpp +++ b/src/nrnpython/nrnpy_p2h.cpp @@ -23,7 +23,7 @@ static PyObject* main_namespace; struct Py2Nrn final { ~Py2Nrn() { - PyLockGIL lock{}; + nanobind::gil_scoped_acquire lock{}; Py_XDECREF(po_); } int type_{}; // 0 toplevel @@ -43,7 +43,7 @@ Member_func p_members[] = {{nullptr, nullptr}}; static void call_python_with_section(Object* pyact, Section* sec) { PyObject* po = ((Py2Nrn*) pyact->u.this_pointer)->po_; PyObject* r; - PyLockGIL lock; + nanobind::gil_scoped_acquire lock{}; PyObject* args = PyTuple_Pack(1, (PyObject*) newpysechelp(sec)); r = nrnpy_pyCallObject(po, args); @@ -156,7 +156,7 @@ static void py2n_component(Object* ob, Symbol* sym, int nindex, int isfunc) { Py2Nrn* pn = (Py2Nrn*) ob->u.this_pointer; PyObject* head = pn->po_; PyObject* tail; - PyLockGIL lock; + nanobind::gil_scoped_acquire lock{}; if (pn->type_ == 0) { // top level if (!main_module) { main_module = PyImport_AddModule("__main__"); @@ -362,7 +362,7 @@ static PyObject* hoccommand_exec_help(Object* ho) { } static double praxis_efun(Object* ho, Object* v) { - PyLockGIL lock; + nanobind::gil_scoped_acquire lock{}; PyObject* pc = nrnpy_ho2po(ho); PyObject* pv = nrnpy_ho2po(v); @@ -391,7 +391,7 @@ static double praxis_efun(Object* ho, Object* v) { } static int hoccommand_exec(Object* ho) { - PyLockGIL lock; + nanobind::gil_scoped_acquire lock{}; PyObject* r = hoccommand_exec_help(ho); if (r == NULL) { @@ -411,7 +411,7 @@ static int hoccommand_exec(Object* ho) { } static int hoccommand_exec_strret(Object* ho, char* buf, int size) { - PyLockGIL lock; + nanobind::gil_scoped_acquire lock{}; PyObject* r = hoccommand_exec_help(ho); if (r) { @@ -438,7 +438,7 @@ static int hoccommand_exec_strret(Object* ho, char* buf, int size) { static void grphcmdtool(Object* ho, int type, double x, double y, int key) { PyObject* po = ((Py2Nrn*) ho->u.this_pointer)->po_; PyObject* r; - PyLockGIL lock; + nanobind::gil_scoped_acquire lock{}; PyObject* args = PyTuple_Pack( 4, PyInt_FromLong(type), PyFloat_FromDouble(x), PyFloat_FromDouble(y), PyInt_FromLong(key)); @@ -460,7 +460,7 @@ static void grphcmdtool(Object* ho, int type, double x, double y, int key) { static Object* callable_with_args(Object* ho, int narg) { PyObject* po = ((Py2Nrn*) ho->u.this_pointer)->po_; - PyLockGIL lock; + nanobind::gil_scoped_acquire lock{}; PyObject* args = PyTuple_New((Py_ssize_t) narg); if (args == NULL) { @@ -493,7 +493,7 @@ static Object* callable_with_args(Object* ho, int narg) { static double func_call(Object* ho, int narg, int* err) { PyObject* po = ((Py2Nrn*) ho->u.this_pointer)->po_; PyObject* r; - PyLockGIL lock; + nanobind::gil_scoped_acquire lock{}; PyObject* args = PyTuple_New((Py_ssize_t) narg); if (args == NULL) { @@ -549,7 +549,7 @@ static double func_call(Object* ho, int narg, int* err) { static double guigetval(Object* ho) { PyObject* po = ((Py2Nrn*) ho->u.this_pointer)->po_; - PyLockGIL lock; + nanobind::gil_scoped_acquire lock{}; PyObject* r = NULL; PyObject* p = PyTuple_GetItem(po, 0); if (PySequence_Check(p) || PyMapping_Check(p)) { @@ -565,7 +565,7 @@ static double guigetval(Object* ho) { static void guisetval(Object* ho, double x) { PyObject* po = ((Py2Nrn*) ho->u.this_pointer)->po_; - PyLockGIL lock; + nanobind::gil_scoped_acquire lock{}; PyObject* pn = PyFloat_FromDouble(x); PyObject* p = PyTuple_GetItem(po, 0); if (PySequence_Check(p) || PyMapping_Check(p)) { @@ -578,7 +578,7 @@ static void guisetval(Object* ho, double x) { static int guigetstr(Object* ho, char** cpp) { PyObject* po = ((Py2Nrn*) ho->u.this_pointer)->po_; - PyLockGIL lock; + nanobind::gil_scoped_acquire lock{}; PyObject* r = PyObject_GetAttr(PyTuple_GetItem(po, 0), PyTuple_GetItem(po, 1)); PyObject* pn = PyObject_Str(r); diff --git a/src/nrnpython/nrnpy_utils.h b/src/nrnpython/nrnpy_utils.h index 5decb2f31b..e6e3264bf5 100644 --- a/src/nrnpython/nrnpy_utils.h +++ b/src/nrnpython/nrnpy_utils.h @@ -160,22 +160,6 @@ class PyErr2NRNString { char* str_; }; - -struct PyLockGIL { - PyLockGIL() - : state_{PyGILState_Ensure()} {} - PyLockGIL(PyLockGIL&&) = delete; - PyLockGIL(PyLockGIL const&) = delete; - PyLockGIL& operator=(PyLockGIL&&) = delete; - PyLockGIL& operator=(PyLockGIL const&) = delete; - ~PyLockGIL() { - PyGILState_Release(state_); - } - - private: - PyGILState_STATE state_; -}; - extern void nrnpy_sec_referr(); #define CHECK_SEC_INVALID(sec) \ { \ diff --git a/src/nrnpython/nrnpython.cpp b/src/nrnpython/nrnpython.cpp index 41fb8c4c30..0a39a4eb46 100644 --- a/src/nrnpython/nrnpython.cpp +++ b/src/nrnpython/nrnpython.cpp @@ -17,6 +17,9 @@ #include #include #include + +#include + extern HocStr* hoc_cbufstr; extern int nrnpy_nositeflag; extern std::string nrnpy_pyexe; @@ -79,7 +82,7 @@ PyObject* basic_sys_path{}; * @param new_first Path to decode and prepend to sys.path. */ void reset_sys_path(std::string_view new_first) { - PyLockGIL _{}; + nanobind::gil_scoped_acquire _{}; auto* const path = PySys_GetObject("path"); nrn_assert(path); // Clear sys.path @@ -261,7 +264,7 @@ static int nrnpython_start(int b) { check("Could not initialise Python", Py_InitializeFromConfig(config)); // Manipulate sys.path, starting from the default values { - PyLockGIL _{}; + nanobind::gil_scoped_acquire _{}; auto* const sys_path = PySys_GetObject("path"); if (!sys_path) { throw std::runtime_error("Could not get sys.path from C++"); @@ -376,7 +379,7 @@ static void nrnpython_real() { #if USE_PYTHON HocTopContextSet { - PyLockGIL lock; + nanobind::gil_scoped_acquire lock{}; retval = (PyRun_SimpleString(hoc_gargstr(1)) == 0); } HocContextRestore From 0a545a3f7f59f317bca18f29a07217a1faee2d45 Mon Sep 17 00:00:00 2001 From: JCGoran Date: Thu, 3 Oct 2024 17:41:39 +0200 Subject: [PATCH 48/68] Fix `PytestReturnNotNoneWarning` (#3114) --- test/coreneuron/test_netmove.py | 10 +++++++--- test/coreneuron/test_spikes.py | 12 ++++++++---- test/gjtests/test_natrans.py | 10 +++++++--- test/pytest_coreneuron/test_nlayer.py | 10 +++++++--- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/test/coreneuron/test_netmove.py b/test/coreneuron/test_netmove.py index 5cbe1858e9..817d2c69ca 100644 --- a/test/coreneuron/test_netmove.py +++ b/test/coreneuron/test_netmove.py @@ -46,7 +46,7 @@ def result(self): return (self.syn.n_netsend, self.syn.n_netmove, self.msgvec.c()) -def test_netmove(): +def _test_netmove(): from neuron import coreneuron coreneuron.enable = False @@ -111,10 +111,10 @@ def runassert(mode): return stdlist -if __name__ == "__main__": +def test_netmove(): from neuron import gui - stdlist = test_netmove() + stdlist = _test_netmove() g = h.Graph() print("n_netsend n_netmove") for result in stdlist: @@ -122,3 +122,7 @@ def runassert(mode): result[2].line(g) g.exec_menu("View = plot") h.quit() + + +if __name__ == "__main__": + test_netmove() diff --git a/test/coreneuron/test_spikes.py b/test/coreneuron/test_spikes.py index cecb8a3d0e..883609c16b 100644 --- a/test/coreneuron/test_spikes.py +++ b/test/coreneuron/test_spikes.py @@ -28,7 +28,7 @@ from neuron import h, gui -def test_spikes( +def _test_spikes( use_mpi4py=mpi4py_option, use_nrnmpi_init=nrnmpi_init_option, file_mode=file_mode_option, @@ -132,9 +132,13 @@ def run(mode): return h -if __name__ == "__main__": - h = test_spikes() +def test_spikes(): + result = _test_spikes() if mpi4py_option or nrnmpi_init_option: pc = h.ParallelContext() pc.barrier() - h.quit() + result.quit() + + +if __name__ == "__main__": + test_spikes() diff --git a/test/gjtests/test_natrans.py b/test/gjtests/test_natrans.py index 53077d1cd5..c01acf7530 100644 --- a/test/gjtests/test_natrans.py +++ b/test/gjtests/test_natrans.py @@ -36,7 +36,7 @@ ) -def test_natrans(): +def _test_natrans(): gids = [gid for gid in range(rank, ncell, nhost)] cells = [] for gid in range(rank, ncell, nhost): @@ -115,7 +115,11 @@ def run(): return cells, gids, sgids, targets -if __name__ == "__main__": - model = test_natrans() +def test_natrans(): + model = _test_natrans() pc.barrier() h.quit() + + +if __name__ == "__main__": + test_natrans() diff --git a/test/pytest_coreneuron/test_nlayer.py b/test/pytest_coreneuron/test_nlayer.py index 5a7670da58..5defbf4d68 100644 --- a/test/pytest_coreneuron/test_nlayer.py +++ b/test/pytest_coreneuron/test_nlayer.py @@ -36,7 +36,7 @@ def run(self): return res -def test_nlayer(): +def _test_nlayer(): res = [] for nlayer in [1, 2, 3]: h.nlayer_extracellular(nlayer) @@ -52,10 +52,14 @@ def test_nlayer(): return res -if __name__ == "__main__": - res = test_nlayer() +def test_nlayer(): + res = _test_nlayer() for i in range(len(res[0][0])): for j in range(2): for k in range(3): print("%g" % res[k][j].x[i], end=" ") print() + + +if __name__ == "__main__": + test_nlayer() From 51bb95d227680c74730fbb81a5316ad38fa226eb Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 3 Oct 2024 19:51:54 +0200 Subject: [PATCH 49/68] Move nmodl directory to nocmodl (#3110) --- cmake/NeuronFileLists.cmake | 10 ++--- src/{nmodl => nocmodl}/consist.cpp | 0 src/{nmodl => nocmodl}/deriv.cpp | 0 src/{nmodl => nocmodl}/difeqdef.h | 0 src/{nmodl => nocmodl}/diffeq.ypp | 0 src/{nmodl => nocmodl}/discrete.cpp | 0 src/{nmodl => nocmodl}/extdef.h | 0 src/{nmodl => nocmodl}/extdef2.h | 0 src/{nmodl => nocmodl}/extdef5.h | 0 src/{nmodl => nocmodl}/init.cpp | 0 src/{nmodl => nocmodl}/io.cpp | 0 src/{nmodl => nocmodl}/kinetic.cpp | 0 src/{nmodl => nocmodl}/lex.lpp | 0 src/{nmodl => nocmodl}/list.cpp | 0 src/{nmodl => nocmodl}/modl.cpp | 0 src/{nmodl => nocmodl}/modl.h | 0 src/{nmodl => nocmodl}/netrec_discon.cpp | 0 src/{nmodl => nocmodl}/nmodlfunc.h | 0 src/{nmodl => nocmodl}/noccout.cpp | 0 src/{nmodl => nocmodl}/nocpout.cpp | 0 src/{nmodl => nocmodl}/parsact.cpp | 0 src/{nmodl => nocmodl}/parse1.ypp | 0 src/{nmodl => nocmodl}/simultan.cpp | 0 src/{nmodl => nocmodl}/solve.cpp | 0 src/{nmodl => nocmodl}/symbol.cpp | 0 src/{nmodl => nocmodl}/symbol.h | 0 src/{nmodl => nocmodl}/version.cpp | 0 src/nrniv/CMakeLists.txt | 52 ++++++++++++------------ 28 files changed, 32 insertions(+), 30 deletions(-) rename src/{nmodl => nocmodl}/consist.cpp (100%) rename src/{nmodl => nocmodl}/deriv.cpp (100%) rename src/{nmodl => nocmodl}/difeqdef.h (100%) rename src/{nmodl => nocmodl}/diffeq.ypp (100%) rename src/{nmodl => nocmodl}/discrete.cpp (100%) rename src/{nmodl => nocmodl}/extdef.h (100%) rename src/{nmodl => nocmodl}/extdef2.h (100%) rename src/{nmodl => nocmodl}/extdef5.h (100%) rename src/{nmodl => nocmodl}/init.cpp (100%) rename src/{nmodl => nocmodl}/io.cpp (100%) rename src/{nmodl => nocmodl}/kinetic.cpp (100%) rename src/{nmodl => nocmodl}/lex.lpp (100%) rename src/{nmodl => nocmodl}/list.cpp (100%) rename src/{nmodl => nocmodl}/modl.cpp (100%) rename src/{nmodl => nocmodl}/modl.h (100%) rename src/{nmodl => nocmodl}/netrec_discon.cpp (100%) rename src/{nmodl => nocmodl}/nmodlfunc.h (100%) rename src/{nmodl => nocmodl}/noccout.cpp (100%) rename src/{nmodl => nocmodl}/nocpout.cpp (100%) rename src/{nmodl => nocmodl}/parsact.cpp (100%) rename src/{nmodl => nocmodl}/parse1.ypp (100%) rename src/{nmodl => nocmodl}/simultan.cpp (100%) rename src/{nmodl => nocmodl}/solve.cpp (100%) rename src/{nmodl => nocmodl}/symbol.cpp (100%) rename src/{nmodl => nocmodl}/symbol.h (100%) rename src/{nmodl => nocmodl}/version.cpp (100%) diff --git a/cmake/NeuronFileLists.cmake b/cmake/NeuronFileLists.cmake index ca4fbcdbfa..d8b03dae3a 100644 --- a/cmake/NeuronFileLists.cmake +++ b/cmake/NeuronFileLists.cmake @@ -385,7 +385,7 @@ set(MODLUNIT_FILES_LIST units1.cpp version.cpp) -set(NMODL_FILES_LIST +set(NOCMODL_FILES_LIST consist.cpp deriv.cpp discrete.cpp @@ -430,7 +430,7 @@ set(NRN_NODEORDEROPTIM_SRC_DIR ${PROJECT_SOURCE_DIR}/src/coreneuron/permute) set(NRN_NRNCVODE_SRC_DIR ${PROJECT_SOURCE_DIR}/src/nrncvode) set(NRN_NRNIV_SRC_DIR ${PROJECT_SOURCE_DIR}/src/nrniv) set(NRN_MODLUNIT_SRC_DIR ${PROJECT_SOURCE_DIR}/src/modlunit) -set(NRN_NMODL_SRC_DIR ${PROJECT_SOURCE_DIR}/src/nmodl) +set(NRN_NOCMODL_SRC_DIR ${PROJECT_SOURCE_DIR}/src/nocmodl) set(NRN_IVOS_SRC_DIR ${PROJECT_SOURCE_DIR}/src/ivos) set(NRN_MUSIC_SRC_DIR ${PROJECT_SOURCE_DIR}/src/neuronmusic) set(NRN_PARALLEL_SRC_DIR ${PROJECT_SOURCE_DIR}/src/parallel) @@ -462,13 +462,13 @@ nrn_create_file_list(NRN_MODFILE_BASE_NAMES src/nrnoc ${MODFILE_BASE_NAMES}) nrn_create_file_list(NRN_BIN_SRC_FILES ${PROJECT_SOURCE_DIR}/src/ivoc/ nrnmain.cpp) nrn_create_file_list(NRN_BIN_SRC_FILES ${PROJECT_SOURCE_DIR}/src/oc/ ockludge.cpp modlreg.cpp) nrn_create_file_list(NRN_MODLUNIT_SRC_FILES ${NRN_MODLUNIT_SRC_DIR} ${MODLUNIT_FILES_LIST}) -nrn_create_file_list(NRN_NMODL_SRC_FILES ${NRN_NMODL_SRC_DIR} ${NMODL_FILES_LIST}) +nrn_create_file_list(NRN_NOCMODL_SRC_FILES ${NRN_NOCMODL_SRC_DIR} ${NOCMODL_FILES_LIST}) nrn_create_file_list(NRNMPI_DYNAMIC_INCLUDE_FILE ${PROJECT_SOURCE_DIR}/src/nrnmpi ${MPI_DYNAMIC_INCLUDE}) nrn_create_file_list(NRN_IVOS_SRC_FILES ${NRN_IVOS_SRC_DIR} ${IVOS_FILES_LIST}) nrn_create_file_list(NRN_MUSIC_SRC_FILES ${NRN_MUSIC_SRC_DIR} ${NRN_MUSIC_FILES_LIST}) list(APPEND NRN_OC_SRC_FILES ${PROJECT_BINARY_DIR}/src/oc/hocusr.h) -list(APPEND NRN_NMODL_SRC_FILES ${NRN_MODLUNIT_SRC_DIR}/units.cpp) +list(APPEND NRN_NOCMODL_SRC_FILES ${NRN_MODLUNIT_SRC_DIR}/units.cpp) # ============================================================================= # Create mswin install lists needed for setup_exe target @@ -480,7 +480,7 @@ if(MINGW) list(APPEND MSWIN_FILES ${MSWIN_SRC_DIR}/notes.txt) list(APPEND NRN_MODLUNIT_SRC_FILES ${PROJECT_SOURCE_DIR}/src/mswin/extra/d2upath.cpp) - list(APPEND NRN_NMODL_SRC_FILES ${PROJECT_SOURCE_DIR}/src/mswin/extra/d2upath.cpp) + list(APPEND NRN_NOCMODL_SRC_FILES ${PROJECT_SOURCE_DIR}/src/mswin/extra/d2upath.cpp) list(APPEND NRN_OC_SRC_FILES ${PROJECT_SOURCE_DIR}/src/mswin/extra/d2upath.cpp) nrn_create_file_list(MSWIN_BIN_FILES ${MSWIN_SRC_DIR} nrniv.ico nrniv10.ico nmodl2a.ico) diff --git a/src/nmodl/consist.cpp b/src/nocmodl/consist.cpp similarity index 100% rename from src/nmodl/consist.cpp rename to src/nocmodl/consist.cpp diff --git a/src/nmodl/deriv.cpp b/src/nocmodl/deriv.cpp similarity index 100% rename from src/nmodl/deriv.cpp rename to src/nocmodl/deriv.cpp diff --git a/src/nmodl/difeqdef.h b/src/nocmodl/difeqdef.h similarity index 100% rename from src/nmodl/difeqdef.h rename to src/nocmodl/difeqdef.h diff --git a/src/nmodl/diffeq.ypp b/src/nocmodl/diffeq.ypp similarity index 100% rename from src/nmodl/diffeq.ypp rename to src/nocmodl/diffeq.ypp diff --git a/src/nmodl/discrete.cpp b/src/nocmodl/discrete.cpp similarity index 100% rename from src/nmodl/discrete.cpp rename to src/nocmodl/discrete.cpp diff --git a/src/nmodl/extdef.h b/src/nocmodl/extdef.h similarity index 100% rename from src/nmodl/extdef.h rename to src/nocmodl/extdef.h diff --git a/src/nmodl/extdef2.h b/src/nocmodl/extdef2.h similarity index 100% rename from src/nmodl/extdef2.h rename to src/nocmodl/extdef2.h diff --git a/src/nmodl/extdef5.h b/src/nocmodl/extdef5.h similarity index 100% rename from src/nmodl/extdef5.h rename to src/nocmodl/extdef5.h diff --git a/src/nmodl/init.cpp b/src/nocmodl/init.cpp similarity index 100% rename from src/nmodl/init.cpp rename to src/nocmodl/init.cpp diff --git a/src/nmodl/io.cpp b/src/nocmodl/io.cpp similarity index 100% rename from src/nmodl/io.cpp rename to src/nocmodl/io.cpp diff --git a/src/nmodl/kinetic.cpp b/src/nocmodl/kinetic.cpp similarity index 100% rename from src/nmodl/kinetic.cpp rename to src/nocmodl/kinetic.cpp diff --git a/src/nmodl/lex.lpp b/src/nocmodl/lex.lpp similarity index 100% rename from src/nmodl/lex.lpp rename to src/nocmodl/lex.lpp diff --git a/src/nmodl/list.cpp b/src/nocmodl/list.cpp similarity index 100% rename from src/nmodl/list.cpp rename to src/nocmodl/list.cpp diff --git a/src/nmodl/modl.cpp b/src/nocmodl/modl.cpp similarity index 100% rename from src/nmodl/modl.cpp rename to src/nocmodl/modl.cpp diff --git a/src/nmodl/modl.h b/src/nocmodl/modl.h similarity index 100% rename from src/nmodl/modl.h rename to src/nocmodl/modl.h diff --git a/src/nmodl/netrec_discon.cpp b/src/nocmodl/netrec_discon.cpp similarity index 100% rename from src/nmodl/netrec_discon.cpp rename to src/nocmodl/netrec_discon.cpp diff --git a/src/nmodl/nmodlfunc.h b/src/nocmodl/nmodlfunc.h similarity index 100% rename from src/nmodl/nmodlfunc.h rename to src/nocmodl/nmodlfunc.h diff --git a/src/nmodl/noccout.cpp b/src/nocmodl/noccout.cpp similarity index 100% rename from src/nmodl/noccout.cpp rename to src/nocmodl/noccout.cpp diff --git a/src/nmodl/nocpout.cpp b/src/nocmodl/nocpout.cpp similarity index 100% rename from src/nmodl/nocpout.cpp rename to src/nocmodl/nocpout.cpp diff --git a/src/nmodl/parsact.cpp b/src/nocmodl/parsact.cpp similarity index 100% rename from src/nmodl/parsact.cpp rename to src/nocmodl/parsact.cpp diff --git a/src/nmodl/parse1.ypp b/src/nocmodl/parse1.ypp similarity index 100% rename from src/nmodl/parse1.ypp rename to src/nocmodl/parse1.ypp diff --git a/src/nmodl/simultan.cpp b/src/nocmodl/simultan.cpp similarity index 100% rename from src/nmodl/simultan.cpp rename to src/nocmodl/simultan.cpp diff --git a/src/nmodl/solve.cpp b/src/nocmodl/solve.cpp similarity index 100% rename from src/nmodl/solve.cpp rename to src/nocmodl/solve.cpp diff --git a/src/nmodl/symbol.cpp b/src/nocmodl/symbol.cpp similarity index 100% rename from src/nmodl/symbol.cpp rename to src/nocmodl/symbol.cpp diff --git a/src/nmodl/symbol.h b/src/nocmodl/symbol.h similarity index 100% rename from src/nmodl/symbol.h rename to src/nocmodl/symbol.h diff --git a/src/nmodl/version.cpp b/src/nocmodl/version.cpp similarity index 100% rename from src/nmodl/version.cpp rename to src/nocmodl/version.cpp diff --git a/src/nrniv/CMakeLists.txt b/src/nrniv/CMakeLists.txt index 07aa0a7624..f1f5830dde 100644 --- a/src/nrniv/CMakeLists.txt +++ b/src/nrniv/CMakeLists.txt @@ -51,45 +51,47 @@ cpp_cc_configure_sanitizers(TARGET modlunit) # Generated .cpp needs to find source-directory .hpp and vice versa. target_include_directories(modlunit PRIVATE "${NRN_MODLUNIT_SRC_DIR}" "${NRN_MODLUNIT_GEN}") -if(NRN_NMODL_CXX_FLAGS) - target_compile_options(modlunit PRIVATE ${NRN_NMODL_CXX_FLAGS}) +if(NRN_NOCMODL_CXX_FLAGS) + target_compile_options(modlunit PRIVATE ${NRN_NOCMODL_CXX_FLAGS}) endif() # ============================================================================= -# Build nocmodl : source-to-source compiler for NMODL +# Build nocmodl : source-to-source compiler for NOCMODL # ============================================================================= -set(NRN_NMODL_GEN "${CMAKE_CURRENT_BINARY_DIR}/nocmodl_generated") -file(MAKE_DIRECTORY "${NRN_NMODL_GEN}") -file(RELATIVE_PATH NRN_NMODL_GEN_REL "${BISON_FLEX_WORKING_DIR}" "${NRN_NMODL_GEN}") -file(RELATIVE_PATH NRN_NMODL_SRC_REL "${BISON_FLEX_WORKING_DIR}" "${NRN_NMODL_SRC_DIR}") +set(NRN_NOCMODL_GEN "${CMAKE_CURRENT_BINARY_DIR}/nocmodl_generated") +file(MAKE_DIRECTORY "${NRN_NOCMODL_GEN}") +file(RELATIVE_PATH NRN_NOCMODL_GEN_REL "${BISON_FLEX_WORKING_DIR}" "${NRN_NOCMODL_GEN}") +file(RELATIVE_PATH NRN_NOCMODL_SRC_REL "${BISON_FLEX_WORKING_DIR}" "${NRN_NOCMODL_SRC_DIR}") add_custom_command( - OUTPUT "${NRN_NMODL_GEN}/lex.cpp" + OUTPUT "${NRN_NOCMODL_GEN}/lex.cpp" WORKING_DIRECTORY "${BISON_FLEX_WORKING_DIR}" - COMMAND "${FLEX_EXECUTABLE}" ARGS -o "${NRN_NMODL_GEN_REL}/lex.cpp" "${NRN_NMODL_SRC_REL}/lex.lpp" - DEPENDS "${NRN_NMODL_SRC_DIR}/lex.lpp" + COMMAND "${FLEX_EXECUTABLE}" ARGS -o "${NRN_NOCMODL_GEN_REL}/lex.cpp" + "${NRN_NOCMODL_SRC_REL}/lex.lpp" + DEPENDS "${NRN_NOCMODL_SRC_DIR}/lex.lpp" COMMENT "[FLEX][nocmodllexer] Building scanner with flex ${FLEX_VERSION}") add_custom_command( - OUTPUT "${NRN_NMODL_GEN}/parse1.hpp" "${NRN_NMODL_GEN}/parse1.cpp" + OUTPUT "${NRN_NOCMODL_GEN}/parse1.hpp" "${NRN_NOCMODL_GEN}/parse1.cpp" WORKING_DIRECTORY "${BISON_FLEX_WORKING_DIR}" - COMMAND "${BISON_EXECUTABLE}" ARGS "--defines=${NRN_NMODL_GEN_REL}/parse1.hpp" -o - "${NRN_NMODL_GEN_REL}/parse1.cpp" "${NRN_NMODL_SRC_REL}/parse1.ypp" - DEPENDS "${NRN_NMODL_SRC_DIR}/parse1.ypp" + COMMAND "${BISON_EXECUTABLE}" ARGS "--defines=${NRN_NOCMODL_GEN_REL}/parse1.hpp" -o + "${NRN_NOCMODL_GEN_REL}/parse1.cpp" "${NRN_NOCMODL_SRC_REL}/parse1.ypp" + DEPENDS "${NRN_NOCMODL_SRC_DIR}/parse1.ypp" COMMENT "[BISON][nocmodlparser] Building parser with bison ${BISON_VERSION}") add_custom_command( - OUTPUT "${NRN_NMODL_GEN}/diffeq.hpp" "${NRN_NMODL_GEN}/diffeq.cpp" + OUTPUT "${NRN_NOCMODL_GEN}/diffeq.hpp" "${NRN_NOCMODL_GEN}/diffeq.cpp" WORKING_DIRECTORY "${BISON_FLEX_WORKING_DIR}" - COMMAND "${BISON_EXECUTABLE}" ARGS "--defines=${NRN_NMODL_GEN_REL}/diffeq.hpp" -o - "${NRN_NMODL_GEN_REL}/diffeq.cpp" "${NRN_NMODL_SRC_REL}/diffeq.ypp" - DEPENDS "${NRN_NMODL_SRC_DIR}/diffeq.ypp" + COMMAND "${BISON_EXECUTABLE}" ARGS "--defines=${NRN_NOCMODL_GEN_REL}/diffeq.hpp" -o + "${NRN_NOCMODL_GEN_REL}/diffeq.cpp" "${NRN_NOCMODL_SRC_REL}/diffeq.ypp" + DEPENDS "${NRN_NOCMODL_SRC_DIR}/diffeq.ypp" COMMENT "[BISON][nocmodlparser] Building parser with bison ${BISON_VERSION}") add_custom_target( nocmodl_generated_files - DEPENDS "${NRN_NMODL_GEN}/lex.cpp" "${NRN_NMODL_GEN}/parse1.hpp" "${NRN_NMODL_GEN}/parse1.cpp" - "${NRN_NMODL_GEN}/diffeq.hpp" "${NRN_NMODL_GEN}/diffeq.cpp") + DEPENDS "${NRN_NOCMODL_GEN}/lex.cpp" "${NRN_NOCMODL_GEN}/parse1.hpp" + "${NRN_NOCMODL_GEN}/parse1.cpp" "${NRN_NOCMODL_GEN}/diffeq.hpp" + "${NRN_NOCMODL_GEN}/diffeq.cpp") add_dependencies(generated_source_files nocmodl_generated_files) -add_executable(nocmodl ${NRN_NMODL_SRC_FILES} "${NRN_NMODL_GEN}/lex.cpp" - "${NRN_NMODL_GEN}/parse1.cpp" "${NRN_NMODL_GEN}/diffeq.cpp") +add_executable(nocmodl ${NRN_NOCMODL_SRC_FILES} "${NRN_NOCMODL_GEN}/lex.cpp" + "${NRN_NOCMODL_GEN}/parse1.cpp" "${NRN_NOCMODL_GEN}/diffeq.cpp") cpp_cc_configure_sanitizers(TARGET nocmodl) target_compile_definitions(nocmodl PRIVATE COMPILE_DEFINITIONS NMODL=1 CVODE=1) # Otherwise the generated code in the binary directory does not find headers in the modlunit source @@ -98,10 +100,10 @@ target_compile_definitions(nocmodl PRIVATE COMPILE_DEFINITIONS NMODL=1 CVODE=1) # submodule. Right now this doesn't work because the CLI11 targets are not exported/installed but # coreneuron-core is. get_target_property(CLI11_HEADER_DIRECTORY CLI11::CLI11 INTERFACE_INCLUDE_DIRECTORIES) -target_include_directories(nocmodl PRIVATE "${NRN_NMODL_GEN}" "${NRN_NMODL_SRC_DIR}" +target_include_directories(nocmodl PRIVATE "${NRN_NOCMODL_GEN}" "${NRN_NOCMODL_SRC_DIR}" "${CLI11_HEADER_DIRECTORY}") -if(NRN_NMODL_CXX_FLAGS) - target_compile_options(nocmodl PRIVATE ${NRN_NMODL_CXX_FLAGS}) +if(NRN_NOCMODL_CXX_FLAGS) + target_compile_options(nocmodl PRIVATE ${NRN_NOCMODL_CXX_FLAGS}) endif() # ============================================================================= From 19dbd47f105469939190f28fe5e4a9bd60a633c2 Mon Sep 17 00:00:00 2001 From: Robert A McDougal Date: Thu, 3 Oct 2024 14:49:55 -0400 Subject: [PATCH 50/68] block unsupported use of set_solve_type (#3117) - Partially solves #1718 in that it blocks attempts to use set_solve_type after nodes have been allocated, which did not work. - A better solution (still needed) would be to allow reallocating e.g. 1D nodes to 3D or vice-versa. --- share/lib/python/neuron/rxd/rxd.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/share/lib/python/neuron/rxd/rxd.py b/share/lib/python/neuron/rxd/rxd.py index 3c0fd18a8e..f1ded6e229 100644 --- a/share/lib/python/neuron/rxd/rxd.py +++ b/share/lib/python/neuron/rxd/rxd.py @@ -291,6 +291,10 @@ def set_solve_type(domain=None, dimension=None, dx=None, nsubseg=None, method=No domain -- a section or Python iterable of sections""" global _dimensions_default, _dimensions + + if initializer.is_initialized(): + raise RxDException("set_solve_type must be called before any access to nodes.") + setting_default = False if domain is None: domain = h.allsec() From ab0a57131967c57649cacdc224fc753abe0044eb Mon Sep 17 00:00:00 2001 From: nrnhines Date: Thu, 3 Oct 2024 16:46:35 -0400 Subject: [PATCH 51/68] NRN_OVERRIDE_LD_PRELOAD can fix AddressSanitizer: CHECK failed: asan_interceptors.cpp (#3116) * NRN_OVERRIDE_LD_PRELOAD env var sets NRN_SANITIZER_LIBRARY_PATH * Some documentation for NRN_OVERRIDE_LD_PRELOAD --- cmake/SanitizerHelper.cmake | 6 ++++++ docs/install/debug.md | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/cmake/SanitizerHelper.cmake b/cmake/SanitizerHelper.cmake index e88a1db7ea..1753503055 100644 --- a/cmake/SanitizerHelper.cmake +++ b/cmake/SanitizerHelper.cmake @@ -10,6 +10,12 @@ set(${CODING_CONV_PREFIX}_SANITIZERS_UNDEFINED_EXCLUSIONS include("${CODING_CONV_CMAKE}/sanitizers.cmake") include(${CODING_CONV_CMAKE}/build-time-copy.cmake) +# If there is an issue with the automatically determined LD_PRELOAD then force with an environment +# variable when running cmake. +if(DEFINED ENV{NRN_OVERRIDE_LD_PRELOAD}) + set(NRN_SANITIZER_LIBRARY_PATH "$ENV{NRN_OVERRIDE_LD_PRELOAD}") +endif() + # Propagate the sanitizer flags to the NEURON sources list(APPEND NRN_COMPILE_FLAGS ${NRN_SANITIZER_COMPILER_FLAGS}) list(APPEND NRN_LINK_FLAGS ${NRN_SANITIZER_COMPILER_FLAGS}) diff --git a/docs/install/debug.md b/docs/install/debug.md index 725f692576..ae42b73779 100644 --- a/docs/install/debug.md +++ b/docs/install/debug.md @@ -177,6 +177,15 @@ use `nrn-enable-sanitizer special -python path/to/script.py` or because the `python` binary is (presumably) not linked against the sanitizer runtime library. +If ctest or nrn-enable-sanitizer runs generate a sanitizer error like +`AddressSanitizer: CHECK failed: asan_interceptors.cpp` +it might be that the automatically determined `LD_PRELOAD` is insufficient. +(It happened to me with ubuntu 24.04 + gcc 13.2.0). In this case you +can temporarily set the `NRN_OVERRIDE_LD_PRELOAD` environment variable before +running cmake. In my case, +`NRN_OVERRIDE_LD_PRELOAD="$(realpath "$(gcc -print-file-name=libasan.so)"):$realpath +"$(gcc -print-file-name=libstdc++.so)")" cmake ...` sufficed. + LSan, TSan and UBSan support suppression files, which can be used to prevent tests failing due to known issues. NEURON includes a suppression file for TSan under `.sanitizers/thread.supp` and @@ -792,4 +801,3 @@ Unlike VTune, LIKWID doesn't support direct comparison of profile data. However, for code regions, and since the profile results are provided as text output, comparing results from two runs is straightforward. For instance, the screenshot below shows FLOPS instructions side by side between two runs: -![VTune Comparison](images/nrn_likwid_presoa_master_comparison.png) \ No newline at end of file From 31c9245eee45a92f39d0937985756523fc578ef4 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Wed, 9 Oct 2024 16:08:21 +0200 Subject: [PATCH 52/68] Use nb::iterator instead of Py_Iterator (#3120) --- src/nrnpython/nrnpy_p2h.cpp | 69 +++++++++---------------------------- src/utils/enumerate.h | 4 +-- 2 files changed, 18 insertions(+), 55 deletions(-) diff --git a/src/nrnpython/nrnpy_p2h.cpp b/src/nrnpython/nrnpy_p2h.cpp index f84cb29bcf..8ea32f97b2 100644 --- a/src/nrnpython/nrnpy_p2h.cpp +++ b/src/nrnpython/nrnpy_p2h.cpp @@ -14,6 +14,7 @@ #include "parse.hpp" #include + namespace nb = nanobind; static char* nrnpyerr_str(); @@ -926,8 +927,8 @@ static Object* py_alltoall_type(int size, int type) { size = 0; // calculate dest size (cannot be -1 so cannot return it) } - char* s = NULL; - int* scnt = NULL; + std::vector s{}; + std::vector scnt{}; int* sdispl = NULL; char* r = NULL; int* rcnt = NULL; @@ -937,49 +938,18 @@ static Object* py_alltoall_type(int size, int type) { // for alltoall, each rank handled identically // for scatter, root handled as list all, other ranks handled as None if (type == 1 || nrnmpi_myid == root) { // psrc is list of nhost items - - scnt = new int[np]; - for (int i = 0; i < np; ++i) { - scnt[i] = 0; - } - - PyObject* iterator = PyObject_GetIter(psrc); - PyObject* p; - - size_t bufsz = 100000; // 100k buffer to start with - if (size > 0) { // or else the positive number specified - bufsz = size; - } - if (size >= 0) { // otherwise count only - s = new char[bufsz]; - } - size_t curpos = 0; - for (size_t i = 0; (p = PyIter_Next(iterator)) != NULL; ++i) { - if (p == Py_None) { - scnt[i] = 0; - Py_DECREF(p); + scnt.reserve(np); + for (const nb::handle& p: nb::list(psrc)) { + if (p.is_none()) { + scnt.push_back(0); continue; } - auto b = pickle(p); + const std::vector b = pickle(p.ptr()); if (size >= 0) { - if (curpos + b.size() >= bufsz) { - bufsz = bufsz * 2 + b.size(); - char* s2 = new char[bufsz]; - for (size_t i = 0; i < curpos; ++i) { - s2[i] = s[i]; - } - delete[] s; - s = s2; - } - for (size_t j = 0; j < b.size(); ++j) { - s[curpos + j] = b[j]; - } + s.insert(std::end(s), std::begin(b), std::end(b)); } - curpos += b.size(); - scnt[i] = static_cast(b.size()); - Py_DECREF(p); + scnt.push_back(static_cast(b.size())); } - Py_DECREF(iterator); // scatter equivalent to alltoall NONE list for not root ranks. } else if (type == 5 && nrnmpi_myid != root) { @@ -996,26 +966,23 @@ static Object* py_alltoall_type(int size, int type) { } sdispl = mk_displ(ones); rcnt = new int[np]; - nrnmpi_int_alltoallv(scnt, ones, sdispl, rcnt, ones, sdispl); + nrnmpi_int_alltoallv(scnt.data(), ones, sdispl, rcnt, ones, sdispl); delete[] ones; delete[] sdispl; // exchange - sdispl = mk_displ(scnt); + sdispl = mk_displ(scnt.data()); rdispl = mk_displ(rcnt); if (size < 0) { pdest = PyTuple_New(2); PyTuple_SetItem(pdest, 0, Py_BuildValue("l", (long) sdispl[np])); PyTuple_SetItem(pdest, 1, Py_BuildValue("l", (long) rdispl[np])); - delete[] scnt; delete[] sdispl; delete[] rcnt; delete[] rdispl; } else { char* r = new char[rdispl[np] + 1]; // force > 0 for all None case - nrnmpi_char_alltoallv(s, scnt, sdispl, r, rcnt, rdispl); - delete[] s; - delete[] scnt; + nrnmpi_char_alltoallv(s.data(), scnt.data(), sdispl, r, rcnt, rdispl); delete[] sdispl; pdest = char2pylist(r, np, rcnt, rdispl); @@ -1029,18 +996,14 @@ static Object* py_alltoall_type(int size, int type) { // destination counts rcnt = new int[1]; - nrnmpi_int_scatter(scnt, rcnt, 1, root); + nrnmpi_int_scatter(scnt.data(), rcnt, 1, root); std::vector r(rcnt[0] + 1); // rcnt[0] can be 0 // exchange if (nrnmpi_myid == root) { - sdispl = mk_displ(scnt); + sdispl = mk_displ(scnt.data()); } - nrnmpi_char_scatterv(s, scnt, sdispl, r.data(), rcnt[0], root); - if (s) - delete[] s; - if (scnt) - delete[] scnt; + nrnmpi_char_scatterv(s.data(), scnt.data(), sdispl, r.data(), rcnt[0], root); if (sdispl) delete[] sdispl; diff --git a/src/utils/enumerate.h b/src/utils/enumerate.h index 1a0b38f2ad..e9492887bc 100644 --- a/src/utils/enumerate.h +++ b/src/utils/enumerate.h @@ -99,7 +99,7 @@ constexpr auto enumerate(T&& iterable) { ++iter; } auto operator*() const { - return std::tie(i, *iter); + return std::forward_as_tuple(i, *iter); } }; struct iterable_wrapper { @@ -129,7 +129,7 @@ constexpr auto renumerate(T&& iterable) { ++iter; } auto operator*() const { - return std::tie(i, *iter); + return std::forward_as_tuple(i, *iter); } }; struct iterable_wrapper { From c9ee32e3f082f2ac84c9e80e83a8a92d1f52ea1d Mon Sep 17 00:00:00 2001 From: JCGoran Date: Wed, 9 Oct 2024 16:39:08 +0200 Subject: [PATCH 53/68] Add NRN_PARALLEL_BUILDS to setup.py (#3122) The environment variable `NRN_PARALLEL_BUILDS` can be used to control the build parallelism. Essentially, `-j${NRN_PARALLEL_BUILDS}`. --- docs/install/python_wheels.md | 2 ++ setup.py | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/install/python_wheels.md b/docs/install/python_wheels.md index 42387bfad8..8d0b1755c9 100644 --- a/docs/install/python_wheels.md +++ b/docs/install/python_wheels.md @@ -171,6 +171,8 @@ bash packaging/python/build_wheels.bash linux 3* coreneuron ``` Where we are passing `3*` to build the wheels with `CoreNEURON` support for all python 3 versions. +You can also control the level of parallelization used for the build using the `NRN_PARALLEL_BUILDS` env variable (default: 4). + ### macOS As mentioned above, for macOS all dependencies have to be available on a system. You have to then clone NEURON repository and execute: diff --git a/setup.py b/setup.py index e15b6e5ac0..ba0922b273 100644 --- a/setup.py +++ b/setup.py @@ -247,7 +247,12 @@ def _run_cmake(self, ext): if self.cmake_defs: cmake_args += ["-D" + opt for opt in self.cmake_defs.split(",")] - build_args = ["--config", cfg, "--", "-j4"] # , 'VERBOSE=1'] + build_args = [ + "--config", + cfg, + "--", + f"-j{os.environ.get('NRN_PARALLEL_BUILDS', 4)}", + ] env = os.environ.copy() env["CXXFLAGS"] = "{} -DVERSION_INFO='{}'".format( From aecfda00df71b504a78f8640b580dc79e867e469 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Mon, 14 Oct 2024 16:12:35 +0200 Subject: [PATCH 54/68] cleaning around hoccommand_exec_help1 (#3124) --- src/nrnpython/nrnpy_p2h.cpp | 108 +++++++++++++----------------------- 1 file changed, 38 insertions(+), 70 deletions(-) diff --git a/src/nrnpython/nrnpy_p2h.cpp b/src/nrnpython/nrnpy_p2h.cpp index 8ea32f97b2..fc0a4d085b 100644 --- a/src/nrnpython/nrnpy_p2h.cpp +++ b/src/nrnpython/nrnpy_p2h.cpp @@ -18,7 +18,7 @@ namespace nb = nanobind; static char* nrnpyerr_str(); -static PyObject* nrnpy_pyCallObject(PyObject*, PyObject*); +static nb::object nrnpy_pyCallObject(nb::callable, PyObject*); static PyObject* main_module; static PyObject* main_namespace; @@ -42,15 +42,12 @@ static void p_destruct(void* v) { Member_func p_members[] = {{nullptr, nullptr}}; static void call_python_with_section(Object* pyact, Section* sec) { - PyObject* po = ((Py2Nrn*) pyact->u.this_pointer)->po_; - PyObject* r; + nb::callable po = nb::borrow(((Py2Nrn*) pyact->u.this_pointer)->po_); nanobind::gil_scoped_acquire lock{}; - PyObject* args = PyTuple_Pack(1, (PyObject*) newpysechelp(sec)); - r = nrnpy_pyCallObject(po, args); - Py_XDECREF(args); - Py_XDECREF(r); - if (!r) { + nb::tuple args = nb::make_tuple(reinterpret_cast(newpysechelp(sec))); + nb::object r = nrnpy_pyCallObject(po, args.ptr()); + if (!r.is_valid()) { char* mes = nrnpyerr_str(); if (mes) { Fprintf(stderr, "%s\n", mes); @@ -109,12 +106,12 @@ Object* nrnpy_pyobject_in_obj(PyObject* po) { return on; } -static PyObject* nrnpy_pyCallObject(PyObject* callable, PyObject* args) { +static nb::object nrnpy_pyCallObject(nb::callable callable, PyObject* args) { // When hoc calls a PythonObject method, then in case python // calls something back in hoc, the hoc interpreter must be // at the top level HocTopContextSet - PyObject* p = PyObject_CallObject(callable, args); + PyObject* p = PyObject_CallObject(callable.ptr(), args); #if 0 printf("PyObject_CallObject callable\n"); PyObject_Print(callable, stdout, 0); @@ -142,7 +139,7 @@ printf("\nreturn %p\n", p); } } **/ - return p; + return nb::steal(p); } static void py2n_component(Object* ob, Symbol* sym, int nindex, int isfunc) { @@ -199,7 +196,7 @@ static void py2n_component(Object* ob, Symbol* sym, int nindex, int isfunc) { } } // printf("PyObject_CallObject %s %p\n", sym->name, tail); - result = nrnpy_pyCallObject(tail, args); + result = nrnpy_pyCallObject(nb::borrow(tail), args).release().ptr(); Py_DECREF(args); // PyObject_Print(result, stdout, 0); // printf(" result of call\n"); @@ -330,36 +327,22 @@ static void hpoasgn(Object* o, int type) { } } -static PyObject* hoccommand_exec_help1(PyObject* po) { - PyObject* r; - // PyObject_Print(po, stdout, 0); - // printf("\n"); - if (PyTuple_Check(po)) { - PyObject* args = PyTuple_GetItem(po, 1); - if (!PyTuple_Check(args)) { - args = PyTuple_Pack(1, args); - } else { - Py_INCREF(args); +static nb::object hoccommand_exec_help1(nb::object po) { + if (nb::tuple::check_(po)) { + nb::object args = po[1]; + if (!nb::tuple::check_(args)) { + args = nb::make_tuple(args); } - // PyObject_Print(PyTuple_GetItem(po, 0), stdout, 0); - // printf("\n"); - // PyObject_Print(args, stdout, 0); - // printf("\n"); - // printf("threadstate %p\n", PyThreadState_GET()); - r = nrnpy_pyCallObject(PyTuple_GetItem(po, 0), args); - Py_DECREF(args); + return nrnpy_pyCallObject(po[0], args.ptr()); } else { - PyObject* args = PyTuple_New(0); - r = nrnpy_pyCallObject(po, args); - Py_DECREF(args); + return nrnpy_pyCallObject(nb::borrow(po), nb::tuple().ptr()); } - return r; } -static PyObject* hoccommand_exec_help(Object* ho) { +static nb::object hoccommand_exec_help(Object* ho) { PyObject* po = ((Py2Nrn*) ho->u.this_pointer)->po_; // printf("%s\n", hoc_object_name(ho)); - return hoccommand_exec_help1(po); + return hoccommand_exec_help1(nb::borrow(po)); } static double praxis_efun(Object* ho, Object* v) { @@ -370,9 +353,9 @@ static double praxis_efun(Object* ho, Object* v) { PyObject* po = Py_BuildValue("(OO)", pc, pv); Py_XDECREF(pc); Py_XDECREF(pv); - PyObject* r = hoccommand_exec_help1(po); + nb::object r = hoccommand_exec_help1(nb::borrow(po)); Py_XDECREF(po); - if (!r) { + if (!r.is_valid()) { char* mes = nrnpyerr_str(); if (mes) { Fprintf(stderr, "%s\n", mes); @@ -384,18 +367,14 @@ static double praxis_efun(Object* ho, Object* v) { } return 1e9; // SystemExit? } - PyObject* pn = PyNumber_Float(r); - double x = PyFloat_AsDouble(pn); - Py_XDECREF(pn); - Py_XDECREF(r); - return x; + return static_cast(nb::float_(r)); } static int hoccommand_exec(Object* ho) { nanobind::gil_scoped_acquire lock{}; - PyObject* r = hoccommand_exec_help(ho); - if (r == NULL) { + nb::object r = hoccommand_exec_help(ho); + if (!r.is_valid()) { char* mes = nrnpyerr_str(); if (mes) { std::string tmp{"Python Callback failed [hoccommand_exec]:\n"}; @@ -407,21 +386,18 @@ static int hoccommand_exec(Object* ho) { PyErr_Print(); } } - Py_XDECREF(r); - return (r != NULL); + return r.is_valid(); } static int hoccommand_exec_strret(Object* ho, char* buf, int size) { nanobind::gil_scoped_acquire lock{}; - PyObject* r = hoccommand_exec_help(ho); - if (r) { - PyObject* pn = PyObject_Str(r); - Py2NRNString str(pn); - Py_XDECREF(pn); + nb::object r = hoccommand_exec_help(ho); + if (r.is_valid()) { + nb::str pn(r); + Py2NRNString str(pn.ptr()); strncpy(buf, str.c_str(), size); buf[size - 1] = '\0'; - Py_XDECREF(r); } else { char* mes = nrnpyerr_str(); if (mes) { @@ -433,20 +409,16 @@ static int hoccommand_exec_strret(Object* ho, char* buf, int size) { PyErr_Print(); } } - return (r != NULL); + return r.is_valid(); } static void grphcmdtool(Object* ho, int type, double x, double y, int key) { - PyObject* po = ((Py2Nrn*) ho->u.this_pointer)->po_; - PyObject* r; + nb::callable po = nb::borrow(((Py2Nrn*) ho->u.this_pointer)->po_); nanobind::gil_scoped_acquire lock{}; - PyObject* args = PyTuple_Pack( - 4, PyInt_FromLong(type), PyFloat_FromDouble(x), PyFloat_FromDouble(y), PyInt_FromLong(key)); - r = nrnpy_pyCallObject(po, args); - Py_XDECREF(args); - Py_XDECREF(r); - if (!r) { + nb::tuple args = nb::make_tuple(type, x, y, key); + nb::object r = nrnpy_pyCallObject(po, args.ptr()); + if (!r.is_valid()) { char* mes = nrnpyerr_str(); if (mes) { Fprintf(stderr, "%s\n", mes); @@ -492,8 +464,7 @@ static Object* callable_with_args(Object* ho, int narg) { } static double func_call(Object* ho, int narg, int* err) { - PyObject* po = ((Py2Nrn*) ho->u.this_pointer)->po_; - PyObject* r; + nb::callable po = nb::borrow(((Py2Nrn*) ho->u.this_pointer)->po_); nanobind::gil_scoped_acquire lock{}; PyObject* args = PyTuple_New((Py_ssize_t) narg); @@ -512,10 +483,10 @@ static double func_call(Object* ho, int narg, int* err) { } } - r = nrnpy_pyCallObject(po, args); + nb::object r = nrnpy_pyCallObject(po, args); Py_XDECREF(args); double rval = 0.0; - if (r == NULL) { + if (!r.is_valid()) { if (!err || *err) { char* mes = nrnpyerr_str(); if (mes) { @@ -535,12 +506,9 @@ static double func_call(Object* ho, int narg, int* err) { *err = 1; } } else { - if (nrnpy_numbercheck(r)) { - PyObject* pn = PyNumber_Float(r); - rval = PyFloat_AsDouble(pn); - Py_XDECREF(pn); + if (nrnpy_numbercheck(r.ptr())) { + rval = static_cast(nb::float_(r)); } - Py_XDECREF(r); if (err) { *err = 0; } // success From 1ef583b31ee1809cd3b24061811427abd52a0919 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Fri, 18 Oct 2024 11:44:42 +0200 Subject: [PATCH 55/68] Avoid warning comming from internal of eigen (#3132) --- src/nrnpython/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nrnpython/CMakeLists.txt b/src/nrnpython/CMakeLists.txt index 1a9696de9d..c857e3c37b 100644 --- a/src/nrnpython/CMakeLists.txt +++ b/src/nrnpython/CMakeLists.txt @@ -74,7 +74,7 @@ else() target_link_libraries(nrnpython ${NRN_DEFAULT_PYTHON_LIBRARIES}) endif() target_link_libraries(nrnpython fmt::fmt) - target_include_directories(nrnpython PUBLIC ${PROJECT_SOURCE_DIR}/${NRN_3RDPARTY_DIR}/eigen) + target_include_directories(nrnpython SYSTEM PUBLIC ${PROJECT_SOURCE_DIR}/${NRN_3RDPARTY_DIR}/eigen) target_include_directories(nrnpython PUBLIC ${PROJECT_BINARY_DIR}/src/nrniv/oc_generated) make_nanobind_target(nanobind ${NRN_DEFAULT_PYTHON_INCLUDES}) target_link_libraries(nrnpython nanobind) From 27efa9271386b24f3cd7090daa46090be5ef14e1 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Fri, 18 Oct 2024 13:56:00 +0200 Subject: [PATCH 56/68] Remove only a small part (#3133) --- .gitlab-ci.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6c755ea369..6072f41ea1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -148,19 +148,6 @@ spack_setup: # BLUECONFIGS_BRANCH does not correspond to a Spack package called blueconfigs SPACK_SETUP_IGNORE_PACKAGE_VARIABLES: BLUECONFIGS -simulation_stack: - stage: .pre - # Take advantage of GitHub PR description parsing in the spack_setup job. - needs: [spack_setup] - trigger: - branch: $BLUECONFIGS_BRANCH - project: hpc/sim/blueconfigs - # NEURON CI status depends on the BlueConfigs CI status. - strategy: depend - variables: - GITLAB_PIPELINES_BRANCH: $GITLAB_PIPELINES_BRANCH - SPACK_ENV_FILE_URL: $SPACK_SETUP_COMMIT_MAPPING_URL - # Performance seems to be terrible when we get too many jobs on a single node. .build: extends: [.spack_build] From 33263d01436d1b89fde299e1c63f3edeca4370ac Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Fri, 18 Oct 2024 16:08:58 +0200 Subject: [PATCH 57/68] Reduce warnings for gnu directory (#3134) --- src/gnu/mcran4.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/gnu/mcran4.cpp b/src/gnu/mcran4.cpp index a9553687f6..fb913a8a9e 100644 --- a/src/gnu/mcran4.cpp +++ b/src/gnu/mcran4.cpp @@ -92,19 +92,6 @@ uint32_t nrnRan4int(uint32_t* idx1, uint32_t idx2) { /*n ^= (((u >> 16) | (u << 16)) ^ 0x178b0f3c) + w * v;*/ n ^= (((u >> 16) | (u << 16)) ^ 0xe874f0c3) + w * v; return n; - - w = n ^ 0x03bcdc3c; - v = w >> 16; - w &= 0xffff; - u = (v - w) * (v + w); - m ^= (((u >> 16) | (u << 16)) ^ 0x96aa3a59) + w * v; - - w = m ^ 0x0f33d1b2; - v = w >> 16; - w &= 0xffff; - u = (v - w) * (v + w); - n ^= (((u >> 16) | (u << 16)) ^ 0xaa5835b9) + w * v; - return n; } /* @@ -128,7 +115,7 @@ uint32_t nrnRan4int(uint32_t* idx1, uint32_t idx2) { */ static const double SHIFT32 = 1.0 / 4294967296.0; /* 2^-32 */ double nrnRan4dbl(uint32_t* idx1, uint32_t idx2) { - uint32_t hi, lo, extra; + uint32_t hi; hi = (uint32_t) nrnRan4int(idx1, idx2); /*top 32 bits*/ /* // lo = (extra // low bits From cf2318c92fe72ca01e3c3554fdf9917a5c3bb2fd Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Fri, 18 Oct 2024 17:56:04 +0200 Subject: [PATCH 58/68] Remove complex part of sparse13 (#3130) --- src/sparse13/spalloc.cpp | 45 --- src/sparse13/spbuild.cpp | 213 ---------- src/sparse13/spconfig.h | 26 -- src/sparse13/spdefs.h | 248 ------------ src/sparse13/spfactor.cpp | 238 +---------- src/sparse13/spmatrix.h | 50 --- src/sparse13/spoutput.cpp | 98 +---- src/sparse13/spsolve.cpp | 328 ---------------- src/sparse13/sputils.cpp | 809 +------------------------------------- 9 files changed, 23 insertions(+), 2032 deletions(-) diff --git a/src/sparse13/spalloc.cpp b/src/sparse13/spalloc.cpp index ab85ebefd9..233093c61f 100644 --- a/src/sparse13/spalloc.cpp +++ b/src/sparse13/spalloc.cpp @@ -15,7 +15,6 @@ * spWhereSingular * spGetSize * spSetReal - * spSetComplex * spFillinCount * spElementCount * @@ -45,11 +44,6 @@ * or implied warranty. */ -#ifndef lint -static char copyright[] = "Sparse1.3: Copyright (c) 1985,86,87,88 by Kenneth S. Kundert"; -static char RCSid[] = "@(#)$Header$"; -#endif - /* * IMPORTS * @@ -126,12 +120,10 @@ char* spCreate(int Size, BOOLEAN Complex, int* pError) } /* Test for valid type. */ -#if NOT spCOMPLEX if (Complex) { *pError = spPANIC; return NULL; } -#endif #if NOT REAL if (NOT Complex) { *pError = spPANIC; @@ -193,9 +185,6 @@ char* spCreate(int Size, BOOLEAN Complex, int* pError) /* Take out the trash. */ Matrix->TrashCan.Real = 0.0; -#if spCOMPLEX - Matrix->TrashCan.Imag = 0.0; -#endif Matrix->TrashCan.Row = 0; Matrix->TrashCan.Col = 0; Matrix->TrashCan.NextInRow = NULL; @@ -233,24 +222,6 @@ char* spCreate(int Size, BOOLEAN Complex, int* pError) Matrix->IntToExtColMap[I] = I; } -#if TRANSLATE - /* Allocate space in memory for ExtToIntColMap vector. */ - if ((Matrix->ExtToIntColMap = ALLOC(int, SizePlusOne)) == NULL) - goto MemoryError; - - /* Allocate space in memory for ExtToIntRowMap vector. */ - if ((Matrix->ExtToIntRowMap = ALLOC(int, SizePlusOne)) == NULL) - goto MemoryError; - - /* Initialize MapExtToInt vectors. */ - for (I = 1; I <= AllocatedSize; I++) { - Matrix->ExtToIntColMap[I] = -1; - Matrix->ExtToIntRowMap[I] = -1; - } - Matrix->ExtToIntColMap[0] = 0; - Matrix->ExtToIntRowMap[0] = 0; -#endif - /* Allocate space for fill-ins and initial set of elements. */ InitializeElementBlocks(Matrix, SPACE_FOR_ELEMENTS * AllocatedSize, SPACE_FOR_FILL_INS * AllocatedSize); @@ -671,14 +642,7 @@ int spGetSize(char* eMatrix, BOOLEAN External) /* Begin `spGetSize'. */ ASSERT(IS_SPARSE(Matrix)); -#if TRANSLATE - if (External) - return Matrix->ExtSize; - else - return Matrix->Size; -#else return Matrix->Size; -#endif } /* @@ -700,15 +664,6 @@ void spSetReal(char* eMatrix) return; } -void spSetComplex(char* eMatrix) -{ - /* Begin `spSetComplex'. */ - - ASSERT(IS_SPARSE((MatrixPtr)eMatrix) AND spCOMPLEX); - ((MatrixPtr)eMatrix)->Complex = YES; - return; -} - /* * ELEMENT OR FILL-IN COUNT * diff --git a/src/sparse13/spbuild.cpp b/src/sparse13/spbuild.cpp index 3b7e9a1da2..f0a5867609 100644 --- a/src/sparse13/spbuild.cpp +++ b/src/sparse13/spbuild.cpp @@ -20,11 +20,9 @@ * * >>> Other functions contained in this file: * spcFindElementInCol - * Translate * spcCreateElement * spcLinkRows * EnlargeMatrix - * ExpandTranslationArrays */ /* @@ -43,11 +41,6 @@ * or implied warranty. */ -#ifndef lint -static char copyright[] = "Sparse1.3: Copyright (c) 1985,86,87,88 by Kenneth S. Kundert"; -static char RCSid[] = "@(#)$Header$"; -#endif - /* * IMPORTS * @@ -70,9 +63,7 @@ static char RCSid[] = "@(#)$Header$"; extern ElementPtr spcGetFillin(MatrixPtr Matrix); extern ElementPtr spcGetElement(MatrixPtr Matrix); -static void Translate(MatrixPtr Matrix, int* Row, int* Col); static void EnlargeMatrix(MatrixPtr Matrix, int NewSize); -static void ExpandTranslationArrays(MatrixPtr Matrix, int NewSize); /* * CLEAR MATRIX @@ -98,18 +89,6 @@ void spClear(char* eMatrix) ASSERT(IS_SPARSE(Matrix)); /* Clear matrix. */ -#if spCOMPLEX - if (Matrix->PreviousMatrixWasComplex OR Matrix->Complex) { - for (I = Matrix->Size; I > 0; I--) { - pElement = Matrix->FirstInCol[I]; - while (pElement != NULL) { - pElement->Real = 0.0; - pElement->Imag = 0.0; - pElement = pElement->NextInCol; - } - } - } else -#endif { for (I = Matrix->Size; I > 0; I--) { pElement = Matrix->FirstInCol[I]; @@ -122,9 +101,6 @@ void spClear(char* eMatrix) /* Empty the trash. */ Matrix->TrashCan.Real = 0.0; -#if spCOMPLEX - Matrix->TrashCan.Imag = 0.0; -#endif Matrix->Error = spOKAY; Matrix->Factored = NO; @@ -183,17 +159,8 @@ RealNumber* spGetElement(char* eMatrix, int Row, int Col) if ((Row == 0) OR(Col == 0)) return &Matrix->TrashCan.Real; -#if NOT TRANSLATE ASSERT(Matrix->NeedsOrdering); -#endif - -#if TRANSLATE - Translate(Matrix, &Row, &Col); - if (Matrix->Error == spNO_MEMORY) - return NULL; -#endif -#if NOT TRANSLATE #if NOT EXPANDABLE ASSERT(Row <= Matrix->Size AND Col <= Matrix->Size); #endif @@ -204,7 +171,6 @@ RealNumber* spGetElement(char* eMatrix, int Row, int Col) EnlargeMatrix(Matrix, MAX(Row, Col)); if (Matrix->Error == spNO_MEMORY) return NULL; -#endif #endif /* @@ -290,109 +256,6 @@ ElementPtr spcFindElementInCol(MatrixPtr Matrix, ElementPtr* LastAddr, int Row, return NULL; } -#if TRANSLATE - -/* - * TRANSLATE EXTERNAL INDICES TO INTERNAL - * - * Convert internal row and column numbers to internal row and column numbers. - * Also updates Ext/Int maps. - * - * - * >>> Arguments: - * Matrix (MatrixPtr) - * Pointer to the matrix. - * Row (int *) - * Upon entry Row is either a external row number of an external node - * number. Upon entry, the internal equivalent is supplied. - * Col (int *) - * Upon entry Column is either a external column number of an external node - * number. Upon entry, the internal equivalent is supplied. - * - * >>> Local variables: - * ExtCol (int) - * Temporary variable used to hold the external column or node number - * during the external to internal column number translation. - * ExtRow (int) - * Temporary variable used to hold the external row or node number during - * the external to internal row number translation. - * IntCol (int) - * Temporary variable used to hold the internal column or node number - * during the external to internal column number translation. - * IntRow (int) - * Temporary variable used to hold the internal row or node number during - * the external to internal row number translation. - */ - -static void Translate(MatrixPtr Matrix, int* Row, int* Col) -{ - int IntRow, IntCol, ExtRow, ExtCol; - - /* Begin `Translate'. */ - ExtRow = *Row; - ExtCol = *Col; - - /* Expand translation arrays if necessary. */ - if ((ExtRow > Matrix->AllocatedExtSize) OR(ExtCol > Matrix->AllocatedExtSize)) { - ExpandTranslationArrays(Matrix, MAX(ExtRow, ExtCol)); - if (Matrix->Error == spNO_MEMORY) - return; - } - - /* Set ExtSize if necessary. */ - if ((ExtRow > Matrix->ExtSize) OR(ExtCol > Matrix->ExtSize)) - Matrix->ExtSize = MAX(ExtRow, ExtCol); - - /* Translate external row or node number to internal row or node number. */ - if ((IntRow = Matrix->ExtToIntRowMap[ExtRow]) == -1) { - Matrix->ExtToIntRowMap[ExtRow] = ++Matrix->CurrentSize; - Matrix->ExtToIntColMap[ExtRow] = Matrix->CurrentSize; - IntRow = Matrix->CurrentSize; - -#if NOT EXPANDABLE - ASSERT(IntRow <= Matrix->Size); -#endif - -#if EXPANDABLE - /* Re-size Matrix if necessary. */ - if (IntRow > Matrix->Size) - EnlargeMatrix(Matrix, IntRow); - if (Matrix->Error == spNO_MEMORY) - return; -#endif - - Matrix->IntToExtRowMap[IntRow] = ExtRow; - Matrix->IntToExtColMap[IntRow] = ExtRow; - } - - /* Translate external column or node number to internal column or node number.*/ - if ((IntCol = Matrix->ExtToIntColMap[ExtCol]) == -1) { - Matrix->ExtToIntRowMap[ExtCol] = ++Matrix->CurrentSize; - Matrix->ExtToIntColMap[ExtCol] = Matrix->CurrentSize; - IntCol = Matrix->CurrentSize; - -#if NOT EXPANDABLE - ASSERT(IntCol <= Matrix->Size); -#endif - -#if EXPANDABLE - /* Re-size Matrix if necessary. */ - if (IntCol > Matrix->Size) - EnlargeMatrix(Matrix, IntCol); - if (Matrix->Error == spNO_MEMORY) - return; -#endif - - Matrix->IntToExtRowMap[IntCol] = ExtCol; - Matrix->IntToExtColMap[IntCol] = ExtCol; - } - - *Row = IntRow; - *Col = IntCol; - return; -} -#endif - #if QUAD_ELEMENT /* * ADDITION OF ADMITTANCE TO MATRIX BY INDEX @@ -649,9 +512,6 @@ ElementPtr spcCreateElement(MatrixPtr Matrix, int Row, int Col, ElementPtr* Last pElement->Row = Row; pElement->Col = Col; pElement->Real = 0.0; -#if spCOMPLEX - pElement->Imag = 0.0; -#endif #if INITIALIZE pElement->pInitInfo = NULL; #endif @@ -708,9 +568,6 @@ ElementPtr spcCreateElement(MatrixPtr Matrix, int Row, int Col, ElementPtr* Last pElement->Col = Col; #endif pElement->Real = 0.0; -#if spCOMPLEX - pElement->Imag = 0.0; -#endif #if INITIALIZE pElement->pInitInfo = NULL; #endif @@ -847,58 +704,6 @@ static void EnlargeMatrix(MatrixPtr Matrix, int NewSize) return; } -#if TRANSLATE - -/* - * EXPAND TRANSLATION ARRAYS - * - * Increases the size arrays that are used to translate external to internal - * row and column numbers. - * - * >>> Arguments: - * Matrix (MatrixPtr) - * Pointer to the matrix. - * NewSize (int) - * The new size of the translation arrays. - * - * >>> Local variables: - * OldAllocatedSize (int) - * The allocated size of the translation arrays before being expanded. - */ - -static void ExpandTranslationArrays(MatrixPtr Matrix, int NewSize) -{ - int I, OldAllocatedSize = Matrix->AllocatedExtSize; - - /* Begin `ExpandTranslationArrays'. */ - Matrix->ExtSize = NewSize; - - if (NewSize <= OldAllocatedSize) - return; - - /* Expand the translation arrays ExtToIntRowMap and ExtToIntColMap. */ - NewSize = MAX(NewSize, EXPANSION_FACTOR * OldAllocatedSize); - Matrix->AllocatedExtSize = NewSize; - - if ((REALLOC(Matrix->ExtToIntRowMap, int, NewSize + 1)) == NULL) { - Matrix->Error = spNO_MEMORY; - return; - } - if ((REALLOC(Matrix->ExtToIntColMap, int, NewSize + 1)) == NULL) { - Matrix->Error = spNO_MEMORY; - return; - } - - /* Initialize the new portion of the vectors. */ - for (I = OldAllocatedSize + 1; I <= NewSize; I++) { - Matrix->ExtToIntRowMap[I] = -1; - Matrix->ExtToIntColMap[I] = -1; - } - - return; -} -#endif - #if INITIALIZE /* * INITIALIZE MATRIX @@ -960,18 +765,6 @@ int (*pInit)(); /* Begin `spInitialize'. */ ASSERT(IS_SPARSE(Matrix)); -#if spCOMPLEX - /* Clear imaginary part of matrix if matrix is real but was complex. */ - if (Matrix->PreviousMatrixWasComplex AND NOT Matrix->Complex) { - for (J = Matrix->Size; J > 0; J--) { - pElement = Matrix->FirstInCol[J]; - while (pElement != NULL) { - pElement->Imag = 0.0; - pElement = pElement->NextInCol; - } - } - } -#endif /* spCOMPLEX */ /* Initialize the matrix. */ for (J = Matrix->Size; J > 0; J--) { @@ -980,9 +773,6 @@ int (*pInit)(); while (pElement != NULL) { if (pElement->pInitInfo == NULL) { pElement->Real = 0.0; -#if spCOMPLEX - pElement->Imag = 0.0; -#endif } else { Error = (*pInit)((RealNumber*)pElement, pElement->pInitInfo, Matrix->IntToExtRowMap[pElement->Row], Col); @@ -997,9 +787,6 @@ int (*pInit)(); /* Empty the trash. */ Matrix->TrashCan.Real = 0.0; -#if spCOMPLEX - Matrix->TrashCan.Imag = 0.0; -#endif Matrix->Error = spOKAY; Matrix->Factored = NO; diff --git a/src/sparse13/spconfig.h b/src/sparse13/spconfig.h index ae52e16216..22cd3f9dcf 100644 --- a/src/sparse13/spconfig.h +++ b/src/sparse13/spconfig.h @@ -67,9 +67,6 @@ * both real and complex systems at the same time, but there is a * slight speed and memory advantage if the routines are complied * to handle only real systems of equations. - * spCOMPLEX - * This specifies that the routines will be complied to handle - * complex systems of equations. * EXPANDABLE * Setting this compiler flag true (1) makes the matrix * expandable before it has been factored. If the matrix is @@ -140,16 +137,6 @@ * must have an allocated length of one plus the size of the * matrix. ARRAY_OFFSET must be either 0 or 1, no other offsets * are valid. - * spSEPARATED_COMPLEX_VECTORS - * This specifies the format for complex vectors. If this is set - * false then a complex vector is made up of one double sized - * array of RealNumber's in which the real and imaginary numbers - * are placed in the alternately array in the array. In other - * words, the first entry would be Complex[1].Real, then comes - * Complex[1].Imag, then Complex[1].Real, etc. If - * spSEPARATED_COMPLEX_VECTORS is set true, then each complex - * vector is represented by two arrays of RealNumbers, one with - * the real terms, the other with the imaginary. [NO] * MODIFIED_MARKOWITZ * This specifies that the modified Markowitz method of pivot * selection is to be used. The modified Markowitz method differs @@ -243,12 +230,6 @@ /* Begin options. */ #define REAL YES #define EXPANDABLE YES -#if defined(cmplx_spPrefix) -/* NEURON's nonlinz.cpp uses cmplx_spGetElement after previous use of matrix */ -#define TRANSLATE YES -#else -#define TRANSLATE NO /* instead of YES */ -#endif #define INITIALIZE NO /* instead of YES */ #define DIAGONAL_PIVOTING YES #define ARRAY_OFFSET NOT FORTRAN @@ -275,13 +256,6 @@ * with user code, so use 0 for NO and 1 for YES. */ #endif /* spINSIDE_SPARSE */ -#if defined(cmplx_spPrefix) -#define spCOMPLEX 1 -#define spSEPARATED_COMPLEX_VECTORS 1 -#else -#define spCOMPLEX 0 /* instead of 1 */ -#define spSEPARATED_COMPLEX_VECTORS 0 -#endif #ifdef spINSIDE_SPARSE /* diff --git a/src/sparse13/spdefs.h b/src/sparse13/spdefs.h index f7977c77ad..78ae57ea8b 100644 --- a/src/sparse13/spdefs.h +++ b/src/sparse13/spdefs.h @@ -41,7 +41,6 @@ #ifdef lint #undef REAL -#undef spCOMPLEX #undef EXPANDABLE #undef TRANSLATE #undef INITIALIZE @@ -60,7 +59,6 @@ #undef DEBUG #define REAL YES -#define spCOMPLEX YES #define EXPANDABLE YES #define TRANSLATE YES #define INITIALIZE YES @@ -133,225 +131,7 @@ } /* Macro function that returns the approx absolute value of a complex number. */ -#if spCOMPLEX -#define ELEMENT_MAG(ptr) (ABS((ptr)->Real) + ABS((ptr)->Imag)) -#else #define ELEMENT_MAG(ptr) ((ptr)->Real < 0.0 ? -(ptr)->Real : (ptr)->Real) -#endif - -/* Complex assignment statements. */ -#define CMPLX_ASSIGN(to, from) \ - { \ - (to).Real = (from).Real; \ - (to).Imag = (from).Imag; \ - } -#define CMPLX_CONJ_ASSIGN(to, from) \ - { \ - (to).Real = (from).Real; \ - (to).Imag = -(from).Imag; \ - } -#define CMPLX_NEGATE_ASSIGN(to, from) \ - { \ - (to).Real = -(from).Real; \ - (to).Imag = -(from).Imag; \ - } -#define CMPLX_CONJ_NEGATE_ASSIGN(to, from) \ - { \ - (to).Real = -(from).Real; \ - (to).Imag = (from).Imag; \ - } -#define CMPLX_CONJ(a) (a).Imag = -(a).Imag -#define CMPLX_NEGATE(a) \ - { \ - (a).Real = -(a).Real; \ - (a).Imag = -(a).Imag; \ - } - -/* Macro that returns the approx magnitude (L-1 norm) of a complex number. */ -#define CMPLX_1_NORM(a) (ABS((a).Real) + ABS((a).Imag)) - -/* Macro that returns the approx magnitude (L-infinity norm) of a complex. */ -#define CMPLX_INF_NORM(a) (MAX(ABS((a).Real), ABS((a).Imag))) - -/* Macro function that returns the magnitude (L-2 norm) of a complex number. */ -#define CMPLX_2_NORM(a) (sqrt((a).Real * (a).Real + (a).Imag * (a).Imag)) - -/* Macro function that performs complex addition. */ -#define CMPLX_ADD(to, from_a, from_b) \ - { \ - (to).Real = (from_a).Real + (from_b).Real; \ - (to).Imag = (from_a).Imag + (from_b).Imag; \ - } - -/* Macro function that performs complex subtraction. */ -#define CMPLX_SUBT(to, from_a, from_b) \ - { \ - (to).Real = (from_a).Real - (from_b).Real; \ - (to).Imag = (from_a).Imag - (from_b).Imag; \ - } - -/* Macro function that is equivalent to += operator for complex numbers. */ -#define CMPLX_ADD_ASSIGN(to, from) \ - { \ - (to).Real += (from).Real; \ - (to).Imag += (from).Imag; \ - } - -/* Macro function that is equivalent to -= operator for complex numbers. */ -#define CMPLX_SUBT_ASSIGN(to, from) \ - { \ - (to).Real -= (from).Real; \ - (to).Imag -= (from).Imag; \ - } - -/* Macro function that multiplies a complex number by a scalar. */ -#define SCLR_MULT(to, sclr, cmplx) \ - { \ - (to).Real = (sclr) * (cmplx).Real; \ - (to).Imag = (sclr) * (cmplx).Imag; \ - } - -/* Macro function that multiply-assigns a complex number by a scalar. */ -#define SCLR_MULT_ASSIGN(to, sclr) \ - { \ - (to).Real *= (sclr); \ - (to).Imag *= (sclr); \ - } - -/* Macro function that multiplies two complex numbers. */ -#define CMPLX_MULT(to, from_a, from_b) \ - { \ - (to).Real = (from_a).Real * (from_b).Real - (from_a).Imag * (from_b).Imag; \ - (to).Imag = (from_a).Real * (from_b).Imag + (from_a).Imag * (from_b).Real; \ - } - -/* Macro function that implements to *= from for complex numbers. */ -#define CMPLX_MULT_ASSIGN(to, from) \ - { \ - RealNumber to_real_ = (to).Real; \ - (to).Real = to_real_ * (from).Real - (to).Imag * (from).Imag; \ - (to).Imag = to_real_ * (from).Imag + (to).Imag * (from).Real; \ - } - -/* Macro function that multiplies two complex numbers, the first of which is - * conjugated. */ -#define CMPLX_CONJ_MULT(to, from_a, from_b) \ - { \ - (to).Real = (from_a).Real * (from_b).Real + (from_a).Imag * (from_b).Imag; \ - (to).Imag = (from_a).Real * (from_b).Imag - (from_a).Imag * (from_b).Real; \ - } - -/* Macro function that multiplies two complex numbers and then adds them - * to another. to = add + mult_a * mult_b */ -#define CMPLX_MULT_ADD(to, mult_a, mult_b, add) \ - { \ - (to).Real = (mult_a).Real * (mult_b).Real - (mult_a).Imag * (mult_b).Imag + (add).Real; \ - (to).Imag = (mult_a).Real * (mult_b).Imag + (mult_a).Imag * (mult_b).Real + (add).Imag; \ - } - -/* Macro function that subtracts the product of two complex numbers from - * another. to = subt - mult_a * mult_b */ -#define CMPLX_MULT_SUBT(to, mult_a, mult_b, subt) \ - { \ - (to).Real = (subt).Real - (mult_a).Real * (mult_b).Real + (mult_a).Imag * (mult_b).Imag; \ - (to).Imag = (subt).Imag - (mult_a).Real * (mult_b).Imag - (mult_a).Imag * (mult_b).Real; \ - } - -/* Macro function that multiplies two complex numbers and then adds them - * to another. to = add + mult_a* * mult_b where mult_a* represents mult_a - * conjugate. */ -#define CMPLX_CONJ_MULT_ADD(to, mult_a, mult_b, add) \ - { \ - (to).Real = (mult_a).Real * (mult_b).Real + (mult_a).Imag * (mult_b).Imag + (add).Real; \ - (to).Imag = (mult_a).Real * (mult_b).Imag - (mult_a).Imag * (mult_b).Real + (add).Imag; \ - } - -/* Macro function that multiplies two complex numbers and then adds them - * to another. to += mult_a * mult_b */ -#define CMPLX_MULT_ADD_ASSIGN(to, from_a, from_b) \ - { \ - (to).Real += (from_a).Real * (from_b).Real - (from_a).Imag * (from_b).Imag; \ - (to).Imag += (from_a).Real * (from_b).Imag + (from_a).Imag * (from_b).Real; \ - } - -/* Macro function that multiplies two complex numbers and then subtracts them - * from another. */ -#define CMPLX_MULT_SUBT_ASSIGN(to, from_a, from_b) \ - { \ - (to).Real -= (from_a).Real * (from_b).Real - (from_a).Imag * (from_b).Imag; \ - (to).Imag -= (from_a).Real * (from_b).Imag + (from_a).Imag * (from_b).Real; \ - } - -/* Macro function that multiplies two complex numbers and then adds them - * to the destination. to += from_a* * from_b where from_a* represents from_a - * conjugate. */ -#define CMPLX_CONJ_MULT_ADD_ASSIGN(to, from_a, from_b) \ - { \ - (to).Real += (from_a).Real * (from_b).Real + (from_a).Imag * (from_b).Imag; \ - (to).Imag += (from_a).Real * (from_b).Imag - (from_a).Imag * (from_b).Real; \ - } - -/* Macro function that multiplies two complex numbers and then subtracts them - * from the destination. to -= from_a* * from_b where from_a* represents from_a - * conjugate. */ -#define CMPLX_CONJ_MULT_SUBT_ASSIGN(to, from_a, from_b) \ - { \ - (to).Real -= (from_a).Real * (from_b).Real + (from_a).Imag * (from_b).Imag; \ - (to).Imag -= (from_a).Real * (from_b).Imag - (from_a).Imag * (from_b).Real; \ - } - -/* - * Macro functions that provide complex division. - */ - -/* Complex division: to = num / den */ -#define CMPLX_DIV(to, num, den) \ - { \ - RealNumber r_, s_; \ - if (((den).Real >= (den).Imag AND(den).Real > -(den).Imag) OR((den).Real < (den).Imag AND(den).Real <= -(den).Imag)) { \ - r_ = (den).Imag / (den).Real; \ - s_ = (den).Real + r_ * (den).Imag; \ - (to).Real = ((num).Real + r_ * (num).Imag) / s_; \ - (to).Imag = ((num).Imag - r_ * (num).Real) / s_; \ - } else { \ - r_ = (den).Real / (den).Imag; \ - s_ = (den).Imag + r_ * (den).Real; \ - (to).Real = (r_ * (num).Real + (num).Imag) / s_; \ - (to).Imag = (r_ * (num).Imag - (num).Real) / s_; \ - } \ - } - -/* Complex division and assignment: num /= den */ -#define CMPLX_DIV_ASSIGN(num, den) \ - { \ - RealNumber r_, s_, t_; \ - if (((den).Real >= (den).Imag AND(den).Real > -(den).Imag) OR((den).Real < (den).Imag AND(den).Real <= -(den).Imag)) { \ - r_ = (den).Imag / (den).Real; \ - s_ = (den).Real + r_ * (den).Imag; \ - t_ = ((num).Real + r_ * (num).Imag) / s_; \ - (num).Imag = ((num).Imag - r_ * (num).Real) / s_; \ - (num).Real = t_; \ - } else { \ - r_ = (den).Real / (den).Imag; \ - s_ = (den).Imag + r_ * (den).Real; \ - t_ = (r_ * (num).Real + (num).Imag) / s_; \ - (num).Imag = (r_ * (num).Imag - (num).Real) / s_; \ - (num).Real = t_; \ - } \ - } - -/* Complex reciprocation: to = 1.0 / den */ -#define CMPLX_RECIPROCAL(to, den) \ - { \ - RealNumber r_; \ - if (((den).Real >= (den).Imag AND(den).Real > -(den).Imag) OR((den).Real < (den).Imag AND(den).Real <= -(den).Imag)) { \ - r_ = (den).Imag / (den).Real; \ - (to).Imag = -r_ * ((to).Real = 1.0 / ((den).Real + r_ * (den).Imag)); \ - } else { \ - r_ = (den).Real / (den).Imag; \ - (to).Real = -r_ * ((to).Imag = -1.0 / ((den).Imag + r_ * (den).Real)); \ - } \ - } /* * ASSERT and ABORT @@ -421,26 +201,6 @@ typedef spREAL RealNumber, *RealVector; -/* - * COMPLEX NUMBER DATA STRUCTURE - * - * >>> Structure fields: - * Real (RealNumber) - * The real portion of the number. Real must be the first - * field in this structure. - * Imag (RealNumber) - * The imaginary portion of the number. This field must follow - * immediately after Real. - */ - -/* Begin `ComplexNumber'. */ - -typedef struct -{ - RealNumber Real; - RealNumber Imag; -} ComplexNumber, *ComplexVector; - /* * MATRIX ELEMENT DATA STRUCTURE * @@ -455,11 +215,6 @@ typedef struct * Real (RealNumber) * The real portion of the value of the element. Real must be the first * field in this structure. - * Imag (RealNumber) - * The imaginary portion of the value of the element. If the matrix - * routines are not compiled to handle complex matrices, then this - * field does not exist. If it exists, it must follow immediately after - * Real. * Row (int) * The row number of the element. * Col (int) @@ -488,9 +243,6 @@ typedef struct struct MatrixElement { RealNumber Real; -#if spCOMPLEX - RealNumber Imag; -#endif int Row; int Col; struct MatrixElement* NextInRow; diff --git a/src/sparse13/spfactor.cpp b/src/sparse13/spfactor.cpp index c3f960f6f4..f01c612deb 100644 --- a/src/sparse13/spfactor.cpp +++ b/src/sparse13/spfactor.cpp @@ -13,7 +13,6 @@ * spPartition * * >>> Other functions contained in this file: - * FactorComplexMatrix CreateInternalVectors * CountMarkowitz MarkowitzProducts * SearchForPivot SearchForSingleton * QuicklySearchDiagonal SearchDiagonal @@ -21,7 +20,7 @@ * FindBiggestInColExclude ExchangeRowsAndCols * spcRowExchange spcColExchange * ExchangeColElements ExchangeRowElements - * RealRowColElimination ComplexRowColElimination + * RealRowColElimination * UpdateMarkowitzNumbers CreateFillin * MatrixIsSingular ZeroPivot * WriteStatus @@ -43,11 +42,6 @@ * or implied warranty. */ -#ifndef lint -static char copyright[] = "Sparse1.3: Copyright (c) 1985,86,87,88 by Kenneth S. Kundert"; -static char RCSid[] = "@(#)$Header$"; -#endif - /* * IMPORTS * @@ -67,7 +61,6 @@ static char RCSid[] = "@(#)$Header$"; #include /* avoid "declared implicitly `extern' and later `static' " warnings. */ -static int FactorComplexMatrix(MatrixPtr Matrix); static void CreateInternalVectors(MatrixPtr Matrix); static void CountMarkowitz(MatrixPtr Matrix, RealVector RHS, int Step); static void MarkowitzProducts(MatrixPtr Matrix, int Step); @@ -82,7 +75,6 @@ static void ExchangeRowsAndCols(MatrixPtr Matrix, ElementPtr pPivot, int Step); static void ExchangeColElements(MatrixPtr Matrix, int Row1, ElementPtr Element1, int Row2, ElementPtr Element2, int Column); static void ExchangeRowElements(MatrixPtr Matrix, int Col1, ElementPtr Element1, int Col2, ElementPtr Element2, int Row); static void RealRowColElimination(MatrixPtr Matrix, ElementPtr pPivot); -static void ComplexRowColElimination(MatrixPtr Matrix, ElementPtr pPivot); static void UpdateMarkowitzNumbers(MatrixPtr Matrix, ElementPtr pPivot); static ElementPtr CreateFillin(MatrixPtr Matrix, int Row, int Col); static int MatrixIsSingular(MatrixPtr Matrix, int Step); @@ -215,10 +207,7 @@ int spOrderAndFactor(char* eMatrix, RealNumber* RHS, RealNumber RelThreshold, Re pPivot = Matrix->Diag[Step]; LargestInCol = FindLargestInCol(pPivot->NextInCol); if ((LargestInCol * RelThreshold < ELEMENT_MAG(pPivot))) { - if (Matrix->Complex) - ComplexRowColElimination(Matrix, pPivot); - else - RealRowColElimination(Matrix, pPivot); + RealRowColElimination(Matrix, pPivot); } else { ReorderingRequired = YES; break; /* for loop */ @@ -265,10 +254,7 @@ int spOrderAndFactor(char* eMatrix, RealNumber* RHS, RealNumber RelThreshold, Re return MatrixIsSingular(Matrix, Step); ExchangeRowsAndCols(Matrix, pPivot, Step); - if (Matrix->Complex) - ComplexRowColElimination(Matrix, pPivot); - else - RealRowColElimination(Matrix, pPivot); + RealRowColElimination(Matrix, pPivot); if (Matrix->Error >= spFATAL) return Matrix->Error; @@ -335,10 +321,6 @@ int spFactor(char* eMatrix) } if (NOT Matrix->Partitioned) spPartition(eMatrix, spDEFAULT_PARTITION); -#if spCOMPLEX - if (Matrix->Complex) - return FactorComplexMatrix(Matrix); -#endif #if REAL Size = Matrix->Size; @@ -412,117 +394,6 @@ int spFactor(char* eMatrix) #endif /* REAL */ } -#if spCOMPLEX -/* - * FACTOR COMPLEX MATRIX - * - * This routine is the companion routine to spFactor(), it - * handles complex matrices. It is otherwise identical. - * - * >>> Returned: - * The error code is returned. Possible errors are listed below. - * - * >>> Arguments: - * Matrix (char *) - * Pointer to matrix. - * - * >>> Possible errors: - * spSINGULAR - * Error is cleared in this function. - */ - -static int FactorComplexMatrix(MatrixPtr Matrix) -{ - ElementPtr pElement; - ElementPtr pColumn; - int Step, Size; - ComplexNumber Mult, Pivot; - - /* Begin `FactorComplexMatrix'. */ - ASSERT(Matrix->Complex); - - Size = Matrix->Size; - pElement = Matrix->Diag[1]; - if (ELEMENT_MAG(pElement) == 0.0) - return ZeroPivot(Matrix, 1); - /* Cmplx expr: *pPivot = 1.0 / *pPivot. */ - CMPLX_RECIPROCAL(*pElement, *pElement); - - /* Start factorization. */ - for (Step = 2; Step <= Size; Step++) { - if (Matrix->DoCmplxDirect[Step]) { /* Update column using direct addressing scatter-gather. */ - ComplexNumber* Dest; - Dest = (ComplexNumber*)Matrix->Intermediate; - - /* Scatter. */ - pElement = Matrix->FirstInCol[Step]; - while (pElement != NULL) { - Dest[pElement->Row] = *(ComplexNumber*)pElement; - pElement = pElement->NextInCol; - } - - /* Update column. */ - pColumn = Matrix->FirstInCol[Step]; - while (pColumn->Row < Step) { - pElement = Matrix->Diag[pColumn->Row]; - /* Cmplx expr: Mult = Dest[pColumn->Row] * (1.0 / *pPivot). */ - CMPLX_MULT(Mult, Dest[pColumn->Row], *pElement); - CMPLX_ASSIGN(*pColumn, Mult); - while ((pElement = pElement->NextInCol) != NULL) { /* Cmplx expr: Dest[pElement->Row] -= Mult * pElement */ - CMPLX_MULT_SUBT_ASSIGN(Dest[pElement->Row], Mult, *pElement); - } - pColumn = pColumn->NextInCol; - } - - /* Gather. */ - pElement = Matrix->Diag[Step]->NextInCol; - while (pElement != NULL) { - *(ComplexNumber*)pElement = Dest[pElement->Row]; - pElement = pElement->NextInCol; - } - - /* Check for singular matrix. */ - Pivot = Dest[Step]; - if (CMPLX_1_NORM(Pivot) == 0.0) - return ZeroPivot(Matrix, Step); - CMPLX_RECIPROCAL(*Matrix->Diag[Step], Pivot); - } else { /* Update column using direct addressing scatter-gather. */ - ComplexNumber** pDest; - pDest = (ComplexNumber**)Matrix->Intermediate; - - /* Scatter. */ - pElement = Matrix->FirstInCol[Step]; - while (pElement != NULL) { - pDest[pElement->Row] = (ComplexNumber*)pElement; - pElement = pElement->NextInCol; - } - - /* Update column. */ - pColumn = Matrix->FirstInCol[Step]; - while (pColumn->Row < Step) { - pElement = Matrix->Diag[pColumn->Row]; - /* Cmplx expr: Mult = *pDest[pColumn->Row] * (1.0 / *pPivot). */ - CMPLX_MULT(Mult, *pDest[pColumn->Row], *pElement); - CMPLX_ASSIGN(*pDest[pColumn->Row], Mult); - while ((pElement = pElement->NextInCol) != NULL) { /* Cmplx expr: *pDest[pElement->Row] -= Mult * pElement */ - CMPLX_MULT_SUBT_ASSIGN(*pDest[pElement->Row], Mult, *pElement); - } - pColumn = pColumn->NextInCol; - } - - /* Check for singular matrix. */ - pElement = Matrix->Diag[Step]; - if (ELEMENT_MAG(pElement) == 0.0) - return ZeroPivot(Matrix, Step); - CMPLX_RECIPROCAL(*pElement, *pElement); - } - } - - Matrix->Factored = YES; - return (Matrix->Error = spOKAY); -} -#endif /* spCOMPLEX */ - /* * PARTITION MATRIX * @@ -566,7 +437,7 @@ void spPartition(char* eMatrix, int Mode) ElementPtr pElement, pColumn; int Step, Size; int *Nc, *No, *Nm; - BOOLEAN *DoRealDirect, *DoCmplxDirect; + BOOLEAN *DoRealDirect; /* Begin `spPartition'. */ ASSERT(IS_SPARSE(Matrix)); @@ -574,7 +445,6 @@ void spPartition(char* eMatrix, int Mode) return; Size = Matrix->Size; DoRealDirect = Matrix->DoRealDirect; - DoCmplxDirect = Matrix->DoCmplxDirect; Matrix->Partitioned = YES; /* If partition is specified by the user, this is easy. */ @@ -584,18 +454,12 @@ void spPartition(char* eMatrix, int Mode) for (Step = 1; Step <= Size; Step++) #if REAL DoRealDirect[Step] = YES; -#endif -#if spCOMPLEX - DoCmplxDirect[Step] = YES; #endif return; } else if (Mode == spINDIRECT_PARTITION) { for (Step = 1; Step <= Size; Step++) #if REAL DoRealDirect[Step] = NO; -#endif -#if spCOMPLEX - DoCmplxDirect[Step] = NO; #endif return; } else @@ -641,9 +505,6 @@ void spPartition(char* eMatrix, int Mode) #if REAL DoRealDirect[Step] = (Nm[Step] + No[Step] > 3 * Nc[Step] - 2 * Nm[Step]); -#endif -#if spCOMPLEX - DoCmplxDirect[Step] = (Nm[Step] + No[Step] > 7 * Nc[Step] - 4 * Nm[Step]); #endif } @@ -703,25 +564,12 @@ static void CreateInternalVectors(MatrixPtr Matrix) Matrix->Error = spNO_MEMORY; } #endif -#if spCOMPLEX - if (Matrix->DoCmplxDirect == NULL) { - if ((Matrix->DoCmplxDirect = ALLOC(BOOLEAN, Size + 1)) == NULL) - Matrix->Error = spNO_MEMORY; - } -#endif /* Create Intermediate vectors for use in MatrixSolve. */ -#if spCOMPLEX - if (Matrix->Intermediate == NULL) { - if ((Matrix->Intermediate = ALLOC(RealNumber, 2 * (Size + 1))) == NULL) - Matrix->Error = spNO_MEMORY; - } -#else if (Matrix->Intermediate == NULL) { if ((Matrix->Intermediate = ALLOC(RealNumber, Size + 1)) == NULL) Matrix->Error = spNO_MEMORY; } -#endif if (Matrix->Error != spNO_MEMORY) Matrix->InternalVectorsAllocated = YES; @@ -765,17 +613,8 @@ static void CountMarkowitz(MatrixPtr Matrix, RealVector RHS, int Step) /* Correct array pointer for ARRAY_OFFSET. */ #if NOT ARRAY_OFFSET -#if spSEPARATED_COMPLEX_VECTORS OR NOT spCOMPLEX if (RHS != NULL) --RHS; -#else - if (RHS != NULL) { - if (Matrix->Complex) - RHS -= 2; - else - --RHS; - } -#endif #endif /* Generate MarkowitzRow Count for each row. */ @@ -793,19 +632,9 @@ static void CountMarkowitz(MatrixPtr Matrix, RealVector RHS, int Step) /* Include nonzero elements in the RHS vector. */ ExtRow = Matrix->IntToExtRowMap[I]; -#if spSEPARATED_COMPLEX_VECTORS OR NOT spCOMPLEX if (RHS != NULL) if (RHS[ExtRow] != 0.0) Count++; -#else - if (RHS != NULL) { - if (Matrix->Complex) { - if ((RHS[2 * ExtRow] != 0.0) OR(RHS[2 * ExtRow + 1] != 0.0)) - Count++; - } else if (RHS[I] != 0.0) - Count++; - } -#endif Matrix->MarkowitzRow[I] = Count; } @@ -2015,10 +1844,6 @@ void spcRowExchange(MatrixPtr Matrix, int Row1, int Row2) SWAP(int, Matrix->MarkowitzRow[Row1], Matrix->MarkowitzRow[Row2]); SWAP(ElementPtr, Matrix->FirstInRow[Row1], Matrix->FirstInRow[Row2]); SWAP(int, Matrix->IntToExtRowMap[Row1], Matrix->IntToExtRowMap[Row2]); -#if TRANSLATE - Matrix->ExtToIntRowMap[Matrix->IntToExtRowMap[Row1]] = Row1; - Matrix->ExtToIntRowMap[Matrix->IntToExtRowMap[Row2]] = Row2; -#endif return; } @@ -2102,10 +1927,6 @@ void spcColExchange(MatrixPtr Matrix, int Col1, int Col2) SWAP(int, Matrix->MarkowitzCol[Col1], Matrix->MarkowitzCol[Col2]); SWAP(ElementPtr, Matrix->FirstInCol[Col1], Matrix->FirstInCol[Col2]); SWAP(int, Matrix->IntToExtColMap[Col1], Matrix->IntToExtColMap[Col2]); -#if TRANSLATE - Matrix->ExtToIntColMap[Matrix->IntToExtColMap[Col1]] = Col1; - Matrix->ExtToIntColMap[Matrix->IntToExtColMap[Col2]] = Col2; -#endif return; } @@ -2454,57 +2275,6 @@ static void RealRowColElimination(MatrixPtr Matrix, ElementPtr pPivot) * spNO_MEMORY */ -static void ComplexRowColElimination(MatrixPtr Matrix, ElementPtr pPivot) -{ -#if spCOMPLEX - ElementPtr pSub; - int Row; - ElementPtr pLower, pUpper; - - /* Begin `ComplexRowColElimination'. */ - - /* Test for zero pivot. */ - if (ELEMENT_MAG(pPivot) == 0.0) { - (void)MatrixIsSingular(Matrix, pPivot->Row); - return; - } - CMPLX_RECIPROCAL(*pPivot, *pPivot); - - pUpper = pPivot->NextInRow; - while (pUpper != NULL) { - /* Calculate upper triangular element. */ - /* Cmplx expr: *pUpper = *pUpper * (1.0 / *pPivot). */ - CMPLX_MULT_ASSIGN(*pUpper, *pPivot); - - pSub = pUpper->NextInCol; - pLower = pPivot->NextInCol; - while (pLower != NULL) { - Row = pLower->Row; - - /* Find element in row that lines up with current lower triangular element. */ - while (pSub != NULL AND pSub->Row < Row) - pSub = pSub->NextInCol; - - /* Test to see if desired element was not found, if not, create fill-in. */ - if (pSub == NULL OR pSub->Row > Row) { - pSub = CreateFillin(Matrix, Row, pUpper->Col); - if (pSub == NULL) { - Matrix->Error = spNO_MEMORY; - return; - } - } - - /* Cmplx expr: pElement -= *pUpper * pLower. */ - CMPLX_MULT_SUBT_ASSIGN(*pSub, *pUpper, *pLower); - pSub = pSub->NextInCol; - pLower = pLower->NextInCol; - } - pUpper = pUpper->NextInRow; - } - return; -#endif /* spCOMPLEX */ -} - /* * UPDATE MARKOWITZ NUMBERS * diff --git a/src/sparse13/spmatrix.h b/src/sparse13/spmatrix.h index a923809ef8..ce5878c324 100644 --- a/src/sparse13/spmatrix.h +++ b/src/sparse13/spmatrix.h @@ -227,11 +227,6 @@ struct spTemplate { */ /* Begin function declarations. */ - -#if defined(__STDC__) || defined(__cplusplus) - -/* For compilers that understand function prototypes. */ - extern void spClear(char*); extern spREAL spCondition(char*, spREAL, int*); extern char* spCreate(int, int, int*); @@ -260,7 +255,6 @@ extern void spPrint(char*, int, int, int); extern spREAL spPseudoCondition(char*); extern spREAL spRoundoff(char*, spREAL); extern void spScale(char*, spREAL[], spREAL[]); -extern void spSetComplex(char*); extern void spSetReal(char*); extern void spStripFills(char*); extern void spWhereSingular(char*, int*, int*); @@ -273,48 +267,4 @@ extern void spMultTransposed(char* eMatrix, spREAL* RHS, spREAL* Solution, std:: extern void spSolve(char* eMatrix, spREAL* RHS, spREAL* Solution, std::optional iRHS = std::nullopt, std::optional iSolution = std::nullopt); extern void spSolveTransposed(char*, spREAL*, spREAL*, std::optional = std::nullopt, std::optional = std::nullopt); -#else /* NOT defined(__STDC__) */ - -/* For compilers that do not understand function prototypes. */ - -extern void spClear(); -extern spREAL spCondition(); -extern char* spCreate(); -extern void spDeleteRowAndCol(); -extern void spDestroy(); -extern void spDeterminant(); -extern int spElementCount(); -extern int spError(); -extern int spFactor(); -extern int spFileMatrix(); -extern int spFileStats(); -extern int spFileVector(); -extern int spFillinCount(); -extern int spGetAdmittance(); -extern spREAL* spGetElement(char*, int, int); -extern char* spGetInitInfo(); -extern int spGetOnes(); -extern int spGetQuad(); -extern int spGetSize(); -extern int spInitialize(); -extern void spInstallInitInfo(); -extern spREAL spLargestElement(); -extern void spMNA_Preorder(); -extern void spMultiply(); -extern void spMultTransposed(); -extern spREAL spNorm(); -extern int spOrderAndFactor(); -extern void spPartition(); -extern void spPrint(); -extern spREAL spPseudoCondition(); -extern spREAL spRoundoff(); -extern void spScale(); -extern void spSetComplex(); -extern void spSetReal(); -extern void spSolve(); -extern void spSolveTransposed(); -extern void spStripFills(); -extern void spWhereSingular(); -#endif /* defined(__STDC__) */ - #endif /* spOKAY */ diff --git a/src/sparse13/spoutput.cpp b/src/sparse13/spoutput.cpp index 534025bcd2..5c33082f3e 100644 --- a/src/sparse13/spoutput.cpp +++ b/src/sparse13/spoutput.cpp @@ -33,11 +33,6 @@ * or implied warranty. */ -#ifndef lint -static char copyright[] = "Sparse1.3: Copyright (c) 1985,86,87,88 by Kenneth S. Kundert"; -static char RCSid[] = "$Header$"; -#endif - /* * IMPORTS * @@ -143,11 +138,7 @@ void spPrint(char* eMatrix, int PrintReordered, int Data, int Header) Size = Matrix->Size; /* Create a packed external to internal row and column translation array. */ -#if TRANSLATE - Top = Matrix->AllocatedExtSize; -#else Top = Matrix->AllocatedSize; -#endif CALLOC(PrintOrdToIntRowMap, int, Top + 1); CALLOC(PrintOrdToIntColMap, int, Top + 1); if (PrintOrdToIntRowMap == NULL OR PrintOrdToIntColMap == NULL) { @@ -286,19 +277,6 @@ void spPrint(char* eMatrix, int PrintReordered, int Data, int Header) } printf("\n"); -#if spCOMPLEX - if (Matrix->Complex AND Data) { - printf(" "); - for (J = StartCol; J <= StopCol; J++) { - if (pImagElements[J - StartCol] != NULL) { - printf(" %8.2lgj", - (double)pImagElements[J - StartCol]->Imag); - } else - printf(" "); - } - printf("\n"); - } -#endif /* spCOMPLEX */ } /* Calculate index of first column in next group. */ @@ -440,31 +418,6 @@ int spFileMatrix(char* eMatrix, char* File, char* Label, int Reordered, int Data return 0; } -#if spCOMPLEX - if (Data AND Matrix->Complex) { - for (I = 1; I <= Size; I++) { - pElement = Matrix->FirstInCol[I]; - while (pElement != NULL) { - if (Reordered) { - Row = pElement->Row; - Col = I; - } else { - Row = Matrix->IntToExtRowMap[pElement->Row]; - Col = Matrix->IntToExtColMap[I]; - } - Err = fprintf(pMatrixFile, "%d\t%d\t%-.15lg\t%-.15lg\n", - Row, Col, (double)pElement->Real, (double)pElement->Imag); - if (Err < 0) - return 0; - pElement = pElement->NextInCol; - } - } - /* Output terminator, a line of zeros. */ - if (Header) - if (fprintf(pMatrixFile, "0\t0\t0.0\t0.0\n") < 0) - return 0; - } -#endif /* spCOMPLEX */ #if REAL if (Data AND NOT Matrix->Complex) { @@ -511,11 +464,9 @@ int spFileMatrix(char* eMatrix, char* File, char* Label, int Reordered, int Data * File (char *) * Name of file into which matrix is to be written. * RHS (RealNumber []) - * Right-hand side vector. This is only the real portion if - * spSEPARATED_COMPLEX_VECTORS is true. + * Right-hand side vector. * iRHS (RealNumber []) - * Right-hand side vector, imaginary portion. Not necessary if matrix - * is real or if spSEPARATED_COMPLEX_VECTORS is set false. + * Right-hand side vector, imaginary portion. * * >>> Local variables: * pMatrixFile (FILE *) @@ -523,17 +474,12 @@ int spFileMatrix(char* eMatrix, char* File, char* Label, int Reordered, int Data * Size (int) * The size of the matrix. * - * >>> Obscure Macros - * IMAG_RHS - * Replaces itself with `, iRHS' if the options spCOMPLEX and - * spSEPARATED_COMPLEX_VECTORS are set, otherwise it disappears - * without a trace. */ int spFileVector(char* eMatrix, char* File, RealVector RHS, RealVector iRHS) { MatrixPtr Matrix = (MatrixPtr)eMatrix; - int I, Size, Err; + int I, Size; FILE* pMatrixFile; /* Begin `spFileVector'. */ @@ -545,44 +491,11 @@ int spFileVector(char* eMatrix, char* File, RealVector RHS, RealVector iRHS) /* Correct array pointers for ARRAY_OFFSET. */ #if NOT ARRAY_OFFSET -#if spCOMPLEX - if (Matrix->Complex) { -#if spSEPARATED_COMPLEX_VECTORS - ASSERT(iRHS != NULL) - --RHS; - --iRHS; -#else - RHS -= 2; -#endif - } else -#endif /* spCOMPLEX */ --RHS; #endif /* NOT ARRAY_OFFSET */ /* Output vector. */ Size = Matrix->Size; -#if spCOMPLEX - if (Matrix->Complex) { -#if spSEPARATED_COMPLEX_VECTORS - for (I = 1; I <= Size; I++) { - Err = fprintf(pMatrixFile, "%-.15lg\t%-.15lg\n", - (double)RHS[I], (double)iRHS[I]); - if (Err < 0) - return 0; - } -#else - for (I = 1; I <= Size; I++) { - Err = fprintf(pMatrixFile, "%-.15lg\t%-.15lg\n", - (double)RHS[2 * I], (double)RHS[2 * I + 1]); - if (Err < 0) - return 0; - } -#endif - } -#endif /* spCOMPLEX */ -#if REAL AND spCOMPLEX - else -#endif #if REAL { for (I = 1; I <= Size; I++) { @@ -656,10 +569,7 @@ int spFileStats(char* eMatrix, char* File, char* Label) fprintf(pStatsFile, "Matrix has not been factored.\n"); fprintf(pStatsFile, "||| Starting new matrix |||\n"); fprintf(pStatsFile, "%s\n", Label); - if (Matrix->Complex) - fprintf(pStatsFile, "Matrix is complex.\n"); - else - fprintf(pStatsFile, "Matrix is real.\n"); + fprintf(pStatsFile, "Matrix is real.\n"); fprintf(pStatsFile, " Size = %d\n", Size); /* Search matrix. */ diff --git a/src/sparse13/spsolve.cpp b/src/sparse13/spsolve.cpp index ee70d3b769..95bc4d436c 100644 --- a/src/sparse13/spsolve.cpp +++ b/src/sparse13/spsolve.cpp @@ -11,10 +11,6 @@ * >>> User accessible functions contained in this file: * spSolve * spSolveTransposed - * - * >>> Other functions contained in this file: - * SolveComplexMatrix - * SolveComplexTransposedMatrix */ /* @@ -33,11 +29,6 @@ * or implied warranty. */ -#ifndef lint -static char copyright[] = "Sparse1.3: Copyright (c) 1985,86,87,88 by Kenneth S. Kundert"; -static char RCSid[] = "@(#)$Header$"; -#endif - /* * IMPORTS * @@ -55,10 +46,6 @@ static char RCSid[] = "@(#)$Header$"; #include "spdefs.h" #include "spmatrix.h" -/* avoid "declared implicitly `extern' and later `static' " warnings. */ -static void SolveComplexMatrix(MatrixPtr Matrix, RealVector RHS, RealVector Solution, std::optional iRHS = std::nullopt, std::optional iSolution = std::nullopt); -static void SolveComplexTransposedMatrix(MatrixPtr Matrix, RealVector RHS, RealVector Solution, std::optional iRHS = std::nullopt, std::optional iSolution = std::nullopt); - /* * SOLVE MATRIX EQUATION * @@ -126,12 +113,6 @@ void spSolve(char* eMatrix, RealVector RHS, RealVector Solution, std::optionalComplex) { - SolveComplexMatrix(Matrix, RHS, Solution, iRHS, iSolution); - return; - } -#endif #if REAL Intermediate = Matrix->Intermediate; @@ -183,155 +164,6 @@ void spSolve(char* eMatrix, RealVector RHS, RealVector Solution, std::optional>> Arguments: - * Matrix (char *) - * Pointer to matrix. - * RHS (RealVector) - * RHS is the real portion of the input data array, the right hand - * side. This data is undisturbed and may be reused for other solves. - * Solution (RealVector) - * Solution is the real portion of the output data array. This routine - * is constructed such that RHS and Solution can be the same - * array. - * iRHS (RealVector) - * iRHS is the imaginary portion of the input data array, the right - * hand side. This data is undisturbed and may be reused for other solves. - * If spSEPARATED_COMPLEX_VECTOR is set false, there is no need to - * supply this array. - * iSolution (RealVector) - * iSolution is the imaginary portion of the output data array. This - * routine is constructed such that iRHS and iSolution can be - * the same array. If spSEPARATED_COMPLEX_VECTOR is set false, there is no - * need to supply this array. - * - * >>> Local variables: - * Intermediate (ComplexVector) - * Temporary storage for use in forward elimination and backward - * substitution. Commonly referred to as c, when the LU factorization - * equations are given as Ax = b, Lc = b, Ux = c. - * Local version of Matrix->Intermediate, which was created during - * the initial factorization in function CreateInternalVectors() in the - * matrix factorization module. - * pElement (ElementPtr) - * Pointer used to address elements in both the lower and upper triangle - * matrices. - * pExtOrder (int *) - * Pointer used to sequentially access each entry in IntToExtRowMap - * and IntToExtColMap arrays. Used to quickly scramble and unscramble - * RHS and Solution to account for row and column interchanges. - * pPivot (ElementPtr) - * Pointer that points to current pivot or diagonal element. - * Size (int) - * Size of matrix. Made local to reduce indirection. - * Temp (ComplexNumber) - * Temporary storage for entries in arrays. - */ - -static void SolveComplexMatrix(MatrixPtr Matrix, RealVector RHS, RealVector Solution, std::optional iRHS, std::optional iSolution) -{ - ElementPtr pElement; - ComplexVector Intermediate; - int I, *pExtOrder, Size; - ElementPtr pPivot; - ComplexVector ExtVector; - ComplexNumber Temp; - - /* Begin `SolveComplexMatrix'. */ - - Size = Matrix->Size; - Intermediate = (ComplexVector)Matrix->Intermediate; - -/* Correct array pointers for ARRAY_OFFSET. */ -#if NOT ARRAY_OFFSET -#if spSEPARATED_COMPLEX_VECTORS - --RHS; - --iRHS; - --Solution; - --iSolution; -#else - RHS -= 2; - Solution -= 2; -#endif -#endif - - /* Initialize Intermediate vector. */ - pExtOrder = &Matrix->IntToExtRowMap[Size]; - -#if spSEPARATED_COMPLEX_VECTORS - for (I = Size; I > 0; I--) { - Intermediate[I].Real = RHS[*(pExtOrder)]; - ASSERT(iRHS.has_value()); - Intermediate[I].Imag = iRHS.value()[*(pExtOrder--)]; - } -#else - ExtVector = (ComplexVector)RHS; - for (I = Size; I > 0; I--) - Intermediate[I] = ExtVector[*(pExtOrder--)]; -#endif - - /* Forward substitution. Solves Lc = b.*/ - for (I = 1; I <= Size; I++) { - Temp = Intermediate[I]; - - /* This step of the substitution is skipped if Temp equals zero. */ - if ((Temp.Real != 0.0) OR(Temp.Imag != 0.0)) { - pPivot = Matrix->Diag[I]; - /* Cmplx expr: Temp *= (1.0 / Pivot). */ - CMPLX_MULT_ASSIGN(Temp, *pPivot); - Intermediate[I] = Temp; - pElement = pPivot->NextInCol; - while (pElement != NULL) { - /* Cmplx expr: Intermediate[Element->Row] -= Temp * *Element. */ - CMPLX_MULT_SUBT_ASSIGN(Intermediate[pElement->Row], - Temp, *pElement); - pElement = pElement->NextInCol; - } - } - } - - /* Backward Substitution. Solves Ux = c.*/ - for (I = Size; I > 0; I--) { - Temp = Intermediate[I]; - pElement = Matrix->Diag[I]->NextInRow; - - while (pElement != NULL) { - /* Cmplx expr: Temp -= *Element * Intermediate[Element->Col]. */ - CMPLX_MULT_SUBT_ASSIGN(Temp, *pElement, Intermediate[pElement->Col]); - pElement = pElement->NextInRow; - } - Intermediate[I] = Temp; - } - - /* Unscramble Intermediate vector while placing data in to Solution vector. */ - pExtOrder = &Matrix->IntToExtColMap[Size]; - -#if spSEPARATED_COMPLEX_VECTORS - for (I = Size; I > 0; I--) { - Solution[*(pExtOrder)] = Intermediate[I].Real; - iSolution.value()[*(pExtOrder--)] = Intermediate[I].Imag; - } -#else - ExtVector = (ComplexVector)Solution; - for (I = Size; I > 0; I--) - ExtVector[*(pExtOrder--)] = Intermediate[I]; -#endif - - return; -} -#endif /* spCOMPLEX */ - #if TRANSPOSE /* * SOLVE TRANSPOSED MATRIX EQUATION @@ -402,13 +234,6 @@ void spSolveTransposed(char* eMatrix, RealVector RHS, RealVector Solution, std:: /* Begin `spSolveTransposed'. */ ASSERT(IS_VALID(Matrix) AND IS_FACTORED(Matrix)); -#if spCOMPLEX - if (Matrix->Complex) { - SolveComplexTransposedMatrix(Matrix, RHS, Solution, iRHS, iSolution); - return; - } -#endif - #if REAL Size = Matrix->Size; Intermediate = Matrix->Intermediate; @@ -457,156 +282,3 @@ void spSolveTransposed(char* eMatrix, RealVector RHS, RealVector Solution, std:: #endif /* REAL */ } #endif /* TRANSPOSE */ - -#if TRANSPOSE AND spCOMPLEX -/* - * SOLVE COMPLEX TRANSPOSED MATRIX EQUATION - * - * Performs forward elimination and back substitution to find the - * unknown vector from the RHS vector and transposed factored - * matrix. This routine is useful when performing sensitivity analysis - * on a circuit using the adjoint method. This routine assumes that - * the pivots are associated with the untransposed lower triangular - * (L) matrix and that the diagonal of the untransposed upper - * triangular (U) matrix consists of ones. - * - * >>> Arguments: - * Matrix (char *) - * Pointer to matrix. - * RHS (RealVector) - * RHS is the input data array, the right hand - * side. This data is undisturbed and may be reused for other solves. - * This vector is only the real portion if the matrix is complex and - * spSEPARATED_COMPLEX_VECTORS is set true. - * Solution (RealVector) - * Solution is the real portion of the output data array. This routine - * is constructed such that RHS and Solution can be the same array. - * This vector is only the real portion if the matrix is complex and - * spSEPARATED_COMPLEX_VECTORS is set true. - * iRHS (RealVector) - * iRHS is the imaginary portion of the input data array, the right - * hand side. This data is undisturbed and may be reused for other solves. - * If either spCOMPLEX or spSEPARATED_COMPLEX_VECTOR is set false, there - * is no need to supply this array. - * iSolution (RealVector) - * iSolution is the imaginary portion of the output data array. This - * routine is constructed such that iRHS and iSolution can be - * the same array. If spCOMPLEX or spSEPARATED_COMPLEX_VECTOR is set - * false, there is no need to supply this array. - * - * >>> Local variables: - * Intermediate (ComplexVector) - * Temporary storage for use in forward elimination and backward - * substitution. Commonly referred to as c, when the LU factorization - * equations are given as Ax = b, Lc = b, Ux = c. Local version of - * Matrix->Intermediate, which was created during - * the initial factorization in function CreateInternalVectors() in the - * matrix factorization module. - * pElement (ElementPtr) - * Pointer used to address elements in both the lower and upper triangle - * matrices. - * pExtOrder (int *) - * Pointer used to sequentially access each entry in IntToExtRowMap - * and IntToExtColMap arrays. Used to quickly scramble and unscramble - * RHS and Solution to account for row and column interchanges. - * pPivot (ElementPtr) - * Pointer that points to current pivot or diagonal element. - * Size (int) - * Size of matrix. Made local to reduce indirection. - * Temp (ComplexNumber) - * Temporary storage for entries in arrays. - * - */ - -static void -SolveComplexTransposedMatrix(MatrixPtr Matrix, RealVector RHS, RealVector Solution, std::optional iRHS, std::optional iSolution) -{ - ElementPtr pElement; - ComplexVector Intermediate; - int I, *pExtOrder, Size; - ComplexVector ExtVector; - ElementPtr pPivot; - ComplexNumber Temp; - - /* Begin `SolveComplexTransposedMatrix'. */ - - Size = Matrix->Size; - Intermediate = (ComplexVector)Matrix->Intermediate; - -/* Correct array pointers for ARRAY_OFFSET. */ -#if NOT ARRAY_OFFSET -#if spSEPARATED_COMPLEX_VECTORS - --RHS; - --iRHS; - --Solution; - --iSolution; -#else - RHS -= 2; - Solution -= 2; -#endif -#endif - - /* Initialize Intermediate vector. */ - pExtOrder = &Matrix->IntToExtColMap[Size]; - -#if spSEPARATED_COMPLEX_VECTORS - for (I = Size; I > 0; I--) { - Intermediate[I].Real = RHS[*(pExtOrder)]; - ASSERT(iRHS.has_value()); - Intermediate[I].Imag = iRHS.value()[*(pExtOrder--)]; - } -#else - ExtVector = (ComplexVector)RHS; - for (I = Size; I > 0; I--) - Intermediate[I] = ExtVector[*(pExtOrder--)]; -#endif - - /* Forward elimination. */ - for (I = 1; I <= Size; I++) { - Temp = Intermediate[I]; - - /* This step of the elimination is skipped if Temp equals zero. */ - if ((Temp.Real != 0.0) OR(Temp.Imag != 0.0)) { - pElement = Matrix->Diag[I]->NextInRow; - while (pElement != NULL) { - /* Cmplx expr: Intermediate[Element->Col] -= Temp * *Element. */ - CMPLX_MULT_SUBT_ASSIGN(Intermediate[pElement->Col], - Temp, *pElement); - pElement = pElement->NextInRow; - } - } - } - - /* Backward Substitution. */ - for (I = Size; I > 0; I--) { - pPivot = Matrix->Diag[I]; - Temp = Intermediate[I]; - pElement = pPivot->NextInCol; - - while (pElement != NULL) { - /* Cmplx expr: Temp -= Intermediate[Element->Row] * *Element. */ - CMPLX_MULT_SUBT_ASSIGN(Temp, Intermediate[pElement->Row], *pElement); - - pElement = pElement->NextInCol; - } - /* Cmplx expr: Intermediate = Temp * (1.0 / *pPivot). */ - CMPLX_MULT(Intermediate[I], Temp, *pPivot); - } - - /* Unscramble Intermediate vector while placing data in to Solution vector. */ - pExtOrder = &Matrix->IntToExtRowMap[Size]; - -#if spSEPARATED_COMPLEX_VECTORS - for (I = Size; I > 0; I--) { - Solution[*(pExtOrder)] = Intermediate[I].Real; - iSolution.value()[*(pExtOrder--)] = Intermediate[I].Imag; - } -#else - ExtVector = (ComplexVector)Solution; - for (I = Size; I > 0; I--) - ExtVector[*(pExtOrder--)] = Intermediate[I]; -#endif - - return; -} -#endif /* TRANSPOSE AND spCOMPLEX */ diff --git a/src/sparse13/sputils.cpp b/src/sparse13/sputils.cpp index 66984fef77..613d10216f 100644 --- a/src/sparse13/sputils.cpp +++ b/src/sparse13/sputils.cpp @@ -24,9 +24,6 @@ * >>> Other functions contained in this file: * CountTwins * SwapCols - * ScaleComplexMatrix - * ComplexMatrixMultiply - * ComplexCondition */ /* @@ -45,11 +42,6 @@ * or implied warranty. */ -#ifndef lint -static char copyright[] = "Sparse1.3: Copyright (c) 1985,86,87,88 by Kenneth S. Kundert"; -static char RCSid[] = "@(#)$Header$"; -#endif - /* * IMPORTS * @@ -76,10 +68,6 @@ extern ElementPtr spcFindElementInCol(MatrixPtr Matrix, ElementPtr* LastAddr, in /* avoid "declared implicitly `extern' and later `static' " warnings. */ static int CountTwins(MatrixPtr Matrix, int Col, ElementPtr* ppTwin1, ElementPtr* ppTwin2); static void SwapCols(MatrixPtr Matrix, ElementPtr pTwin1, ElementPtr pTwin2); -static void ScaleComplexMatrix(MatrixPtr Matrix, RealVector RHS_ScaleFactors, RealVector SolutionScaleFactors); -static void ComplexMatrixMultiply(MatrixPtr Matrix, RealVector RHS, RealVector Solution, std::optional iRHS = std::nullopt, std::optional iSolution = std::nullopt); -static void ComplexTransposedMatrixMultiply(MatrixPtr Matrix, RealVector RHS, RealVector Solution, std::optional iRHS = std::nullopt, std::optional iSolution = std::nullopt); -static RealNumber ComplexCondition(MatrixPtr Matrix, RealNumber NormOfMatrix, int* pError); #if MODIFIED_NODAL /* @@ -267,10 +255,6 @@ static void SwapCols(MatrixPtr Matrix, ElementPtr pTwin1, ElementPtr pTwin2) SWAP(ElementPtr, Matrix->FirstInCol[Col1], Matrix->FirstInCol[Col2]); SWAP(int, Matrix->IntToExtColMap[Col1], Matrix->IntToExtColMap[Col2]); -#if TRANSLATE - Matrix->ExtToIntColMap[Matrix->IntToExtColMap[Col2]] = Col2; - Matrix->ExtToIntColMap[Matrix->IntToExtColMap[Col1]] = Col1; -#endif Matrix->Diag[Col1] = pTwin2; Matrix->Diag[Col2] = pTwin1; @@ -348,13 +332,6 @@ void spScale(char* eMatrix, RealVector RHS_ScaleFactors, RealVector SolutionScal if (NOT Matrix->RowsLinked) spcLinkRows(Matrix); -#if spCOMPLEX - if (Matrix->Complex) { - ScaleComplexMatrix(Matrix, RHS_ScaleFactors, SolutionScaleFactors); - return; - } -#endif - #if REAL lSize = Matrix->Size; @@ -395,108 +372,6 @@ void spScale(char* eMatrix, RealVector RHS_ScaleFactors, RealVector SolutionScal } #endif /* SCALING */ -#if spCOMPLEX AND SCALING -/* - * SCALE COMPLEX MATRIX - * - * This function scales the matrix to enhance the possibility of - * finding a good pivoting order. Note that scaling enhances accuracy - * of the solution only if it affects the pivoting order, so it makes - * no sense to scale the matrix before spFactor(). If scaling is - * desired it should be done before spOrderAndFactor(). There - * are several things to take into account when choosing the scale - * factors. First, the scale factors are directly multiplied against - * the elements in the matrix. To prevent roundoff, each scale factor - * should be equal to an integer power of the number base of the - * machine. Since most machines operate in base two, scale factors - * should be a power of two. Second, the matrix should be scaled such - * that the matrix of element uncertainties is equilibrated. Third, - * this function multiplies the scale factors by the elements, so if - * one row tends to have uncertainties 1000 times smaller than the - * other rows, then its scale factor should be 1024, not 1/1024. - * Fourth, to save time, this function does not scale rows or columns - * if their scale factors are equal to one. Thus, the scale factors - * should be normalized to the most common scale factor. Rows and - * columns should be normalized separately. For example, if the size - * of the matrix is 100 and 10 rows tend to have uncertainties near - * 1e-6 and the remaining 90 have uncertainties near 1e-12, then the - * scale factor for the 10 should be 1/1,048,576 and the scale factors - * for the remaining 90 should be 1. Fifth, since this routine - * directly operates on the matrix, it is necessary to apply the scale - * factors to the RHS and Solution vectors. It may be easier to - * simply use spOrderAndFactor() on a scaled matrix to choose the - * pivoting order, and then throw away the matrix. Subsequent - * factorizations, performed with spFactor(), will not need to have - * the RHS and Solution vectors descaled. Lastly, this function - * should not be executed before the function spMNA_Preorder. - * - * >>> Arguments: - * Matrix (char *) - * Pointer to the matrix to be scaled. - * SolutionScaleFactors (RealVector) - * The array of Solution scale factors. These factors scale the columns. - * All scale factors are real valued. - * RHS_ScaleFactors (RealVector) - * The array of RHS scale factors. These factors scale the rows. - * All scale factors are real valued. - * - * >>> Local variables: - * lSize (int) - * Local version of the size of the matrix. - * pElement (ElementPtr) - * Pointer to an element in the matrix. - * pExtOrder (int *) - * Pointer into either IntToExtRowMap or IntToExtColMap vector. Used to - * compensate for any row or column swaps that have been performed. - * ScaleFactor (RealNumber) - * The scale factor being used on the current row or column. - */ - -static void ScaleComplexMatrix(MatrixPtr Matrix, RealVector RHS_ScaleFactors, RealVector SolutionScaleFactors) -{ - ElementPtr pElement; - int I, lSize, *pExtOrder; - RealNumber ScaleFactor; - - /* Begin `ScaleComplexMatrix'. */ - lSize = Matrix->Size; - -/* Correct pointers to arrays for ARRAY_OFFSET */ -#if NOT ARRAY_OFFSET - --RHS_ScaleFactors; - --SolutionScaleFactors; -#endif - - /* Scale Rows */ - pExtOrder = &Matrix->IntToExtRowMap[1]; - for (I = 1; I <= lSize; I++) { - if ((ScaleFactor = RHS_ScaleFactors[*(pExtOrder++)]) != 1.0) { - pElement = Matrix->FirstInRow[I]; - - while (pElement != NULL) { - pElement->Real *= ScaleFactor; - pElement->Imag *= ScaleFactor; - pElement = pElement->NextInRow; - } - } - } - - /* Scale Columns */ - pExtOrder = &Matrix->IntToExtColMap[1]; - for (I = 1; I <= lSize; I++) { - if ((ScaleFactor = SolutionScaleFactors[*(pExtOrder++)]) != 1.0) { - pElement = Matrix->FirstInCol[I]; - - while (pElement != NULL) { - pElement->Real *= ScaleFactor; - pElement->Imag *= ScaleFactor; - pElement = pElement->NextInCol; - } - } - } - return; -} -#endif /* SCALING AND spCOMPLEX */ #if MULTIPLICATION /* @@ -516,12 +391,10 @@ static void ScaleComplexMatrix(MatrixPtr Matrix, RealVector RHS_ScaleFactors, Re * Solution is the vector being multiplied by the matrix. * iRHS (RealVector) * iRHS is the imaginary portion of the right hand side. This is - * what is being solved for. This is only necessary if the matrix is - * complex and spSEPARATED_COMPLEX_VECTORS is true. + * what is being solved for. * iSolution (RealVector) * iSolution is the imaginary portion of the vector being multiplied - * by the matrix. This is only necessary if the matrix is - * complex and spSEPARATED_COMPLEX_VECTORS is true. + * by the matrix. * */ @@ -538,13 +411,6 @@ void spMultiply(char* eMatrix, RealVector RHS, RealVector Solution, std::optiona if (NOT Matrix->RowsLinked) spcLinkRows(Matrix); -#if spCOMPLEX - if (Matrix->Complex) { - ComplexMatrixMultiply(Matrix, RHS, Solution, iRHS, iSolution); - return; - } -#endif - #if REAL #if NOT ARRAY_OFFSET /* Correct array pointers for ARRAY_OFFSET. */ @@ -574,95 +440,6 @@ void spMultiply(char* eMatrix, RealVector RHS, RealVector Solution, std::optiona } #endif /* MULTIPLICATION */ -#if spCOMPLEX AND MULTIPLICATION -/* - * COMPLEX MATRIX MULTIPLICATION - * - * Multiplies matrix by solution vector to find source vector. - * Assumes matrix has not been factored. This routine can be used - * as a test to see if solutions are correct. - * - * >>> Arguments: - * Matrix (char *) - * Pointer to the matrix. - * RHS (RealVector) - * RHS is the right hand side. This is what is being solved for. - * This is only the real portion of the right-hand side if the matrix - * is complex and spSEPARATED_COMPLEX_VECTORS is set true. - * Solution (RealVector) - * Solution is the vector being multiplied by the matrix. This is only - * the real portion if the matrix is complex and - * spSEPARATED_COMPLEX_VECTORS is set true. - * iRHS (RealVector) - * iRHS is the imaginary portion of the right hand side. This is - * what is being solved for. This is only necessary if the matrix is - * complex and spSEPARATED_COMPLEX_VECTORS is true. - * iSolution (RealVector) - * iSolution is the imaginary portion of the vector being multiplied - * by the matrix. This is only necessary if the matrix is - * complex and spSEPARATED_COMPLEX_VECTORS is true. - * - */ - -static void ComplexMatrixMultiply(MatrixPtr Matrix, RealVector RHS, RealVector Solution, std::optional iRHS, std::optional iSolution) -{ - ElementPtr pElement; - ComplexVector Vector; - ComplexNumber Sum; - int I, *pExtOrder; - -/* Begin `ComplexMatrixMultiply'. */ - -/* Correct array pointers for ARRAY_OFFSET. */ -#if NOT ARRAY_OFFSET -#if spSEPARATED_COMPLEX_VECTORS - --RHS; - --iRHS; - --Solution; - --iSolution; -#else - RHS -= 2; - Solution -= 2; -#endif -#endif - - /* Initialize Intermediate vector with reordered Solution vector. */ - Vector = (ComplexVector)Matrix->Intermediate; - pExtOrder = &Matrix->IntToExtColMap[Matrix->Size]; - -#if spSEPARATED_COMPLEX_VECTORS - for (I = Matrix->Size; I > 0; I--) { - Vector[I].Real = Solution[*pExtOrder]; - ASSERT(iSolution.has_value()); - Vector[I].Imag = iSolution.value()[*(pExtOrder--)]; - } -#else - for (I = Matrix->Size; I > 0; I--) - Vector[I] = ((ComplexVector)Solution)[*(pExtOrder--)]; -#endif - - pExtOrder = &Matrix->IntToExtRowMap[Matrix->Size]; - for (I = Matrix->Size; I > 0; I--) { - pElement = Matrix->FirstInRow[I]; - Sum.Real = Sum.Imag = 0.0; - - while (pElement != NULL) { /* Cmplx expression : Sum += Element * Vector[Col] */ - CMPLX_MULT_ADD_ASSIGN(Sum, *pElement, Vector[pElement->Col]); - pElement = pElement->NextInRow; - } - -#if spSEPARATED_COMPLEX_VECTORS - RHS[*pExtOrder] = Sum.Real; - ASSERT(iRHS != std::nullopt); - iRHS.value()[*pExtOrder--] = Sum.Imag; -#else - ((ComplexVector)RHS)[*pExtOrder--] = Sum; -#endif - } - return; -} -#endif /* spCOMPLEX AND MULTIPLICATION */ - #if MULTIPLICATION AND TRANSPOSE /* * TRANSPOSED MATRIX MULTIPLICATION @@ -681,12 +458,10 @@ static void ComplexMatrixMultiply(MatrixPtr Matrix, RealVector RHS, RealVector S * Solution is the vector being multiplied by the matrix. * iRHS (RealVector) * iRHS is the imaginary portion of the right hand side. This is - * what is being solved for. This is only necessary if the matrix is - * complex and spSEPARATED_COMPLEX_VECTORS is true. + * what is being solved for. * iSolution (RealVector) * iSolution is the imaginary portion of the vector being multiplied - * by the matrix. This is only necessary if the matrix is - * complex and spSEPARATED_COMPLEX_VECTORS is true. + * by the matrix. * */ @@ -701,12 +476,6 @@ void spMultTransposed(char* eMatrix, RealVector RHS, RealVector Solution, std::o /* Begin `spMultTransposed'. */ ASSERT(IS_SPARSE(Matrix) AND NOT Matrix->Factored); -#if spCOMPLEX - if (Matrix->Complex) { - ComplexTransposedMatrixMultiply(Matrix, RHS, Solution, iRHS, iSolution); - return; - } -#endif #if REAL #if NOT ARRAY_OFFSET @@ -737,94 +506,6 @@ void spMultTransposed(char* eMatrix, RealVector RHS, RealVector Solution, std::o } #endif /* MULTIPLICATION AND TRANSPOSE */ -#if spCOMPLEX AND MULTIPLICATION AND TRANSPOSE -/* - * COMPLEX TRANSPOSED MATRIX MULTIPLICATION - * - * Multiplies transposed matrix by solution vector to find source vector. - * Assumes matrix has not been factored. This routine can be used - * as a test to see if solutions are correct. - * - * >>> Arguments: - * Matrix (char *) - * Pointer to the matrix. - * RHS (RealVector) - * RHS is the right hand side. This is what is being solved for. - * This is only the real portion of the right-hand side if the matrix - * is complex and spSEPARATED_COMPLEX_VECTORS is set true. - * Solution (RealVector) - * Solution is the vector being multiplied by the matrix. This is only - * the real portion if the matrix is complex and - * spSEPARATED_COMPLEX_VECTORS is set true. - * iRHS (RealVector) - * iRHS is the imaginary portion of the right hand side. This is - * what is being solved for. This is only necessary if the matrix is - * complex and spSEPARATED_COMPLEX_VECTORS is true. - * iSolution (RealVector) - * iSolution is the imaginary portion of the vector being multiplied - * by the matrix. This is only necessary if the matrix is - * complex and spSEPARATED_COMPLEX_VECTORS is true. - * - */ - -static void ComplexTransposedMatrixMultiply(MatrixPtr Matrix, RealVector RHS, RealVector Solution, std::optional iRHS, std::optional iSolution) -{ - ElementPtr pElement; - ComplexVector Vector; - ComplexNumber Sum; - int I, *pExtOrder; - -/* Begin `ComplexMatrixMultiply'. */ - -/* Correct array pointers for ARRAY_OFFSET. */ -#if NOT ARRAY_OFFSET -#if spSEPARATED_COMPLEX_VECTORS - --RHS; - --iRHS; - --Solution; - --iSolution; -#else - RHS -= 2; - Solution -= 2; -#endif -#endif - - /* Initialize Intermediate vector with reordered Solution vector. */ - Vector = (ComplexVector)Matrix->Intermediate; - pExtOrder = &Matrix->IntToExtRowMap[Matrix->Size]; - -#if spSEPARATED_COMPLEX_VECTORS - for (I = Matrix->Size; I > 0; I--) { - Vector[I].Real = Solution[*pExtOrder]; - ASSERT(iSolution.has_value()) - Vector[I].Imag = iSolution.value()[*(pExtOrder--)]; - } -#else - for (I = Matrix->Size; I > 0; I--) - Vector[I] = ((ComplexVector)Solution)[*(pExtOrder--)]; -#endif - - pExtOrder = &Matrix->IntToExtColMap[Matrix->Size]; - for (I = Matrix->Size; I > 0; I--) { - pElement = Matrix->FirstInCol[I]; - Sum.Real = Sum.Imag = 0.0; - - while (pElement != NULL) { /* Cmplx expression : Sum += Element * Vector[Row] */ - CMPLX_MULT_ADD_ASSIGN(Sum, *pElement, Vector[pElement->Row]); - pElement = pElement->NextInCol; - } - -#if spSEPARATED_COMPLEX_VECTORS - RHS[*pExtOrder] = Sum.Real; - ASSERT(iRHS != std::nullopt); - iRHS.value()[*pExtOrder--] = Sum.Imag; -#else - ((ComplexVector)RHS)[*pExtOrder--] = Sum; -#endif - } - return; -} -#endif /* spCOMPLEX AND MULTIPLICATION AND TRANSPOSE */ #if DETERMINANT /* @@ -859,8 +540,6 @@ static void ComplexTransposedMatrixMultiply(MatrixPtr Matrix, RealVector RHS, Re * number is scaled to be greater than or equal to 1.0 and less than 10.0. * * >>> Local variables: - * Norm (RealNumber) - * L-infinity norm of a complex number. * Size (int) * Local storage for Matrix->Size. * Temp (RealNumber) @@ -871,10 +550,6 @@ void spDeterminant(char* eMatrix, int* pExponent, RealNumber* pDeterminant, std: { MatrixPtr Matrix = (MatrixPtr)eMatrix; int I, Size; - RealNumber Norm, nr, ni; - ComplexNumber Pivot, cDeterminant; - -#define NORM(a) (nr = ABS((a).Real), ni = ABS((a).Imag), MAX(nr, ni)) /* Begin `spDeterminant'. */ ASSERT(IS_SPARSE(Matrix) AND IS_FACTORED(Matrix)); @@ -882,72 +557,12 @@ void spDeterminant(char* eMatrix, int* pExponent, RealNumber* pDeterminant, std: if (Matrix->Error == spSINGULAR) { *pDeterminant = 0.0; -#if spCOMPLEX - if (Matrix->Complex) { - ASSERT(piDeterminant != std::nullopt); - *piDeterminant.value() = 0.0; - } -#endif return; } Size = Matrix->Size; I = 0; -#if spCOMPLEX - if (Matrix->Complex) /* Complex Case. */ - { - cDeterminant.Real = 1.0; - cDeterminant.Imag = 0.0; - - while (++I <= Size) { - CMPLX_RECIPROCAL(Pivot, *Matrix->Diag[I]); - CMPLX_MULT_ASSIGN(cDeterminant, Pivot); - - /* Scale Determinant. */ - Norm = NORM(cDeterminant); - if (Norm != 0.0) { - while (Norm >= 1.0e12) { - cDeterminant.Real *= 1.0e-12; - cDeterminant.Imag *= 1.0e-12; - *pExponent += 12; - Norm = NORM(cDeterminant); - } - while (Norm < 1.0e-12) { - cDeterminant.Real *= 1.0e12; - cDeterminant.Imag *= 1.0e12; - *pExponent -= 12; - Norm = NORM(cDeterminant); - } - } - } - - /* Scale Determinant again, this time to be between 1.0 <= x < 10.0. */ - Norm = NORM(cDeterminant); - if (Norm != 0.0) { - while (Norm >= 10.0) { - cDeterminant.Real *= 0.1; - cDeterminant.Imag *= 0.1; - (*pExponent)++; - Norm = NORM(cDeterminant); - } - while (Norm < 1.0) { - cDeterminant.Real *= 10.0; - cDeterminant.Imag *= 10.0; - (*pExponent)--; - Norm = NORM(cDeterminant); - } - } - if (Matrix->NumberOfInterchangesIsOdd) - CMPLX_NEGATE(cDeterminant); - - *pDeterminant = cDeterminant.Real; - *piDeterminant.value() = cDeterminant.Imag; - } -#endif /* spCOMPLEX */ -#if REAL AND spCOMPLEX - else -#endif #if REAL { /* Real Case. */ *pDeterminant = 1.0; @@ -1074,123 +689,6 @@ void spStripFills(char* eMatrix) } #endif -#if TRANSLATE AND DELETE -/* - * DELETE A ROW AND COLUMN FROM THE MATRIX - * - * Deletes a row and a column from a matrix. - * - * Sparse will abort if an attempt is made to delete a row or column that - * doesn't exist. - * - * >>> Arguments: - * eMatrix (char *) - * Pointer to the matrix in which the row and column are to be deleted. - * Row (int) - * Row to be deleted. - * Col (int) - * Column to be deleted. - * - * >>> Local variables: - * ExtCol (int) - * The external column that is being deleted. - * ExtRow (int) - * The external row that is being deleted. - * pElement (ElementPtr) - * Pointer to an element in the matrix. Used when scanning rows and - * columns in order to eliminate elements from the last row or column. - * ppElement (ElementPtr *) - * Pointer to the location of an ElementPtr. This location will be - * filled with a NULL pointer if it is the new last element in its row - * or column. - * pElement (ElementPtr) - * Pointer to an element in the last row or column of the matrix. - * Size (int) - * The local version Matrix->Size, the size of the matrix. - */ - -void spDeleteRowAndCol(char* eMatrix, int Row, int Col) -{ - MatrixPtr Matrix = (MatrixPtr)eMatrix; - ElementPtr pElement, *ppElement, pLastElement; - int Size, ExtRow, ExtCol; - - /* Begin `spDeleteRowAndCol'. */ - - ASSERT(IS_SPARSE(Matrix) AND Row > 0 AND Col > 0); - ASSERT(Row <= Matrix->ExtSize AND Col <= Matrix->ExtSize); - - Size = Matrix->Size; - ExtRow = Row; - ExtCol = Col; - if (NOT Matrix->RowsLinked) - spcLinkRows(Matrix); - - Row = Matrix->ExtToIntRowMap[Row]; - Col = Matrix->ExtToIntColMap[Col]; - ASSERT(Row > 0 AND Col > 0); - - /* Move Row so that it is the last row in the matrix. */ - if (Row != Size) - spcRowExchange(Matrix, Row, Size); - - /* Move Col so that it is the last column in the matrix. */ - if (Col != Size) - spcColExchange(Matrix, Col, Size); - - /* Correct Diag pointers. */ - if (Row == Col) - SWAP(ElementPtr, Matrix->Diag[Row], Matrix->Diag[Size]) - else { - Matrix->Diag[Row] = spcFindElementInCol(Matrix, Matrix->FirstInCol + Row, - Row, Row, NO); - Matrix->Diag[Col] = spcFindElementInCol(Matrix, Matrix->FirstInCol + Col, - Col, Col, NO); - } - - /* - * Delete last row and column of the matrix. - */ - /* Break the column links to every element in the last row. */ - pLastElement = Matrix->FirstInRow[Size]; - while (pLastElement != NULL) { - ppElement = &(Matrix->FirstInCol[pLastElement->Col]); - while ((pElement = *ppElement) != NULL) { - if (pElement == pLastElement) - *ppElement = NULL; /* Unlink last element in column. */ - else - ppElement = &pElement->NextInCol; /* Skip element. */ - } - pLastElement = pLastElement->NextInRow; - } - - /* Break the row links to every element in the last column. */ - pLastElement = Matrix->FirstInCol[Size]; - while (pLastElement != NULL) { - ppElement = &(Matrix->FirstInRow[pLastElement->Row]); - while ((pElement = *ppElement) != NULL) { - if (pElement == pLastElement) - *ppElement = NULL; /* Unlink last element in row. */ - else - ppElement = &pElement->NextInRow; /* Skip element. */ - } - pLastElement = pLastElement->NextInCol; - } - - /* Clean up some details. */ - Matrix->Size = Size - 1; - Matrix->Diag[Size] = NULL; - Matrix->FirstInRow[Size] = NULL; - Matrix->FirstInCol[Size] = NULL; - Matrix->CurrentSize--; - Matrix->ExtToIntRowMap[ExtRow] = -1; - Matrix->ExtToIntColMap[ExtCol] = -1; - Matrix->NeedsOrdering = YES; - - return; -} -#endif - #if PSEUDOCONDITION /* * CALCULATE PSEUDOCONDITION @@ -1321,23 +819,14 @@ RealNumber spCondition(char* eMatrix, RealNumber NormOfMatrix, int* pError) return 0.0; } -#if spCOMPLEX - if (Matrix->Complex) - return ComplexCondition(Matrix, NormOfMatrix, pError); -#endif - #if REAL Size = Matrix->Size; T = Matrix->Intermediate; -#if spCOMPLEX - Tm = Matrix->Intermediate + Size; -#else Tm = ALLOC(RealNumber, Size + 1); if (Tm == NULL) { *pError = spNO_MEMORY; return 0.0; } -#endif for (I = Size; I > 0; I--) T[I] = 0.0; @@ -1484,9 +973,7 @@ RealNumber spCondition(char* eMatrix, RealNumber NormOfMatrix, int* pError) for (ASz = 0.0, I = Size; I > 0; I--) ASz += ABS(T[I]); -#if NOT spCOMPLEX FREE(Tm); -#endif Linpack = ASy / ASz; OLeary = E / MaxY; @@ -1495,210 +982,6 @@ RealNumber spCondition(char* eMatrix, RealNumber NormOfMatrix, int* pError) #endif /* REAL */ } -#if spCOMPLEX -/* - * ESTIMATE CONDITION NUMBER - * - * Complex version of spCondition(). - * - * >>> Returns: - * The reciprocal of the condition number. - * - * >>> Arguments: - * Matrix (MatrixPtr) - * Pointer to the matrix. - * NormOfMatrix (RealNumber) - * The L-infinity norm of the unfactored matrix as computed by - * spNorm(). - * pError (int *) - * Used to return error code. - * - * >>> Possible errors: - * spNO_MEMORY - */ - -static RealNumber ComplexCondition(MatrixPtr Matrix, RealNumber NormOfMatrix, int* pError) -{ - ElementPtr pElement; - ComplexVector T, Tm; - int I, K, Row; - ElementPtr pPivot; - int Size; - RealNumber E, Em, ASp, ASm, ASw, ASy, ASv, ASz, MaxY, ScaleFactor; - RealNumber Linpack, OLeary, InvNormOfInverse; - ComplexNumber Wp, Wm; - - /* Begin `ComplexCondition'. */ - - Size = Matrix->Size; - T = (ComplexVector)Matrix->Intermediate; - Tm = ALLOC(ComplexNumber, Size + 1); - if (Tm == NULL) { - *pError = spNO_MEMORY; - return 0.0; - } - for (I = Size; I > 0; I--) - T[I].Real = T[I].Imag = 0.0; - - /* - * Part 1. Ay = e. - * Solve Ay = LUy = e where e consists of +1 and -1 terms with the sign - * chosen to maximize the size of w in Lw = e. Since the terms in w can - * get very large, scaling is used to avoid overflow. - */ - - /* Forward elimination. Solves Lw = e while choosing e. */ - E = 1.0; - for (I = 1; I <= Size; I++) { - pPivot = Matrix->Diag[I]; - if (T[I].Real < 0.0) - Em = -E; - else - Em = E; - Wm = T[I]; - Wm.Real += Em; - ASm = CMPLX_1_NORM(Wm); - CMPLX_MULT_ASSIGN(Wm, *pPivot); - if (CMPLX_1_NORM(Wm) > SLACK) { - ScaleFactor = 1.0 / MAX(SQR(SLACK), CMPLX_1_NORM(Wm)); - for (K = Size; K > 0; K--) - SCLR_MULT_ASSIGN(T[K], ScaleFactor); - E *= ScaleFactor; - Em *= ScaleFactor; - ASm *= ScaleFactor; - SCLR_MULT_ASSIGN(Wm, ScaleFactor); - } - Wp = T[I]; - Wp.Real -= Em; - ASp = CMPLX_1_NORM(Wp); - CMPLX_MULT_ASSIGN(Wp, *pPivot); - - /* Update T for both values of W, minus value is placed in Tm. */ - pElement = pPivot->NextInCol; - while (pElement != NULL) { - Row = pElement->Row; - /* Cmplx expr: Tm[Row] = T[Row] - (Wp * *pElement). */ - CMPLX_MULT_SUBT(Tm[Row], Wm, *pElement, T[Row]); - /* Cmplx expr: T[Row] -= Wp * *pElement. */ - CMPLX_MULT_SUBT_ASSIGN(T[Row], Wm, *pElement); - ASp += CMPLX_1_NORM(T[Row]); - ASm += CMPLX_1_NORM(Tm[Row]); - pElement = pElement->NextInCol; - } - - /* If minus value causes more growth, overwrite T with its values. */ - if (ASm > ASp) { - T[I] = Wm; - pElement = pPivot->NextInCol; - while (pElement != NULL) { - T[pElement->Row] = Tm[pElement->Row]; - pElement = pElement->NextInCol; - } - } else - T[I] = Wp; - } - - /* Compute 1-norm of T, which now contains w, and scale ||T|| to 1/SLACK. */ - for (ASw = 0.0, I = Size; I > 0; I--) - ASw += CMPLX_1_NORM(T[I]); - ScaleFactor = 1.0 / (SLACK * ASw); - if (ScaleFactor < 0.5) { - for (I = Size; I > 0; I--) - SCLR_MULT_ASSIGN(T[I], ScaleFactor); - E *= ScaleFactor; - } - - /* Backward Substitution. Solves Uy = w.*/ - for (I = Size; I >= 1; I--) { - pElement = Matrix->Diag[I]->NextInRow; - while (pElement != NULL) { /* Cmplx expr: T[I] -= T[pElement->Col] * *pElement. */ - CMPLX_MULT_SUBT_ASSIGN(T[I], T[pElement->Col], *pElement); - pElement = pElement->NextInRow; - } - if (CMPLX_1_NORM(T[I]) > SLACK) { - ScaleFactor = 1.0 / MAX(SQR(SLACK), CMPLX_1_NORM(T[I])); - for (K = Size; K > 0; K--) - SCLR_MULT_ASSIGN(T[K], ScaleFactor); - E *= ScaleFactor; - } - } - - /* Compute 1-norm of T, which now contains y, and scale ||T|| to 1/SLACK. */ - for (ASy = 0.0, I = Size; I > 0; I--) - ASy += CMPLX_1_NORM(T[I]); - ScaleFactor = 1.0 / (SLACK * ASy); - if (ScaleFactor < 0.5) { - for (I = Size; I > 0; I--) - SCLR_MULT_ASSIGN(T[I], ScaleFactor); - ASy = 1.0 / SLACK; - E *= ScaleFactor; - } - - /* Compute infinity-norm of T for O'Leary's estimate. */ - for (MaxY = 0.0, I = Size; I > 0; I--) - if (MaxY < CMPLX_1_NORM(T[I])) - MaxY = CMPLX_1_NORM(T[I]); - - /* - * Part 2. A* z = y where the * represents the transpose. - * Recall that A = LU implies A* = U* L*. - */ - - /* Forward elimination, U* v = y. */ - for (I = 1; I <= Size; I++) { - pElement = Matrix->Diag[I]->NextInRow; - while (pElement != NULL) { /* Cmplx expr: T[pElement->Col] -= T[I] * *pElement. */ - CMPLX_MULT_SUBT_ASSIGN(T[pElement->Col], T[I], *pElement); - pElement = pElement->NextInRow; - } - if (CMPLX_1_NORM(T[I]) > SLACK) { - ScaleFactor = 1.0 / MAX(SQR(SLACK), CMPLX_1_NORM(T[I])); - for (K = Size; K > 0; K--) - SCLR_MULT_ASSIGN(T[K], ScaleFactor); - ASy *= ScaleFactor; - } - } - - /* Compute 1-norm of T, which now contains v, and scale ||T|| to 1/SLACK. */ - for (ASv = 0.0, I = Size; I > 0; I--) - ASv += CMPLX_1_NORM(T[I]); - ScaleFactor = 1.0 / (SLACK * ASv); - if (ScaleFactor < 0.5) { - for (I = Size; I > 0; I--) - SCLR_MULT_ASSIGN(T[I], ScaleFactor); - ASy *= ScaleFactor; - } - - /* Backward Substitution, L* z = v. */ - for (I = Size; I >= 1; I--) { - pPivot = Matrix->Diag[I]; - pElement = pPivot->NextInCol; - while (pElement != NULL) { /* Cmplx expr: T[I] -= T[pElement->Row] * *pElement. */ - CMPLX_MULT_SUBT_ASSIGN(T[I], T[pElement->Row], *pElement); - pElement = pElement->NextInCol; - } - CMPLX_MULT_ASSIGN(T[I], *pPivot); - if (CMPLX_1_NORM(T[I]) > SLACK) { - ScaleFactor = 1.0 / MAX(SQR(SLACK), CMPLX_1_NORM(T[I])); - for (K = Size; K > 0; K--) - SCLR_MULT_ASSIGN(T[K], ScaleFactor); - ASy *= ScaleFactor; - } - } - - /* Compute 1-norm of T, which now contains z. */ - for (ASz = 0.0, I = Size; I > 0; I--) - ASz += CMPLX_1_NORM(T[I]); - - FREE(Tm); - - Linpack = ASy / ASz; - OLeary = E / MaxY; - InvNormOfInverse = MIN(Linpack, OLeary); - return InvNormOfInverse / NormOfMatrix; -} -#endif /* spCOMPLEX */ - /* * L-INFINITY MATRIX NORM * @@ -1727,33 +1010,17 @@ RealNumber spNorm(char* eMatrix) if (NOT Matrix->RowsLinked) spcLinkRows(Matrix); -/* Compute row sums. */ + /* Compute row sums. */ #if REAL - if (NOT Matrix->Complex) { - for (I = Matrix->Size; I > 0; I--) { - pElement = Matrix->FirstInRow[I]; - AbsRowSum = 0.0; - while (pElement != NULL) { - AbsRowSum += ABS(pElement->Real); - pElement = pElement->NextInRow; - } - if (Max < AbsRowSum) - Max = AbsRowSum; - } - } -#endif -#if spCOMPLEX - if (Matrix->Complex) { - for (I = Matrix->Size; I > 0; I--) { - pElement = Matrix->FirstInRow[I]; - AbsRowSum = 0.0; - while (pElement != NULL) { - AbsRowSum += CMPLX_1_NORM(*pElement); - pElement = pElement->NextInRow; - } - if (Max < AbsRowSum) - Max = AbsRowSum; + for (I = Matrix->Size; I > 0; I--) { + pElement = Matrix->FirstInRow[I]; + AbsRowSum = 0.0; + while (pElement != NULL) { + AbsRowSum += ABS(pElement->Real); + pElement = pElement->NextInRow; } + if (Max < AbsRowSum) + Max = AbsRowSum; } #endif return Max; @@ -1833,14 +1100,13 @@ RealNumber spLargestElement(char* eMatrix) int I; RealNumber Mag, AbsColSum, Max = 0.0, MaxRow = 0.0, MaxCol = 0.0; RealNumber Pivot; - ComplexNumber cPivot; ElementPtr pElement, pDiag; /* Begin `spLargestElement'. */ ASSERT(IS_SPARSE(Matrix)); #if REAL - if (Matrix->Factored AND NOT Matrix->Complex) { + if (Matrix->Factored) { if (Matrix->Error == spSINGULAR) return 0.0; @@ -1871,7 +1137,7 @@ RealNumber spLargestElement(char* eMatrix) if (AbsColSum > MaxCol) MaxCol = AbsColSum; } - } else if (NOT Matrix->Complex) { + } else { for (I = 1; I <= Matrix->Size; I++) { pElement = Matrix->FirstInCol[I]; while (pElement != NULL) { @@ -1883,51 +1149,6 @@ RealNumber spLargestElement(char* eMatrix) } return Max; } -#endif -#if spCOMPLEX - if (Matrix->Factored AND Matrix->Complex) { - if (Matrix->Error == spSINGULAR) - return 0.0; - - /* Find the bound on the size of the largest element over all factorization. */ - for (I = 1; I <= Matrix->Size; I++) { - pDiag = Matrix->Diag[I]; - - /* Lower triangular matrix. */ - CMPLX_RECIPROCAL(cPivot, *pDiag); - Mag = CMPLX_1_NORM(cPivot); - if (Mag > MaxRow) - MaxRow = Mag; - pElement = Matrix->FirstInRow[I]; - while (pElement != pDiag) { - Mag = CMPLX_1_NORM(*pElement); - if (Mag > MaxRow) - MaxRow = Mag; - pElement = pElement->NextInRow; - } - - /* Upper triangular matrix. */ - pElement = Matrix->FirstInCol[I]; - AbsColSum = 1.0; /* Diagonal of U is unity. */ - while (pElement != pDiag) { - AbsColSum += CMPLX_1_NORM(*pElement); - pElement = pElement->NextInCol; - } - if (AbsColSum > MaxCol) - MaxCol = AbsColSum; - } - } else if (Matrix->Complex) { - for (I = 1; I <= Matrix->Size; I++) { - pElement = Matrix->FirstInCol[I]; - while (pElement != NULL) { - Mag = CMPLX_1_NORM(*pElement); - if (Mag > Max) - Max = Mag; - pElement = pElement->NextInCol; - } - } - return Max; - } #endif return MaxRow * MaxCol; } From 7f8ba2d4a3389ac69a54f308bd6b090ddea24915 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Mon, 21 Oct 2024 10:54:26 +0200 Subject: [PATCH 59/68] We should not used save-always anymore (#3136) Here is the depreciation: https://github.com/actions/cache/pull/1452 --- .github/workflows/neuron-ci.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/neuron-ci.yml b/.github/workflows/neuron-ci.yml index dfe8a9327c..c77d5a6b45 100644 --- a/.github/workflows/neuron-ci.yml +++ b/.github/workflows/neuron-ci.yml @@ -237,10 +237,10 @@ jobs: echo ----- - name: Restore compiler cache - uses: actions/cache@v4 + uses: actions/cache/restore@v4 + id: restore-compiler-cache with: path: ${{runner.workspace}}/ccache - save-always: true key: ${{matrix.os}}-${{hashfiles('matrix.json')}}-${{github.ref}}-${{github.sha}} restore-keys: | ${{matrix.os}}-${{hashfiles('matrix.json')}}-${{github.ref}}- @@ -441,6 +441,15 @@ jobs: INSTALL_DIR : ${{ runner.workspace }}/install MATRIX_EVAL: ${{ matrix.config.matrix_eval }} + - name: Save compiler cache + uses: actions/cache/save@v4 + if: always() && steps.restore-compiler-cache.outputs.cache-hit != 'true' + with: + path: ${{runner.workspace}}/ccache + key: | + ${{matrix.os}}-${{hashfiles('matrix.json')}}-${{github.ref}}- + ${{matrix.os}}-${{hashfiles('matrix.json')}}- + # This step will set up an SSH connection on tmate.io for live debugging. # To enable it, you have to: # * add 'live-debug-ci' to your PR title From ceedb15fc50214aed566af5ded5382fe835b6d9a Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Mon, 21 Oct 2024 13:37:52 +0200 Subject: [PATCH 60/68] nrn_py_CallObject take a nb::object for args (#3127) This object can be any iterable like list or tuple. --- src/nrnpython/nrnpy_hoc.cpp | 1 - src/nrnpython/nrnpy_p2h.cpp | 21 +++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/nrnpython/nrnpy_hoc.cpp b/src/nrnpython/nrnpy_hoc.cpp index 311139567c..96ae36c38b 100644 --- a/src/nrnpython/nrnpy_hoc.cpp +++ b/src/nrnpython/nrnpy_hoc.cpp @@ -21,7 +21,6 @@ #include #include - namespace nb = nanobind; extern PyTypeObject* psection_type; diff --git a/src/nrnpython/nrnpy_p2h.cpp b/src/nrnpython/nrnpy_p2h.cpp index fc0a4d085b..6bfae26924 100644 --- a/src/nrnpython/nrnpy_p2h.cpp +++ b/src/nrnpython/nrnpy_p2h.cpp @@ -18,7 +18,7 @@ namespace nb = nanobind; static char* nrnpyerr_str(); -static nb::object nrnpy_pyCallObject(nb::callable, PyObject*); +static nb::object nrnpy_pyCallObject(nb::callable, nb::object); static PyObject* main_module; static PyObject* main_namespace; @@ -46,7 +46,7 @@ static void call_python_with_section(Object* pyact, Section* sec) { nanobind::gil_scoped_acquire lock{}; nb::tuple args = nb::make_tuple(reinterpret_cast(newpysechelp(sec))); - nb::object r = nrnpy_pyCallObject(po, args.ptr()); + nb::object r = nrnpy_pyCallObject(po, args); if (!r.is_valid()) { char* mes = nrnpyerr_str(); if (mes) { @@ -106,12 +106,13 @@ Object* nrnpy_pyobject_in_obj(PyObject* po) { return on; } -static nb::object nrnpy_pyCallObject(nb::callable callable, PyObject* args) { +static nb::object nrnpy_pyCallObject(nb::callable callable, nb::object args) { // When hoc calls a PythonObject method, then in case python // calls something back in hoc, the hoc interpreter must be // at the top level HocTopContextSet - PyObject* p = PyObject_CallObject(callable.ptr(), args); + nb::tuple tup(args); + nb::object p = nb::steal(PyObject_CallObject(callable.ptr(), tup.ptr())); #if 0 printf("PyObject_CallObject callable\n"); PyObject_Print(callable, stdout, 0); @@ -139,7 +140,7 @@ printf("\nreturn %p\n", p); } } **/ - return nb::steal(p); + return p; } static void py2n_component(Object* ob, Symbol* sym, int nindex, int isfunc) { @@ -196,7 +197,7 @@ static void py2n_component(Object* ob, Symbol* sym, int nindex, int isfunc) { } } // printf("PyObject_CallObject %s %p\n", sym->name, tail); - result = nrnpy_pyCallObject(nb::borrow(tail), args).release().ptr(); + result = nrnpy_pyCallObject(nb::borrow(tail), nb::borrow(args)).release().ptr(); Py_DECREF(args); // PyObject_Print(result, stdout, 0); // printf(" result of call\n"); @@ -333,9 +334,9 @@ static nb::object hoccommand_exec_help1(nb::object po) { if (!nb::tuple::check_(args)) { args = nb::make_tuple(args); } - return nrnpy_pyCallObject(po[0], args.ptr()); + return nrnpy_pyCallObject(po[0], args); } else { - return nrnpy_pyCallObject(nb::borrow(po), nb::tuple().ptr()); + return nrnpy_pyCallObject(nb::borrow(po), nb::tuple()); } } @@ -417,7 +418,7 @@ static void grphcmdtool(Object* ho, int type, double x, double y, int key) { nanobind::gil_scoped_acquire lock{}; nb::tuple args = nb::make_tuple(type, x, y, key); - nb::object r = nrnpy_pyCallObject(po, args.ptr()); + nb::object r = nrnpy_pyCallObject(po, args); if (!r.is_valid()) { char* mes = nrnpyerr_str(); if (mes) { @@ -483,7 +484,7 @@ static double func_call(Object* ho, int narg, int* err) { } } - nb::object r = nrnpy_pyCallObject(po, args); + nb::object r = nrnpy_pyCallObject(po, nb::borrow(args)); Py_XDECREF(args); double rval = 0.0; if (!r.is_valid()) { From 510b9bc94592e77d282d28921db483e25a1400f6 Mon Sep 17 00:00:00 2001 From: nrnhines Date: Mon, 21 Oct 2024 20:50:56 -0400 Subject: [PATCH 61/68] NRN_ENABLE_DIGEST and NRN_ENABLE_ARCH_INDEP_EXP_POW (#3135) * Selected messages from old digest-debug branch Print digest of cvode f(y,t) and solvex(b,...) cmake -DNRN_DIGEST=ON nrn_digest() starts the accumulation of cvode digest info. nrn_digest("filename") prints accumulated cvode digest info. filename format is: message threadid index t digest where digest is the first 16 hex characters of the SHA1 hash of the double* array indicated by the message. -DNRN_ENABLE_ARCH_INDEP_EXP_POW=ON (default OFF) Provides h.use_exp_pow_precision(style) style = 0 means use normal machine IEEE precision for exp(x) and pow(x,y) style = 1 means use 53 bit mpfr style = 2 means use IEEE but truncate to 32 bit precision. sundials uses hoc_pow. digest format has a f(y,t) call count. * nrn_digest(tid, i) will print the details of the i'th digest item of thread tid. * sundial RPowerR uses hoc_pow. nrn_digest(tid, i, "abort") calls abort() on reaching index i of thread tid * Documentation for nrn_digest and use_exp_pow_precision --- CMakeLists.txt | 11 +++ cmake/BuildOptionDefaults.cmake | 2 + cmake_nrnconf.h.in | 7 ++ docs/cmake_doc/options.rst | 20 +++++ docs/python/programming/internals.rst | 112 +++++++++++++++++++++++++ src/nocmodl/nocpout.cpp | 2 + src/nrncvode/occvode.cpp | 31 +++++-- src/nrniv/CMakeLists.txt | 20 +++++ src/nrniv/nmodlrandom.cpp | 8 +- src/nrniv/nrnmenu.cpp | 3 +- src/nrnpython/CMakeLists.txt | 3 +- src/oc/debug.cpp | 92 +++++++++++++++++++++ src/oc/hoc_init.cpp | 4 + src/oc/math.cpp | 114 +++++++++++++++++++++++++- src/oc/nrndigest.h | 19 +++++ src/oc/oc_ansi.h | 1 + src/oc/ocfunc.h | 6 ++ src/sundials/shared/sundialsmath.c | 6 +- 18 files changed, 444 insertions(+), 17 deletions(-) create mode 100644 src/oc/nrndigest.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 87d423a7b4..57bd453036 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,6 +85,13 @@ option( NRN_ENABLE_PERFORMANCE_TESTS "Enable tests that measure performance. These are known to be unreliable when run on busy/oversubscribed machines such as CI runners." ${NRN_ENABLE_PERFORMANCE_TESTS_DEFAULT}) +option(NRN_ENABLE_DIGEST + "Provides nrn_digest function for debugging cross platform floating result differences." + ${NRN_ENABLE_DIGEST_DEFAULT}) +option( + NRN_ENABLE_ARCH_INDEP_EXP_POW + "Provides use_exp_pow_precision(style) function so that exp and pow produce same results on all platforms" + ${NRN_ENABLE_ARCH_INDEP_EXP_POW_DEFAULT}) # This can be helpful in very specific CI build configurations, where ccache is used *and* different # CI builds are built under different directories. option(NRN_AVOID_ABSOLUTE_PATHS @@ -1056,6 +1063,10 @@ if(NRN_ENABLE_PROFILING) message(STATUS " Caliper | ${caliper_DIR}") endif() endif() +if(NRN_ENABLE_DIGEST OR NRN_ARCH_INDEP_EXP_POW) + message(STATUS "NRN_ENABLE_DIGEST | ${NRN_ENABLE_DIGEST}") + message(STATUS "NRN_ENABLE_ARCH_INDEP_EXP_POW | ${NRN_ENABLE_ARCH_INDEP_EXP_POW}") +endif() message(STATUS "--------------+--------------------------------------------------------------") message(STATUS " See documentation : https://www.neuron.yale.edu/neuron/") message(STATUS "--------------+--------------------------------------------------------------") diff --git a/cmake/BuildOptionDefaults.cmake b/cmake/BuildOptionDefaults.cmake index e3e1f3dd63..b43338e5ac 100644 --- a/cmake/BuildOptionDefaults.cmake +++ b/cmake/BuildOptionDefaults.cmake @@ -29,6 +29,8 @@ set(NRN_AVOID_ABSOLUTE_PATHS_DEFAULT OFF) set(NRN_NMODL_CXX_FLAGS_DEFAULT "-O0") set(NRN_SANITIZERS_DEFAULT "") set(NRN_ENABLE_MATH_OPT_DEFAULT OFF) +set(NRN_ENABLE_DIGEST_DEFAULT OFF) +set(NRN_ENABLE_ARCH_INDEP_EXP_POW_DEFAULT OFF) # Some distributions may set the prefix. To avoid errors, unset it set(NRN_PYTHON_DYNAMIC_DEFAULT "") diff --git a/cmake_nrnconf.h.in b/cmake_nrnconf.h.in index 5bbd435916..3c7851c6d5 100644 --- a/cmake_nrnconf.h.in +++ b/cmake_nrnconf.h.in @@ -1,5 +1,12 @@ #pragma once +/* Define to one if want to debug using sha1 hashes of data */ +#cmakedefine01 NRN_ENABLE_DIGEST + +/* Define to one if want to allow selection of architecture independent */ +/* 53 bit double precision of exp and pow from mpfr */ +#cmakedefine01 NRN_ENABLE_ARCH_INDEP_EXP_POW + /* Define if building universal (internal helper macro) */ #cmakedefine AC_APPLE_UNIVERSAL_BUILD @AC_APPLE_UNIVERSAL_BUILD@ diff --git a/docs/cmake_doc/options.rst b/docs/cmake_doc/options.rst index 087b477ab1..fcb296682a 100644 --- a/docs/cmake_doc/options.rst +++ b/docs/cmake_doc/options.rst @@ -674,3 +674,23 @@ NRN_ENABLE_MATH_OPT:BOOL=OFF Note: Compilers like Intel, NVHPC, Cray etc enable such optimisations by default. + +NRN_ENABLE_DIGEST:BOOL=OFF +------------------------------ + Provides \ :func:`nrn_digest` function for debugging cross platform floating + result differences. + + Requires libcrypto + +NRN_ENABLE_ARCH_INDEP_EXP_POW:BOOL=OFF +--------------------------------- + Provides \ :func:`use_exp_pow_precision` function so that exp and pow produce + same results on all platforms. + + Requires mpfr (multiple precision floating-point computation). eg. + ``sudo apt install libmpfr-dev`` + + To get platform independent floating point results with clang, + also consider using + ``-DCMAKE_C_FLAGS="-ffp-contract=off" -DCMAKE_CXX_FLAGS="-ffp-contract=off"`` + or, alternatively, ``"-fp-model=strict`` diff --git a/docs/python/programming/internals.rst b/docs/python/programming/internals.rst index fab28b96e0..5f6096bae6 100755 --- a/docs/python/programming/internals.rst +++ b/docs/python/programming/internals.rst @@ -261,3 +261,115 @@ Miscellaneous the variable from its interpreter name. Not needed by or useful for the user; returns 1.0 on success. +---- + +Debugging +~~~~~~~~~~~ + +.. function:: nrn_digest + + Syntax: + ``h.nrn_digest()`` + + ``h.nrn_digest(tid, i)`` + + ``h.nrn_digest(tid, i, "abort")`` + + ``h.nrn_digest(filename)`` + + Description: + Available when configured with the cmake option ``-DNRN_ENABLE_DIGEST=ON`` + + If the same simulation gives different results on different machines, + this function can help isolate the statement that generates the + first difference during the simulation. + I think :meth:`ParallelContext.prcellstate` is generally better, but in rare + situations, nrn_digest can be very helpful. + + The first three forms begin digest gathering. The last form + prints the gathered digest information to the filename. + With just the two ``tid, i`` arguments, the i gathered item of the + tid thread is printed (for single thread simulations, use ``tid = 0``), + to the terminal as well as the individual values of the array + for that digest item. With the third ``"abort"`` argument, the + ith gathered item is printed and ``abort()`` is called (dropping + into gdb if that is being used so that one can observe the backtrace). + + Lines are inserted into the digest by calling the C function declared + in ``src/oc/nrndigest.h``. + ``void nrn_digest_dbl_array(const char* msg, int tid, double t, double* array, size_t sz);`` + at the moment, such lines are present in ``src/nrncvode/occvode.cpp`` + to instrument the cvode callbacks that compute ``y' = f(y, t)`` and the + approximate jacobian matrix solver ``M*x = b``. I.e in part + + .. code-block:: + + #include "nrndigest.h" + ... + void Cvode::fun_thread(neuron::model_sorted_token const& sorted_token, + double tt, + double* y, + double* ydot, + NrnThread* nt) { + CvodeThreadData& z = CTD(nt->id); + #if NRN_DIGEST + if (nrn_digest_) { + nrn_digest_dbl_array("y", nt->id, tt, y, z.nvsize_); + } + #endif + ... + #if NRN_DIGEST + if (nrn_digest_ && ydot) { + nrn_digest_dbl_array("ydot", nt->id, tt, ydot, z.nvsize_); + } + #endif + + Note: when manually adding such lines, the conditional compilation and + nrn\_digest\_ test are not needed. The arguments to + ``nrn_digest_dbl_array`` determine the line added to the digest. + The 5th arg is the size of the 4th arg double array. The double array + is processed by SHA1 and the first 16 hex digits are appended to the line. + An example of the first few lines of output in a digest file is + .. code-block:: + + tid=0 size=1344 + y 0 0 0 e1f6a372856b45e6 + y 0 1 0 e1f6a372856b45e6 + ydot 0 2 0 523c9694c335e458 + y 0 3 4.7121609153871379e-09 fabb4bc469447404 + ydot 0 4 4.7121609153871379e-09 60bcff174645fc29 + + The first line is thread id and number of lines for that thread. + Other thread groups, if any, follow the end of each thread group. + The digest lines consist of thread id, line identifier (start from 0 + for each group), double value of the 3rd arg, hash of the array. + +---- + +.. function:: use_exp_pow_precision + + Syntax: + ``h.use_exp_pow_precision(istyle)`` + + Description: + Works when configured with the cmake option + ``-DNRN_ENABLE_ARCH_INDEP_EXP_POW=ON`` and otherwise does nothing. + + * istyle = 1 + All calls to :func:`exp` and :func:`pow` as well as their use + internally, in mod files, and by cvode, are computed on mac, linux, + windows so that double precision floating point results are + cross platform consistent. (Makes use of a + multiple precision floating-point computation library.) + + * istyle = 2 + exp and pow are rounded to 32 bits of mantissa + + * istyle = 0 + Default. + exp and pow calcualted natively (cross platform values can have + round off error differences.) + + When using clang (eg. on a mac) cross platform floating point + identity is often attainable with C and C++ flag option + ``"-ffp-contract=off"``. diff --git a/src/nocmodl/nocpout.cpp b/src/nocmodl/nocpout.cpp index 92c18d6b2d..c11d63e24d 100644 --- a/src/nocmodl/nocpout.cpp +++ b/src/nocmodl/nocpout.cpp @@ -256,6 +256,8 @@ void parout() { \n#if !NRNGPU\ \n#undef exp\ \n#define exp hoc_Exp\ +\n#undef pow\ +\n#define pow hoc_pow\ \n#endif\n\ "); if (protect_include_) { diff --git a/src/nrncvode/occvode.cpp b/src/nrncvode/occvode.cpp index 67e24d1c87..a2f6bd24eb 100644 --- a/src/nrncvode/occvode.cpp +++ b/src/nrncvode/occvode.cpp @@ -12,6 +12,7 @@ #include "vrecitem.h" #include "membfunc.h" #include "nonvintblock.h" +#include "nrndigest.h" #include #include @@ -323,7 +324,7 @@ void Cvode::new_no_cap_memb(CvodeThreadData& z, NrnThread* _nt) { } } } - assert(ncm->ml.size() == n); + assert(ncm->ml.size() == std::size_t(n)); } } @@ -456,7 +457,7 @@ extern void nrn_extra_scatter_gather(int, int); void Cvode::scatter_y(neuron::model_sorted_token const& sorted_token, double* y, int tid) { CvodeThreadData& z = CTD(tid); - assert(z.nonvint_extra_offset_ == z.pv_.size()); + assert(std::size_t(z.nonvint_extra_offset_) == z.pv_.size()); for (int i = 0; i < z.nonvint_extra_offset_; ++i) { // TODO: understand why this wasn't needed before if (z.pv_[i]) { @@ -494,7 +495,7 @@ void Cvode::gather_y(N_Vector y) { void Cvode::gather_y(double* y, int tid) { CvodeThreadData& z = CTD(tid); nrn_extra_scatter_gather(1, tid); - assert(z.nonvint_extra_offset_ == z.pv_.size()); + assert(std::size_t(z.nonvint_extra_offset_) == z.pv_.size()); for (int i = 0; i < z.nonvint_extra_offset_; ++i) { // TODO: understand why this wasn't needed before if (z.pv_[i]) { @@ -565,6 +566,12 @@ int Cvode::solvex_thread(neuron::model_sorted_token const& sorted_token, if (z.nvsize_ == 0) { return 0; } +#if NRN_DIGEST + if (nrn_digest_) { + nrn_digest_dbl_array("solvex enter b", nt->id, t_, b, z.nvsize_); + nrn_digest_dbl_array("solvex enter y", nt->id, t_, y, z.nvsize_); + } +#endif lhs(sorted_token, nt); // special version for cvode. scatter_ydot(b, nt->id); if (z.cmlcap_) { @@ -597,6 +604,11 @@ int Cvode::solvex_thread(neuron::model_sorted_token const& sorted_token, // printf("\texit b\n"); // for (i=0; i < neq_; ++i) { printf("\t\t%d %g\n", i, b[i]);} nrn_nonvint_block_ode_solve(z.nvsize_, b, y, nt->id); +#if NRN_DIGEST + if (nrn_digest_) { + nrn_digest_dbl_array("solvex leave b", nt->id, t_, b, z.nvsize_); + } +#endif return 0; } @@ -670,9 +682,20 @@ void Cvode::fun_thread(neuron::model_sorted_token const& sorted_token, double* ydot, NrnThread* nt) { CvodeThreadData& z = CTD(nt->id); +#if NRN_DIGEST + if (nrn_digest_) { + nrn_digest_dbl_array("y", nt->id, tt, y, z.nvsize_); + } +#endif fun_thread_transfer_part1(sorted_token, tt, y, nt); nrn_nonvint_block_ode_fun(z.nvsize_, y, ydot, nt->id); fun_thread_transfer_part2(sorted_token, ydot, nt); + +#if NRN_DIGEST + if (nrn_digest_ && ydot) { + nrn_digest_dbl_array("ydot", nt->id, tt, ydot, z.nvsize_); + } +#endif } void Cvode::fun_thread_transfer_part1(neuron::model_sorted_token const& sorted_token, @@ -740,7 +763,6 @@ void Cvode::fun_thread_transfer_part2(neuron::model_sorted_token const& sorted_t } void Cvode::fun_thread_ms_part1(double tt, double* y, NrnThread* nt) { - CvodeThreadData& z = ctd_[nt->id]; nt->_t = tt; // fix this!!! @@ -1001,7 +1023,6 @@ void Cvode::error_weights(double* pd) { void Cvode::acor(double* pd) { int i, id; - NrnThread* nt; for (id = 0; id < nctd_; ++id) { CvodeThreadData& z = ctd_[id]; double* s = n_vector_data(acorvec(), id); diff --git a/src/nrniv/CMakeLists.txt b/src/nrniv/CMakeLists.txt index f1f5830dde..0f9cd2564a 100644 --- a/src/nrniv/CMakeLists.txt +++ b/src/nrniv/CMakeLists.txt @@ -414,6 +414,26 @@ endif() if(NRN_ENABLE_THREADS) target_link_libraries(nrniv_lib Threads::Threads) endif() + +if(${NRN_ENABLE_DIGEST}) + if(NRN_MACOS_BUILD) + # where to get openssl/sha.h after brew install openssl + set_property( + SOURCE ${NRN_OC_SRC_DIR}/debug.cpp + APPEND + PROPERTY INCLUDE_DIRECTORIES /opt/homebrew/Cellar/openssl@3/3.1.0/include) + find_library(LIB_CRYPTO crypto PATHS /opt/homebrew/Cellar/openssl@3/3.1.0/lib REQUIRED) + target_link_libraries(nrniv_lib ${LIB_CRYPTO}) + else() + target_link_libraries(nrniv_lib crypto) + endif() +endif() + +if(${NRN_ENABLE_ARCH_INDEP_EXP_POW}) + find_library(LIB_MPFR mpfr REQUIRED) + target_link_libraries(nrniv_lib ${LIB_MPFR}) +endif() + if(NRN_WINDOWS_BUILD) target_link_libraries(nrniv_lib ${TERMCAP_LIBRARIES} ${Readline_LIBRARY}) else() diff --git a/src/nrniv/nmodlrandom.cpp b/src/nrniv/nmodlrandom.cpp index 66be7a9dc1..88806ddde9 100644 --- a/src/nrniv/nmodlrandom.cpp +++ b/src/nrniv/nmodlrandom.cpp @@ -100,12 +100,8 @@ static void nmodlrandom_destruct(void* v) { } void NMODLRandom_reg() { - class2oc("NMODLRandom", - nmodlrandom_cons, - nmodlrandom_destruct, - members, - retobj_members, - nullptr); + class2oc( + "NMODLRandom", nmodlrandom_cons, nmodlrandom_destruct, members, retobj_members, nullptr); if (!nmodlrandom_sym) { nmodlrandom_sym = hoc_lookup("NMODLRandom"); assert(nmodlrandom_sym); diff --git a/src/nrniv/nrnmenu.cpp b/src/nrniv/nrnmenu.cpp index f4103033cb..0f8e87f750 100644 --- a/src/nrniv/nrnmenu.cpp +++ b/src/nrniv/nrnmenu.cpp @@ -1129,8 +1129,7 @@ static Member_ret_obj_func mt_retobj_members[] = {{"pp_begin", mt_pp_begin}, {0, 0}}; static Member_ret_str_func mt_retstr_func[] = {{"code", mt_code}, {"file", mt_file}, {0, 0}}; void MechanismType_reg() { - class2oc( - "MechanismType", mt_cons, mt_destruct, mt_members, mt_retobj_members, mt_retstr_func); + class2oc("MechanismType", mt_cons, mt_destruct, mt_members, mt_retobj_members, mt_retstr_func); mt_class_sym_ = hoc_lookup("MechanismType"); } diff --git a/src/nrnpython/CMakeLists.txt b/src/nrnpython/CMakeLists.txt index c857e3c37b..0996b99c04 100644 --- a/src/nrnpython/CMakeLists.txt +++ b/src/nrnpython/CMakeLists.txt @@ -74,7 +74,8 @@ else() target_link_libraries(nrnpython ${NRN_DEFAULT_PYTHON_LIBRARIES}) endif() target_link_libraries(nrnpython fmt::fmt) - target_include_directories(nrnpython SYSTEM PUBLIC ${PROJECT_SOURCE_DIR}/${NRN_3RDPARTY_DIR}/eigen) + target_include_directories(nrnpython SYSTEM + PUBLIC ${PROJECT_SOURCE_DIR}/${NRN_3RDPARTY_DIR}/eigen) target_include_directories(nrnpython PUBLIC ${PROJECT_BINARY_DIR}/src/nrniv/oc_generated) make_nanobind_target(nanobind ${NRN_DEFAULT_PYTHON_INCLUDES}) target_link_libraries(nrnpython nanobind) diff --git a/src/oc/debug.cpp b/src/oc/debug.cpp index 2f8aeb5626..c9e0bb9988 100644 --- a/src/oc/debug.cpp +++ b/src/oc/debug.cpp @@ -1,12 +1,21 @@ #include <../../nrnconf.h> /* /local/src/master/nrn/src/oc/debug.cpp,v 1.7 1996/04/09 16:39:14 hines Exp */ + #include "hocdec.h" #include "code.h" #include "equation.h" +#include "multicore.h" #include #include "utils/logger.hpp" +#include "nrndigest.h" +#if NRN_DIGEST +#include +#include +#include +#endif + int hoc_zzdebug; #define prcod(c1, c2) else if (p->pf == c1) Printf("%p %p %s", fmt::ptr(p), fmt::ptr(p->pf), c2) @@ -144,3 +153,86 @@ void debugzz(Inst* p) { } #endif /*OCSMALL*/ } + +#if NRN_DIGEST + +int nrn_digest_; +static std::vector> digest; // nthread string vectors +static std::vector digest_cnt; // nthread counts. +static int nrn_digest_print_item_ = -1; +static int nrn_digest_print_tid_ = 0; +static bool nrn_digest_abort_ = false; + +void nrn_digest() { + if (ifarg(1) && hoc_is_str_arg(1)) { + // print the digest to the file and turn off accumulation + const char* fname = gargstr(1); + FILE* f = fopen(fname, "w"); + if (!f) { + hoc_execerr_ext("Could not open %s for writing", fname); + } + + int tid = 0; + for (auto& d: digest) { + fprintf(f, "tid=%d size=%zd\n", tid, digest[tid].size()); + for (auto& s: d) { + fprintf(f, "%s\n", s.c_str()); + } + tid++; + } + fclose(f); + nrn_digest_ = 0; + } else { // start accumulating digest info + nrn_digest_ = 1; + nrn_digest_print_item_ = -1; + nrn_digest_print_tid_ = 0; + if (ifarg(2)) { + nrn_digest_print_tid_ = int(chkarg(1, 0., nrn_nthread - 1)); + nrn_digest_print_item_ = int(chkarg(2, 0., 1e9)); + } + nrn_digest_abort_ = (ifarg(3) && strcmp(gargstr(3), "abort") == 0); + } + size_t size = digest.size() ? digest[0].size() : 0; + digest.clear(); // in any case, start over. + digest.resize(nrn_nthread); + digest_cnt.clear(); + digest_cnt.resize(nrn_nthread); + hoc_ret(); + hoc_pushx(double(size)); +} + +void nrn_digest_dbl_array(const char* msg, int tid, double t, double* array, size_t sz) { + if (!nrn_digest_) { + return; + } + unsigned char md[SHA_DIGEST_LENGTH]; + size_t n = sz * sizeof(double); + unsigned char* d = (unsigned char*) array; + SHA1(d, n, md); + + std::string s(msg); + char buf[100]; + int ix = int(digest_cnt[tid]); + digest_cnt[tid]++; + sprintf(buf, " %d %d %.17g ", tid, ix, t); + s += buf; + + for (int i = 0; i < 8; ++i) { + sprintf(buf, "%02x", (int) md[i]); + s += buf; + } + + digest[tid].push_back(s); + + if (nrn_digest_print_item_ == ix && nrn_digest_print_tid_ == tid) { + printf("ZZ %s\n", s.c_str()); + if (nrn_digest_abort_) { + abort(); + } + for (size_t i = 0; i < sz; ++i) { + printf("Z %zd %.20g\n", i, array[i]); + } + } +} + +#endif // NRN_DIGEST diff --git a/src/oc/hoc_init.cpp b/src/oc/hoc_init.cpp index bfcd5a9342..e8bd07f46c 100644 --- a/src/oc/hoc_init.cpp +++ b/src/oc/hoc_init.cpp @@ -195,6 +195,10 @@ static struct { /* Builtin functions with multiple or variable args */ #if defined(WIN32) {"WinExec", hoc_win_exec}, #endif +#if NRN_DIGEST + {"nrn_digest", nrn_digest}, +#endif + {"use_exp_pow_precision", hoc_use_exp_pow_precision}, {0, 0}}; static struct { /* functions that return a string */ diff --git a/src/oc/math.cpp b/src/oc/math.cpp index a568087679..2f2321fcf7 100644 --- a/src/oc/math.cpp +++ b/src/oc/math.cpp @@ -9,12 +9,16 @@ #include "nrnmpiuse.h" #include "ocfunc.h" +#include "nrnassrt.h" #include #include #include #include +#if NRN_ARCH_INDEP_EXP_POW +#include +#endif #define EPS hoc_epsilon #define MAXERRCOUNT 5 @@ -61,6 +65,109 @@ double hoc_Log10(double x) { return errcheck(log10(x), "log10"); } +#if NRN_ARCH_INDEP_EXP_POW + +static double accuracy32(double val) { + int ex; + double mant = frexp(val, &ex); + // round to about 32 bits after . + double prec = 4294967296.0; + double result = mant * prec; + result = round(result); + result /= prec; + result = ldexp(result, ex); + return result; +} + +static double pow_arch_indep(double x, double y) { + mpfr_prec_t prec = 53; + mpfr_rnd_t rnd = MPFR_RNDN; + + mpfr_t x_, y_; + mpfr_init2(x_, prec); + mpfr_init2(y_, prec); + + mpfr_set_d(x_, x, rnd); + mpfr_set_d(y_, y, rnd); + + mpfr_pow(x_, x_, y_, rnd); + + double r = mpfr_get_d(x_, rnd); + + mpfr_clear(x_); + mpfr_clear(y_); + + return r; +} + +static double exp_arch_indep(double x) { + mpfr_prec_t prec = 53; + mpfr_rnd_t rnd = MPFR_RNDN; + + mpfr_t x_; + mpfr_init2(x_, prec); + mpfr_set_d(x_, x, rnd); + mpfr_exp(x_, x_, rnd); + double r = mpfr_get_d(x_, rnd); + mpfr_clear(x_); + return r; +} + +static double pow_precision32(double x, double y) { + return accuracy32(pow(x, y)); +} + +static double exp_precision32(double x) { + return accuracy32(exp(x)); +} + +static double (*pow_ptr)(double x, double y) = pow; +static double (*pow_ieee_ptr)(double x, + double y) = pow; // avoid error! Maybe because of c++ overloading. +static double (*exp_ptr)(double x) = exp; + +int nrn_use_exp_pow_precision(int style) { + if (style == 0) { // default IEEE + pow_ptr = pow; + exp_ptr = exp; + } else if (style == 1) { // 53 bit mpfr + pow_ptr = pow_arch_indep; + exp_ptr = exp_arch_indep; + } else if (style == 2) { // 32 bit truncation + pow_ptr = pow_precision32; + exp_ptr = exp_precision32; + } + return style; +} + +#endif // NRN_ARCH_INDEP_EXP_POW + +void hoc_use_exp_pow_precision() { + int style = 0; + if (ifarg(1)) { + style = chkarg(1, 0.0, 2.0); + } +#if NRN_ARCH_INDEP_EXP_POW + style = nrn_use_exp_pow_precision(style); +#else + style = 0; +#endif // NRN_ARCH_INDEP_EXP_POW + hoc_ret(); + hoc_pushx(double(style)); +} + +// Try to overcome difference between linux and windows. +// by rounding mantissa to 32 bit accuracy or using +// hopefully arch independent mpfr for exp and pow. + +double hoc_pow(double x, double y) { +#if NRN_ARCH_INDEP_EXP_POW + return (*pow_ptr)(x, y); +#else + return pow(x, y); +#endif +} + /* used by nmodl and other c, c++ code */ double hoc_Exp(double x) { if (x < -700.) { @@ -78,7 +185,12 @@ double hoc_Exp(double x) { } return exp(700.); } + +#if NRN_ARCH_INDEP_EXP_POW + return (*exp_ptr)(x); +#else return exp(x); +#endif } /* used by interpreter */ @@ -103,7 +215,7 @@ double hoc_Sqrt(double x) { double hoc_Pow(double x, double y) { clear_fe_except(); - return errcheck(pow(x, y), "exponentiation"); + return errcheck(hoc_pow(x, y), "exponentiation"); } double hoc_integer(double x) { diff --git a/src/oc/nrndigest.h b/src/oc/nrndigest.h new file mode 100644 index 0000000000..0709460d0c --- /dev/null +++ b/src/oc/nrndigest.h @@ -0,0 +1,19 @@ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NRN_DIGEST NRN_ENABLE_DIGEST + +#if NRN_DIGEST +extern int nrn_digest_; // debugging differences on different machines. +extern void nrn_digest_dbl_array(const char* msg, int tid, double t, double* array, size_t sz); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/src/oc/oc_ansi.h b/src/oc/oc_ansi.h index 0b95fc8732..70466b93bb 100644 --- a/src/oc/oc_ansi.h +++ b/src/oc/oc_ansi.h @@ -100,6 +100,7 @@ void install_vector_method(const char*, double (*)(void*)); int vector_arg_px(int i, double** p); double hoc_Exp(double); +extern "C" double hoc_pow(double, double); int hoc_is_tempobj_arg(int narg); std::FILE* hoc_obj_file_arg(int i); void hoc_reg_nmodl_text(int type, const char* txt); diff --git a/src/oc/ocfunc.h b/src/oc/ocfunc.h index b30006011a..67bf910d86 100644 --- a/src/oc/ocfunc.h +++ b/src/oc/ocfunc.h @@ -38,6 +38,12 @@ extern void hoc_Setcolor(void); extern void hoc_init_space(void); extern void hoc_install_hoc_obj(void); extern void nrn_feenableexcept(void); + +#if NRN_DIGEST +extern void nrn_digest(); +#endif +extern void hoc_use_exp_pow_precision(); + void hoc_coreneuron_handle(); void hoc_get_config_key(); void hoc_get_config_val(); diff --git a/src/sundials/shared/sundialsmath.c b/src/sundials/shared/sundialsmath.c index 972d3d82f1..84fb7e555e 100755 --- a/src/sundials/shared/sundialsmath.c +++ b/src/sundials/shared/sundialsmath.c @@ -39,12 +39,14 @@ realtype RPowerI(realtype base, int exponent) return(prod); } +extern double hoc_pow(double, double); + realtype RPowerR(realtype base, realtype exponent) { if (base <= ZERO) return(ZERO); #if defined(SUNDIALS_USE_GENERIC_MATH) - return((realtype) pow((double) base, (double) exponent)); + return((realtype) hoc_pow((double) base, (double) exponent)); #elif defined(SUNDIALS_SINGLE_PRECISION) return(powf(base, exponent)); #elif defined(SUNDIALS_EXTENDED_PRECISION) @@ -79,7 +81,7 @@ realtype RAbs(realtype x) realtype RPower2(realtype x) { #if defined(SUNDIALS_USE_GENERIC_MATH) - return((realtype) pow((double) x, 2.0)); + return((realtype) hoc_pow((double) x, 2.0)); #elif defined(SUNDIALS_SINGLE_PRECISION) return(powf(x, TWO)); #elif defined(SUNDIALS_EXTENDED_PRECISION) From 13e183b09419c1e064ed72dab7bf005d8c134b39 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 24 Oct 2024 10:28:38 +0200 Subject: [PATCH 62/68] Arguments for nrnpy_pyCallObject are created with nanobind (#3140) --- src/nrnpython/nrnpy_p2h.cpp | 43 +++++++++++++------------------------ 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/src/nrnpython/nrnpy_p2h.cpp b/src/nrnpython/nrnpy_p2h.cpp index 6bfae26924..c9dc98db92 100644 --- a/src/nrnpython/nrnpy_p2h.cpp +++ b/src/nrnpython/nrnpy_p2h.cpp @@ -177,28 +177,22 @@ static void py2n_component(Object* ob, Symbol* sym, int nindex, int isfunc) { PyErr_Print(); hoc_execerror("No attribute:", sym->name); } - PyObject* args = 0; Object* on; PyObject* result = 0; if (isfunc) { - args = PyTuple_New(nindex); + nb::list args{}; for (i = 0; i < nindex; ++i) { - PyObject* arg = nrnpy_hoc_pop("isfunc py2n_component"); + nb::object arg = nb::steal(nrnpy_hoc_pop("isfunc py2n_component")); if (!arg) { PyErr2NRNString e; e.get_pyerr(); - Py_DECREF(args); hoc_execerr_ext("arg %d error: %s", i, e.c_str()); } - // PyObject_Print(arg, stdout, 0); - // printf(" %d arg %d\n", arg->ob_refcnt, i); - if (PyTuple_SetItem(args, nindex - 1 - i, arg)) { - assert(0); - } + args.append(arg); } + args.reverse(); // printf("PyObject_CallObject %s %p\n", sym->name, tail); - result = nrnpy_pyCallObject(nb::borrow(tail), nb::borrow(args)).release().ptr(); - Py_DECREF(args); + result = nrnpy_pyCallObject(nb::borrow(tail), args).release().ptr(); // PyObject_Print(result, stdout, 0); // printf(" result of call\n"); if (!result) { @@ -216,7 +210,7 @@ static void py2n_component(Object* ob, Symbol* sym, int nindex, int isfunc) { return; } } else if (nindex) { - PyObject* arg; + nb::object arg; int n = hoc_pop_ndim(); if (n > 1) { hoc_execerr_ext( @@ -226,15 +220,15 @@ static void py2n_component(Object* ob, Symbol* sym, int nindex, int isfunc) { n); } if (hoc_stack_type() == NUMBER) { - arg = Py_BuildValue("l", (long) hoc_xpop()); + arg = nb::int_((long) hoc_xpop()); } else { // I don't think it is syntactically possible // for this to be a VAR. It is possible for it to // be an Object but the GetItem below will raise // TypeError: list indices must be integers or slices, not hoc.HocObject - arg = nrnpy_hoc_pop("nindex py2n_component"); + arg = nb::steal(nrnpy_hoc_pop("nindex py2n_component")); } - result = PyObject_GetItem(tail, arg); + result = PyObject_GetItem(tail, arg.ptr()); if (!result) { PyErr_Print(); hoc_execerror("Python get item failed:", hoc_object_name(ob)); @@ -468,24 +462,17 @@ static double func_call(Object* ho, int narg, int* err) { nb::callable po = nb::borrow(((Py2Nrn*) ho->u.this_pointer)->po_); nanobind::gil_scoped_acquire lock{}; - PyObject* args = PyTuple_New((Py_ssize_t) narg); - if (args == NULL) { - hoc_execerror("PyTuple_New failed", 0); - } + nb::list args{}; for (int i = 0; i < narg; ++i) { - PyObject* item = nrnpy_hoc_pop("func_call"); - if (item == NULL) { - Py_XDECREF(args); + nb::object item = nb::steal(nrnpy_hoc_pop("func_call")); + if (!item) { hoc_execerror("nrnpy_hoc_pop failed", 0); } - if (PyTuple_SetItem(args, (Py_ssize_t) (narg - i - 1), item) != 0) { - Py_XDECREF(args); - hoc_execerror("PyTuple_SetItem failed", 0); - } + args.append(item); } + args.reverse(); - nb::object r = nrnpy_pyCallObject(po, nb::borrow(args)); - Py_XDECREF(args); + nb::object r = nrnpy_pyCallObject(po, args); double rval = 0.0; if (!r.is_valid()) { if (!err || *err) { From f8e94c53da9d59570e6922acef6715f85776ff2e Mon Sep 17 00:00:00 2001 From: adamjhn Date: Thu, 24 Oct 2024 14:59:12 -0400 Subject: [PATCH 63/68] Move reference data from test_rxd.py to test_rxd.json. (#3143) * Added a --save flag to regenerate the data. --------- Co-authored-by: nrnhines --- setup.py | 2 +- share/lib/python/neuron/tests/test_rxd.json | 666 +++++++++++++++++ share/lib/python/neuron/tests/test_rxd.py | 750 ++------------------ 3 files changed, 730 insertions(+), 688 deletions(-) create mode 100644 share/lib/python/neuron/tests/test_rxd.json diff --git a/setup.py b/setup.py index ba0922b273..05e8ca67e1 100644 --- a/setup.py +++ b/setup.py @@ -500,7 +500,7 @@ def setup_package(): name=package_name, package_dir={"": NRN_PY_ROOT}, packages=py_packages, - package_data={"neuron": ["*.dat"]}, + package_data={"neuron": ["*.dat", "tests/*.json"]}, ext_modules=extensions, scripts=[ os.path.join(NRN_PY_SCRIPTS, f) diff --git a/share/lib/python/neuron/tests/test_rxd.json b/share/lib/python/neuron/tests/test_rxd.json new file mode 100644 index 0000000000..10c681c18f --- /dev/null +++ b/share/lib/python/neuron/tests/test_rxd.json @@ -0,0 +1,666 @@ +{ + "trivial_ecs_data": { + "False": [ + 1.0, + 0.9999975013886804, + 0.9999774378669442, + 0.9998977298459816, + 0.999683249239208, + 0.999233095122319, + 0.9984342775161097, + 0.9971750000657644, + 0.9953548976762606, + 0.9928916564339986, + 0.9897243754423741, + 0.985814368310196, + 0.9811441475925942, + 0.9757152507508027, + 0.9695454356132381, + 0.9626656387440524, + 0.9551169704970437, + 0.9469479227048566, + 0.9382118896237476, + 0.928965047713157, + 0.9192646017261445, + 0.9091673798703476, + 0.8987287461912615, + 0.8880017910312052, + 0.8770367581645542, + 0.8658806682496021, + 0.8545771012638642, + 0.8431661046665001, + 0.8316841985149556, + 0.8201644532317675, + 0.8086366199145236, + 0.7971272968665187, + 0.7856601193366658, + 0.7742559622858297, + 0.7629331483660402, + 0.7517076552500634, + 0.7405933180308322, + 0.729602023674572, + 0.7187438955075627, + 0.7080274664897305, + 0.6974598406190147, + 0.6870468422535746, + 0.6767931534640339, + 0.666702439759881, + 0.6567774646932262, + 0.6470201939460375, + 0.6374318895671022, + 0.6280131950530249, + 0.618764211972033, + 0.6096845688168512, + 0.6007734827485834, + 0.592029814861357, + 0.5834521195604474, + 0.5750386886069674, + 0.566787590341624, + 0.5586967045597302, + 0.5507637534704564, + 0.542986329135765, + 0.5353619177489981, + 0.5278879210798492, + 0.520561675381579, + 0.5133804680278274, + 0.5063415521201762, + 0.4994421592836728, + 0.4926795108456907, + 0.4860508275736653, + 0.47955333812926787, + 0.47318428638032217, + 0.4669409376970896, + 0.46082058434632084, + 0.4548205500845658, + 0.44893819404152296, + 0.4431709139745962, + 0.437516148967192, + 0.4319713816355469, + 0.4265341399019367, + 0.42120199838589845, + 0.4159725794595267, + 0.41084355400792044, + 0.40581264193139277, + 0.40087761242206477, + 0.3960362840438892, + 0.3912865246419576, + 0.38662625110408755, + 0.3820534289951289, + 0.3775660720821487, + 0.37316224176661034, + 0.3688400464378394, + 0.3645976407604392, + 0.3604332249068622, + 0.356345043745043, + 0.3523313859898391, + 0.34839058332598377, + 0.3445210095093366, + 0.3407210794523858, + 0.33698924829922156, + 0.33332401049454546, + 0.3297238988506902, + 0.32618748361610794, + 0.3227133715483166, + 0.319300204993885 + ], + "0.01": [ + 1.0, + 1.0, + 1.0, + 0.9999999999993757, + 0.999999999994894, + 0.9999999999684935, + 0.9999999997476527, + 0.9999999928933891, + 0.9999999611564773, + 0.9999998797767268, + 0.9999996998881439, + 0.9999993374567407, + 0.9999984853833065, + 0.9999969740580187, + 0.9999944882384337, + 0.999990631594901, + 0.9999849509581288, + 0.9999769206381163, + 0.9999582122018839, + 0.99992971528816, + 0.9998885520830331, + 0.9998315279906315, + 0.9996818635176349, + 0.9994522087548297, + 0.9991215537513378, + 0.9986688188931263, + 0.9980737640971887, + 0.9973169807956457, + 0.9963810719470815, + 0.9952501731851596, + 0.9939108695612834, + 0.9923517494757513, + 0.990563762843154, + 0.9885402079277492, + 0.9862765182500737, + 0.9837701825347182, + 0.9810207339245086, + 0.9780291325294735, + 0.9747989764631944, + 0.9713343413786614, + 0.9676399370120405, + 0.961066451151739, + 0.9539287981955907, + 0.9462557577841545, + 0.9380908351574285, + 0.9295048630248105, + 0.9272938750656939, + 0.9250579717836777, + 0.9227970935562565, + 0.916466538640017, + 0.9099911643714976, + 0.903362145740033, + 0.896607665570261, + 0.8897506341029571, + 0.882783639668767, + 0.875743025331908, + 0.8686235564310014, + 0.8614266253277882, + 0.8541863694353786, + 0.8468993821613305, + 0.8395705411269264, + 0.8322240727536439, + 0.8248512178576504, + 0.8174717412783322, + 0.8101012803420092, + 0.8027295128162794, + 0.795382570912665, + 0.7880520562862553, + 0.7807347758418224, + 0.7734449586662135, + 0.7661975818043348, + 0.7589799271016704, + 0.7518171027828684, + 0.7446977692713531, + 0.7376160661849058, + 0.7305954685552188, + 0.7236266087584206, + 0.7167068363521265, + 0.7140993659873981, + 0.7115003569088247, + 0.7053989759513706, + 0.6937157033260776, + 0.6892286429757224, + 0.6847738597616794, + 0.680346043973446, + 0.6736943892225341, + 0.6671180984407125, + 0.662236424428377, + 0.6573969190546712, + 0.6525933206930011, + 0.6478347503609198, + 0.6431166994074956, + 0.6384369406609263, + 0.629051615757503, + 0.6198222188768284, + 0.6175428046075583, + 0.6152735586037428, + 0.6111170811525735, + 0.6031212235932468, + 0.5952593537962105, + 0.5921305073271925, + 0.589021543706074, + 0.5843049292559478, + 0.5796335964525046, + 0.57501603797955, + 0.5704420014938749, + 0.5659178448897603, + 0.5614455517225058, + 0.5591788147005415, + 0.5569248277948933, + 0.5506074431348664, + 0.5478382336692825, + 0.5450878675432425, + 0.5387888979259772, + 0.5362404522913171, + 0.5337094641249713, + 0.5282374991063938, + 0.5259248453123049, + 0.5236262813729924, + 0.5182614252948405, + 0.5158555311460749, + 0.5134660721175922, + 0.5077709278071862, + 0.5053179819941784, + 0.5028817741460606, + 0.49744076421889366, + 0.49520127183112733, + 0.4929770110029178, + 0.4880637158772831, + 0.4859684631915766, + 0.4838861487508862, + 0.4790294757925702, + 0.47687065162757547, + 0.47472669028331466, + 0.4696849124713687, + 0.4675266379954105, + 0.4653827515472591, + 0.46059622403775785, + 0.45860850681188087, + 0.4566341643290534, + 0.45222826180913167, + 0.4503369914749967, + 0.4484573582920104, + 0.4440766399353272, + 0.44214365209440704, + 0.4402239033393764, + 0.4357529446107943, + 0.4338466468246234, + 0.4319526748954548, + 0.42771940093115685, + 0.4259480291636831, + 0.42418839478752657, + 0.4202300998323772, + 0.4185239107729718, + 0.4168280791675472, + 0.4128821813954716, + 0.411151841187283, + 0.40943320175716824, + 0.4054591322631254, + 0.4037685048216922, + 0.40208843869666, + 0.39832558823662206, + 0.39674079574945603, + 0.3951663234845347, + 0.3916025661247801, + 0.3900627879465062, + 0.38853217065630374, + 0.3849784483231059, + 0.38342810283841006, + 0.38188806435279576, + 0.3783453864065237, + 0.37683971858666915, + 0.3753431215943966, + 0.37198272430919915, + 0.3705596473205069, + 0.369145673011817, + 0.36593017118156906, + 0.36453932880580625, + 0.363156559348617, + 0.35995389116692217, + 0.358562523467025, + 0.3571802314864285, + 0.35401195406372227, + 0.3526654576925955, + 0.35132677928092004, + 0.34831289231094187, + 0.34703074630323383, + 0.3457566587383628, + 0.3428492728160761, + 0.34159142512656304, + 0.34034067750180974, + 0.3374508889913977, + 0.33619956600663337, + 0.3349562466940476, + 0.33211336362253635, + 0.3309044582410871, + 0.3297023177069934, + 0.32698870975793815, + 0.32583004833643353, + 0.3246785486149972, + 0.322044467574018, + 0.3209052709390766, + 0.31977231337146067 + ], + "1e-05": [ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 0.9999999999999994, + 0.999999999999973, + 0.9999999999998286, + 0.9999999999994353, + 0.9999999999985202, + 0.9999999999965848, + 0.999999999991421, + 0.9999999999815654, + 0.999999999964278, + 0.999999999935795, + 0.9999999998244792, + 0.9999999995977931, + 0.9999999987558622, + 0.9999999969054565, + 0.9999999933717028, + 0.9999999871894636, + 0.9999999770945371, + 0.9999999615055236, + 0.9999999384936957, + 0.9999999057511308, + 0.9999998222204166, + 0.9999996889877318, + 0.9999994874837334, + 0.999999195494715, + 0.9999987869759616, + 0.9999978778927708, + 0.9999965094234947, + 0.9999945377974364, + 0.9999917976154723, + 0.9999881018395208, + 0.9999832421044165, + 0.99997698930736, + 0.9999690944252602, + 0.9999592894154012, + 0.9999401848217758, + 0.9999149868024333, + 0.9998825523031787, + 0.9998416677700266, + 0.999791059592578, + 0.9997294043566004, + 0.9996553389790277, + 0.9995674703998882, + 0.9994643850266823, + 0.9993446578768971, + 0.9992068613209312, + 0.9990495732666511, + 0.9988713847468418, + 0.9986709069017091, + 0.9984467774205655, + 0.9981976664057219, + 0.9979222816860815, + 0.9976193735297934, + 0.9972877388223238, + 0.9969262246908328, + 0.996533731653732, + 0.9961092162614316, + 0.9956516933112639, + 0.995160237588464, + 0.9946339852522628, + 0.9940721347820276, + 0.9934739476576494, + 0.9928387486094244, + 0.9921659257088754, + 0.9914549300102379, + 0.9907052751690002, + 0.9899165365563947, + 0.9890883505202034, + 0.9882204130405648, + 0.9873124787416938, + 0.9863643591450846, + 0.9853759215363472, + 0.9843470868598637, + 0.9832778285393545, + 0.9821681700454686, + 0.9810181837632249, + 0.9798279882523508, + 0.9785977472498147, + 0.9773276666315711, + 0.9760179936337368, + 0.9746690135138534, + 0.973281049070232, + 0.9718544574226932, + 0.970389628347756, + 0.9688869823638351, + 0.9662560899384262, + 0.9635203094788997, + 0.9606821993780256, + 0.9577444920812167, + 0.9547100690683178, + 0.9515819411366752, + 0.9483632227757351, + 0.9450571205495613, + 0.9416669020994433, + 0.9381959000999215, + 0.9346474739514014, + 0.9310250019996876, + 0.9273318651890746, + 0.9235714575523157, + 0.9197471440736972, + 0.9158622774695346, + 0.9119201741117782, + 0.9079241163948638, + 0.9038773101093882, + 0.8997829152661703, + 0.8956440506833048, + 0.8914637634703556, + 0.8872450198182428, + 0.8829907105064231, + 0.8787036576202755, + 0.8707492329414495, + 0.8687467372991504, + 0.8667391782827082, + 0.8647268018964069, + 0.862709850134354, + 0.8585978518713738, + 0.8544698540373321, + 0.8503277143424198, + 0.8461732532162092, + 0.8420082064910313, + 0.8378342644221053, + 0.8336530592192254, + 0.8294661713938566, + 0.8252750957253966, + 0.8210812732955917, + 0.8168861005800381, + 0.8126909232910099, + 0.808497028390498, + 0.801870527941527, + 0.7952548736200997, + 0.7886543612287468, + 0.7820730076362225, + 0.775514525626251, + 0.7689823476263041, + 0.76247965836786, + 0.756009378236416, + 0.749574210390875, + 0.743176642418555, + 0.7368189633320615, + 0.7305032399754438, + 0.724231346521673, + 0.7180049651772312, + 0.7118256478753264, + 0.7056948259233441, + 0.7032583360819944, + 0.700829860418756, + 0.6984094703765288, + 0.6959972339923495, + 0.6935932151265922, + 0.6889317429731345, + 0.6817668349582598, + 0.6746798126979188, + 0.6676718056770632, + 0.6607437321602112, + 0.6538963342916061, + 0.6471301405555971, + 0.6404455882961573, + 0.638787241606903, + 0.6371340113764097, + 0.6354859019485614, + 0.632317967018681, + 0.6291691359121044, + 0.624349241554268, + 0.619574789517913, + 0.614845708115443, + 0.6101619207501211, + 0.6055232995513015, + 0.6009296921089062, + 0.5963809255909179, + 0.5884265027887375, + 0.5806112287452613, + 0.5729337321697969, + 0.5653924576034643, + 0.5579857024960585, + 0.5561548262393686, + 0.5543322220611878, + 0.5525178614766851, + 0.5497619522652349, + 0.5470251014903538, + 0.5421958421956508, + 0.5374261214848611, + 0.5327153071436265, + 0.5280627574430141, + 0.5234678232476324, + 0.518929844460602, + 0.5144481596200524, + 0.5100220936639072, + 0.5056509822652775, + 0.501334134582734, + 0.497070898714232, + 0.492860583575257, + 0.488702496136303, + 0.4845959780644786, + 0.4805403496661883, + 0.4765349345681554, + 0.47257907275051975, + 0.46867209134329857, + 0.46481334795798307, + 0.4610021777856322, + 0.45723791746718145, + 0.4535199242983486, + 0.44984757092630373, + 0.4462202100082472, + 0.44263723745342903, + 0.4390980178177817, + 0.4356019204361891, + 0.43214835473501945, + 0.4287367135374875, + 0.4253663990336738, + 0.4220368326096732, + 0.41874742793163006, + 0.4154976298562691, + 0.41228686587129565, + 0.4091145679414439, + 0.40436315170089987, + 0.3996975358470319, + 0.3951158478239174, + 0.39061627014508404, + 0.3861970390853348, + 0.3841086119821148, + 0.3820380229802458, + 0.37998508572555983, + 0.3779496187417315, + 0.3745426919167079, + 0.3711844376968717, + 0.3678740151003091, + 0.3646106064268745, + 0.36139339169632445, + 0.3582215708412834, + 0.35509431859041374, + 0.35201085923465375, + 0.34897048346845855, + 0.345972428841367, + 0.3430159436132327, + 0.3401003270324417, + 0.3372248854371575, + 0.33438895086942516, + 0.33159183891956634, + 0.32883286088925856, + 0.32611135696096716, + 0.32342673756054513, + 0.320778362376132 + ] + }, + "scalar_bistable_data": [ + 4.666144368739565e-24, + 2.888704007378301e-23, + 1.9865049531958455e-22, + 1.3417088797559409e-21, + 8.872570814175612e-21, + 5.740880124662936e-20, + 3.632196361482048e-19, + 2.2456041210043948e-18, + 1.3557115052023306e-17, + 7.986451339137776e-17, + 4.587323676899687e-16, + 2.567045965818934e-15, + 1.398326895049454e-14, + 7.407949505967694e-14, + 3.8132509319176133e-13, + 1.905347304599464e-12, + 9.231798364410495e-12, + 4.33273265966826e-11, + 1.9674719569026998e-10, + 8.63399030466642e-10, + 3.657079221471436e-09, + 1.4932070567139546e-08, + 5.869401066025267e-08, + 2.218029569259483e-07, + 8.04721279962928e-07, + 2.79921382956858e-06, + 9.323183477925758e-06, + 2.969562407156746e-05, + 9.035408030381584e-05, + 0.0002623954841897342, + 0.0007269141545185264, + 0.0019207269099111785, + 0.004841879243431059, + 0.01164965343224167, + 0.02674863273052536, + 0.05846777500048251, + 0.12067994530088386, + 0.23084596756508963, + 0.3962758789592411, + 0.5900229199038892, + 0.7586218889021915, + 0.8722981880509894, + 0.9370823930113995, + 0.9705058492437157, + 0.9867204567968437, + 0.9942426940783657, + 0.9975977799681778, + 0.9990359504416326, + 0.9996249801006252, + 0.9998477834074035, + 0.9999041758657206, + 0.9998477834074035, + 0.9996249801006252, + 0.9990359504416326, + 0.9975977799681778, + 0.9942426940783657, + 0.9867204567968437, + 0.9705058492437147, + 0.9370823930113918, + 0.8722981880509718, + 0.75862188890219, + 0.5900229199038813, + 0.39627587895923605, + 0.2308459675650862, + 0.12067994530088234, + 0.058467775000481934, + 0.026748632730525093, + 0.011649653432241593, + 0.0048418792434310265, + 0.0019207269099111698, + 0.0007269141545185239, + 0.00026239548418973194, + 9.035408030381517e-05, + 2.9695624071567297e-05, + 9.323183477925707e-06, + 2.799213829568571e-06, + 8.04721279962927e-07, + 2.2180295692594684e-07, + 5.869401066025244e-08, + 1.4932070567139493e-08, + 3.6570792214714333e-09, + 8.633990304666437e-10, + 1.967471956902688e-10, + 4.332732659668245e-11, + 9.231798364410489e-12, + 1.9053473045994673e-12, + 3.813250931917625e-13, + 7.407949505967726e-14, + 1.3983268950494506e-14, + 2.5670459658189344e-15, + 4.587323676899693e-16, + 7.986451339137798e-17, + 1.3557115052023379e-17, + 2.2456041210043886e-18, + 3.632196361482047e-19, + 5.740880124662945e-20, + 8.872570814175644e-21, + 1.341708879755948e-21, + 1.9865049531958394e-22, + 2.8887040073782976e-23, + 4.66614436873957e-24 + ] +} \ No newline at end of file diff --git a/share/lib/python/neuron/tests/test_rxd.py b/share/lib/python/neuron/tests/test_rxd.py index db85696c90..dc6cd2aef8 100644 --- a/share/lib/python/neuron/tests/test_rxd.py +++ b/share/lib/python/neuron/tests/test_rxd.py @@ -2,7 +2,9 @@ import neuron import unittest import sys -from multiprocessing import Process +import os +import json +from multiprocessing import Process, Lock try: import multiprocessing as mp @@ -11,674 +13,12 @@ except: pass -scalar_bistable_data = [ - 4.666144368739553e-24, - 2.888704007378294e-23, - 1.986504953195841e-22, - 1.341708879755938e-21, - 8.872570814175589e-21, - 5.740880124662921e-20, - 3.632196361482038e-19, - 2.245604121004388e-18, - 1.355711505202327e-17, - 7.986451339137754e-17, - 4.587323676899676e-16, - 2.567045965818926e-15, - 1.398326895049450e-14, - 7.407949505967670e-14, - 3.813250931917600e-13, - 1.905347304599457e-12, - 9.231798364410461e-12, - 4.332732659668245e-11, - 1.967471956902693e-10, - 8.633990304666386e-10, - 3.657079221471421e-09, - 1.493207056713948e-08, - 5.869401066025243e-08, - 2.218029569259474e-07, - 8.047212799629250e-07, - 2.799213829568570e-06, - 9.323183477925731e-06, - 2.969562407156739e-05, - 9.035408030381566e-05, - 2.623954841897339e-04, - 7.269141545185255e-04, - 1.920726909911178e-03, - 4.841879243431064e-03, - 1.164965343224173e-02, - 2.674863273052559e-02, - 5.846777500048252e-02, - 1.206799453008834e-01, - 2.308459675650935e-01, - 3.962758789592548e-01, - 5.900229199039158e-01, - 7.586218889022415e-01, - 8.722981880510015e-01, - 9.370823930114011e-01, - 9.705058492437171e-01, - 9.867204567968444e-01, - 9.942426940783661e-01, - 9.975977799681778e-01, - 9.990359504416327e-01, - 9.996249801006252e-01, - 9.998477834074035e-01, - 9.999041758657206e-01, - 9.998477834074035e-01, - 9.996249801006252e-01, - 9.990359504416326e-01, - 9.975977799681777e-01, - 9.942426940783655e-01, - 9.867204567968437e-01, - 9.705058492437160e-01, - 9.370823930113995e-01, - 8.722981880509845e-01, - 7.586218889021992e-01, - 5.900229199038706e-01, - 3.962758789592359e-01, - 2.308459675650852e-01, - 1.206799453008814e-01, - 5.846777500048142e-02, - 2.674863273052497e-02, - 1.164965343224158e-02, - 4.841879243431020e-03, - 1.920726909911166e-03, - 7.269141545185224e-04, - 2.623954841897313e-04, - 9.035408030381501e-05, - 2.969562407156726e-05, - 9.323183477925702e-06, - 2.799213829568569e-06, - 8.047212799629269e-07, - 2.218029569259469e-07, - 5.869401066025247e-08, - 1.493207056713951e-08, - 3.657079221471437e-09, - 8.633990304666446e-10, - 1.967471956902691e-10, - 4.332732659668252e-11, - 9.231798364410503e-12, - 1.905347304599471e-12, - 3.813250931917631e-13, - 7.407949505967741e-14, - 1.398326895049453e-14, - 2.567045965818940e-15, - 4.587323676899705e-16, - 7.986451339137816e-17, - 1.355711505202341e-17, - 2.245604121004394e-18, - 3.632196361482056e-19, - 5.740880124662959e-20, - 8.872570814175665e-21, - 1.341708879755951e-21, - 1.986504953195844e-22, - 2.888704007378305e-23, - 4.666144368739581e-24, -] +# load the reference data from rxd_data.json +fdir = os.path.dirname(os.path.abspath(__file__)) +test_data = json.load(open(os.path.join(fdir, "test_rxd.json"), "r")) -trivial_ecs_data = { - False: [ - 1.000000000000000e00, - 9.999975013886804e-01, - 9.999774378669442e-01, - 9.998977298459814e-01, - 9.996832492392076e-01, - 9.992330951223182e-01, - 9.984342775161091e-01, - 9.971750000657639e-01, - 9.953548976762590e-01, - 9.928916564339932e-01, - 9.897243754423555e-01, - 9.858143683101370e-01, - 9.811441475924241e-01, - 9.757152507503439e-01, - 9.695454356120868e-01, - 9.626656387413414e-01, - 9.551169704910168e-01, - 9.469479226921377e-01, - 9.382118895981384e-01, - 9.289650476637475e-01, - 9.192646016344460e-01, - 9.091673797060952e-01, - 8.987287459064514e-01, - 8.880017905518656e-01, - 8.770367573796769e-01, - 8.658806669966089e-01, - 8.545770993099358e-01, - 8.431661016850746e-01, - 8.316841940567001e-01, - 8.201644466893430e-01, - 8.086366104805101e-01, - 7.971272834839320e-01, - 7.856601006415908e-01, - 7.742559365417961e-01, - 7.629331133899011e-01, - 7.517076083292696e-01, - 7.405932558321451e-01, - 7.296019421444131e-01, - 7.187437897643434e-01, - 7.080273307086645e-01, - 6.974596679100502e-01, - 6.870466245332152e-01, - 6.767928813219394e-01, - 6.667021023212317e-01, - 6.567770494779278e-01, - 6.470196867258985e-01, - 6.374312742221647e-01, - 6.280124534282580e-01, - 6.187633237355973e-01, - 6.096835113211366e-01, - 6.007722308951912e-01, - 5.920283409711493e-01, - 5.834503932497362e-01, - 5.750366766708355e-01, - 5.667852566452943e-01, - 5.586940099388136e-01, - 5.507606556408047e-01, - 5.429827826135633e-01, - 5.353578737816238e-01, - 5.278833275879240e-01, - 5.205564769125375e-01, - 5.133746057212193e-01, - 5.063349636848303e-01, - 4.994347789867492e-01, - 4.926712695135610e-01, - 4.860416526044784e-01, - 4.795431535169798e-01, - 4.731730127498988e-01, - 4.669284923505265e-01, - 4.608068813190689e-01, - 4.548055002118984e-01, - 4.489217050343421e-01, - 4.431528905041363e-01, - 4.374964927580476e-01, - 4.319499915664357e-01, - 4.265109121135835e-01, - 4.211768263954196e-01, - 4.159453542806875e-01, - 4.108141642766345e-01, - 4.057809740358395e-01, - 4.008435506368045e-01, - 3.959997106673694e-01, - 3.912473201368166e-01, - 3.865842942396779e-01, - 3.820085969917059e-01, - 3.775182407561858e-01, - 3.731112856767305e-01, - 3.687858390308746e-01, - 3.645400545171554e-01, - 3.603721314869148e-01, - 3.562803141307546e-01, - 3.522628906284160e-01, - 3.483181922698216e-01, - 3.444445925540838e-01, - 3.406405062724689e-01, - 3.369043885805584e-01, - 3.332347340641985e-01, - 3.296300758032397e-01, - 3.260889844365475e-01, - 3.226100672312980e-01, - 3.191919671591613e-01, - ], - 1e-2: [ - 1.000000000000000e00, - 1.000000000000000e00, - 1.000000000000000e00, - 9.999999999993757e-01, - 9.999999999948940e-01, - 9.999999999684935e-01, - 9.999999997476527e-01, - 9.999999928933891e-01, - 9.999999611564773e-01, - 9.999998797767268e-01, - 9.999996998881439e-01, - 9.999993374567406e-01, - 9.999984853833063e-01, - 9.999969740580184e-01, - 9.999944882384333e-01, - 9.999906315949002e-01, - 9.999849509581277e-01, - 9.999769206381147e-01, - 9.999582122018814e-01, - 9.999297152881566e-01, - 9.998885520830283e-01, - 9.998315279906250e-01, - 9.996818635176246e-01, - 9.994522087548142e-01, - 9.991215537513162e-01, - 9.986688188930973e-01, - 9.980737640971513e-01, - 9.973169807955987e-01, - 9.963810719470240e-01, - 9.952501731850908e-01, - 9.939108695612021e-01, - 9.923517494756579e-01, - 9.905637628430480e-01, - 9.885402079276301e-01, - 9.862765182499404e-01, - 9.837701825345700e-01, - 9.810207339243457e-01, - 9.780291325292961e-01, - 9.747989764630028e-01, - 9.713343413784561e-01, - 9.676399370118218e-01, - 9.610664511514549e-01, - 9.539287981952346e-01, - 9.462557577837218e-01, - 9.380908351569157e-01, - 9.295048630242134e-01, - 9.272938750650753e-01, - 9.250579717830375e-01, - 9.227970935555948e-01, - 9.164665386395120e-01, - 9.099911643711576e-01, - 9.033621457398684e-01, - 8.966076655702790e-01, - 8.897506341031615e-01, - 8.827836396691656e-01, - 8.757430253325005e-01, - 8.686235564317917e-01, - 8.614266253287830e-01, - 8.541863694365750e-01, - 8.468993821627302e-01, - 8.395705411285332e-01, - 8.322240727554534e-01, - 8.248512178596673e-01, - 8.174717412805539e-01, - 8.101012803444277e-01, - 8.027295128188973e-01, - 7.953825709154709e-01, - 7.880520562892473e-01, - 7.807347758450052e-01, - 7.734449586695845e-01, - 7.661975818078829e-01, - 7.589799271053987e-01, - 7.518171027867613e-01, - 7.446977692754075e-01, - 7.376160661891280e-01, - 7.305954685595947e-01, - 7.236266087629475e-01, - 7.167068363568081e-01, - 7.140993659912696e-01, - 7.115003569118910e-01, - 7.053989759515575e-01, - 6.937157033233743e-01, - 6.892286429728892e-01, - 6.847738597587193e-01, - 6.803460439703601e-01, - 6.736943892201644e-01, - 6.671180984390447e-01, - 6.622364244386257e-01, - 6.573969190766189e-01, - 6.525933207264888e-01, - 6.478347504056896e-01, - 6.431166994633450e-01, - 6.384369407276960e-01, - 6.290516157893640e-01, - 6.198222188748919e-01, - 6.175428045973979e-01, - 6.152735585854211e-01, - 6.111170811451881e-01, - 6.031212236479893e-01, - 5.952593539110380e-01, - 5.921305074751056e-01, - 5.890215438866859e-01, - 5.843049294344698e-01, - 5.796335966290896e-01, - 5.750160381540556e-01, - 5.704420016665088e-01, - 5.659178450605010e-01, - 5.614455518912613e-01, - 5.591788148460601e-01, - 5.569248279174298e-01, - 5.506074431743505e-01, - 5.478382336868175e-01, - 5.450878675391179e-01, - 5.387888979310328e-01, - 5.362404523147913e-01, - 5.337094641666161e-01, - 5.282374991972423e-01, - 5.259248454152894e-01, - 5.236262814879684e-01, - 5.182614254027890e-01, - 5.158555312376837e-01, - 5.134660721930772e-01, - 5.077709278344216e-01, - 5.053179820104490e-01, - 5.028817741515068e-01, - 4.974407642335685e-01, - 4.952012718592664e-01, - 4.929770110443390e-01, - 4.880637159524582e-01, - 4.859684632733423e-01, - 4.838861488391641e-01, - 4.790294758699501e-01, - 4.768706516921771e-01, - 4.747266903353097e-01, - 4.696849124915995e-01, - 4.675266380099869e-01, - 4.653827515562493e-01, - 4.605962240576634e-01, - 4.586085068420688e-01, - 4.566341643693850e-01, - 4.522282618718538e-01, - 4.503369915407668e-01, - 4.484573583607938e-01, - 4.440766399922996e-01, - 4.421436521416536e-01, - 4.402239033770282e-01, - 4.357529446279363e-01, - 4.338466468392896e-01, - 4.319526749076715e-01, - 4.277194009540304e-01, - 4.259480291942094e-01, - 4.241883948256027e-01, - 4.202300998848154e-01, - 4.185239108263153e-01, - 4.168280792217872e-01, - 4.128821814385824e-01, - 4.111518412231812e-01, - 4.094332017859506e-01, - 4.054591322790473e-01, - 4.037685048369686e-01, - 4.020884387112946e-01, - 3.983255882607288e-01, - 3.967407957791139e-01, - 3.951663235196693e-01, - 3.916025661686941e-01, - 3.900627879901100e-01, - 3.885321706996029e-01, - 3.849784483567140e-01, - 3.834281028668022e-01, - 3.818880643760414e-01, - 3.783453864220350e-01, - 3.768397186025170e-01, - 3.753431216105738e-01, - 3.719827243333056e-01, - 3.705596473485314e-01, - 3.691456730437073e-01, - 3.659301712184497e-01, - 3.645393288417587e-01, - 3.631565593836533e-01, - 3.599538911939479e-01, - 3.585625234903733e-01, - 3.571802315061479e-01, - 3.540119540790766e-01, - 3.526654577087503e-01, - 3.513267792978637e-01, - 3.483128923342382e-01, - 3.470307463292109e-01, - 3.457566587669847e-01, - 3.428492728471916e-01, - 3.415914251565042e-01, - 3.403406775305906e-01, - 3.374508890138111e-01, - 3.361995660265230e-01, - 3.349562467114465e-01, - 3.321133636377239e-01, - 3.309044582572311e-01, - 3.297023177240813e-01, - 3.269887097799309e-01, - 3.258300483601927e-01, - 3.246785486404988e-01, - 3.220444676004350e-01, - 3.209052709642934e-01, - 3.197723133954909e-01, - ], - 1e-5: [ - 1.000000000000000e00, - 1.000000000000000e00, - 1.000000000000000e00, - 1.000000000000000e00, - 1.000000000000000e00, - 1.000000000000000e00, - 1.000000000000000e00, - 1.000000000000000e00, - 9.999999999999994e-01, - 9.999999999999730e-01, - 9.999999999998286e-01, - 9.999999999994353e-01, - 9.999999999985202e-01, - 9.999999999965848e-01, - 9.999999999914210e-01, - 9.999999999815654e-01, - 9.999999999642780e-01, - 9.999999999357950e-01, - 9.999999998244792e-01, - 9.999999995977931e-01, - 9.999999987558622e-01, - 9.999999969054565e-01, - 9.999999933717028e-01, - 9.999999871894636e-01, - 9.999999770945371e-01, - 9.999999615055236e-01, - 9.999999384936957e-01, - 9.999999057511308e-01, - 9.999998222204165e-01, - 9.999996889877317e-01, - 9.999994874837332e-01, - 9.999991954947148e-01, - 9.999987869759613e-01, - 9.999978778927705e-01, - 9.999965094234943e-01, - 9.999945377974357e-01, - 9.999917976154713e-01, - 9.999881018395195e-01, - 9.999832421044147e-01, - 9.999769893073577e-01, - 9.999690944252573e-01, - 9.999592894153977e-01, - 9.999401848217710e-01, - 9.999149868024271e-01, - 9.998825523031706e-01, - 9.998416677700163e-01, - 9.997910595925650e-01, - 9.997294043565842e-01, - 9.996553389790078e-01, - 9.995674703998642e-01, - 9.994643850266534e-01, - 9.993446578768627e-01, - 9.992068613208905e-01, - 9.990495732666037e-01, - 9.988713847467867e-01, - 9.986709069016458e-01, - 9.984467774204933e-01, - 9.981976664056399e-01, - 9.979222816859891e-01, - 9.976193735296895e-01, - 9.972877388222079e-01, - 9.969262246907040e-01, - 9.965337316535895e-01, - 9.961092162612745e-01, - 9.956516933110915e-01, - 9.951602375882754e-01, - 9.946339852520572e-01, - 9.940721347818040e-01, - 9.934739476574072e-01, - 9.928387486091628e-01, - 9.921659257085935e-01, - 9.914549300099351e-01, - 9.907052751686757e-01, - 9.899165365560477e-01, - 9.890883505198331e-01, - 9.882204130401707e-01, - 9.873124787412751e-01, - 9.863643591446407e-01, - 9.853759215358775e-01, - 9.843470868593674e-01, - 9.832778285388312e-01, - 9.821681700449177e-01, - 9.810181837626457e-01, - 9.798279882517430e-01, - 9.785977472491776e-01, - 9.773276666309043e-01, - 9.760179936330398e-01, - 9.746690135131258e-01, - 9.732810490694735e-01, - 9.718544574219034e-01, - 9.703896283469345e-01, - 9.688869823629818e-01, - 9.662560899379753e-01, - 9.635203094788860e-01, - 9.606821993784824e-01, - 9.577444920821762e-01, - 9.547100690698106e-01, - 9.515819411387303e-01, - 9.483632227783803e-01, - 9.450571205528219e-01, - 9.416669021033438e-01, - 9.381959001044843e-01, - 9.346474739566473e-01, - 9.310250020056358e-01, - 9.273318651957428e-01, - 9.235714575597201e-01, - 9.197471440818522e-01, - 9.158622774784529e-01, - 9.119201741214706e-01, - 9.079241164053400e-01, - 9.038773101206564e-01, - 8.997829152782374e-01, - 8.956440506961761e-01, - 8.914637634840353e-01, - 8.872450198327338e-01, - 8.829907105217275e-01, - 8.787036576363941e-01, - 8.707492329602121e-01, - 8.687467373185769e-01, - 8.667391783027991e-01, - 8.647268019171629e-01, - 8.627098501557753e-01, - 8.585978518951599e-01, - 8.544698540634895e-01, - 8.503277143709528e-01, - 8.461732532471191e-01, - 8.420082065243172e-01, - 8.378342644577640e-01, - 8.336530592572513e-01, - 8.294661714342418e-01, - 8.252750957681314e-01, - 8.210812733406646e-01, - 8.168861006274361e-01, - 8.126909233407180e-01, - 8.084970284424999e-01, - 8.018705279973948e-01, - 7.952548736797830e-01, - 7.886543612921902e-01, - 7.820730077033664e-01, - 7.755145256970315e-01, - 7.689823477006539e-01, - 7.624796584457091e-01, - 7.560093783176929e-01, - 7.495742104755058e-01, - 7.431766425064636e-01, - 7.368189634231701e-01, - 7.305032400696735e-01, - 7.242313466189446e-01, - 7.180049652774664e-01, - 7.118256479784464e-01, - 7.056948260292686e-01, - 7.032583361895295e-01, - 7.008298605278855e-01, - 6.984094704872370e-01, - 6.959972341046202e-01, - 6.935932152404094e-01, - 6.889317430774708e-01, - 6.817668350489530e-01, - 6.746798127752269e-01, - 6.676718057412527e-01, - 6.607437322115557e-01, - 6.538963343303841e-01, - 6.471301405820917e-01, - 6.404455883106537e-01, - 6.387872416184449e-01, - 6.371340113850150e-01, - 6.354859019542481e-01, - 6.323179670207283e-01, - 6.291691359105558e-01, - 6.243492415503886e-01, - 6.195747895117473e-01, - 6.148457081070352e-01, - 6.101619207395151e-01, - 6.055232995385412e-01, - 6.009296920940354e-01, - 5.963809255739797e-01, - 5.884265027623434e-01, - 5.806112287097513e-01, - 5.729337321255051e-01, - 5.653924575507177e-01, - 5.579857024351769e-01, - 5.561548261765027e-01, - 5.543322219963571e-01, - 5.525178614099090e-01, - 5.497619521958399e-01, - 5.470251014183799e-01, - 5.421958421339816e-01, - 5.374261214332550e-01, - 5.327153071018452e-01, - 5.280627574108234e-01, - 5.234678232248013e-01, - 5.189298444469039e-01, - 5.144481596152644e-01, - 5.100220936678099e-01, - 5.056509822776560e-01, - 5.013341346033774e-01, - 4.970708987429328e-01, - 4.928605836118120e-01, - 4.887024961805134e-01, - 4.845959781161491e-01, - 4.805403497251276e-01, - 4.765349346341766e-01, - 4.725790728234394e-01, - 4.686720914229373e-01, - 4.648133480441644e-01, - 4.610021778781840e-01, - 4.572379175659361e-01, - 4.535199244031417e-01, - 4.498475710369739e-01, - 4.462202101246375e-01, - 4.426372375753840e-01, - 4.390980179451507e-01, - 4.356019205688260e-01, - 4.321483548727800e-01, - 4.287367136802313e-01, - 4.253663991812640e-01, - 4.220368327619753e-01, - 4.187474280885136e-01, - 4.154976300176047e-01, - 4.122868660369579e-01, - 4.091145681113114e-01, - 4.043631518312791e-01, - 3.996975359393022e-01, - 3.951158478794149e-01, - 3.906162701651016e-01, - 3.861970390711226e-01, - 3.841086119708872e-01, - 3.820380229719526e-01, - 3.799850857201517e-01, - 3.779496187391600e-01, - 3.745426919402392e-01, - 3.711844377457629e-01, - 3.678740151738357e-01, - 3.646106065243293e-01, - 3.613933918170190e-01, - 3.582215709845467e-01, - 3.550943187555968e-01, - 3.520108594211252e-01, - 3.489704836755959e-01, - 3.459724290685680e-01, - 3.430159438599149e-01, - 3.401003272980346e-01, - 3.372248857211048e-01, - 3.343889511711801e-01, - 3.315918392385992e-01, - 3.288328612250609e-01, - 3.261113573130471e-01, - 3.234267379284118e-01, - 3.207783627593125e-01, - ], -} - -def scalar_bistable(): +def scalar_bistable(lock, path=None): from neuron import rxd h.load_file("stdrun.hoc") @@ -694,15 +34,25 @@ def scalar_bistable(): # check the results result = h.Vector(c.nodes.concentration) - cmpV = h.Vector(scalar_bistable_data) - cmpV.sub(result) - cmpV.abs() - if cmpV.sum() < 1e-6: - sys.exit(0) - sys.exit(-1) - - -def trivial_ecs(scale): + if path is not None: + lock.acquire() + if os.path.exists(path): + data = json.load(open(path, "r")) + else: + data = {} + data["scalar_bistable_data"] = list(result) + json.dump(data, open(path, "w"), indent=4) + lock.release() + else: + cmpV = h.Vector(test_data["scalar_bistable_data"]) + cmpV.sub(result) + cmpV.abs() + if cmpV.sum() >= 1e-6: + sys.exit(-1) + sys.exit(0) + + +def trivial_ecs(scale, lock, path=None): from neuron import h, crxd as rxd import numpy import warnings @@ -714,6 +64,7 @@ def trivial_ecs(scale): h.CVode().active(True) h.CVode().event(tstop) else: # fixed step case + h.CVode().active(False) h.dt = 0.1 sec = h.Section() # NEURON requires at least 1 section @@ -757,40 +108,63 @@ def trivial_ecs(scale): h.finitialize() h.continuerun(tstop) # run the simulation - # compare with previous solution - ecs_vec.sub(h.Vector(trivial_ecs_data[scale])) - ecs_vec.abs() - if ecs_vec.sum() > 1e-9: - return -1 - return 0 + if path is not None: + lock.acquire() + if os.path.exists(path): + data = json.load(open(path, "r")) + else: + data = {} + if "trivial_ecs_data" not in data: + data["trivial_ecs_data"] = {} + data["trivial_ecs_data"][str(scale)] = list(ecs_vec) + json.dump(data, open(path, "w"), indent=4) + lock.release() + else: + # compare with previous solution + ecs_vec.sub(h.Vector(test_data["trivial_ecs_data"][str(scale)])) + ecs_vec.abs() + if ecs_vec.sum() > 1e-9: + sys.exit(-1) + sys.exit(0) class RxDTestCase(unittest.TestCase): """Tests of rxd""" + @classmethod + def setUpClass(cls): + # Check for --save in command-line arguments + cls.path = None + cls.lock = Lock() + if len(sys.argv) > 1: + for arg1, arg2 in zip(sys.argv, sys.argv[1:]): + if arg1 == "--save": + cls.path = arg2 + break + def test_rxd(self): - p = Process(target=scalar_bistable) + p = Process(target=scalar_bistable, args=(self.lock, self.path)) p.start() p.join() assert p.exitcode == 0 return 0 def test_ecs_diffusion_fixed_step(self): - p = Process(target=trivial_ecs, args=(False,)) + p = Process(target=trivial_ecs, args=(False, self.lock, self.path)) p.start() p.join() assert p.exitcode == 0 return 0 def test_ecs_diffusion_variable_step_coarse(self): - p = Process(target=trivial_ecs, args=(1e-2,)) + p = Process(target=trivial_ecs, args=(1e-2, self.lock, self.path)) p.start() p.join() assert p.exitcode == 0 return 0 def test_ecs_diffusion_variable_step_fine(self): - p = Process(target=trivial_ecs, args=(1e-5,)) + p = Process(target=trivial_ecs, args=(1e-5, self.lock, self.path)) p.start() p.join() assert p.exitcode == 0 @@ -807,5 +181,7 @@ def test(): if __name__ == "__main__": - # unittest.main() + """Run the rxd tests unless --save is given, in which case save the + test data to that path without comparing the results to the reference data. + """ test() From cd7ac7dd9635384e3cce28cc7dcc482afa98ea54 Mon Sep 17 00:00:00 2001 From: nrnhines Date: Thu, 24 Oct 2024 20:41:03 -0400 Subject: [PATCH 64/68] Code change for ion and ion style semantics. Unlimited numbers. (#3097) --------- Co-authored-by: Luc Grosheintz --- cmake/NeuronFileLists.cmake | 1 + src/coreneuron/io/nrn_checkpoint.cpp | 6 ++++-- src/coreneuron/io/phase2.cpp | 5 +++-- src/coreneuron/mechanism/register_mech.cpp | 9 +++++---- src/coreneuron/permute/node_permute.cpp | 5 +++-- src/neuron/cache/mechanism_range.hpp | 2 +- .../nrncore_write/callbacks/nrncore_callbacks.cpp | 6 +++--- src/nrniv/nrncore_write/data/cell_group.cpp | 6 +++--- src/nrniv/nrncore_write/data/cell_group.h | 4 ++-- src/nrnoc/init.cpp | 4 ++-- src/nrnoc/ion_semantics.h | 14 ++++++++++++++ src/nrnoc/membfunc.h | 1 + 12 files changed, 42 insertions(+), 21 deletions(-) create mode 100644 src/nrnoc/ion_semantics.h diff --git a/cmake/NeuronFileLists.cmake b/cmake/NeuronFileLists.cmake index d8b03dae3a..47dd1dcc93 100644 --- a/cmake/NeuronFileLists.cmake +++ b/cmake/NeuronFileLists.cmake @@ -21,6 +21,7 @@ set(HEADER_FILES_TO_INSTALL nrnoc/md1redef.h nrnoc/md2redef.h nrnoc/membdef.h + nrnoc/ion_semantics.h nrnoc/membfunc.h nrnoc/multicore.h nrnoc/multisplit.h diff --git a/src/coreneuron/io/nrn_checkpoint.cpp b/src/coreneuron/io/nrn_checkpoint.cpp index ed91d7de81..c7c7743ed9 100644 --- a/src/coreneuron/io/nrn_checkpoint.cpp +++ b/src/coreneuron/io/nrn_checkpoint.cpp @@ -11,6 +11,7 @@ #include #include +#include "nrnoc/ion_semantics.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/io/nrn_filehandler.hpp" @@ -296,8 +297,9 @@ void CheckPoints::write_phase2(NrnThread& nt) const { // out into the following function. d[ix] = nrn_original_aos_index(ptype, d[ix], nt, ml_pinv); } - } else if (s >= 0 && s < 1000) { // ion - d[ix] = nrn_original_aos_index(s, d[ix], nt, ml_pinv); + } else if (nrn_semantics_is_ion(s)) { // ion + auto type = nrn_semantics_ion_type(s); + d[ix] = nrn_original_aos_index(type, d[ix], nt, ml_pinv); } #if CHKPNTDEBUG if (s != -8) { // WATCH values change diff --git a/src/coreneuron/io/phase2.cpp b/src/coreneuron/io/phase2.cpp index 19fb12e8a3..3c712f1f5b 100644 --- a/src/coreneuron/io/phase2.cpp +++ b/src/coreneuron/io/phase2.cpp @@ -6,6 +6,7 @@ # ============================================================================= */ +#include "nrnoc/ion_semantics.h" #include "coreneuron/io/phase2.hpp" #include "coreneuron/coreneuron.hpp" #include "coreneuron/sim/multicore.hpp" @@ -699,8 +700,8 @@ void Phase2::pdata_relocation(const NrnThread& nt, const std::vector& **/ break; default: - if (s >= 0 && s < 1000) { // ion - int etype = s; + if (nrn_semantics_is_ion(s)) { // ion + int etype = nrn_semantics_ion_type(s); /* if ion is SoA, must recalculate pdata values */ /* if ion is AoS, have to deal with offset */ Memb_list* eml = nt._ml_list[etype]; diff --git a/src/coreneuron/mechanism/register_mech.cpp b/src/coreneuron/mechanism/register_mech.cpp index 260d420411..2ef95e976f 100644 --- a/src/coreneuron/mechanism/register_mech.cpp +++ b/src/coreneuron/mechanism/register_mech.cpp @@ -9,6 +9,7 @@ #include #include "coreneuron/nrnconf.h" +#include "nrnoc/ion_semantics.h" #include "coreneuron/sim/multicore.hpp" #include "coreneuron/membrane_definitions.h" #include "coreneuron/mechanism/eion.hpp" @@ -212,7 +213,7 @@ void hoc_register_dparam_semantics(int type, int ix, const char* name) { xx_ion and #xx_ion which will get a semantics value of -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, - type, and type+1000 respectively + 2*type, and 2*type+1 respectively */ auto& memb_func = corenrn.get_memb_funcs(); if (strcmp(name, "area") == 0) { @@ -240,7 +241,7 @@ void hoc_register_dparam_semantics(int type, int ix, const char* name) { } else { int i = name[0] == '#' ? 1 : 0; int etype = nrn_get_mechtype(name + i); - memb_func[type].dparam_semantics[ix] = etype + i * 1000; + memb_func[type].dparam_semantics[ix] = nrn_semantics_from_ion(etype, i); /* note that if style is needed (i==1), then we are writing a concentration */ if (i) { ion_write_depend(type, etype); @@ -300,8 +301,8 @@ int nrn_mech_depend(int type, int* dependencies) { int idep = 0; if (ds) for (int i = 0; i < dpsize; ++i) { - if (ds[i] > 0 && ds[i] < 1000) { - int deptype = ds[i]; + if (nrn_semantics_is_ion(ds[i])) { + int deptype = nrn_semantics_ion_type(ds[i]); int idepnew = depend_append(idep, dependencies, deptype, type); if ((idepnew > idep) && !corenrn.get_ion_write_dependency().empty() && !corenrn.get_ion_write_dependency()[deptype].empty()) { diff --git a/src/coreneuron/permute/node_permute.cpp b/src/coreneuron/permute/node_permute.cpp index a19230b4fc..eb33da0991 100644 --- a/src/coreneuron/permute/node_permute.cpp +++ b/src/coreneuron/permute/node_permute.cpp @@ -94,6 +94,7 @@ so pdata_m(k, isz) = inew + data_t #include "coreneuron/nrniv/nrniv_decl.h" #include "coreneuron/utils/nrn_assert.h" #include "coreneuron/coreneuron.hpp" +#include "nrnoc/ion_semantics.h" #else #include "nrnoc/multicore.h" #include "oc/nrnassrt.h" @@ -333,8 +334,8 @@ static void update_pdata_values(Memb_list* ml, int type, NrnThread& nt) { nrn_assert(0); } } - } else if (s >= 0 && s < 1000) { // ion - int etype = s; + } else if (nrn_semantics_is_ion(s)) { // ion + int etype = nrn_semantics_ion_type(s); int elayout = corenrn.get_mech_data_layout()[etype]; Memb_list* eml = nt._ml_list[etype]; int edata0 = eml->data - nt._data; diff --git a/src/neuron/cache/mechanism_range.hpp b/src/neuron/cache/mechanism_range.hpp index 4a332ebb06..8cca0ce44d 100644 --- a/src/neuron/cache/mechanism_range.hpp +++ b/src/neuron/cache/mechanism_range.hpp @@ -22,7 +22,7 @@ void indices_to_cache(short type, Callable callable) { auto const sem = dparam_semantics[field]; // See https://github.com/neuronsimulator/nrn/issues/2312 for discussion of possible // extensions to caching. - if ((sem > 0 && sem < 1000) || sem == -1 /* area */ || sem == -9 /* diam */) { + if (nrn_semantics_is_ion(sem) || sem == -1 /* area */ || sem == -9 /* diam */) { std::invoke(callable, field); } } diff --git a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp index 158ae0c028..a91b69ec14 100644 --- a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp +++ b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp @@ -670,10 +670,10 @@ int* datum2int(int type, } } else if (etype == -9) { pdata[jj] = eindex; - } else if (etype > 0 && etype < 1000) { // ion pointer + } else if (nrn_semantics_is_ion(etype)) { // ion pointer pdata[jj] = eindex; - } else if (etype > 1000 && etype < 2000) { // ionstyle can be explicit instead of - // pointer to int* + } else if (nrn_semantics_is_ionstyle(etype)) { + // ionstyle can be explicit instead of pointer to int* pdata[jj] = eindex; } else if (etype == -2) { // an ion and this is the iontype pdata[jj] = eindex; diff --git a/src/nrniv/nrncore_write/data/cell_group.cpp b/src/nrniv/nrncore_write/data/cell_group.cpp index e034359387..8ee75d4191 100644 --- a/src/nrniv/nrncore_write/data/cell_group.cpp +++ b/src/nrniv/nrncore_write/data/cell_group.cpp @@ -343,15 +343,15 @@ void CellGroup::datumindex_fill(int ith, CellGroup& cg, DatumIndices& di, Memb_l } assert(etype != 0); // pointer into one of the tml types? - } else if (dmap[j] > 0 && dmap[j] < 1000) { // double* into eion type data - etype = dmap[j]; + } else if (nrn_semantics_is_ion(dmap[j])) { // double* into eion type data + etype = nrn_semantics_ion_type(dmap[j]); Memb_list* eml = cg.type2ml[etype]; assert(eml); auto* const pval = dparam[j].get(); auto const legacy_index = eml->legacy_index(pval); assert(legacy_index >= 0); eindex = legacy_index; - } else if (dmap[j] > 1000) { // int* into ion dparam[xxx][0] + } else if (nrn_semantics_is_ionstyle(dmap[j])) { // int* into ion dparam[xxx][0] // store the actual ionstyle etype = dmap[j]; eindex = *dparam[j].get(); diff --git a/src/nrniv/nrncore_write/data/cell_group.h b/src/nrniv/nrncore_write/data/cell_group.h index 374c2a2510..e86b1500cb 100644 --- a/src/nrniv/nrncore_write/data/cell_group.h +++ b/src/nrniv/nrncore_write/data/cell_group.h @@ -32,8 +32,8 @@ class CellGroup { // following three are parallel arrays std::vector output_ps; // n_presyn of these, real are first, tml order for acell. std::vector output_gid; // n_presyn of these, -(type + 1000*index) if no gid - std::vector output_vindex; // n_presyn of these. >=0 if associated with voltage, -(type + - // 1000*index) for acell. + std::vector output_vindex; // n_presyn of these. >=0 if associated with voltage, + // -(type + 1000*index) for acell. int n_netcon; // all that have targets associated with this threads Point_process. std::vector netcons; int* netcon_srcgid; // -(type + 1000*index) refers to acell with no gid diff --git a/src/nrnoc/init.cpp b/src/nrnoc/init.cpp index 267eac5c55..f77c107137 100644 --- a/src/nrnoc/init.cpp +++ b/src/nrnoc/init.cpp @@ -765,7 +765,7 @@ namespace { */ // name to int map for the negative types -// xx_ion and #xx_ion will get values of type and type+1000 respectively +// xx_ion and #xx_ion will get values of type*2 and type*2+1 respectively static std::unordered_map name_to_negint = {{"area", -1}, {"iontype", -2}, {"cvodeieq", -3}, @@ -785,7 +785,7 @@ int dparam_semantics_to_int(std::string_view name) { bool const i{name[0] == '#'}; Symbol* s = hoc_lookup(std::string{name.substr(i)}.c_str()); if (s && s->type == MECHANISM) { - return s->subtype + i * 1000; + return nrn_semantics_from_ion(s->subtype, i); } throw std::runtime_error("unknown dparam semantics: " + std::string{name}); } diff --git a/src/nrnoc/ion_semantics.h b/src/nrnoc/ion_semantics.h new file mode 100644 index 0000000000..2a3dfc8253 --- /dev/null +++ b/src/nrnoc/ion_semantics.h @@ -0,0 +1,14 @@ +#pragma once + +inline int nrn_semantics_from_ion(int type, int i) { + return 2 * type + i; +} +inline bool nrn_semantics_is_ion(int i) { + return i >= 0 && (i & 1) == 0; +} +inline bool nrn_semantics_is_ionstyle(int i) { + return i >= 0 && (i & 1) == 1; +} +inline int nrn_semantics_ion_type(int i) { + return i / 2; +} diff --git a/src/nrnoc/membfunc.h b/src/nrnoc/membfunc.h index ad80ed9d7e..18647c19b7 100644 --- a/src/nrnoc/membfunc.h +++ b/src/nrnoc/membfunc.h @@ -5,6 +5,7 @@ extern void hoc_register_prop_size(int type, int psize, int dpsize); #include "nrnoc_ml.h" #include "oc_ansi.h" // neuron::model_sorted_token #include "options.h" // EXTRACELLULAR +#include "ion_semantics.h" #include #include From d52f6ae252c966e564fc9631df315158c827a214 Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Wed, 30 Oct 2024 15:12:07 +0100 Subject: [PATCH 65/68] Constify OcMatrix (#3148) Minify usage of mep as it get a non stable pointer on the matrix itself. --- src/ivoc/matrix.cpp | 17 ++-- src/ivoc/ocmatrix.cpp | 83 ++++++++++--------- src/ivoc/ocmatrix.h | 123 +++++++++++++++------------- src/nrniv/matrixmap.cpp | 16 ++-- src/nrniv/matrixmap.h | 2 +- src/nrnpython/rxd.cpp | 14 ++-- src/nrnpython/rxd_extracellular.cpp | 55 ++++++------- test/unit_tests/matrix.cpp | 5 ++ 8 files changed, 162 insertions(+), 153 deletions(-) diff --git a/src/ivoc/matrix.cpp b/src/ivoc/matrix.cpp index 8fa098d61d..ddc8d41cfa 100644 --- a/src/ivoc/matrix.cpp +++ b/src/ivoc/matrix.cpp @@ -64,13 +64,10 @@ static double m_ncol(void* v) { static double m_setval(void* v) { Matrix* m = (Matrix*) v; - int i, j; - double val, *pval; - i = (int) chkarg(1, 0, m->nrow() - 1); - j = (int) chkarg(2, 0, m->ncol() - 1); - val = *getarg(3); - pval = m->mep(i, j); - *pval = val; + int i = (int) chkarg(1, 0, m->nrow() - 1); + int j = (int) chkarg(2, 0, m->ncol() - 1); + double val = *getarg(3); + m->coeff(i, j) = val; return val; } @@ -171,7 +168,7 @@ static double m_scanf(void* v) { m->resize(nrow, ncol); for (i = 0; i < nrow; ++i) for (j = 0; j < ncol; ++j) { - *(m->mep(i, j)) = hoc_scan(f); + m->coeff(i, j) = hoc_scan(f); } return 0.; } @@ -602,7 +599,7 @@ static Object** m_set(void* v) { int k; for (k = 0, i = 0; i < nrow; ++i) { for (j = 0; j < ncol; ++j) { - *(m->mep(i, j)) = *getarg(++k); + m->coeff(i, j) = *getarg(++k); } } return temp_objvar(m); @@ -641,7 +638,7 @@ static Object** m_from_vector(void* v) { double* ve = vector_vec(vout); for (j = 0; j < ncol; ++j) for (i = 0; i < nrow; ++i) { - *(m->mep(i, j)) = ve[k++]; + m->coeff(i, j) = ve[k++]; } return temp_objvar(m); } diff --git a/src/ivoc/ocmatrix.cpp b/src/ivoc/ocmatrix.cpp index 7afa87498a..593bdef793 100644 --- a/src/ivoc/ocmatrix.cpp +++ b/src/ivoc/ocmatrix.cpp @@ -34,21 +34,20 @@ OcMatrix* OcMatrix::instance(int nrow, int ncol, int type) { } } -void OcMatrix::unimp() { - hoc_execerror("Matrix method not implemented for this type matrix", 0); +void OcMatrix::unimp() const { + hoc_execerror("Matrix method not implemented for this type matrix", nullptr); } -void OcMatrix::nonzeros(std::vector& m, std::vector& n) { - m.clear(); - n.clear(); +std::vector> OcMatrix::nonzeros() const { + std::vector> nzs; for (int i = 0; i < nrow(); i++) { for (int j = 0; j < ncol(); j++) { - if (getval(i, j) != 0) { - m.push_back(i); - n.push_back(j); + if (getval(i, j) != 0.) { + nzs.emplace_back(i, j); } } } + return nzs; } OcFullMatrix* OcMatrix::full() { @@ -65,16 +64,16 @@ OcFullMatrix::OcFullMatrix(int nrow, int ncol) m_.setZero(); } -double* OcFullMatrix::mep(int i, int j) { - return &m_(i, j); +double& OcFullMatrix::coeff(int i, int j) { + return m_(i, j); } -double OcFullMatrix::getval(int i, int j) { +double OcFullMatrix::getval(int i, int j) const { return m_(i, j); } -int OcFullMatrix::nrow() { +int OcFullMatrix::nrow() const { return m_.rows(); } -int OcFullMatrix::ncol() { +int OcFullMatrix::ncol() const { return m_.cols(); } @@ -84,29 +83,29 @@ void OcFullMatrix::resize(int i, int j) { m_.conservativeResizeLike(v); } -void OcFullMatrix::mulv(Vect* vin, Vect* vout) { +void OcFullMatrix::mulv(Vect* vin, Vect* vout) const { auto v1 = Vect2VEC(vin); auto v2 = Vect2VEC(vout); v2 = m_ * v1; } -void OcFullMatrix::mulm(Matrix* in, Matrix* out) { +void OcFullMatrix::mulm(Matrix* in, Matrix* out) const { out->full()->m_ = m_ * in->full()->m_; } -void OcFullMatrix::muls(double s, Matrix* out) { +void OcFullMatrix::muls(double s, Matrix* out) const { out->full()->m_ = s * m_; } -void OcFullMatrix::add(Matrix* in, Matrix* out) { +void OcFullMatrix::add(Matrix* in, Matrix* out) const { out->full()->m_ = m_ + in->full()->m_; } -void OcFullMatrix::copy(Matrix* out) { +void OcFullMatrix::copy(Matrix* out) const { out->full()->m_ = m_; } -void OcFullMatrix::bcopy(Matrix* out, int i0, int j0, int n0, int m0, int i1, int j1) { +void OcFullMatrix::bcopy(Matrix* out, int i0, int j0, int n0, int m0, int i1, int j1) const { out->full()->m_.block(i1, j1, n0, m0) = m_.block(i0, j0, n0, m0); } @@ -119,14 +118,14 @@ void OcFullMatrix::transpose(Matrix* out) { } // As only symmetric matrix are accepted, eigenvalues are not complex -void OcFullMatrix::symmeigen(Matrix* mout, Vect* vout) { +void OcFullMatrix::symmeigen(Matrix* mout, Vect* vout) const { auto v1 = Vect2VEC(vout); Eigen::EigenSolver es(m_); v1 = es.eigenvalues().real(); mout->full()->m_ = es.eigenvectors().real(); } -void OcFullMatrix::svd1(Matrix* u, Matrix* v, Vect* d) { +void OcFullMatrix::svd1(Matrix* u, Matrix* v, Vect* d) const { auto v1 = Vect2VEC(d); Eigen::JacobiSVD svd(m_, Eigen::ComputeFullU | Eigen::ComputeFullV); v1 = svd.singularValues(); @@ -138,17 +137,17 @@ void OcFullMatrix::svd1(Matrix* u, Matrix* v, Vect* d) { } } -void OcFullMatrix::getrow(int k, Vect* out) { +void OcFullMatrix::getrow(int k, Vect* out) const { auto v1 = Vect2VEC(out); v1 = m_.row(k); } -void OcFullMatrix::getcol(int k, Vect* out) { +void OcFullMatrix::getcol(int k, Vect* out) const { auto v1 = Vect2VEC(out); v1 = m_.col(k); } -void OcFullMatrix::getdiag(int k, Vect* out) { +void OcFullMatrix::getdiag(int k, Vect* out) const { auto vout = m_.diagonal(k); if (k >= 0) { for (int i = 0, j = k; i < nrow() && j < ncol(); ++i, ++j) { @@ -205,15 +204,15 @@ void OcFullMatrix::ident() { m_.setIdentity(); } -void OcFullMatrix::exp(Matrix* out) { +void OcFullMatrix::exp(Matrix* out) const { out->full()->m_ = m_.exp(); } -void OcFullMatrix::pow(int i, Matrix* out) { +void OcFullMatrix::pow(int i, Matrix* out) const { out->full()->m_ = m_.pow(i).eval(); } -void OcFullMatrix::inverse(Matrix* out) { +void OcFullMatrix::inverse(Matrix* out) const { out->full()->m_ = m_.inverse(); } @@ -226,7 +225,7 @@ void OcFullMatrix::solv(Vect* in, Vect* out, bool use_lu) { v2 = lu_->solve(v1); } -double OcFullMatrix::det(int* e) { +double OcFullMatrix::det(int* e) const { *e = 0; double m = m_.determinant(); if (m) { @@ -248,8 +247,8 @@ OcSparseMatrix::OcSparseMatrix(int nrow, int ncol) : OcMatrix(MSPARSE) , m_(nrow, ncol) {} -double* OcSparseMatrix::mep(int i, int j) { - return &m_.coeffRef(i, j); +double& OcSparseMatrix::coeff(int i, int j) { + return m_.coeffRef(i, j); } void OcSparseMatrix::zero() { @@ -260,19 +259,19 @@ void OcSparseMatrix::zero() { } } -double OcSparseMatrix::getval(int i, int j) { +double OcSparseMatrix::getval(int i, int j) const { return m_.coeff(i, j); } -int OcSparseMatrix::nrow() { +int OcSparseMatrix::nrow() const { return m_.rows(); } -int OcSparseMatrix::ncol() { +int OcSparseMatrix::ncol() const { return m_.cols(); } -void OcSparseMatrix::mulv(Vect* vin, Vect* vout) { +void OcSparseMatrix::mulv(Vect* vin, Vect* vout) const { auto v1 = Vect2VEC(vin); auto v2 = Vect2VEC(vout); v2 = m_ * v1; @@ -330,7 +329,7 @@ void OcSparseMatrix::setcol(int k, double in) { } } -void OcSparseMatrix::ident(void) { +void OcSparseMatrix::ident() { m_.setIdentity(); } @@ -348,7 +347,7 @@ void OcSparseMatrix::setdiag(int k, double in) { } } -int OcSparseMatrix::sprowlen(int i) { +int OcSparseMatrix::sprowlen(int i) const { int acc = 0; for (decltype(m_)::InnerIterator it(m_, i); it; ++it) { acc += 1; @@ -356,7 +355,7 @@ int OcSparseMatrix::sprowlen(int i) { return acc; } -double OcSparseMatrix::spgetrowval(int i, int jindx, int* j) { +double OcSparseMatrix::spgetrowval(int i, int jindx, int* j) const { int acc = 0; for (decltype(m_)::InnerIterator it(m_, i); it; ++it) { if (acc == jindx) { @@ -368,13 +367,13 @@ double OcSparseMatrix::spgetrowval(int i, int jindx, int* j) { return 0; } -void OcSparseMatrix::nonzeros(std::vector& m, std::vector& n) { - m.clear(); - n.clear(); +std::vector> OcSparseMatrix::nonzeros() const { + std::vector> nzs; + nzs.reserve(m_.nonZeros()); for (int k = 0; k < m_.outerSize(); ++k) { for (decltype(m_)::InnerIterator it(m_, k); it; ++it) { - m.push_back(it.row()); - n.push_back(it.col()); + nzs.emplace_back(it.row(), it.col()); } } + return nzs; } diff --git a/src/ivoc/ocmatrix.h b/src/ivoc/ocmatrix.h index 15960fe51f..9e874c86a3 100644 --- a/src/ivoc/ocmatrix.h +++ b/src/ivoc/ocmatrix.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -20,23 +21,35 @@ class OcMatrix { static OcMatrix* instance(int nrow, int ncol, int type = MFULL); virtual ~OcMatrix() = default; - virtual double* mep(int i, int j) { + // This function is deprecated and should not be used! + // mep stands for 'matrix element pointer' + inline double* mep(int i, int j) { + return &coeff(i, j); + } + + inline double operator()(int i, int j) const { + return getval(i, j); + }; + + virtual double& coeff(int i, int j) { + static double zero = 0.0; unimp(); - return nullptr; - } // matrix element pointer + return zero; + } + inline double& operator()(int i, int j) { - return *mep(i, j); + return coeff(i, j); }; - virtual double getval(int i, int j) { + virtual double getval(int i, int j) const { unimp(); return 0.; } - virtual int nrow() { + virtual int nrow() const { unimp(); return 0; } - virtual int ncol() { + virtual int ncol() const { unimp(); return 0; } @@ -44,32 +57,32 @@ class OcMatrix { unimp(); } - virtual void nonzeros(std::vector& m, std::vector& n); + virtual std::vector> nonzeros() const; OcFullMatrix* full(); - inline void mulv(Vect& in, Vect& out) { + inline void mulv(Vect& in, Vect& out) const { mulv(&in, &out); }; - virtual void mulv(Vect* in, Vect* out) { + virtual void mulv(Vect* in, Vect* out) const { unimp(); } - virtual void mulm(Matrix* in, Matrix* out) { + virtual void mulm(Matrix* in, Matrix* out) const { unimp(); } - virtual void muls(double, Matrix* out) { + virtual void muls(double, Matrix* out) const { unimp(); } - virtual void add(Matrix*, Matrix* out) { + virtual void add(Matrix*, Matrix* out) const { unimp(); } - virtual void getrow(int, Vect* out) { + virtual void getrow(int, Vect* out) const { unimp(); } - virtual void getcol(int, Vect* out) { + virtual void getcol(int, Vect* out) const { unimp(); } - virtual void getdiag(int, Vect* out) { + virtual void getdiag(int, Vect* out) const { unimp(); } virtual void setrow(int, Vect* in) { @@ -96,47 +109,47 @@ class OcMatrix { virtual void ident() { unimp(); } - virtual void exp(Matrix* out) { + virtual void exp(Matrix* out) const { unimp(); } - virtual void pow(int, Matrix* out) { + virtual void pow(int, Matrix* out) const { unimp(); } - virtual void inverse(Matrix* out) { + virtual void inverse(Matrix* out) const { unimp(); } virtual void solv(Vect* vin, Vect* vout, bool use_lu) { unimp(); } - virtual void copy(Matrix* out) { + virtual void copy(Matrix* out) const { unimp(); } - virtual void bcopy(Matrix* mout, int i0, int j0, int n0, int m0, int i1, int j1) { + virtual void bcopy(Matrix* mout, int i0, int j0, int n0, int m0, int i1, int j1) const { unimp(); } virtual void transpose(Matrix* out) { unimp(); } - virtual void symmeigen(Matrix* mout, Vect* vout) { + virtual void symmeigen(Matrix* mout, Vect* vout) const { unimp(); } - virtual void svd1(Matrix* u, Matrix* v, Vect* d) { + virtual void svd1(Matrix* u, Matrix* v, Vect* d) const { unimp(); } - virtual double det(int* e) { + virtual double det(int* e) const { unimp(); return 0.0; } - virtual int sprowlen(int) { + virtual int sprowlen(int) const { unimp(); return 0; } - virtual double spgetrowval(int i, int jindx, int* j) { + virtual double spgetrowval(int i, int jindx, int* j) const { unimp(); return 0.; } - void unimp(); + void unimp() const; protected: OcMatrix(int type); @@ -155,19 +168,19 @@ class OcFullMatrix final: public OcMatrix { // type 1 OcFullMatrix(int, int); ~OcFullMatrix() override = default; - double* mep(int, int) override; - double getval(int i, int j) override; - int nrow() override; - int ncol() override; + double& coeff(int, int) override; + double getval(int i, int j) const override; + int nrow() const override; + int ncol() const override; void resize(int, int) override; - void mulv(Vect* in, Vect* out) override; - void mulm(Matrix* in, Matrix* out) override; - void muls(double, Matrix* out) override; - void add(Matrix*, Matrix* out) override; - void getrow(int, Vect* out) override; - void getcol(int, Vect* out) override; - void getdiag(int, Vect* out) override; + void mulv(Vect* in, Vect* out) const override; + void mulm(Matrix* in, Matrix* out) const override; + void muls(double, Matrix* out) const override; + void add(Matrix*, Matrix* out) const override; + void getrow(int, Vect* out) const override; + void getcol(int, Vect* out) const override; + void getdiag(int, Vect* out) const override; void setrow(int, Vect* in) override; void setcol(int, Vect* in) override; void setdiag(int, Vect* in) override; @@ -176,16 +189,16 @@ class OcFullMatrix final: public OcMatrix { // type 1 void setdiag(int, double in) override; void zero() override; void ident() override; - void exp(Matrix* out) override; - void pow(int, Matrix* out) override; - void inverse(Matrix* out) override; + void exp(Matrix* out) const override; + void pow(int, Matrix* out) const override; + void inverse(Matrix* out) const override; void solv(Vect* vin, Vect* vout, bool use_lu) override; - void copy(Matrix* out) override; - void bcopy(Matrix* mout, int i0, int j0, int n0, int m0, int i1, int j1) override; + void copy(Matrix* out) const override; + void bcopy(Matrix* mout, int i0, int j0, int n0, int m0, int i1, int j1) const override; void transpose(Matrix* out) override; - void symmeigen(Matrix* mout, Vect* vout) override; - void svd1(Matrix* u, Matrix* v, Vect* d) override; - double det(int* exponent) override; + void symmeigen(Matrix* mout, Vect* vout) const override; + void svd1(Matrix* u, Matrix* v, Vect* d) const override; + double det(int* exponent) const override; private: Eigen::Matrix m_{}; @@ -197,12 +210,12 @@ class OcSparseMatrix final: public OcMatrix { // type 2 OcSparseMatrix(int, int); ~OcSparseMatrix() override = default; - double* mep(int, int) override; - int nrow() override; - int ncol() override; - double getval(int, int) override; - void ident(void) override; - void mulv(Vect* in, Vect* out) override; + double& coeff(int, int) override; + int nrow() const override; + int ncol() const override; + double getval(int, int) const override; + void ident() override; + void mulv(Vect* in, Vect* out) const override; void solv(Vect* vin, Vect* vout, bool use_lu) override; void setrow(int, Vect* in) override; @@ -212,10 +225,10 @@ class OcSparseMatrix final: public OcMatrix { // type 2 void setcol(int, double in) override; void setdiag(int, double in) override; - void nonzeros(std::vector& m, std::vector& n) override; + std::vector> nonzeros() const override; - int sprowlen(int) override; // how many elements in row - double spgetrowval(int i, int jindx, int* j) override; + int sprowlen(int) const override; // how many elements in row + double spgetrowval(int i, int jindx, int* j) const override; void zero() override; diff --git a/src/nrniv/matrixmap.cpp b/src/nrniv/matrixmap.cpp index f07cfbed2b..658e66c5c0 100644 --- a/src/nrniv/matrixmap.cpp +++ b/src/nrniv/matrixmap.cpp @@ -19,7 +19,8 @@ void MatrixMap::mmfree() { void MatrixMap::add(double fac) { for (int i = 0; i < plen_; ++i) { - *ptree_[i] += fac * (*pm_[i]); + auto [it, jt] = pm_[i]; + *ptree_[i] += fac * m_(it, jt); } } @@ -28,13 +29,10 @@ void MatrixMap::alloc(int start, int nnode, Node** nodes, int* layer) { mmfree(); plen_ = 0; - std::vector nonzero_i, nonzero_j; - m_.nonzeros(nonzero_i, nonzero_j); - pm_.resize(nonzero_i.size()); - ptree_.resize(nonzero_i.size()); - for (int k = 0; k < nonzero_i.size(); k++) { - const int i = nonzero_i[k]; - const int j = nonzero_j[k]; + std::vector> nzs = m_.nonzeros(); + pm_.resize(nzs.size()); + ptree_.resize(nzs.size()); + for (const auto [i, j]: nzs) { int it; if (i < nnode) { it = nodes[i]->eqn_index_ + layer[i]; @@ -45,7 +43,7 @@ void MatrixMap::alloc(int start, int nnode, Node** nodes, int* layer) { it = start + i - nnode; } int jt; - pm_[plen_] = m_.mep(i, j); + pm_[plen_] = std::make_pair(i, j); if (j < nnode) { jt = nodes[j]->eqn_index_ + layer[j]; if (layer[j] > 0 && !nodes[j]->extnode) { diff --git a/src/nrniv/matrixmap.h b/src/nrniv/matrixmap.h index f216dcc9c3..c20b774327 100644 --- a/src/nrniv/matrixmap.h +++ b/src/nrniv/matrixmap.h @@ -116,6 +116,6 @@ class MatrixMap { // the map int plen_ = 0; - std::vector pm_{}; + std::vector> pm_{}; std::vector ptree_{}; }; diff --git a/src/nrnpython/rxd.cpp b/src/nrnpython/rxd.cpp index 7cf61f7513..ff548a7f4a 100644 --- a/src/nrnpython/rxd.cpp +++ b/src/nrnpython/rxd.cpp @@ -1516,7 +1516,7 @@ void solve_reaction(ICSReactions* react, double pd; double dt = *dt_ptr; double dx = FLT_EPSILON; - auto jacobian = std::make_unique(N, N); + OcFullMatrix jacobian(N, N); auto b = std::make_unique(N); auto x = std::make_unique(N); @@ -1655,7 +1655,7 @@ void solve_reaction(ICSReactions* react, if (react->state_idx[segment][jac_i][jac_j] != SPECIES_ABSENT) { pd = (result_array_dx[jac_i][jac_j] - result_array[jac_i][jac_j]) / dx; - *jacobian->mep(jac_idx, idx) = (idx == jac_idx) - dt * pd; + jacobian(jac_idx, idx) = (idx == jac_idx) - dt * pd; jac_idx += 1; } result_array_dx[jac_i][jac_j] = 0; @@ -1665,7 +1665,7 @@ void solve_reaction(ICSReactions* react, // pd is our Jacobian approximated if (react->ecs_state[segment][jac_i] != NULL) { pd = (ecs_result_dx[jac_i] - ecs_result[jac_i]) / dx; - *jacobian->mep(jac_idx, idx) = -dt * pd; + jacobian(jac_idx, idx) = -dt * pd; jac_idx += 1; } ecs_result_dx[jac_i] = 0; @@ -1707,7 +1707,7 @@ void solve_reaction(ICSReactions* react, // pd is our Jacobian approximated if (react->state_idx[segment][jac_i][jac_j] != SPECIES_ABSENT) { pd = (result_array_dx[jac_i][jac_j] - result_array[jac_i][jac_j]) / dx; - *jacobian->mep(jac_idx, idx) = -dt * pd; + jacobian(jac_idx, idx) = -dt * pd; jac_idx += 1; } } @@ -1716,10 +1716,10 @@ void solve_reaction(ICSReactions* react, // pd is our Jacobian approximated if (react->ecs_state[segment][jac_i] != NULL) { pd = (ecs_result_dx[jac_i] - ecs_result[jac_i]) / dx; - *jacobian->mep(jac_idx, idx) = (idx == jac_idx) - dt * pd; + jacobian(jac_idx, idx) = (idx == jac_idx) - dt * pd; jac_idx += 1; } else { - *jacobian->mep(idx, idx) = 1.0; + jacobian(idx, idx) = 1.0; } // reset dx array ecs_states_for_reaction_dx[i] -= dx; @@ -1728,7 +1728,7 @@ void solve_reaction(ICSReactions* react, } } // solve for x, destructively - jacobian->solv(b.get(), x.get(), false); + jacobian.solv(b.get(), x.get(), false); if (bval != NULL) // variable-step { diff --git a/src/nrnpython/rxd_extracellular.cpp b/src/nrnpython/rxd_extracellular.cpp index aeb377eed4..a26d61eeb2 100644 --- a/src/nrnpython/rxd_extracellular.cpp +++ b/src/nrnpython/rxd_extracellular.cpp @@ -290,7 +290,6 @@ void* ecs_do_reactions(void* dataptr) { double* mc_mults_array = NULL; double dx = FLT_EPSILON; double pd; - std::unique_ptr jacobian; std::vector x{}; std::vector b{}; @@ -316,8 +315,7 @@ void* ecs_do_reactions(void* dataptr) { if (react->num_species_involved == 0) continue; /*allocate data structures*/ - jacobian = std::make_unique(react->num_species_involved, - react->num_species_involved); + OcFullMatrix jacobian(react->num_species_involved, react->num_species_involved); b.resize(react->num_species_involved); x.resize(react->num_species_involved); states_cache = (double*) malloc(sizeof(double) * react->num_species_involved); @@ -358,23 +356,23 @@ void* ecs_do_reactions(void* dataptr) { for (k = 0; k < react->num_species_involved; k++) { pd = (results_array_dx[k] - results_array[k]) / dx; - *jacobian->mep(k, j) = (j == k) - dt * pd; + jacobian(k, j) = (j == k) - dt * pd; } states_cache_dx[j] -= dx; } // solve for x if (react->num_species_involved == 1) { - react->species_states[0][i] += b[0] / jacobian->getval(0, 0); + react->species_states[0][i] += b[0] / jacobian(0, 0); } else { // find entry in leftmost column with largest absolute value // Pivot for (j = 0; j < react->num_species_involved; j++) { for (k = j + 1; k < react->num_species_involved; k++) { - if (abs(jacobian->getval(j, j)) < abs(jacobian->getval(k, j))) { + if (abs(jacobian(j, j)) < abs(jacobian(k, j))) { for (n = 0; n < react->num_species_involved; n++) { - temp = jacobian->getval(j, n); - *jacobian->mep(j, n) = jacobian->getval(k, n); - *jacobian->mep(k, n) = temp; + temp = jacobian(j, n); + jacobian(j, n) = jacobian(k, n); + jacobian(k, n) = temp; } } } @@ -382,11 +380,11 @@ void* ecs_do_reactions(void* dataptr) { for (j = 0; j < react->num_species_involved - 1; j++) { for (k = j + 1; k < react->num_species_involved; k++) { - ge_value = jacobian->getval(k, j) / jacobian->getval(j, j); + ge_value = jacobian(k, j) / jacobian(j, j); for (n = 0; n < react->num_species_involved; n++) { - val_to_set = jacobian->getval(k, n) - - ge_value * jacobian->getval(j, n); - *jacobian->mep(k, n) = val_to_set; + val_to_set = jacobian(k, n) - + ge_value * jacobian(j, n); + jacobian(k, n) = val_to_set; } b[k] = b[k] - ge_value * b[j]; } @@ -396,10 +394,10 @@ void* ecs_do_reactions(void* dataptr) { x[j] = b[j]; for (k = j + 1; k < react->num_species_involved; k++) { if (k != j) { - x[j] = x[j] - jacobian->getval(j, k) * x[k]; + x[j] = x[j] - jacobian(j, k) * x[k]; } } - x[j] = x[j] / jacobian->getval(j, j); + x[j] = x[j] / jacobian(j, j); } for (j = 0; j < react->num_species_involved; j++) { // I think this should be something like @@ -446,8 +444,7 @@ void* ecs_do_reactions(void* dataptr) { if (react->num_species_involved == 0) continue; /*allocate data structures*/ - jacobian = std::make_unique(react->num_species_involved, - react->num_species_involved); + OcFullMatrix jacobian(react->num_species_involved, react->num_species_involved); b.resize(react->num_species_involved); x.resize(react->num_species_involved); states_cache = (double*) malloc(sizeof(double) * react->num_species_involved); @@ -480,23 +477,23 @@ void* ecs_do_reactions(void* dataptr) { for (k = 0; k < react->num_species_involved; k++) { pd = (results_array_dx[k] - results_array[k]) / dx; - *jacobian->mep(k, j) = (j == k) - dt * pd; + jacobian(k, j) = (j == k) - dt * pd; } states_cache_dx[j] -= dx; } // solve for x if (react->num_species_involved == 1) { - react->species_states[0][i] += b[0] / jacobian->getval(0, 0); + react->species_states[0][i] += b[0] / jacobian(0, 0); } else { // find entry in leftmost column with largest absolute value // Pivot for (j = 0; j < react->num_species_involved; j++) { for (k = j + 1; k < react->num_species_involved; k++) { - if (abs(jacobian->getval(j, j)) < abs(jacobian->getval(k, j))) { + if (abs(jacobian(j, j)) < abs(jacobian(k, j))) { for (n = 0; n < react->num_species_involved; n++) { - temp = jacobian->getval(j, n); - *jacobian->mep(j, n) = jacobian->getval(k, n); - *jacobian->mep(k, n) = temp; + temp = jacobian(j, n); + jacobian(j, n) = jacobian(k, n); + jacobian(k, n) = temp; } } } @@ -504,11 +501,11 @@ void* ecs_do_reactions(void* dataptr) { for (j = 0; j < react->num_species_involved - 1; j++) { for (k = j + 1; k < react->num_species_involved; k++) { - ge_value = jacobian->getval(k, j) / jacobian->getval(j, j); + ge_value = jacobian(k, j) / jacobian(j, j); for (n = 0; n < react->num_species_involved; n++) { - val_to_set = jacobian->getval(k, n) - - ge_value * jacobian->getval(j, n); - *jacobian->mep(k, n) = val_to_set; + val_to_set = jacobian(k, n) - + ge_value * jacobian(j, n); + jacobian(k, n) = val_to_set; } b[k] = b[k] - ge_value * b[j]; } @@ -518,10 +515,10 @@ void* ecs_do_reactions(void* dataptr) { x[j] = b[j]; for (k = j + 1; k < react->num_species_involved; k++) { if (k != j) { - x[j] = x[j] - jacobian->getval(j, k) * x[k]; + x[j] = x[j] - jacobian(j, k) * x[k]; } } - x[j] = x[j] / jacobian->getval(j, j); + x[j] = x[j] / jacobian(j, j); } for (j = 0; j < react->num_species_involved; j++) { // I think this should be something like diff --git a/test/unit_tests/matrix.cpp b/test/unit_tests/matrix.cpp index 27386501ca..115dbfe120 100644 --- a/test/unit_tests/matrix.cpp +++ b/test/unit_tests/matrix.cpp @@ -94,6 +94,11 @@ SCENARIO("A Matrix", "[neuron_ivoc][OcMatrix]") { m.setrow(3, 2.0); REQUIRE(compareMatrix(m, {{3., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}, {2., 2., 2.}})); } + { + std::vector> nzs = m.nonzeros(); + std::vector> res = {{0, 0}, {1, 1} , {2, 2}, {3, 0}, {3, 1}, {3, 2}}; + REQUIRE(nzs == res); + } { std::vector x, y; m.nonzeros(x, y); From a6510feaff8c66dd611fce6b783adda6cb15ff29 Mon Sep 17 00:00:00 2001 From: nrnhines Date: Wed, 30 Oct 2024 19:21:58 -0400 Subject: [PATCH 66/68] Allow parallel test coverage (e.g. ctest -j 8 ) (#3162) --- cmake/Coverage.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/Coverage.cmake b/cmake/Coverage.cmake index aa2bae3bf5..9178c17636 100644 --- a/cmake/Coverage.cmake +++ b/cmake/Coverage.cmake @@ -34,7 +34,7 @@ if(NRN_ENABLE_COVERAGE) if(NOT BUILD_TYPE_UPPER STREQUAL "DEBUG") message(WARNING "Using CMAKE_BUILD_TYPE=Debug is recommended with NRN_ENABLE_COVERAGE") endif() - set(NRN_COVERAGE_FLAGS_UNQUOTED --coverage -fno-inline) + set(NRN_COVERAGE_FLAGS_UNQUOTED --coverage -fno-inline -fprofile-update=atomic) string(JOIN " " NRN_COVERAGE_FLAGS ${NRN_COVERAGE_FLAGS_UNQUOTED}) set(NRN_COVERAGE_LINK_FLAGS --coverage) From ebe3d3ba9a22beafe6f9b6d1099977f67d24f19d Mon Sep 17 00:00:00 2001 From: Luc Grosheintz Date: Thu, 31 Oct 2024 11:16:58 +0100 Subject: [PATCH 67/68] Update `external/nmodl`. (#3151) --- external/nmodl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/nmodl b/external/nmodl index e6250014dd..800d098cc3 160000 --- a/external/nmodl +++ b/external/nmodl @@ -1 +1 @@ -Subproject commit e6250014dd2c5ae5d9cb30af6920668835b31137 +Subproject commit 800d098cc3bf658cf7eed314df5870aaf96d9dd8 From 7653d2154fc33c90a74e048bcef42b25c6d2155b Mon Sep 17 00:00:00 2001 From: Emmanuel Ferdman Date: Fri, 1 Nov 2024 20:06:21 +0200 Subject: [PATCH 68/68] Update Python MacOS download page (#3169) Signed-off-by: Emmanuel Ferdman --- docs/install/mac_pkg.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/install/mac_pkg.md b/docs/install/mac_pkg.md index 86cee22d88..cc93bd80c5 100644 --- a/docs/install/mac_pkg.md +++ b/docs/install/mac_pkg.md @@ -162,7 +162,7 @@ generally only for the architecture indicated by ```uname -m```. That is ok for openmpi but since the various python libraries are linked against during build to create the version specific neuron modules, those python installers also have to be universal. Fortunately, universal python versions -can be found at [python.org](http://python.org/Downloads/macOS) at least for +can be found at [python.org](https://www.python.org/downloads/macos) at least for (as of 2022-01-01) python3.8, python3.9, and python3.10. - ```xcode-select --install```: