Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
gaoqiong
pybind11
Commits
30d43c49
Commit
30d43c49
authored
Apr 14, 2017
by
Cris Luengo
Committed by
Dean Moldovan
May 08, 2017
Browse files
Now `shape`, `size`, `ndims` and `itemsize` are also signed integers.
parent
b68959e8
Changes
13
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
207 additions
and
205 deletions
+207
-205
docs/advanced/pycpp/numpy.rst
docs/advanced/pycpp/numpy.rst
+17
-20
include/pybind11/buffer_info.h
include/pybind11/buffer_info.h
+14
-14
include/pybind11/class_support.h
include/pybind11/class_support.h
+4
-6
include/pybind11/eigen.h
include/pybind11/eigen.h
+5
-5
include/pybind11/numpy.h
include/pybind11/numpy.h
+90
-90
include/pybind11/pytypes.h
include/pybind11/pytypes.h
+5
-5
include/pybind11/stl_bind.h
include/pybind11/stl_bind.h
+7
-7
tests/test_buffers.cpp
tests/test_buffers.cpp
+21
-21
tests/test_eigen.py
tests/test_eigen.py
+2
-2
tests/test_numpy_array.cpp
tests/test_numpy_array.cpp
+31
-29
tests/test_numpy_array.py
tests/test_numpy_array.py
+6
-1
tests/test_numpy_dtypes.cpp
tests/test_numpy_dtypes.cpp
+3
-3
tests/test_numpy_vectorize.cpp
tests/test_numpy_vectorize.cpp
+2
-2
No files found.
docs/advanced/pycpp/numpy.rst
View file @
30d43c49
...
...
@@ -57,10 +57,10 @@ specification.
struct buffer_info {
void *ptr;
size_t itemsize;
s
size_t itemsize;
std::string format;
in
t ndim;
std::vector<size_t> shape;
ssize_
t ndim;
std::vector<
s
size_t> shape;
std::vector<ssize_t> strides;
};
...
...
@@ -95,8 +95,8 @@ buffer objects (e.g. a NumPy matrix).
throw std::runtime_error("Incompatible buffer dimension!");
auto strides = Strides(
info.strides[rowMajor ? 0 : 1] / sizeof(Scalar),
info.strides[rowMajor ? 1 : 0] / sizeof(Scalar));
info.strides[rowMajor ? 0 : 1] /
(py::ssize_t)
sizeof(Scalar),
info.strides[rowMajor ? 1 : 0] /
(py::ssize_t)
sizeof(Scalar));
auto map = Eigen::Map<Matrix, 0, Strides>(
static_cat<Scalar *>(info.ptr), info.shape[0], info.shape[1], strides);
...
...
@@ -111,17 +111,14 @@ as follows:
.def_buffer([](Matrix &m) -> py::buffer_info {
return py::buffer_info(
m.data(), /* Pointer to buffer */
sizeof(Scalar), /* Size of one scalar */
/* Python struct-style format descriptor */
py::format_descriptor<Scalar>::format(),
/* Number of dimensions */
2,
/* Buffer dimensions */
{ m.rows(), m.cols() },
/* Strides (in bytes) for each index */
m.data(), /* Pointer to buffer */
sizeof(Scalar), /* Size of one scalar */
py::format_descriptor<Scalar>::format(), /* Python struct-style format descriptor */
2, /* Number of dimensions */
{ m.rows(), m.cols() }, /* Buffer dimensions */
{ sizeof(Scalar) * (rowMajor ? m.cols() : 1),
sizeof(Scalar) * (rowMajor ? 1 : m.rows()) }
/* Strides (in bytes) for each index */
);
})
...
...
@@ -321,17 +318,17 @@ where ``N`` gives the required dimensionality of the array:
m.def("sum_3d", [](py::array_t<double> x) {
auto r = x.unchecked<3>(); // x must have ndim = 3; can be non-writeable
double sum = 0;
for (size_t i = 0; i < r.shape(0); i++)
for (size_t j = 0; j < r.shape(1); j++)
for (size_t k = 0; k < r.shape(2); k++)
for (
s
size_t i = 0; i < r.shape(0); i++)
for (
s
size_t j = 0; j < r.shape(1); j++)
for (
s
size_t k = 0; k < r.shape(2); k++)
sum += r(i, j, k);
return sum;
});
m.def("increment_3d", [](py::array_t<double> x) {
auto r = x.mutable_unchecked<3>(); // Will throw if ndim != 3 or flags.writeable is false
for (size_t i = 0; i < r.shape(0); i++)
for (size_t j = 0; j < r.shape(1); j++)
for (size_t k = 0; k < r.shape(2); k++)
for (
s
size_t i = 0; i < r.shape(0); i++)
for (
s
size_t j = 0; j < r.shape(1); j++)
for (
s
size_t k = 0; k < r.shape(2); k++)
r(i, j, k) += 1.0;
}, py::arg().noconvert());
...
...
include/pybind11/buffer_info.h
View file @
30d43c49
...
...
@@ -15,31 +15,31 @@ NAMESPACE_BEGIN(pybind11)
/// Information record describing a Python buffer object
struct
buffer_info
{
void
*
ptr
=
nullptr
;
// Pointer to the underlying storage
size_t
itemsize
=
0
;
// Size of individual items in bytes
size_t
size
=
0
;
// Total number of entries
std
::
string
format
;
// For homogeneous buffers, this should be set to format_descriptor<T>::format()
size_t
ndim
=
0
;
// Number of dimensions
std
::
vector
<
size_t
>
shape
;
// Shape of the tensor (1 entry per dimension)
void
*
ptr
=
nullptr
;
// Pointer to the underlying storage
s
size_t
itemsize
=
0
;
// Size of individual items in bytes
s
size_t
size
=
0
;
// Total number of entries
std
::
string
format
;
// For homogeneous buffers, this should be set to format_descriptor<T>::format()
s
size_t
ndim
=
0
;
// Number of dimensions
std
::
vector
<
s
size_t
>
shape
;
// Shape of the tensor (1 entry per dimension)
std
::
vector
<
ssize_t
>
strides
;
// Number of entries between adjacent entries (for each per dimension)
buffer_info
()
{
}
buffer_info
(
void
*
ptr
,
size_t
itemsize
,
const
std
::
string
&
format
,
size_t
ndim
,
detail
::
any_container
<
size_t
>
shape_in
,
detail
::
any_container
<
ssize_t
>
strides_in
)
buffer_info
(
void
*
ptr
,
s
size_t
itemsize
,
const
std
::
string
&
format
,
s
size_t
ndim
,
detail
::
any_container
<
s
size_t
>
shape_in
,
detail
::
any_container
<
ssize_t
>
strides_in
)
:
ptr
(
ptr
),
itemsize
(
itemsize
),
size
(
1
),
format
(
format
),
ndim
(
ndim
),
shape
(
std
::
move
(
shape_in
)),
strides
(
std
::
move
(
strides_in
))
{
if
(
ndim
!=
shape
.
size
()
||
ndim
!=
strides
.
size
())
if
(
ndim
!=
(
ssize_t
)
shape
.
size
()
||
ndim
!=
(
ssize_t
)
strides
.
size
())
pybind11_fail
(
"buffer_info: ndim doesn't match shape and/or strides length"
);
for
(
size_t
i
=
0
;
i
<
ndim
;
++
i
)
for
(
size_t
i
=
0
;
i
<
(
size_t
)
ndim
;
++
i
)
size
*=
shape
[
i
];
}
buffer_info
(
void
*
ptr
,
size_t
itemsize
,
const
std
::
string
&
format
,
size_t
size
)
buffer_info
(
void
*
ptr
,
s
size_t
itemsize
,
const
std
::
string
&
format
,
s
size_t
size
)
:
buffer_info
(
ptr
,
itemsize
,
format
,
1
,
{
size
},
{
itemsize
})
{
}
explicit
buffer_info
(
Py_buffer
*
view
,
bool
ownview
=
true
)
:
buffer_info
(
view
->
buf
,
(
size_t
)
view
->
itemsize
,
view
->
format
,
(
size_t
)
view
->
ndim
,
:
buffer_info
(
view
->
buf
,
view
->
itemsize
,
view
->
format
,
view
->
ndim
,
{
view
->
shape
,
view
->
shape
+
view
->
ndim
},
{
view
->
strides
,
view
->
strides
+
view
->
ndim
})
{
this
->
view
=
view
;
this
->
ownview
=
ownview
;
...
...
@@ -78,13 +78,13 @@ NAMESPACE_BEGIN(detail)
template
<
typename
T
,
typename
SFINAE
=
void
>
struct
compare_buffer_info
{
static
bool
compare
(
const
buffer_info
&
b
)
{
return
b
.
format
==
format_descriptor
<
T
>::
format
()
&&
b
.
itemsize
==
sizeof
(
T
);
return
b
.
format
==
format_descriptor
<
T
>::
format
()
&&
b
.
itemsize
==
(
ssize_t
)
sizeof
(
T
);
}
};
template
<
typename
T
>
struct
compare_buffer_info
<
T
,
detail
::
enable_if_t
<
std
::
is_integral
<
T
>::
value
>>
{
static
bool
compare
(
const
buffer_info
&
b
)
{
return
b
.
itemsize
==
sizeof
(
T
)
&&
(
b
.
format
==
format_descriptor
<
T
>::
value
||
return
(
size_t
)
b
.
itemsize
==
sizeof
(
T
)
&&
(
b
.
format
==
format_descriptor
<
T
>::
value
||
((
sizeof
(
T
)
==
sizeof
(
long
))
&&
b
.
format
==
(
std
::
is_unsigned
<
T
>::
value
?
"L"
:
"l"
))
||
((
sizeof
(
T
)
==
sizeof
(
size_t
))
&&
b
.
format
==
(
std
::
is_unsigned
<
T
>::
value
?
"N"
:
"n"
)));
}
...
...
include/pybind11/class_support.h
View file @
30d43c49
...
...
@@ -433,7 +433,7 @@ inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) {
#endif
type
->
tp_flags
|=
Py_TPFLAGS_HAVE_GC
;
type
->
tp_dictoffset
=
type
->
tp_basicsize
;
// place dict at the end
type
->
tp_basicsize
+=
(
Py_
ssize_t
)
sizeof
(
PyObject
*
);
// and allocate enough space for it
type
->
tp_basicsize
+=
(
ssize_t
)
sizeof
(
PyObject
*
);
// and allocate enough space for it
type
->
tp_traverse
=
pybind11_traverse
;
type
->
tp_clear
=
pybind11_clear
;
...
...
@@ -459,18 +459,16 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
view
->
ndim
=
1
;
view
->
internal
=
info
;
view
->
buf
=
info
->
ptr
;
view
->
itemsize
=
(
Py_ssize_t
)
info
->
itemsize
;
view
->
itemsize
=
info
->
itemsize
;
view
->
len
=
view
->
itemsize
;
for
(
auto
s
:
info
->
shape
)
view
->
len
*=
(
Py_ssize_t
)
s
;
view
->
len
*=
s
;
if
((
flags
&
PyBUF_FORMAT
)
==
PyBUF_FORMAT
)
view
->
format
=
const_cast
<
char
*>
(
info
->
format
.
c_str
());
if
((
flags
&
PyBUF_STRIDES
)
==
PyBUF_STRIDES
)
{
view
->
ndim
=
(
int
)
info
->
ndim
;
view
->
strides
=
&
info
->
strides
[
0
];
// Next is a pointer cast, let's make sure it's safe.
static_assert
(
sizeof
(
Py_ssize_t
)
==
sizeof
(
info
->
shape
[
0
]),
"sizeof(Py_ssize_t) != sizeof(size_t)"
);
view
->
shape
=
(
Py_ssize_t
*
)
&
info
->
shape
[
0
];
view
->
shape
=
&
info
->
shape
[
0
];
}
Py_INCREF
(
view
->
obj
);
return
0
;
...
...
include/pybind11/eigen.h
View file @
30d43c49
...
...
@@ -68,7 +68,7 @@ template <typename T> using is_eigen_other = all_of<
template
<
bool
EigenRowMajor
>
struct
EigenConformable
{
bool
conformable
=
false
;
EigenIndex
rows
=
0
,
cols
=
0
;
EigenDStride
stride
{
0
,
0
};
// Only valid if negativestride
e
s is false!
EigenDStride
stride
{
0
,
0
};
// Only valid if negativestrides is false!
bool
negativestrides
=
false
;
// If true, do not use stride!
EigenConformable
(
bool
fits
=
false
)
:
conformable
{
fits
}
{}
...
...
@@ -207,7 +207,7 @@ template <typename Type_> struct EigenProps {
// Casts an Eigen type to numpy array. If given a base, the numpy array references the src data,
// otherwise it'll make a copy. writeable lets you turn off the writeable flag for the array.
template
<
typename
props
>
handle
eigen_array_cast
(
typename
props
::
Type
const
&
src
,
handle
base
=
handle
(),
bool
writeable
=
true
)
{
constexpr
size_t
elem_size
=
sizeof
(
typename
props
::
Scalar
);
constexpr
s
size_t
elem_size
=
sizeof
(
typename
props
::
Scalar
);
array
a
;
if
(
props
::
vector
)
a
=
array
({
src
.
size
()
},
{
elem_size
*
src
.
innerStride
()
},
src
.
data
(),
base
);
...
...
@@ -581,9 +581,9 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
object
matrix_type
=
module
::
import
(
"scipy.sparse"
).
attr
(
rowMajor
?
"csr_matrix"
:
"csc_matrix"
);
array
data
(
(
size_t
)
src
.
nonZeros
(),
src
.
valuePtr
());
array
outerIndices
(
(
size_t
)
(
rowMajor
?
src
.
rows
()
:
src
.
cols
())
+
1
,
src
.
outerIndexPtr
());
array
innerIndices
(
(
size_t
)
src
.
nonZeros
(),
src
.
innerIndexPtr
());
array
data
(
src
.
nonZeros
(),
src
.
valuePtr
());
array
outerIndices
((
rowMajor
?
src
.
rows
()
:
src
.
cols
())
+
1
,
src
.
outerIndexPtr
());
array
innerIndices
(
src
.
nonZeros
(),
src
.
innerIndexPtr
());
return
matrix_type
(
std
::
make_tuple
(
data
,
innerIndices
,
outerIndices
),
...
...
include/pybind11/numpy.h
View file @
30d43c49
This diff is collapsed.
Click to expand it.
include/pybind11/pytypes.h
View file @
30d43c49
...
...
@@ -1165,15 +1165,15 @@ public:
static
std
::
vector
<
Py_ssize_t
>
py_strides
{
};
static
std
::
vector
<
Py_ssize_t
>
py_shape
{
};
buf
.
buf
=
info
.
ptr
;
buf
.
itemsize
=
(
Py_ssize_t
)
info
.
itemsize
;
buf
.
itemsize
=
info
.
itemsize
;
buf
.
format
=
const_cast
<
char
*>
(
info
.
format
.
c_str
());
buf
.
ndim
=
(
int
)
info
.
ndim
;
buf
.
len
=
(
Py_ssize_t
)
info
.
size
;
buf
.
len
=
info
.
size
;
py_strides
.
clear
();
py_shape
.
clear
();
for
(
size_t
i
=
0
;
i
<
info
.
ndim
;
++
i
)
{
py_strides
.
push_back
(
(
Py_ssize_t
)
info
.
strides
[
i
]);
py_shape
.
push_back
(
(
Py_ssize_t
)
info
.
shape
[
i
]);
for
(
size_t
i
=
0
;
i
<
(
size_t
)
info
.
ndim
;
++
i
)
{
py_strides
.
push_back
(
info
.
strides
[
i
]);
py_shape
.
push_back
(
info
.
shape
[
i
]);
}
buf
.
strides
=
py_strides
.
data
();
buf
.
shape
=
py_shape
.
data
();
...
...
include/pybind11/stl_bind.h
View file @
30d43c49
...
...
@@ -345,21 +345,21 @@ vector_buffer(Class_& cl) {
format_descriptor
<
T
>::
format
();
cl
.
def_buffer
([](
Vector
&
v
)
->
buffer_info
{
return
buffer_info
(
v
.
data
(),
sizeof
(
T
),
format_descriptor
<
T
>::
format
(),
1
,
{
v
.
size
()},
{
sizeof
(
T
)});
return
buffer_info
(
v
.
data
(),
static_cast
<
ssize_t
>
(
sizeof
(
T
)
)
,
format_descriptor
<
T
>::
format
(),
1
,
{
v
.
size
()},
{
sizeof
(
T
)});
});
cl
.
def
(
"__init__"
,
[](
Vector
&
vec
,
buffer
buf
)
{
auto
info
=
buf
.
request
();
if
(
info
.
ndim
!=
1
||
info
.
strides
[
0
]
<=
0
||
info
.
strides
[
0
]
%
static_cast
<
ssize_t
>
(
sizeof
(
T
)))
if
(
info
.
ndim
!=
1
||
info
.
strides
[
0
]
%
static_cast
<
ssize_t
>
(
sizeof
(
T
)))
throw
type_error
(
"Only valid 1D buffers can be copied to a vector"
);
if
(
!
detail
::
compare_buffer_info
<
T
>::
compare
(
info
)
||
sizeof
(
T
)
!=
info
.
itemsize
)
if
(
!
detail
::
compare_buffer_info
<
T
>::
compare
(
info
)
||
(
ssize_t
)
sizeof
(
T
)
!=
info
.
itemsize
)
throw
type_error
(
"Format mismatch (Python: "
+
info
.
format
+
" C++: "
+
format_descriptor
<
T
>::
format
()
+
")"
);
new
(
&
vec
)
Vector
();
vec
.
reserve
(
info
.
shape
[
0
]);
vec
.
reserve
(
(
size_t
)
info
.
shape
[
0
]);
T
*
p
=
static_cast
<
T
*>
(
info
.
ptr
);
auto
step
=
info
.
strides
[
0
]
/
static_cast
<
ssize_t
>
(
sizeof
(
T
));
T
*
end
=
p
+
static_cast
<
ssize_t
>
(
info
.
shape
[
0
]
)
*
step
;
for
(;
p
<
end
;
p
+=
step
)
ssize_t
step
=
info
.
strides
[
0
]
/
static_cast
<
ssize_t
>
(
sizeof
(
T
));
T
*
end
=
p
+
info
.
shape
[
0
]
*
step
;
for
(;
p
!=
end
;
p
+=
step
)
vec
.
push_back
(
*
p
);
});
...
...
tests/test_buffers.cpp
View file @
30d43c49
...
...
@@ -12,16 +12,16 @@
class
Matrix
{
public:
Matrix
(
size_t
rows
,
size_t
cols
)
:
m_rows
(
rows
),
m_cols
(
cols
)
{
Matrix
(
s
size_t
rows
,
s
size_t
cols
)
:
m_rows
(
rows
),
m_cols
(
cols
)
{
print_created
(
this
,
std
::
to_string
(
m_rows
)
+
"x"
+
std
::
to_string
(
m_cols
)
+
" matrix"
);
m_data
=
new
float
[
rows
*
cols
];
memset
(
m_data
,
0
,
sizeof
(
float
)
*
rows
*
cols
);
m_data
=
new
float
[
(
size_t
)
(
rows
*
cols
)
];
memset
(
m_data
,
0
,
sizeof
(
float
)
*
(
size_t
)
(
rows
*
cols
)
)
;
}
Matrix
(
const
Matrix
&
s
)
:
m_rows
(
s
.
m_rows
),
m_cols
(
s
.
m_cols
)
{
print_copy_created
(
this
,
std
::
to_string
(
m_rows
)
+
"x"
+
std
::
to_string
(
m_cols
)
+
" matrix"
);
m_data
=
new
float
[
m_rows
*
m_cols
];
memcpy
(
m_data
,
s
.
m_data
,
sizeof
(
float
)
*
m_rows
*
m_cols
);
m_data
=
new
float
[
(
size_t
)
(
m_rows
*
m_cols
)
];
memcpy
(
m_data
,
s
.
m_data
,
sizeof
(
float
)
*
(
size_t
)
(
m_rows
*
m_cols
)
)
;
}
Matrix
(
Matrix
&&
s
)
:
m_rows
(
s
.
m_rows
),
m_cols
(
s
.
m_cols
),
m_data
(
s
.
m_data
)
{
...
...
@@ -41,8 +41,8 @@ public:
delete
[]
m_data
;
m_rows
=
s
.
m_rows
;
m_cols
=
s
.
m_cols
;
m_data
=
new
float
[
m_rows
*
m_cols
];
memcpy
(
m_data
,
s
.
m_data
,
sizeof
(
float
)
*
m_rows
*
m_cols
);
m_data
=
new
float
[
(
size_t
)
(
m_rows
*
m_cols
)
];
memcpy
(
m_data
,
s
.
m_data
,
sizeof
(
float
)
*
(
size_t
)
(
m_rows
*
m_cols
)
)
;
return
*
this
;
}
...
...
@@ -56,47 +56,47 @@ public:
return
*
this
;
}
float
operator
()(
size_t
i
,
size_t
j
)
const
{
return
m_data
[
i
*
m_cols
+
j
];
float
operator
()(
s
size_t
i
,
s
size_t
j
)
const
{
return
m_data
[
(
size_t
)
(
i
*
m_cols
+
j
)
];
}
float
&
operator
()(
size_t
i
,
size_t
j
)
{
return
m_data
[
i
*
m_cols
+
j
];
float
&
operator
()(
s
size_t
i
,
s
size_t
j
)
{
return
m_data
[
(
size_t
)
(
i
*
m_cols
+
j
)
];
}
float
*
data
()
{
return
m_data
;
}
size_t
rows
()
const
{
return
m_rows
;
}
size_t
cols
()
const
{
return
m_cols
;
}
s
size_t
rows
()
const
{
return
m_rows
;
}
s
size_t
cols
()
const
{
return
m_cols
;
}
private:
size_t
m_rows
;
size_t
m_cols
;
s
size_t
m_rows
;
s
size_t
m_cols
;
float
*
m_data
;
};
test_initializer
buffers
([](
py
::
module
&
m
)
{
py
::
class_
<
Matrix
>
mtx
(
m
,
"Matrix"
,
py
::
buffer_protocol
());
mtx
.
def
(
py
::
init
<
size_t
,
size_t
>
())
mtx
.
def
(
py
::
init
<
s
size_t
,
s
size_t
>
())
/// Construct from a buffer
.
def
(
"__init__"
,
[](
Matrix
&
v
,
py
::
buffer
b
)
{
py
::
buffer_info
info
=
b
.
request
();
if
(
info
.
format
!=
py
::
format_descriptor
<
float
>::
format
()
||
info
.
ndim
!=
2
)
throw
std
::
runtime_error
(
"Incompatible buffer format!"
);
new
(
&
v
)
Matrix
(
info
.
shape
[
0
],
info
.
shape
[
1
]);
memcpy
(
v
.
data
(),
info
.
ptr
,
sizeof
(
float
)
*
v
.
rows
()
*
v
.
cols
());
memcpy
(
v
.
data
(),
info
.
ptr
,
sizeof
(
float
)
*
(
size_t
)
(
v
.
rows
()
*
v
.
cols
())
)
;
})
.
def
(
"rows"
,
&
Matrix
::
rows
)
.
def
(
"cols"
,
&
Matrix
::
cols
)
/// Bare bones interface
.
def
(
"__getitem__"
,
[](
const
Matrix
&
m
,
std
::
pair
<
size_t
,
size_t
>
i
)
{
.
def
(
"__getitem__"
,
[](
const
Matrix
&
m
,
std
::
pair
<
s
size_t
,
s
size_t
>
i
)
{
if
(
i
.
first
>=
m
.
rows
()
||
i
.
second
>=
m
.
cols
())
throw
py
::
index_error
();
return
m
(
i
.
first
,
i
.
second
);
})
.
def
(
"__setitem__"
,
[](
Matrix
&
m
,
std
::
pair
<
size_t
,
size_t
>
i
,
float
v
)
{
.
def
(
"__setitem__"
,
[](
Matrix
&
m
,
std
::
pair
<
s
size_t
,
s
size_t
>
i
,
float
v
)
{
if
(
i
.
first
>=
m
.
rows
()
||
i
.
second
>=
m
.
cols
())
throw
py
::
index_error
();
m
(
i
.
first
,
i
.
second
)
=
v
;
...
...
@@ -109,8 +109,8 @@ test_initializer buffers([](py::module &m) {
py
::
format_descriptor
<
float
>::
format
(),
/* Python struct-style format descriptor */
2
,
/* Number of dimensions */
{
m
.
rows
(),
m
.
cols
()
},
/* Buffer dimensions */
{
static_cast
<
ssize_t
>
(
sizeof
(
float
)
*
m
.
rows
()),
/* Strides (in bytes) for each index */
static_cast
<
ssize_t
>
(
sizeof
(
float
)
)
}
{
sizeof
(
float
)
*
size_t
(
m
.
rows
()),
/* Strides (in bytes) for each index */
sizeof
(
float
)
}
);
})
;
...
...
tests/test_eigen.py
View file @
30d43c49
...
...
@@ -186,7 +186,7 @@ def test_negative_stride_from_python(msg):
double_threer
(
second_row
)
assert
msg
(
excinfo
.
value
)
==
"""
double_threer(): incompatible function arguments. The following argument types are supported:
1. (numpy.ndarray[float32[1, 3], flags.writeable]) ->
arg0:
None
1. (
arg0:
numpy.ndarray[float32[1, 3], flags.writeable]) -> None
Invoked with: array([ 5., 4., 3.], dtype=float32)
"""
...
...
@@ -195,7 +195,7 @@ def test_negative_stride_from_python(msg):
double_threec
(
second_col
)
assert
msg
(
excinfo
.
value
)
==
"""
double_threec(): incompatible function arguments. The following argument types are supported:
1. (numpy.ndarray[float32[3, 1], flags.writeable]) ->
arg0:
None
1. (
arg0:
numpy.ndarray[float32[3, 1], flags.writeable]) -> None
Invoked with: array([ 7., 4., 1.], dtype=float32)
"""
...
...
tests/test_numpy_array.cpp
View file @
30d43c49
...
...
@@ -13,53 +13,52 @@
#include <pybind11/stl.h>
#include <cstdint>
#include <vector>
using
arr
=
py
::
array
;
using
arr_t
=
py
::
array_t
<
uint16_t
,
0
>
;
static_assert
(
std
::
is_same
<
arr_t
::
value_type
,
uint16_t
>::
value
,
""
);
template
<
typename
...
Ix
>
arr
data
(
const
arr
&
a
,
Ix
...
index
)
{
return
arr
(
a
.
nbytes
()
-
size_t
(
a
.
offset_at
(
index
...)
)
,
(
const
uint8_t
*
)
a
.
data
(
index
...));
return
arr
(
a
.
nbytes
()
-
a
.
offset_at
(
index
...),
(
const
uint8_t
*
)
a
.
data
(
index
...));
}
template
<
typename
...
Ix
>
arr
data_t
(
const
arr_t
&
a
,
Ix
...
index
)
{
return
arr
(
a
.
size
()
-
size_t
(
a
.
index_at
(
index
...)
)
,
a
.
data
(
index
...));
return
arr
(
a
.
size
()
-
a
.
index_at
(
index
...),
a
.
data
(
index
...));
}
arr
&
mutate_data
(
arr
&
a
)
{
auto
ptr
=
(
uint8_t
*
)
a
.
mutable_data
();
for
(
size_t
i
=
0
;
i
<
a
.
nbytes
();
i
++
)
for
(
s
size_t
i
=
0
;
i
<
a
.
nbytes
();
i
++
)
ptr
[
i
]
=
(
uint8_t
)
(
ptr
[
i
]
*
2
);
return
a
;
}
arr_t
&
mutate_data_t
(
arr_t
&
a
)
{
auto
ptr
=
a
.
mutable_data
();
for
(
size_t
i
=
0
;
i
<
a
.
size
();
i
++
)
for
(
s
size_t
i
=
0
;
i
<
a
.
size
();
i
++
)
ptr
[
i
]
++
;
return
a
;
}
template
<
typename
...
Ix
>
arr
&
mutate_data
(
arr
&
a
,
Ix
...
index
)
{
auto
ptr
=
(
uint8_t
*
)
a
.
mutable_data
(
index
...);
for
(
size_t
i
=
0
;
i
<
a
.
nbytes
()
-
size_t
(
a
.
offset_at
(
index
...)
)
;
i
++
)
for
(
s
size_t
i
=
0
;
i
<
a
.
nbytes
()
-
a
.
offset_at
(
index
...);
i
++
)
ptr
[
i
]
=
(
uint8_t
)
(
ptr
[
i
]
*
2
);
return
a
;
}
template
<
typename
...
Ix
>
arr_t
&
mutate_data_t
(
arr_t
&
a
,
Ix
...
index
)
{
auto
ptr
=
a
.
mutable_data
(
index
...);
for
(
size_t
i
=
0
;
i
<
a
.
size
()
-
size_t
(
a
.
index_at
(
index
...)
)
;
i
++
)
for
(
s
size_t
i
=
0
;
i
<
a
.
size
()
-
a
.
index_at
(
index
...);
i
++
)
ptr
[
i
]
++
;
return
a
;
}
template
<
typename
...
Ix
>
py
::
ssize_t
index_at
(
const
arr
&
a
,
Ix
...
idx
)
{
return
a
.
index_at
(
idx
...);
}
template
<
typename
...
Ix
>
py
::
ssize_t
index_at_t
(
const
arr_t
&
a
,
Ix
...
idx
)
{
return
a
.
index_at
(
idx
...);
}
template
<
typename
...
Ix
>
py
::
ssize_t
offset_at
(
const
arr
&
a
,
Ix
...
idx
)
{
return
a
.
offset_at
(
idx
...);
}
template
<
typename
...
Ix
>
py
::
ssize_t
offset_at_t
(
const
arr_t
&
a
,
Ix
...
idx
)
{
return
a
.
offset_at
(
idx
...);
}
template
<
typename
...
Ix
>
py
::
ssize_t
at_t
(
const
arr_t
&
a
,
Ix
...
idx
)
{
return
a
.
at
(
idx
...);
}
template
<
typename
...
Ix
>
ssize_t
index_at
(
const
arr
&
a
,
Ix
...
idx
)
{
return
a
.
index_at
(
idx
...);
}
template
<
typename
...
Ix
>
ssize_t
index_at_t
(
const
arr_t
&
a
,
Ix
...
idx
)
{
return
a
.
index_at
(
idx
...);
}
template
<
typename
...
Ix
>
ssize_t
offset_at
(
const
arr
&
a
,
Ix
...
idx
)
{
return
a
.
offset_at
(
idx
...);
}
template
<
typename
...
Ix
>
ssize_t
offset_at_t
(
const
arr_t
&
a
,
Ix
...
idx
)
{
return
a
.
offset_at
(
idx
...);
}
template
<
typename
...
Ix
>
ssize_t
at_t
(
const
arr_t
&
a
,
Ix
...
idx
)
{
return
a
.
at
(
idx
...);
}
template
<
typename
...
Ix
>
arr_t
&
mutate_at_t
(
arr_t
&
a
,
Ix
...
idx
)
{
a
.
mutable_at
(
idx
...)
++
;
return
a
;
}
#define def_index_fn(name, type) \
...
...
@@ -88,9 +87,9 @@ test_initializer numpy_array([](py::module &m) {
sm
.
def
(
"ndim"
,
[](
const
arr
&
a
)
{
return
a
.
ndim
();
});
sm
.
def
(
"shape"
,
[](
const
arr
&
a
)
{
return
arr
(
a
.
ndim
(),
a
.
shape
());
});
sm
.
def
(
"shape"
,
[](
const
arr
&
a
,
size_t
dim
)
{
return
a
.
shape
(
dim
);
});
sm
.
def
(
"shape"
,
[](
const
arr
&
a
,
s
size_t
dim
)
{
return
a
.
shape
(
dim
);
});
sm
.
def
(
"strides"
,
[](
const
arr
&
a
)
{
return
arr
(
a
.
ndim
(),
a
.
strides
());
});
sm
.
def
(
"strides"
,
[](
const
arr
&
a
,
size_t
dim
)
{
return
a
.
strides
(
dim
);
});
sm
.
def
(
"strides"
,
[](
const
arr
&
a
,
s
size_t
dim
)
{
return
a
.
strides
(
dim
);
});
sm
.
def
(
"writeable"
,
[](
const
arr
&
a
)
{
return
a
.
writeable
();
});
sm
.
def
(
"size"
,
[](
const
arr
&
a
)
{
return
a
.
size
();
});
sm
.
def
(
"itemsize"
,
[](
const
arr
&
a
)
{
return
a
.
itemsize
();
});
...
...
@@ -202,33 +201,33 @@ test_initializer numpy_array([](py::module &m) {
sm
.
def
(
"proxy_add2"
,
[](
py
::
array_t
<
double
>
a
,
double
v
)
{
auto
r
=
a
.
mutable_unchecked
<
2
>
();
for
(
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
size_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
s
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
s
size_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
r
(
i
,
j
)
+=
v
;
},
py
::
arg
().
noconvert
(),
py
::
arg
());
sm
.
def
(
"proxy_init3"
,
[](
double
start
)
{
py
::
array_t
<
double
,
py
::
array
::
c_style
>
a
({
3
,
3
,
3
});
auto
r
=
a
.
mutable_unchecked
<
3
>
();
for
(
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
size_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
size_t
k
=
0
;
k
<
r
.
shape
(
2
);
k
++
)
for
(
s
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
s
size_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
s
size_t
k
=
0
;
k
<
r
.
shape
(
2
);
k
++
)
r
(
i
,
j
,
k
)
=
start
++
;
return
a
;
});
sm
.
def
(
"proxy_init3F"
,
[](
double
start
)
{
py
::
array_t
<
double
,
py
::
array
::
f_style
>
a
({
3
,
3
,
3
});
auto
r
=
a
.
mutable_unchecked
<
3
>
();
for
(
size_t
k
=
0
;
k
<
r
.
shape
(
2
);
k
++
)
for
(
size_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
s
size_t
k
=
0
;
k
<
r
.
shape
(
2
);
k
++
)
for
(
s
size_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
s
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
r
(
i
,
j
,
k
)
=
start
++
;
return
a
;
});
sm
.
def
(
"proxy_squared_L2_norm"
,
[](
py
::
array_t
<
double
>
a
)
{
auto
r
=
a
.
unchecked
<
1
>
();
double
sumsq
=
0
;
for
(
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
s
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
sumsq
+=
r
[
i
]
*
r
(
i
);
// Either notation works for a 1D array
return
sumsq
;
});
...
...
@@ -243,17 +242,17 @@ test_initializer numpy_array([](py::module &m) {
sm
.
def
(
"proxy_add2_dyn"
,
[](
py
::
array_t
<
double
>
a
,
double
v
)
{
auto
r
=
a
.
mutable_unchecked
();
if
(
r
.
ndim
()
!=
2
)
throw
std
::
domain_error
(
"error: ndim != 2"
);
for
(
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
size_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
s
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
s
size_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
r
(
i
,
j
)
+=
v
;
},
py
::
arg
().
noconvert
(),
py
::
arg
());
sm
.
def
(
"proxy_init3_dyn"
,
[](
double
start
)
{
py
::
array_t
<
double
,
py
::
array
::
c_style
>
a
({
3
,
3
,
3
});
auto
r
=
a
.
mutable_unchecked
();
if
(
r
.
ndim
()
!=
3
)
throw
std
::
domain_error
(
"error: ndim != 3"
);
for
(
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
size_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
size_t
k
=
0
;
k
<
r
.
shape
(
2
);
k
++
)
for
(
s
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
s
size_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
s
size_t
k
=
0
;
k
<
r
.
shape
(
2
);
k
++
)
r
(
i
,
j
,
k
)
=
start
++
;
return
a
;
});
...
...
@@ -269,6 +268,9 @@ test_initializer numpy_array([](py::module &m) {
sm
.
def
(
"array_fail_test"
,
[]()
{
return
py
::
array
(
py
::
object
());
});
sm
.
def
(
"array_t_fail_test"
,
[]()
{
return
py
::
array_t
<
double
>
(
py
::
object
());
});
// Make sure the error from numpy is being passed through:
sm
.
def
(
"array_fail_test_negative_size"
,
[]()
{
int
c
=
0
;
return
py
::
array
(
-
1
,
&
c
);
});
// Issue (unnumbered; reported in #788): regression: initializer lists can be ambiguous
sm
.
def
(
"array_initializer_list"
,
[]()
{
return
py
::
array_t
<
float
>
(
1
);
});
// { 1 } also works, but clang warns about it
sm
.
def
(
"array_initializer_list"
,
[]()
{
return
py
::
array_t
<
float
>
({
1
,
2
});
});
...
...
@@ -277,7 +279,7 @@ test_initializer numpy_array([](py::module &m) {
// reshape array to 2D without changing size
sm
.
def
(
"array_reshape2"
,
[](
py
::
array_t
<
double
>
a
)
{
const
size_t
dim_sz
=
(
size_t
)
std
::
sqrt
(
a
.
size
());
const
s
size_t
dim_sz
=
(
s
size_t
)
std
::
sqrt
(
a
.
size
());
if
(
dim_sz
*
dim_sz
!=
a
.
size
())
throw
std
::
domain_error
(
"array_reshape2: input array total size is not a squared integer"
);
a
.
resize
({
dim_sz
,
dim_sz
});
...
...
tests/test_numpy_array.py
View file @
30d43c49
...
...
@@ -384,7 +384,8 @@ def test_array_unchecked_dyn_dims(msg):
def
test_array_failure
():
from
pybind11_tests.array
import
array_fail_test
,
array_t_fail_test
from
pybind11_tests.array
import
(
array_fail_test
,
array_t_fail_test
,
array_fail_test_negative_size
)
with
pytest
.
raises
(
ValueError
)
as
excinfo
:
array_fail_test
()
...
...
@@ -394,6 +395,10 @@ def test_array_failure():
array_t_fail_test
()
assert
str
(
excinfo
.
value
)
==
'cannot create a pybind11::array_t from a nullptr'
with
pytest
.
raises
(
ValueError
)
as
excinfo
:
array_fail_test_negative_size
()
assert
str
(
excinfo
.
value
)
==
'negative dimensions are not allowed'
def
test_array_resize
(
msg
):
from
pybind11_tests.array
import
(
array_reshape2
,
array_resize3
)
...
...
tests/test_numpy_dtypes.cpp
View file @
30d43c49
...
...
@@ -149,7 +149,7 @@ py::array_t<StringStruct, 0> create_string_array(bool non_empty) {
if
(
non_empty
)
{
auto
req
=
arr
.
request
();
auto
ptr
=
static_cast
<
StringStruct
*>
(
req
.
ptr
);
for
(
size_t
i
=
0
;
i
<
req
.
size
*
req
.
itemsize
;
i
++
)
for
(
s
size_t
i
=
0
;
i
<
req
.
size
*
req
.
itemsize
;
i
++
)
static_cast
<
char
*>
(
req
.
ptr
)[
i
]
=
0
;
ptr
[
1
].
a
[
0
]
=
'a'
;
ptr
[
1
].
b
[
0
]
=
'a'
;
ptr
[
2
].
a
[
0
]
=
'a'
;
ptr
[
2
].
b
[
0
]
=
'a'
;
...
...
@@ -178,7 +178,7 @@ py::list print_recarray(py::array_t<S, 0> arr) {
const
auto
req
=
arr
.
request
();
const
auto
ptr
=
static_cast
<
S
*>
(
req
.
ptr
);
auto
l
=
py
::
list
();
for
(
size_t
i
=
0
;
i
<
req
.
size
;
i
++
)
{
for
(
s
size_t
i
=
0
;
i
<
req
.
size
;
i
++
)
{
std
::
stringstream
ss
;
ss
<<
ptr
[
i
];
l
.
append
(
py
::
str
(
ss
.
str
()));
...
...
@@ -225,7 +225,7 @@ py::array_t<int32_t, 0> test_array_ctors(int i) {
using
arr_t
=
py
::
array_t
<
int32_t
,
0
>
;
std
::
vector
<
int32_t
>
data
{
1
,
2
,
3
,
4
,
5
,
6
};
std
::
vector
<
size_t
>
shape
{
3
,
2
};
std
::
vector
<
s
size_t
>
shape
{
3
,
2
};
std
::
vector
<
ssize_t
>
strides
{
8
,
4
};
auto
ptr
=
data
.
data
();
...
...
tests/test_numpy_vectorize.cpp
View file @
30d43c49
...
...
@@ -50,8 +50,8 @@ test_initializer numpy_vectorize([](py::module &m) {
py
::
array_t
<
float
,
py
::
array
::
forcecast
>
arg2
,
py
::
array_t
<
double
,
py
::
array
::
forcecast
>
arg3
)
{
size_t
ndim
;
std
::
vector
<
size_t
>
shape
;
s
size_t
ndim
;
std
::
vector
<
s
size_t
>
shape
;
std
::
array
<
py
::
buffer_info
,
3
>
buffers
{{
arg1
.
request
(),
arg2
.
request
(),
arg3
.
request
()
}};
return
py
::
detail
::
broadcast
(
buffers
,
ndim
,
shape
);
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment