1 #ifndef MEDUSA_BITS_OPERATORS_COMPUTESHAPES_HPP_
2 #define MEDUSA_BITS_OPERATORS_COMPUTESHAPES_HPP_
15 #include <type_traits>
20 template <
class vec_t>
21 template <sh::shape_flags mask,
typename approx_t>
22 RaggedShapeStorage<vec_t, typename sh::operator_tuple<mask, vec_t::dim>::type>
25 "Domain and approximation engine dimensions do not match");
26 RaggedShapeStorage<vec_t, typename sh::operator_tuple<mask, vec_t::dim>::type> storage;
27 storage.resize(supportSizes());
35 template <
class vec_t>
36 template <
typename OperatorTuple,
typename approx_t>
37 RaggedShapeStorage<vec_t, OperatorTuple>
40 "Domain and approximation engine dimensions do not match");
41 RaggedShapeStorage<vec_t, OperatorTuple> storage;
42 OperatorTuple operators{};
43 storage.resize(supportSizes());
50 template <
class vec_t>
51 template <
typename OperatorTuple,
typename approx_t>
52 RaggedShapeStorage<vec_t, OperatorTuple>
56 "Domain and approximation engine dimensions do not match");
57 RaggedShapeStorage<vec_t, OperatorTuple> storage;
58 storage.resize(supportSizes());
64 namespace shapes_internal {
67 template <
typename approx_t,
typename shape_storage_t,
typename OperatorTuple, std::
size_t N>
68 struct ShapeComputer {
69 static void compute(
const OperatorTuple& operators,
const approx_t& approx,
int node,
70 shape_storage_t* storage) {
72 ShapeComputer<approx_t, shape_storage_t, OperatorTuple, N-1>::compute(
73 operators, approx, node, storage);
77 typedef typename std::tuple_element<N-1, OperatorTuple>::type op_family_t;
79 auto op_family = std::get<N-1>(operators);
82 for (
const auto op : op_family.operators()) {
86 storage->template setShape<op_family_t>(i, node, approx.getShape(op));
92 template <
typename approx_t,
typename shape_storage_t,
typename OperatorTuple>
93 struct ShapeComputer<approx_t, shape_storage_t, OperatorTuple, 0> {
94 static void compute(
const OperatorTuple&,
const approx_t&,
int, shape_storage_t*) {}
100 template <
typename approx_t,
typename shape_storage_t,
typename ...Operators>
101 void computeShapes(
const DomainDiscretization<typename approx_t::vector_t>& domain,
102 approx_t approx,
const indexes_t& indexes,
103 const std::tuple<Operators...>& operators, shape_storage_t* storage) {
104 int N = domain.size();
106 "domain.support.size = %d and domain.size = %d, but should be the same. "
107 "Did you forget to find support before computing shapes?",
108 domain.supports().size(), domain.size());
109 for (
const auto& c : indexes) {
111 "Index %d is not a valid index of a point in the domain, must be in range "
112 "[%d, %d).", c, 0, N);
114 "Node %d has empty support! Did you forget to find support before "
115 "computing shapes?", c);
118 "Storage must of appropriate size before calling computeShapes(), got size %d, "
119 "expected %d.", storage->size(), N);
123 int isize =
static_cast<int>(indexes.size());
125 #if !defined(_OPENMP)
126 approx_t& local_approx = approx;
128 std::vector<approx_t> approx_copies(omp_get_max_threads(), approx);
129 #pragma omp parallel for private(cc) schedule(static)
131 for (cc = 0; cc < isize; ++cc) {
132 int node = indexes[cc];
135 approx_t& local_approx = approx_copies[omp_get_thread_num()];
137 assert_msg(storage->supportSize(node) == domain.supportSize(node),
138 "Storage must of appropriate size before calling computeShapes(). "
139 "Got support size %d at node %d, expected %d.",
140 storage->supportSize(node), node, domain.supportSize(node));
142 storage->setSupport(node, domain.support(node));
144 Range<typename approx_t::vector_t> supp_domain = domain.supportNodes(node);
145 local_approx.compute(supp_domain[0], supp_domain);
147 shapes_internal::ShapeComputer<
148 approx_t, shape_storage_t, std::tuple<Operators...>,
sizeof...(Operators)
149 >::compute(operators, local_approx, node, storage);
155 #endif // MEDUSA_BITS_OPERATORS_COMPUTESHAPES_HPP_