-
Notifications
You must be signed in to change notification settings - Fork 556
/
Copy pathmatrixreal.cpp
87 lines (69 loc) · 2.93 KB
/
matrixreal.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*
* Copyright (C) 2006-2021 Music Technology Group - Universitat Pompeu Fabra
*
* This file is part of Essentia
*
* Essentia is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation (FSF), either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the Affero GNU General Public License
* version 3 along with this program. If not, see http://www.gnu.org/licenses/
*/
#include "typedefs.h"
using namespace std;
using namespace essentia;
DEFINE_PYTHON_TYPE(MatrixReal);
PyObject* MatrixReal::toPythonRef(TNT::Array2D<Real>* mat) {
npy_intp dims[2];
dims[0] = mat->dim1();
dims[1] = mat->dim2();
PyObject* result;
if (dims[0] == 0 || dims[1] == 0) {
result = PyArray_SimpleNew(2, dims, NPY_FLOAT);
}
else {
result = PyArray_SimpleNewFromData(2, dims, NPY_FLOAT, &((*mat)[0][0]));
}
if (result == NULL) {
throw EssentiaException("MatrixReal: dang null object");
}
if (PyArray_SetBaseObject((PyArrayObject*)result, TO_PYTHON_PROXY(MatrixReal, mat)) < 0) {
Py_DECREF(result);
throw EssentiaException("MatrixReal: failed to set base object");
}
return result;
}
void* MatrixReal::fromPythonRef(PyObject* obj) {
// Note! Even though the input numpy.array's BASE pointer might already be
// pointing to a TNT::Array2D<Real> that we could just return right away, the
// caller wouldn't know whether this was the case, or if a new TNT::Array2D
// was created, and hence wouldn't know whether or not to call delete (they should not in the
// first case, and they should in the second case). This problem is due to the
// fact that we cannot create TNT::Array2D wrapper objects that just point to
// a numpy.array's data and are ALWAYS safe to delete
throw EssentiaException("MatrixReal::fromPythonRef: not implemented");
}
void* MatrixReal::fromPythonCopy(PyObject* obj) {
if (!PyArray_Check(obj)) {
throw EssentiaException("MatrixReal::fromPythonRef: argument not a PyArray");
}
if (PyArray_NDIM((const PyArrayObject *) obj) != 2) {
throw EssentiaException("MatrixReal::fromPythonRef: argument is not a 2-dimensional PyArray");
}
TNT::Array2D<Real>* tntmat = new TNT::Array2D<Real>(PyArray_DIM((const PyArrayObject *) obj, 0), PyArray_DIM((const PyArrayObject *) obj, 1), 0.0);
// copy data from numpy array to matrix
PyArrayObject* numpyarr = (PyArrayObject*)obj;
for (int i=0; i<int(tntmat->dim1()); ++i) {
const Real* src = (Real*)(numpyarr->data + i*numpyarr->strides[0]);
Real* dest = &((*tntmat)[i][0]);
fastcopy(dest, src, tntmat->dim2());
}
return tntmat;
}