Browse code

Cleaned up doxygen tags, documented leftover classes. Added mainpage with a link back to the BioC landing page.

LTLA authored on 21/09/2020 06:42:57
Showing1 changed files
... ...
@@ -12,11 +12,16 @@
12 12
 #include "Csparse_reader.h"
13 13
 #include "utils.h"
14 14
 
15
+#include <memory>
16
+#include <algorithm>
17
+
15 18
 namespace beachmat {
16 19
 
17 20
 /**
18 21
  * @brief Virtual base class for a logical, integer or numeric (i.e., double-precision) matrix,
19
- * providing methods to extract rows or columns in dense form.
22
+ *
23
+ * This provides methods to extract rows or columns in dense form.
24
+ * We suggest using the `read_lin_block()` function to construct instances of this class.
20 25
  */
21 26
 class lin_matrix {
22 27
 public:
... ...
@@ -32,28 +37,28 @@ public:
32 37
     lin_matrix& operator=(lin_matrix&&) = default;
33 38
 
34 39
     /**
35
-     * Extract a column as an array of integers.
40
+     * Extract values from a column as an array of integers, restricted to a contiguous subset of rows.
36 41
      *
37 42
      * @param c Index of the column of interest.
38 43
      * @param work The workspace, potentially used to store extracted values.
39 44
      * This should have at least `last - first` addressable elements.
40 45
      * @param first The index of the first row of interest.
41
-     * @param last The index of the first row of that is _not_ of interest.
46
+     * @param last The index of one-past-the-last row of interest.
42 47
      *
43 48
      * @return A pointer is returned to the values of `c` as integers, starting at the `first` element.
44 49
      * This may or may not involve populating `work` with values copied from the underlying matrix;
45
-     * a copy will have been performed if the return value compares equal to `work`.
50
+     * a copy will have been performed iff the return value compares equal to `work`.
46 51
      */
47 52
     virtual const int* get_col(size_t c, int* work, size_t first, size_t last) = 0;
48 53
 
49 54
     /**
50
-     * Extract a row as an array of integers.
55
+     * Extract values from a row as an array of integers, restricted to a contiguous subset of columns.
51 56
      *
52 57
      * @param r Index of the row of interest.
53 58
      * @param work The workspace, potentially used to store extracted values.
54 59
      * This should have at least `last - first` addressable elements.
55 60
      * @param first The index of the first column of interest.
56
-     * @param last The index of the first column of that is _not_ of interest.
61
+     * @param last The index of one-past-the-last column of interest.
57 62
      *
58 63
      * @return A pointer is returned to the values of `r` as integers, starting at the `first` element.
59 64
      * This involves creating a copy in the workspace so the return value is always equal to `work`.
... ...
@@ -61,28 +66,28 @@ public:
61 66
     virtual const int* get_row(size_t r, int* work, size_t first, size_t last) = 0;
62 67
 
63 68
     /**
64
-     * Extract a column as an array of doubles.
69
+     * Extract values from a column as an array of doubles, restricted to a contiguous subset of rows.
65 70
      *
66 71
      * @param c Index of the column of interest.
67 72
      * @param work The workspace, potentially used to store extracted values.
68 73
      * This should have at least `last - first` addressable elements.
69 74
      * @param first The index of the first row of interest.
70
-     * @param last The index of the first row of that is _not_ of interest.
75
+     * @param last The index of one-past-the-last row of interest.
71 76
      *
72 77
      * @return A pointer is returned to the values of `c` as doubles, starting at the `first` element.
73 78
      * This may or may not involve populating `work` with values copied from the underlying matrix;
74
-     * a copy will have been performed if the return value compares equal to `work`.
79
+     * a copy will have been performed iff the return value compares equal to `work`.
75 80
      */
76 81
     virtual const double* get_col(size_t c, double* work, size_t first, size_t last) = 0;
77 82
 
78 83
     /**
79
-     * Extract a row as an array of doubles.
84
+     * Extract values from a row as an array of doubles, restricted to a contiguous subset of columns.
80 85
      *
81 86
      * @param r Index of the row of interest.
82 87
      * @param work The workspace, potentially used to store extracted values.
83 88
      * This should have at least `last - first` addressable elements.
84 89
      * @param first The index of the first column of interest.
85
-     * @param last The index of the first column of that is _not_ of interest.
90
+     * @param last The index of one-past-the-last column of interest.
86 91
      *
87 92
      * @return A pointer is returned to the values of `r` as doubles, starting at the `first` element.
88 93
      * This involves creating a copy in the workspace so the return value is always equal to `work`.
... ...
@@ -90,7 +95,7 @@ public:
90 95
     virtual const double* get_row(size_t r, double* work, size_t first, size_t last) = 0;
91 96
 
92 97
     /**
93
-     * Extract a column as an array of integers.
98
+     * Extract values from a column as an array of integers.
94 99
      *
95 100
      * @param c Index of the column of interest.
96 101
      * @param work The workspace, potentially used to store extracted values.
... ...
@@ -98,14 +103,14 @@ public:
98 103
      *
99 104
      * @return A pointer is returned to the values of `c` as integers, starting at the first element.
100 105
      * This may or may not involve populating `work` with values copied from the underlying matrix;
101
-     * a copy will have been performed if the return value compares equal to `work`.
106
+     * a copy will have been performed iff the return value compares equal to `work`.
102 107
      */
103 108
     const int* get_col(size_t c, int* work) {
104 109
         return get_col(c, work, 0, nrow);
105 110
     }
106 111
 
107 112
     /**
108
-     * Extract a row as an array of integers.
113
+     * Extract values from a row as an array of integers.
109 114
      *
110 115
      * @param r Index of the column of interest.
111 116
      * @param work The workspace, potentially used to store extracted values.
... ...
@@ -119,7 +124,7 @@ public:
119 124
     }
120 125
 
121 126
     /**
122
-     * Extract a column as an array of doubles.
127
+     * Extract values from a column as an array of doubles.
123 128
      *
124 129
      * @param c Index of the column of interest.
125 130
      * @param work The workspace, potentially used to store extracted values.
... ...
@@ -127,14 +132,14 @@ public:
127 132
      *
128 133
      * @return A pointer is returned to the values of `c` as doubles, starting at the first element.
129 134
      * This may or may not involve populating `work` with values copied from the underlying matrix;
130
-     * a copy will have been performed if the return value compares equal to `work`.
135
+     * a copy will have been performed iff the return value compares equal to `work`.
131 136
      */
132 137
     const double* get_col(size_t c, double* work) {
133 138
         return get_col(c, work, 0, nrow);
134 139
     }
135 140
 
136 141
     /**
137
-     * Extract a row as an array of doubles.
142
+     * Extract values from a row as an array of doubles.
138 143
      *
139 144
      * @param r Index of the column of interest.
140 145
      * @param work The workspace, potentially used to store extracted values.
... ...
@@ -176,8 +181,10 @@ protected:
176 181
 };
177 182
 
178 183
 /**
179
- * @brief Virtual base class for a sparse logical, integer or numeric (i.e., double-precision) matrix,
180
- * providing methods to extract rows or columns in dense or sparse form.
184
+ * @brief Virtual base class for a sparse logical, integer or numeric (i.e., double-precision) matrix.
185
+ *
186
+ * This provides methods to extract rows or columns in dense or sparse form.
187
+ * We suggest using the `read_lin_sparse_block()` function to construct instances of this class.
181 188
  */
182 189
 class lin_sparse_matrix : public lin_matrix {
183 190
 public:
... ...
@@ -193,7 +200,8 @@ public:
193 200
     lin_sparse_matrix& operator=(lin_sparse_matrix&&) = default;
194 201
 
195 202
     /**
196
-     * Extract all non-zero elements in a row, storing values as integers.
203
+     * Extract all non-zero elements in a row, restricted to a contiguous subset of columns.
204
+     * Values are returned as integers.
197 205
      *
198 206
      * @param r Index of the row of interest.
199 207
      * @param work_x The workspace for extracted non-zero values.
... ...
@@ -201,16 +209,17 @@ public:
201 209
      * @param work_i The workspace for column indices.
202 210
      * This should have at least `last - first` addressable elements.
203 211
      * @param first The index of the first column of interest.
204
-     * @param last The index of the first column of that is _not_ of interest.
212
+     * @param last The index of one-past-the-last column of interest.
205 213
      *
206
-     * @return A `sparse_index` is returned containing pointers to the workspace,
214
+     * @return A `sparse_index` is returned containing pointers to the workspaces,
207 215
      * containing non-zero elements in `r` with column indices in `[first, last)`.
208
-     * A copy of non-zero values and their indices is always performed into the workspace.
216
+     * A copy of non-zero values and their indices is always performed into the workspaces.
209 217
      */
210 218
     virtual sparse_index<const int*, int> get_row(size_t r, int* work_x, int* work_i, size_t first, size_t last) = 0;
211 219
 
212 220
     /**
213
-     * Extract all non-zero elements in a column, storing values as integers.
221
+     * Extract all non-zero elements in a column, restricted to a contiguous subset of rows.
222
+     * Values are returned as integers.
214 223
      *
215 224
      * @param r Index of the column of interest.
216 225
      * @param work_x The workspace for extracted non-zero values.
... ...
@@ -218,16 +227,17 @@ public:
218 227
      * @param work_i The workspace for column indices.
219 228
      * This should have at least `last - first` addressable elements.
220 229
      * @param first The index of the first row of interest.
221
-     * @param last The index of the first row of that is _not_ of interest.
230
+     * @param last The index of one-past-the-last row of interest.
222 231
      *
223 232
      * @return A `sparse_index` is returned containing pointers to non-zero elements in `c` with row indices in `[first, last)`.
224 233
      * This may or may not involve populating `work` with values copied from the underlying matrix;
225
-     * a copy will have been performed if the return value's pointers compare equal to `work_x` and `work_i`.
234
+     * a copy will have been performed iff the return value's pointers compare equal to `work_x` and `work_i`.
226 235
      */
227 236
     virtual sparse_index<const int*, int> get_col(size_t c, int* work_x, int* work_i, size_t first, size_t last) = 0;
228 237
 
229 238
     /**
230
-     * Extract all non-zero elements in a row, storing values as doubles.
239
+     * Extract all non-zero elements in a row, restricted to a contiguous subset of columns.
240
+     * Values are returned as doubles.
231 241
      *
232 242
      * @param r Index of the row of interest.
233 243
      * @param work_x The workspace for extracted non-zero values.
... ...
@@ -235,16 +245,17 @@ public:
235 245
      * @param work_i The workspace for column indices.
236 246
      * This should have at least `last - first` addressable elements.
237 247
      * @param first The index of the first column of interest.
238
-     * @param last The index of the first column of that is _not_ of interest.
248
+     * @param last The index of one-past-the-last column of interest.
239 249
      *
240
-     * @return A `sparse_index` is returned containing pointers to the workspace.
250
+     * @return A `sparse_index` is returned containing pointers to the workspaces.
241 251
      * containing non-zero elements in `r` with column indices in `[first, last)`.
242
-     * A copy of non-zero values and their indices is always performed into the workspace.
252
+     * A copy of non-zero values and their indices is always performed into the workspaces.
243 253
      */
244 254
     virtual sparse_index<const double*, int> get_row(size_t r, double* work_x, int* work_i, size_t first, size_t last) = 0;
245 255
 
246 256
     /**
247
-     * Extract all non-zero elements in a column, storing values as doubles.
257
+     * Extract all non-zero elements in a column, restricted to a contiguous subset of rows.
258
+     * Values are returned as doubles.
248 259
      *
249 260
      * @param r Index of the column of interest.
250 261
      * @param work_x The workspace for extracted non-zero values.
... ...
@@ -252,11 +263,11 @@ public:
252 263
      * @param work_i The workspace for column indices.
253 264
      * This should have at least `last - first` addressable elements.
254 265
      * @param first The index of the first row of interest.
255
-     * @param last The index of the first row of that is _not_ of interest.
266
+     * @param last The index of one-past-the-last row of interest.
256 267
      *
257 268
      * @return A `sparse_index` is returned containing pointers to non-zero elements in `c` with row indices in `[first, last)`.
258 269
      * This may or may not involve populating `work` with values copied from the underlying matrix;
259
-     * a copy will have been performed if the return value's pointers compare equal to `work_x` and `work_i`.
270
+     * a copy will have been performed iff the return value's pointers compare equal to `work_x` and `work_i`.
260 271
      */
261 272
     virtual sparse_index<const double*, int> get_col(size_t c, double* work_x, int* work_i, size_t first, size_t last) = 0;
262 273
 
... ...
@@ -271,7 +282,7 @@ public:
271 282
      *
272 283
      * @return A `sparse_index` is returned containing pointers to all non-zero elements in `c`.
273 284
      * This may or may not involve populating `work` with values copied from the underlying matrix;
274
-     * a copy will have been performed if the return value's pointers compare equal to `work_x` and `work_i`.
285
+     * a copy will have been performed iff the return value's pointers compare equal to `work_x` and `work_i`.
275 286
      */
276 287
     sparse_index<const int*, int> get_col(size_t c, int* work_x, int* work_i) {
277 288
         return get_col(c, work_x, work_i, 0, this->nrow);
... ...
@@ -286,9 +297,9 @@ public:
286 297
      * @param work_i The workspace for column indices.
287 298
      * This should have at least `last - first` addressable elements.
288 299
      *
289
-     * @return A `sparse_index` is returned containing pointers to the workspace,
300
+     * @return A `sparse_index` is returned containing pointers to the workspaces,
290 301
      * containing all non-zero elements in `r`.
291
-     * A copy of non-zero values and their indices is always performed into the workspace.
302
+     * A copy of non-zero values and their indices is always performed into the workspaces.
292 303
      */
293 304
     sparse_index<const int*, int> get_row(size_t r, int* work_x, int* work_i) {
294 305
         return get_row(r, work_x, work_i, 0, this->ncol);
... ...
@@ -305,7 +316,7 @@ public:
305 316
      *
306 317
      * @return A `sparse_index` is returned containing pointers to all non-zero elements in `c`.
307 318
      * This may or may not involve populating `work` with values copied from the underlying matrix;
308
-     * a copy will have been performed if the return value's pointers compare equal to `work_x` and `work_i`.
319
+     * a copy will have been performed iff the return value's pointers compare equal to `work_x` and `work_i`,
309 320
      */
310 321
     sparse_index<const double*, int> get_col(size_t c, double* work_x, int* work_i) {
311 322
         return get_col(c, work_x, work_i, 0, this->nrow);
... ...
@@ -322,7 +333,7 @@ public:
322 333
      *
323 334
      * @return A `sparse_index` is returned containing pointers to the workspace,
324 335
      * containing all non-zero elements in `r`.
325
-     * A copy of non-zero values and their indices is always performed into the workspace.
336
+     * A copy of non-zero values and their indices is always performed into the workspaces.
326 337
      */
327 338
     sparse_index<const double*, int> get_row(size_t r, double* work_x, int* work_i) {
328 339
         return get_row(r, work_x, work_i, 0, this->ncol);
... ...
@@ -348,6 +359,9 @@ protected:
348 359
 /**
349 360
  * @brief Logical, integer or numeric matrices in the "ordinary" R format, i.e., column-major dense arrays.
350 361
  *
362
+ * It is unlikely that this class will be constructed directly by users;
363
+ * most applications will use `read_lin_block()` instead.
364
+ *
351 365
  * @tparam V The class of the `Rcpp::Vector` holding the R-level data.
352 366
  */
353 367
 template <class V>
... ...
@@ -436,6 +450,9 @@ inline const double* double_ordinary_matrix::get_col(size_t c, double* work, siz
436 450
 /**
437 451
  * @brief Sparse logical or numeric matrices in the `lgCMatrix` or `dgCMatrix` format, respectively, from the **Matrix** package.
438 452
  *
453
+ * It is unlikely that this class will be constructed directly by users;
454
+ * most applications will use `read_lin_block()` or `read_lin_sparse_block()` instead.
455
+ *
439 456
  * @tparam V The class of the `Rcpp::Vector` holding the R-level data for non-zero values.
440 457
  */
441 458
 template <class V, typename TIT>
... ...
@@ -528,6 +545,9 @@ inline sparse_index<const double*, int> dgCMatrix::get_col(size_t c, double* wor
528 545
 /**
529 546
  * @brief Sparse integer, logical or numeric matrices in the `SparseArraySeed` format from the **DelayedArray** package.
530 547
  *
548
+ * It is unlikely that this class will be constructed directly by users;
549
+ * most applications will use `read_lin_block()` or `read_lin_sparse_block()` instead.
550
+ *
531 551
  * @tparam V The class of the `Rcpp::Vector` holding the R-level data for non-zero values.
532 552
  */
533 553
 template <class V, typename TIT>
Browse code

Added version 3 of the beachmat C++ API (with tests).

- Streamlined to focus on DelayedArray block processing structures,
reduce compilation size and time, code complexity.
- Provided all-LIN class to avoid need for user-side templating.
- Improved ease of sparse-specific read/write operations.
- Added doxygen for user-exposed C++ functions.
- Added another dedicated test package.

Aaron Lun authored on 19/09/2020 07:44:10 • GitHub committed on 19/09/2020 07:44:10
Showing1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,637 @@
1
+#ifndef BEACHMAT_LIN_MATRIX_H
2
+#define BEACHMAT_LIN_MATRIX_H
3
+
4
+/**
5
+ * @file lin_matrix.h
6
+ *
7
+ * Class definitions for the logical, integer or numeric (LIN) matrix.
8
+ */
9
+
10
+#include "Rcpp.h"
11
+#include "ordinary_reader.h"
12
+#include "Csparse_reader.h"
13
+#include "utils.h"
14
+
15
+namespace beachmat {
16
+
17
+/**
18
+ * @brief Virtual base class for a logical, integer or numeric (i.e., double-precision) matrix,
19
+ * providing methods to extract rows or columns in dense form.
20
+ */
21
+class lin_matrix {
22
+public:
23
+    /**
24
+     * Trivial constructor.
25
+     */
26
+    lin_matrix() {}
27
+
28
+    virtual ~lin_matrix() = default;
29
+    lin_matrix(const lin_matrix&) = default;
30
+    lin_matrix& operator=(const lin_matrix&) = default;
31
+    lin_matrix(lin_matrix&&) = default;
32
+    lin_matrix& operator=(lin_matrix&&) = default;
33
+
34
+    /**
35
+     * Extract a column as an array of integers.
36
+     *
37
+     * @param c Index of the column of interest.
38
+     * @param work The workspace, potentially used to store extracted values.
39
+     * This should have at least `last - first` addressable elements.
40
+     * @param first The index of the first row of interest.
41
+     * @param last The index of the first row of that is _not_ of interest.
42
+     *
43
+     * @return A pointer is returned to the values of `c` as integers, starting at the `first` element.
44
+     * This may or may not involve populating `work` with values copied from the underlying matrix;
45
+     * a copy will have been performed if the return value compares equal to `work`.
46
+     */
47
+    virtual const int* get_col(size_t c, int* work, size_t first, size_t last) = 0;
48
+
49
+    /**
50
+     * Extract a row as an array of integers.
51
+     *
52
+     * @param r Index of the row of interest.
53
+     * @param work The workspace, potentially used to store extracted values.
54
+     * This should have at least `last - first` addressable elements.
55
+     * @param first The index of the first column of interest.
56
+     * @param last The index of the first column of that is _not_ of interest.
57
+     *
58
+     * @return A pointer is returned to the values of `r` as integers, starting at the `first` element.
59
+     * This involves creating a copy in the workspace so the return value is always equal to `work`.
60
+     */
61
+    virtual const int* get_row(size_t r, int* work, size_t first, size_t last) = 0;
62
+
63
+    /**
64
+     * Extract a column as an array of doubles.
65
+     *
66
+     * @param c Index of the column of interest.
67
+     * @param work The workspace, potentially used to store extracted values.
68
+     * This should have at least `last - first` addressable elements.
69
+     * @param first The index of the first row of interest.
70
+     * @param last The index of the first row of that is _not_ of interest.
71
+     *
72
+     * @return A pointer is returned to the values of `c` as doubles, starting at the `first` element.
73
+     * This may or may not involve populating `work` with values copied from the underlying matrix;
74
+     * a copy will have been performed if the return value compares equal to `work`.
75
+     */
76
+    virtual const double* get_col(size_t c, double* work, size_t first, size_t last) = 0;
77
+
78
+    /**
79
+     * Extract a row as an array of doubles.
80
+     *
81
+     * @param r Index of the row of interest.
82
+     * @param work The workspace, potentially used to store extracted values.
83
+     * This should have at least `last - first` addressable elements.
84
+     * @param first The index of the first column of interest.
85
+     * @param last The index of the first column of that is _not_ of interest.
86
+     *
87
+     * @return A pointer is returned to the values of `r` as doubles, starting at the `first` element.
88
+     * This involves creating a copy in the workspace so the return value is always equal to `work`.
89
+     */
90
+    virtual const double* get_row(size_t r, double* work, size_t first, size_t last) = 0;
91
+
92
+    /**
93
+     * Extract a column as an array of integers.
94
+     *
95
+     * @param c Index of the column of interest.
96
+     * @param work The workspace, potentially used to store extracted values.
97
+     * This should have at least `last - first` addressable elements.
98
+     *
99
+     * @return A pointer is returned to the values of `c` as integers, starting at the first element.
100
+     * This may or may not involve populating `work` with values copied from the underlying matrix;
101
+     * a copy will have been performed if the return value compares equal to `work`.
102
+     */
103
+    const int* get_col(size_t c, int* work) {
104
+        return get_col(c, work, 0, nrow);
105
+    }
106
+
107
+    /**
108
+     * Extract a row as an array of integers.
109
+     *
110
+     * @param r Index of the column of interest.
111
+     * @param work The workspace, potentially used to store extracted values.
112
+     * This should have at least `last - first` addressable elements.
113
+     *
114
+     * @return A pointer is returned to the values of `r` as integers, starting at the first element.
115
+     * This involves creating a copy in the workspace so the return value is always equal to `work`.
116
+     */
117
+    const int* get_row(size_t r, int* work) {
118
+        return get_row(r, work, 0, ncol);        
119
+    }
120
+
121
+    /**
122
+     * Extract a column as an array of doubles.
123
+     *
124
+     * @param c Index of the column of interest.
125
+     * @param work The workspace, potentially used to store extracted values.
126
+     * This should have at least `last - first` addressable elements.
127
+     *
128
+     * @return A pointer is returned to the values of `c` as doubles, starting at the first element.
129
+     * This may or may not involve populating `work` with values copied from the underlying matrix;
130
+     * a copy will have been performed if the return value compares equal to `work`.
131
+     */
132
+    const double* get_col(size_t c, double* work) {
133
+        return get_col(c, work, 0, nrow);
134
+    }
135
+
136
+    /**
137
+     * Extract a row as an array of doubles.
138
+     *
139
+     * @param r Index of the column of interest.
140
+     * @param work The workspace, potentially used to store extracted values.
141
+     * This should have at least `last - first` addressable elements.
142
+     *
143
+     * @return A pointer is returned to the values of `r` as doubles, starting at the first element.
144
+     * This involves creating a copy in the workspace so the return value is always equal to `work`.
145
+     */
146
+    const double* get_row(size_t r, double* work) {
147
+        return get_row(r, work, 0, ncol);        
148
+    }
149
+
150
+    /**
151
+     * Get the number of rows in the matrix.
152
+     */
153
+    size_t get_nrow() const { return nrow; }
154
+
155
+    /**
156
+     * Get the number of columns in the matrix.
157
+     */
158
+    size_t get_ncol() const { return ncol; }
159
+
160
+    /**
161
+     * Is the matrix sparse?
162
+     */
163
+    virtual bool is_sparse() const { return false; }
164
+
165
+    /**
166
+     * Clone the current object, returning a pointer to a copy.
167
+     */
168
+    std::unique_ptr<lin_matrix> clone() const {
169
+        return std::unique_ptr<lin_matrix>(this->clone_internal());
170
+    }
171
+
172
+protected:
173
+    size_t nrow=0, ncol=0;
174
+
175
+    virtual lin_matrix* clone_internal() const = 0;
176
+};
177
+
178
+/**
179
+ * @brief Virtual base class for a sparse logical, integer or numeric (i.e., double-precision) matrix,
180
+ * providing methods to extract rows or columns in dense or sparse form.
181
+ */
182
+class lin_sparse_matrix : public lin_matrix {
183
+public:
184
+    /**
185
+     * Trivial constructor.
186
+     */
187
+    lin_sparse_matrix() {}
188
+
189
+    ~lin_sparse_matrix() = default;
190
+    lin_sparse_matrix(const lin_sparse_matrix&) = default;
191
+    lin_sparse_matrix& operator=(const lin_sparse_matrix&) = default;
192
+    lin_sparse_matrix(lin_sparse_matrix&&) = default;
193
+    lin_sparse_matrix& operator=(lin_sparse_matrix&&) = default;
194
+
195
+    /**
196
+     * Extract all non-zero elements in a row, storing values as integers.
197
+     *
198
+     * @param r Index of the row of interest.
199
+     * @param work_x The workspace for extracted non-zero values.
200
+     * This should have at least `last - first` addressable elements.
201
+     * @param work_i The workspace for column indices.
202
+     * This should have at least `last - first` addressable elements.
203
+     * @param first The index of the first column of interest.
204
+     * @param last The index of the first column of that is _not_ of interest.
205
+     *
206
+     * @return A `sparse_index` is returned containing pointers to the workspace,
207
+     * containing non-zero elements in `r` with column indices in `[first, last)`.
208
+     * A copy of non-zero values and their indices is always performed into the workspace.
209
+     */
210
+    virtual sparse_index<const int*, int> get_row(size_t r, int* work_x, int* work_i, size_t first, size_t last) = 0;
211
+
212
+    /**
213
+     * Extract all non-zero elements in a column, storing values as integers.
214
+     *
215
+     * @param r Index of the column of interest.
216
+     * @param work_x The workspace for extracted non-zero values.
217
+     * This should have at least `last - first` addressable elements.
218
+     * @param work_i The workspace for column indices.
219
+     * This should have at least `last - first` addressable elements.
220
+     * @param first The index of the first row of interest.
221
+     * @param last The index of the first row of that is _not_ of interest.
222
+     *
223
+     * @return A `sparse_index` is returned containing pointers to non-zero elements in `c` with row indices in `[first, last)`.
224
+     * This may or may not involve populating `work` with values copied from the underlying matrix;
225
+     * a copy will have been performed if the return value's pointers compare equal to `work_x` and `work_i`.
226
+     */
227
+    virtual sparse_index<const int*, int> get_col(size_t c, int* work_x, int* work_i, size_t first, size_t last) = 0;
228
+
229
+    /**
230
+     * Extract all non-zero elements in a row, storing values as doubles.
231
+     *
232
+     * @param r Index of the row of interest.
233
+     * @param work_x The workspace for extracted non-zero values.
234
+     * This should have at least `last - first` addressable elements.
235
+     * @param work_i The workspace for column indices.
236
+     * This should have at least `last - first` addressable elements.
237
+     * @param first The index of the first column of interest.
238
+     * @param last The index of the first column of that is _not_ of interest.
239
+     *
240
+     * @return A `sparse_index` is returned containing pointers to the workspace.
241
+     * containing non-zero elements in `r` with column indices in `[first, last)`.
242
+     * A copy of non-zero values and their indices is always performed into the workspace.
243
+     */
244
+    virtual sparse_index<const double*, int> get_row(size_t r, double* work_x, int* work_i, size_t first, size_t last) = 0;
245
+
246
+    /**
247
+     * Extract all non-zero elements in a column, storing values as doubles.
248
+     *
249
+     * @param r Index of the column of interest.
250
+     * @param work_x The workspace for extracted non-zero values.
251
+     * This should have at least `last - first` addressable elements.
252
+     * @param work_i The workspace for column indices.
253
+     * This should have at least `last - first` addressable elements.
254
+     * @param first The index of the first row of interest.
255
+     * @param last The index of the first row of that is _not_ of interest.
256
+     *
257
+     * @return A `sparse_index` is returned containing pointers to non-zero elements in `c` with row indices in `[first, last)`.
258
+     * This may or may not involve populating `work` with values copied from the underlying matrix;
259
+     * a copy will have been performed if the return value's pointers compare equal to `work_x` and `work_i`.
260
+     */
261
+    virtual sparse_index<const double*, int> get_col(size_t c, double* work_x, int* work_i, size_t first, size_t last) = 0;
262
+
263
+    /**
264
+     * Extract all non-zero elements in a column, storing values as integers.
265
+     *
266
+     * @param r Index of the column of interest.
267
+     * @param work_x The workspace for extracted non-zero values.
268
+     * This should have at least `last - first` addressable elements.
269
+     * @param work_i The workspace for column indices.
270
+     * This should have at least `last - first` addressable elements.
271
+     *
272
+     * @return A `sparse_index` is returned containing pointers to all non-zero elements in `c`.
273
+     * This may or may not involve populating `work` with values copied from the underlying matrix;
274
+     * a copy will have been performed if the return value's pointers compare equal to `work_x` and `work_i`.
275
+     */
276
+    sparse_index<const int*, int> get_col(size_t c, int* work_x, int* work_i) {
277
+        return get_col(c, work_x, work_i, 0, this->nrow);
278
+    }
279
+
280
+    /**
281
+     * Extract all non-zero elements in a row, storing values as integers.
282
+     *
283
+     * @param r Index of the row of interest.
284
+     * @param work_x The workspace for extracted non-zero values.
285
+     * This should have at least `last - first` addressable elements.
286
+     * @param work_i The workspace for column indices.
287
+     * This should have at least `last - first` addressable elements.
288
+     *
289
+     * @return A `sparse_index` is returned containing pointers to the workspace,
290
+     * containing all non-zero elements in `r`.
291
+     * A copy of non-zero values and their indices is always performed into the workspace.
292
+     */
293
+    sparse_index<const int*, int> get_row(size_t r, int* work_x, int* work_i) {
294
+        return get_row(r, work_x, work_i, 0, this->ncol);
295
+    }
296
+
297
+    /**
298
+     * Extract all non-zero elements in a column, storing values as doubles.
299
+     *
300
+     * @param r Index of the column of interest.
301
+     * @param work_x The workspace for extracted non-zero values.
302
+     * This should have at least `last - first` addressable elements.
303
+     * @param work_i The workspace for column indices.
304
+     * This should have at least `last - first` addressable elements.
305
+     *
306
+     * @return A `sparse_index` is returned containing pointers to all non-zero elements in `c`.
307
+     * This may or may not involve populating `work` with values copied from the underlying matrix;
308
+     * a copy will have been performed if the return value's pointers compare equal to `work_x` and `work_i`.
309
+     */
310
+    sparse_index<const double*, int> get_col(size_t c, double* work_x, int* work_i) {
311
+        return get_col(c, work_x, work_i, 0, this->nrow);
312
+    }
313
+
314
+    /**
315
+     * Extract all non-zero elements in a row, storing values as doubles.
316
+     *
317
+     * @param r Index of the row of interest.
318
+     * @param work_x The workspace for extracted non-zero values.
319
+     * This should have at least `last - first` addressable elements.
320
+     * @param work_i The workspace for column indices.
321
+     * This should have at least `last - first` addressable elements.
322
+     *
323
+     * @return A `sparse_index` is returned containing pointers to the workspace,
324
+     * containing all non-zero elements in `r`.
325
+     * A copy of non-zero values and their indices is always performed into the workspace.
326
+     */
327
+    sparse_index<const double*, int> get_row(size_t r, double* work_x, int* work_i) {
328
+        return get_row(r, work_x, work_i, 0, this->ncol);
329
+    }
330
+
331
+    bool is_sparse() const { return true; }
332
+
333
+    /**
334
+     * Get the number of non-zero elements in the matrix.
335
+     */
336
+    virtual size_t get_nnzero() const = 0;
337
+
338
+    /**
339
+     * Clone the current object, returning a pointer to a copy.
340
+     */
341
+    std::unique_ptr<lin_sparse_matrix> clone() const {
342
+        return std::unique_ptr<lin_sparse_matrix>(this->clone_internal());
343
+    }
344
+protected:
345
+    lin_sparse_matrix* clone_internal() const = 0;
346
+};
347
+
348
+/**
349
+ * @brief Logical, integer or numeric matrices in the "ordinary" R format, i.e., column-major dense arrays.
350
+ *
351
+ * @tparam V The class of the `Rcpp::Vector` holding the R-level data.
352
+ */
353
+template <class V>
354
+class lin_ordinary_matrix : public lin_matrix {
355
+public:
356
+    /**
357
+     * Constructor from an ordinary R-level matrix.
358
+     *
359
+     * @param mat An ordinary R matrix.
360
+     */
361
+    lin_ordinary_matrix(Rcpp::RObject mat) : reader(mat) {
362
+        this->nrow = reader.get_nrow();
363
+        this->ncol = reader.get_ncol();
364
+        return;
365
+    }
366
+
367
+    ~lin_ordinary_matrix() = default;
368
+    lin_ordinary_matrix(const lin_ordinary_matrix&) = default;
369
+    lin_ordinary_matrix& operator=(const lin_ordinary_matrix&) = default;
370
+    lin_ordinary_matrix(lin_ordinary_matrix&&) = default;
371
+    lin_ordinary_matrix& operator=(lin_ordinary_matrix&&) = default;
372
+
373
+    const int* get_col(size_t c, int* work, size_t first, size_t last);
374
+
375
+    const int* get_row(size_t r, int* work, size_t first, size_t last) {
376
+        reader.get_row(r, work, first, last);       
377
+        return work;
378
+    }
379
+
380
+    const double* get_col(size_t c, double* work, size_t first, size_t last);
381
+
382
+    const double* get_row(size_t r, double* work, size_t first, size_t last) {
383
+        reader.get_row(r, work, first, last); 
384
+        return work;
385
+    }
386
+private:
387
+    ordinary_reader<V> reader;
388
+
389
+    lin_ordinary_matrix<V>* clone_internal() const {
390
+        return new lin_ordinary_matrix<V>(*this);
391
+    }
392
+};
393
+
394
+using integer_ordinary_matrix = lin_ordinary_matrix<Rcpp::IntegerVector>;
395
+
396
+template <>
397
+inline const int* integer_ordinary_matrix::get_col(size_t c, int* work, size_t first, size_t last) {
398
+    return reader.get_col(c, first, last);
399
+}
400
+
401
+template <>
402
+inline const double* integer_ordinary_matrix::get_col(size_t c, double* work, size_t first, size_t last) {
403
+    auto out = reader.get_col(c, first, last);
404
+    std::copy(out, out + last - first, work);
405
+    return work;
406
+}
407
+
408
+using logical_ordinary_matrix = lin_ordinary_matrix<Rcpp::LogicalVector>;
409
+
410
+template <>
411
+inline const int* logical_ordinary_matrix::get_col(size_t c, int* work, size_t first, size_t last) {
412
+    return reader.get_col(c, first, last);
413
+}
414
+
415
+template <>
416
+inline const double* logical_ordinary_matrix::get_col(size_t c, double* work, size_t first, size_t last) {
417
+    auto out = reader.get_col(c, first, last);
418
+    std::copy(out, out + last - first, work);
419
+    return work;
420
+}
421
+
422
+using double_ordinary_matrix = lin_ordinary_matrix<Rcpp::NumericVector>;
423
+
424
+template <>
425
+inline const int* double_ordinary_matrix::get_col(size_t c, int* work, size_t first, size_t last) {
426
+    auto out = reader.get_col(c, first, last);
427
+    std::copy(out, out + last - first, work);
428
+    return work;
429
+}
430
+
431
+template <>
432
+inline const double* double_ordinary_matrix::get_col(size_t c, double* work, size_t first, size_t last) {
433
+    return reader.get_col(c, first, last);
434
+}
435
+
436
+/**
437
+ * @brief Sparse logical or numeric matrices in the `lgCMatrix` or `dgCMatrix` format, respectively, from the **Matrix** package.
438
+ *
439
+ * @tparam V The class of the `Rcpp::Vector` holding the R-level data for non-zero values.
440
+ */
441
+template <class V, typename TIT>
442
+class gCMatrix : public lin_sparse_matrix {
443
+public:
444
+    /**
445
+     * Constructor from a `*gCMatrix`.
446
+     *
447
+     * @param mat A S4 object of the `dgCMatrix` or `lgCMatrix` class.
448
+     */
449
+    gCMatrix(Rcpp::RObject mat) : reader(mat) {
450
+        this->nrow = reader.get_nrow();
451
+        this->ncol = reader.get_ncol();
452
+        return;
453
+    }
454
+   
455
+    ~gCMatrix() = default;
456
+    gCMatrix(const gCMatrix&) = default;
457
+    gCMatrix& operator=(const gCMatrix&) = default;
458
+    gCMatrix(gCMatrix&&) = default;
459
+    gCMatrix& operator=(gCMatrix&&) = default;
460
+
461
+    const int* get_col(size_t c, int* work, size_t first, size_t last) {
462
+        reader.get_col(c, work, first, last);
463
+        return work;        
464
+    }
465
+
466
+    const int* get_row(size_t r, int* work, size_t first, size_t last) {
467
+        reader.get_row(r, work, first, last);       
468
+        return work;
469
+    }
470
+
471
+    const double* get_col(size_t c, double* work, size_t first, size_t last) {
472
+        reader.get_col(c, work, first, last);
473
+        return work;
474
+    }
475
+
476
+    const double* get_row(size_t r, double* work, size_t first, size_t last) {
477
+        reader.get_row(r, work, first, last); 
478
+        return work;
479
+    }
480
+    
481
+    sparse_index<const int*, int> get_col(size_t c, int* work_x, int* work_i, size_t first, size_t last);
482
+
483
+    sparse_index<const int*, int> get_row(size_t r, int* work_x, int* work_i, size_t first, size_t last) {
484
+        return reader.template get_row<const int*>(r, work_x, work_i, first, last);
485
+    }
486
+
487
+    sparse_index<const double*, int> get_col(size_t c, double* work_x, int* work_i, size_t first, size_t last);
488
+
489
+    sparse_index<const double*, int> get_row(size_t r, double* work_x, int* work_i, size_t first, size_t last) {
490
+        return reader.template get_row<const double*>(r, work_x, work_i, first, last);
491
+    }
492
+
493
+    size_t get_nnzero () const {
494
+        return reader.get_nnzero();
495
+    }
496
+private:
497
+    gCMatrix_reader<V, TIT> reader;
498
+
499
+    gCMatrix<V, TIT>* clone_internal() const {
500
+        return new gCMatrix<V, TIT>(*this);
501
+    }
502
+};
503
+
504
+using lgCMatrix = gCMatrix<Rcpp::LogicalVector, const int*>;
505
+
506
+template <>
507
+inline sparse_index<const int*, int> lgCMatrix::get_col(size_t c, int* work_x, int* work_i, size_t first, size_t last) {
508
+    return reader.get_col(c, first, last);
509
+}
510
+
511
+template <>
512
+inline sparse_index<const double*, int> lgCMatrix::get_col(size_t c, double* work_x, int* work_i, size_t first, size_t last) {
513
+    return transplant<const double*>(reader.get_col(c, first, last), work_x, work_i);
514
+}
515
+
516
+using dgCMatrix = gCMatrix<Rcpp::NumericVector, const double*>;
517
+
518
+template <>
519
+inline sparse_index<const int*, int> dgCMatrix::get_col(size_t c, int* work_x, int* work_i, size_t first, size_t last) {
520
+    return transplant<const int*>(reader.get_col(c, first, last), work_x, work_i);
521
+}
522
+
523
+template <>
524
+inline sparse_index<const double*, int> dgCMatrix::get_col(size_t c, double* work_x, int* work_i, size_t first, size_t last) {
525
+    return reader.get_col(c, first, last);
526
+}
527
+
528
+/**
529
+ * @brief Sparse integer, logical or numeric matrices in the `SparseArraySeed` format from the **DelayedArray** package.
530
+ *
531
+ * @tparam V The class of the `Rcpp::Vector` holding the R-level data for non-zero values.
532
+ */
533
+template <class V, typename TIT>
534
+class lin_SparseArraySeed : public lin_sparse_matrix {
535
+public:
536
+    /**
537
+     * Constructor from a `SparseArraySeed`.
538
+     *
539
+     * @param mat A S4 object of the `SparseArraySeed` class.
540
+     */
541
+    lin_SparseArraySeed(Rcpp::RObject mat) : reader(mat) {
542
+        this->nrow = reader.get_nrow();
543
+        this->ncol = reader.get_ncol();
544
+        return;
545
+    }
546
+
547
+    ~lin_SparseArraySeed() = default;
548
+    lin_SparseArraySeed(const lin_SparseArraySeed&) = default;
549
+    lin_SparseArraySeed& operator=(const lin_SparseArraySeed&) = default;
550
+    lin_SparseArraySeed(lin_SparseArraySeed&&) = default;
551
+    lin_SparseArraySeed& operator=(lin_SparseArraySeed&&) = default;
552
+
553
+    const int* get_col(size_t c, int* work, size_t first, size_t last) {
554
+        reader.get_col(c, work, first, last);
555
+        return work;        
556
+    }
557
+
558
+    const int* get_row(size_t r, int* work, size_t first, size_t last) {
559
+        reader.get_row(r, work, first, last);       
560
+        return work;
561
+    }
562
+
563
+    const double* get_col(size_t c, double* work, size_t first, size_t last) {
564
+        reader.get_col(c, work, first, last);
565
+        return work;
566
+    }
567
+
568
+    const double* get_row(size_t r, double* work, size_t first, size_t last) {
569
+        reader.get_row(r, work, first, last); 
570
+        return work;
571
+    }
572
+
573
+    sparse_index<const int*, int> get_col(size_t c, int* work_x, int* work_i, size_t first, size_t last);
574
+
575
+    sparse_index<const int*, int> get_row(size_t r, int* work_x, int* work_i, size_t first, size_t last) {
576
+        return reader.template get_row<const int*>(r, work_x, work_i, first, last);
577
+    }
578
+
579
+    sparse_index<const double*, int> get_col(size_t c, double* work_x, int* work_i, size_t first, size_t last);
580
+
581
+    sparse_index<const double*, int> get_row(size_t r, double* work_x, int* work_i, size_t first, size_t last) {
582
+        return reader.template get_row<const double*>(r, work_x, work_i, first, last);
583
+    }
584
+
585
+    size_t get_nnzero () const {
586
+        return reader.get_nnzero();
587
+    }
588
+private:
589
+    SparseArraySeed_reader<V, TIT> reader;
590
+
591
+    lin_SparseArraySeed<V, TIT>* clone_internal() const {
592
+        return new lin_SparseArraySeed<V, TIT>(*this);
593
+    }
594
+};
595
+
596
+using integer_SparseArraySeed = lin_SparseArraySeed<Rcpp::IntegerVector, const int*>;
597
+
598
+template <>
599
+inline sparse_index<const int*, int> integer_SparseArraySeed::get_col(size_t c, int* work_x, int* work_i, size_t first, size_t last) {
600
+    return reader.get_col(c, first, last);
601
+}
602
+
603
+template <>
604
+inline sparse_index<const double*, int> integer_SparseArraySeed::get_col(size_t c, double* work_x, int* work_i, size_t first, size_t last)
605
+{
606
+    return transplant<const double*>(reader.get_col(c, first, last), work_x, work_i);
607
+}
608
+
609
+using logical_SparseArraySeed = lin_SparseArraySeed<Rcpp::LogicalVector, const int*>;
610
+
611
+template <>
612
+inline sparse_index<const int*, int> logical_SparseArraySeed::get_col(size_t c, int* work_x, int* work_i, size_t first, size_t last) {
613
+    return reader.get_col(c, first, last);
614
+}
615
+
616
+template <>
617
+inline sparse_index<const double*, int> logical_SparseArraySeed::get_col(size_t c, double* work_x, int* work_i, size_t first, size_t last)
618
+{
619
+    return transplant<const double*>(reader.get_col(c, first, last), work_x, work_i);
620
+}
621
+
622
+using double_SparseArraySeed = lin_SparseArraySeed<Rcpp::NumericVector, const double*>;
623
+
624
+template <>
625
+inline sparse_index<const int*, int> double_SparseArraySeed::get_col(size_t c, int* work_x, int* work_i, size_t first, size_t last) {
626
+    return transplant<const int*>(reader.get_col(c, first, last), work_x, work_i);
627
+}
628
+
629
+template <>
630
+inline sparse_index<const double*, int> double_SparseArraySeed::get_col(size_t c, double* work_x, int* work_i, size_t first, size_t last)
631
+{
632
+    return reader.get_col(c, first, last);
633
+}
634
+
635
+}
636
+
637
+#endif