Skip to content

Commit bfbb92f

Browse files
authored
local and collective contains for map, bag, counting set, and set (#394)
1 parent 133c77c commit bfbb92f

File tree

10 files changed

+186
-1
lines changed

10 files changed

+186
-1
lines changed

include/ygm/container/bag.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <initializer_list>
1313
#include <ygm/container/container_traits.hpp>
1414
#include <ygm/container/detail/base_async_insert.hpp>
15+
#include <ygm/container/detail/base_contains.hpp>
1516
#include <ygm/container/detail/base_count.hpp>
1617
#include <ygm/container/detail/base_iteration.hpp>
1718
#include <ygm/container/detail/base_iterators.hpp>
@@ -28,6 +29,7 @@ namespace ygm::container {
2829
*/
2930
template <typename Item>
3031
class bag : public detail::base_async_insert_value<bag<Item>, std::tuple<Item>>,
32+
public detail::base_contains<bag<Item>, std::tuple<Item>>,
3133
public detail::base_count<bag<Item>, std::tuple<Item>>,
3234
public detail::base_misc<bag<Item>, std::tuple<Item>>,
3335
public detail::base_iterators<bag<Item>>,
@@ -259,6 +261,17 @@ class bag : public detail::base_async_insert_value<bag<Item>, std::tuple<Item>>,
259261
return std::count(m_local_bag.begin(), m_local_bag.end(), val);
260262
}
261263

264+
/**
265+
* @brief Check if a value exists locally
266+
*
267+
* @param val Value to check for
268+
* @return True if value exists locally, false otherwise
269+
*/
270+
bool local_contains(const value_type &val) const {
271+
return std::find(m_local_bag.begin(), m_local_bag.end(), val) !=
272+
m_local_bag.end();
273+
}
274+
262275
/**
263276
* @brief Execute a functor on every locally-held item
264277
*

include/ygm/container/counting_set.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <ygm/comm.hpp>
99
#include <ygm/container/container_traits.hpp>
10+
#include <ygm/container/detail/base_contains.hpp>
1011
#include <ygm/container/detail/base_count.hpp>
1112
#include <ygm/container/detail/base_iteration.hpp>
1213
#include <ygm/container/detail/base_misc.hpp>
@@ -25,6 +26,7 @@ namespace ygm::container {
2526
template <typename Key>
2627
class counting_set
2728
: public detail::base_count<counting_set<Key>, std::tuple<Key, size_t>>,
29+
public detail::base_contains<counting_set<Key>, std::tuple<Key, size_t>>,
2830
public detail::base_misc<counting_set<Key>, std::tuple<Key, size_t>>,
2931
public detail::base_iterators<counting_set<Key>>,
3032
public detail::base_iteration_key_value<counting_set<Key>,
@@ -286,6 +288,16 @@ class counting_set
286288
return local_count;
287289
}
288290

291+
/**
292+
* @brief Check if a locally-held item exists
293+
*
294+
* @param val Value to check for
295+
* @return true if value exists locally, false otherwise
296+
*/
297+
bool local_contains(const key_type &key) const {
298+
return m_map.local_contains(key);
299+
}
300+
289301
/**
290302
* @brief Count the total number of items counted
291303
*
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2019-2025 Lawrence Livermore National Security, LLC and other YGM
2+
// Project Developers. See the top-level COPYRIGHT file for details.
3+
//
4+
// SPDX-License-Identifier: MIT
5+
6+
#pragma once
7+
8+
#include <tuple>
9+
#include <utility>
10+
11+
namespace ygm::container::detail {
12+
13+
/**
14+
* @brief Curiously-recurring template parameter struct that provides
15+
* count operation
16+
*/
17+
template <typename derived_type, typename for_all_args>
18+
struct base_contains {
19+
/**
20+
* @brief Checks for the presence of a value within a container.
21+
*
22+
* @param value Value to search for within container (key in the case of
23+
* containers with keys)
24+
* @return True if `value` exists in container; false otherwise.
25+
*/
26+
bool contains(
27+
const typename std::tuple_element<0, for_all_args>::type& value) const {
28+
const derived_type* derived_this = static_cast<const derived_type*>(this);
29+
derived_this->comm().barrier();
30+
return ::ygm::logical_or(derived_this->local_contains(value),
31+
derived_this->comm());
32+
}
33+
};
34+
35+
} // namespace ygm::container::detail

