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
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
203 additions
and
201 deletions
+203
-201
docs/advanced/pycpp/numpy.rst
+15
-18
include/pybind11/buffer_info.h
+12
-12
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.
...
@@ -57,10 +57,10 @@ specification.
struct buffer_info {
struct buffer_info {
void *ptr;
void *ptr;
size_t itemsize;
s
s
ize_t itemsize;
std::string format;
std::string format;
in
t ndim;
ssize_
t ndim;
std::vector<size_t> shape;
std::vector<s
s
ize_t> shape;
std::vector<ssize_t> strides;
std::vector<ssize_t> strides;
};
};
...
@@ -95,8 +95,8 @@ buffer objects (e.g. a NumPy matrix).
...
@@ -95,8 +95,8 @@ buffer objects (e.g. a NumPy matrix).
throw std::runtime_error("Incompatible buffer dimension!");
throw std::runtime_error("Incompatible buffer dimension!");
auto strides = Strides(
auto strides = Strides(
info.strides[rowMajor ? 0 : 1] / sizeof(Scalar),
info.strides[rowMajor ? 0 : 1] /
(py::ssize_t)
sizeof(Scalar),
info.strides[rowMajor ? 1 : 0] / sizeof(Scalar));
info.strides[rowMajor ? 1 : 0] /
(py::ssize_t)
sizeof(Scalar));
auto map = Eigen::Map<Matrix, 0, Strides>(
auto map = Eigen::Map<Matrix, 0, Strides>(
static_cat<Scalar *>(info.ptr), info.shape[0], info.shape[1], strides);
static_cat<Scalar *>(info.ptr), info.shape[0], info.shape[1], strides);
...
@@ -113,15 +113,12 @@ as follows:
...
@@ -113,15 +113,12 @@ as follows:
return py::buffer_info(
return py::buffer_info(
m.data(), /* Pointer to buffer */
m.data(), /* Pointer to buffer */
sizeof(Scalar), /* Size of one scalar */
sizeof(Scalar), /* Size of one scalar */
/* Python struct-style format descriptor */
py::format_descriptor<Scalar>::format(), /* Python struct-style format descriptor */
py::format_descriptor<Scalar>::format(),
2, /* Number of dimensions */
/* Number of dimensions */
{ m.rows(), m.cols() }, /* Buffer dimensions */
2,
/* Buffer dimensions */
{ m.rows(), m.cols() },
/* Strides (in bytes) for each index */
{ sizeof(Scalar) * (rowMajor ? m.cols() : 1),
{ sizeof(Scalar) * (rowMajor ? m.cols() : 1),
sizeof(Scalar) * (rowMajor ? 1 : m.rows()) }
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:
...
@@ -321,17 +318,17 @@ where ``N`` gives the required dimensionality of the array:
m.def("sum_3d", [](py::array_t<double> x) {
m.def("sum_3d", [](py::array_t<double> x) {
auto r = x.unchecked<3>(); // x must have ndim = 3; can be non-writeable
auto r = x.unchecked<3>(); // x must have ndim = 3; can be non-writeable
double sum = 0;
double sum = 0;
for (size_t i = 0; i < r.shape(0); i++)
for (s
s
ize_t i = 0; i < r.shape(0); i++)
for (size_t j = 0; j < r.shape(1); j++)
for (s
s
ize_t j = 0; j < r.shape(1); j++)
for (size_t k = 0; k < r.shape(2); k++)
for (s
s
ize_t k = 0; k < r.shape(2); k++)
sum += r(i, j, k);
sum += r(i, j, k);
return sum;
return sum;
});
});
m.def("increment_3d", [](py::array_t<double> x) {
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
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 (s
s
ize_t i = 0; i < r.shape(0); i++)
for (size_t j = 0; j < r.shape(1); j++)
for (s
s
ize_t j = 0; j < r.shape(1); j++)
for (size_t k = 0; k < r.shape(2); k++)
for (s
s
ize_t k = 0; k < r.shape(2); k++)
r(i, j, k) += 1.0;
r(i, j, k) += 1.0;
}, py::arg().noconvert());
}, py::arg().noconvert());
...
...
include/pybind11/buffer_info.h
View file @
30d43c49
...
@@ -16,30 +16,30 @@ NAMESPACE_BEGIN(pybind11)
...
@@ -16,30 +16,30 @@ NAMESPACE_BEGIN(pybind11)
/// Information record describing a Python buffer object
/// Information record describing a Python buffer object
struct
buffer_info
{
struct
buffer_info
{
void
*
ptr
=
nullptr
;
// Pointer to the underlying storage
void
*
ptr
=
nullptr
;
// Pointer to the underlying storage
size_t
itemsize
=
0
;
// Size of individual items in bytes
s
s
ize_t
itemsize
=
0
;
// Size of individual items in bytes
size_t
size
=
0
;
// Total number of entries
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()
std
::
string
format
;
// For homogeneous buffers, this should be set to format_descriptor<T>::format()
size_t
ndim
=
0
;
// Number of dimensions
s
s
ize_t
ndim
=
0
;
// Number of dimensions
std
::
vector
<
size_t
>
shape
;
// Shape of the tensor (1 entry per dimension)
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)
std
::
vector
<
ssize_t
>
strides
;
// Number of entries between adjacent entries (for each per dimension)
buffer_info
()
{
}
buffer_info
()
{
}
buffer_info
(
void
*
ptr
,
s
ize_t
itemsize
,
const
std
::
string
&
format
,
size_t
ndim
,
buffer_info
(
void
*
ptr
,
s
size_t
itemsize
,
const
std
::
string
&
format
,
s
size_t
ndim
,
detail
::
any_container
<
size_t
>
shape_in
,
detail
::
any_container
<
ssize_t
>
strides_in
)
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
),
:
ptr
(
ptr
),
itemsize
(
itemsize
),
size
(
1
),
format
(
format
),
ndim
(
ndim
),
shape
(
std
::
move
(
shape_in
)),
strides
(
std
::
move
(
strides_in
))
{
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"
);
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
];
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
})
{
}
:
buffer_info
(
ptr
,
itemsize
,
format
,
1
,
{
size
},
{
itemsize
})
{
}
explicit
buffer_info
(
Py_buffer
*
view
,
bool
ownview
=
true
)
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
})
{
{
view
->
shape
,
view
->
shape
+
view
->
ndim
},
{
view
->
strides
,
view
->
strides
+
view
->
ndim
})
{
this
->
view
=
view
;
this
->
view
=
view
;
this
->
ownview
=
ownview
;
this
->
ownview
=
ownview
;
...
@@ -78,13 +78,13 @@ NAMESPACE_BEGIN(detail)
...
@@ -78,13 +78,13 @@ NAMESPACE_BEGIN(detail)
template
<
typename
T
,
typename
SFINAE
=
void
>
struct
compare_buffer_info
{
template
<
typename
T
,
typename
SFINAE
=
void
>
struct
compare_buffer_info
{
static
bool
compare
(
const
buffer_info
&
b
)
{
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
>>
{
template
<
typename
T
>
struct
compare_buffer_info
<
T
,
detail
::
enable_if_t
<
std
::
is_integral
<
T
>::
value
>>
{
static
bool
compare
(
const
buffer_info
&
b
)
{
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
(
long
))
&&
b
.
format
==
(
std
::
is_unsigned
<
T
>::
value
?
"L"
:
"l"
))
||
((
sizeof
(
T
)
==
sizeof
(
size_t
))
&&
b
.
format
==
(
std
::
is_unsigned
<
T
>::
value
?
"N"
:
"n"
)));
((
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) {
...
@@ -433,7 +433,7 @@ inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) {
#endif
#endif
type
->
tp_flags
|=
Py_TPFLAGS_HAVE_GC
;
type
->
tp_flags
|=
Py_TPFLAGS_HAVE_GC
;
type
->
tp_dictoffset
=
type
->
tp_basicsize
;
// place dict at the end
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_traverse
=
pybind11_traverse
;
type
->
tp_clear
=
pybind11_clear
;
type
->
tp_clear
=
pybind11_clear
;
...
@@ -459,18 +459,16 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
...
@@ -459,18 +459,16 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
view
->
ndim
=
1
;
view
->
ndim
=
1
;
view
->
internal
=
info
;
view
->
internal
=
info
;
view
->
buf
=
info
->
ptr
;
view
->
buf
=
info
->
ptr
;
view
->
itemsize
=
(
Py_ssize_t
)
info
->
itemsize
;
view
->
itemsize
=
info
->
itemsize
;
view
->
len
=
view
->
itemsize
;
view
->
len
=
view
->
itemsize
;
for
(
auto
s
:
info
->
shape
)
for
(
auto
s
:
info
->
shape
)
view
->
len
*=
(
Py_ssize_t
)
s
;
view
->
len
*=
s
;
if
((
flags
&
PyBUF_FORMAT
)
==
PyBUF_FORMAT
)
if
((
flags
&
PyBUF_FORMAT
)
==
PyBUF_FORMAT
)
view
->
format
=
const_cast
<
char
*>
(
info
->
format
.
c_str
());
view
->
format
=
const_cast
<
char
*>
(
info
->
format
.
c_str
());
if
((
flags
&
PyBUF_STRIDES
)
==
PyBUF_STRIDES
)
{
if
((
flags
&
PyBUF_STRIDES
)
==
PyBUF_STRIDES
)
{
view
->
ndim
=
(
int
)
info
->
ndim
;
view
->
ndim
=
(
int
)
info
->
ndim
;
view
->
strides
=
&
info
->
strides
[
0
];
view
->
strides
=
&
info
->
strides
[
0
];
// Next is a pointer cast, let's make sure it's safe.
view
->
shape
=
&
info
->
shape
[
0
];
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
];
}
}
Py_INCREF
(
view
->
obj
);
Py_INCREF
(
view
->
obj
);
return
0
;
return
0
;
...
...
include/pybind11/eigen.h
View file @
30d43c49
...
@@ -68,7 +68,7 @@ template <typename T> using is_eigen_other = all_of<
...
@@ -68,7 +68,7 @@ template <typename T> using is_eigen_other = all_of<
template
<
bool
EigenRowMajor
>
struct
EigenConformable
{
template
<
bool
EigenRowMajor
>
struct
EigenConformable
{
bool
conformable
=
false
;
bool
conformable
=
false
;
EigenIndex
rows
=
0
,
cols
=
0
;
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!
bool
negativestrides
=
false
;
// If true, do not use stride!
EigenConformable
(
bool
fits
=
false
)
:
conformable
{
fits
}
{}
EigenConformable
(
bool
fits
=
false
)
:
conformable
{
fits
}
{}
...
@@ -207,7 +207,7 @@ template <typename Type_> struct EigenProps {
...
@@ -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,
// 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.
// 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
)
{
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
;
array
a
;
if
(
props
::
vector
)
if
(
props
::
vector
)
a
=
array
({
src
.
size
()
},
{
elem_size
*
src
.
innerStride
()
},
src
.
data
(),
base
);
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>> {
...
@@ -581,9 +581,9 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
object
matrix_type
=
module
::
import
(
"scipy.sparse"
).
attr
(
object
matrix_type
=
module
::
import
(
"scipy.sparse"
).
attr
(
rowMajor
?
"csr_matrix"
:
"csc_matrix"
);
rowMajor
?
"csr_matrix"
:
"csc_matrix"
);
array
data
(
(
size_t
)
src
.
nonZeros
(),
src
.
valuePtr
());
array
data
(
src
.
nonZeros
(),
src
.
valuePtr
());
array
outerIndices
((
size_t
)
(
rowMajor
?
src
.
rows
()
:
src
.
cols
())
+
1
,
src
.
outerIndexPtr
());
array
outerIndices
((
rowMajor
?
src
.
rows
()
:
src
.
cols
())
+
1
,
src
.
outerIndexPtr
());
array
innerIndices
(
(
size_t
)
src
.
nonZeros
(),
src
.
innerIndexPtr
());
array
innerIndices
(
src
.
nonZeros
(),
src
.
innerIndexPtr
());
return
matrix_type
(
return
matrix_type
(
std
::
make_tuple
(
data
,
innerIndices
,
outerIndices
),
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<
...
@@ -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
>
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
<
s
s
ize_t
Dim
=
0
,
typename
Strides
>
ssize_t
byte_offset_unsafe
(
const
Strides
&
)
{
return
0
;
}
template
<
size_t
Dim
=
0
,
typename
Strides
,
typename
...
Ix
>
template
<
s
s
ize_t
Dim
=
0
,
typename
Strides
,
typename
...
Ix
>
ssize_t
byte_offset_unsafe
(
const
Strides
&
strides
,
size_t
i
,
Ix
...
index
)
{
ssize_t
byte_offset_unsafe
(
const
Strides
&
strides
,
s
s
ize_t
i
,
Ix
...
index
)
{
return
static_cast
<
ssize_t
>
(
i
)
*
strides
[
Dim
]
+
byte_offset_unsafe
<
Dim
+
1
>
(
strides
,
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
/** Proxy class providing unsafe, unchecked const access to array data. This is constructed through
...
@@ -268,23 +268,23 @@ protected:
...
@@ -268,23 +268,23 @@ protected:
const
unsigned
char
*
data_
;
const
unsigned
char
*
data_
;
// Storing the shape & strides in local variables (i.e. these arrays) allows the compiler to
// 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
// 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
s
size_t
*
,
std
::
array
<
ssize_t
,
(
size_t
)
Dims
>>
conditional_t
<
Dynamic
,
const
ssize_t
*
,
std
::
array
<
ssize_t
,
(
size_t
)
Dims
>>
strides_
;
shape_
,
strides_
;
const
size_t
dims_
;
const
s
s
ize_t
dims_
;
friend
class
pybind11
::
array
;
friend
class
pybind11
::
array
;
// Constructor for compile-time dimensions:
// Constructor for compile-time dimensions:
template
<
bool
Dyn
=
Dynamic
>
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
}
{
:
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
];
shape_
[
i
]
=
shape
[
i
];
strides_
[
i
]
=
strides
[
i
];
strides_
[
i
]
=
strides
[
i
];
}
}
}
}
// Constructor for runtime dimensions:
// Constructor for runtime dimensions:
template
<
bool
Dyn
=
Dynamic
>
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
}
{}
:
data_
{
reinterpret_cast
<
const
unsigned
char
*>
(
data
)},
shape_
{
shape
},
strides_
{
strides
},
dims_
{
dims
}
{}
public
:
public
:
...
@@ -295,39 +295,39 @@ public:
...
@@ -295,39 +295,39 @@ public:
template
<
typename
...
Ix
>
const
T
&
operator
()(
Ix
...
index
)
const
{
template
<
typename
...
Ix
>
const
T
&
operator
()(
Ix
...
index
)
const
{
static_assert
(
sizeof
...(
Ix
)
==
Dims
||
Dynamic
,
static_assert
(
sizeof
...(
Ix
)
==
Dims
||
Dynamic
,
"Invalid number of indices for unchecked array reference"
);
"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
/** 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)`.
* 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
>>
template
<
s
s
ize_t
D
=
Dims
,
typename
=
enable_if_t
<
D
==
1
||
Dynamic
>>
const
T
&
operator
[](
size_t
index
)
const
{
return
operator
()(
index
);
}
const
T
&
operator
[](
s
s
ize_t
index
)
const
{
return
operator
()(
index
);
}
/// Pointer access to the data at the given indices.
/// 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)
/// 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`
/// 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
/// 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
/// Returns the total number of elements in the referenced array, i.e. the product of the shapes
template
<
bool
Dyn
=
Dynamic
>
template
<
bool
Dyn
=
Dynamic
>
enable_if_t
<!
Dyn
,
size_t
>
size
()
const
{
enable_if_t
<!
Dyn
,
s
s
ize_t
>
size
()
const
{
return
std
::
accumulate
(
shape_
.
begin
(),
shape_
.
end
(),
(
s
ize_t
)
1
,
std
::
multiplies
<
size_t
>
());
return
std
::
accumulate
(
shape_
.
begin
(),
shape_
.
end
(),
(
s
size_t
)
1
,
std
::
multiplies
<
s
size_t
>
());
}
}
template
<
bool
Dyn
=
Dynamic
>
template
<
bool
Dyn
=
Dynamic
>
enable_if_t
<
Dyn
,
size_t
>
size
()
const
{
enable_if_t
<
Dyn
,
s
s
ize_t
>
size
()
const
{
return
std
::
accumulate
(
shape_
,
shape_
+
ndim
(),
(
s
ize_t
)
1
,
std
::
multiplies
<
size_t
>
());
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
/// 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).
/// 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
();
return
size
()
*
itemsize
();
}
}
};
};
...
@@ -349,11 +349,11 @@ public:
...
@@ -349,11 +349,11 @@ public:
* reference is to a 1-dimensional array (or has runtime dimensions). When present, this is
* reference is to a 1-dimensional array (or has runtime dimensions). When present, this is
* exactly equivalent to `obj(index)`.
* exactly equivalent to `obj(index)`.
*/
*/
template
<
size_t
D
=
Dims
,
typename
=
enable_if_t
<
D
==
1
||
Dynamic
>>
template
<
s
s
ize_t
D
=
Dims
,
typename
=
enable_if_t
<
D
==
1
||
Dynamic
>>
T
&
operator
[](
size_t
index
)
{
return
operator
()(
index
);
}
T
&
operator
[](
s
s
ize_t
index
)
{
return
operator
()(
index
);
}
/// Mutable pointer access to the data at the given indices.
/// 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
>
template
<
typename
T
,
ssize_t
Dim
>
...
@@ -381,7 +381,7 @@ public:
...
@@ -381,7 +381,7 @@ public:
dtype
(
const
char
*
format
)
:
dtype
(
std
::
string
(
format
))
{
}
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
;
dict
args
;
args
[
"names"
]
=
names
;
args
[
"names"
]
=
names
;
args
[
"formats"
]
=
formats
;
args
[
"formats"
]
=
formats
;
...
@@ -404,8 +404,8 @@ public:
...
@@ -404,8 +404,8 @@ public:
}
}
/// Size of the data type in bytes.
/// Size of the data type in bytes.
size_t
itemsize
()
const
{
s
s
ize_t
itemsize
()
const
{
return
(
size_t
)
detail
::
array_descriptor_proxy
(
m_ptr
)
->
elsize
;
return
detail
::
array_descriptor_proxy
(
m_ptr
)
->
elsize
;
}
}
/// Returns true for structured data types.
/// Returns true for structured data types.
...
@@ -425,7 +425,7 @@ private:
...
@@ -425,7 +425,7 @@ private:
return
reinterpret_borrow
<
object
>
(
obj
);
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
// Recursively strip all void fields with empty names that are generated for
// padding fields (as of NumPy v1.11).
// padding fields (as of NumPy v1.11).
if
(
!
has_fields
())
if
(
!
has_fields
())
...
@@ -501,7 +501,7 @@ public:
...
@@ -501,7 +501,7 @@ public:
api
.
PyArray_Type_
,
descr
.
release
().
ptr
(),
(
int
)
ndim
,
shape
->
data
(),
strides
->
data
(),
api
.
PyArray_Type_
,
descr
.
release
().
ptr
(),
(
int
)
ndim
,
shape
->
data
(),
strides
->
data
(),
const_cast
<
void
*>
(
ptr
),
flags
,
nullptr
));
const_cast
<
void
*>
(
ptr
),
flags
,
nullptr
));
if
(
!
tmp
)
if
(
!
tmp
)
pybind11_fail
(
"NumPy: unable to create array!"
);
throw
error_already_set
(
);
if
(
ptr
)
{
if
(
ptr
)
{
if
(
base
)
{
if
(
base
)
{
api
.
PyArray_SetBaseObject_
(
tmp
.
ptr
(),
base
.
inc_ref
().
ptr
());
api
.
PyArray_SetBaseObject_
(
tmp
.
ptr
(),
base
.
inc_ref
().
ptr
());
...
@@ -528,7 +528,7 @@ public:
...
@@ -528,7 +528,7 @@ public:
:
array
(
std
::
move
(
shape
),
{},
ptr
,
base
)
{
}
:
array
(
std
::
move
(
shape
),
{},
ptr
,
base
)
{
}
template
<
typename
T
>
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
)
explicit
array
(
const
buffer_info
&
info
)
:
array
(
pybind11
::
dtype
(
info
),
info
.
shape
,
info
.
strides
,
info
.
ptr
)
{
}
:
array
(
pybind11
::
dtype
(
info
),
info
.
shape
,
info
.
strides
,
info
.
ptr
)
{
}
...
@@ -539,23 +539,23 @@ public:
...
@@ -539,23 +539,23 @@ public:
}
}
/// Total number of elements
/// Total number of elements
size_t
size
()
const
{
s
s
ize_t
size
()
const
{
return
std
::
accumulate
(
shape
(),
shape
()
+
ndim
(),
(
s
ize_t
)
1
,
std
::
multiplies
<
size_t
>
());
return
std
::
accumulate
(
shape
(),
shape
()
+
ndim
(),
(
s
size_t
)
1
,
std
::
multiplies
<
s
size_t
>
());
}
}
/// Byte size of a single element
/// Byte size of a single element
size_t
itemsize
()
const
{
s
s
ize_t
itemsize
()
const
{
return
(
size_t
)
detail
::
array_descriptor_proxy
(
detail
::
array_proxy
(
m_ptr
)
->
descr
)
->
elsize
;
return
detail
::
array_descriptor_proxy
(
detail
::
array_proxy
(
m_ptr
)
->
descr
)
->
elsize
;
}
}
/// Total number of bytes
/// Total number of bytes
size_t
nbytes
()
const
{
s
s
ize_t
nbytes
()
const
{
return
size
()
*
itemsize
();
return
size
()
*
itemsize
();
}
}
/// Number of dimensions
/// Number of dimensions
size_t
ndim
()
const
{
s
s
ize_t
ndim
()
const
{
return
(
size_t
)
detail
::
array_proxy
(
m_ptr
)
->
nd
;
return
detail
::
array_proxy
(
m_ptr
)
->
nd
;
}
}
/// Base object
/// Base object
...
@@ -564,12 +564,12 @@ public:
...
@@ -564,12 +564,12 @@ public:
}
}
/// Dimensions of the array
/// Dimensions of the array
const
size_t
*
shape
()
const
{
const
s
s
ize_t
*
shape
()
const
{
return
reinterpret_cast
<
const
size_t
*>
(
detail
::
array_proxy
(
m_ptr
)
->
dimensions
)
;
return
detail
::
array_proxy
(
m_ptr
)
->
dimensions
;
}
}
/// Dimension along a given axis
/// 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
())
if
(
dim
>=
ndim
())
fail_dim_check
(
dim
,
"invalid axis"
);
fail_dim_check
(
dim
,
"invalid axis"
);
return
shape
()[
dim
];
return
shape
()[
dim
];
...
@@ -577,11 +577,11 @@ public:
...
@@ -577,11 +577,11 @@ public:
/// Strides of the array
/// Strides of the array
const
ssize_t
*
strides
()
const
{
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
/// Stride along a given axis
ssize_t
strides
(
size_t
dim
)
const
{
ssize_t
strides
(
s
s
ize_t
dim
)
const
{
if
(
dim
>=
ndim
())
if
(
dim
>=
ndim
())
fail_dim_check
(
dim
,
"invalid axis"
);
fail_dim_check
(
dim
,
"invalid axis"
);
return
strides
()[
dim
];
return
strides
()[
dim
];
...
@@ -619,9 +619,9 @@ public:
...
@@ -619,9 +619,9 @@ public:
/// Byte offset from beginning of the array to a given index (full or partial).
/// 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.
/// May throw if the index would lead to out of bounds access.
template
<
typename
...
Ix
>
ssize_t
offset_at
(
Ix
...
index
)
const
{
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"
);
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
;
}
ssize_t
offset_at
()
const
{
return
0
;
}
...
@@ -629,7 +629,7 @@ public:
...
@@ -629,7 +629,7 @@ public:
/// Item count from beginning of the array to a given index (full or partial).
/// 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.
/// May throw if the index would lead to out of bounds access.
template
<
typename
...
Ix
>
ssize_t
index_at
(
Ix
...
index
)
const
{
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
/** Returns a proxy object that provides access to the array's data without bounds or
...
@@ -638,7 +638,7 @@ public:
...
@@ -638,7 +638,7 @@ public:
* and the caller must take care not to access invalid dimensions or dimension indices.
* 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
()
{
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
())
+
throw
std
::
domain_error
(
"array has incorrect number of dimensions: "
+
std
::
to_string
(
ndim
())
+
"; expected "
+
std
::
to_string
(
Dims
));
"; expected "
+
std
::
to_string
(
Dims
));
return
detail
::
unchecked_mutable_reference
<
T
,
Dims
>
(
mutable_data
(),
shape
(),
strides
(),
ndim
());
return
detail
::
unchecked_mutable_reference
<
T
,
Dims
>
(
mutable_data
(),
shape
(),
strides
(),
ndim
());
...
@@ -651,7 +651,7 @@ public:
...
@@ -651,7 +651,7 @@ public:
* invalid dimensions or dimension indices.
* invalid dimensions or dimension indices.
*/
*/
template
<
typename
T
,
ssize_t
Dims
=
-
1
>
detail
::
unchecked_reference
<
T
,
Dims
>
unchecked
()
const
{
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
())
+
throw
std
::
domain_error
(
"array has incorrect number of dimensions: "
+
std
::
to_string
(
ndim
())
+
"; expected "
+
std
::
to_string
(
Dims
));
"; expected "
+
std
::
to_string
(
Dims
));
return
detail
::
unchecked_reference
<
T
,
Dims
>
(
data
(),
shape
(),
strides
(),
ndim
());
return
detail
::
unchecked_reference
<
T
,
Dims
>
(
data
(),
shape
(),
strides
(),
ndim
());
...
@@ -690,14 +690,14 @@ public:
...
@@ -690,14 +690,14 @@ public:
protected
:
protected
:
template
<
typename
,
typename
>
friend
struct
detail
::
npy_format_descriptor
;
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
)
+
throw
index_error
(
msg
+
": "
+
std
::
to_string
(
dim
)
+
" (ndim = "
+
std
::
to_string
(
ndim
())
+
")"
);
" (ndim = "
+
std
::
to_string
(
ndim
())
+
")"
);
}
}
template
<
typename
...
Ix
>
ssize_t
byte_offset
(
Ix
...
index
)
const
{
template
<
typename
...
Ix
>
ssize_t
byte_offset
(
Ix
...
index
)
const
{
check_dimensions
(
index
...);
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
{
void
check_writeable
()
const
{
...
@@ -705,7 +705,7 @@ protected:
...
@@ -705,7 +705,7 @@ protected:
throw
std
::
domain_error
(
"array is not writeable"
);
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
();
auto
ndim
=
shape
.
size
();
std
::
vector
<
ssize_t
>
strides
(
ndim
);
std
::
vector
<
ssize_t
>
strides
(
ndim
);
if
(
ndim
)
{
if
(
ndim
)
{
...
@@ -718,12 +718,12 @@ protected:
...
@@ -718,12 +718,12 @@ protected:
}
}
template
<
typename
...
Ix
>
void
check_dimensions
(
Ix
...
index
)
const
{
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
)
{
if
(
i
>=
*
shape
)
{
throw
index_error
(
std
::
string
(
"index "
)
+
std
::
to_string
(
i
)
+
throw
index_error
(
std
::
string
(
"index "
)
+
std
::
to_string
(
i
)
+
" is out of bounds for axis "
+
std
::
to_string
(
axis
)
+
" is out of bounds for axis "
+
std
::
to_string
(
axis
)
+
...
@@ -772,12 +772,12 @@ public:
...
@@ -772,12 +772,12 @@ public:
explicit
array_t
(
size_t
count
,
const
T
*
ptr
=
nullptr
,
handle
base
=
handle
())
explicit
array_t
(
size_t
count
,
const
T
*
ptr
=
nullptr
,
handle
base
=
handle
())
:
array
({
count
},
{},
ptr
,
base
)
{
}
:
array
({
count
},
{},
ptr
,
base
)
{
}
constexpr
size_t
itemsize
()
const
{
constexpr
s
s
ize_t
itemsize
()
const
{
return
sizeof
(
T
);
return
sizeof
(
T
);
}
}
template
<
typename
...
Ix
>
ssize_t
index_at
(
Ix
...
index
)
const
{
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
{
template
<
typename
...
Ix
>
const
T
*
data
(
Ix
...
index
)
const
{
...
@@ -792,14 +792,14 @@ public:
...
@@ -792,14 +792,14 @@ public:
template
<
typename
...
Ix
>
const
T
&
at
(
Ix
...
index
)
const
{
template
<
typename
...
Ix
>
const
T
&
at
(
Ix
...
index
)
const
{
if
(
sizeof
...(
index
)
!=
ndim
())
if
(
sizeof
...(
index
)
!=
ndim
())
fail_dim_check
(
sizeof
...(
index
),
"index dimension mismatch"
);
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
// Mutable reference to element at a given index
template
<
typename
...
Ix
>
T
&
mutable_at
(
Ix
...
index
)
{
template
<
typename
...
Ix
>
T
&
mutable_at
(
Ix
...
index
)
{
if
(
sizeof
...(
index
)
!=
ndim
())
if
(
sizeof
...(
index
)
!=
ndim
())
fail_dim_check
(
sizeof
...(
index
),
"index dimension mismatch"
);
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
/** Returns a proxy object that provides access to the array's data without bounds or
...
@@ -949,16 +949,16 @@ public:
...
@@ -949,16 +949,16 @@ public:
struct
field_descriptor
{
struct
field_descriptor
{
const
char
*
name
;
const
char
*
name
;
size_t
offset
;
s
s
ize_t
offset
;
size_t
size
;
s
s
ize_t
size
;
size_t
alignment
;
s
s
ize_t
alignment
;
std
::
string
format
;
std
::
string
format
;
dtype
descr
;
dtype
descr
;
};
};
inline
PYBIND11_NOINLINE
void
register_structured_dtype
(
inline
PYBIND11_NOINLINE
void
register_structured_dtype
(
const
std
::
initializer_list
<
field_descriptor
>&
fields
,
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
*&
))
{
bool
(
*
direct_converter
)(
PyObject
*
,
void
*&
))
{
auto
&
numpy_internals
=
get_numpy_internals
();
auto
&
numpy_internals
=
get_numpy_internals
();
...
@@ -986,7 +986,7 @@ inline PYBIND11_NOINLINE void register_structured_dtype(
...
@@ -986,7 +986,7 @@ inline PYBIND11_NOINLINE void register_structured_dtype(
std
::
vector
<
field_descriptor
>
ordered_fields
(
fields
);
std
::
vector
<
field_descriptor
>
ordered_fields
(
fields
);
std
::
sort
(
ordered_fields
.
begin
(),
ordered_fields
.
end
(),
std
::
sort
(
ordered_fields
.
begin
(),
ordered_fields
.
end
(),
[](
const
field_descriptor
&
a
,
const
field_descriptor
&
b
)
{
return
a
.
offset
<
b
.
offset
;
});
[](
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
;
std
::
ostringstream
oss
;
oss
<<
"T{"
;
oss
<<
"T{"
;
for
(
auto
&
field
:
ordered_fields
)
{
for
(
auto
&
field
:
ordered_fields
)
{
...
@@ -1142,7 +1142,7 @@ public:
...
@@ -1142,7 +1142,7 @@ public:
common_iterator
()
:
p_ptr
(
0
),
m_strides
()
{}
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
())
{
:
p_ptr
(
reinterpret_cast
<
char
*>
(
ptr
)),
m_strides
(
strides
.
size
())
{
m_strides
.
back
()
=
static_cast
<
value_type
>
(
strides
.
back
());
m_strides
.
back
()
=
static_cast
<
value_type
>
(
strides
.
back
());
for
(
size_type
i
=
m_strides
.
size
()
-
1
;
i
!=
0
;
--
i
)
{
for
(
size_type
i
=
m_strides
.
size
()
-
1
;
i
!=
0
;
--
i
)
{
...
@@ -1167,18 +1167,18 @@ private:
...
@@ -1167,18 +1167,18 @@ private:
template
<
size_t
N
>
class
multi_array_iterator
{
template
<
size_t
N
>
class
multi_array_iterator
{
public
:
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
,
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_shape
(
shape
.
size
()),
m_index
(
shape
.
size
(),
0
),
m_common_iterator
()
{
m_common_iterator
()
{
// Manual copy to avoid conversion warning if using std::copy
// Manual copy to avoid conversion warning if using std::copy
for
(
size_t
i
=
0
;
i
<
shape
.
size
();
++
i
)
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
)
for
(
size_t
i
=
0
;
i
<
N
;
++
i
)
init_common_iterator
(
buffers
[
i
],
shape
,
m_common_iterator
[
i
],
strides
);
init_common_iterator
(
buffers
[
i
],
shape
,
m_common_iterator
[
i
],
strides
);
}
}
...
@@ -1205,8 +1205,9 @@ private:
...
@@ -1205,8 +1205,9 @@ private:
using
common_iter
=
common_iterator
;
using
common_iter
=
common_iterator
;
void
init_common_iterator
(
const
buffer_info
&
buffer
,
void
init_common_iterator
(
const
buffer_info
&
buffer
,
const
std
::
vector
<
size_t
>
&
shape
,
const
container_type
&
shape
,
common_iter
&
iterator
,
std
::
vector
<
ssize_t
>
&
strides
)
{
common_iter
&
iterator
,
container_type
&
strides
)
{
auto
buffer_shape_iter
=
buffer
.
shape
.
rbegin
();
auto
buffer_shape_iter
=
buffer
.
shape
.
rbegin
();
auto
buffer_strides_iter
=
buffer
.
strides
.
rbegin
();
auto
buffer_strides_iter
=
buffer
.
strides
.
rbegin
();
auto
shape_iter
=
shape
.
rbegin
();
auto
shape_iter
=
shape
.
rbegin
();
...
@@ -1245,13 +1246,13 @@ enum class broadcast_trivial { non_trivial, c_trivial, f_trivial };
...
@@ -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
// singleton or a full-size, C-contiguous (`c_trivial`) or Fortran-contiguous (`f_trivial`) storage
// buffer; returns `non_trivial` otherwise.
// buffer; returns `non_trivial` otherwise.
template
<
size_t
N
>
template
<
size_t
N
>
broadcast_trivial
broadcast
(
const
std
::
array
<
buffer_info
,
N
>
&
buffers
,
s
ize_t
&
ndim
,
std
::
vector
<
size_t
>
&
shape
)
{
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
ize_t
(
0
),
[](
size_t
res
,
const
buffer_info
&
buf
)
{
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
);
return
std
::
max
(
res
,
buf
.
ndim
);
});
});
shape
.
clear
();
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
// Figure out the output size, and make sure all input arrays conform (i.e. are either size 1 or
// the full size).
// the full size).
...
@@ -1286,11 +1287,10 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, size_t &n
...
@@ -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)
// Check for C contiguity (but only if previous inputs were also C contiguous)
if
(
trivial_broadcast_c
)
{
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
end
=
buffers
[
i
].
shape
.
crend
();
auto
shape_iter
=
buffers
[
i
].
shape
.
crbegin
();
for
(
auto
shape_iter
=
buffers
[
i
].
shape
.
crbegin
(),
stride_iter
=
buffers
[
i
].
strides
.
crbegin
();
auto
stride_iter
=
buffers
[
i
].
strides
.
crbegin
();
trivial_broadcast_c
&&
shape_iter
!=
end
;
++
shape_iter
,
++
stride_iter
)
{
for
(;
trivial_broadcast_c
&&
shape_iter
!=
end
;
++
shape_iter
,
++
stride_iter
)
{
if
(
expect_stride
==
*
stride_iter
)
if
(
expect_stride
==
*
stride_iter
)
expect_stride
*=
*
shape_iter
;
expect_stride
*=
*
shape_iter
;
else
else
...
@@ -1300,11 +1300,10 @@ broadcast_trivial broadcast(const std::array<buffer_info, N> &buffers, size_t &n
...
@@ -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)
// Check for Fortran contiguity (if previous inputs were also F contiguous)
if
(
trivial_broadcast_f
)
{
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
end
=
buffers
[
i
].
shape
.
cend
();
auto
shape_iter
=
buffers
[
i
].
shape
.
cbegin
();
for
(
auto
shape_iter
=
buffers
[
i
].
shape
.
cbegin
(),
stride_iter
=
buffers
[
i
].
strides
.
cbegin
();
auto
stride_iter
=
buffers
[
i
].
strides
.
cbegin
();
trivial_broadcast_f
&&
shape_iter
!=
end
;
++
shape_iter
,
++
stride_iter
)
{
for
(;
trivial_broadcast_f
&&
shape_iter
!=
end
;
++
shape_iter
,
++
stride_iter
)
{
if
(
expect_stride
==
*
stride_iter
)
if
(
expect_stride
==
*
stride_iter
)
expect_stride
*=
*
shape_iter
;
expect_stride
*=
*
shape_iter
;
else
else
...
@@ -1336,25 +1335,26 @@ struct vectorize_helper {
...
@@ -1336,25 +1335,26 @@ struct vectorize_helper {
std
::
array
<
buffer_info
,
N
>
buffers
{{
args
.
request
()...
}};
std
::
array
<
buffer_info
,
N
>
buffers
{{
args
.
request
()...
}};
/* Determine dimensions parameters of output array */
/* Determine dimensions parameters of output array */
size_t
ndim
=
0
;
ssize_t
nd
=
0
;
std
::
vector
<
size_t
>
shape
(
0
);
std
::
vector
<
ssize_t
>
shape
(
0
);
auto
trivial
=
broadcast
(
buffers
,
ndim
,
shape
);
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
);
std
::
vector
<
ssize_t
>
strides
(
ndim
);
if
(
ndim
>
0
)
{
if
(
ndim
>
0
)
{
if
(
trivial
==
broadcast_trivial
::
f_trivial
)
{
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
)
{
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
[
i
-
1
];
}
}
size
*=
shape
[
ndim
-
1
];
size
*=
shape
[
ndim
-
1
];
}
}
else
{
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
)
{
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
[
i
];
}
}
size
*=
shape
[
0
];
size
*=
shape
[
0
];
...
@@ -1372,7 +1372,7 @@ struct vectorize_helper {
...
@@ -1372,7 +1372,7 @@ struct vectorize_helper {
if
(
trivial
==
broadcast_trivial
::
non_trivial
)
{
if
(
trivial
==
broadcast_trivial
::
non_trivial
)
{
apply_broadcast
<
Index
...
>
(
buffers
,
buf
,
index
);
apply_broadcast
<
Index
...
>
(
buffers
,
buf
,
index
);
}
else
{
}
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
])...);
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:
...
@@ -1165,15 +1165,15 @@ public:
static
std
::
vector
<
Py_ssize_t
>
py_strides
{
};
static
std
::
vector
<
Py_ssize_t
>
py_strides
{
};
static
std
::
vector
<
Py_ssize_t
>
py_shape
{
};
static
std
::
vector
<
Py_ssize_t
>
py_shape
{
};
buf
.
buf
=
info
.
ptr
;
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
.
format
=
const_cast
<
char
*>
(
info
.
format
.
c_str
());
buf
.
ndim
=
(
int
)
info
.
ndim
;
buf
.
ndim
=
(
int
)
info
.
ndim
;
buf
.
len
=
(
Py_ssize_t
)
info
.
size
;
buf
.
len
=
info
.
size
;
py_strides
.
clear
();
py_strides
.
clear
();
py_shape
.
clear
();
py_shape
.
clear
();
for
(
size_t
i
=
0
;
i
<
info
.
ndim
;
++
i
)
{
for
(
size_t
i
=
0
;
i
<
(
size_t
)
info
.
ndim
;
++
i
)
{
py_strides
.
push_back
(
(
Py_ssize_t
)
info
.
strides
[
i
]);
py_strides
.
push_back
(
info
.
strides
[
i
]);
py_shape
.
push_back
(
(
Py_ssize_t
)
info
.
shape
[
i
]);
py_shape
.
push_back
(
info
.
shape
[
i
]);
}
}
buf
.
strides
=
py_strides
.
data
();
buf
.
strides
=
py_strides
.
data
();
buf
.
shape
=
py_shape
.
data
();
buf
.
shape
=
py_shape
.
data
();
...
...
include/pybind11/stl_bind.h
View file @
30d43c49
...
@@ -345,21 +345,21 @@ vector_buffer(Class_& cl) {
...
@@ -345,21 +345,21 @@ vector_buffer(Class_& cl) {
format_descriptor
<
T
>::
format
();
format_descriptor
<
T
>::
format
();
cl
.
def_buffer
([](
Vector
&
v
)
->
buffer_info
{
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
)
{
cl
.
def
(
"__init__"
,
[](
Vector
&
vec
,
buffer
buf
)
{
auto
info
=
buf
.
request
();
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"
);
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
()
+
")"
);
throw
type_error
(
"Format mismatch (Python: "
+
info
.
format
+
" C++: "
+
format_descriptor
<
T
>::
format
()
+
")"
);
new
(
&
vec
)
Vector
();
new
(
&
vec
)
Vector
();
vec
.
reserve
(
info
.
shape
[
0
]);
vec
.
reserve
(
(
size_t
)
info
.
shape
[
0
]);
T
*
p
=
static_cast
<
T
*>
(
info
.
ptr
);
T
*
p
=
static_cast
<
T
*>
(
info
.
ptr
);
auto
step
=
info
.
strides
[
0
]
/
static_cast
<
ssize_t
>
(
sizeof
(
T
));
ssize_t
step
=
info
.
strides
[
0
]
/
static_cast
<
ssize_t
>
(
sizeof
(
T
));
T
*
end
=
p
+
static_cast
<
ssize_t
>
(
info
.
shape
[
0
])
*
step
;
T
*
end
=
p
+
info
.
shape
[
0
]
*
step
;
for
(;
p
<
end
;
p
+=
step
)
for
(;
p
!=
end
;
p
+=
step
)
vec
.
push_back
(
*
p
);
vec
.
push_back
(
*
p
);
});
});
...
...
tests/test_buffers.cpp
View file @
30d43c49
...
@@ -12,16 +12,16 @@
...
@@ -12,16 +12,16 @@
class
Matrix
{
class
Matrix
{
public
:
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"
);
print_created
(
this
,
std
::
to_string
(
m_rows
)
+
"x"
+
std
::
to_string
(
m_cols
)
+
" matrix"
);
m_data
=
new
float
[
rows
*
cols
];
m_data
=
new
float
[
(
size_t
)
(
rows
*
cols
)
];
memset
(
m_data
,
0
,
sizeof
(
float
)
*
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
)
{
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"
);
print_copy_created
(
this
,
std
::
to_string
(
m_rows
)
+
"x"
+
std
::
to_string
(
m_cols
)
+
" matrix"
);
m_data
=
new
float
[
m_rows
*
m_cols
];
m_data
=
new
float
[
(
size_t
)
(
m_rows
*
m_cols
)
];
memcpy
(
m_data
,
s
.
m_data
,
sizeof
(
float
)
*
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
)
{
Matrix
(
Matrix
&&
s
)
:
m_rows
(
s
.
m_rows
),
m_cols
(
s
.
m_cols
),
m_data
(
s
.
m_data
)
{
...
@@ -41,8 +41,8 @@ public:
...
@@ -41,8 +41,8 @@ public:
delete
[]
m_data
;
delete
[]
m_data
;
m_rows
=
s
.
m_rows
;
m_rows
=
s
.
m_rows
;
m_cols
=
s
.
m_cols
;
m_cols
=
s
.
m_cols
;
m_data
=
new
float
[
m_rows
*
m_cols
];
m_data
=
new
float
[
(
size_t
)
(
m_rows
*
m_cols
)
];
memcpy
(
m_data
,
s
.
m_data
,
sizeof
(
float
)
*
m_rows
*
m_cols
);
memcpy
(
m_data
,
s
.
m_data
,
sizeof
(
float
)
*
(
size_t
)
(
m_rows
*
m_cols
)
);
return
*
this
;
return
*
this
;
}
}
...
@@ -56,47 +56,47 @@ public:
...
@@ -56,47 +56,47 @@ public:
return
*
this
;
return
*
this
;
}
}
float
operator
()(
s
ize_t
i
,
size_t
j
)
const
{
float
operator
()(
s
size_t
i
,
s
size_t
j
)
const
{
return
m_data
[
i
*
m_cols
+
j
];
return
m_data
[
(
size_t
)
(
i
*
m_cols
+
j
)
];
}
}
float
&
operator
()(
s
ize_t
i
,
size_t
j
)
{
float
&
operator
()(
s
size_t
i
,
s
size_t
j
)
{
return
m_data
[
i
*
m_cols
+
j
];
return
m_data
[
(
size_t
)
(
i
*
m_cols
+
j
)
];
}
}
float
*
data
()
{
return
m_data
;
}
float
*
data
()
{
return
m_data
;
}
size_t
rows
()
const
{
return
m_rows
;
}
s
s
ize_t
rows
()
const
{
return
m_rows
;
}
size_t
cols
()
const
{
return
m_cols
;
}
s
s
ize_t
cols
()
const
{
return
m_cols
;
}
private
:
private
:
size_t
m_rows
;
s
s
ize_t
m_rows
;
size_t
m_cols
;
s
s
ize_t
m_cols
;
float
*
m_data
;
float
*
m_data
;
};
};
test_initializer
buffers
([](
py
::
module
&
m
)
{
test_initializer
buffers
([](
py
::
module
&
m
)
{
py
::
class_
<
Matrix
>
mtx
(
m
,
"Matrix"
,
py
::
buffer_protocol
());
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
/// Construct from a buffer
.
def
(
"__init__"
,
[](
Matrix
&
v
,
py
::
buffer
b
)
{
.
def
(
"__init__"
,
[](
Matrix
&
v
,
py
::
buffer
b
)
{
py
::
buffer_info
info
=
b
.
request
();
py
::
buffer_info
info
=
b
.
request
();
if
(
info
.
format
!=
py
::
format_descriptor
<
float
>::
format
()
||
info
.
ndim
!=
2
)
if
(
info
.
format
!=
py
::
format_descriptor
<
float
>::
format
()
||
info
.
ndim
!=
2
)
throw
std
::
runtime_error
(
"Incompatible buffer format!"
);
throw
std
::
runtime_error
(
"Incompatible buffer format!"
);
new
(
&
v
)
Matrix
(
info
.
shape
[
0
],
info
.
shape
[
1
]);
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
(
"rows"
,
&
Matrix
::
rows
)
.
def
(
"cols"
,
&
Matrix
::
cols
)
.
def
(
"cols"
,
&
Matrix
::
cols
)
/// Bare bones interface
/// 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
())
if
(
i
.
first
>=
m
.
rows
()
||
i
.
second
>=
m
.
cols
())
throw
py
::
index_error
();
throw
py
::
index_error
();
return
m
(
i
.
first
,
i
.
second
);
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
())
if
(
i
.
first
>=
m
.
rows
()
||
i
.
second
>=
m
.
cols
())
throw
py
::
index_error
();
throw
py
::
index_error
();
m
(
i
.
first
,
i
.
second
)
=
v
;
m
(
i
.
first
,
i
.
second
)
=
v
;
...
@@ -109,8 +109,8 @@ test_initializer buffers([](py::module &m) {
...
@@ -109,8 +109,8 @@ test_initializer buffers([](py::module &m) {
py
::
format_descriptor
<
float
>::
format
(),
/* Python struct-style format descriptor */
py
::
format_descriptor
<
float
>::
format
(),
/* Python struct-style format descriptor */
2
,
/* Number of dimensions */
2
,
/* Number of dimensions */
{
m
.
rows
(),
m
.
cols
()
},
/* Buffer dimensions */
{
m
.
rows
(),
m
.
cols
()
},
/* Buffer dimensions */
{
s
tatic_cast
<
ssize_t
>
(
sizeof
(
float
)
*
m
.
rows
()),
/* Strides (in bytes) for each index */
{
s
izeof
(
float
)
*
size_t
(
m
.
rows
()),
/* Strides (in bytes) for each index */
s
tatic_cast
<
ssize_t
>
(
sizeof
(
float
)
)
}
s
izeof
(
float
)
}
);
);
})
})
;
;
...
...
tests/test_eigen.py
View file @
30d43c49
...
@@ -186,7 +186,7 @@ def test_negative_stride_from_python(msg):
...
@@ -186,7 +186,7 @@ def test_negative_stride_from_python(msg):
double_threer
(
second_row
)
double_threer
(
second_row
)
assert
msg
(
excinfo
.
value
)
==
"""
assert
msg
(
excinfo
.
value
)
==
"""
double_threer(): incompatible function arguments. The following argument types are supported:
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)
Invoked with: array([ 5., 4., 3.], dtype=float32)
"""
"""
...
@@ -195,7 +195,7 @@ def test_negative_stride_from_python(msg):
...
@@ -195,7 +195,7 @@ def test_negative_stride_from_python(msg):
double_threec
(
second_col
)
double_threec
(
second_col
)
assert
msg
(
excinfo
.
value
)
==
"""
assert
msg
(
excinfo
.
value
)
==
"""
double_threec(): incompatible function arguments. The following argument types are supported:
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)
Invoked with: array([ 7., 4., 1.], dtype=float32)
"""
"""
...
...
tests/test_numpy_array.cpp
View file @
30d43c49
...
@@ -13,53 +13,52 @@
...
@@ -13,53 +13,52 @@
#include <pybind11/stl.h>
#include <pybind11/stl.h>
#include <cstdint>
#include <cstdint>
#include <vector>
using
arr
=
py
::
array
;
using
arr
=
py
::
array
;
using
arr_t
=
py
::
array_t
<
uint16_t
,
0
>
;
using
arr_t
=
py
::
array_t
<
uint16_t
,
0
>
;
static_assert
(
std
::
is_same
<
arr_t
::
value_type
,
uint16_t
>::
value
,
""
);
static_assert
(
std
::
is_same
<
arr_t
::
value_type
,
uint16_t
>::
value
,
""
);
template
<
typename
...
Ix
>
arr
data
(
const
arr
&
a
,
Ix
...
index
)
{
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
)
{
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
)
{
arr
&
mutate_data
(
arr
&
a
)
{
auto
ptr
=
(
uint8_t
*
)
a
.
mutable_data
();
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
);
ptr
[
i
]
=
(
uint8_t
)
(
ptr
[
i
]
*
2
);
return
a
;
return
a
;
}
}
arr_t
&
mutate_data_t
(
arr_t
&
a
)
{
arr_t
&
mutate_data_t
(
arr_t
&
a
)
{
auto
ptr
=
a
.
mutable_data
();
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
]
++
;
ptr
[
i
]
++
;
return
a
;
return
a
;
}
}
template
<
typename
...
Ix
>
arr
&
mutate_data
(
arr
&
a
,
Ix
...
index
)
{
template
<
typename
...
Ix
>
arr
&
mutate_data
(
arr
&
a
,
Ix
...
index
)
{
auto
ptr
=
(
uint8_t
*
)
a
.
mutable_data
(
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
);
ptr
[
i
]
=
(
uint8_t
)
(
ptr
[
i
]
*
2
);
return
a
;
return
a
;
}
}
template
<
typename
...
Ix
>
arr_t
&
mutate_data_t
(
arr_t
&
a
,
Ix
...
index
)
{
template
<
typename
...
Ix
>
arr_t
&
mutate_data_t
(
arr_t
&
a
,
Ix
...
index
)
{
auto
ptr
=
a
.
mutable_data
(
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
]
++
;
ptr
[
i
]
++
;
return
a
;
return
a
;
}
}
template
<
typename
...
Ix
>
py
::
ssize_t
index_at
(
const
arr
&
a
,
Ix
...
idx
)
{
return
a
.
index_at
(
idx
...);
}
template
<
typename
...
Ix
>
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
>
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
>
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
>
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
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
;
}
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) \
#define def_index_fn(name, type) \
...
@@ -88,9 +87,9 @@ test_initializer numpy_array([](py::module &m) {
...
@@ -88,9 +87,9 @@ test_initializer numpy_array([](py::module &m) {
sm
.
def
(
"ndim"
,
[](
const
arr
&
a
)
{
return
a
.
ndim
();
});
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
)
{
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
)
{
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
(
"writeable"
,
[](
const
arr
&
a
)
{
return
a
.
writeable
();
});
sm
.
def
(
"size"
,
[](
const
arr
&
a
)
{
return
a
.
size
();
});
sm
.
def
(
"size"
,
[](
const
arr
&
a
)
{
return
a
.
size
();
});
sm
.
def
(
"itemsize"
,
[](
const
arr
&
a
)
{
return
a
.
itemsize
();
});
sm
.
def
(
"itemsize"
,
[](
const
arr
&
a
)
{
return
a
.
itemsize
();
});
...
@@ -202,33 +201,33 @@ test_initializer numpy_array([](py::module &m) {
...
@@ -202,33 +201,33 @@ test_initializer numpy_array([](py::module &m) {
sm
.
def
(
"proxy_add2"
,
[](
py
::
array_t
<
double
>
a
,
double
v
)
{
sm
.
def
(
"proxy_add2"
,
[](
py
::
array_t
<
double
>
a
,
double
v
)
{
auto
r
=
a
.
mutable_unchecked
<
2
>
();
auto
r
=
a
.
mutable_unchecked
<
2
>
();
for
(
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
s
s
ize_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
size_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
s
s
ize_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
r
(
i
,
j
)
+=
v
;
r
(
i
,
j
)
+=
v
;
},
py
::
arg
().
noconvert
(),
py
::
arg
());
},
py
::
arg
().
noconvert
(),
py
::
arg
());
sm
.
def
(
"proxy_init3"
,
[](
double
start
)
{
sm
.
def
(
"proxy_init3"
,
[](
double
start
)
{
py
::
array_t
<
double
,
py
::
array
::
c_style
>
a
({
3
,
3
,
3
});
py
::
array_t
<
double
,
py
::
array
::
c_style
>
a
({
3
,
3
,
3
});
auto
r
=
a
.
mutable_unchecked
<
3
>
();
auto
r
=
a
.
mutable_unchecked
<
3
>
();
for
(
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
s
s
ize_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
size_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
s
s
ize_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
size_t
k
=
0
;
k
<
r
.
shape
(
2
);
k
++
)
for
(
s
s
ize_t
k
=
0
;
k
<
r
.
shape
(
2
);
k
++
)
r
(
i
,
j
,
k
)
=
start
++
;
r
(
i
,
j
,
k
)
=
start
++
;
return
a
;
return
a
;
});
});
sm
.
def
(
"proxy_init3F"
,
[](
double
start
)
{
sm
.
def
(
"proxy_init3F"
,
[](
double
start
)
{
py
::
array_t
<
double
,
py
::
array
::
f_style
>
a
({
3
,
3
,
3
});
py
::
array_t
<
double
,
py
::
array
::
f_style
>
a
({
3
,
3
,
3
});
auto
r
=
a
.
mutable_unchecked
<
3
>
();
auto
r
=
a
.
mutable_unchecked
<
3
>
();
for
(
size_t
k
=
0
;
k
<
r
.
shape
(
2
);
k
++
)
for
(
s
s
ize_t
k
=
0
;
k
<
r
.
shape
(
2
);
k
++
)
for
(
size_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
s
s
ize_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
s
s
ize_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
r
(
i
,
j
,
k
)
=
start
++
;
r
(
i
,
j
,
k
)
=
start
++
;
return
a
;
return
a
;
});
});
sm
.
def
(
"proxy_squared_L2_norm"
,
[](
py
::
array_t
<
double
>
a
)
{
sm
.
def
(
"proxy_squared_L2_norm"
,
[](
py
::
array_t
<
double
>
a
)
{
auto
r
=
a
.
unchecked
<
1
>
();
auto
r
=
a
.
unchecked
<
1
>
();
double
sumsq
=
0
;
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
sumsq
+=
r
[
i
]
*
r
(
i
);
// Either notation works for a 1D array
return
sumsq
;
return
sumsq
;
});
});
...
@@ -243,17 +242,17 @@ test_initializer numpy_array([](py::module &m) {
...
@@ -243,17 +242,17 @@ test_initializer numpy_array([](py::module &m) {
sm
.
def
(
"proxy_add2_dyn"
,
[](
py
::
array_t
<
double
>
a
,
double
v
)
{
sm
.
def
(
"proxy_add2_dyn"
,
[](
py
::
array_t
<
double
>
a
,
double
v
)
{
auto
r
=
a
.
mutable_unchecked
();
auto
r
=
a
.
mutable_unchecked
();
if
(
r
.
ndim
()
!=
2
)
throw
std
::
domain_error
(
"error: ndim != 2"
);
if
(
r
.
ndim
()
!=
2
)
throw
std
::
domain_error
(
"error: ndim != 2"
);
for
(
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
s
s
ize_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
size_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
s
s
ize_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
r
(
i
,
j
)
+=
v
;
r
(
i
,
j
)
+=
v
;
},
py
::
arg
().
noconvert
(),
py
::
arg
());
},
py
::
arg
().
noconvert
(),
py
::
arg
());
sm
.
def
(
"proxy_init3_dyn"
,
[](
double
start
)
{
sm
.
def
(
"proxy_init3_dyn"
,
[](
double
start
)
{
py
::
array_t
<
double
,
py
::
array
::
c_style
>
a
({
3
,
3
,
3
});
py
::
array_t
<
double
,
py
::
array
::
c_style
>
a
({
3
,
3
,
3
});
auto
r
=
a
.
mutable_unchecked
();
auto
r
=
a
.
mutable_unchecked
();
if
(
r
.
ndim
()
!=
3
)
throw
std
::
domain_error
(
"error: ndim != 3"
);
if
(
r
.
ndim
()
!=
3
)
throw
std
::
domain_error
(
"error: ndim != 3"
);
for
(
size_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
s
s
ize_t
i
=
0
;
i
<
r
.
shape
(
0
);
i
++
)
for
(
size_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
s
s
ize_t
j
=
0
;
j
<
r
.
shape
(
1
);
j
++
)
for
(
size_t
k
=
0
;
k
<
r
.
shape
(
2
);
k
++
)
for
(
s
s
ize_t
k
=
0
;
k
<
r
.
shape
(
2
);
k
++
)
r
(
i
,
j
,
k
)
=
start
++
;
r
(
i
,
j
,
k
)
=
start
++
;
return
a
;
return
a
;
});
});
...
@@ -269,6 +268,9 @@ test_initializer numpy_array([](py::module &m) {
...
@@ -269,6 +268,9 @@ test_initializer numpy_array([](py::module &m) {
sm
.
def
(
"array_fail_test"
,
[]()
{
return
py
::
array
(
py
::
object
());
});
sm
.
def
(
"array_fail_test"
,
[]()
{
return
py
::
array
(
py
::
object
());
});
sm
.
def
(
"array_t_fail_test"
,
[]()
{
return
py
::
array_t
<
double
>
(
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
// 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
);
});
// { 1 } also works, but clang warns about it
sm
.
def
(
"array_initializer_list"
,
[]()
{
return
py
::
array_t
<
float
>
({
1
,
2
});
});
sm
.
def
(
"array_initializer_list"
,
[]()
{
return
py
::
array_t
<
float
>
({
1
,
2
});
});
...
@@ -277,7 +279,7 @@ test_initializer numpy_array([](py::module &m) {
...
@@ -277,7 +279,7 @@ test_initializer numpy_array([](py::module &m) {
// reshape array to 2D without changing size
// reshape array to 2D without changing size
sm
.
def
(
"array_reshape2"
,
[](
py
::
array_t
<
double
>
a
)
{
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
())
if
(
dim_sz
*
dim_sz
!=
a
.
size
())
throw
std
::
domain_error
(
"array_reshape2: input array total size is not a squared integer"
);
throw
std
::
domain_error
(
"array_reshape2: input array total size is not a squared integer"
);
a
.
resize
({
dim_sz
,
dim_sz
});
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):
...
@@ -384,7 +384,8 @@ def test_array_unchecked_dyn_dims(msg):
def
test_array_failure
():
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
:
with
pytest
.
raises
(
ValueError
)
as
excinfo
:
array_fail_test
()
array_fail_test
()
...
@@ -394,6 +395,10 @@ def test_array_failure():
...
@@ -394,6 +395,10 @@ def test_array_failure():
array_t_fail_test
()
array_t_fail_test
()
assert
str
(
excinfo
.
value
)
==
'cannot create a pybind11::array_t from a nullptr'
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
):
def
test_array_resize
(
msg
):
from
pybind11_tests.array
import
(
array_reshape2
,
array_resize3
)
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) {
...
@@ -149,7 +149,7 @@ py::array_t<StringStruct, 0> create_string_array(bool non_empty) {
if
(
non_empty
)
{
if
(
non_empty
)
{
auto
req
=
arr
.
request
();
auto
req
=
arr
.
request
();
auto
ptr
=
static_cast
<
StringStruct
*>
(
req
.
ptr
);
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
;
static_cast
<
char
*>
(
req
.
ptr
)[
i
]
=
0
;
ptr
[
1
].
a
[
0
]
=
'a'
;
ptr
[
1
].
b
[
0
]
=
'a'
;
ptr
[
1
].
a
[
0
]
=
'a'
;
ptr
[
1
].
b
[
0
]
=
'a'
;
ptr
[
2
].
a
[
0
]
=
'a'
;
ptr
[
2
].
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) {
...
@@ -178,7 +178,7 @@ py::list print_recarray(py::array_t<S, 0> arr) {
const
auto
req
=
arr
.
request
();
const
auto
req
=
arr
.
request
();
const
auto
ptr
=
static_cast
<
S
*>
(
req
.
ptr
);
const
auto
ptr
=
static_cast
<
S
*>
(
req
.
ptr
);
auto
l
=
py
::
list
();
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
;
std
::
stringstream
ss
;
ss
<<
ptr
[
i
];
ss
<<
ptr
[
i
];
l
.
append
(
py
::
str
(
ss
.
str
()));
l
.
append
(
py
::
str
(
ss
.
str
()));
...
@@ -225,7 +225,7 @@ py::array_t<int32_t, 0> test_array_ctors(int i) {
...
@@ -225,7 +225,7 @@ py::array_t<int32_t, 0> test_array_ctors(int i) {
using
arr_t
=
py
::
array_t
<
int32_t
,
0
>
;
using
arr_t
=
py
::
array_t
<
int32_t
,
0
>
;
std
::
vector
<
int32_t
>
data
{
1
,
2
,
3
,
4
,
5
,
6
};
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
};
std
::
vector
<
ssize_t
>
strides
{
8
,
4
};
auto
ptr
=
data
.
data
();
auto
ptr
=
data
.
data
();
...
...
tests/test_numpy_vectorize.cpp
View file @
30d43c49
...
@@ -50,8 +50,8 @@ test_initializer numpy_vectorize([](py::module &m) {
...
@@ -50,8 +50,8 @@ test_initializer numpy_vectorize([](py::module &m) {
py
::
array_t
<
float
,
py
::
array
::
forcecast
>
arg2
,
py
::
array_t
<
float
,
py
::
array
::
forcecast
>
arg2
,
py
::
array_t
<
double
,
py
::
array
::
forcecast
>
arg3
py
::
array_t
<
double
,
py
::
array
::
forcecast
>
arg3
)
{
)
{
size_t
ndim
;
s
s
ize_t
ndim
;
std
::
vector
<
size_t
>
shape
;
std
::
vector
<
s
s
ize_t
>
shape
;
std
::
array
<
py
::
buffer_info
,
3
>
buffers
{{
arg1
.
request
(),
arg2
.
request
(),
arg3
.
request
()
}};
std
::
array
<
py
::
buffer_info
,
3
>
buffers
{{
arg1
.
request
(),
arg2
.
request
(),
arg3
.
request
()
}};
return
py
::
detail
::
broadcast
(
buffers
,
ndim
,
shape
);
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