50#ifndef GUM_OPERATOR_PATTERN_ALLOWED
61# ifdef GUM_MULTI_DIM_OPERATOR_NAME
62# define GUM_MULTI_DIM_OPERATOR_TYPE T
64 template <
typename T >
71#ifdef GUM_MULTI_DIM_OPERATOR_POINTER_NAME
72#define GUM_MULTI_DIM_OPERATOR_TYPE T *
78#ifdef GUM_MULTI_DIM_OPERATOR_NAME_F
79#define GUM_MULTI_DIM_OPERATOR_TYPE T
84 const T ( *f )(
const T&,
const T& ) )
87#ifdef GUM_MULTI_DIM_OPERATOR_POINTER_NAME_F
88#define GUM_MULTI_DIM_OPERATOR_TYPE T *
93 const T* ( *f )(
const T*,
const T* ) )
96#ifdef GUM_MULTI_DIM_OPERATOR_IMPL2ARRAY_NAME
97#define GUM_MULTI_DIM_OPERATOR_TYPE T
104#ifdef GUM_MULTI_DIM_OPERATOR_POINTER_IMPL2ARRAY_NAME
105#define GUM_MULTI_DIM_OPERATOR_TYPE T *
106 template <
typename T>
108 GUM_MULTI_DIM_OPERATOR_POINTER_IMPL2ARRAY_NAME(
117# ifdef GUM_MULTI_DIM_OPERATOR_IMPL2ARRAY_NAME
122# ifdef GUM_MULTI_DIM_OPERATOR_POINTER_IMPL2ARRAY_NAME
134 Idx current_offset = 1;
136 for (
const auto var: t1_vars) {
137 t1_offsets.insert(var, current_offset);
138 current_offset *= var->domainSize();
143 Idx current_offset = 1;
145 for (
const auto var: t2_vars) {
146 t2_offsets.insert(var, current_offset);
147 current_offset *= var->domainSize();
161 std::vector< Idx > t1_alone_offset;
162 std::vector< Idx > t1_alone_domain;
163 Idx t1_alone_domain_size = 1;
165 std::vector< Idx > t2_alone_offset;
166 std::vector< Idx > t2_alone_domain;
167 Idx t2_alone_domain_size = 1;
169 std::vector< Idx > t1_and_t2_1_offset;
170 std::vector< Idx > t1_and_t2_2_offset;
171 std::vector< Idx > t1_and_t2_domain;
172 std::vector< const DiscreteVariable* > t1_and_t2_vars;
173 Idx t1_and_t2_domain_size = 1;
176 for (
const auto var: t1_vars)
177 if (t2_vars.exists(var)) {
178 t1_and_t2_domain.push_back(var->domainSize());
179 t1_and_t2_1_offset.push_back(t1_offsets[var]);
180 t1_and_t2_2_offset.push_back(t2_offsets[var]);
181 t1_and_t2_vars.push_back(var);
182 t1_and_t2_domain_size *= var->domainSize();
184 t1_alone_domain.push_back(var->domainSize());
185 t1_alone_offset.push_back(t1_offsets[var]);
186 t1_alone_domain_size *= var->domainSize();
189 for (
const auto var: t2_vars)
190 if (!t1_vars.exists(var)) {
191 t2_alone_domain.push_back(var->domainSize());
192 t2_alone_offset.push_back(t2_offsets[var]);
193 t2_alone_domain_size *= var->domainSize();
200 bool t1_and_t2_begin_vars =
false;
202 if (t1_and_t2_vars.size()) {
203 unsigned int nb_t1_t2_vars = 0;
205 for (
auto iter = t1_vars.begin(); nb_t1_t2_vars != t1_and_t2_vars.size();
206 ++iter, ++nb_t1_t2_vars)
207 if (*iter != t1_and_t2_vars[nb_t1_t2_vars])
break;
209 if (nb_t1_t2_vars == t1_and_t2_vars.size()) {
212 for (
auto iter = t2_vars.begin(); nb_t1_t2_vars != t1_and_t2_vars.size();
213 ++iter, ++nb_t1_t2_vars)
214 if (*iter != t1_and_t2_vars[nb_t1_t2_vars])
break;
216 if (nb_t1_t2_vars == t1_and_t2_vars.size()) { t1_and_t2_begin_vars =
true; }
231 std::vector< Idx > t1_and_t2_value = t1_and_t2_domain;
232 std::vector< Idx > t1_and_t2_1_down = t1_and_t2_1_offset;
233 std::vector< Idx > t1_and_t2_2_down = t1_and_t2_2_offset;
235 for (
unsigned int i = 0; i < t1_and_t2_domain.size(); ++i) {
236 t1_and_t2_1_down[i] *= (t1_and_t2_domain[i] - 1);
237 t1_and_t2_2_down[i] *= (t1_and_t2_domain[i] - 1);
240 std::vector< Idx > t1_alone_value = t1_alone_domain;
241 std::vector< Idx > t1_alone_down = t1_alone_offset;
243 for (
unsigned int i = 0; i < t1_alone_domain.size(); ++i) {
244 t1_alone_down[i] *= (t1_alone_domain[i] - 1);
247 std::vector< Idx > t2_alone_value = t2_alone_domain;
248 std::vector< Idx > t2_alone_down = t2_alone_offset;
250 for (
unsigned int i = 0; i < t2_alone_domain.size(); ++i) {
251 t2_alone_down[i] *= (t2_alone_domain[i] - 1);
263 for (
const auto var: t1_vars)
264 if (t2_vars.exists(var)) *result << *var;
266 for (
const auto var: t2_vars)
267 if (!t1_vars.exists(var)) *result << *var;
269 for (
const auto var: t1_vars)
270 if (!t2_vars.exists(var)) *result << *var;
272 result->endMultipleChanges();
278 GUM_MULTI_DIM_OPERATOR_TYPE* pt1
279 =
const_cast< GUM_MULTI_DIM_OPERATOR_TYPE*
>(&(t1->unsafeGet(0)));
280 GUM_MULTI_DIM_OPERATOR_TYPE* pt2
281 =
const_cast< GUM_MULTI_DIM_OPERATOR_TYPE*
>(&(t2->unsafeGet(0)));
282 GUM_MULTI_DIM_OPERATOR_TYPE* pres
283 =
const_cast< GUM_MULTI_DIM_OPERATOR_TYPE*
>(&(result->unsafeGet(0)));
284 GUM_MULTI_DIM_OPERATOR_TYPE* pt2_deb = pt2;
285 GUM_MULTI_DIM_OPERATOR_TYPE* pt1_alone_begin;
290 if (t1_and_t2_begin_vars) {
291 for (
Idx i = 0; i < t1_alone_domain_size; ++i) {
293 pt1_alone_begin = pt1;
295 for (
Idx j = 0; j < t2_alone_domain_size; ++j) {
296 pt1 = pt1_alone_begin;
298 for (
Idx z = 0; z < t1_and_t2_domain_size; ++z) {
299 *pres = GUM_MULTI_DIM_OPERATOR(*pt1, *pt2);
311 Idx t1_alone_begin_offset = 0;
313 for (
Idx i = 0; i < t1_alone_domain_size; ++i) {
315 t1_alone_begin_offset = t1_offset;
317 for (
Idx j = 0; j < t2_alone_domain_size; ++j) {
318 t1_offset = t1_alone_begin_offset;
320 for (
Idx z = 0; z < t1_and_t2_domain_size; ++z) {
321 *pres = GUM_MULTI_DIM_OPERATOR(pt1[t1_offset], pt2[t2_offset]);
325 for (
unsigned int k = 0; k < t1_and_t2_value.size(); ++k) {
326 if (--t1_and_t2_value[k]) {
327 t1_offset += t1_and_t2_1_offset[k];
328 t2_offset += t1_and_t2_2_offset[k];
332 t1_and_t2_value[k] = t1_and_t2_domain[k];
333 t1_offset -= t1_and_t2_1_down[k];
334 t2_offset -= t1_and_t2_2_down[k];
339 for (
unsigned int k = 0; k < t2_alone_value.size(); ++k) {
340 if (--t2_alone_value[k]) {
341 t2_offset += t2_alone_offset[k];
345 t2_alone_value[k] = t2_alone_domain[k];
346 t2_offset -= t2_alone_down[k];
351 for (
unsigned int k = 0; k < t1_alone_value.size(); ++k) {
352 if (--t1_alone_value[k]) {
353 t1_offset += t1_alone_offset[k];
357 t1_alone_value[k] = t1_alone_domain[k];
358 t1_offset -= t1_alone_down[k];
366# undef GUM_MULTI_DIM_OPERATOR_TYPE
The class for generic Hash Tables.
Multidimensional matrix stored as an array in memory.
<agrum/base/multidim/multiDimImplementation.h>
void beginMultipleChanges() override
Call this method before doing important changes in this MultiDimContainer.
The generic class for storing (ordered) sequences of objects.
Size Idx
Type for indexes.
gum is the global namespace for all aGrUM entities