include/ygm/container/map.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <ygm/container/detail/base_async_reduce.hpp>
1414
#include <ygm/container/detail/base_async_visit.hpp>
1515
#include <ygm/container/detail/base_batch_erase.hpp>
16+
#include <ygm/container/detail/base_contains.hpp>
1617
#include <ygm/container/detail/base_count.hpp>
1718
#include <ygm/container/detail/base_iteration.hpp>
1819
#include <ygm/container/detail/base_iterators.hpp>
@@ -28,6 +29,7 @@ class map
2829
public detail::base_async_insert_or_assign<map<Key, Value>,
2930
std::tuple<Key, Value>>,
3031
public detail::base_misc<map<Key, Value>, std::tuple<Key, Value>>,
32+
public detail::base_contains<map<Key, Value>, std::tuple<Key, Value>>,
3133
public detail::base_count<map<Key, Value>, std::tuple<Key, Value>>,
3234
public detail::base_async_reduce<map<Key, Value>, std::tuple<Key, Value>>,
3335
public detail::base_async_erase_key<map<Key, Value>,
@@ -562,6 +564,16 @@ class map
562564
return m_local_map.count(key);
563565
}
564566

567+
/**
568+
* @brief Check if a key exists locally
569+
*
570+
* @param key key to check for
571+
* @return True if `key` exists locally, false otherwise
572+
*/
573+
bool local_contains(const key_type& key) const {
574+
return m_local_map.contains(key);
575+
}
576+
565577
// void serialize(const std::string& fname) { m_impl.serialize(fname); }
566578
// void deserialize(const std::string& fname) { m_impl.deserialize(fname); }
567579

include/ygm/container/set.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <ygm/container/detail/base_async_insert.hpp>
1313
#include <ygm/container/detail/base_async_insert_contains.hpp>
1414
#include <ygm/container/detail/base_batch_erase.hpp>
15+
#include <ygm/container/detail/base_contains.hpp>
1516
#include <ygm/container/detail/base_count.hpp>
1617
#include <ygm/container/detail/base_iteration.hpp>
1718
#include <ygm/container/detail/base_iterators.hpp>
@@ -27,6 +28,7 @@ class set
2728
public detail::base_batch_erase_key<set<Value>, std::tuple<Value>>,
2829
public detail::base_async_contains<set<Value>, std::tuple<Value>>,
2930
public detail::base_async_insert_contains<set<Value>, std::tuple<Value>>,
31+
public detail::base_contains<set<Value>, std::tuple<Value>>,
3032
public detail::base_count<set<Value>, std::tuple<Value>>,
3133
public detail::base_misc<set<Value>, std::tuple<Value>>,
3234
public detail::base_iterators<set<Value>>,
@@ -228,6 +230,16 @@ class set
228230
return m_local_set.count(val);
229231
}
230232

