Skip to content

Commit

Permalink
Fix type punning warning for bfs in gcc release
Browse files Browse the repository at this point in the history
Use union for value & shadow_value instead of reinterpret_cast<value_type*>(value_)

Also removed meaningless double casts in pagerank tests
  • Loading branch information
pratzl committed Nov 16, 2023
1 parent 20f4b82 commit 75b14a9
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 22 deletions.
86 changes: 65 additions & 21 deletions include/graph/views/breadth_first_search.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,17 @@ class vertices_breadth_first_search_view : public bfs_base<G, Queue, Alloc> {
using shadow_value_type =
vertex_descriptor<vertex_id_t<graph_type>, shadow_vertex_type*, _detail::ref_to_ptr<vertex_value_type>>;

union internal_value {
value_type value_;
shadow_value_type shadow_;

internal_value(vertex_id_type start_at) : shadow_{start_at, nullptr} {}
internal_value(const internal_value& rhs) : shadow_(rhs.shadow_) {}
internal_value() : shadow_{} {}
~internal_value() {}
internal_value& operator=(const internal_value& rhs) { value_.shadow = rhs.value_.shadow; }
};

public:
iterator(const bfs_range_type& range) : the_range_(&const_cast<bfs_range_type&>(range)) {}
iterator() = default;
Expand All @@ -286,16 +297,16 @@ class vertices_breadth_first_search_view : public bfs_base<G, Queue, Alloc> {
auto&& uvi = the_range_->uv_;
vertex_id_type v_id = the_range_->real_target_id(*uvi, u_id);
auto& v = *find_vertex(g, v_id);
value_ = {v_id, &v, invoke(*the_range_->value_fn_, v)};
return reinterpret_cast<reference>(value_);
value_.shadow_ = {v_id, &v, invoke(*the_range_->value_fn_, v)};
return value_.value_;
}

constexpr bool operator==(const end_sentinel&) const noexcept { return the_range_->Q_.empty(); }
constexpr bool operator!=(const end_sentinel& rhs) const noexcept { return !operator==(rhs); }

private:
mutable shadow_value_type value_ = {};
bfs_range_type* the_range_ = nullptr;
mutable internal_value value_;
bfs_range_type* the_range_ = nullptr;
friend end_sentinel;
};

Expand Down Expand Up @@ -367,6 +378,17 @@ class vertices_breadth_first_search_view<G, void, Queue, Alloc> : public bfs_bas
using shadow_vertex_type = remove_reference_t<vertex_reference>;
using shadow_value_type = vertex_descriptor<vertex_id_t<graph_type>, shadow_vertex_type*, void>;

union internal_value {
value_type value_;
shadow_value_type shadow_;

internal_value(vertex_id_type start_at) : shadow_{start_at, nullptr} {}
internal_value(const internal_value& rhs) : shadow_(rhs.shadow_) {}
internal_value() : shadow_{} {}
~internal_value() {}
internal_value& operator=(const internal_value& rhs) { value_.shadow = rhs.value_.shadow; }
};

public:
iterator(const bfs_range_type& range) : the_range_(&const_cast<bfs_range_type&>(range)) {}
iterator() = default;
Expand All @@ -393,16 +415,16 @@ class vertices_breadth_first_search_view<G, void, Queue, Alloc> : public bfs_bas
auto&& uvi = the_range_->uv_;
vertex_id_type v_id = the_range_->real_target_id(*uvi, u_id);
auto& v = *find_vertex(g, v_id);
value_ = {v_id, &v};
return reinterpret_cast<reference>(value_);
value_.shadow_ = {v_id, &v};
return value_.value_;
}

bool operator==(const end_sentinel&) const noexcept { return the_range_->Q_.empty(); }
//bool operator!=(const end_sentinel& rhs) const noexcept { return !operator==(rhs); }

private:
mutable shadow_value_type value_ = {};
bfs_range_type* the_range_ = nullptr;
mutable internal_value value_;
bfs_range_type* the_range_ = nullptr;
friend end_sentinel;
};

