@@ -175,40 +175,52 @@ TEST_CASE("theta sketch: get_result trims to k in one pass", "[theta_sketch]") {
175175 const uint32_t k = 1 << theta_constants::DEFAULT_LG_K ;
176176 REQUIRE (update_sketch.get_num_retained () > k); // over-provisioned before trimming
177177
178- compact_theta_sketch result = update_sketch.get_result ();
179- REQUIRE_FALSE (result.is_empty ());
180- REQUIRE (result.is_estimation_mode ());
181- REQUIRE (result.get_num_retained () == k); // trimmed to nominal size
182- REQUIRE_FALSE (result.is_ordered ()); // unordered: no sort performed
183-
184- // fused get_result() must match trim() + compact()
178+ // default is ordered, matching union/intersection get_result
179+ compact_theta_sketch ordered_result = update_sketch.get_result ();
180+ REQUIRE_FALSE (ordered_result.is_empty ());
181+ REQUIRE (ordered_result.is_estimation_mode ());
182+ REQUIRE (ordered_result.get_num_retained () == k); // trimmed to nominal size
183+ REQUIRE (ordered_result.is_ordered ());
184+ REQUIRE (std::is_sorted (ordered_result.begin (), ordered_result.end ()));
185+
186+ // fused get_result(true) must match trim() + compact(true)
185187 update_theta_sketch trimmed = update_sketch;
186188 trimmed.trim ();
187- compact_theta_sketch expected = trimmed.compact (false );
188- REQUIRE (result.get_theta64 () == expected.get_theta64 ());
189- REQUIRE (result.get_num_retained () == expected.get_num_retained ());
190- REQUIRE (result.get_estimate () == expected.get_estimate ());
191-
192- // same set of retained hashes (order-independent)
193- std::vector<uint64_t > a (result.begin (), result.end ());
194- std::vector<uint64_t > b (expected.begin (), expected.end ());
195- std::sort (a.begin (), a.end ());
196- std::sort (b.begin (), b.end ());
197- REQUIRE (a == b);
189+ compact_theta_sketch expected = trimmed.compact (true );
190+ REQUIRE (ordered_result.get_theta64 () == expected.get_theta64 ());
191+ REQUIRE (ordered_result.get_num_retained () == expected.get_num_retained ());
192+ REQUIRE (ordered_result.get_estimate () == expected.get_estimate ());
193+ REQUIRE (std::vector<uint64_t >(ordered_result.begin (), ordered_result.end ())
194+ == std::vector<uint64_t >(expected.begin (), expected.end ()));
195+
196+ // unordered variant: same trimmed set and theta, no sort
197+ compact_theta_sketch unordered_result = update_sketch.get_result (false );
198+ REQUIRE_FALSE (unordered_result.is_ordered ());
199+ REQUIRE (unordered_result.get_num_retained () == k);
200+ REQUIRE (unordered_result.get_theta64 () == expected.get_theta64 ());
201+ std::vector<uint64_t > unordered_hashes (unordered_result.begin (), unordered_result.end ());
202+ std::sort (unordered_hashes.begin (), unordered_hashes.end ());
203+ REQUIRE (unordered_hashes == std::vector<uint64_t >(expected.begin (), expected.end ()));
198204}
199205
200206TEST_CASE (" theta sketch: get_result on empty and below-k sketches" , " [theta_sketch]" ) {
201207 compact_theta_sketch empty_result = update_theta_sketch::builder ().build ().get_result ();
202208 REQUIRE (empty_result.is_empty ());
203209 REQUIRE (empty_result.get_num_retained () == 0 );
210+ REQUIRE (empty_result.is_ordered ());
204211
205212 update_theta_sketch small = update_theta_sketch::builder ().build ();
206213 for (int i = 0 ; i < 100 ; i++) small.update (i);
207214 REQUIRE_FALSE (small.is_estimation_mode ());
208- compact_theta_sketch small_result = small.get_result ();
215+
216+ compact_theta_sketch small_result = small.get_result (); // default ordered
209217 REQUIRE_FALSE (small_result.is_estimation_mode ());
210218 REQUIRE (small_result.get_num_retained () == 100 ); // below k: nothing trimmed
211219 REQUIRE (small_result.get_estimate () == Approx (100.0 ));
220+ REQUIRE (small_result.is_ordered ());
221+ REQUIRE (std::is_sorted (small_result.begin (), small_result.end ()));
222+
223+ REQUIRE_FALSE (small.get_result (false ).is_ordered ()); // unordered variant
212224}
213225
214226TEST_CASE (" theta sketch: deserialize compact v1 empty from java" , " [theta_sketch]" ) {
0 commit comments