tatami_test
Utilities for testing tatami libraries
Loading...
Searching...
No Matches
test_unsorted_access.hpp
Go to the documentation of this file.
1#ifndef TATAMI_TEST_TEST_UNSORTED_ACCESS_HPP
2#define TATAMI_TEST_TEST_UNSORTED_ACCESS_HPP
3
4#include <gtest/gtest.h>
5
9
10#include "fetch.hpp"
12#include "test_access.hpp"
13
14#include <vector>
15#include <limits>
16#include <random>
17#include <cmath>
18
24namespace tatami_test {
25
29namespace internal {
30
31template<bool use_oracle_, typename Value_, typename Index_, typename ...Args_>
32void test_unsorted_access_base(const tatami::Matrix<Value_, Index_>& matrix, const TestAccessOptions& options, Index_ extent, Args_... args) {
33 auto NR = matrix.nrow();
34 auto NC = matrix.ncol();
35
36 auto sequence = simulate_test_access_sequence(NR, NC, options);
37 auto oracle = create_oracle<use_oracle_>(sequence, options);
38 auto swork = tatami::new_extractor<true, use_oracle_>(&matrix, options.use_row, oracle, args...);
39
41 opt.sparse_ordered_index = false;
42 auto swork_uns = tatami::new_extractor<true, use_oracle_>(&matrix, options.use_row, oracle, args..., opt);
43
44 opt.sparse_extract_index = false;
45 auto swork_uns_v = tatami::new_extractor<true, use_oracle_>(&matrix, options.use_row, oracle, args..., opt);
46
47 opt.sparse_extract_value = false;
48 auto swork_uns_n = tatami::new_extractor<true, use_oracle_>(&matrix, options.use_row, oracle, args..., opt);
49
50 opt.sparse_extract_index = true;
51 auto swork_uns_i = tatami::new_extractor<true, use_oracle_>(&matrix, options.use_row, oracle, args..., opt);
52
53 // Looping over rows/columns and checking extraction for various unsorted combinations.
54 for (auto i : sequence) {
55 auto observed = [&]() {
56 if constexpr(use_oracle_) {
57 return fetch(*swork, extent);
58 } else {
59 return fetch(*swork, i, extent);
60 }
61 }();
62
63 auto observed_uns = [&]() {
64 if constexpr(use_oracle_) {
65 return fetch(*swork_uns, extent);
66 } else {
67 return fetch(*swork_uns, i, extent);
68 }
69 }();
70
71 {
72 // Poor man's zip + unzip.
73 std::vector<std::pair<Index_, Value_> > collected;
74 collected.reserve(observed.value.size());
75 for (Index_ i = 0, end = observed_uns.value.size(); i < end; ++i) {
76 collected.emplace_back(observed_uns.index[i], observed_uns.value[i]);
77 }
78 std::sort(collected.begin(), collected.end());
79
80 std::vector<Value_> sorted_v;
81 std::vector<Index_> sorted_i;
82 sorted_v.reserve(collected.size());
83 sorted_i.reserve(collected.size());
84 for (const auto& p : collected) {
85 sorted_i.push_back(p.first);
86 sorted_v.push_back(p.second);
87 }
88
89 ASSERT_EQ(observed.index, sorted_i);
90 compare_vectors(observed.value, sorted_v, "unsorted sparse");
91 }
92
93 {
94 std::vector<int> indices(extent);
95 auto observed_i = [&]() {
96 if constexpr(use_oracle_) {
97 return swork_uns_i->fetch(NULL, indices.data());
98 } else {
99 return swork_uns_i->fetch(i, NULL, indices.data());
100 }
101 }();
102 ASSERT_TRUE(observed_i.value == NULL);
103
104 tatami::copy_n(observed_i.index, observed_i.number, indices.data());
105 indices.resize(observed_i.number);
106 ASSERT_EQ(observed_uns.index, indices);
107 }
108
109 {
110 std::vector<double> values(extent);
111 auto observed_v = [&]() {
112 if constexpr(use_oracle_) {
113 return swork_uns_v->fetch(values.data(), NULL);
114 } else {
115 return swork_uns_v->fetch(i, values.data(), NULL);
116 }
117 }();
118 ASSERT_TRUE(observed_v.index == NULL);
119
120 tatami::copy_n(observed_v.value, observed_v.number, values.data());
121 values.resize(observed_v.number);
122 compare_vectors(observed_uns.value, values, "unsorted sparse, values only");
123 }
124
125 {
126 auto observed_n = [&]() {
127 if constexpr(use_oracle_) {
128 return swork_uns_n->fetch(NULL, NULL);
129 } else {
130 return swork_uns_n->fetch(i, NULL, NULL);
131 }
132 }();
133 ASSERT_TRUE(observed_n.value == NULL);
134 ASSERT_TRUE(observed_n.index == NULL);
135 ASSERT_EQ(observed.value.size(), observed_n.number);
136 }
137 }
138}
139
140template<bool use_oracle_, typename Value_, typename Index_>
141void test_unsorted_full_access(const tatami::Matrix<Value_, Index_>& matrix, const TestAccessOptions& options) {
142 Index_ nsecondary = (options.use_row ? matrix.ncol() : matrix.nrow());
143 internal::test_unsorted_access_base<use_oracle_>(matrix, options, nsecondary);
144}
145
146template<bool use_oracle_, typename Value_, typename Index_>
147void test_unsorted_block_access(const tatami::Matrix<Value_, Index_>& matrix, double relative_start, double relative_length, const TestAccessOptions& options) {
148 Index_ nsecondary = (options.use_row ? matrix.ncol() : matrix.nrow());
149 Index_ start = nsecondary * relative_start;
150 Index_ length = nsecondary * relative_length;
151 internal::test_unsorted_access_base<use_oracle_>(matrix, options, nsecondary, start, length);
152}
153
154template<bool use_oracle_, typename Value_, typename Index_>
155void test_unsorted_indexed_access(const tatami::Matrix<Value_, Index_>& matrix, double relative_start, double probability, const TestAccessOptions& options) {
156 Index_ nsecondary = (options.use_row ? matrix.ncol() : matrix.nrow());
157 auto index_ptr = create_indexed_subset(
158 nsecondary,
159 relative_start,
160 probability,
161 create_seed(matrix.nrow(), matrix.ncol(), options) + 1001 * probability + 13 * relative_start
162 );
163 Index_ num_indices = index_ptr->size();
164 internal::test_unsorted_access_base<use_oracle_>(matrix, options, num_indices, std::move(index_ptr));
165}
166
167}
184template<typename Value_, typename Index_>
186 if (options.use_oracle) {
187 internal::test_unsorted_full_access<true>(matrix, options);
188 } else {
189 internal::test_unsorted_full_access<false>(matrix, options);
190 }
191}
192
211template<typename Value_, typename Index_>
212void test_unsorted_block_access(const tatami::Matrix<Value_, Index_>& matrix, double relative_start, double relative_length, const TestAccessOptions& options) {
213 if (options.use_oracle) {
214 internal::test_unsorted_block_access<true>(matrix, relative_start, relative_length, options);
215 } else {
216 internal::test_unsorted_block_access<false>(matrix, relative_start, relative_length, options);
217 }
218}
219
238template<typename Value_, typename Index_>
239void test_unsorted_indexed_access(const tatami::Matrix<Value_, Index_>& matrix, double relative_start, double probability, const TestAccessOptions& options) {
240 if (options.use_oracle) {
241 internal::test_unsorted_indexed_access<true>(matrix, relative_start, probability, options);
242 } else {
243 internal::test_unsorted_indexed_access<false>(matrix, relative_start, probability, options);
244 }
245}
246
247}
248
249#endif
virtual Index_ ncol() const=0
virtual Index_ nrow() const=0
Create an indexed subset of dimension elements.
Fetch a row/column into a vector.
Utilities for testing tatami libraries.
Definition create_indexed_subset.hpp:15
void test_unsorted_full_access(const tatami::Matrix< Value_, Index_ > &matrix, const TestAccessOptions &options)
Definition test_unsorted_access.hpp:185
void test_unsorted_block_access(const tatami::Matrix< Value_, Index_ > &matrix, double relative_start, double relative_length, const TestAccessOptions &options)
Definition test_unsorted_access.hpp:212
void test_unsorted_indexed_access(const tatami::Matrix< Value_, Index_ > &matrix, double relative_start, double probability, const TestAccessOptions &options)
Definition test_unsorted_access.hpp:239
tatami::VectorPtr< Index_ > create_indexed_subset(Index_ extent, double relative_start, double probability, uint64_t seed)
Definition create_indexed_subset.hpp:35
std::vector< Value_ > fetch(tatami::MyopicDenseExtractor< Value_, Index_ > &ext, Index_ i, size_t number)
Definition fetch.hpp:46
Value_ * copy_n(const Value_ *input, Size_ n, Value_ *output)
bool sparse_extract_index
bool sparse_ordered_index
bool sparse_extract_value
Options for test_full_access() and friends.
Definition test_access.hpp:39
bool use_oracle
Definition test_access.hpp:43
Test access patterns on a tatami::Matrix.