Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
pybind11
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
pybind11
Commits
30d43c49
Commit
30d43c49
authored
Apr 14, 2017
by
Cris Luengo
Committed by
Dean Moldovan
May 08, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Now `shape`, `size`, `ndims` and `itemsize` are also signed integers.
parent
b68959e8
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
207 additions
and
205 deletions
+207
-205
docs/advanced/pycpp/numpy.rst
+17
-20
include/pybind11/buffer_info.h
+14
-14
include/pybind11/class_support.h
+4
-6
include/pybind11/eigen.h
+5
-5
include/pybind11/numpy.h
+90
-90
include/pybind11/pytypes.h
+5
-5
include/pybind11/stl_bind.h
+7
-7
tests/test_buffers.cpp
+21
-21
tests/test_eigen.py
+2
-2
tests/test_numpy_array.cpp
+31
-29
tests/test_numpy_array.py
+6
-1
tests/test_numpy_dtypes.cpp
+3
-3
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
s
ize_t itemsize;
std::string format;
in
t ndim;
std::vector<size_t> shape;
ssize_
t ndim;
std::vector<s
s
ize_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
s
ize_t i = 0; i < r.shape(0); i++)
for (s
s
ize_t j = 0; j < r.shape(1); j++)
for (s
s
ize_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
s
ize_t i = 0; i < r.shape(0); i++)
for (s
s
ize_t j = 0; j < r.shape(1); j++)
for (s
s
ize_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
s
ize_t
itemsize
=
0
;
// Size of individual items in bytes
s
s
ize_t
size
=
0
;
// Total number of entries
std
::
string
format
;
// For homogeneous buffers, this should be set to format_descriptor<T>::format()
s
s
ize_t
ndim
=
0
;
// Number of dimensions
std
::
vector
<
s
s
ize_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
,
s
ize_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
s
ize_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
,
s
ize_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
s
ize_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
...
...
@@ -251,10 +251,10 @@ template <typename T> using is_pod_struct = all_of<
satisfies_none_of
<
T
,
std
::
is_reference
,
std
::
is_array
,
is_std_array
,
std
::
is_arithmetic
,
is_complex
,
std
::
is_enum
>
>
;
template
<
size_t
Dim
=
0
,
typename
Strides
>
ssize_t
byte_offset_unsafe
(
const
Strides
&
)
{
return
0
;
}
template
<
size_t
Dim
=
0
,
typename
Strides
,
typename
...
Ix
>
ssize_t
byte_offset_unsafe
(
const
Strides
&
strides
,
size_t
i
,
Ix
...
index
)
{
return
static_cast
<
ssize_t
>
(
i
)
*
strides
[
Dim
]
+
byte_offset_unsafe
<
Dim
+
1
>
(
strides
,
index
...);
template
<
s
s
ize_t
Dim
=
0
,
typename
Strides
>
ssize_t
byte_offset_unsafe
(
const
Strides
&
)
{
return
0
;
}
template
<
s
s
ize_t
Dim
=
0
,
typename
Strides
,
typename
...
Ix
>
ssize_t
byte_offset_unsafe
(
const
Strides
&
strides
,
s
s
ize_t
i
,
Ix
...
index
)
{
return
i
*
strides
[
Dim
]
+
byte_offset_unsafe
<
Dim
+
1
>
(
strides
,
index
...);
}
/** Proxy class providing unsafe, unchecked const access to array data. This is constructed through
...
...
@@ -268,23 +268,23 @@ protected:
const
unsigned
char
*
data_
;
// Storing the shape & strides in local variables (i.e. these arrays) allows the compiler to
// make large performance gains on big, nested loops, but requires compile-time dimensions
conditional_t
<
Dynamic
,
const
s
ize_t
*
,
std
::
array
<
size_t
,
(
size_t
)
Dims
>>
shape_
;
conditional_t
<
Dynamic
,
const
ssize_t
*
,
std
::
array
<
ssize_t
,
(
size_t
)
Dims
>>
strides_
;
const
size_t
dims_
;
conditional_t
<
Dynamic
,
const
s
size_t
*
,
std
::
array
<
ssize_t
,
(
size_t
)
Dims
>>
shape_
,
strides_
;
const
s
s
ize_t
dims_
;
friend
class
pybind11
::
array
;
// Constructor for compile-time dimensions:
template
<
bool
Dyn
=
Dynamic
>
unchecked_reference
(
const
void
*
data
,
const
s
ize_t
*
shape
,
const
ssize_t
*
strides
,
enable_if_t
<!
Dyn
,
size_t
>
)
unchecked_reference
(
const
void
*
data
,
const
s
size_t
*
shape
,
const
ssize_t
*
strides
,
enable_if_t
<!
Dyn
,
s
size_t
>
)
:
data_
{
reinterpret_cast
<
const
unsigned
char
*>
(
data
)},
dims_
{
Dims
}
{
for
(
size_t
i
=
0
;
i
<
dims_
;
i
++
)
{
for
(
size_t
i
=
0
;
i
<
(
size_t
)
dims_
;
i
++
)
{
shape_
[
i
]
=
shape
[
i
];
strides_
[
i
]
=
strides
[
i
];
}
}
// Constructor for runtime dimensions:
template
<
bool
Dyn
=
Dynamic
>
unchecked_reference
(
const
void
*
data
,
const
s
ize_t
*
shape
,
const
ssize_t
*
strides
,
enable_if_t
<
Dyn
,
size_t
>
dims
)
unchecked_reference
(
const
void
*
data
,
const
s
size_t
*
shape
,
const
ssize_t
*
strides
,
enable_if_t
<
Dyn
,
s
size_t
>
dims
)
:
data_
{
reinterpret_cast
<
const
unsigned
char
*>
(
data
)},
shape_
{
shape
},
strides_
{
strides
},
dims_
{
dims
}
{}
public
:
...
...
@@ -295,39 +295,39 @@ public:
template
<
typename
...
Ix
>
const
T
&
operator
()(
Ix
...
index
)
const
{
static_assert
(
sizeof
...(
Ix
)
==
Dims
||
Dynamic
,
"Invalid number of indices for unchecked array reference"
);
return
*
reinterpret_cast
<
const
T
*>
(
data_
+
byte_offset_unsafe
(
strides_
,
size_t
(
index
)...));
return
*
reinterpret_cast
<
const
T
*>
(
data_
+
byte_offset_unsafe
(
strides_
,
s
s
ize_t
(
index
)...));
}
/** Unchecked const reference access to data; this operator only participates if the reference
* is to a 1-dimensional array. When present, this is exactly equivalent to `obj(index)`.
*/
template
<
size_t
D
=
Dims
,
typename
=
enable_if_t
<
D
==
1
||
Dynamic
>>
const
T
&
operator
[](
size_t
index
)
const
{
return
operator
()(
index
);
}
template
<
s
s
ize_t
D
=
Dims
,
typename
=
enable_if_t
<
D
==
1
||
Dynamic
>>
const
T
&
operator
[](
s
s
ize_t
index
)
const
{
return
operator
()(
index
);
}
/// Pointer access to the data at the given indices.
template
<
typename
...
Ix
>
const
T
*
data
(
Ix
...
ix
)
const
{
return
&
operator
()(
size_t
(
ix
)...);
}
template
<
typename
...
Ix
>
const
T
*
data
(
Ix
...
ix
)
const
{
return
&
operator
()(
s
s
ize_t
(
ix
)...);
}
/// Returns the item size, i.e. sizeof(T)
constexpr
static
size_t
itemsize
()
{
return
sizeof
(
T
);
}
constexpr
static
s
s
ize_t
itemsize
()
{
return
sizeof
(
T
);
}
/// Returns the shape (i.e. size) of dimension `dim`
s
ize_t
shape
(
size_t
dim
)
const
{
return
shape_
[
dim
];
}
s
size_t
shape
(
ssize_t
dim
)
const
{
return
shape_
[(
size_t
)
dim
];
}
/// Returns the number of dimensions of the array
size_t
ndim
()
const
{
return
dims_
;
}
s
s
ize_t
ndim
()
const
{
return
dims_
;
}
/// Returns the total number of elements in the referenced array, i.e. the product of the shapes
template
<
bool
Dyn
=
Dynamic
>
enable_if_t
<!
Dyn
,
size_t
>
size
()
const
{
return
std
::
accumulate
(
shape_
.
begin
(),
shape_
.
end
(),
(
s
ize_t
)
1
,
std
::
multiplies
<
size_t
>
());
enable_if_t
<!
Dyn
,
s
s
ize_t
>
size
()
const
{
return
std
::
accumulate
(
shape_
.
begin
(),
shape_
.
end
(),
(
s
size_t
)
1
,
std
::
multiplies
<
s
size_t
>
());
}
template
<
bool
Dyn
=
Dynamic
>
enable_if_t
<
Dyn
,
size_t
>
size
()
const
{
return
std
::
accumulate
(
shape_
,
shape_
+
ndim
(),
(
s
ize_t
)
1
,
std
::
multiplies
<
size_t
>
());
enable_if_t
<
Dyn
,
s
s
ize_t
>
size
()
const
{
return
std
::
accumulate
(
shape_
,
shape_
+
ndim
(),
(
s
size_t
)
1
,
std
::
multiplies
<
s
size_t
>
());
}
/// Returns the total number of bytes used by the referenced data. Note that the actual span in
/// memory may be larger if the referenced array has non-contiguous strides (e.g. for a slice).
size_t
nbytes
()
const
{
s
s
ize_t
nbytes
()
const
{
return
size
()
*
itemsize
();
}
};
...
...
@@ -349,11 +349,11 @@ public:
* reference is to a 1-dimensional array (or has runtime dimensions). When present, this is
* exactly equivalent to `obj(index)`.
*/
template
<
size_t
D
=
Dims
,
typename
=
enable_if_t
<
D
==
1
||
Dynamic
>>
T
&
operator
[](
size_t
index
)
{
return
operator
()(
index
);
}
template
<
s
s
ize_t
D
=
Dims
,
typename
=
enable_if_t
<
D
==
1
||
Dynamic
>>
T
&
operator
[](
s
s
ize_t
index
)
{
return
operator
()(
index
);
}
/// Mutable pointer access to the data at the given indices.
template
<
typename
...
Ix
>
T
*
mutable_data
(
Ix
...
ix
)
{
return
&
operator
()(
size_t
(
ix
)...);
}
template
<
typename
...
Ix
>
T
*
mutable_data
(
Ix
...
ix
)
{
return
&
operator
()(
s
s
ize_t
(
ix
)...);
}
};
template
<
typename
T
,
ssize_t
Dim
>
...
...
@@ -381,7 +381,7 @@ public:
dtype
(
const
char
*
format
)
:
dtype
(
std
::
string
(
format
))
{
}
dtype
(
list
names
,
list
formats
,
list
offsets
,
size_t
itemsize
)
{
dtype
(
list
names
,
list
formats
,
list
offsets
,
s
s
ize_t
itemsize
)
{
dict
args
;
args
[
"names"
]
=
names
;
args
[
"formats"
]
=
formats
;
...
...
@@ -404,8 +404,8 @@ public:
}
/// Size of the data type in bytes.
size_t
itemsize
()
const
{
return
(
size_t
)
detail
::
array_descriptor_proxy
(
m_ptr
)
->
elsize
;
s
s
ize_t
itemsize
()
const
{
return
detail
::
array_descriptor_proxy
(
m_ptr
)
->
elsize
;
}
/// Returns true for structured data types.
...
...
@@ -425,7 +425,7 @@ private:
return
reinterpret_borrow
<
object
>
(
obj
);
}
dtype
strip_padding
(
size_t
itemsize
)
{
dtype
strip_padding
(
s
s
ize_t
itemsize
)
{
// Recursively strip all void fields with empty names that are generated for
// padding fields (as of NumPy v1.11).
if
(
!
has_fields
())
...
...
@@ -501,7 +501,7 @@ public:
api
.
PyArray_Type_
,
descr
.
release
().
ptr
(),
(
int
)
ndim
,
shape
->
data
(),
strides
->
data
(),
const_cast
<
void
*>
(
ptr
),
flags
,
nullptr
));
if
(
!
tmp
)
pybind11_fail
(
"NumPy: unable to create array!"
);
throw
error_already_set
(
);
if
(
ptr
)
{
if
(
base
)
{
api
.
PyArray_SetBaseObject_
(
tmp
.
ptr
(),
base
.
inc_ref
().
ptr
());
...
...
@@ -528,7 +528,7 @@ public:
:
array
(
std
::
move
(
shape
),
{},
ptr
,
base
)
{
}
template
<
typename
T
>
explicit
array
(
size_t
count
,
const
T
*
ptr
,
handle
base
=
handle
())
:
array
({
count
},
{},
ptr
,
base
)
{
}
explicit
array
(
s
s
ize_t
count
,
const
T
*
ptr
,
handle
base
=
handle
())
:
array
({
count
},
{},
ptr
,
base
)
{
}
explicit
array
(
const
buffer_info
&
info
)
:
array
(
pybind11
::
dtype
(
info
),
info
.
shape
,
info
.
strides
,
info
.
ptr
)
{
}
...
...
@@ -539,23 +539,23 @@ public:
}
/// Total number of elements
size_t
size
()
const
{
return
std
::
accumulate
(
shape
(),
shape
()
+
ndim
(),
(
s
ize_t
)
1
,
std
::
multiplies
<
size_t
>
());
s
s
ize_t
size
()
const
{
return
std
::
accumulate
(
shape
(),
shape
()
+
ndim
(),
(
s
size_t
)
1
,
std
::
multiplies
<
s
size_t
>
());
}
/// Byte size of a single element
size_t
itemsize
()
const
{
return
(
size_t
)
detail
::
array_descriptor_proxy
(
detail
::
array_proxy
(
m_ptr
)
->
descr
)
->
elsize
;
s
s
ize_t
itemsize
()
const
{
return
detail
::
array_descriptor_proxy
(
detail
::
array_proxy
(
m_ptr
)
->
descr
)
->
elsize
;
}
/// Total number of bytes
size_t
nbytes
()
const
{
s
s
ize_t
nbytes
()
const
{
return
size
()
*
itemsize
();
}
/// Number of dimensions
size_t
ndim
()
const
{
return
(
size_t
)
detail
::
array_proxy
(
m_ptr
)
->
nd
;
s
s
ize_t
ndim
()
const
{
return
detail
::
array_proxy
(
m_ptr
)
->
nd
;
}
/// Base object
...
...
@@ -564,12 +564,12 @@ public:
}
/// Dimensions of the array
const
size_t
*
shape
()
const
{
return
reinterpret_cast
<
const
size_t
*>
(
detail
::
array_proxy
(
m_ptr
)
->
dimensions
)
;
const
s
s
ize_t
*
shape
()
const
{
return
detail
::
array_proxy
(
m_ptr
)
->
dimensions
;
}
/// Dimension along a given axis
s
ize_t
shape
(
size_t
dim
)
const
{
s
size_t
shape
(
s
size_t
dim
)
const
{
if
(
dim
>=
ndim
())
fail_dim_check
(
dim
,
"invalid axis"
);
return
shape
()[
dim
];
...
...
@@ -577,11 +577,11 @@ public:
/// Strides of the array
const
ssize_t
*
strides
()
const
{
return
reinterpret_cast
<
const
ssize_t
*>
(
detail
::
array_proxy
(
m_ptr
)
->
strides
)
;
return
detail
::
array_proxy
(
m_ptr
)
->
strides
;
}
/// Stride along a given axis
ssize_t
strides
(
size_t
dim
)
const
{
ssize_t
strides
(
s
s
ize_t
dim
)
const
{
if
(
dim
>=
ndim
())
fail_dim_check
(
dim
,
"invalid axis"
);
return
strides
()[
dim
];
...
...
@@ -619,9 +619,9 @@ public:
/// Byte offset from beginning of the array to a given index (full or partial).
/// May throw if the index would lead to out of bounds access.
template
<
typename
...
Ix
>
ssize_t
offset_at
(
Ix
...
index
)
const
{
if
(
sizeof
...(
index
)
>
ndim
())
if
(
(
ssize_t
)
sizeof
...(
index
)
>
ndim
())
fail_dim_check
(
sizeof
...(
index
),
"too many indices for an array"
);
return
byte_offset
(
size_t
(
index
)...);
return
byte_offset
(
s
s
ize_t
(
index
)...);
}
ssize_t
offset_at
()
const
{
return
0
;
}
...
...
@@ -629,7 +629,7 @@ public:
/// Item count from beginning of the array to a given index (full or partial).
/// May throw if the index would lead to out of bounds access.
template
<
typename
...
Ix
>
ssize_t
index_at
(
Ix
...
index
)
const
{
return
offset_at
(
index
...)
/
static_cast
<
ssize_t
>
(
itemsize
()
);
return
offset_at
(
index
...)
/
itemsize
(
);
}
/** Returns a proxy object that provides access to the array's data without bounds or
...
...
@@ -638,7 +638,7 @@ public:
* and the caller must take care not to access invalid dimensions or dimension indices.
*/
template
<
typename
T
,
ssize_t
Dims
=
-
1
>
detail
::
unchecked_mutable_reference
<
T
,
Dims
>
mutable_unchecked
()
{
if
(
Dims
>=
0
&&
ndim
()
!=
(
size_t
)
Dims
)
if
(
Dims
>=
0
&&
ndim
()
!=
Dims
)
throw
std
::
domain_error
(
"array has incorrect number of dimensions: "
+
std
::
to_string
(
ndim
())
+
"; expected "
+
std
::
to_string
(
Dims
));
return
detail
::
unchecked_mutable_reference
<
T
,
Dims
>
(
mutable_data
(),
shape
(),
strides
(),
ndim
());
...
...
@@ -651,7 +651,7 @@ public:
* invalid dimensions or dimension indices.
*/
template
<
typename
T
,
ssize_t
Dims
=
-
1
>
detail
::
unchecked_reference
<
T
,
Dims
>
unchecked
()
const
{
if
(
Dims
>=
0
&&
ndim
()
!=
(
size_t
)
Dims
)
if
(
Dims
>=
0
&&
ndim
()
!=
Dims
)
throw
std
::
domain_error
(
"array has incorrect number of dimensions: "
+
std
::
to_string
(
ndim
())
+
"; expected "
+
std
::
to_string
(
Dims
));
return
detail
::
unchecked_reference
<
T
,
Dims
>
(
data
(),
shape
(),
strides
(),
ndim
());
...
...
@@ -690,14 +690,14 @@ public:
protected
:
template
<
typename
,
typename
>
friend
struct
detail
::
npy_format_descriptor
;
void
fail_dim_check
(
size_t
dim
,
const
std
::
string
&
msg
)
const
{
void
fail_dim_check
(
s
s
ize_t
dim
,
const
std
::
string
&
msg
)
const
{
throw
index_error
(
msg
+
": "
+
std
::
to_string
(
dim
)
+
" (ndim = "
+
std
::
to_string
(
ndim
())
+
")"
);
}
template
<
typename
...
Ix
>
ssize_t
byte_offset
(
Ix
...
index
)
const
{
check_dimensions
(
index
...);
return
detail
::
byte_offset_unsafe
(
strides
(),
size_t
(
index
)...);
return
detail
::
byte_offset_unsafe
(
strides
(),
s
s
ize_t
(
index
)...);
}
void
check_writeable
()
const
{
...
...
@@ -705,7 +705,7 @@ protected:
throw
std
::
domain_error
(
"array is not writeable"
);
}
static
std
::
vector
<
ssize_t
>
default_strides
(
const
std
::
vector
<
size_t
>&
shape
,
size_t
itemsize
)
{
static
std
::
vector
<
Py_intptr_t
>
default_strides
(
const
std
::
vector
<
Py_intptr_t
>&
shape
,
s
size_t
itemsize
)
{
auto
ndim
=
shape
.
size
();
std
::
vector
<
ssize_t
>
strides
(
ndim
);
if
(
ndim
)
{
...
...
@@ -718,12 +718,12 @@ protected:
}
template
<
typename
...
Ix
>
void
check_dimensions
(
Ix
...
index
)
const
{
check_dimensions_impl
(
s
ize_t
(
0
),
shape
(),
size_t
(
index
)...);
check_dimensions_impl
(
s
size_t
(
0
),
shape
(),
s
size_t
(
index
)...);
}
void
check_dimensions_impl
(
s
ize_t
,
const
size_t
*
)
const
{
}
void
check_dimensions_impl
(
s
size_t
,
const
s
size_t
*
)
const
{
}
template
<
typename
...
Ix
>
void
check_dimensions_impl
(
s
ize_t
axis
,
const
size_t
*
shape
,
size_t
i
,
Ix
...
index
)
const
{
template
<
typename
...
Ix
>
void
check_dimensions_impl
(
s
size_t
axis
,
const
ssize_t
*
shape
,
s
size_t
i
,
Ix
...
index
)
const
{
if
(
i
>=
*
shape
)
{
throw
index_error
(
std
::
string
(
"index "
)
+
std
::
to_string
(
i
)
+
" is out of bounds for axis "
+
std
::
to_string
(
axis
)
+
...
...
@@ -772,12 +772,12 @@ public:
explicit
array_t
(
size_t
count
,
const
T
*
ptr
=
nullptr
,
handle
base
=
handle
())
:
array
({
count
},
{},
ptr
,
base
)
{
}
constexpr
size_t
itemsize
()
const
{
constexpr
s
s
ize_t
itemsize
()
const
{
return
sizeof
(
T
);
}
template
<
typename
...
Ix
>
ssize_t
index_at
(
Ix
...
index
)
const
{
return
offset_at
(
index
...)
/
static_cast
<
ssize_t
>
(
itemsize
()
);
return
offset_at
(
index
...)
/
itemsize
(
);
}
template
<
typename
...
Ix
>
const
T
*
data
(
Ix
...
index
)
const
{
...
...
@@ -792,14 +792,14 @@ public:
template
<
typename
...
Ix
>
const
T
&
at
(
Ix
...
index
)
const
{
if
(
sizeof
...(
index
)
!=
ndim
())
fail_dim_check
(
sizeof
...(
index
),
"index dimension mismatch"
);
return
*
(
static_cast
<
const
T
*>
(
array
::
data
())
+
byte_offset
(
s
ize_t
(
index
)...)
/
static_cast
<
ssize_t
>
(
itemsize
()
));
return
*
(
static_cast
<
const
T
*>
(
array
::
data
())
+
byte_offset
(
s
size_t
(
index
)...)
/
itemsize
(
));
}
// Mutable reference to element at a given index
template
<
typename
...
Ix
>
T
&
mutable_at
(
Ix
...
index
)
{
if
(
sizeof
...(
index
)
!=
ndim
())
fail_dim_check
(
sizeof
...(
index
),
"index dimension mismatch"
);
return
*
(
static_cast
<
T
*>
(
array
::
mutable_data
())
+
byte_offset
(
s
ize_t
(
index
)...)
/
static_cast
<
ssize_t
>
(
itemsize
()
));
return
*
(
static_cast
<
T
*>
(
array
::
mutable_data
())
+
byte_offset
(
s
size_t
(
index
)...)
/
itemsize
(
));
}
/** Returns a proxy object that provides access to the array's data without bounds or
...
...
@@ -949,16 +949,16 @@ public:
struct
field_descriptor
{
const
char
*
name
;
size_t
offset
;
size_t
size
;
size_t
alignment
;
s
s
ize_t
offset
;
s
s
ize_t
size
;
s
s
ize_t
alignment
;
std
::
string
format
;
dtype
descr
;
};
inline
PYBIND11_NOINLINE
void
register_structured_dtype
(
const
std
::
initializer_list
<
field_descriptor
>&
fields
,
const
std
::
type_info
&
tinfo
,
size_t
itemsize
,
const
std
::
type_info
&
tinfo
,
s
s
ize_t
itemsize
,
bool
(
*
direct_converter
)(
PyObject
*
,
void
*&
))
{
auto
&
numpy_internals
=
get_numpy_internals
();
...
...
@@ -986,7 +986,7 @@ inline PYBIND11_NOINLINE void register_structured_dtype(
std
::
vector
<
field_descriptor
>
ordered_fields
(
fields
);
std
::
sort
(
ordered_fields
.
begin
(),
ordered_fields
.
end
(),
[](
const
field_descriptor
&
a
,
const
field_descriptor
&
b
)
{
return
a
.
offset
<
b
.
offset
;
});
size_t
offset
=
0
;
s
s
ize_t
offset
=
0
;
std
::
ostringstream
oss
;
oss
<<
"T{"
;
for
(
auto
&
field
:
ordered_fields
)
{
...
...
@@ -1142,7 +1142,7 @@ public:
common_iterator
()
:
p_ptr
(
0
),
m_strides
()
{}
common_iterator
(
void
*
ptr
,
const
container_type
&
strides
,
const
std
::
vector
<
size_t
>
&
shape
)
common_iterator
(
void
*
ptr
,
const
container_type
&
strides
,
const
container_type
&
shape
)
:
p_ptr
(
reinterpret_cast
<
char
*>
(
ptr
)),
m_strides
(
strides
.
size
())
{
m_strides
.
back
()
=
static_cast
<
value_type
>
(
strides
.
back
());
for
(
size_type
i
=
m_strides
.
size
()
-
1
;
i
!=
0
;
--
i
)
{
...
...
@@ -1167,18 +1167,18 @@ private:
template
<
size_t
N
>
class
multi_array_iterator
{
public
:
using
container_type
=
std
::
vector
<
size_t
>
;
using
container_type
=
std
::
vector
<
s
s
ize_t
>
;
multi_array_iterator
(
const
std
::
array
<
buffer_info
,
N
>
&
buffers
,
const
std
::
vector
<
size_t
>
&
shape
)
const
container_type
&
shape
)
:
m_shape
(
shape
.
size
()),
m_index
(
shape
.
size
(),
0
),
m_common_iterator
()
{
// Manual copy to avoid conversion warning if using std::copy
for
(
size_t
i
=
0
;
i
<
shape
.
size
();
++
i
)
m_shape
[
i
]
=
s
tatic_cast
<
container_type
::
value_type
>
(
shape
[
i
])
;
m_shape
[
i
]
=
s
hape
[
i
]
;
std
::
vector
<
ssize_t
>
strides
(
shape
.
size
());
container_type
strides
(
shape
.
size
());
for
(
size_t
i
=
0
;
i
<
N
;
++
i
)
init_common_iterator
(
buffers
[
i
],
shape
,
m_common_iterator
[
i
],
strides
);
}
...
...
@@ -1205,8 +1205,9 @@ private:
using
common_iter
=
common_iterator
;
void
init_common_iterator
(
const
buffer_info
&
buffer
,
const
std
::
vector
<
size_t
>
&
shape
,
common_iter
&
iterator
,
std
::
vector
<
ssize_t
>
&
strides
)
{
const
container_type
&
shape
,
common_iter
&
iterator
,
container_type
&
strides
)
{
auto
buffer_shape_iter
=
buffer
.
shape
.
rbegin
();
auto
buffer_strides_iter
=
buffer
.
strides
.
rbegin
();
auto
shape_iter
=
shape
.
rbegin
();
...
...
@@ -1245,13 +1246,13 @@ enum class broadcast_trivial { non_trivial, c_trivial, f_trivial };
// singleton or a full-size, C-contiguous (`c_trivial`) or Fortran-contiguous (`f_trivial`) storage
// buffer; returns `non_trivial` otherwise.
template
<
size_t
N
>
broadcast_trivial
broadcast
(
const
std
::
array
<
buffer_info
,
N
>
&
buffers
,
s
ize_t
&
ndim
,
std
::
vector
<
size_t
>
&
shape
)
{
ndim
=
std
::
accumulate
(
buffers
.
begin
(),
buffers
.
end
(),
s
ize_t
(
0
),
[](
size_t
res
,
const
buffer_info
&
buf
)
{
broadcast_trivial
broadcast
(
const
std
::
array
<
buffer_info
,
N
>
&
buffers
,
s
size_t
&
ndim
,
std
::
vector
<
s
size_t
>
&
shape
)
{
ndim
=
std
::
accumulate
(
buffers
.
begin
(),
buffers
.
end
(),
s
size_t
(
0
),
[](
s
size_t
res
,
const
buffer_info
&
buf
)
{
return
std
::
max
(
res
,
buf
.
ndim
);
});
shape
.
clear
();
shape
.
resize
(
ndim
,
1
);
shape
.
resize
(
(
size_t
)
ndim
,
1
);
// Figure out the output size, and make sure all input arrays conform (i.e. are either size 1 or
// the full size).
...
...
@@ -1286,11 +1287,10 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, size_t &n
// Check for C contiguity (but only if previous inputs were also C contiguous)
if
(
trivial_broadcast_c
)
{
ssize_t
expect_stride
=
static_cast
<
ssize_t
>
(
buffers
[
i
].
itemsize
)
;
ssize_t
expect_stride
=
buffers
[
i
].
itemsize
;
auto
end
=
buffers
[
i
].
shape
.
crend
();
auto
shape_iter
=
buffers
[
i
].
shape
.
crbegin
();
auto
stride_iter
=
buffers
[
i
].
strides
.
crbegin
();
for
(;
trivial_broadcast_c
&&
shape_iter
!=
end
;
++
shape_iter
,
++
stride_iter
)
{
for
(
auto
shape_iter
=
buffers
[
i
].
shape
.
crbegin
(),
stride_iter
=
buffers
[
i
].
strides
.
crbegin
();
trivial_broadcast_c
&&
shape_iter
!=
end
;
++
shape_iter
,
++
stride_iter
)
{
if
(
expect_stride
==
*
stride_iter
)
expect_stride
*=
*
shape_iter
;
else
...
...
@@ -1300,11 +1300,10 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, size_t &n
// Check for Fortran contiguity (if previous inputs were also F contiguous)
if
(
trivial_broadcast_f
)
{
ssize_t
expect_stride
=
static_cast
<
ssize_t
>
(
buffers
[
i
].
itemsize
)
;
ssize_t
expect_stride
=
buffers
[
i
].
itemsize
;
auto
end
=
buffers
[
i
].
shape
.
cend
();
auto
shape_iter
=
buffers
[
i
].
shape
.
cbegin
();
auto
stride_iter
=
buffers
[
i
].
strides
.
cbegin
();
for
(;
trivial_broadcast_f
&&
shape_iter
!=
end
;
++
shape_iter
,
++
stride_iter
)
{
for
(
auto
shape_iter
=
buffers
[
i
].
shape
.
cbegin
(),
stride_iter
=
buffers
[
i
].
strides
.
cbegin
();
trivial_broadcast_f
&&
shape_iter
!=
end
;
++
shape_iter
,
++
stride_iter
)
{
if
(
expect_stride
==
*
stride_iter
)
expect_stride
*=
*
shape_iter
;
else
...
...
@@ -1336,25 +1335,26 @@ struct vectorize_helper {
std
::
array
<
buffer_info
,
N
>
buffers
{{
args
.
request
()...
}};
/* Determine dimensions parameters of output array */
size_t
ndim
=
0
;
std
::
vector
<
size_t
>
shape
(
0
);
auto
trivial
=
broadcast
(
buffers
,
ndim
,
shape
);
ssize_t
nd
=
0
;
std
::
vector
<
ssize_t
>
shape
(
0
);
auto
trivial
=
broadcast
(
buffers
,
nd
,
shape
);
size_t
ndim
=
(
size_t
)
nd
;
size_t
size
=
1
;
s
s
ize_t
size
=
1
;
std
::
vector
<
ssize_t
>
strides
(
ndim
);
if
(
ndim
>
0
)
{
if
(
trivial
==
broadcast_trivial
::
f_trivial
)
{
strides
[
0
]
=
s
tatic_cast
<
ssize_t
>
(
sizeof
(
Return
)
);
strides
[
0
]
=
s
izeof
(
Return
);
for
(
size_t
i
=
1
;
i
<
ndim
;
++
i
)
{
strides
[
i
]
=
strides
[
i
-
1
]
*
s
tatic_cast
<
ssize_t
>
(
shape
[
i
-
1
])
;
strides
[
i
]
=
strides
[
i
-
1
]
*
s
hape
[
i
-
1
]
;
size
*=
shape
[
i
-
1
];
}
size
*=
shape
[
ndim
-
1
];
}
else
{
strides
[
ndim
-
1
]
=
s
tatic_cast
<
ssize_t
>
(
sizeof
(
Return
)
);
strides
[
ndim
-
1
]
=
s
izeof
(
Return
);
for
(
size_t
i
=
ndim
-
1
;
i
>
0
;
--
i
)
{
strides
[
i
-
1
]
=
strides
[
i
]
*
s
tatic_cast
<
ssize_t
>
(
shape
[
i
])
;
strides
[
i
-
1
]
=
strides
[
i
]
*
s
hape
[
i
]
;
size
*=
shape
[
i
];
}
size
*=
shape
[
0
];
...
...
@@ -1372,7 +1372,7 @@ struct vectorize_helper {
if
(
trivial
==
broadcast_trivial
::
non_trivial
)
{
apply_broadcast
<
Index
...
>
(
buffers
,
buf
,
index
);
}
else
{
for
(
size_t
i
=
0
;
i
<
size
;
++
i
)
for
(
s
s
ize_t
i
=
0
;
i
<
size
;
++
i
)
output
[
i
]
=
f
((
reinterpret_cast
<
Args
*>
(
buffers
[
Index
].
ptr
)[
buffers
[
Index
].
size
==
1
?
0
:
i
])...);
}
...
...
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
(),
s
izeof
(
T
),
format_descriptor
<
T
>::
format
(),
1
,
{
v
.
size
()},
{
sizeof
(
T
)});
return
buffer_info
(
v
.
data
(),
s
tatic_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
(
s
ize_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
()(
s
ize_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
()(
s
ize_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
s
ize_t
rows
()
const
{
return
m_rows
;
}
s
s
ize_t
cols
()
const
{
return
m_cols
;
}
private
:
size_t
m_rows
;
size_t
m_cols
;
s
s
ize_t
m_rows
;
s
s
ize_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
<
s
ize_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
<
s
ize_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
<
s
ize_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 */
{
s
tatic_cast
<
ssize_t
>
(
sizeof
(
float
)
*
m
.
rows
()),
/* Strides (in bytes) for each index */
s
tatic_cast
<
ssize_t
>
(
sizeof
(
float
)
)
}
{
s
izeof
(
float
)
*
size_t
(
m
.
rows
()),
/* Strides (in bytes) for each index */
s
izeof
(
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
s
ize_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
s
ize_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
(
s
ize_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
(
s
ize_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
s
ize_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
s
ize_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
s
ize_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
s
s
ize_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
s
ize_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
s
s
ize_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
s
s
ize_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
s
ize_t
k
=
0
;
k
<
r
.
shape
(
2
);
k
++
)
for
(
s
s
ize_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
s
s
ize_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
s
ize_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
s
ize_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
s
s
ize_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
s
ize_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
s
s
ize_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
s
s
ize_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
s
ize_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
s
ize_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
s
ize_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
s
ize_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
s
ize_t
ndim
;
std
::
vector
<
s
s
ize_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