ViennaCL - The Vienna Computing Library  1.5.1
matrix_proxy.hpp
Go to the documentation of this file.
1 #ifndef VIENNACL_MATRIX_PROXY_HPP_
2 #define VIENNACL_MATRIX_PROXY_HPP_
3 
4 /* =========================================================================
5  Copyright (c) 2010-2014, Institute for Microelectronics,
6  Institute for Analysis and Scientific Computing,
7  TU Wien.
8  Portions of this software are copyright by UChicago Argonne, LLC.
9 
10  -----------------
11  ViennaCL - The Vienna Computing Library
12  -----------------
13 
14  Project Head: Karl Rupp rupp@iue.tuwien.ac.at
15 
16  (A list of authors and contributors can be found in the PDF manual)
17 
18  License: MIT (X11), see file LICENSE in the base directory
19 ============================================================================= */
20 
25 #include "viennacl/forwards.h"
26 #include "viennacl/range.hpp"
27 #include "viennacl/matrix.hpp"
29 
30 namespace viennacl
31 {
32 
37  template <typename MatrixType>
38  class matrix_range : public matrix_base<typename MatrixType::cpu_value_type, typename MatrixType::orientation_functor>
39  {
40  typedef matrix_base<typename MatrixType::cpu_value_type,
41  typename MatrixType::orientation_functor> base_type;
42  typedef matrix_range<MatrixType> self_type;
43 
44  public:
45  typedef typename MatrixType::orientation_category orientation_category;
46 
47  typedef typename MatrixType::value_type value_type;
52  typedef const value_type & const_reference;
53 
54  matrix_range(MatrixType & A,
55  range const & row_range,
56  range const & col_range) : base_type(A.handle(),
57  row_range.size(), row_range.start(), 1, A.internal_size1(),
58  col_range.size(), col_range.start(), 1, A.internal_size2()) {}
59 
60  using base_type::operator=;
61 
62  };
63 
64 
68 
69  //row_major:
70  template <typename CPU_MATRIX, typename SCALARTYPE>
71  void copy(const CPU_MATRIX & cpu_matrix,
72  matrix_range<matrix<SCALARTYPE, row_major, 1> > & gpu_matrix_range )
73  {
74  assert( (cpu_matrix.size1() == gpu_matrix_range.size1())
75  && (cpu_matrix.size2() == gpu_matrix_range.size2())
76  && bool("Matrix size mismatch!"));
77 
78  if ( gpu_matrix_range.start2() != 0)
79  {
80  std::vector<SCALARTYPE> entries(gpu_matrix_range.size2());
81 
82  //copy each stride separately:
83  for (vcl_size_t i=0; i < gpu_matrix_range.size1(); ++i)
84  {
85  for (vcl_size_t j=0; j < gpu_matrix_range.size2(); ++j)
86  entries[j] = cpu_matrix(i,j);
87 
88  vcl_size_t start_offset = (gpu_matrix_range.start1() + i) * gpu_matrix_range.internal_size2() + gpu_matrix_range.start2();
89  vcl_size_t num_entries = gpu_matrix_range.size2();
90  viennacl::backend::memory_write(gpu_matrix_range.handle(), sizeof(SCALARTYPE)*start_offset, sizeof(SCALARTYPE)*num_entries, &(entries[0]));
91  //std::cout << "Strided copy worked!" << std::endl;
92  }
93  }
94  else
95  {
96  //full block can be copied:
97  std::vector<SCALARTYPE> entries(gpu_matrix_range.size1()*gpu_matrix_range.internal_size2());
98 
99  //copy each stride separately:
100  for (vcl_size_t i=0; i < gpu_matrix_range.size1(); ++i)
101  for (vcl_size_t j=0; j < gpu_matrix_range.size2(); ++j)
102  entries[i*gpu_matrix_range.internal_size2() + j] = cpu_matrix(i,j);
103 
104  vcl_size_t start_offset = gpu_matrix_range.start1() * gpu_matrix_range.internal_size2();
105  vcl_size_t num_entries = gpu_matrix_range.size1() * gpu_matrix_range.internal_size2();
106  viennacl::backend::memory_write(gpu_matrix_range.handle(), sizeof(SCALARTYPE)*start_offset, sizeof(SCALARTYPE)*num_entries, &(entries[0]));
107  //std::cout << "Block copy worked!" << std::endl;
108  }
109  }
110 
111  //column_major:
112  template <typename CPU_MATRIX, typename SCALARTYPE>
113  void copy(const CPU_MATRIX & cpu_matrix,
115  {
116  assert( (cpu_matrix.size1() == gpu_matrix_range.size1())
117  && (cpu_matrix.size2() == gpu_matrix_range.size2())
118  && bool("Matrix size mismatch!"));
119 
120  if ( gpu_matrix_range.start1() != 0 || gpu_matrix_range.size1() != gpu_matrix_range.size1())
121  {
122  std::vector<SCALARTYPE> entries(gpu_matrix_range.size1());
123 
124  //copy each stride separately:
125  for (vcl_size_t j=0; j < gpu_matrix_range.size2(); ++j)
126  {
127  for (vcl_size_t i=0; i < gpu_matrix_range.size1(); ++i)
128  entries[i] = cpu_matrix(i,j);
129 
130  vcl_size_t start_offset = (gpu_matrix_range.start2() + j) * gpu_matrix_range.internal_size1() + gpu_matrix_range.start1();
131  vcl_size_t num_entries = gpu_matrix_range.size1();
132  viennacl::backend::memory_write(gpu_matrix_range.handle(), sizeof(SCALARTYPE)*start_offset, sizeof(SCALARTYPE)*num_entries, &(entries[0]));
133  //std::cout << "Strided copy worked!" << std::endl;
134  }
135  }
136  else
137  {
138  //full block can be copied:
139  std::vector<SCALARTYPE> entries(gpu_matrix_range.internal_size1()*gpu_matrix_range.size2());
140 
141  //copy each stride separately:
142  for (vcl_size_t i=0; i < gpu_matrix_range.size1(); ++i)
143  for (vcl_size_t j=0; j < gpu_matrix_range.size2(); ++j)
144  entries[i + j*gpu_matrix_range.internal_size1()] = cpu_matrix(i,j);
145 
146  vcl_size_t start_offset = gpu_matrix_range.start2() * gpu_matrix_range.internal_size1();
147  vcl_size_t num_entries = gpu_matrix_range.internal_size1() * gpu_matrix_range.size2();
148  viennacl::backend::memory_write(gpu_matrix_range.handle(), sizeof(SCALARTYPE)*start_offset, sizeof(SCALARTYPE)*num_entries, &(entries[0]));
149  //std::cout << "Block copy worked!" << std::endl;
150  }
151 
152  }
153 
154 
158 
159 
160  //row_major:
161  template <typename CPU_MATRIX, typename SCALARTYPE>
162  void copy(matrix_range<matrix<SCALARTYPE, row_major, 1> > const & gpu_matrix_range,
163  CPU_MATRIX & cpu_matrix)
164  {
165  assert( (cpu_matrix.size1() == gpu_matrix_range.size1())
166  && (cpu_matrix.size2() == gpu_matrix_range.size2())
167  && bool("Matrix size mismatch!"));
168 
169  if ( gpu_matrix_range.start2() != 0)
170  {
171  std::vector<SCALARTYPE> entries(gpu_matrix_range.size2());
172 
173  //copy each stride separately:
174  for (vcl_size_t i=0; i < gpu_matrix_range.size1(); ++i)
175  {
176  vcl_size_t start_offset = (gpu_matrix_range.start1() + i) * gpu_matrix_range.internal_size2() + gpu_matrix_range.start2();
177  vcl_size_t num_entries = gpu_matrix_range.size2();
178  viennacl::backend::memory_read(gpu_matrix_range.handle(), sizeof(SCALARTYPE)*start_offset, sizeof(SCALARTYPE)*num_entries, &(entries[0]));
179  //std::cout << "Strided copy worked!" << std::endl;
180 
181  for (vcl_size_t j=0; j < gpu_matrix_range.size2(); ++j)
182  cpu_matrix(i,j) = entries[j];
183  }
184  }
185  else
186  {
187  //full block can be copied:
188  std::vector<SCALARTYPE> entries(gpu_matrix_range.size1()*gpu_matrix_range.internal_size2());
189 
190  vcl_size_t start_offset = gpu_matrix_range.start1() * gpu_matrix_range.internal_size2();
191  vcl_size_t num_entries = gpu_matrix_range.size1() * gpu_matrix_range.size2();
192  viennacl::backend::memory_read(gpu_matrix_range.handle(), sizeof(SCALARTYPE)*start_offset, sizeof(SCALARTYPE)*num_entries, &(entries[0]));
193  //std::cout << "Block copy worked!" << std::endl;
194 
195  for (vcl_size_t i=0; i < gpu_matrix_range.size1(); ++i)
196  for (vcl_size_t j=0; j < gpu_matrix_range.size2(); ++j)
197  cpu_matrix(i,j) = entries[i*gpu_matrix_range.internal_size2() + j];
198  }
199 
200  }
201 
202 
203  //column_major:
204  template <typename CPU_MATRIX, typename SCALARTYPE>
205  void copy(matrix_range<matrix<SCALARTYPE, column_major, 1> > const & gpu_matrix_range,
206  CPU_MATRIX & cpu_matrix)
207  {
208  assert( (cpu_matrix.size1() == gpu_matrix_range.size1())
209  && (cpu_matrix.size2() == gpu_matrix_range.size2())
210  && bool("Matrix size mismatch!"));
211 
212  if ( gpu_matrix_range.start1() != 0)
213  {
214  std::vector<SCALARTYPE> entries(gpu_matrix_range.size1());
215 
216  //copy each stride separately:
217  for (vcl_size_t j=0; j < gpu_matrix_range.size2(); ++j)
218  {
219  vcl_size_t start_offset = (gpu_matrix_range.start2() + j) * gpu_matrix_range.internal_size1() + gpu_matrix_range.start1();
220  vcl_size_t num_entries = gpu_matrix_range.size1();
221  viennacl::backend::memory_read(gpu_matrix_range.handle(), sizeof(SCALARTYPE)*start_offset, sizeof(SCALARTYPE)*num_entries, &(entries[0]));
222  //std::cout << "Strided copy worked!" << std::endl;
223 
224  for (vcl_size_t i=0; i < gpu_matrix_range.size1(); ++i)
225  cpu_matrix(i,j) = entries[i];
226  }
227  }
228  else
229  {
230  //full block can be copied:
231  std::vector<SCALARTYPE> entries(gpu_matrix_range.internal_size1()*gpu_matrix_range.size2());
232 
233  //copy each stride separately:
234  vcl_size_t start_offset = gpu_matrix_range.start2() * gpu_matrix_range.internal_size1();
235  vcl_size_t num_entries = gpu_matrix_range.internal_size1() * gpu_matrix_range.size2();
236  viennacl::backend::memory_read(gpu_matrix_range.handle(), sizeof(SCALARTYPE)*start_offset, sizeof(SCALARTYPE)*num_entries, &(entries[0]));
237  //std::cout << "Block copy worked!" << std::endl;
238 
239  for (vcl_size_t i=0; i < gpu_matrix_range.size1(); ++i)
240  for (vcl_size_t j=0; j < gpu_matrix_range.size2(); ++j)
241  cpu_matrix(i,j) = entries[i + j*gpu_matrix_range.internal_size1()];
242  }
243 
244  }
245 
246 
247  //
248  // Convenience function
249  //
250  template <typename MatrixType>
251  matrix_range<MatrixType> project(MatrixType & A, viennacl::range const & r1, viennacl::range const & r2)
252  {
253  assert(r1.size() <= A.size1() && r2.size() <= A.size2() && bool("Size of range invalid!"));
254 
255  return matrix_range<MatrixType>(A, r1, r2);
256  }
257 
258 
259  template <typename MatrixType>
261  {
262  assert(r1.size() <= A.size1() && r2.size() <= A.size2() && bool("Size of range invalid!"));
263 
264  return matrix_range<MatrixType>(A,
265  viennacl::range(A.start1() + r1.start(), A.start1() + r1.start() + r1.size()),
266  viennacl::range(A.start2() + r2.start(), A.start2() + r2.start() + r2.size())
267  );
268  }
269 
270 
271 
272 
273 //
274 //
275 //
277 //
278 //
279 //
280 
281 
282 
283 
284 
289  template <typename MatrixType>
290  class matrix_slice : public matrix_base<typename MatrixType::cpu_value_type, typename MatrixType::orientation_functor>
291  {
292  typedef matrix_base<typename MatrixType::cpu_value_type,
293  typename MatrixType::orientation_functor> base_type;
294  typedef matrix_slice<MatrixType> self_type;
295 
296  public:
297  typedef typename MatrixType::orientation_category orientation_category;
298 
299  typedef typename MatrixType::value_type value_type;
304  typedef const value_type & const_reference;
305 
306  matrix_slice(MatrixType & A,
307  slice const & row_slice,
308  slice const & col_slice) : base_type(A.handle(),
309  row_slice.size(), row_slice.start(), row_slice.stride(), A.internal_size1(),
310  col_slice.size(), col_slice.start(), col_slice.stride(), A.internal_size2()) {}
311 
312  using base_type::operator=;
313 
314  };
315 
316 
317 
321 
322  //row_major:
323  template <typename CPU_MATRIX, typename SCALARTYPE>
324  void copy(const CPU_MATRIX & cpu_matrix,
325  matrix_slice<matrix<SCALARTYPE, row_major, 1> > & gpu_matrix_slice )
326  {
327  assert( (cpu_matrix.size1() == gpu_matrix_slice.size1())
328  && (cpu_matrix.size2() == gpu_matrix_slice.size2())
329  && bool("Matrix size mismatch!"));
330 
331  if ( (gpu_matrix_slice.size1() > 0) && (gpu_matrix_slice.size1() > 0) )
332  {
333  vcl_size_t num_entries = gpu_matrix_slice.size2() * gpu_matrix_slice.stride2(); //no. of entries per stride
334 
335  std::vector<SCALARTYPE> entries(num_entries);
336 
337  //copy each stride separately:
338  for (vcl_size_t i=0; i < gpu_matrix_slice.size1(); ++i)
339  {
340  vcl_size_t start_offset = (gpu_matrix_slice.start1() + i * gpu_matrix_slice.stride1()) * gpu_matrix_slice.internal_size2() + gpu_matrix_slice.start2();
341  viennacl::backend::memory_read(gpu_matrix_slice.handle(), sizeof(SCALARTYPE)*start_offset, sizeof(SCALARTYPE)*num_entries, &(entries[0]));
342 
343  for (vcl_size_t j=0; j < gpu_matrix_slice.size2(); ++j)
344  entries[j * gpu_matrix_slice.stride2()] = cpu_matrix(i,j);
345 
346  viennacl::backend::memory_write(gpu_matrix_slice.handle(), sizeof(SCALARTYPE)*start_offset, sizeof(SCALARTYPE)*num_entries, &(entries[0]));
347  }
348  }
349  }
350 
351  //column_major:
352  template <typename CPU_MATRIX, typename SCALARTYPE>
353  void copy(const CPU_MATRIX & cpu_matrix,
355  {
356  assert( (cpu_matrix.size1() == gpu_matrix_slice.size1())
357  && (cpu_matrix.size2() == gpu_matrix_slice.size2())
358  && bool("Matrix size mismatch!"));
359 
360 
361  if ( (gpu_matrix_slice.size1() > 0) && (gpu_matrix_slice.size1() > 0) )
362  {
363  vcl_size_t num_entries = gpu_matrix_slice.size1() * gpu_matrix_slice.stride1(); //no. of entries per stride
364 
365  std::vector<SCALARTYPE> entries(num_entries);
366 
367  //copy each column stride separately:
368  for (vcl_size_t j=0; j < gpu_matrix_slice.size2(); ++j)
369  {
370  vcl_size_t start_offset = gpu_matrix_slice.start1() + (gpu_matrix_slice.start2() + j * gpu_matrix_slice.stride2()) * gpu_matrix_slice.internal_size1();
371 
372  viennacl::backend::memory_read(gpu_matrix_slice.handle(), sizeof(SCALARTYPE)*start_offset, sizeof(SCALARTYPE)*num_entries, &(entries[0]));
373 
374  for (vcl_size_t i=0; i < gpu_matrix_slice.size1(); ++i)
375  entries[i * gpu_matrix_slice.stride1()] = cpu_matrix(i,j);
376 
377  viennacl::backend::memory_write(gpu_matrix_slice.handle(), sizeof(SCALARTYPE)*start_offset, sizeof(SCALARTYPE)*num_entries, &(entries[0]));
378  }
379  }
380 
381  }
382 
383 
387 
388 
389  //row_major:
390  template <typename CPU_MATRIX, typename SCALARTYPE>
391  void copy(matrix_slice<matrix<SCALARTYPE, row_major, 1> > const & gpu_matrix_slice,
392  CPU_MATRIX & cpu_matrix)
393  {
394  assert( (cpu_matrix.size1() == gpu_matrix_slice.size1())
395  && (cpu_matrix.size2() == gpu_matrix_slice.size2())
396  && bool("Matrix size mismatch!"));
397 
398  if ( (gpu_matrix_slice.size1() > 0) && (gpu_matrix_slice.size1() > 0) )
399  {
400  vcl_size_t num_entries = gpu_matrix_slice.size2() * gpu_matrix_slice.stride2(); //no. of entries per stride
401 
402  std::vector<SCALARTYPE> entries(num_entries);
403 
404  //copy each stride separately:
405  for (vcl_size_t i=0; i < gpu_matrix_slice.size1(); ++i)
406  {
407  vcl_size_t start_offset = (gpu_matrix_slice.start1() + i * gpu_matrix_slice.stride1()) * gpu_matrix_slice.internal_size2() + gpu_matrix_slice.start2();
408 
409  viennacl::backend::memory_read(gpu_matrix_slice.handle(), sizeof(SCALARTYPE)*start_offset, sizeof(SCALARTYPE)*num_entries, &(entries[0]));
410 
411  for (vcl_size_t j=0; j < gpu_matrix_slice.size2(); ++j)
412  cpu_matrix(i,j) = entries[j * gpu_matrix_slice.stride2()];
413  }
414  }
415 
416  }
417 
418 
419  //column_major:
420  template <typename CPU_MATRIX, typename SCALARTYPE>
421  void copy(matrix_slice<matrix<SCALARTYPE, column_major, 1> > const & gpu_matrix_slice,
422  CPU_MATRIX & cpu_matrix)
423  {
424  assert( (cpu_matrix.size1() == gpu_matrix_slice.size1())
425  && (cpu_matrix.size2() == gpu_matrix_slice.size2())
426  && bool("Matrix size mismatch!"));
427 
428  if ( (gpu_matrix_slice.size1() > 0) && (gpu_matrix_slice.size1() > 0) )
429  {
430  vcl_size_t num_entries = gpu_matrix_slice.size1() * gpu_matrix_slice.stride1(); //no. of entries per stride
431 
432  std::vector<SCALARTYPE> entries(num_entries);
433 
434  //copy each column stride separately:
435  for (vcl_size_t j=0; j < gpu_matrix_slice.size2(); ++j)
436  {
437  vcl_size_t start_offset = gpu_matrix_slice.start1() + (gpu_matrix_slice.start2() + j * gpu_matrix_slice.stride2()) * gpu_matrix_slice.internal_size1();
438 
439  viennacl::backend::memory_read(gpu_matrix_slice.handle(), sizeof(SCALARTYPE)*start_offset, sizeof(SCALARTYPE)*num_entries, &(entries[0]));
440 
441  for (vcl_size_t i=0; i < gpu_matrix_slice.size1(); ++i)
442  cpu_matrix(i,j) = entries[i * gpu_matrix_slice.stride1()];
443  }
444  }
445 
446  }
447 
448 
449  //
450  // Convenience function
451  //
452  template <typename MatrixType>
453  matrix_slice<MatrixType> project(MatrixType & A, viennacl::slice const & r1, viennacl::slice const & r2)
454  {
455  assert(r1.size() <= A.size1() && r2.size() <= A.size2() && bool("Size of slice invalid!"));
456 
457  return matrix_slice<MatrixType>(A, r1, r2);
458  }
459 
460  template <typename MatrixType>
462  {
463  assert(r1.size() <= A.size1() && r2.size() <= A.size2() && bool("Size of slice invalid!"));
464 
465  return matrix_slice<MatrixType>(A,
466  viennacl::slice(A.start1() + r1.start(), r1.stride(), r1.size()),
467  viennacl::slice(A.start2() + r2.start(), r2.stride(), r2.size())
468  );
469  }
470 
471  template <typename MatrixType>
473  {
474  assert(r1.size() <= A.size1() && r2.size() <= A.size2() && bool("Size of slice invalid!"));
475 
476  return matrix_slice<MatrixType>(A,
477  viennacl::slice(A.start1() + r1.start(), A.stride1() * r1.stride(), r1.size()),
478  viennacl::slice(A.start2() + r2.start(), A.stride2() * r2.stride(), r2.size())
479  );
480  }
481 
482  // TODO: Allow mix of range/slice
483 
484 }
485 
486 #endif
MatrixType::orientation_category orientation_category
Definition: matrix_proxy.hpp:297
std::size_t vcl_size_t
Definition: forwards.h:58
void memory_write(mem_handle &dst_buffer, vcl_size_t dst_offset, vcl_size_t bytes_to_write, const void *ptr, bool async=false)
Writes data from main RAM identified by 'ptr' to the buffer identified by 'dst_buffer'.
Definition: memory.hpp:220
basic_slice slice
Definition: forwards.h:344
Implementations of dense matrix related operations including matrix-vector products.
size_type size() const
Definition: slice.hpp:56
Class for representing strided submatrices of a bigger matrix A.
Definition: forwards.h:358
Implementation of the dense matrix class.
value_type reference
Definition: matrix_proxy.hpp:51
viennacl::result_of::cpu_value_type< value_type >::type cpu_value_type
Definition: matrix_proxy.hpp:48
matrix_range< MatrixType > project(MatrixType &A, viennacl::range const &r1, viennacl::range const &r2)
Definition: matrix_proxy.hpp:251
const value_type & const_reference
Definition: matrix_proxy.hpp:304
size_type internal_size1() const
Returns the internal number of rows. Usually required for launching OpenCL kernels only...
Definition: matrix.hpp:647
const value_type & const_reference
Definition: matrix_proxy.hpp:52
range::difference_type difference_type
Definition: matrix_proxy.hpp:50
A dense matrix class.
Definition: forwards.h:290
result_of::size_type< viennacl::vector_base< T > >::type stride(viennacl::vector_base< T > const &s)
Definition: stride.hpp:46
This file provides the forward declarations for the main types used within ViennaCL.
size_type start() const
Definition: slice.hpp:54
A dense matrix class.
Definition: forwards.h:293
void memory_read(mem_handle const &src_buffer, vcl_size_t src_offset, vcl_size_t bytes_to_read, void *ptr, bool async=false)
Reads data from a buffer back to main RAM.
Definition: memory.hpp:261
MatrixType::orientation_category orientation_category
Definition: matrix_proxy.hpp:45
viennacl::result_of::cpu_value_type< value_type >::type cpu_value_type
Definition: matrix_proxy.hpp:300
MatrixType::value_type value_type
Definition: matrix_proxy.hpp:299
MatrixType::value_type value_type
Definition: matrix_proxy.hpp:47
matrix_range(MatrixType &A, range const &row_range, range const &col_range)
Definition: matrix_proxy.hpp:54
matrix_slice(MatrixType &A, slice const &row_slice, slice const &col_slice)
Definition: matrix_proxy.hpp:306
range::size_type size_type
Definition: matrix_proxy.hpp:49
difference_type stride() const
Definition: slice.hpp:55
vcl_size_t size(VectorType const &vec)
Generic routine for obtaining the size of a vector (ViennaCL, uBLAS, etc.)
Definition: size.hpp:144
size_type start() const
Definition: range.hpp:55
result_of::size_type< T >::type start(T const &obj)
Definition: start.hpp:43
SizeType size_type
Definition: range.hpp:42
void copy(std::vector< SCALARTYPE > &cpu_vec, circulant_matrix< SCALARTYPE, ALIGNMENT > &gpu_mat)
Copies a circulant matrix from the std::vector to the OpenCL device (either GPU or multi-core CPU) ...
Definition: circulant_matrix.hpp:150
value_type reference
Definition: matrix_proxy.hpp:303
size_type size() const
Definition: range.hpp:56
matrix_base()
The default constructor. Does not allocate any memory.
Definition: matrix.hpp:255
T::ERROR_CANNOT_DEDUCE_CPU_SCALAR_TYPE_FOR_T type
Definition: result_of.hpp:276
range::difference_type difference_type
Definition: matrix_proxy.hpp:302
DistanceType difference_type
Definition: range.hpp:43
A range class that refers to an interval [start, stop), where 'start' is included, and 'stop' is excluded.
Definition: forwards.h:339
handle_type & handle()
Returns the OpenCL handle, non-const-version.
Definition: matrix.hpp:654
Implementation of a range object for use with proxy objects.
basic_range range
Definition: forwards.h:339
Class for representing non-strided submatrices of a bigger matrix A.
Definition: forwards.h:355
A slice class that refers to an interval [start, stop), where 'start' is included, and 'stop' is excluded.
Definition: forwards.h:344
range::size_type size_type
Definition: matrix_proxy.hpp:301
size_type internal_size2() const
Returns the internal number of columns. Usually required for launching OpenCL kernels only...
Definition: matrix.hpp:649