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
6#include <vector>
7#include <limits>
8#include <random>
9#include <cmath>
10
14
16#include "test_access.hpp"
17
23namespace tatami_test {
24
28namespace internal {
29
30template<bool use_oracle_, typename Value_, typename Index_, typename ...Args_>
31void test_unsorted_access_base(const tatami::Matrix<Value_, Index_>& matrix, const TestAccessOptions& options, const Index_ extent, Args_... args) {
32 const auto NR = matrix.nrow();
33 const auto NC = matrix.ncol();
34
35 auto sequence = simulate_test_access_sequence(NR, NC, options);
36 auto oracle = create_oracle<use_oracle_>(sequence, options);
37 auto swork = tatami::new_extractor<true, use_oracle_>(&matrix, options.use_row, oracle, args...);
38
40 opt.sparse_ordered_index = false;
41 auto swork_uns = tatami::new_extractor<true, use_oracle_>(&matrix, options.use_row, oracle, args..., opt);
42 opt.sparse_extract_index = false;
43 auto swork_uns_v = tatami::new_extractor<true, use_oracle_>(&matrix, options.use_row, oracle, args..., opt);
44 opt.sparse_extract_value = false;
45 auto swork_uns_n = tatami::new_extractor<true, use_oracle_>(&matrix, options.use_row, oracle, args..., opt);
46 opt.sparse_extract_index = true;
47 auto swork_uns_i = tatami::new_extractor<true, use_oracle_>(&matrix, options.use_row, oracle, args..., opt);
48
49 sanisizer::as_size_type<std::vector<Value_> >(extent);
50 std::vector<Value_> mat_vbuffer(extent), mat_vstore1(extent), mat_vstore2(extent);
51 sanisizer::as_size_type<std::vector<Index_> >(extent);
52 std::vector<Index_> mat_ibuffer(extent), mat_istore1(extent), mat_istore2(extent);
53
54 std::vector<std::pair<Index_, Value_> > collected;
55 std::vector<Value_> sorted_v;
56 std::vector<Index_> sorted_i;
57
58 for (const auto i : sequence) {
59 // Regular sparse retrieval.
60 {
61 std::fill(mat_ibuffer.begin(), mat_ibuffer.end(), 0);
62 std::fill(mat_vbuffer.begin(), mat_vbuffer.end(), 0);
63 const auto vbuf = mat_vbuffer.data();
64 const auto ibuf = mat_ibuffer.data();
65
66 auto observed = [&]() {
67 if constexpr(use_oracle_) {
68 return swork->fetch(vbuf, ibuf);
69 } else {
70 return swork->fetch(Fix(i), vbuf, ibuf);
71 }
72 }();
73
74 mat_vstore1.clear();
75 mat_vstore1.insert(mat_vstore1.end(), observed.value, observed.value + observed.number);
76 mat_istore1.clear();
77 mat_istore1.insert(mat_istore1.end(), observed.index, observed.index + observed.number);
78 }
79
80 // Unsorted sparse retrieval with both values and indices.
81 {
82 std::fill(mat_ibuffer.begin(), mat_ibuffer.end(), 0);
83 std::fill(mat_vbuffer.begin(), mat_vbuffer.end(), 0);
84 const auto vbuf = mat_vbuffer.data();
85 const auto ibuf = mat_ibuffer.data();
86
87 auto observed_uns = [&]() {
88 if constexpr(use_oracle_) {
89 return swork_uns->fetch(vbuf, ibuf);
90 } else {
91 return swork_uns->fetch(Fix(i), vbuf, ibuf);
92 }
93 }();
94
95 // Poor man's zip + unzip with sorting.
96 collected.clear();
97 for (I<decltype(observed_uns.number)> i = 0; i < observed_uns.number; ++i) {
98 collected.emplace_back(observed_uns.index[i], observed_uns.value[i]);
99 }
100 std::sort(collected.begin(), collected.end());
101 sorted_i.clear();
102 sorted_v.clear();
103 for (const auto& p : collected) {
104 sorted_i.push_back(p.first);
105 sorted_v.push_back(p.second);
106 }
107 ASSERT_EQ(mat_istore1, sorted_i);
108 compare_vectors(mat_vstore1, sorted_v, "unsorted sparse");
109
110 mat_vstore1.clear();
111 mat_vstore1.insert(mat_vstore1.end(), observed_uns.value, observed_uns.value + observed_uns.number);
112 mat_istore1.clear();
113 mat_istore1.insert(mat_istore1.end(), observed_uns.index, observed_uns.index + observed_uns.number);
114 }
115
116 // Unsorted sparse retrieval with indices.
117 {
118 std::fill(mat_ibuffer.begin(), mat_ibuffer.end(), 0);
119 const auto ibuf = mat_ibuffer.data();
120
121 auto observed_i = [&]() {
122 if constexpr(use_oracle_) {
123 return swork_uns_i->fetch(NULL, ibuf);
124 } else {
125 return swork_uns_i->fetch(Fix(i), NULL, ibuf);
126 }
127 }();
128
129 ASSERT_TRUE(observed_i.value == NULL);
130 mat_istore2.clear();
131 mat_istore2.insert(mat_istore2.end(), observed_i.index, observed_i.index + observed_i.number);
132 ASSERT_EQ(mat_istore1, mat_istore2);
133 }
134
135 // Unsorted sparse retrieval with values.
136 {
137 std::fill(mat_vbuffer.begin(), mat_vbuffer.end(), 0);
138 const auto vbuf = mat_vbuffer.data();
139
140 auto observed_v = [&]() {
141 if constexpr(use_oracle_) {
142 return swork_uns_v->fetch(vbuf, NULL);
143 } else {
144 return swork_uns_v->fetch(Fix(i), vbuf, NULL);
145 }
146 }();
147
148 ASSERT_TRUE(observed_v.index == NULL);
149 mat_vstore2.clear();
150 mat_vstore2.insert(mat_vstore2.end(), observed_v.value, observed_v.value + observed_v.number);
151 compare_vectors(mat_vstore1, mat_vstore2, "unsorted sparse, values only");
152 }
153
154 {
155 auto observed_n = [&]() {
156 if constexpr(use_oracle_) {
157 return swork_uns_n->fetch(NULL, NULL);
158 } else {
159 return swork_uns_n->fetch(Fix(i), NULL, NULL);
160 }
161 }();
162
163 ASSERT_TRUE(observed_n.value == NULL);
164 ASSERT_TRUE(observed_n.index == NULL);
165 ASSERT_EQ(mat_vstore1.size(), observed_n.number);
166 }
167 }
168}
169
170template<bool use_oracle_, typename Value_, typename Index_>
171void test_unsorted_full_access(const tatami::Matrix<Value_, Index_>& matrix, const TestAccessOptions& options) {
172 const Index_ nsecondary = (options.use_row ? matrix.ncol() : matrix.nrow());
173 internal::test_unsorted_access_base<use_oracle_>(matrix, options, nsecondary);
174}
175
176template<bool use_oracle_, typename Value_, typename Index_>
177void test_unsorted_block_access(const tatami::Matrix<Value_, Index_>& matrix, double relative_start, double relative_length, const TestAccessOptions& options) {
178 const Index_ nsecondary = (options.use_row ? matrix.ncol() : matrix.nrow());
179 const Index_ start = nsecondary * relative_start;
180 const Index_ length = nsecondary * relative_length;
181 internal::test_unsorted_access_base<use_oracle_>(matrix, options, nsecondary, start, length);
182}
183
184template<bool use_oracle_, typename Value_, typename Index_>
185void test_unsorted_indexed_access(const tatami::Matrix<Value_, Index_>& matrix, double relative_start, double probability, const TestAccessOptions& options) {
186 const Index_ nsecondary = (options.use_row ? matrix.ncol() : matrix.nrow());
187 auto index_ptr = create_indexed_subset(
188 nsecondary,
189 relative_start,
190 probability,
191 static_cast<SeedType>(
192 create_seed(matrix.nrow(), matrix.ncol(), options)
193 + static_cast<SeedType>(1001 * probability)
194 + static_cast<SeedType>(13 * relative_start)
195 )
196 );
197 const Index_ num_indices = index_ptr->size();
198 internal::test_unsorted_access_base<use_oracle_>(matrix, options, num_indices, std::move(index_ptr));
199}
200
201}
218template<typename Value_, typename Index_>
220 if (options.use_oracle) {
221 internal::test_unsorted_full_access<true>(matrix, options);
222 } else {
223 internal::test_unsorted_full_access<false>(matrix, options);
224 }
225}
226
245template<typename Value_, typename Index_>
246void test_unsorted_block_access(const tatami::Matrix<Value_, Index_>& matrix, double relative_start, double relative_length, const TestAccessOptions& options) {
247 if (options.use_oracle) {
248 internal::test_unsorted_block_access<true>(matrix, relative_start, relative_length, options);
249 } else {
250 internal::test_unsorted_block_access<false>(matrix, relative_start, relative_length, options);
251 }
252}
253
272template<typename Value_, typename Index_>
273void test_unsorted_indexed_access(const tatami::Matrix<Value_, Index_>& matrix, double relative_start, double probability, const TestAccessOptions& options) {
274 if (options.use_oracle) {
275 internal::test_unsorted_indexed_access<true>(matrix, relative_start, probability, options);
276 } else {
277 internal::test_unsorted_indexed_access<false>(matrix, relative_start, probability, options);
278 }
279}
280
281}
282
283#endif
virtual Index_ ncol() const=0
virtual Index_ nrow() const=0
Create an indexed subset of dimension elements.
Utilities for testing tatami libraries.
Definition create_indexed_subset.hpp:16
void test_unsorted_full_access(const tatami::Matrix< Value_, Index_ > &matrix, const TestAccessOptions &options)
Definition test_unsorted_access.hpp:219
tatami::VectorPtr< Index_ > create_indexed_subset(const Index_ extent, const double relative_start, const double probability, const SeedType seed)
Definition create_indexed_subset.hpp:36
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:246
RngEngine::result_type SeedType
Definition utils.hpp:39
void test_unsorted_indexed_access(const tatami::Matrix< Value_, Index_ > &matrix, double relative_start, double probability, const TestAccessOptions &options)
Definition test_unsorted_access.hpp:273
auto new_extractor(const Matrix< Value_, Index_ > &matrix, const bool row, MaybeOracle< oracle_, Index_ > oracle, Args_ &&... args)
bool sparse_extract_index
bool sparse_ordered_index
bool sparse_extract_value
Options for test_full_access() and friends.
Definition test_access.hpp:40
bool use_oracle
Definition test_access.hpp:44
Test access patterns on a tatami::Matrix.