233+
/**
234+
* @brief Check if a value exists locally
235+
*
236+
* @param val Value to check for
237+
* @return True if value exists locally, false otherwise
238+
*/
239+
bool local_contains(const value_type &val) const {
240+
return m_local_set.contains(val);
241+
}
242+
231243
/**
232244
* @brief Get the number of elements stored on the local process.
233245
*

test/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ add_ygm_test(test_set)
5050
add_ygm_test(test_bag)
5151
#add_ygm_test(test_tagged_bag)
5252
add_ygm_test(test_array)
53-
#add_ygm_test(test_counting_set)
53+
# add_ygm_test(test_counting_set)
5454
add_ygm_test(test_disjoint_set)
5555
#add_ygm_test(test_container_serialization)
5656
add_ygm_test(test_line_parser)

test/test_bag.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ int main(int argc, char** argv) {
4040
YGM_ASSERT_RELEASE(bbag.count("red") == 1);
4141
YGM_ASSERT_RELEASE(bbag.size() == 3);
4242

43+
// test contains.
44+
YGM_ASSERT_RELEASE(bbag.contains("dog"));
45+
YGM_ASSERT_RELEASE(bbag.contains("apple"));
46+
YGM_ASSERT_RELEASE(bbag.contains("red"));
47+
YGM_ASSERT_RELEASE(!bbag.contains("blue"));
48+
4349
for (auto& value : bbag) {
4450
world.cout(value);
4551
}
@@ -158,6 +164,12 @@ int main(int argc, char** argv) {
158164
YGM_ASSERT_RELEASE(bbag.count("apple") == (size_t)world.size());
159165
YGM_ASSERT_RELEASE(bbag.count("red") == (size_t)world.size());
160166

167+
// test contains
168+
YGM_ASSERT_RELEASE(bbag.contains("dog"));
169+
YGM_ASSERT_RELEASE(bbag.contains("apple"));
170+
YGM_ASSERT_RELEASE(bbag.contains("red"));
171+
YGM_ASSERT_RELEASE(!bbag.contains("blue"));
172+
161173
{
162174
std::vector<std::string> all_data;
163175
bbag.gather(all_data, 0);

test/test_counting_set.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ int main(int argc, char **argv) {
4444
YGM_ASSERT_RELEASE(count_map["dog"] == 1);
4545
YGM_ASSERT_RELEASE(count_map["apple"] == 1);
4646
YGM_ASSERT_RELEASE(count_map.count("cat") == 0);
47+
48+
// test contains
49+
YGM_ASSERT_RELEASE(cset.contains("dog"));
50+
YGM_ASSERT_RELEASE(cset.contains("apple"));
51+
YGM_ASSERT_RELEASE(cset.contains("red"));
52+
YGM_ASSERT_RELEASE(!cset.contains("blue"));
4753
}
4854

4955
//
@@ -66,6 +72,12 @@ int main(int argc, char **argv) {
6672
YGM_ASSERT_RELEASE(cset.count("cat") == 0);
6773

6874
YGM_ASSERT_RELEASE(cset.count_all() == 3 * (size_t)world.size());
75+
76+
// test contains
77+
YGM_ASSERT_RELEASE(cset.contains("dog"));
78+
YGM_ASSERT_RELEASE(cset.contains("apple"));
79+
YGM_ASSERT_RELEASE(cset.contains("red"));
80+
YGM_ASSERT_RELEASE(!cset.contains("blue"));
6981
}
7082

7183
//
@@ -113,6 +125,12 @@ int main(int argc, char **argv) {
113125
YGM_ASSERT_RELEASE(cset.count("dog") == 0);
114126
YGM_ASSERT_RELEASE(cset.count("apple") == 0);
115127
YGM_ASSERT_RELEASE(cset.count("red") == 0);
128+
129+
// test contains
130+
YGM_ASSERT_RELEASE(!cset.contains("dog"));
131+
YGM_ASSERT_RELEASE(!cset.contains("apple"));
132+
YGM_ASSERT_RELEASE(!cset.contains("red"));
133+
YGM_ASSERT_RELEASE(!cset.contains("blue"));
116134
}
117135

118136
// //
@@ -166,6 +184,12 @@ int main(int argc, char **argv) {
166184
YGM_ASSERT_RELEASE(cset2.count("bird") == (size_t)world.size());
167185
YGM_ASSERT_RELEASE(cset2.count("red") == 0);
168186
YGM_ASSERT_RELEASE(cset2.size() == 3);
187+
188+
// test contains
189+
YGM_ASSERT_RELEASE(cset2.contains("dog"));
190+
YGM_ASSERT_RELEASE(cset2.contains("cat"));
191+
YGM_ASSERT_RELEASE(cset2.contains("bird"));
192+
YGM_ASSERT_RELEASE(!cset2.contains("red"));
169193
}
170194

171195
//

test/test_map.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ int main(int argc, char **argv) {
4040
YGM_ASSERT_RELEASE(smap.count("dog") == 1);
4141
YGM_ASSERT_RELEASE(smap.count("apple") == 1);
4242
YGM_ASSERT_RELEASE(smap.count("red") == 1);
43+
44+
// test contains.
45+
YGM_ASSERT_RELEASE(smap.contains("dog"));
46+
YGM_ASSERT_RELEASE(smap.contains("apple"));
47+
YGM_ASSERT_RELEASE(smap.contains("red"));
48+
YGM_ASSERT_RELEASE(!smap.contains("blue"));
4349
}
4450

4551
//
@@ -54,6 +60,12 @@ int main(int argc, char **argv) {
5460
YGM_ASSERT_RELEASE(smap.count("dog") == 1);
5561
YGM_ASSERT_RELEASE(smap.count("apple") == 1);
5662
YGM_ASSERT_RELEASE(smap.count("red") == 1);
63+
64+
// test contains.
65+
YGM_ASSERT_RELEASE(smap.contains("dog"));
66+
YGM_ASSERT_RELEASE(smap.contains("apple"));
67+
YGM_ASSERT_RELEASE(smap.contains("red"));
68+
YGM_ASSERT_RELEASE(!smap.contains("blue"));
5769
}
5870

5971
//
@@ -142,13 +154,21 @@ int main(int argc, char **argv) {
142154

143155
YGM_ASSERT_RELEASE(smap.size() == 2);
144156

157+
// test contains.
158+
YGM_ASSERT_RELEASE(smap.contains("dog"));
159+
YGM_ASSERT_RELEASE(smap.contains("cat"));
160+
YGM_ASSERT_RELEASE(!smap.contains("red"));
161+
YGM_ASSERT_RELEASE(!smap.contains("blue"));
162+
145163
if (world.rank() == 0) {
146164
smap.async_erase("dog");
147165
}
148166
YGM_ASSERT_RELEASE(smap.count("dog") == 0);
149167
YGM_ASSERT_RELEASE(smap.size() == 1);
168+
YGM_ASSERT_RELEASE(!smap.contains("dog"));
150169
smap.async_erase("cat");
151170
YGM_ASSERT_RELEASE(smap.count("cat") == 0);
171+
YGM_ASSERT_RELEASE(!smap.contains("cat"));
152172

153173
YGM_ASSERT_RELEASE(smap.size() == 0);
154174
}
@@ -268,9 +288,17 @@ int main(int argc, char **argv) {
268288
YGM_ASSERT_RELEASE(smap.count("dog") == 1);
269289
YGM_ASSERT_RELEASE(smap.count("apple") == 1);
270290
YGM_ASSERT_RELEASE(smap.count("red") == 1);
291+
292+
YGM_ASSERT_RELEASE(!smap.contains("car"));
271293
smap.async_insert_or_assign("car", "truck");
272294
YGM_ASSERT_RELEASE(smap.size() == 4);
273295
YGM_ASSERT_RELEASE(smap.count("car") == 1);
296+
297+
// test contains.
298+
YGM_ASSERT_RELEASE(smap.contains("dog"));
299+
YGM_ASSERT_RELEASE(smap.contains("car"));
300+
YGM_ASSERT_RELEASE(smap.contains("red"));
301+
YGM_ASSERT_RELEASE(!smap.contains("blue"));
274302
}
275303

276304
// Test batch erase from set

0 commit comments

Comments
 (0)