Expand Down Expand Up @@ -482,6 +504,17 @@ class edges_breadth_first_search_view : public bfs_base<G, Queue, Alloc> {
using shadow_value_type =
edge_descriptor<vertex_id_type, Sourced, shadow_edge_type*, _detail::ref_to_ptr<edge_value_type>>;

union internal_value {
value_type value_;
shadow_value_type shadow_;

internal_value(vertex_id_type start_at) : shadow_{start_at, nullptr} {}
internal_value(const internal_value& rhs) : shadow_(rhs.shadow_) {}
internal_value() : shadow_{} {}
~internal_value() {}
internal_value& operator=(const internal_value& rhs) { value_.shadow = rhs.value_.shadow; }
};

public:
iterator(const bfs_range_type& range) : the_range_(&const_cast<bfs_range_type&>(range)) {}
iterator() = default;
Expand All @@ -506,20 +539,20 @@ class edges_breadth_first_search_view : public bfs_base<G, Queue, Alloc> {
auto&& u_id = the_range_->Q_.front();
auto&& uvi = the_range_->uv_;
if constexpr (Sourced) {
value_.source_id = u_id;
value_.shadow_.source_id = u_id;
}
value_.target_id = the_range_->real_target_id(*uvi, u_id);
value_.edge = &*uvi;
value_.value = invoke(*the_range_->value_fn_, *uvi);
return reinterpret_cast<reference>(value_);
value_.shadow_.target_id = the_range_->real_target_id(*uvi, u_id);
value_.shadow_.edge = &*uvi;
value_.shadow_.value = invoke(*the_range_->value_fn_, *uvi);
return value_.value_;
}

bool operator==(const end_sentinel&) const noexcept { return the_range_->Q_.empty(); }
bool operator!=(const end_sentinel& rhs) const noexcept { return !operator==(rhs); }

private:
mutable shadow_value_type value_ = {};
bfs_range_type* the_range_ = nullptr;
mutable internal_value value_;
bfs_range_type* the_range_ = nullptr;
friend end_sentinel;
};

Expand Down Expand Up @@ -584,6 +617,17 @@ class edges_breadth_first_search_view<G, void, Sourced, Queue, Alloc> : public b
using shadow_edge_type = remove_reference_t<edge_reference_type>;
using shadow_value_type = edge_descriptor<vertex_id_type, Sourced, shadow_edge_type*, void>;

union internal_value {
value_type value_;
shadow_value_type shadow_;

internal_value(vertex_id_type start_at) : shadow_{start_at, nullptr} {}
internal_value(const internal_value& rhs) : shadow_(rhs.shadow_) {}
internal_value() : shadow_{} {}
~internal_value() {}
internal_value& operator=(const internal_value& rhs) { value_.shadow = rhs.value_.shadow; }
};

public:
iterator(const bfs_range_type& range) : the_range_(&const_cast<bfs_range_type&>(range)) {}
iterator() = default;
Expand All @@ -608,19 +652,19 @@ class edges_breadth_first_search_view<G, void, Sourced, Queue, Alloc> : public b
auto&& u_id = the_range_->Q_.front();
auto&& uvi = the_range_->uv_;
if constexpr (Sourced) {
value_.source_id = u_id;
value_.shadow_.source_id = u_id;
}
value_.target_id = the_range_->real_target_id(*uvi, u_id);
value_.edge = &*uvi;
return reinterpret_cast<reference>(value_);
value_.shadow_.target_id = the_range_->real_target_id(*uvi, u_id);
value_.shadow_.edge = &*uvi;
return value_.value_;
}

bool operator==(const end_sentinel&) const noexcept { return the_range_->Q_.empty(); }
bool operator!=(const end_sentinel& rhs) const noexcept { return !operator==(rhs); }

private:
mutable shadow_value_type value_ = {};
bfs_range_type* the_range_ = nullptr;
mutable internal_value value_;
bfs_range_type* the_range_ = nullptr;
friend end_sentinel;
};

Expand Down
2 changes: 1 addition & 1 deletion tests/pagerank_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ TEST_CASE("PageRank", "[pagerank]") {
auto&& g = load_ordered_graph<G>(TEST_DATA_ROOT_DIR "germany_routes.csv", name_order_policy::source_order_found);

std::vector<double> page_rank(size(vertices(g)));
std::graph::pagerank(g, page_rank, double(0.85), double(1e-4), 10);
std::graph::pagerank(g, page_rank, 0.85, 1e-4, 10);

std::vector<double> answer = {0.051086017487729, 0.065561667371485, 0.106818581147795, 0.141889899564636,
0.065561667371485, 0.078952299317762, 0.065561667371485, 0.078952299317762,
Expand Down

0 comments on commit 75b14a9

Please sign in to comment.