Skip to content

Commit ec73ccc

Browse files
Merge origin/main into feat/contains-value; resolve CHANGELOG conflict
Co-authored-by: marius-bughiu <11870708+marius-bughiu@users.noreply.github.com>
2 parents aaa8f0a + 1d6534a commit ec73ccc

6 files changed

Lines changed: 517 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,18 @@ All notable changes to Celerity are documented here. This project follows [Keep
44

55
## [Unreleased]
66

7+
### Fixed
8+
9+
- `StringFnV1AHasher.Hash(null)` now throws `ArgumentNullException` (parameter name `"key"`) instead of `NullReferenceException`. Public APIs should signal a null argument as an explicit contract violation, not as an unchecked dereference. The Celerity dictionaries store the out-of-band `null` / `default(TKey)` key entry without ever calling the hasher, so the surface area of this change is limited to direct `StringFnV1AHasher` usage and to consumers that plug the hasher into custom `IHashProvider<string>` callers that do not handle the null-key slot themselves. The XML doc comment on `Hash` now declares the exception, and `StringFnV1AHasherTests.Hash_NullString_*` is updated to assert `ArgumentNullException` rather than pinning the previous wart. Closes #71.
10+
11+
## [1.2.0] - 2026-05-10
12+
713
### Added
814

915
- `ContainsValue(TValue? value)` on `IntDictionary<TValue, THasher>`, `LongDictionary<TValue, THasher>`, and `CelerityDictionary<TKey, TValue, THasher>` — BCL-parity `O(n)` linear scan that returns `true` if any entry's value equals `value` under `EqualityComparer<TValue>.Default`, matching `Dictionary<TKey, TValue>.ContainsValue(TValue)`. The scan walks the probe table (skipping `EMPTY_KEY` / `default(TKey)` slots so the empty `default(TValue)` payload there is not mistaken for a real entry) and, when present, the out-of-band zero-key / default-key slot. No allocation on the hot path beyond the cached `EqualityComparer<TValue>.Default` access. Closes #73.
1016
- `ContainsValueTests` — coverage on all three dictionaries: empty-map false return, match in a regular slot, match found only in the zero-key / default-key / null-string-key slot, missing-value false return, default-`TValue` (`0`) lookup on both empty and populated dictionaries (regression check that `EMPTY_KEY` slots are skipped and not reported as `0` matches), `null`-`TValue` lookup on a reference-type value, duplicate values short-circuiting, post-resize correctness across a 100-entry insert from a tiny initial capacity, and post-`Remove` / post-`Clear` invalidation.
17+
- `IEnumerable<T>` constructor on `IntSet`, `IntSet<THasher>`, and `CeleritySet<T, THasher>` (and the `IntSet` convenience subclass), mirroring the dictionary `IEnumerable<KeyValuePair<,>>` ctor shipped in 1.1.2. Throws `ArgumentNullException` on a null source. Unlike the dictionary ctor, duplicate elements (including duplicate `default(T)` / zero entries) are silently deduplicated to match BCL `HashSet<T>(IEnumerable<T>)` semantics — sets do not have a duplicate-key contract. When the source implements `ICollection<T>`, its `Count` is used to size the backing storage; otherwise the caller-supplied `capacity` parameter is used. The out-of-band `default(T)` / zero slot is populated correctly when the source contains it. Closes the last set-side API-parity gap for milestone 1.1.0 and unblocks future `IReadOnlySet<T>` work. Closes #69.
18+
- `SetIEnumerableConstructorTests` — coverage for both sets: null-source and invalid-load-factor validation, empty sources, array / list / non-collection enumerable sources, duplicate-element silent dedupe (including duplicate zero / `null` / `default(T)` entries), zero-element / null-reference-element capture, 500-entry large-source round-trip, source-independence after construction, caller-specified capacity dominating the source count, cross-set copy (`CeleritySet` from an `IntSet` enumeration), and an open-generic `IntSet<Int32WangNaiveHasher>` smoke test.
1119
- `README.md` — new "Choosing a collection" section: a decision table mapping common workloads (`int`-keyed, `long`-keyed, `Guid` / `string` / other-keyed dictionaries, the two set shapes) onto the right Celerity type, plus a short note on picking a hasher and an honest "where Celerity is not the right answer today" list (concurrent access, mutable `IDictionary<,>` consumers, `FrozenDictionary`-style build-once lookups). Sits between the Quick start and Benchmarks sections so a reader who has scanned the API surface can pick the right type without spelunking `docs/api/`. Implements the "Document when to use which collection" item from issue #15.
1220
- `README.md` — new "Quick start" section with concrete, runnable usage examples for `IntDictionary`, `CelerityDictionary` (with `GuidHasher`, `StringFnV1AHasher`, `DefaultHasher<T>`), the sets (`IntSet`, `CeleritySet`), and the `IEnumerable<KeyValuePair<,>>` constructor. Covers indexer get/set, `TryAdd` / `Add` semantics, `TryGetValue`, removal, and bulk-load from a BCL `Dictionary<,>`. Closes the "Add usage examples to README" item from issue #15.
1321

@@ -84,6 +92,7 @@ First successful 1.1.x publish. Tags `v1.1.0` and `v1.1.1` exist on the reposito
8492

8593
Initial public versions, including `CelerityDictionary<TKey, TValue, THasher>`, `IntDictionary<TValue>`, the `Int32WangNaiveHasher`, `Int64Murmur3Hasher`, and `StringFnV1AHasher` hash providers, and the BenchmarkDotNet benchmark suite comparing `CelerityDictionary` against the BCL `Dictionary<int, int>`. See the git history under tags `v0.1.*` for specifics.
8694

87-
[Unreleased]: https://github.com/marius-bughiu/Celerity/compare/v1.1.2...HEAD
95+
[Unreleased]: https://github.com/marius-bughiu/Celerity/compare/v1.2.0...HEAD
96+
[1.2.0]: https://github.com/marius-bughiu/Celerity/releases/tag/v1.2.0
8897
[1.1.2]: https://github.com/marius-bughiu/Celerity/releases/tag/v1.1.2
8998
[0.1.0]: https://github.com/marius-bughiu/Celerity/releases/tag/v0.1.0

0 commit comments

Comments
 (0)