Skip to content

Commit bf8685a

Browse files
committed
[libc++] Optimize {set,map}::{lower,upper}_bound
1 parent 1098a5c commit bf8685a

File tree

3 files changed

+126
-41
lines changed

3 files changed

+126
-41
lines changed

libcxx/include/__tree

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,32 +1165,81 @@ public:
11651165
template <class _Key>
11661166
_LIBCPP_HIDE_FROM_ABI size_type __count_multi(const _Key& __k) const;
11671167

1168+
template <bool _LowerBound, class _Key>
1169+
_LIBCPP_HIDE_FROM_ABI __end_node_pointer __lower_upper_bound_unique_impl(const _Key& __v) const {
1170+
auto __rt = __root();
1171+
auto __result = __end_node();
1172+
auto __comp = __lazy_synth_three_way_comparator<_Compare, _Key, value_type>(value_comp());
1173+
while (__rt != nullptr) {
1174+
auto __comp_res = __comp(__v, __rt->__get_value());
1175+
1176+
if (__comp_res.__less()) {
1177+
__result = static_cast<__end_node_pointer>(__rt);
1178+
__rt = static_cast<__node_pointer>(__rt->__left_);
1179+
} else if (__comp_res.__greater()) {
1180+
__rt = static_cast<__node_pointer>(__rt->__right_);
1181+
} else if _LIBCPP_CONSTEXPR (_LowerBound) {
1182+
return static_cast<__end_node_pointer>(__rt);
1183+
} else {
1184+
return __rt->__right_ ? static_cast<__end_node_pointer>(std::__tree_min(__rt->__right_)) : __result;
1185+
}
1186+
}
1187+
return __result;
1188+
}
1189+
11681190
template <class _Key>
1169-
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Key& __v) {
1170-
return __lower_bound(__v, __root(), __end_node());
1191+
_LIBCPP_HIDE_FROM_ABI iterator __lower_bound_unique(const _Key& __v) {
1192+
return iterator(__lower_upper_bound_unique_impl<true>(__v));
11711193
}
1194+
11721195
template <class _Key>
1173-
_LIBCPP_HIDE_FROM_ABI iterator __lower_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result);
1196+
_LIBCPP_HIDE_FROM_ABI const_iterator __lower_bound_unique(const _Key& __v) const {
1197+
return const_iterator(__lower_upper_bound_unique_impl<true>(__v));
1198+
}
1199+
11741200
template <class _Key>
1175-
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Key& __v) const {
1176-
return __lower_bound(__v, __root(), __end_node());
1201+
_LIBCPP_HIDE_FROM_ABI iterator __upper_bound_unique(const _Key& __v) {
1202+
return iterator(__lower_upper_bound_unique_impl<false>(__v));
1203+
}
1204+
1205+
template <class _Key>
1206+
_LIBCPP_HIDE_FROM_ABI const_iterator __upper_bound_unique(const _Key& __v) const {
1207+
return iterator(__lower_upper_bound_unique_impl<false>(__v));
11771208
}
1209+
1210+
template <class _Key>
1211+
_LIBCPP_HIDE_FROM_ABI iterator __lower_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result);
1212+
11781213
template <class _Key>
11791214
_LIBCPP_HIDE_FROM_ABI const_iterator
11801215
__lower_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result) const;
1216+
11811217
template <class _Key>
1182-
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Key& __v) {
1183-
return __upper_bound(__v, __root(), __end_node());
1218+
_LIBCPP_HIDE_FROM_ABI iterator __lower_bound_multi(const _Key& __v) {
1219+
return __lower_bound(__v, __root(), __end_node());
11841220
}
11851221
template <class _Key>
1186-
_LIBCPP_HIDE_FROM_ABI iterator __upper_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result);
1222+
_LIBCPP_HIDE_FROM_ABI const_iterator __lower_bound_multi(const _Key& __v) const {
1223+
return __lower_bound(__v, __root(), __end_node());
1224+
}
1225+
11871226
template <class _Key>
1188-
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Key& __v) const {
1227+
_LIBCPP_HIDE_FROM_ABI iterator __upper_bound_multi(const _Key& __v) {
11891228
return __upper_bound(__v, __root(), __end_node());
11901229
}
1230+
1231+
template <class _Key>
1232+
_LIBCPP_HIDE_FROM_ABI const_iterator __upper_bound_multi(const _Key& __v) const {
1233+
return __upper_bound(__v, __root(), __end_node());
1234+
}
1235+
1236+
template <class _Key>
1237+
_LIBCPP_HIDE_FROM_ABI iterator __upper_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result);
1238+
11911239
template <class _Key>
11921240
_LIBCPP_HIDE_FROM_ABI const_iterator
11931241
__upper_bound(const _Key& __v, __node_pointer __root, __end_node_pointer __result) const;
1242+
11941243
template <class _Key>
11951244
_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> __equal_range_unique(const _Key& __k);
11961245
template <class _Key>

libcxx/include/map

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,30 +1268,40 @@ public:
12681268
}
12691269
# endif // _LIBCPP_STD_VER >= 20
12701270

1271-
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.lower_bound(__k); }
1272-
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const { return __tree_.lower_bound(__k); }
1271+
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.__lower_bound_unique(__k); }
1272+
1273+
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const {
1274+
return __tree_.__lower_bound_unique(__k);
1275+
}
1276+
1277+
// The transparent versions of the lookup functions use the _multi version, since a non-element key is allowed to
1278+
// match multiple elements.
12731279
# if _LIBCPP_STD_VER >= 14
12741280
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
12751281
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
1276-
return __tree_.lower_bound(__k);
1282+
return __tree_.__lower_bound_multi(__k);
12771283
}
12781284

12791285
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
12801286
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const {
1281-
return __tree_.lower_bound(__k);
1287+
return __tree_.__lower_bound_multi(__k);
12821288
}
12831289
# endif
12841290

1285-
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.upper_bound(__k); }
1286-
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const { return __tree_.upper_bound(__k); }
1291+
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.__upper_bound_unique(__k); }
1292+
1293+
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const {
1294+
return __tree_.__upper_bound_unique(__k);
1295+
}
1296+
12871297
# if _LIBCPP_STD_VER >= 14
12881298
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
12891299
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
1290-
return __tree_.upper_bound(__k);
1300+
return __tree_.__upper_bound_multi(__k);
12911301
}
12921302
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
12931303
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const {
1294-
return __tree_.upper_bound(__k);
1304+
return __tree_.__upper_bound_multi(__k);
12951305
}
12961306
# endif
12971307

@@ -1831,30 +1841,38 @@ public:
18311841
}
18321842
# endif // _LIBCPP_STD_VER >= 20
18331843

1834-
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.lower_bound(__k); }
1835-
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const { return __tree_.lower_bound(__k); }
1844+
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.__lower_bound_multi(__k); }
1845+
1846+
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const {
1847+
return __tree_.__lower_bound_multi(__k);
1848+
}
1849+
18361850
# if _LIBCPP_STD_VER >= 14
18371851
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
18381852
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
1839-
return __tree_.lower_bound(__k);
1853+
return __tree_.__lower_bound_multi(__k);
18401854
}
18411855

18421856
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
18431857
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const {
1844-
return __tree_.lower_bound(__k);
1858+
return __tree_.__lower_bound_multi(__k);
18451859
}
18461860
# endif
18471861

1848-
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.upper_bound(__k); }
1849-
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const { return __tree_.upper_bound(__k); }
1862+
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.__upper_bound_multi(__k); }
1863+
1864+
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const {
1865+
return __tree_.__upper_bound_multi(__k);
1866+
}
1867+
18501868
# if _LIBCPP_STD_VER >= 14
18511869
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
18521870
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
1853-
return __tree_.upper_bound(__k);
1871+
return __tree_.__upper_bound_multi(__k);
18541872
}
18551873
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
18561874
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const {
1857-
return __tree_.upper_bound(__k);
1875+
return __tree_.__upper_bound_multi(__k);
18581876
}
18591877
# endif
18601878

libcxx/include/set

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -849,30 +849,40 @@ public:
849849
}
850850
# endif // _LIBCPP_STD_VER >= 20
851851

852-
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.lower_bound(__k); }
853-
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const { return __tree_.lower_bound(__k); }
852+
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.__lower_bound_unique(__k); }
853+
854+
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const {
855+
return __tree_.__lower_bound_unique(__k);
856+
}
857+
858+
// The transparent versions of the lookup functions use the _multi version, since a non-element key is allowed to
859+
// match multiple elements.
854860
# if _LIBCPP_STD_VER >= 14
855861
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
856862
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
857-
return __tree_.lower_bound(__k);
863+
return __tree_.__lower_bound_multi(__k);
858864
}
859865

860866
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
861867
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const {
862-
return __tree_.lower_bound(__k);
868+
return __tree_.__lower_bound_multi(__k);
863869
}
864870
# endif
865871

866-
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.upper_bound(__k); }
867-
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const { return __tree_.upper_bound(__k); }
872+
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.__upper_bound_unique(__k); }
873+
874+
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const {
875+
return __tree_.__upper_bound_unique(__k);
876+
}
877+
868878
# if _LIBCPP_STD_VER >= 14
869879
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
870880
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
871-
return __tree_.upper_bound(__k);
881+
return __tree_.__upper_bound_multi(__k);
872882
}
873883
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
874884
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const {
875-
return __tree_.upper_bound(__k);
885+
return __tree_.__upper_bound_multi(__k);
876886
}
877887
# endif
878888

@@ -1301,30 +1311,38 @@ public:
13011311
}
13021312
# endif // _LIBCPP_STD_VER >= 20
13031313

1304-
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.lower_bound(__k); }
1305-
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const { return __tree_.lower_bound(__k); }
1314+
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.__lower_bound_multi(__k); }
1315+
1316+
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const {
1317+
return __tree_.__lower_bound_multi(__k);
1318+
}
1319+
13061320
# if _LIBCPP_STD_VER >= 14
13071321
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
13081322
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) {
1309-
return __tree_.lower_bound(__k);
1323+
return __tree_.__lower_bound_multi(__k);
13101324
}
13111325

13121326
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
13131327
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const {
1314-
return __tree_.lower_bound(__k);
1328+
return __tree_.__lower_bound_multi(__k);
13151329
}
13161330
# endif
13171331

1318-
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.upper_bound(__k); }
1319-
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const { return __tree_.upper_bound(__k); }
1332+
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.__upper_bound_multi(__k); }
1333+
1334+
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const {
1335+
return __tree_.__upper_bound_multi(__k);
1336+
}
1337+
13201338
# if _LIBCPP_STD_VER >= 14
13211339
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
13221340
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) {
1323-
return __tree_.upper_bound(__k);
1341+
return __tree_.__upper_bound_multi(__k);
13241342
}
13251343
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0>
13261344
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const {
1327-
return __tree_.upper_bound(__k);
1345+
return __tree_.__upper_bound_multi(__k);
13281346
}
13291347
# endif
13301348

0 commit comments

Comments
 (0)