Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CPPVARIABLES.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ DDS_CPPOPTS = select({
"-Wno-character-conversion",
"-Werror",
],
# Optimisation (/O2, /Od) and language standard (/std) come from Bazel's
# Optimization (/O2, /Od) and language standard (/std) come from Bazel's
# compilation_mode and the patched MSVC default_cpp_std (/std:c++20).
# Restating them here overrides the toolchain and triggers MSVC D9025.
# /utf-8 must stay in these arms, not a global --cxxopt: wasm-transition
Expand Down
2 changes: 1 addition & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ The fault has not however yet showed up as far as I know.
A survival mechanism has been added to handle the situation if the
transposition table becomess full: The transposition table is emptied.

Before this, a full transposition table would in practise lock up
Before this, a full transposition table would in practice lock up
the program. Therefore the present size of the transposition table
is quite large (393 MB) to handle the most difficult deals.

Expand Down
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Security Policy

## What DDS is, for threat-modelling purposes
## What DDS is, for threat-modeling purposes

DDS is an **in-process library**, not a service. It opens no sockets and
crosses no privilege boundary. In the normal deployment the input is a bridge
Expand Down Expand Up @@ -71,7 +71,7 @@ is uneven across entry points:
array must actually hold that many deals — so a caller exposing these two to
untrusted input must bound the count itself, both against a hostile value
and against memory exhaustion.
- `convert_from_pbn()` silently ignores characters it does not recognise
- `convert_from_pbn()` silently ignores characters it does not recognize
rather than rejecting the string, so a PBN deal with an invalid rank parses
one card short. The resulting deal is now rejected downstream, but the error
code says `RETURN_CARD_COUNT` rather than `RETURN_PBN_FAULT`.
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ bazel run -c opt //benchmarks:dds_replay -- /path/to/recording.jsonl
Useful options:

```sh
--list summarise the recording without running DDS
--list summarize the recording without running DDS
--threads N worker threads; repeat the flag to sweep several
--repeat N run N times and report the best
--purpose play only one kind of call (bid/lead/play/claimcheck/par)
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/dds_replay_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ auto usage() -> int
" --no-par skip par calculations\n"
" --no-verify do not compare results against the recording\n"
" --tricks also break the report down by trick number\n"
" --list summarise the recording and exit\n");
" --list summarize the recording and exit\n");
return 2;
}

Expand Down
5 changes: 3 additions & 2 deletions doc/dll-description.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ <h3 id="the-par-calculation-functions">The PAR Calculation Functions</h3>
<p>The functions <code>SidesParBin</code> and <code>DealerParBin</code> provide binary output of the par results, making it easy to tailor-make the output text format. Two such functions, <code>ConvertToSidesTextFormat</code> and <code>ConvertToDealerTextFormat</code>, are included as examples. </p>
<p>It is possible as an option to perform par calculation in <code>CalcAllTables</code> and <code>CalcAllTablesPBN</code>. </p>
<p>The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration.</p>
<h3 id="double-dummy-value-analyser-functions">Double Dummy Value Analyser Functions</h3>
<a id="double-dummy-value-analyser-functions"></a>
<h3 id="double-dummy-value-analyzer-functions">Double Dummy Value Analyzer Functions</h3>
<p>The functions <code>AnalysePlayBin</code>, <code>AnalysePlayPBN</code>, <code>AnalyseAllPlaysBin</code> and <code>AnalyseAllPlaysPBN</code> take the played cards in a game or games and calculate and present their double dummy values.</p>
<table>
<thead>
Expand Down Expand Up @@ -1126,7 +1127,7 @@ <h2 id="functions">Functions</h2>
<p>DDS first detects the number of cores and the available memory. If this doesn't work for some reason, it defaults to 1 thread which is allowed to use the maximum memory size per thread.</p>
<p>DDS then checks whether a number of threads equal to the number of cores will fit within the available memory when each thread may use the maximum memory per thread. If there is not enough memory for this, DDS scales back its ambition. If there is enough memory for the preferred memory size, then DDS still creates a number of threads equal to the number of cores. If there is not even enough memory for this, DDS scales back the number of threads to fit within the memory.</p>
<p>SetMaxThreads no longer influences the thread count: its argument is ignored and internal, global batch threading was removed. To cap workers, pass an explicit maxThreads to the *N or *X entry points, or manage concurrency in the calling application (typically one SolverContext per thread). DDS will otherwise select a suitable number of threads on its own.</p>
<p>Calling SetMaxThreads() is harmless but has no effect beyond initialisation; InitializeStaticMemory() is the non-deprecated spelling.</p>
<p>Calling SetMaxThreads() is harmless but has no effect beyond initialization; InitializeStaticMemory() is the non-deprecated spelling.</p>
<p>SetMaxThreads can be called multiple times, but it cannot change the number of threads: use the per-call maxThreads argument instead.</p>
<p>It is possible to ask DDS to give up its dynamically allocated memory by calling FreeMemory. This could be useful for instance if there is a long pause where DDS is not used within a session. DDS will free its memory when the DLL detaches from the user program, so there is no need for the user to call this function before detaching.
<a name="ReturnCodes"></a></p>
Expand Down
6 changes: 4 additions & 2 deletions doc/dll-description.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ It is possible as an option to perform par calculation in `CalcAllTables` and `C

The par calculation is executed using a single thread. But the calculation is very fast and its duration is negligible compared to the double dummy calculation duration.

### Double Dummy Value Analyser Functions
<a id="double-dummy-value-analyser-functions"></a>

### Double Dummy Value Analyzer Functions

The functions `AnalysePlayBin`, `AnalysePlayPBN`, `AnalyseAllPlaysBin` and `AnalyseAllPlaysPBN` take the played cards in a game or games and calculate and present their double dummy values.

Expand Down Expand Up @@ -1212,7 +1214,7 @@ DDS then checks whether a number of threads equal to the number of cores will fi

SetMaxThreads no longer influences the thread count: its argument is ignored and internal batch threading was removed. To cap workers, pass an explicit maxThreads to the *N or *X entry points, or manage concurrency in the calling application (typically one SolverContext per thread). DDS will otherwise select a suitable number of threads on its own.

Calling SetMaxThreads() is harmless but has no effect beyond initialisation; InitializeStaticMemory() is the non-deprecated spelling.
Calling SetMaxThreads() is harmless but has no effect beyond initialization; InitializeStaticMemory() is the non-deprecated spelling.

SetMaxThreads can be called multiple times, but it cannot change the number of threads: use the per-call maxThreads argument instead.

Expand Down
2 changes: 1 addition & 1 deletion doc/heuristic-sorting.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ LHO is void and LHO has trump card(s), or
RHO is void and RHO has trump card(s).
If RHO has either the highest rank of the suit played by hand-to-play or the next highest rank, then there is a suitBonus change of –18.

If it is a trump contract, the suit is not trump, the own hand has a singleton, the own hand has at least one trump, partner has the highest rank in the suit and at least a suit length of 2, then there is a suitBonus change of +16. Suits are thus favoured where the opponents have as few move alternatives as possible.
If it is a trump contract, the suit is not trump, the own hand has a singleton, the own hand has at least one trump, partner has the highest rank in the suit and at least a suit length of 2, then there is a suitBonus change of +16. Suits are thus favored where the opponents have as few move alternatives as possible.

countLH = (suit length of LHO) * 4, if LHO is not void in the suit,
countLH = (depth + 4), if LHO is void in the suit
Expand Down
6 changes: 3 additions & 3 deletions docs/dotnet_interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ var ctx = new SolverContext(new SolverConfig { ... });
### Configuration & Resources

- **SetMaxThreads(int userThreads)**
Deprecated, and a no-op beyond initialisation: `userThreads` is ignored and
Deprecated, and a no-op beyond initialization: `userThreads` is ignored and
the internal batch threading it once configured has been removed. It is an
alias of `InitializeStaticMemory()`. Worker counts are chosen per call by the
`maxThreads` argument of the `*N` and `*X` entry points, or by the embedding
Expand Down Expand Up @@ -286,8 +286,8 @@ and should be used with caution, as they may not manage resources as efficiently
### Configuration & Resources

- **SetMaxThreads(int userThreads)**
Deprecated, and a no-op beyond initialisation: `userThreads` is ignored, not
honoured as a thread limit. The modern API manages threading via
Deprecated, and a no-op beyond initialization: `userThreads` is ignored, not
honored as a thread limit. The modern API manages threading via
`SolverContext`, and the `*N`/`*X` entry points take a per-call `maxThreads`.

- **SetThreading(int code)**
Expand Down
6 changes: 3 additions & 3 deletions docs/release_notes/release_v3_1_0.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ TOTAL calc 9.35 123.59 8.42

### Correctness fixes

- **`AnalysePlay` under-counted tricks** (#156): each card was analysed against
- **`AnalysePlay` under-counted tricks** (#156): each card was analyzed against
a cold transposition table, so the hint-bounded search settled on the wrong
bound. The play path now reuses the caller's context, matching `SolveBoard`.
- **Move ordering and pruning corruption** from signed→unsigned casts (see
above) — search behaviour only, but it cost significant time.
above) — search behavior only, but it cost significant time.
- **Heap-use-after-free in `clear_tt`** and a null dereference in
`TransTableS::reset_memory` after memory release.
- **Par output now names the declaring seat** when successive par contracts
Expand All @@ -102,7 +102,7 @@ entry points, so callers can size or opt out of the library's parallelism:
`CalcAllTablesX`, `CalcAllTablesPBNX`, `SolveAllBoardsN`, `SolveAllBoardsBinN`,
`SolveAllBoardsSeq`, `SolveAllBoardsBinSeq`.

`SetMaxThreads` is deprecated in favour of `InitializeStaticMemory`; the old
`SetMaxThreads` is deprecated in favor of `InitializeStaticMemory`; the old
name still works and no longer influences batch parallelism.

### Platforms and build
Expand Down
2 changes: 1 addition & 1 deletion jni/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ java_library(

# Stage the host shared library under native/<os>-<arch>/ for jar embedding.
# copy_file outputs are not configurable, so there is one per os+arch triplet
# gated by target_compatible_with; only the host's is analysed, and its output
# gated by target_compatible_with; only the host's is analyzed, and its output
# path's arch matches what Dds.loadEmbedded() looks up at runtime. copy_file is
# shell-free, so no cp/copy toolchain assumption on any host (incl. Windows).
# Host platform only (Phase 1) — a multi-arch fat jar is a separate follow-up.
Expand Down
2 changes: 1 addition & 1 deletion jni/java/org/dds/ffm/DdsStatus.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private DdsStatus() {

/**
* Symbolic name of a status code (e.g. {@code "RETURN_TRUMP_WRONG"}), or
* {@code "RETURN(<code>)"} for an unrecognised value. Handy for assertion
* {@code "RETURN(<code>)"} for an unrecognized value. Handy for assertion
* and log messages.
*/
public static String name(int code) {
Expand Down
4 changes: 2 additions & 2 deletions library/src/calc_tables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ int STDCALL CalcAllTablesN(
int ind = 0;
resp->no_of_boards = 0;

// With no deals the loop below writes no boards, and bo is an uninitialised
// With no deals the loop below writes no boards, and bo is an uninitialized
// local -- solving a board from it reads indeterminate values. Return early,
// matching CalcAllTablesX().
if (dealsp->no_of_tables == 0)
Expand Down Expand Up @@ -398,7 +398,7 @@ int STDCALL CalcAllTablesN(
}

// ind counts the boards actually written; deriving the count from a
// last-index variable initialised to 0 claimed one board even when none
// last-index variable initialized to 0 claimed one board even when none
// had been filled in.
bo.no_of_boards = ind;

Expand Down
2 changes: 1 addition & 1 deletion library/src/dds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ void DDSFinalize(void)
* @brief Library constructor/destructor for Apple platforms.
*
* Register DDSInitialize/DDSFinalize so the library's static memory is set
* up automatically when the library is loaded, matching the behaviour of the
* up automatically when the library is loaded, matching the behavior of the
* Windows (DllMain) and USES_CONSTRUCTOR paths. This frees callers from having
* to call InitializeStaticMemory() themselves.
*/
Expand Down
2 changes: 1 addition & 1 deletion library/src/par_validate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* values and formats them into fixed-size character buffers, so an entry far
* outside the legal range overflows those buffers. CalcDDtable() always
* produces legal tables, but the par entry points are exported and a caller
* may hand-build or deserialise a table, so the range is checked here rather
* may hand-build or deserialize a table, so the range is checked here rather
* than assumed.
*
* @param tablep Table to validate. May be nullptr.
Expand Down
2 changes: 1 addition & 1 deletion library/src/solver_context/solver_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ auto SolverContext::clear_tt() const -> void
// memory (ASan: heap-use-after-free in TransTable{L,S}::lookup).
//
// Disposing instead makes the documented "recreates lazily on demand"
// behaviour real: tt_ becomes null, so the next trans_table() rebuilds from
// behavior real: tt_ becomes null, so the next trans_table() rebuilds from
// the owner's config. Nothing is lost, because the kind and memory limits
// live in SolverContext::cfg_, not in the TT instance.
dispose_trans_table();
Expand Down
2 changes: 1 addition & 1 deletion library/src/trans_table/trans_table_p.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
Experiments with a subsumption tree (storing more specific patterns
beneath more general ones, as bridge-solver does) trimmed the number of
patterns visited per lookup by about 15% but made every visit slower,
since skipping a subtree needs its size, a dependent load that serialises
since skipping a subtree needs its size, a dependent load that serializes
the scan. The flat array was faster on every workload tried.
*/

Expand Down
2 changes: 1 addition & 1 deletion library/src/trans_table/trans_table_p.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

#include <trans_table/trans_table.hpp>

/// \brief Transposition table organised as shape → relative-rank patterns.
/// \brief Transposition table organized as shape → relative-rank patterns.
///
/// This implementation follows the "shape → pattern" cache of macroxue's
/// bridge-solver. A position is keyed by its suit-length shape (plus trick
Expand Down
6 changes: 3 additions & 3 deletions library/tests/deal_input_validation_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ constexpr char kShortOneCard[] =
"N:QJ6.K652.J85.T8 873.J97.AT764.Q4 K5.T83.KQ9.A7652 AT942.AQ4.32.KJ3";

/// The same deal with a card replaced by an invalid rank. convert_from_pbn()
/// silently skips unrecognised characters, so this also arrives one card short.
/// silently skips unrecognized characters, so this also arrives one card short.
constexpr char kBadRank[] =
"N:QJ6.K652.J85.TZ8 873.J97.AT764.Q4 K5.T83.KQ9.A7652 AT942.AQ4.32.KJ3";

Expand Down Expand Up @@ -261,8 +261,8 @@ TEST(CalcTableValidation, CalcAllTablesRejectsNegativeTableCount)
TEST(CalcTableValidation, CalcAllTablesWithZeroDealsSolvesNothing)
{
// With no deals the board-building loop writes nothing, but the board count
// was derived from a last-index variable initialised to 0 and so claimed
// one board -- solving an uninitialised entry of a stack-local Boards.
// was derived from a last-index variable initialized to 0 and so claimed
// one board -- solving an uninitialized entry of a stack-local Boards.
// MemorySanitizer reports it; found by the calc_all_tables fuzz harness.
DdTableDeals deals;
std::memset(&deals, 0, sizeof(deals));
Expand Down
8 changes: 4 additions & 4 deletions library/tests/fuzz/findings/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,19 +102,19 @@ validation logic itself.
Fixed by range-checking `currentTrickSuit[k]` inside that loop, where it is
actually used as a subscript, rather than in `board_range_checks()` — this
rejects only inputs that would genuinely have been read out of bounds, and
leaves callers that pass an uninitialised suit alongside a zero rank working
leaves callers that pass an uninitialized suit alongside a zero rank working
as before whenever the value is never used.

Seed: `corpus/solve_board/regression_unchecked_trick_suit.bin`.
Tests: `library/tests/deal_input_validation_test.cpp` (`DumpInputSafety`).

### 05 — `CalcAllTablesN()` solved an uninitialised board when given no deals
### 05 — `CalcAllTablesN()` solved an uninitialized board when given no deals

Found by the `calc_all_tables` harness on its first CI run, under
MemorySanitizer (`zero_tables.bin`).

`Boards bo;` is an uninitialised stack local. The board count was derived from
a `lastIndex` variable initialised to 0 and only assigned inside the
`Boards bo;` is an uninitialized stack local. The board count was derived from
a `lastIndex` variable initialized to 0 and only assigned inside the
board-building loop, so `bo.no_of_boards = lastIndex + 1` claimed **one** board
even when `no_of_tables == 0` and the loop had written none.
`calc_all_boards_n()` then solved `bo.deals[0]`, `bo.target[0]`,
Expand Down
2 changes: 1 addition & 1 deletion library/tests/heuristic_sorting/dispatch_findex_test.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* @file dispatch_findex_test.cpp
* @brief Behaviour of WeightCase-based heuristic dispatch.
* @brief Behavior of WeightCase-based heuristic dispatch.
*
* Move generation always passes a precomputed WeightCase. This file covers the
* dispatcher's fallback when an unrecognized case reaches call_heuristic.
Expand Down
2 changes: 1 addition & 1 deletion library/tests/solve_board/analyse_play_consistency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ auto solve_max(int trump, int leader, const std::vector<Card>& cur,
}

// Core check: AnalysePlayPBN's per-card trick count must match an independent
// SolveBoardPBN of the reconstructed position at every analysed ply.
// SolveBoardPBN of the reconstructed position at every analyzed ply.
auto check_self_consistency(const Hands& hands, int trump, int opening_leader,
const std::vector<Card>& play) -> void
{
Expand Down
4 changes: 2 additions & 2 deletions library/tests/system/configure_tt_api_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ auto solve_known_deal(SolverContext& ctx, FutureTricks& fut) -> int
}

/// A table recreated between two solves of the same deal has not seen that
/// deal; the next solve must initialise it again rather than run against an
/// deal; the next solve must initialize it again rather than run against an
/// inert (never init()-ed) cache.
TEST(ConfigureTtApiTest, ATableRecreatedBetweenSolvesOfTheSameDealIsInitialisedAgain)
{
Expand Down Expand Up @@ -305,7 +305,7 @@ TEST(ConfigureTtApiTest, ConfigureTtComparesTheEnvironmentResolvedKind)

TEST(ConfigureTtApiTest, SwitchKindRecreatesTable)
{
// Default context, isolated from any ambient override (override behaviour
// Default context, isolated from any ambient override (override behavior
// is covered by the Environment* tests).
ScopedEnv no_override("DDS_TT_KIND", nullptr);
SolverContext ctx;
Expand Down
2 changes: 1 addition & 1 deletion library/tests/system/max_threads_equivalence_test.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// @file max_threads_equivalence_test.cpp
/// @brief Tests that the *N batch APIs honour maxThreads and stay equivalent to
/// @brief Tests that the *N batch APIs honor maxThreads and stay equivalent to
/// the auto path, plus that the rename/alias both initialize the library.

#include <gtest/gtest.h>
Expand Down
2 changes: 1 addition & 1 deletion library/tests/trans_table/trans_table_p_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ TEST_F(TransTablePTest, DifferentHandTricksOrShapeDoNotMatch)
}

// ---------------------------------------------------------------------------
// Relative-rank pattern generalisation
// Relative-rank pattern generalization
// ---------------------------------------------------------------------------

TEST_F(TransTablePTest, PositionDifferingOnlyInIrrelevantCardsHits)
Expand Down
Loading