blob: b68b5539649677019eac2131d624f4cf5a972de2 [file] [log] [blame]
Wenzel Jakob38bd7112015-07-05 20:05:44 +02001/*
Wenzel Jakoba576e6a2015-07-29 17:51:54 +02002 example/example7.cpp -- supporting Pythons' buffer protocol
Wenzel Jakob38bd7112015-07-05 20:05:44 +02003
4 Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
5
6 All rights reserved. Use of this source code is governed by a
7 BSD-style license that can be found in the LICENSE file.
8*/
9
10#include "example.h"
11
12class Matrix {
13public:
14 Matrix(size_t rows, size_t cols) : m_rows(rows), m_cols(cols) {
15 std::cout << "Value constructor: Creating a " << rows << "x" << cols << " matrix " << std::endl;
16 m_data = new float[rows*cols];
17 memset(m_data, 0, sizeof(float) * rows * cols);
18 }
19
20 Matrix(const Matrix &s) : m_rows(s.m_rows), m_cols(s.m_cols) {
21 std::cout << "Copy constructor: Creating a " << m_rows << "x" << m_cols << " matrix " << std::endl;
22 m_data = new float[m_rows * m_cols];
23 memcpy(m_data, s.m_data, sizeof(float) * m_rows * m_cols);
24 }
25
26 Matrix(Matrix &&s) : m_rows(s.m_rows), m_cols(s.m_cols), m_data(s.m_data) {
27 std::cout << "Move constructor: Creating a " << m_rows << "x" << m_cols << " matrix " << std::endl;
28 s.m_rows = 0;
29 s.m_cols = 0;
30 s.m_data = nullptr;
31 }
32
33 ~Matrix() {
34 std::cout << "Freeing a " << m_rows << "x" << m_cols << " matrix " << std::endl;
35 delete[] m_data;
36 }
37
38 Matrix &operator=(const Matrix &s) {
39 std::cout << "Assignment operator : Creating a " << s.m_rows << "x" << s.m_cols << " matrix " << std::endl;
40 delete[] m_data;
41 m_rows = s.m_rows;
42 m_cols = s.m_cols;
43 m_data = new float[m_rows * m_cols];
44 memcpy(m_data, s.m_data, sizeof(float) * m_rows * m_cols);
45 return *this;
46 }
47
48 Matrix &operator=(Matrix &&s) {
49 std::cout << "Move assignment operator : Creating a " << s.m_rows << "x" << s.m_cols << " matrix " << std::endl;
50 if (&s != this) {
51 delete[] m_data;
52 m_rows = s.m_rows; m_cols = s.m_cols; m_data = s.m_data;
53 s.m_rows = 0; s.m_cols = 0; s.m_data = nullptr;
54 }
55 return *this;
56 }
57
58 float operator()(size_t i, size_t j) const {
59 return m_data[i*m_cols + j];
60 }
61
62 float &operator()(size_t i, size_t j) {
63 return m_data[i*m_cols + j];
64 }
65
66 float *data() { return m_data; }
67
68 size_t rows() const { return m_rows; }
69 size_t cols() const { return m_cols; }
70private:
71 size_t m_rows;
72 size_t m_cols;
73 float *m_data;
74};
75
76void init_ex7(py::module &m) {
77 py::class_<Matrix> mtx(m, "Matrix");
78
79 mtx.def(py::init<size_t, size_t>())
80 /// Construct from a buffer
81 .def("__init__", [](Matrix &v, py::buffer b) {
82 py::buffer_info info = b.request();
83 if (info.format != py::format_descriptor<float>::value() || info.ndim != 2)
84 throw std::runtime_error("Incompatible buffer format!");
85 new (&v) Matrix(info.shape[0], info.shape[1]);
86 memcpy(v.data(), info.ptr, sizeof(float) * v.rows() * v.cols());
87 })
88
89 .def("rows", &Matrix::rows)
90 .def("cols", &Matrix::cols)
91
92 /// Bare bones interface
93 .def("__getitem__", [](const Matrix &m, std::pair<size_t, size_t> i) {
94 if (i.first >= m.rows() || i.second >= m.cols())
95 throw py::index_error();
96 return m(i.first, i.second);
97 })
98 .def("__setitem__", [](Matrix &m, std::pair<size_t, size_t> i, float v) {
99 if (i.first >= m.rows() || i.second >= m.cols())
100 throw py::index_error();
101 m(i.first, i.second) = v;
102 })
103 /// Provide buffer access
104 .def_buffer([](Matrix &m) -> py::buffer_info {
105 return py::buffer_info(
106 m.data(), /* Pointer to buffer */
107 sizeof(float), /* Size of one scalar */
108 py::format_descriptor<float>::value(), /* Python struct-style format descriptor */
109 2, /* Number of dimensions */
110 { m.rows(), m.cols() }, /* Buffer dimensions */
111 { sizeof(float) * m.rows(), /* Strides (in bytes) for each index */
112 sizeof(float) }
113 );
114 });
115}