Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
E
eigenpy
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Guilhem Saurel
eigenpy
Commits
7ec95dab
Unverified
Commit
7ec95dab
authored
3 years ago
by
Justin Carpentier
Committed by
GitHub
3 years ago
Browse files
Options
Downloads
Plain Diff
Merge pull request #242 from jcarpent/devel
Enhance support of ufunc
parents
50111167
23a2cd3b
No related branches found
Branches containing commit
Tags
v4.10.0
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
cmake
+1
-1
1 addition, 1 deletion
cmake
include/eigenpy/ufunc.hpp
+111
-13
111 additions, 13 deletions
include/eigenpy/ufunc.hpp
unittest/python/test_user_type.py
+4
-0
4 additions, 0 deletions
unittest/python/test_user_type.py
with
116 additions
and
14 deletions
cmake
@
b65eb53f
Compare
2e42d6c1
...
b65eb53f
Subproject commit
2e42d6c120fdde4d119da2fcd53d40c3b12f285a
Subproject commit
b65eb53f07339035bfe27b6149228059ebc62c97
This diff is collapsed.
Click to expand it.
include/eigenpy/ufunc.hpp
+
111
−
13
View file @
7ec95dab
//
//
// Copyright (c) 2020 INRIA
// Copyright (c) 2020-2021 INRIA
// code aptapted from https://github.com/numpy/numpy/blob/41977b24ae011a51f64faa75cb524c7350fdedd9/numpy/core/src/umath/_rational_tests.c.src
//
//
#ifndef __eigenpy_ufunc_hpp__
#ifndef __eigenpy_ufunc_hpp__
#define __eigenpy_ufunc_hpp__
#define __eigenpy_ufunc_hpp__
#include
"eigenpy/register.hpp"
#include
"eigenpy/register.hpp"
#include
"eigenpy/user-type.hpp"
namespace
eigenpy
namespace
eigenpy
{
{
...
@@ -18,6 +20,77 @@ namespace eigenpy
...
@@ -18,6 +20,77 @@ namespace eigenpy
#define EIGENPY_NPY_CONST_UFUNC_ARG
#define EIGENPY_NPY_CONST_UFUNC_ARG
#endif
#endif
template
<
typename
T
>
void
matrix_multiply
(
char
**
args
,
npy_intp
const
*
dimensions
,
npy_intp
const
*
steps
)
{
/* pointers to data for input and output arrays */
char
*
ip1
=
args
[
0
];
char
*
ip2
=
args
[
1
];
char
*
op
=
args
[
2
];
/* lengths of core dimensions */
npy_intp
dm
=
dimensions
[
0
];
npy_intp
dn
=
dimensions
[
1
];
npy_intp
dp
=
dimensions
[
2
];
/* striding over core dimensions */
npy_intp
is1_m
=
steps
[
0
];
npy_intp
is1_n
=
steps
[
1
];
npy_intp
is2_n
=
steps
[
2
];
npy_intp
is2_p
=
steps
[
3
];
npy_intp
os_m
=
steps
[
4
];
npy_intp
os_p
=
steps
[
5
];
/* core dimensions counters */
npy_intp
m
,
p
;
/* calculate dot product for each row/column vector pair */
for
(
m
=
0
;
m
<
dm
;
m
++
)
{
for
(
p
=
0
;
p
<
dp
;
p
++
)
{
SpecialMethods
<
T
>::
dotfunc
(
ip1
,
is1_n
,
ip2
,
is2_n
,
op
,
dn
,
NULL
);
/* advance to next column of 2nd input array and output array */
ip2
+=
is2_p
;
op
+=
os_p
;
}
/* reset to first column of 2nd input array and output array */
ip2
-=
is2_p
*
p
;
op
-=
os_p
*
p
;
/* advance to next row of 1st input array and output array */
ip1
+=
is1_m
;
op
+=
os_m
;
}
}
template
<
typename
T
>
void
gufunc_matrix_multiply
(
char
**
args
,
npy_intp
EIGENPY_NPY_CONST_UFUNC_ARG
*
dimensions
,
npy_intp
EIGENPY_NPY_CONST_UFUNC_ARG
*
steps
,
void
*
NPY_UNUSED
(
func
))
{
/* outer dimensions counter */
npy_intp
N_
;
/* length of flattened outer dimensions */
npy_intp
dN
=
dimensions
[
0
];
/* striding over flattened outer dimensions for input and output arrays */
npy_intp
s0
=
steps
[
0
];
npy_intp
s1
=
steps
[
1
];
npy_intp
s2
=
steps
[
2
];
/*
* loop through outer dimensions, performing matrix multiply on
* core dimensions for each loop
*/
for
(
N_
=
0
;
N_
<
dN
;
N_
++
,
args
[
0
]
+=
s0
,
args
[
1
]
+=
s1
,
args
[
2
]
+=
s2
)
{
matrix_multiply
<
T
>
(
args
,
dimensions
+
1
,
steps
+
3
);
}
}
#define EIGENPY_REGISTER_BINARY_OPERATOR(name,op) \
#define EIGENPY_REGISTER_BINARY_OPERATOR(name,op) \
template<typename T1, typename T2, typename R> \
template<typename T1, typename T2, typename R> \
void binary_op_##name(char** args, EIGENPY_NPY_CONST_UFUNC_ARG npy_intp * dimensions, EIGENPY_NPY_CONST_UFUNC_ARG npy_intp * steps, void *
/*data*/
) \
void binary_op_##name(char** args, EIGENPY_NPY_CONST_UFUNC_ARG npy_intp * dimensions, EIGENPY_NPY_CONST_UFUNC_ARG npy_intp * steps, void *
/*data*/
) \
...
@@ -127,7 +200,7 @@ namespace eigenpy
...
@@ -127,7 +200,7 @@ namespace eigenpy
template
<
typename
Scalar
>
template
<
typename
Scalar
>
void
registerCommonUfunc
()
void
registerCommonUfunc
()
{
{
const
int
code
=
Register
::
getTypeCode
<
Scalar
>
();
const
int
type_
code
=
Register
::
getTypeCode
<
Scalar
>
();
PyObject
*
numpy_str
;
PyObject
*
numpy_str
;
#if PY_MAJOR_VERSION >= 3
#if PY_MAJOR_VERSION >= 3
...
@@ -140,23 +213,48 @@ namespace eigenpy
...
@@ -140,23 +213,48 @@ namespace eigenpy
Py_DECREF
(
numpy_str
);
Py_DECREF
(
numpy_str
);
import_ufunc
();
import_ufunc
();
// Matrix multiply
{
int
types
[
3
]
=
{
type_code
,
type_code
,
type_code
};
std
::
stringstream
ss
;
ss
<<
"return result of multiplying two matrices of "
;
ss
<<
bp
::
type_info
(
typeid
(
Scalar
)).
name
();
PyUFuncObject
*
ufunc
=
(
PyUFuncObject
*
)
PyObject_GetAttrString
(
numpy
,
"matmul"
);
if
(
!
ufunc
)
{
std
::
stringstream
ss
;
ss
<<
"Impossible to define matrix_multiply for given type "
<<
bp
::
type_info
(
typeid
(
Scalar
)).
name
()
<<
std
::
endl
;
eigenpy
::
Exception
(
ss
.
str
());
}
if
(
PyUFunc_RegisterLoopForType
((
PyUFuncObject
*
)
ufunc
,
type_code
,
&
internal
::
gufunc_matrix_multiply
<
Scalar
>
,
types
,
0
)
<
0
)
{
std
::
stringstream
ss
;
ss
<<
"Impossible to register matrix_multiply for given type "
<<
bp
::
type_info
(
typeid
(
Scalar
)).
name
()
<<
std
::
endl
;
eigenpy
::
Exception
(
ss
.
str
());
}
Py_DECREF
(
ufunc
);
}
// Binary operators
// Binary operators
EIGENPY_REGISTER_BINARY_UFUNC
(
add
,
code
,
Scalar
,
Scalar
,
Scalar
);
EIGENPY_REGISTER_BINARY_UFUNC
(
add
,
type_
code
,
Scalar
,
Scalar
,
Scalar
);
EIGENPY_REGISTER_BINARY_UFUNC
(
subtract
,
code
,
Scalar
,
Scalar
,
Scalar
);
EIGENPY_REGISTER_BINARY_UFUNC
(
subtract
,
type_
code
,
Scalar
,
Scalar
,
Scalar
);
EIGENPY_REGISTER_BINARY_UFUNC
(
multiply
,
code
,
Scalar
,
Scalar
,
Scalar
);
EIGENPY_REGISTER_BINARY_UFUNC
(
multiply
,
type_
code
,
Scalar
,
Scalar
,
Scalar
);
EIGENPY_REGISTER_BINARY_UFUNC
(
divide
,
code
,
Scalar
,
Scalar
,
Scalar
);
EIGENPY_REGISTER_BINARY_UFUNC
(
divide
,
type_
code
,
Scalar
,
Scalar
,
Scalar
);
// Comparison operators
// Comparison operators
EIGENPY_REGISTER_BINARY_UFUNC
(
equal
,
code
,
Scalar
,
Scalar
,
bool
);
EIGENPY_REGISTER_BINARY_UFUNC
(
equal
,
type_
code
,
Scalar
,
Scalar
,
bool
);
EIGENPY_REGISTER_BINARY_UFUNC
(
not_equal
,
code
,
Scalar
,
Scalar
,
bool
);
EIGENPY_REGISTER_BINARY_UFUNC
(
not_equal
,
type_
code
,
Scalar
,
Scalar
,
bool
);
EIGENPY_REGISTER_BINARY_UFUNC
(
greater
,
code
,
Scalar
,
Scalar
,
bool
);
EIGENPY_REGISTER_BINARY_UFUNC
(
greater
,
type_
code
,
Scalar
,
Scalar
,
bool
);
EIGENPY_REGISTER_BINARY_UFUNC
(
less
,
code
,
Scalar
,
Scalar
,
bool
);
EIGENPY_REGISTER_BINARY_UFUNC
(
less
,
type_
code
,
Scalar
,
Scalar
,
bool
);
EIGENPY_REGISTER_BINARY_UFUNC
(
greater_equal
,
code
,
Scalar
,
Scalar
,
bool
);
EIGENPY_REGISTER_BINARY_UFUNC
(
greater_equal
,
type_
code
,
Scalar
,
Scalar
,
bool
);
EIGENPY_REGISTER_BINARY_UFUNC
(
less_equal
,
code
,
Scalar
,
Scalar
,
bool
);
EIGENPY_REGISTER_BINARY_UFUNC
(
less_equal
,
type_
code
,
Scalar
,
Scalar
,
bool
);
// Unary operators
// Unary operators
EIGENPY_REGISTER_UNARY_UFUNC
(
negative
,
code
,
Scalar
,
Scalar
);
EIGENPY_REGISTER_UNARY_UFUNC
(
negative
,
type_
code
,
Scalar
,
Scalar
);
Py_DECREF
(
numpy
);
Py_DECREF
(
numpy
);
}
}
...
...
This diff is collapsed.
Click to expand it.
unittest/python/test_user_type.py
+
4
−
0
View file @
7ec95dab
...
@@ -32,6 +32,10 @@ def test(dtype):
...
@@ -32,6 +32,10 @@ def test(dtype):
assert
not
(
mat
>
mat
).
all
()
assert
not
(
mat
>
mat
).
all
()
assert
not
(
mat
<
mat
).
all
()
assert
not
(
mat
<
mat
).
all
()
mat2
=
mat
.
dot
(
mat
.
T
)
if
np
.
__version__
>=
'
1.17.0
'
:
mat2
=
np
.
matmul
(
mat
,
mat
.
T
)
def
test_cast
(
from_dtype
,
to_dtype
):
def
test_cast
(
from_dtype
,
to_dtype
):
np
.
can_cast
(
from_dtype
,
to_dtype
)
np
.
can_cast
(
from_dtype
,
to_dtype
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment