graph.hpp array cstddef serif/utils/dependencies/detail/type_lists.hpp src/include/serif/utils/dependencies/computation_graph.hpp serif::utils::dependencies::detail::Graph serif serif::utils serif::utils::dependencies serif::utils::dependencies::detail #pragmaonce #include<array> #include<cstddef> #include"serif/utils/dependencies/detail/type_lists.hpp" namespaceserif::utils::dependencies::detail{ template<typename...Computations> structGraph{ staticconstexprstd::size_tsize=sizeof...(Computations); usingMask=std::array<bool,size>; usingMatrix=std::array<Mask,size>; usingOrder=std::array<std::size_t,size>; template<typenameComputationT> [[nodiscard]]staticconstevalMaskprerequisites(){ return{contains_key_v<typename Computations::Key, typename ComputationT::Inputs>...}; } staticconstexprMatrixedges{prerequisites<Computations>()...}; [[nodiscard]]staticconstevalOrdermake_order(){ Orderresult{}; result.fill(size); Maskvisited{}; std::array<std::size_t,size>remaining{}; for(std::size_tcandidate=0;candidate<size;++candidate){ std::size_tcount=0; for(constboolprerequisite:edges[candidate]){ count+=prerequisite; } remaining[candidate]=count; } for(std::size_tposition=0;position<size;++position){ std::size_tselected=size; for(std::size_tcandidate=0;candidate<size;++candidate){ if(!visited[candidate]&&remaining[candidate]==0){ selected=candidate; break; } } if(selected==size){ break; } result[position]=selected; visited[selected]=true; for(std::size_tuser=0;user<size;++user){ if(edges[user][selected]){ --remaining[user]; } } } returnresult; } staticconstexprOrderorder=make_order(); [[nodiscard]]staticconstevalboolacyclic(){ for(conststd::size_tindex:order){ if(index==size){ returnfalse; } } returntrue; } template<typename...Keys> [[nodiscard]]staticconstevalMaskrequired(KeyList<Keys...>){ Maskresult{(contains_key_v<typenameComputations::Key,KeyList<Keys...>>)...}; for(std::size_tposition=size;position>0;--position){ conststd::size_tuser=order[position-1]; if(user==size||!result[user]){ continue; } for(std::size_tinput=0;input<size;++input){ result[input]=result[input]||edges[user][input]; } } returnresult; } }; }