aGrUM  0.16.0
partialInstantiationPattern4BaseName.h
Go to the documentation of this file.
1 
32 
33 // check if we allowed these patterns to be used
34 #ifndef GUM_PARTIAL_INSTANTIATION_PATTERN_ALLOWED
35 
36 // #warning To use partialIntantiationPattern, you must define
37 // GUM_PARTIAL_INSTANTIATION_PATTERN_ALLOWED
38 
39 #else
40 namespace gum {
41 
42  // a specialized function instantiating some variables of a table and returning
43  // the result
44 
45 # ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_NAME
46 # define GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE GUM_SCALAR
47  template < typename GUM_SCALAR >
48  MultiDimImplementation< GUM_SCALAR >* GUM_MULTI_DIM_PARTIAL_INSTANTIATION_NAME(
49  const MultiDimImplementation< GUM_SCALAR >* table,
50  const HashTable< const DiscreteVariable*, Idx >& inst_vars)
51 # endif
52 
53  // clang-format off
54 
55 #ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER_NAME
56 #define GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE GUM_SCALAR *
57 #define GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER
58  template <typename GUM_SCALAR>
59  MultiDimImplementation<GUM_SCALAR*>*
61  const MultiDimImplementation<GUM_SCALAR*>* table,
62  const HashTable<const DiscreteVariable*, Idx>& inst_vars )
63 #endif
64 
65  // clang-format on
66 
67  {
68 
69  // get the variables of the uninstantiated table
70  const Sequence< const DiscreteVariable* >& table_vars =
71  table->variablesSequence();
72 
73  // Compute the offset of the variables. In addition, get the offset in
74  // table induced by the instantiation inst_var
75  Idx table_alone_offset = 0;
76  Idx offset = 1;
77  HashTable< const DiscreteVariable*, Idx > var1offset(table_vars.size());
78 
79  for (const auto var : table_vars) {
80  if (inst_vars.exists(var)) { table_alone_offset += inst_vars[var] * offset; }
81 
82  var1offset.insert(var, offset);
83  offset *= var->domainSize();
84  }
85 
86  // Compute the sequence of variables in the result table. Compute as
87  // well the offsets and the domain size of the variables that belong to
88  // result. Finally, compute has_before_incr: this is a Boolean indicating
89  // whether the instantiated variables are the last variables in the
90  // variables sequence of table (true) or not (false). If this Boolean is
91  // true, then we can fill result by parsing both table and result using
92  // only 1-increments.
93  Sequence< const DiscreteVariable* > result_varSeq;
94  std::vector< Idx > table_and_result_offset;
95  std::vector< Idx > table_and_result_domain;
96  Idx result_domain_size = 1;
97  bool has_before_incr = true;
98  bool found_inst_var = false;
99 
100  for (const auto var : table_vars) {
101  if (!inst_vars.exists(var)) {
102  table_and_result_domain.push_back(var->domainSize());
103  table_and_result_offset.push_back(var1offset[var]);
104  result_domain_size *= var->domainSize();
105  result_varSeq << var;
106 
107  if (found_inst_var) has_before_incr = false;
108  } else {
109  found_inst_var = true;
110  }
111  }
112 
113  // table_and_result_value is a vector indictating, for each
114  // uninstantiated variable, how many increments we can still perform on
115  // that variable before we must perform a "major" increment: for
116  // instance, let A and B be two variables of size 10. Then, if
117  // table_and_result_value[A] = 3 and table_and_result_value[B] = 2, this
118  // means that the offset they represent is 78 (10^2 - 32). If we still
119  // increment B twice, then the offset should be 80, which means that we
120  // shall increment A once and decrease B by 10. The value by which
121  // variables shall be decreased is indicated in table_and_result_down
122  std::vector< Idx > table_and_result_value = table_and_result_domain;
123  std::vector< Idx > table_and_result_down = table_and_result_offset;
124 
125  for (unsigned int i = 0; i < table_and_result_down.size(); ++i)
126  table_and_result_down[i] *= (table_and_result_domain[i] - 1);
127 
128  // create a table "result" containing only the variables that are not
129  // instantiated: the variables are stored in the order in which they
130  // appear in "table". Hence, ++ operations on an instantiation on table
131  // will more or less correspond to a ++ operation on an instantiation on
132  // result
133  MultiDimArray< GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE >* result =
134  new MultiDimArray< GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE >;
135  result->beginMultipleChanges();
136 
137  for (const auto var : result_varSeq)
138  *result << *var;
139 
140  result->endMultipleChanges();
141 
142 # ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER
143  // fill the matrix with any element
144  {
145  const Instantiation table_inst(table);
146  const GUM_SCALAR& any_element = *(table->get(table_inst));
147 
148  for (Idx i = 0; i < result_domain_size; ++i) {
149  result->unsafeSet(i, new GUM_SCALAR(any_element));
150  }
151  }
152 # endif /* GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER */
153 
154  // compute the result: it is now sufficient to loop over the variables
155  // that were not instantiated. ptable and presult are pointers on the
156  // arrays that are directly used for this loop
157  GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE* presult =
158  const_cast< GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE* >(
159  &(result->unsafeGet(0)));
160  Instantiation table_inst(table);
161  table_inst += table_alone_offset;
162 
163  // but before doing so, check whether the instantiated variables are the
164  // last ones or not. If so, we can optimize the parsing of ptable and
165  // presult as both tables need be parsed using only 1-increments
166  if (has_before_incr) {
167  for (Idx i = 0; i < result_domain_size; ++i) {
168 # ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER
169  **presult = *(table->get(table_inst));
170 # else
171  *presult = table->get(table_inst);
172 # endif
173 
174  // update the offset of result and table
175  ++table_inst;
176  ++presult;
177  }
178  } else {
179  // here, some uninstantiated variables exist after the instantiated
180  // ones in the variables sequence of table. So, we must perform a more
181  // complicated parsing of ptable
182  for (Idx j = 0; j < result_domain_size; ++j) {
183 # ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER
184  **presult = *(table->get(table_inst));
185 # else
186  *presult = table->get(table_inst);
187 # endif
188 
189  // update the offset of table for the outer loop
190  for (unsigned int k = 0; k < table_and_result_value.size(); ++k) {
191  --table_and_result_value[k];
192 
193  if (table_and_result_value[k]) {
194  table_inst += table_and_result_offset[k];
195  break;
196  }
197 
198  table_and_result_value[k] = table_and_result_domain[k];
199  table_inst -= table_and_result_down[k];
200  }
201 
202  // update the offset of result for the outer loop
203  ++presult;
204  }
205  }
206 
207  return result;
208  }
209 
210 # undef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_TYPE
211 
212 # ifdef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER
213 # undef GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER
214 # endif
215 
216 } /* End of namespace gum */
217 
218 #endif /* GUM_PARTIAL_INSTANTIATION_PATTERN_ALLOWED */
#define GUM_MULTI_DIM_PARTIAL_INSTANTIATION_NAME
a specialized partial instantiation function for multiDimArrays
#define GUM_MULTI_DIM_PARTIAL_INSTANTIATION_POINTER_NAME
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.