28 #ifndef GUM_OPERATOR_PATTERN_ALLOWED 40 # ifdef GUM_MULTI_DIM_OPERATOR_NAME 41 # define GUM_MULTI_DIM_OPERATOR_TYPE T 42 template <
typename T >
43 MultiDimImplementation< T >*
44 GUM_MULTI_DIM_OPERATOR_NAME(
const MultiDimImplementation< T >* t1,
45 const MultiDimImplementation< T >* t2)
50 #ifdef GUM_MULTI_DIM_OPERATOR_POINTER_NAME 51 #define GUM_MULTI_DIM_OPERATOR_TYPE T * 53 MultiDimImplementation<T*>* GUM_MULTI_DIM_OPERATOR_POINTER_NAME(
54 const MultiDimImplementation<T*>* t1,
55 const MultiDimImplementation<T*>* t2 )
58 #ifdef GUM_MULTI_DIM_OPERATOR_NAME_F 59 #define GUM_MULTI_DIM_OPERATOR_TYPE T 61 MultiDimImplementation<T>* GUM_MULTI_DIM_OPERATOR_NAME_F(
62 const MultiDimImplementation<T>* t1,
63 const MultiDimImplementation<T>* t2,
64 const T ( *f )(
const T&,
const T& ) )
67 #ifdef GUM_MULTI_DIM_OPERATOR_POINTER_NAME_F 68 #define GUM_MULTI_DIM_OPERATOR_TYPE T * 70 MultiDimImplementation<T*>* GUM_MULTI_DIM_OPERATOR_POINTER_NAME_F(
71 const MultiDimImplementation<T*>* t1,
72 const MultiDimImplementation<T*>* t2,
73 const T ( *f )(
const T*,
const T* ) )
81 const Sequence< const DiscreteVariable* >& t1_vars = t1->variablesSequence();
82 const Sequence< const DiscreteVariable* >& t2_vars = t2->variablesSequence();
85 HashTable< const DiscreteVariable*, Idx > t1_offsets;
87 Idx current_offset = 1;
89 for (
const auto var : t1_vars) {
90 t1_offsets.insert(var, current_offset);
91 current_offset *= var->domainSize();
94 HashTable< const DiscreteVariable*, Idx > t2_offsets;
96 Idx current_offset = 1;
98 for (
const auto var : t2_vars) {
99 t2_offsets.insert(var, current_offset);
100 current_offset *= var->domainSize();
112 std::vector< const DiscreteVariable* > t1_alone_var;
113 std::vector< Idx > t1_alone_domain;
114 Idx t1_alone_domain_size = 1;
116 std::vector< const DiscreteVariable* > t2_alone_var;
117 std::vector< Idx > t2_alone_domain;
118 Idx t2_alone_domain_size = 1;
120 std::vector< const DiscreteVariable* > t1_and_t2_var;
121 std::vector< Idx > t1_and_t2_domain;
122 Idx t1_and_t2_domain_size = 1;
125 for (
const auto var : t1_vars)
126 if (t2_vars.exists(var)) {
127 t1_and_t2_domain.push_back(var->domainSize());
128 t1_and_t2_var.push_back(var);
129 t1_and_t2_domain_size *= var->domainSize();
131 t1_alone_domain.push_back(var->domainSize());
132 t1_alone_var.push_back(var);
133 t1_alone_domain_size *= var->domainSize();
136 for (
const auto var : t2_vars)
137 if (!t1_vars.exists(var)) {
138 t2_alone_domain.push_back(var->domainSize());
139 t2_alone_var.push_back(var);
140 t2_alone_domain_size *= var->domainSize();
147 bool t1_and_t2_begin_vars =
false;
149 if (t1_and_t2_var.size()) {
150 unsigned int nb_t1_t2_vars = 0;
152 for (
const auto var : t1_vars) {
153 if (var != t1_and_t2_var[nb_t1_t2_vars])
break;
157 if (nb_t1_t2_vars == t1_and_t2_var.size()) {
160 for (
auto iter = t2_vars.begin(); nb_t1_t2_vars != t1_and_t2_var.size();
161 ++iter, ++nb_t1_t2_vars)
162 if (*iter != t1_and_t2_var[nb_t1_t2_vars])
break;
164 if (nb_t1_t2_vars == t1_and_t2_var.size()) t1_and_t2_begin_vars =
true;
176 std::vector< Idx > t1_and_t2_value = t1_and_t2_domain;
177 std::vector< Idx > t1_alone_value = t1_alone_domain;
178 std::vector< Idx > t2_alone_value = t2_alone_domain;
185 MultiDimArray< GUM_MULTI_DIM_OPERATOR_TYPE >* result =
186 new MultiDimArray< GUM_MULTI_DIM_OPERATOR_TYPE >;
187 result->beginMultipleChanges();
189 for (
const auto var : t1_vars)
190 if (t2_vars.exists(var)) *result << *var;
192 for (
const auto var : t2_vars)
193 if (!t1_vars.exists(var)) *result << *var;
195 for (
const auto var : t1_vars)
196 if (!t2_vars.exists(var)) *result << *var;
198 result->endMultipleChanges();
204 Idx result_offset = 0;
205 Instantiation t2_inst(t2);
206 Instantiation t1_inst(t1);
207 Instantiation t1_alone_begin_inst(t1);
212 if (t1_and_t2_begin_vars) {
213 for (
Idx i = 0; i < t1_alone_domain_size; ++i) {
215 t1_alone_begin_inst = t1_inst;
217 for (
Idx j = 0; j < t2_alone_domain_size; ++j) {
218 t1_inst = t1_alone_begin_inst;
220 for (
Idx z = 0; z < t1_and_t2_domain_size; ++z) {
223 GUM_MULTI_DIM_OPERATOR(t1->get(t1_inst), t2->get(t2_inst)));
234 for (
Idx i = 0; i < t1_alone_domain_size; ++i) {
236 t1_alone_begin_inst = t1_inst;
238 for (
Idx j = 0; j < t2_alone_domain_size; ++j) {
239 t1_inst = t1_alone_begin_inst;
241 for (
Idx z = 0; z < t1_and_t2_domain_size; ++z) {
244 GUM_MULTI_DIM_OPERATOR(t1->get(t1_inst), t2->get(t2_inst)));
249 for (
unsigned int k = 0; k < t1_and_t2_value.size(); ++k) {
250 --t1_and_t2_value[k];
252 if (t1_and_t2_value[k]) {
253 t1_inst.incVar(*(t1_and_t2_var[k]));
254 t2_inst.incVar(*(t1_and_t2_var[k]));
258 t1_and_t2_value[k] = t1_and_t2_domain[k];
259 t1_inst.setFirstVar(*(t1_and_t2_var[k]));
260 t2_inst.setFirstVar(*(t1_and_t2_var[k]));
265 for (
unsigned int k = 0; k < t2_alone_value.size(); ++k) {
268 if (t2_alone_value[k]) {
269 t2_inst.incVar(*(t2_alone_var[k]));
273 t2_alone_value[k] = t2_alone_domain[k];
274 t2_inst.setFirstVar(*(t2_alone_var[k]));
279 for (
unsigned int k = 0; k < t1_alone_value.size(); ++k) {
282 if (t1_alone_value[k]) {
283 t1_inst.incVar(*(t1_alone_var[k]));
287 t1_alone_value[k] = t1_alone_domain[k];
288 t1_inst.setFirstVar(*(t1_alone_var[k]));
296 # undef GUM_MULTI_DIM_OPERATOR_TYPE gum is the global namespace for all aGrUM entities