diff --git a/arbor/hardware/memory.cpp b/arbor/hardware/memory.cpp index 9495327b6d18e8744a75040ca0091773c7e62750..4274ede47640a81846f117cba6944885a75eede8 100644 --- a/arbor/hardware/memory.cpp +++ b/arbor/hardware/memory.cpp @@ -15,7 +15,11 @@ namespace hw { #if defined(__linux__) memory_size_type allocated_memory() { +#if defined(__GLIBC__) && (__GLIBC__ > 2 || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 33))) + auto m = mallinfo2(); +#else auto m = mallinfo(); +#endif return m.hblkhd + m.uordblks; } #else diff --git a/arbor/include/arbor/simd/simd.hpp b/arbor/include/arbor/simd/simd.hpp index 0c5f05cd9ce3f3beffc080e5d1f37110f59ebd2c..b0d3b028578995af89ddc29bda2dc3663cc2c495 100644 --- a/arbor/include/arbor/simd/simd.hpp +++ b/arbor/include/arbor/simd/simd.hpp @@ -174,7 +174,7 @@ namespace detail { {} indirect_indexed_expression& operator=(V s) { - typename simd_traits<ImplIndex>::scalar_type idx[width]; + typename simd_traits<ImplIndex>::scalar_type idx[simd_traits<ImplIndex>::width]; ImplIndex::copy_to(index.value_, idx); for (unsigned i = 0; i < width; ++i) { p[idx[i]] = s; @@ -244,10 +244,10 @@ namespace detail { switch (constraint) { case index_constraint::none: { - typename ImplIndex::scalar_type o[width]; + typename ImplIndex::scalar_type o[simd_traits<ImplIndex>::width]; ImplIndex::copy_to(index.value_, o); - V a[width]; + V a[simd_traits<Impl>::width]; Impl::copy_to(s.value_, a); V temp = 0; diff --git a/arbor/include/arbor/util/pp_util.hpp b/arbor/include/arbor/util/pp_util.hpp index 5956ad65e16ae50e23f48176fe0661fdfdf63059..0b05f6f9b8d125e97e39e29e834e3912688a3b59 100644 --- a/arbor/include/arbor/util/pp_util.hpp +++ b/arbor/include/arbor/util/pp_util.hpp @@ -34,7 +34,7 @@ // Implementation macros for ARB_PP_FOREACH: -#define ARB_PP_FOREACH_1_(M, A, ...) M(A) +#define ARB_PP_FOREACH_1_(M, A) M(A) #define ARB_PP_FOREACH_2_(M, A, ...) M(A) ARB_PP_FOREACH_1_(M, __VA_ARGS__) #define ARB_PP_FOREACH_3_(M, A, ...) M(A) ARB_PP_FOREACH_2_(M, __VA_ARGS__) #define ARB_PP_FOREACH_4_(M, A, ...) M(A) ARB_PP_FOREACH_3_(M, __VA_ARGS__) diff --git a/arbor/io/trace.hpp b/arbor/io/trace.hpp index c9f9be8fbb250cd17d13b28c92dd7a8893447d7e..5b50b7d60ac3aea08c84d4ac5b2039da0ad63758 100644 --- a/arbor/io/trace.hpp +++ b/arbor/io/trace.hpp @@ -21,7 +21,7 @@ // // TRACE output is to std::cerr is serialized. -#define TRACE(vars...) arb::impl::debug_emit_trace(__FILE__, __LINE__, #vars, ##vars) +#define TRACE(...) arb::impl::debug_emit_trace(__FILE__, __LINE__, #__VA_ARGS__, ##__VA_ARGS__) // DEBUG << ...; diff --git a/arbor/mc_cell_group.cpp b/arbor/mc_cell_group.cpp index 78d2d791c120450eead105f7b643ee25c8ffeadd..fa0f6a4d9fe790fa379f6eec03cce30e24ccbcee 100644 --- a/arbor/mc_cell_group.cpp +++ b/arbor/mc_cell_group.cpp @@ -109,7 +109,13 @@ using fvm_probe_scratch = std::tuple<std::vector<double>, std::vector<cable_samp template <typename VoidFn, typename... A> void tuple_foreach(VoidFn&& f, std::tuple<A...>& t) { - (void)(int []){(f(std::get<A>(t)), 0)...}; + // executes functions in order (pack expansion) + // uses comma operator (unary left fold) + // avoids potentially overloaded comma operator (cast to void) + std::apply( + [g = std::forward<VoidFn>(f)](auto&& ...x){ + (..., static_cast<void>(g(std::forward<decltype(x)>(x))));}, + t); } void reserve_scratch(fvm_probe_scratch& scratch, std::size_t n) { diff --git a/arbor/s_expr.cpp b/arbor/s_expr.cpp index 3de9491574fdba10c9fcbded8d5e7a535e7c3010..fed7878a8173a0d3f28dbbf29faea409906c5348 100644 --- a/arbor/s_expr.cpp +++ b/arbor/s_expr.cpp @@ -125,6 +125,16 @@ private: // Consume and return the next token in the stream. void parse() { using namespace std::string_literals; +#define ARB_CASE_LETTERS \ + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': \ + case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': \ + case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': \ + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': \ + case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': \ + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': +#define ARB_CASE_DIGITS \ + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': \ + case '9': while (!empty()) { switch (*stream_) { @@ -166,11 +176,10 @@ private: case ')': token_ = {loc(), tok::rparen, {character()}}; return; - case 'a' ... 'z': - case 'A' ... 'Z': + ARB_CASE_LETTERS token_ = symbol(); return; - case '0' ... '9': + ARB_CASE_DIGITS token_ = number(); return; case '"': @@ -200,6 +209,8 @@ private: return; } } +#undef ARB_CASE_LETTERS +#undef ARB_CASE_DIGITS if (!empty()) { // todo: handle error: should never hit this diff --git a/arborio/asc_lexer.cpp b/arborio/asc_lexer.cpp index a93299efb7af20bd82ded3f4d21d891196332fdd..c51bf8793996eae2da70b1e4180cdd1d5104430d 100644 --- a/arborio/asc_lexer.cpp +++ b/arborio/asc_lexer.cpp @@ -136,6 +136,16 @@ private: // Consume and return the next token in the stream. void parse() { using namespace std::string_literals; +#define ARB_CASE_LETTERS \ + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': \ + case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': \ + case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': \ + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': \ + case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': \ + case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': +#define ARB_CASE_DIGITS \ + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': \ + case '9': while (!empty()) { switch (*stream_) { @@ -177,11 +187,10 @@ private: case ')': token_ = {loc(), tok::rparen, {character()}}; return; - case 'a' ... 'z': - case 'A' ... 'Z': + ARB_CASE_LETTERS token_ = symbol(); return; - case '0' ... '9': + ARB_CASE_DIGITS token_ = number(); return; case '"': @@ -225,6 +234,8 @@ private: return; } } +#undef ARB_CASE_LETTERS +#undef ARB_CASE_DIGITS if (!empty()) { token_ = {loc(), tok::error, "Internal lexer error: expected end of input, please open a bug report"s}; diff --git a/modcc/printer/infoprinter.cpp b/modcc/printer/infoprinter.cpp index 421a5b67de00608b4843a882d4a2b4d26da9b4ea..e0b729fc21f4f7bf427e0d7b9f5f08f6c5d1230c 100644 --- a/modcc/printer/infoprinter.cpp +++ b/modcc/printer/infoprinter.cpp @@ -35,54 +35,55 @@ std::string build_info_header(const Module& m, const printer_options& opt, bool "#include <{}mechanism_abi.h>\n\n", arb_header_prefix()); + out << fmt::format("extern \"C\" {{\n" + " arb_mechanism_type make_{0}_{1}() {{\n" + " // Tables\n", + std::regex_replace(opt.cpp_namespace, std::regex{"::"}, "_"), + name); + const auto& [state_ids, global_ids, param_ids] = public_variable_ids(m); const auto& assigned_ids = m.assigned_block().parameters; - auto fmt_var = [&](const auto& id) { + auto fmt_id = [&](const auto& id) { auto lo = id.has_range() ? id.range.first : lowest; auto hi = id.has_range() ? id.range.second : max; auto val = id.has_value() ? id.value : "NAN"; - return fmt::format(FMT_COMPILE("{{ \"{}\", \"{}\", {}, {}, {} }}"), id.name(), id.unit_string(), val, lo, hi); + return fmt::format(FMT_COMPILE("{{ \"{}\", \"{}\", {}, {}, {} }}"), id.name(), + id.unit_string(), val, lo, hi); + }; + auto fmt_ion = [&](const auto& ion) { + return fmt::format(FMT_COMPILE("{{ \"{}\", {}, {}, {}, {}, {}, {}, {} }}"), + ion.name, + ion.writes_concentration_int(), ion.writes_concentration_ext(), + ion.writes_rev_potential(), ion.uses_rev_potential(), + ion.uses_valence(), ion.verifies_valence(), ion.expected_valence); + }; + auto print_array_head = [&](char const * type, char const * name, auto size) { + out << " static " << type; + if (size) out << " " << name << "[] = {"; + else out << "* " << name << " = NULL;"; + }; + auto print_array_tail = [&](char const * type, char const * name, auto size) { + if (size) out << " };"; + out << fmt::format("\n static arb_size_type n_{} = {};\n", name, size); + }; + auto print_array = [&](char const* type, char const * name, auto & fmt_func, auto const & arr) { + io::separator sep("", ",\n "); + print_array_head(type, name, arr.size()); + for (const auto& var: arr) out << sep << fmt_func(var); + print_array_tail(type, name, arr.size()); + }; + auto print_arrays = [&](char const* type, char const * name, auto & fmt_func, auto const & arr0, auto const & arr1) { + io::separator sep("", ",\n "); + print_array_head(type, name, arr0.size() + arr1.size()); + for (const auto& var: arr0) out << sep << fmt_func(var); + for (const auto& var: arr1) out << sep << fmt_func(var); + print_array_tail(type, name, arr0.size() + arr1.size()); }; - out << fmt::format("extern \"C\" {{\n" - " arb_mechanism_type make_{0}_{1}() {{\n" - " // Tables\n", - std::regex_replace(opt.cpp_namespace, std::regex{"::"}, "_"), - name); - { - io::separator sep("", ",\n "); - out << " static arb_field_info globals[] = { "; - for (const auto& var: global_ids) out << sep << fmt_var(var); - out << fmt::format(" }};\n" - " static arb_size_type n_globals = {};\n", global_ids.size()); - } - { - io::separator sep("", ",\n "); - out << " static arb_field_info state_vars[] = { "; - for (const auto& id: state_ids) out << sep << fmt_var(id); - for (const auto& id: assigned_ids) out << sep << fmt_var(id); - out << fmt::format(" }};\n" - " static arb_size_type n_state_vars = {};\n", assigned_ids.size() + state_ids.size()); - } - { - io::separator sep("", ",\n "); - out << " static arb_field_info parameters[] = { "; - for (const auto& id: param_ids) out << sep << fmt_var(id); - out << fmt::format(" }};\n" - " static arb_size_type n_parameters = {};\n", param_ids.size()); - } - { - io::separator sep("", ",\n"); - out << " static arb_ion_info ions[] = { "; - for (const auto& ion: m.ion_deps()) out << sep - << fmt::format(FMT_COMPILE("{{ \"{}\", {}, {}, {}, {}, {}, {}, {} }}"), - ion.name, - ion.writes_concentration_int(), ion.writes_concentration_ext(), - ion.writes_rev_potential(), ion.uses_rev_potential(), - ion.uses_valence(), ion.verifies_valence(), ion.expected_valence); - out << fmt::format(" }};\n" - " static arb_size_type n_ions = {};\n", m.ion_deps().size()); - } + print_array("arb_field_info", "globals", fmt_id, global_ids); + print_arrays("arb_field_info", "state_vars", fmt_id, state_ids, assigned_ids); + print_array("arb_field_info", "parameters", fmt_id, param_ids); + print_array("arb_ion_info", "ions", fmt_ion, m.ion_deps()); out << fmt::format(FMT_COMPILE("\n" " arb_mechanism_type result;\n"