1 // SPDX-License-Identifier: Apache-2.0
2 //
3 // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
4 // Copyright 2008-2016 National ICT Australia (NICTA)
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 // ------------------------------------------------------------------------
17
18
19 //! \addtogroup spglue_relational
20 //! @{
21
22
23
24 template<typename T1, typename T2>
25 inline
26 void
apply(SpMat<uword> & out,const mtSpGlue<uword,T1,T2,spglue_rel_lt> & X)27 spglue_rel_lt::apply(SpMat<uword>& out, const mtSpGlue<uword, T1, T2, spglue_rel_lt>& X)
28 {
29 arma_extra_debug_sigprint();
30
31 const SpProxy<T1> PA(X.A);
32 const SpProxy<T2> PB(X.B);
33
34 const bool is_alias = PA.is_alias(out) || PB.is_alias(out);
35
36 if(is_alias == false)
37 {
38 spglue_rel_lt::apply_noalias(out, PA, PB);
39 }
40 else
41 {
42 SpMat<uword> tmp;
43
44 spglue_rel_lt::apply_noalias(tmp, PA, PB);
45
46 out.steal_mem(tmp);
47 }
48 }
49
50
51
52 template<typename T1, typename T2>
53 inline
54 void
apply_noalias(SpMat<uword> & out,const SpProxy<T1> & PA,const SpProxy<T2> & PB)55 spglue_rel_lt::apply_noalias(SpMat<uword>& out, const SpProxy<T1>& PA, const SpProxy<T2>& PB)
56 {
57 arma_extra_debug_sigprint();
58
59 typedef typename T1::elem_type eT;
60
61 arma_debug_assert_same_size(PA.get_n_rows(), PA.get_n_cols(), PB.get_n_rows(), PB.get_n_cols(), "operator<");
62
63 const uword max_n_nonzero = PA.get_n_nonzero() + PB.get_n_nonzero();
64
65 // Resize memory to upper bound
66 out.reserve(PA.get_n_rows(), PA.get_n_cols(), max_n_nonzero);
67
68 // Now iterate across both matrices.
69 typename SpProxy<T1>::const_iterator_type x_it = PA.begin();
70 typename SpProxy<T1>::const_iterator_type x_end = PA.end();
71
72 typename SpProxy<T2>::const_iterator_type y_it = PB.begin();
73 typename SpProxy<T2>::const_iterator_type y_end = PB.end();
74
75 uword count = 0;
76
77 while( (x_it != x_end) || (y_it != y_end) )
78 {
79 uword out_val;
80
81 const uword x_it_col = x_it.col();
82 const uword x_it_row = x_it.row();
83
84 const uword y_it_col = y_it.col();
85 const uword y_it_row = y_it.row();
86
87 bool use_y_loc = false;
88
89 if(x_it == y_it)
90 {
91 out_val = ((*x_it) < (*y_it)) ? uword(1) : uword(0);
92
93 ++x_it;
94 ++y_it;
95 }
96 else
97 {
98 if((x_it_col < y_it_col) || ((x_it_col == y_it_col) && (x_it_row < y_it_row))) // if y is closer to the end
99 {
100 out_val = ((*x_it) < eT(0)) ? uword(1) : uword(0);
101
102 ++x_it;
103 }
104 else
105 {
106 out_val = (eT(0) < (*y_it)) ? uword(1) : uword(0);
107
108 ++y_it;
109
110 use_y_loc = true;
111 }
112 }
113
114 if(out_val != uword(0))
115 {
116 access::rw(out.values[count]) = out_val;
117
118 const uword out_row = (use_y_loc == false) ? x_it_row : y_it_row;
119 const uword out_col = (use_y_loc == false) ? x_it_col : y_it_col;
120
121 access::rw(out.row_indices[count]) = out_row;
122 access::rw(out.col_ptrs[out_col + 1])++;
123 ++count;
124 }
125
126 arma_check( (count > max_n_nonzero), "internal error: spglue_rel_lt::apply_noalias(): count > max_n_nonzero" );
127 }
128
129 const uword out_n_cols = out.n_cols;
130
131 uword* col_ptrs = access::rwp(out.col_ptrs);
132
133 // Fix column pointers to be cumulative.
134 for(uword c = 1; c <= out_n_cols; ++c)
135 {
136 col_ptrs[c] += col_ptrs[c - 1];
137 }
138
139 if(count < max_n_nonzero)
140 {
141 if(count <= (max_n_nonzero/2))
142 {
143 out.mem_resize(count);
144 }
145 else
146 {
147 // quick resize without reallocating memory and copying data
148 access::rw( out.n_nonzero) = count;
149 access::rw( out.values[count]) = eT(0);
150 access::rw(out.row_indices[count]) = uword(0);
151 }
152 }
153 }
154
155
156
157 //
158
159
160
161 template<typename T1, typename T2>
162 inline
163 void
apply(SpMat<uword> & out,const mtSpGlue<uword,T1,T2,spglue_rel_gt> & X)164 spglue_rel_gt::apply(SpMat<uword>& out, const mtSpGlue<uword, T1, T2, spglue_rel_gt>& X)
165 {
166 arma_extra_debug_sigprint();
167
168 const SpProxy<T1> PA(X.A);
169 const SpProxy<T2> PB(X.B);
170
171 const bool is_alias = PA.is_alias(out) || PB.is_alias(out);
172
173 if(is_alias == false)
174 {
175 spglue_rel_gt::apply_noalias(out, PA, PB);
176 }
177 else
178 {
179 SpMat<uword> tmp;
180
181 spglue_rel_gt::apply_noalias(tmp, PA, PB);
182
183 out.steal_mem(tmp);
184 }
185 }
186
187
188
189 template<typename T1, typename T2>
190 inline
191 void
apply_noalias(SpMat<uword> & out,const SpProxy<T1> & PA,const SpProxy<T2> & PB)192 spglue_rel_gt::apply_noalias(SpMat<uword>& out, const SpProxy<T1>& PA, const SpProxy<T2>& PB)
193 {
194 arma_extra_debug_sigprint();
195
196 typedef typename T1::elem_type eT;
197
198 arma_debug_assert_same_size(PA.get_n_rows(), PA.get_n_cols(), PB.get_n_rows(), PB.get_n_cols(), "operator>");
199
200 const uword max_n_nonzero = PA.get_n_nonzero() + PB.get_n_nonzero();
201
202 // Resize memory to upper bound
203 out.reserve(PA.get_n_rows(), PA.get_n_cols(), max_n_nonzero);
204
205 // Now iterate across both matrices.
206 typename SpProxy<T1>::const_iterator_type x_it = PA.begin();
207 typename SpProxy<T1>::const_iterator_type x_end = PA.end();
208
209 typename SpProxy<T2>::const_iterator_type y_it = PB.begin();
210 typename SpProxy<T2>::const_iterator_type y_end = PB.end();
211
212 uword count = 0;
213
214 while( (x_it != x_end) || (y_it != y_end) )
215 {
216 uword out_val;
217
218 const uword x_it_col = x_it.col();
219 const uword x_it_row = x_it.row();
220
221 const uword y_it_col = y_it.col();
222 const uword y_it_row = y_it.row();
223
224 bool use_y_loc = false;
225
226 if(x_it == y_it)
227 {
228 out_val = ((*x_it) > (*y_it)) ? uword(1) : uword(0);
229
230 ++x_it;
231 ++y_it;
232 }
233 else
234 {
235 if((x_it_col < y_it_col) || ((x_it_col == y_it_col) && (x_it_row < y_it_row))) // if y is closer to the end
236 {
237 out_val = ((*x_it) > eT(0)) ? uword(1) : uword(0);
238
239 ++x_it;
240 }
241 else
242 {
243 out_val = (eT(0) > (*y_it)) ? uword(1) : uword(0);
244
245 ++y_it;
246
247 use_y_loc = true;
248 }
249 }
250
251 if(out_val != uword(0))
252 {
253 access::rw(out.values[count]) = out_val;
254
255 const uword out_row = (use_y_loc == false) ? x_it_row : y_it_row;
256 const uword out_col = (use_y_loc == false) ? x_it_col : y_it_col;
257
258 access::rw(out.row_indices[count]) = out_row;
259 access::rw(out.col_ptrs[out_col + 1])++;
260 ++count;
261 }
262
263 arma_check( (count > max_n_nonzero), "internal error: spglue_rel_gt::apply_noalias(): count > max_n_nonzero" );
264 }
265
266 const uword out_n_cols = out.n_cols;
267
268 uword* col_ptrs = access::rwp(out.col_ptrs);
269
270 // Fix column pointers to be cumulative.
271 for(uword c = 1; c <= out_n_cols; ++c)
272 {
273 col_ptrs[c] += col_ptrs[c - 1];
274 }
275
276 if(count < max_n_nonzero)
277 {
278 if(count <= (max_n_nonzero/2))
279 {
280 out.mem_resize(count);
281 }
282 else
283 {
284 // quick resize without reallocating memory and copying data
285 access::rw( out.n_nonzero) = count;
286 access::rw( out.values[count]) = eT(0);
287 access::rw(out.row_indices[count]) = uword(0);
288 }
289 }
290 }
291
292
293
294 //
295
296
297
298 template<typename T1, typename T2>
299 inline
300 void
apply(SpMat<uword> & out,const mtSpGlue<uword,T1,T2,spglue_rel_and> & X)301 spglue_rel_and::apply(SpMat<uword>& out, const mtSpGlue<uword, T1, T2, spglue_rel_and>& X)
302 {
303 arma_extra_debug_sigprint();
304
305 const SpProxy<T1> PA(X.A);
306 const SpProxy<T2> PB(X.B);
307
308 const bool is_alias = PA.is_alias(out) || PB.is_alias(out);
309
310 if(is_alias == false)
311 {
312 spglue_rel_and::apply_noalias(out, PA, PB);
313 }
314 else
315 {
316 SpMat<uword> tmp;
317
318 spglue_rel_and::apply_noalias(tmp, PA, PB);
319
320 out.steal_mem(tmp);
321 }
322 }
323
324
325
326 template<typename T1, typename T2>
327 inline
328 void
apply_noalias(SpMat<uword> & out,const SpProxy<T1> & PA,const SpProxy<T2> & PB)329 spglue_rel_and::apply_noalias(SpMat<uword>& out, const SpProxy<T1>& PA, const SpProxy<T2>& PB)
330 {
331 arma_extra_debug_sigprint();
332
333 typedef typename T1::elem_type eT;
334
335 arma_debug_assert_same_size(PA.get_n_rows(), PA.get_n_cols(), PB.get_n_rows(), PB.get_n_cols(), "operator&&");
336
337 if( (PA.get_n_nonzero() == 0) || (PB.get_n_nonzero() == 0) )
338 {
339 out.zeros(PA.get_n_rows(), PA.get_n_cols());
340 return;
341 }
342
343 const uword max_n_nonzero = (std::min)(PA.get_n_nonzero(), PB.get_n_nonzero());
344
345 // Resize memory to upper bound
346 out.reserve(PA.get_n_rows(), PA.get_n_cols(), max_n_nonzero);
347
348 // Now iterate across both matrices.
349 typename SpProxy<T1>::const_iterator_type x_it = PA.begin();
350 typename SpProxy<T1>::const_iterator_type x_end = PA.end();
351
352 typename SpProxy<T2>::const_iterator_type y_it = PB.begin();
353 typename SpProxy<T2>::const_iterator_type y_end = PB.end();
354
355 uword count = 0;
356
357 while( (x_it != x_end) || (y_it != y_end) )
358 {
359 const uword x_it_row = x_it.row();
360 const uword x_it_col = x_it.col();
361
362 const uword y_it_row = y_it.row();
363 const uword y_it_col = y_it.col();
364
365 if(x_it == y_it)
366 {
367 access::rw(out.values[count]) = uword(1);
368
369 access::rw(out.row_indices[count]) = x_it_row;
370 access::rw(out.col_ptrs[x_it_col + 1])++;
371 ++count;
372
373 ++x_it;
374 ++y_it;
375 }
376 else
377 {
378 if((x_it_col < y_it_col) || ((x_it_col == y_it_col) && (x_it_row < y_it_row))) // if y is closer to the end
379 {
380 ++x_it;
381 }
382 else
383 {
384 ++y_it;
385 }
386 }
387
388 arma_check( (count > max_n_nonzero), "internal error: spglue_rel_and::apply_noalias(): count > max_n_nonzero" );
389 }
390
391 const uword out_n_cols = out.n_cols;
392
393 uword* col_ptrs = access::rwp(out.col_ptrs);
394
395 // Fix column pointers to be cumulative.
396 for(uword c = 1; c <= out_n_cols; ++c)
397 {
398 col_ptrs[c] += col_ptrs[c - 1];
399 }
400
401 if(count < max_n_nonzero)
402 {
403 if(count <= (max_n_nonzero/2))
404 {
405 out.mem_resize(count);
406 }
407 else
408 {
409 // quick resize without reallocating memory and copying data
410 access::rw( out.n_nonzero) = count;
411 access::rw( out.values[count]) = eT(0);
412 access::rw(out.row_indices[count]) = uword(0);
413 }
414 }
415 }
416
417
418
419 //
420
421
422
423 template<typename T1, typename T2>
424 inline
425 void
apply(SpMat<uword> & out,const mtSpGlue<uword,T1,T2,spglue_rel_or> & X)426 spglue_rel_or::apply(SpMat<uword>& out, const mtSpGlue<uword, T1, T2, spglue_rel_or>& X)
427 {
428 arma_extra_debug_sigprint();
429
430 const SpProxy<T1> PA(X.A);
431 const SpProxy<T2> PB(X.B);
432
433 const bool is_alias = PA.is_alias(out) || PB.is_alias(out);
434
435 if(is_alias == false)
436 {
437 spglue_rel_or::apply_noalias(out, PA, PB);
438 }
439 else
440 {
441 SpMat<uword> tmp;
442
443 spglue_rel_or::apply_noalias(tmp, PA, PB);
444
445 out.steal_mem(tmp);
446 }
447 }
448
449
450
451 template<typename T1, typename T2>
452 inline
453 void
apply_noalias(SpMat<uword> & out,const SpProxy<T1> & PA,const SpProxy<T2> & PB)454 spglue_rel_or::apply_noalias(SpMat<uword>& out, const SpProxy<T1>& PA, const SpProxy<T2>& PB)
455 {
456 arma_extra_debug_sigprint();
457
458 typedef typename T1::elem_type eT;
459
460 arma_debug_assert_same_size(PA.get_n_rows(), PA.get_n_cols(), PB.get_n_rows(), PB.get_n_cols(), "operator||");
461
462 const uword max_n_nonzero = PA.get_n_nonzero() + PB.get_n_nonzero();
463
464 // Resize memory to upper bound
465 out.reserve(PA.get_n_rows(), PA.get_n_cols(), max_n_nonzero);
466
467 // Now iterate across both matrices.
468 typename SpProxy<T1>::const_iterator_type x_it = PA.begin();
469 typename SpProxy<T1>::const_iterator_type x_end = PA.end();
470
471 typename SpProxy<T2>::const_iterator_type y_it = PB.begin();
472 typename SpProxy<T2>::const_iterator_type y_end = PB.end();
473
474 uword count = 0;
475
476 while( (x_it != x_end) || (y_it != y_end) )
477 {
478 const uword x_it_col = x_it.col();
479 const uword x_it_row = x_it.row();
480
481 const uword y_it_col = y_it.col();
482 const uword y_it_row = y_it.row();
483
484 bool use_y_loc = false;
485
486 if(x_it == y_it)
487 {
488 ++x_it;
489 ++y_it;
490 }
491 else
492 {
493 if((x_it_col < y_it_col) || ((x_it_col == y_it_col) && (x_it_row < y_it_row))) // if y is closer to the end
494 {
495 ++x_it;
496 }
497 else
498 {
499 ++y_it;
500
501 use_y_loc = true;
502 }
503 }
504
505 access::rw(out.values[count]) = uword(1);
506
507 const uword out_row = (use_y_loc == false) ? x_it_row : y_it_row;
508 const uword out_col = (use_y_loc == false) ? x_it_col : y_it_col;
509
510 access::rw(out.row_indices[count]) = out_row;
511 access::rw(out.col_ptrs[out_col + 1])++;
512 ++count;
513
514 arma_check( (count > max_n_nonzero), "internal error: spglue_rel_or::apply_noalias(): count > max_n_nonzero" );
515 }
516
517 const uword out_n_cols = out.n_cols;
518
519 uword* col_ptrs = access::rwp(out.col_ptrs);
520
521 // Fix column pointers to be cumulative.
522 for(uword c = 1; c <= out_n_cols; ++c)
523 {
524 col_ptrs[c] += col_ptrs[c - 1];
525 }
526
527 if(count < max_n_nonzero)
528 {
529 if(count <= (max_n_nonzero/2))
530 {
531 out.mem_resize(count);
532 }
533 else
534 {
535 // quick resize without reallocating memory and copying data
536 access::rw( out.n_nonzero) = count;
537 access::rw( out.values[count]) = eT(0);
538 access::rw(out.row_indices[count]) = uword(0);
539 }
540 }
541 }
542
543
544
545 //! @}
546