#pragma once #include #include #include #include #include #include #include #include #include #include #include namespace hysj::inline _HYSJ_VERSION_NAMESPACE::graphs{ #define HYSJ_GRAPHS_SEMIADJACENCY_MODES \ HYSJ_PRODUCT((HYSJ_SELECT((0)(1),HYSJ_GRAPHS_ELEMENT_TAGS)) \ (HYSJ_GRAPHS_DIRECTIONAL_TAGS) \ (HYSJ_GRAPHS_DIRECTIONAL_TAGS)) namespace hooks::semiadjacent_hook{ inline constexpr struct semiadjacent_fn{ friend constexpr auto ordered_tag_invoke(semiadjacent_fn,priority_tag<1>,auto t,auto d0,auto d1,const auto &g,auto v) arrow((semiadjacent(t,d0,d1,g,v))) //FIXME: no arrow because partial ordering bug in gcc - jeh template friend constexpr auto ordered_tag_invoke(semiadjacent_fn, priority_tag<0>, constant_t,auto d0,auto d1,const auto &g,auto v) noexcept(noexcept( views::btransform( graphs::vincident(d0,g,v), std::bind_front(graphs::port,d1,std::cref(g))))) -> decltype(auto) requires( T == vertex_tag && requires { views::btransform( graphs::vincident(d0,g,v), std::bind_front(graphs::port,d1,std::cref(g))); }){ return views::btransform( graphs::vincident(d0,g,v), std::bind_front(graphs::port,d1,std::cref(g))); } //FIXME: // make filter conditional based on directions // - jeh //FIXME: // gcc-segfault with constraints // - jeh friend constexpr auto ordered_tag_invoke(semiadjacent_fn, priority_tag<0>, edge_tag_type,auto d0,auto d1,const auto &g,auto e) noexcept(noexcept( views::bjoin( views::btransform( graphs::eincident(d0,std::cref(g),e), std::bind_front(graphs::vincident,d1,std::cref(g)))))) -> decltype(auto) { return views::bjoin( views::btransform( graphs::eincident(d0,std::cref(g),e), std::bind_front(graphs::vincident,d1,std::cref(g)))); } friend constexpr auto tag_invoke(semiadjacent_fn fn,auto t,auto d0,auto d1,const auto &g,auto v) arrow((ordered_tag_invoke(fn,priority_tag<1>{},t,d0,d1,g,v))) template constexpr auto operator()(constant_t t,auto d0,auto d1,const auto &g,auto i)const arrow((tag_invoke(*this,t,d0,d1,unwrap(g),i))) } semiadjacent{}; } //hooks using hooks::semiadjacent_hook::semiadjacent; #define HYSJ_LAMBDA(X,x,D0,d0,D1,d1) \ inline constexpr auto x##d0##d1##semiadjacent = \ std::bind_front(graphs::semiadjacent,X##_tag,D0##_tag,D1##_tag); HYSJ_MAP_LAMBDA(HYSJ_GRAPHS_SEMIADJACENCY_MODES) #undef HYSJ_LAMBDA inline constexpr struct { constexpr auto operator()(auto t,auto d0,auto d1,const auto &g,auto i)const arrow((views::bfilter(semiadjacent(t,d0,d1,g,i),none_of(i)))); } exclusive_semiadjacent{}; #define HYSJ_LAMBDA(X,x,D0,d0,D1,d1) \ inline constexpr auto e##x##d0##d1##semiadjacent = \ std::bind_front(graphs::exclusive_semiadjacent,X##_tag,D0##_tag,D1##_tag); HYSJ_MAP_LAMBDA(HYSJ_GRAPHS_SEMIADJACENCY_MODES) #undef HYSJ_LAMBDA #define HYSJ_GRAPHS_ADJACENCY_MODES HYSJ_GRAPHS_INCIDENCE_MODES namespace hooks::adjacent_hook{ inline constexpr struct adjacent_fn{ friend constexpr auto ordered_tag_invoke(adjacent_fn,priority_tag<1>,auto t,auto d,const auto &g,auto v) arrow((adjacent(t,d,g,v))) consteval static auto semiadjacency(vertex_tag_type,auto){ return graphs::semiadjacent; } consteval static auto semiadjacency(edge_tag_type,auto d){ if constexpr(concepts::undirected_constant) return graphs::exclusive_semiadjacent; else return graphs::semiadjacent; } consteval static auto semiadjacent_second_direction(vertex_tag_type,auto){ return out_tag; } static auto semiadjacent_second_direction(edge_tag_type,auto d){ return d; } template friend constexpr auto ordered_tag_invoke(adjacent_fn, priority_tag<0>, constant_t t,auto d,const auto &g,auto v) arrow((semiadjacency(t,d) (t,d,semiadjacent_second_direction(t,d),std::cref(g),v))) friend constexpr auto tag_invoke(adjacent_fn fn,auto t,auto d,const auto &g,auto v) arrow((ordered_tag_invoke(fn,priority_tag<1>{},t,d,g,v))) template constexpr auto operator()(constant_t t,auto d,const auto &g,auto i)const arrow((tag_invoke(*this,t,d,unwrap(g),i)) (-> concepts::element_id_range)) } adjacent{}; } //hooks using hooks::adjacent_hook::adjacent; #define HYSJ_LAMBDA(X,x,...) \ inline constexpr auto x##adjacent = \ std::bind_front(graphs::adjacent,X##_tag); HYSJ_MAP_LAMBDA(HYSJ_GRAPHS_ELEMENT_TAGS) #undef HYSJ_LAMBDA #define HYSJ_LAMBDA(X,x,D,d) \ inline constexpr auto x##d##adjacent = \ std::bind_front(graphs::adjacent,X##_tag,D##_tag); HYSJ_MAP_LAMBDA(HYSJ_GRAPHS_ADJACENCY_MODES) #undef HYSJ_LAMBDA namespace traits{ template using adjacent_t = decltype(graphs::adjacent(constant_c, std::declval(), std::declval(), std::declval())); #define HYSJ_LAMBDA(X,x,D,d) \ template> \ using x##d##adjacent_t = adjacent_t; HYSJ_MAP_LAMBDA(HYSJ_GRAPHS_ADJACENCY_MODES) #undef HYSJ_LAMBDA } namespace concepts{ template> concept adjacency_graph = (requires(constant_t t,D d,const G &g,I i){ graphs::adjacent(t,d,g,i); }); #define HYSJ_LAMBDA(X,x,D,d) \ template \ concept x##d##adjacency_graph = adjacency_graph; HYSJ_MAP_LAMBDA(HYSJ_GRAPHS_ADJACENCY_MODES) #undef HYSJ_LAMBDA #define HYSJ_LAMBDA(D,X,x,...) && adjacency_graph template concept directional_adjacency_graph = true HYSJ_MAP(HYSJ_LAMBDA,D,HYSJ_GRAPHS_ELEMENT_TAGS) ; #undef HYSJ_LAMBDA } //concepts } //hysj::graphs #include