30 #ifndef GUM_OPERATOR_PATTERN_ALLOWED 42 # ifdef GUM_MULTI_DIM_OPERATOR_NAME 43 # define GUM_MULTI_DIM_OPERATOR_TYPE T 44 template <
typename T >
45 MultiDimImplementation< T >* GUM_MULTI_DIM_OPERATOR_NAME(
const MultiDimImplementation< T >* t1,
46 const MultiDimImplementation< T >* t2)
51 #ifdef GUM_MULTI_DIM_OPERATOR_POINTER_NAME 52 #define GUM_MULTI_DIM_OPERATOR_TYPE T * 54 MultiDimImplementation<T*>* GUM_MULTI_DIM_OPERATOR_POINTER_NAME(
55 const MultiDimImplementation<T*>* t1,
56 const MultiDimImplementation<T*>* t2 )
59 #ifdef GUM_MULTI_DIM_OPERATOR_NAME_F 60 #define GUM_MULTI_DIM_OPERATOR_TYPE T 62 MultiDimImplementation<T>* GUM_MULTI_DIM_OPERATOR_NAME_F(
63 const MultiDimImplementation<T>* t1,
64 const MultiDimImplementation<T>* t2,
65 const T ( *f )(
const T&,
const T& ) )
68 #ifdef GUM_MULTI_DIM_OPERATOR_POINTER_NAME_F 69 #define GUM_MULTI_DIM_OPERATOR_TYPE T * 71 MultiDimImplementation<T*>* GUM_MULTI_DIM_OPERATOR_POINTER_NAME_F(
72 const MultiDimImplementation<T*>* t1,
73 const MultiDimImplementation<T*>* t2,
74 const T ( *f )(
const T*,
const T* ) )
82 const Sequence<
const DiscreteVariable* >& t1_vars = t1->variablesSequence();
83 const Sequence<
const DiscreteVariable* >& t2_vars = t2->variablesSequence();
86 HashTable<
const DiscreteVariable*, Idx > t1_offsets;
88 Idx current_offset = 1;
90 for (
const auto var: t1_vars) {
91 t1_offsets.insert(var, current_offset);
92 current_offset *= var->domainSize();
95 HashTable<
const DiscreteVariable*, Idx > t2_offsets;
97 Idx current_offset = 1;
99 for (
const auto var: t2_vars) {
100 t2_offsets.insert(var, current_offset);
101 current_offset *= var->domainSize();
113 std::vector<
const DiscreteVariable* > t1_alone_var;
114 std::vector< Idx > t1_alone_domain;
115 Idx t1_alone_domain_size = 1;
117 std::vector<
const DiscreteVariable* > t2_alone_var;
118 std::vector< Idx > t2_alone_domain;
119 Idx t2_alone_domain_size = 1;
121 std::vector<
const DiscreteVariable* > t1_and_t2_var;
122 std::vector< Idx > t1_and_t2_domain;
123 Idx t1_and_t2_domain_size = 1;
126 for (
const auto var: t1_vars)
127 if (t2_vars.exists(var)) {
128 t1_and_t2_domain.push_back(var->domainSize());
129 t1_and_t2_var.push_back(var);
130 t1_and_t2_domain_size *= var->domainSize();
132 t1_alone_domain.push_back(var->domainSize());
133 t1_alone_var.push_back(var);
134 t1_alone_domain_size *= var->domainSize();
137 for (
const auto var: t2_vars)
138 if (!t1_vars.exists(var)) {
139 t2_alone_domain.push_back(var->domainSize());
140 t2_alone_var.push_back(var);
141 t2_alone_domain_size *= var->domainSize();
148 bool t1_and_t2_begin_vars =
false;
150 if (t1_and_t2_var.size()) {
151 unsigned int nb_t1_t2_vars = 0;
153 for (
const auto var: t1_vars) {
154 if (var != t1_and_t2_var[nb_t1_t2_vars])
break;
158 if (nb_t1_t2_vars == t1_and_t2_var.size()) {
161 for (
auto iter = t2_vars.begin(); nb_t1_t2_vars != t1_and_t2_var.size();
162 ++iter, ++nb_t1_t2_vars)
163 if (*iter != t1_and_t2_var[nb_t1_t2_vars])
break;
165 if (nb_t1_t2_vars == t1_and_t2_var.size()) t1_and_t2_begin_vars =
true;
177 std::vector< Idx > t1_and_t2_value = t1_and_t2_domain;
178 std::vector< Idx > t1_alone_value = t1_alone_domain;
179 std::vector< Idx > t2_alone_value = t2_alone_domain;
186 MultiDimArray< GUM_MULTI_DIM_OPERATOR_TYPE >* result
187 =
new MultiDimArray< GUM_MULTI_DIM_OPERATOR_TYPE >;
188 result->beginMultipleChanges();
190 for (
const auto var: t1_vars)
191 if (t2_vars.exists(var)) *result << *var;
193 for (
const auto var: t2_vars)
194 if (!t1_vars.exists(var)) *result << *var;
196 for (
const auto var: t1_vars)
197 if (!t2_vars.exists(var)) *result << *var;
199 result->endMultipleChanges();
205 Idx result_offset = 0;
206 Instantiation t2_inst(t2);
207 Instantiation t1_inst(t1);
208 Instantiation t1_alone_begin_inst(t1);
213 if (t1_and_t2_begin_vars) {
214 for (Idx i = 0; i < t1_alone_domain_size; ++i) {
216 t1_alone_begin_inst = t1_inst;
218 for (Idx j = 0; j < t2_alone_domain_size; ++j) {
219 t1_inst = t1_alone_begin_inst;
221 for (Idx z = 0; z < t1_and_t2_domain_size; ++z) {
222 result->unsafeSet(result_offset,
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) {
242 result->unsafeSet(result_offset,
243 GUM_MULTI_DIM_OPERATOR(t1->get(t1_inst), t2->get(t2_inst)));
248 for (
unsigned int k = 0; k < t1_and_t2_value.size(); ++k) {
249 --t1_and_t2_value[k];
251 if (t1_and_t2_value[k]) {
252 t1_inst.incVar(*(t1_and_t2_var[k]));
253 t2_inst.incVar(*(t1_and_t2_var[k]));
257 t1_and_t2_value[k] = t1_and_t2_domain[k];
258 t1_inst.setFirstVar(*(t1_and_t2_var[k]));
259 t2_inst.setFirstVar(*(t1_and_t2_var[k]));
264 for (
unsigned int k = 0; k < t2_alone_value.size(); ++k) {
267 if (t2_alone_value[k]) {
268 t2_inst.incVar(*(t2_alone_var[k]));
272 t2_alone_value[k] = t2_alone_domain[k];
273 t2_inst.setFirstVar(*(t2_alone_var[k]));
278 for (
unsigned int k = 0; k < t1_alone_value.size(); ++k) {
281 if (t1_alone_value[k]) {
282 t1_inst.incVar(*(t1_alone_var[k]));
286 t1_alone_value[k] = t1_alone_domain[k];
287 t1_inst.setFirstVar(*(t1_alone_var[k]));
295 # undef GUM_MULTI_DIM_OPERATOR_TYPE