#ifndef PFOR_PFOR_PARALLELIZABLE_H #define PFOR_PFOR_PARALLELIZABLE_H #include "expression/access.h" #include "expression/algorithm.h" #include "expression/info.h" #include "expression/operandtag.h" #include "expression/tagger.h" #include "index/properties.h" #include "index/traits.h" #include "lineardiophantineequation.h" #include "mp/pack.h" namespace pfor { namespace impl { template struct IsLinearOrInjective: std::integral_constant> or index::isInjective> > {}; /** * @brief true if all indices are linear or injective */ template constexpr bool allLinearOrInjective = packAll, IsLinearOrInjective>; } /** */ template struct TestVariable; /* * if all indices are not either linear or at least injective, default to sequential */ template struct TestVariable, IncludeList, Pack, std::enable_if_t< not index::allLinear and not impl::allLinearOrInjective > > { static constexpr bool value = false; }; /* * if not only linear expressions for indices, defaults to Fw = emptyset or |F| = 1 * when non linear still are injective */ template struct TestVariable, IncludeList, Pack, std::enable_if_t< not index::allLinear and impl::allLinearOrInjective > > { using First = expr::OperandTag; using Indices = PackUniq>::indices>; static constexpr std::size_t cwrite = expr::countWrite; static constexpr std::size_t cindices = PackSize::value; static constexpr bool value = (cwrite == 0 || (cwrite == 1 && cindices == 1)); }; /* * if only linear expressions for indices, use linear diophantine equations */ template struct TestVariable, std::enable_if_t> > { using wtags = expr::FilterOperandTags, expr::Access::write>; using wit = expr::IndicesFromOperandTags; using allit = expr::IndicesFromOperandTags; static constexpr bool value = noLinearDiophantineSolutionForGrid; }; template constexpr bool testVariable = TestVariable::value; /** * ConstantWriteAccess */ template struct HasConstantWriteAccess; template struct HasConstantWriteAccess, Ts...>> { static constexpr bool value = index::isConstant || HasConstantWriteAccess>::value; }; template struct HasConstantWriteAccess, Ts...>> { static constexpr bool value = HasConstantWriteAccess>::value; }; template<> struct HasConstantWriteAccess> { static constexpr bool value = false; }; template constexpr bool hasConstantWriteAccess = HasConstantWriteAccess

::value; /** * RWControl */ template struct RWControl; template struct RWControl, Ts...>> { using First = expr::OperandTag; using IncludeList = expr::IncludeTags>; using ExcludeList = expr::ExcludeTags>; static constexpr bool noConstantWrite = !hasConstantWriteAccess; static constexpr bool noIndexConflict = testVariable>; static constexpr bool value = noConstantWrite && noIndexConflict && RWControl::value; }; template<> struct RWControl> { static constexpr bool value = true; }; template constexpr bool rwControl = RWControl::value; /** * Parallelizable */ template struct Parallelizable; template struct Parallelizable> { using tags = expr::ExpressionTagger>; using filtered_tags = expr::ExcludeTags; static constexpr bool value = rwControl; }; /** * @param[in] E an expression * * @return true if the expression can be run in parallel */ template constexpr bool parallelizable = Parallelizable::value; } #endif