From dbffab9091e57e8cce8ad94b8e89940a060ddd09 Mon Sep 17 00:00:00 2001 From: Adam Wildavsky Date: Mon, 17 Aug 2026 19:04:02 +0200 Subject: [PATCH 1/2] Use American spelling for initialize and initialization. Align the Python export initialize_static_memory with the C++ InitializeStaticMemory name. Co-authored-by: Cursor --- library/src/api/dll.h | 4 ++-- library/src/init.cpp | 2 +- library/tests/system/BUILD.bazel | 2 +- .../system/max_threads_equivalence_test.cpp | 6 +++--- python/dds3/__init__.py | 6 +++--- python/src/bindings.cpp | 16 ++++++++-------- python/tests/test_import.py | 2 ++ specs/lookup-tables.md | 10 +++++----- specs/move-generation.md | 2 +- specs/python-binding.md | 4 ++-- 10 files changed, 28 insertions(+), 26 deletions(-) diff --git a/library/src/api/dll.h b/library/src/api/dll.h index deb25a392..8e476204c 100644 --- a/library/src/api/dll.h +++ b/library/src/api/dll.h @@ -429,10 +429,10 @@ struct DDSInfo /** - * @brief Initialise the solver's static memory. + * @brief Initialize the solver's static memory. * * Allocates the transposition-table memory pools, registers scheduler and - * thread-manager state, and performs one-time lookup-table initialisation. + * thread-manager state, and performs one-time lookup-table initialization. * This does NOT control the number of worker threads — use the * SolveAllBoardsN / CalcAllTablesN family for per-call thread caps. */ diff --git a/library/src/init.cpp b/library/src/init.cpp index 1b206925b..c9900ad11 100644 --- a/library/src/init.cpp +++ b/library/src/init.cpp @@ -36,7 +36,7 @@ int _initialized = 0; /* - * Initialise the solver's static memory: TT memory pools, scheduler / + * Initialize the solver's static memory: TT memory pools, scheduler / * thread-manager state, and one-time lookup-table setup. * * Public API documentation is maintained in the API headers. diff --git a/library/tests/system/BUILD.bazel b/library/tests/system/BUILD.bazel index d5ff3ff75..54c1cc86b 100644 --- a/library/tests/system/BUILD.bazel +++ b/library/tests/system/BUILD.bazel @@ -113,7 +113,7 @@ filegroup( visibility = ["//python:__pkg__"], ) -# max_threads override equivalence + rename/alias initialisation test +# max_threads override equivalence + rename/alias initialization test cc_test( name = "max_threads_equivalence_test", size = "small", diff --git a/library/tests/system/max_threads_equivalence_test.cpp b/library/tests/system/max_threads_equivalence_test.cpp index 52e48b9a7..d2adae8af 100644 --- a/library/tests/system/max_threads_equivalence_test.cpp +++ b/library/tests/system/max_threads_equivalence_test.cpp @@ -1,6 +1,6 @@ /// @file max_threads_equivalence_test.cpp /// @brief Tests that the *N batch APIs honour maxThreads and stay equivalent to -/// the auto path, plus that the rename/alias both initialise the library. +/// the auto path, plus that the rename/alias both initialize the library. #include #include @@ -102,7 +102,7 @@ TEST(MaxThreadsEquivalence, SolveAllBoardsBinNMatchesAuto) const FutureTricks& fa = solved_auto.solved_board[b]; const FutureTricks& fo = solved_one.solved_board[b]; ASSERT_EQ(fa.cards, fo.cards) << "card count differs at board=" << b; - // Only the first `cards` entries are meaningful; the tail is uninitialised. + // Only the first `cards` entries are meaningful; the tail is uninitialized. for (int c = 0; c < fa.cards; c++) { EXPECT_EQ(fa.suit[c], fo.suit[c]) << "suit at board=" << b << " c=" << c; @@ -122,7 +122,7 @@ TEST(MaxThreadsEquivalence, InitializeStaticMemoryThenSolve) EXPECT_EQ(CalcDDtable(deal, &table), RETURN_NO_FAULT); } -// The deprecated SetMaxThreads alias still initialises the library. +// The deprecated SetMaxThreads alias still initializes the library. TEST(MaxThreadsEquivalence, DeprecatedSetMaxThreadsAliasStillWorks) { SetMaxThreads(1); diff --git a/python/dds3/__init__.py b/python/dds3/__init__.py index dda8d8137..d759dc214 100644 --- a/python/dds3/__init__.py +++ b/python/dds3/__init__.py @@ -7,7 +7,7 @@ from ._dds3 import calc_par from ._dds3 import calc_par_from_table from ._dds3 import dealer_par - from ._dds3 import initialise_static_memory + from ._dds3 import initialize_static_memory from ._dds3 import module_name from ._dds3 import par from ._dds3 import set_max_threads @@ -26,7 +26,7 @@ from _dds3 import calc_par from _dds3 import calc_par_from_table from _dds3 import dealer_par - from _dds3 import initialise_static_memory + from _dds3 import initialize_static_memory from _dds3 import module_name from _dds3 import par from _dds3 import set_max_threads @@ -45,7 +45,7 @@ "calc_par", "calc_par_from_table", "dealer_par", - "initialise_static_memory", + "initialize_static_memory", "module_name", "par", "set_max_threads", diff --git a/python/src/bindings.cpp b/python/src/bindings.cpp index 0d103285c..742552a4b 100644 --- a/python/src/bindings.cpp +++ b/python/src/bindings.cpp @@ -609,33 +609,33 @@ auto register_calc_par_bindings(py::module_& module) -> void auto register_analysis_bindings(py::module_& module) -> void { - // initialise_static_memory: allocate the solver's static memory pools and - // perform one-time lookup-table initialisation. This does NOT control the + // initialize_static_memory: allocate the solver's static memory pools and + // perform one-time lookup-table initialization. This does NOT control the // worker-thread count; use solve_all_boards_* (which parallelise across the // machine's hardware threads automatically) or one SolverContext per worker // thread for per-board concurrency. module.def( - "initialise_static_memory", + "initialize_static_memory", []() { py::gil_scoped_release release; InitializeStaticMemory(); }, - "Initialise the solver's static memory.\n\n" + "Initialize the solver's static memory.\n\n" "Allocates the transposition-table memory pools and performs one-time\n" - "lookup-table initialisation. This does NOT control the number of worker\n" + "lookup-table initialization. This does NOT control the number of worker\n" "threads: solve_all_boards_* parallelise across the machine's hardware\n" "threads automatically, and for per-board concurrency from Python you\n" "create one SolverContext per worker thread and pass it to solve_board /\n" "solve_board_pbn."); - // set_max_threads: DEPRECATED alias of initialise_static_memory. The thread + // set_max_threads: DEPRECATED alias of initialize_static_memory. The thread // count argument is ignored; retained only for backward compatibility. module.def( "set_max_threads", [](const int user_threads) { if (PyErr_WarnEx( PyExc_DeprecationWarning, - "set_max_threads() is deprecated; use initialise_static_memory(). " + "set_max_threads() is deprecated; use initialize_static_memory(). " "The user_threads argument is ignored.", 1) != 0) { throw py::error_already_set(); @@ -644,7 +644,7 @@ auto register_analysis_bindings(py::module_& module) -> void SetMaxThreads(user_threads); }, py::arg("user_threads") = 0, - "DEPRECATED: use initialise_static_memory() instead.\n\n" + "DEPRECATED: use initialize_static_memory() instead.\n\n" "Legacy thread-resource hook (wraps the deprecated SetMaxThreads C API,\n" "now a thin alias of InitializeStaticMemory). Calling this emits a\n" "DeprecationWarning.\n\n" diff --git a/python/tests/test_import.py b/python/tests/test_import.py index bf235c82c..d83fc3443 100644 --- a/python/tests/test_import.py +++ b/python/tests/test_import.py @@ -5,6 +5,7 @@ from dds3 import calc_dd_table from dds3 import calc_par from dds3 import calc_par_from_table +from dds3 import initialize_static_memory from dds3 import module_name from dds3 import par from dds3 import SolverContext @@ -27,6 +28,7 @@ def test_import_and_api_root(self) -> None: self.assertTrue(callable(par)) self.assertTrue(callable(calc_par)) self.assertTrue(callable(calc_par_from_table)) + self.assertTrue(callable(initialize_static_memory)) self.assertIsNotNone(SolverContext) # Verify SolverContext can be instantiated. diff --git a/specs/lookup-tables.md b/specs/lookup-tables.md index d333b5c2e..269e032d6 100644 --- a/specs/lookup-tables.md +++ b/specs/lookup-tables.md @@ -8,7 +8,7 @@ last-updated: 2026-07-18 > **Specs vs. doxygen.** Each table's exact indexing and return encoding is > documented inline in `lookup_tables.hpp`. This spec records what the tables are -> collectively, their initialisation/immutability contract, and who depends on +> collectively, their initialization/immutability contract, and who depends on > them. ## Purpose @@ -34,14 +34,14 @@ inner loops of [move-generation](move-generation.md) and the search index these `win_ranks[8192][14]` (bitmask of the top-N cards), and `group_data[8192]` (`MoveGroupType` run decomposition — up to 7 runs of adjacent ranks with their top card, tail sequence, full sequence, and inter-run gaps). -- **Initialised once, eagerly, at startup.** `init_lookup_tables()` fills the - storage via static initialisation (`DdsLutInitGuard`), guarded by +- **Initialized once, eagerly, at startup.** `init_lookup_tables()` fills the + storage via static initialization (`DdsLutInitGuard`), guarded by `std::call_once`. It is **thread-safe, idempotent, and a no-op after startup** — - explicit calls are safe but redundant. No consumer needs to initialise them. + explicit calls are safe but redundant. No consumer needs to initialize them. - **Read-only and immutable after init.** The tables are exposed as `const` references to fixed-size arrays, giving zero-overhead direct indexing (`highest_rank[aggr]`, `rel_rank[aggr][rank]`). Any thread may read them - concurrently; nothing mutates them post-initialisation. + concurrently; nothing mutates them post-initialization. - **`MoveGroupType` is the run-decomposition contract** consumed by move generation: `last_group_` (−1 for empty, up to 6), and per-group `rank_`, `sequence_`, `fullseq_`, and `gap_` arrays. `rank_`, `sequence_` and diff --git a/specs/move-generation.md b/specs/move-generation.md index c4d80979e..584be927a 100644 --- a/specs/move-generation.md +++ b/specs/move-generation.md @@ -47,7 +47,7 @@ and transposition-table hits. `Moves` is an internal component — it is not par void situation (0–3 hands void), 13 categories total. It indexes the statistics tables and the heuristic's per-situation tracking. - **Invariants are assertion-checked.** Public methods assume valid input and - prior initialisation; violations trip asserts in debug builds. The move-finding + prior initialization; violations trip asserts in debug builds. The move-finding methods signal "no move" by returning `nullptr`, not by throwing. - **Statistics/printing are diagnostic-only** and emit under `DDS_MOVES` / `DDS_MOVES_DETAILS` (see [constants-and-debug](constants-and-debug.md)); they are off the hot path in diff --git a/specs/python-binding.md b/specs/python-binding.md index ae377158f..6987b4a51 100644 --- a/specs/python-binding.md +++ b/specs/python-binding.md @@ -32,9 +32,9 @@ context API and the flat API from [dds-public-api](dds-public-api.md). - **Public surface is the package `__all__`.** `python/dds3/__init__.py` re-exports the extension symbols; see that list and `docs/python_interface.md` rather than duplicating names here. Notable capability-wide pieces: a Python `SolverContext` - for TT reuse, and `initialise_static_memory` for lookup-table setup. Note + for TT reuse, and `initialize_static_memory` for lookup-table setup. Note `set_max_threads` is exported but **deprecated** — it is an alias of - `initialise_static_memory` that ignores its argument and warns; it does not set + `initialize_static_memory` that ignores its argument and warns; it does not set a worker count. - **In-package native staging is platform-specific.** `_dds3_in_package` copies the built extension into `dds3/` under the filename Python expects — From 38d4d301e691f7c455cc7854655e63620eb90d2c Mon Sep 17 00:00:00 2001 From: Adam Wildavsky Date: Mon, 17 Aug 2026 22:48:53 +0200 Subject: [PATCH 2/2] Address remaining v3.1.0 release-notes review comments. Ship initialize_static_memory in the notes, correct the Seq/threading opt-out, and tighten the AnalysePlay compatibility wording. Co-authored-by: Cursor --- docs/release_notes/draft_v3_1_0.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/release_notes/draft_v3_1_0.md b/docs/release_notes/draft_v3_1_0.md index bdee4f8bf..96b5e455d 100644 --- a/docs/release_notes/draft_v3_1_0.md +++ b/docs/release_notes/draft_v3_1_0.md @@ -31,8 +31,8 @@ points: - `solve_all_boards_pbn`, `solve_all_boards_bin` — batch solving, parallelised across hardware threads inside the library. - `dealer_par` — par contracts from the dealer's perspective. -- `initialise_static_memory` (replaces the deprecated `set_max_threads`; the - C equivalent is spelled `InitializeStaticMemory` — the Python module currenly uses some British spelling, we plan to settle on American English throughout). +- `initialize_static_memory` (mirrors the C-side `SetMaxThreads` → + `InitializeStaticMemory` deprecation). All of these release the GIL around the native call and validate their inputs. Batch entry points accept an optional `max_threads`. @@ -58,7 +58,6 @@ Batch entry points accept an optional `max_threads`. empty table on next use. - Thin LTO on macOS builds, inlined hot accessors, and native WASM exception handling. - - **New performance tooling** — utilities for comparing solver performance between two commits, and for recording warm benchmarks from a live consumer. The comparison below (18-core Mac) shows solver performance is back at 2.9 @@ -91,8 +90,8 @@ TOTAL calc 9.35 123.59 8.42 `TransTableS::reset_memory` after memory release. - **Par output now names the declaring seat** when successive par contracts differ, in both the C++ and .NET paths. -- Worker exceptions in parallel board solving are reported as `RETURN_UNKNOWN_FAULT` -rather than terminating the process. +- Worker exceptions in parallel board solving are reported as `RETURN_UNKNOWN_FAULT` + rather than terminating the process. ### New public C API @@ -133,12 +132,15 @@ name still works and no longer influences batch parallelism. ## Compatibility -No breaking changes for 3.0 consumers. The only deprecation is `SetMaxThreads`, +No API breaks for 3.0 consumers. The only deprecation is `SetMaxThreads`, which remains available as an alias. -`SolveAllBoards*/CalcAllTables*` now spawn threads by default where 3.0 was sequential; -the `*Seq` variant opts out. There is also a bug fix which changes the -output from AnalysePlay*. +`SolveAllBoards*`/`CalcAllTables*` now spawn threads by default where 3.0 was +sequential; pass `maxThreads = 1` to the `*N`/`*X` variants, or call +`SolveAllBoardsSeq`/`SolveAllBoardsBinSeq`, to stay on one thread. The +[incorrect results with v3 #156](https://github.com/dds-bridge/dds/issues/156) +fix changes the trick counts returned by `AnalysePlay*`; they were previously +under-counted. ## Contributors