tatami
C++ API for different matrix representations
Loading...
Searching...
No Matches
boolean_helpers.hpp
Go to the documentation of this file.
1#ifndef TATAMI_ISOMETRIC_UNARY_BOOLEAN_HELPERS_H
2#define TATAMI_ISOMETRIC_UNARY_BOOLEAN_HELPERS_H
3
6#include <vector>
7#include <type_traits>
8
15namespace tatami {
16
20template<typename InputValue_, typename Index_, typename OutputValue_>
21void delayed_boolean_cast(const InputValue_* input, Index_ length, OutputValue_* output) {
22 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
23 input = output; // basically an assertion to the compiler to skip aliasing protection.
24 }
25 for (Index_ i = 0; i < length; ++i) {
26 output[i] = static_cast<bool>(input[i]);
27 }
28}
29
30template<typename InputValue_, typename Index_, typename OutputValue_>
31void delayed_boolean_not(const InputValue_* input, Index_ length, OutputValue_* output) {
32 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
33 input = output; // basically an assertion to the compiler to skip aliasing protection.
34 }
35 for (Index_ i = 0; i < length; ++i) {
36 output[i] = !static_cast<bool>(input[i]);
37 }
38}
39
40template<BooleanOperation op_, typename InputValue_, typename Index_, typename OutputValue_>
41void delayed_boolean_run_simple(const InputValue_* input, Index_ length, bool scalar, OutputValue_* output) {
42 if constexpr(op_ == BooleanOperation::AND) {
43 if (scalar) {
44 delayed_boolean_cast(input, length, output);
45 } else {
46 std::fill_n(output, length, 0);
47 }
48 } else if constexpr(op_ == BooleanOperation::OR) {
49 if (scalar) {
50 std::fill_n(output, length, 1);
51 } else {
52 delayed_boolean_cast(input, length, output);
53 }
54 } else if constexpr(op_ == BooleanOperation::XOR) {
55 if (scalar) {
56 delayed_boolean_not(input, length, output);
57 } else {
58 delayed_boolean_cast(input, length, output);
59 }
60 } else { // EQUAL
61 if (scalar) {
62 delayed_boolean_cast(input, length, output);
63 } else {
64 delayed_boolean_not(input, length, output);
65 }
66 }
67}
68
69template<BooleanOperation op_>
70bool delayed_boolean_actual_sparse(bool scalar) {
71 return delayed_boolean<op_>(0, scalar) == static_cast<bool>(0);
72}
88template<BooleanOperation op_, typename OutputValue_, typename InputValue_, typename Index_>
89class DelayedUnaryIsometricBooleanScalarHelper final : public DelayedUnaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> {
90public:
94 DelayedUnaryIsometricBooleanScalarHelper(bool scalar) : my_scalar(scalar) {
95 my_sparse = delayed_boolean_actual_sparse<op_>(my_scalar);
96 }
97
98private:
99 bool my_scalar;
100 bool my_sparse;
101
102public:
103 std::optional<Index_> nrow() const {
104 return std::nullopt;
105 }
106
107 std::optional<Index_> ncol() const {
108 return std::nullopt;
109 }
110
111public:
112 bool zero_depends_on_row() const {
113 return false;
114 }
115
117 return false;
118 }
119
121 return false;
122 }
123
125 return false;
126 }
127
128public:
129 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
130 delayed_boolean_run_simple<op_>(input, length, my_scalar, output);
131 }
132
133 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
134 delayed_boolean_run_simple<op_>(input, static_cast<Index_>(indices.size()), my_scalar, output);
135 }
136
137public:
138 bool is_sparse() const {
139 return my_sparse;
140 }
141
142 void sparse(bool, Index_, Index_ number, const InputValue_* input_value, const Index_*, OutputValue_* output_value) const {
143 delayed_boolean_run_simple<op_>(input_value, number, my_scalar, output_value);
144 }
145
146 OutputValue_ fill(bool, Index_) const {
147 // Remember, the operation needs to be performed on the InputValue_
148 // to use in casting it to the OutputValue_.
149 return delayed_boolean<op_>(0, my_scalar);
150 }
151};
152
160template<typename OutputValue_, typename InputValue_, typename Index_>
162
170template<typename OutputValue_, typename InputValue_, typename Index_>
172
180template<typename OutputValue_, typename InputValue_, typename Index_>
182
190template<typename OutputValue_, typename InputValue_, typename Index_>
192
196// Back-compatibility only.
197template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
198std::shared_ptr<DelayedUnaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> > make_DelayedUnaryIsometricBooleanEqualScalar(bool scalar) {
199 return std::make_shared<DelayedUnaryIsometricBooleanEqualScalarHelper<OutputValue_, InputValue_, Index_> >(scalar);
200}
201
202template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
203std::shared_ptr<DelayedUnaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> > make_DelayedUnaryIsometricBooleanAndScalar(bool scalar) {
204 return std::make_shared<DelayedUnaryIsometricBooleanAndScalarHelper<OutputValue_, InputValue_, Index_> >(scalar);
205}
206
207template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
208std::shared_ptr<DelayedUnaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> > make_DelayedUnaryIsometricBooleanOrScalar(bool scalar) {
209 return std::make_shared<DelayedUnaryIsometricBooleanOrScalarHelper<OutputValue_, InputValue_, Index_> >(scalar);
210}
211
212template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int>
213std::shared_ptr<DelayedUnaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> > make_DelayedUnaryIsometricBooleanXorScalar(bool scalar) {
214 return std::make_shared<DelayedUnaryIsometricBooleanXorScalarHelper<OutputValue_, InputValue_, Index_> >(scalar);
215}
230template<typename OutputValue_, typename InputValue_, typename Index_>
231class DelayedUnaryIsometricBooleanNotHelper final : public DelayedUnaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> {
232public:
233 std::optional<Index_> nrow() const {
234 return std::nullopt;
235 }
236
237 std::optional<Index_> ncol() const {
238 return std::nullopt;
239 }
240
241public:
242 bool zero_depends_on_row() const {
243 return false;
244 }
245
247 return false;
248 }
249
251 return false;
252 }
253
255 return false;
256 }
257
258public:
259 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
260 delayed_boolean_not(input, length, output);
261 }
262
263 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
264 delayed_boolean_not(input, static_cast<Index_>(indices.size()), output);
265 }
266
267public:
268 bool is_sparse() const {
269 return false;
270 }
271
272 void sparse(bool, Index_, Index_ number, const InputValue_* input_value, const Index_*, OutputValue_* output_value) const {
273 delayed_boolean_not(input_value, number, output_value);
274 }
275
276 OutputValue_ fill(bool, Index_) const {
277 return 1;
278 }
279};
280
291template<typename OutputValue_, typename InputValue_, typename Index_>
292class DelayedUnaryIsometricBooleanCastHelper final : public DelayedUnaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> {
293public:
294 std::optional<Index_> nrow() const {
295 return std::nullopt;
296 }
297
298 std::optional<Index_> ncol() const {
299 return std::nullopt;
300 }
301
302public:
303 bool zero_depends_on_row() const {
304 return false;
305 }
306
308 return false;
309 }
310
312 return false;
313 }
314
316 return false;
317 }
318
319public:
320 void dense(bool, Index_, Index_, Index_ length, const InputValue_* input, OutputValue_* output) const {
321 delayed_boolean_cast(input, length, output);
322 }
323
324 void dense(bool, Index_, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
325 delayed_boolean_cast(input, static_cast<Index_>(indices.size()), output);
326 }
327
328public:
329 bool is_sparse() const {
330 return true;
331 }
332
333 void sparse(bool, Index_, Index_ number, const InputValue_* input_value, const Index_*, OutputValue_* output_value) const {
334 delayed_boolean_cast(input_value, number, output_value);
335 }
336
337 OutputValue_ fill(bool, Index_) const {
338 return 0;
339 }
340};
341
345// Back-compatibility only.
346typedef DelayedUnaryIsometricBooleanCastHelper<double, double, int> DelayedUnaryIsometricBooleanCast;
347typedef DelayedUnaryIsometricBooleanNotHelper<double, double, int> DelayedUnaryIsometricBooleanNot;
364template<BooleanOperation op_, typename OutputValue_, typename InputValue_, typename Index_, typename Vector_>
365class DelayedUnaryIsometricBooleanVectorHelper final : public DelayedUnaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> {
366public:
374 DelayedUnaryIsometricBooleanVectorHelper(Vector_ vector, bool by_row) : my_vector(std::move(vector)), my_by_row(by_row) {
375 for (auto x : my_vector) {
376 if (!delayed_boolean_actual_sparse<op_>(x)) {
377 my_sparse = false;
378 break;
379 }
380 }
381 }
382
383private:
384 Vector_ my_vector;
385 bool my_by_row;
386 bool my_sparse = true;
387
388public:
389 std::optional<Index_> nrow() const {
390 if (my_by_row) {
391 return my_vector.size();
392 } else {
393 return std::nullopt;
394 }
395 }
396
397 std::optional<Index_> ncol() const {
398 if (my_by_row) {
399 return std::nullopt;
400 } else {
401 return my_vector.size();
402 }
403 }
404
405public:
406 bool zero_depends_on_row() const {
407 return my_by_row;
408 }
409
411 return !my_by_row;
412 }
413
415 return my_by_row;
416 }
417
419 return !my_by_row;
420 }
421
422public:
423 void dense(bool row, Index_ idx, Index_ start, Index_ length, const InputValue_* input, OutputValue_* output) const {
424 if (row == my_by_row) {
425 delayed_boolean_run_simple<op_>(input, length, my_vector[idx], output);
426 } else {
427 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
428 input = output; // basically an assertion to the compiler to skip aliasing protection.
429 }
430 for (Index_ i = 0; i < length; ++i) {
431 output[i] = delayed_boolean<op_>(input[i], my_vector[i + start]);
432 }
433 }
434 }
435
436 void dense(bool row, Index_ idx, const std::vector<Index_>& indices, const InputValue_* input, OutputValue_* output) const {
437 if (row == my_by_row) {
438 delayed_boolean_run_simple<op_>(input, static_cast<Index_>(indices.size()), my_vector[idx], output);
439 } else {
440 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
441 input = output; // basically an assertion to the compiler to skip aliasing protection.
442 }
443 Index_ length = indices.size();
444 for (Index_ i = 0; i < length; ++i) {
445 output[i] = delayed_boolean<op_>(input[i], my_vector[indices[i]]);
446 }
447 }
448 }
449
450public:
451 bool is_sparse() const {
452 return my_sparse;
453 }
454
455 void sparse(bool row, Index_ idx, Index_ number, const InputValue_* input_value, const Index_* index, OutputValue_* output_value) const {
456 if (row == my_by_row) {
457 delayed_boolean_run_simple<op_>(input_value, number, my_vector[idx], output_value);
458 } else {
459 if constexpr(std::is_same<InputValue_, OutputValue_>::value) {
460 input_value = output_value; // basically an assertion to the compiler to skip aliasing protection.
461 }
462 for (Index_ i = 0; i < number; ++i) {
463 output_value[i] = delayed_boolean<op_>(input_value[i], my_vector[index[i]]);
464 }
465 }
466 }
467
468 OutputValue_ fill(bool row, Index_ idx) const {
469 if (row == my_by_row) {
470 return delayed_boolean<op_>(0, my_vector[idx]);
471 } else {
472 // We should only get to this point if it's sparse, otherwise no
473 // single fill value would work across the length of my_vector.
474 return 0;
475 }
476 }
477};
478
486template<typename OutputValue_, typename InputValue_, typename Index_, typename Vector_>
488
496template<typename OutputValue_, typename InputValue_, typename Index_, typename Vector_>
498
506template<typename OutputValue_, typename InputValue_, typename Index_, typename Vector_>
508
516template<typename OutputValue_, typename InputValue_, typename Index_, typename Vector_>
518
522// Back-compatibility only.
523template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int, typename Vector_>
524std::shared_ptr<DelayedUnaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> > make_DelayedUnaryIsometricBooleanEqualVector(Vector_ vector, bool by_row) {
525 return std::make_shared<DelayedUnaryIsometricBooleanEqualVectorHelper<OutputValue_, InputValue_, Index_, Vector_> >(std::move(vector), by_row);
526}
527
528template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int, typename Vector_>
529std::shared_ptr<DelayedUnaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> > make_DelayedUnaryIsometricBooleanAndVector(Vector_ vector, bool by_row) {
530 return std::make_shared<DelayedUnaryIsometricBooleanAndVectorHelper<OutputValue_, InputValue_, Index_, Vector_> >(std::move(vector), by_row);
531}
532
533template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int, typename Vector_>
534std::shared_ptr<DelayedUnaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> > make_DelayedUnaryIsometricBooleanOrVector(Vector_ vector, bool by_row) {
535 return std::make_shared<DelayedUnaryIsometricBooleanOrVectorHelper<OutputValue_, InputValue_, Index_, Vector_> >(std::move(vector), by_row);
536}
537
538template<typename OutputValue_ = double, typename InputValue_ = double, typename Index_ = int, typename Vector_>
539std::shared_ptr<DelayedUnaryIsometricOperationHelper<OutputValue_, InputValue_, Index_> > make_DelayedUnaryIsometricBooleanXorVector(Vector_ vector, bool by_row) {
540 return std::make_shared<DelayedUnaryIsometricBooleanXorVectorHelper<OutputValue_, InputValue_, Index_, Vector_> >(std::move(vector), by_row);
541}
547}
548
549#endif
Utilities for delayed boolean operations.
Delayed unary isometric boolean cast.
Definition boolean_helpers.hpp:292
bool non_zero_depends_on_row() const
Definition boolean_helpers.hpp:311
bool zero_depends_on_row() const
Definition boolean_helpers.hpp:303
std::optional< Index_ > nrow() const
Definition boolean_helpers.hpp:294
std::optional< Index_ > ncol() const
Definition boolean_helpers.hpp:298
bool non_zero_depends_on_column() const
Definition boolean_helpers.hpp:315
OutputValue_ fill(bool, Index_) const
Definition boolean_helpers.hpp:337
void dense(bool, Index_, const std::vector< Index_ > &indices, const InputValue_ *input, OutputValue_ *output) const
Definition boolean_helpers.hpp:324
bool zero_depends_on_column() const
Definition boolean_helpers.hpp:307
void sparse(bool, Index_, Index_ number, const InputValue_ *input_value, const Index_ *, OutputValue_ *output_value) const
Definition boolean_helpers.hpp:333
void dense(bool, Index_, Index_, Index_ length, const InputValue_ *input, OutputValue_ *output) const
Definition boolean_helpers.hpp:320
bool is_sparse() const
Definition boolean_helpers.hpp:329
Helper for a delayed unary isometric boolean NOT operation.
Definition boolean_helpers.hpp:231
bool non_zero_depends_on_row() const
Definition boolean_helpers.hpp:250
OutputValue_ fill(bool, Index_) const
Definition boolean_helpers.hpp:276
std::optional< Index_ > nrow() const
Definition boolean_helpers.hpp:233
bool is_sparse() const
Definition boolean_helpers.hpp:268
std::optional< Index_ > ncol() const
Definition boolean_helpers.hpp:237
bool non_zero_depends_on_column() const
Definition boolean_helpers.hpp:254
void dense(bool, Index_, Index_, Index_ length, const InputValue_ *input, OutputValue_ *output) const
Definition boolean_helpers.hpp:259
bool zero_depends_on_row() const
Definition boolean_helpers.hpp:242
void sparse(bool, Index_, Index_ number, const InputValue_ *input_value, const Index_ *, OutputValue_ *output_value) const
Definition boolean_helpers.hpp:272
bool zero_depends_on_column() const
Definition boolean_helpers.hpp:246
void dense(bool, Index_, const std::vector< Index_ > &indices, const InputValue_ *input, OutputValue_ *output) const
Definition boolean_helpers.hpp:263
Helper for delayed unary isometric scalar boolean operations.
Definition boolean_helpers.hpp:89
bool non_zero_depends_on_column() const
Definition boolean_helpers.hpp:124
bool zero_depends_on_column() const
Definition boolean_helpers.hpp:116
void dense(bool, Index_, Index_, Index_ length, const InputValue_ *input, OutputValue_ *output) const
Definition boolean_helpers.hpp:129
OutputValue_ fill(bool, Index_) const
Definition boolean_helpers.hpp:146
std::optional< Index_ > nrow() const
Definition boolean_helpers.hpp:103
std::optional< Index_ > ncol() const
Definition boolean_helpers.hpp:107
bool is_sparse() const
Definition boolean_helpers.hpp:138
void sparse(bool, Index_, Index_ number, const InputValue_ *input_value, const Index_ *, OutputValue_ *output_value) const
Definition boolean_helpers.hpp:142
DelayedUnaryIsometricBooleanScalarHelper(bool scalar)
Definition boolean_helpers.hpp:94
bool zero_depends_on_row() const
Definition boolean_helpers.hpp:112
bool non_zero_depends_on_row() const
Definition boolean_helpers.hpp:120
void dense(bool, Index_, const std::vector< Index_ > &indices, const InputValue_ *input, OutputValue_ *output) const
Definition boolean_helpers.hpp:133
Helper for delayed unary isometric vector boolean operations.
Definition boolean_helpers.hpp:365
void dense(bool row, Index_ idx, Index_ start, Index_ length, const InputValue_ *input, OutputValue_ *output) const
Definition boolean_helpers.hpp:423
bool is_sparse() const
Definition boolean_helpers.hpp:451
bool non_zero_depends_on_row() const
Definition boolean_helpers.hpp:414
std::optional< Index_ > nrow() const
Definition boolean_helpers.hpp:389
bool zero_depends_on_row() const
Definition boolean_helpers.hpp:406
DelayedUnaryIsometricBooleanVectorHelper(Vector_ vector, bool by_row)
Definition boolean_helpers.hpp:374
void dense(bool row, Index_ idx, const std::vector< Index_ > &indices, const InputValue_ *input, OutputValue_ *output) const
Definition boolean_helpers.hpp:436
OutputValue_ fill(bool row, Index_ idx) const
Definition boolean_helpers.hpp:468
void sparse(bool row, Index_ idx, Index_ number, const InputValue_ *input_value, const Index_ *index, OutputValue_ *output_value) const
Definition boolean_helpers.hpp:455
bool zero_depends_on_column() const
Definition boolean_helpers.hpp:410
std::optional< Index_ > ncol() const
Definition boolean_helpers.hpp:397
bool non_zero_depends_on_column() const
Definition boolean_helpers.hpp:418
Helper operation interface for DelayedUnaryIsometricOperation.
Definition helper_interface.hpp:27
Flexible representations for matrix data.
Definition Extractor.hpp:15
Interface for tatami::DelayedUnaryIsometricOperation helpers.