Skip to content

Commit

Permalink
Merge pull request #477 from jcarpent/topic/devel
Browse files Browse the repository at this point in the history
Add id() helper
  • Loading branch information
jcarpent authored Jun 10, 2024
2 parents ca81cf1 + ee2748a commit e99f461
Show file tree
Hide file tree
Showing 22 changed files with 85 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

### Added
- Added a deprecation call policy shortcut ([#466](https://github.com/stack-of-tasks/eigenpy/pull/466))
- Added id() helper to retrieve unique object identifier in Python ([#477](https://github.com/stack-of-tasks/eigenpy/pull/477))

### Fixed
- Fix register_symbolic_link_to_registered_type() for multiple successive registrations ([#471](https://github.com/stack-of-tasks/eigenpy/pull/471))
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ set(${PROJECT_NAME}_HEADERS
include/eigenpy/eigen-to-python.hpp
include/eigenpy/eigen-from-python.hpp
include/eigenpy/eigen-typedef.hpp
include/eigenpy/id.hpp
include/eigenpy/numpy-map.hpp
include/eigenpy/geometry.hpp
include/eigenpy/geometry-conversion.hpp
Expand Down
3 changes: 2 additions & 1 deletion include/eigenpy/angle-axis.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ class AngleAxisVisitor : public bp::def_visitor<AngleAxisVisitor<AngleAxis> > {
static void expose() {
bp::class_<AngleAxis>(
"AngleAxis", "AngleAxis representation of a rotation.\n\n", bp::no_init)
.def(AngleAxisVisitor<AngleAxis>());
.def(AngleAxisVisitor<AngleAxis>())
.def(IdVisitor<AngleAxis>());

// Cast to Eigen::RotationBase
bp::implicitly_convertible<AngleAxis, RotationBase>();
Expand Down
4 changes: 3 additions & 1 deletion include/eigenpy/decompositions/EigenSolver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ struct EigenSolverVisitor
}

static void expose(const std::string& name) {
bp::class_<Solver>(name.c_str(), bp::no_init).def(EigenSolverVisitor());
bp::class_<Solver>(name.c_str(), bp::no_init)
.def(EigenSolverVisitor())
.def(IdVisitor<Solver>());
}

private:
Expand Down
3 changes: 2 additions & 1 deletion include/eigenpy/decompositions/LDLT.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 INRIA
* Copyright 2020-2024 INRIA
*/

#ifndef __eigenpy_decomposition_ldlt_hpp__
Expand Down Expand Up @@ -119,6 +119,7 @@ struct LDLTSolverVisitor
"have zeros in the bottom right rank(A) - n submatrix. Avoiding the "
"square root on D also stabilizes the computation.",
bp::no_init)
.def(IdVisitor<Solver>())
.def(LDLTSolverVisitor());
}

Expand Down
3 changes: 2 additions & 1 deletion include/eigenpy/decompositions/LLT.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020-2021 INRIA
* Copyright 2020-2024 INRIA
*/

#ifndef __eigenpy_decomposition_llt_hpp__
Expand Down Expand Up @@ -115,6 +115,7 @@ struct LLTSolverVisitor
"remains useful in many other situations like generalised eigen "
"problems with hermitian matrices.",
bp::no_init)
.def(IdVisitor<Solver>())
.def(LLTSolverVisitor());
}

Expand Down
1 change: 1 addition & 0 deletions include/eigenpy/decompositions/PermutationMatrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ struct PermutationMatrixVisitor
"This class represents a permutation matrix, "
"internally stored as a vector of integers.",
bp::no_init)
.def(IdVisitor<PermutationMatrix>())
.def(PermutationMatrixVisitor());
}
};
Expand Down
3 changes: 2 additions & 1 deletion include/eigenpy/decompositions/SelfAdjointEigenSolver.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2020 INRIA
* Copyright 2020-2024 INRIA
*/

#ifndef __eigenpy_decomposition_self_adjoint_eigen_solver_hpp__
Expand Down Expand Up @@ -84,6 +84,7 @@ struct SelfAdjointEigenSolverVisitor

static void expose(const std::string& name) {
bp::class_<Solver>(name.c_str(), bp::no_init)
.def(IdVisitor<Solver>())
.def(SelfAdjointEigenSolverVisitor());
}

Expand Down
3 changes: 2 additions & 1 deletion include/eigenpy/decompositions/minres.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ struct MINRESSolverVisitor
"defaults are the size of the problem for the maximal number of "
"iterations and NumTraits<Scalar>::epsilon() for the tolerance.\n",
bp::no_init)
.def(MINRESSolverVisitor());
.def(MINRESSolverVisitor())
.def(IdVisitor<Solver>());
}

private:
Expand Down
3 changes: 2 additions & 1 deletion include/eigenpy/decompositions/sparse/LDLT.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ struct SimplicialLDLTVisitor
"prior to the factorization such that the factorized matrix is P A "
"P^-1.",
bp::no_init)
.def(SimplicialLDLTVisitor());
.def(SimplicialLDLTVisitor())
.def(IdVisitor<Solver>());
}

private:
Expand Down
3 changes: 2 additions & 1 deletion include/eigenpy/decompositions/sparse/LLT.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ struct SimplicialLLTVisitor
"prior to the factorization such that the factorized matrix is P A "
"P^-1.",
bp::no_init)
.def(SimplicialLLTVisitor());
.def(SimplicialLLTVisitor())
.def(IdVisitor<Solver>());
}
};

Expand Down
1 change: 1 addition & 0 deletions include/eigenpy/fwd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,5 +200,6 @@ struct has_operator_equal : internal::has_operator_equal_impl<T1, T2>::type {};
} // namespace eigenpy

#include "eigenpy/alignment.hpp"
#include "eigenpy/id.hpp"

#endif // ifndef __eigenpy_fwd_hpp__
33 changes: 33 additions & 0 deletions include/eigenpy/id.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// Copyright (c) 2024 INRIA
//

#ifndef __eigenpy_id_hpp__
#define __eigenpy_id_hpp__

#include <boost/python.hpp>
#include <boost/cstdint.hpp>

namespace eigenpy {

///
/// \brief Add the Python method id to retrieving a unique id for a given object
/// exposed with Boost.Python
///
template <class C>
struct IdVisitor : public bp::def_visitor<IdVisitor<C> > {
template <class PyClass>
void visit(PyClass& cl) const {
cl.def("id", &id, bp::arg("self"),
"Returns the unique identity of an object.\n"
"For object held in C++, it corresponds to its memory address.");
}

private:
static boost::int64_t id(const C& self) {
return boost::int64_t(reinterpret_cast<const void*>(&self));
}
};
} // namespace eigenpy

#endif // ifndef __eigenpy_id_hpp__
3 changes: 2 additions & 1 deletion include/eigenpy/quaternion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,8 @@ class QuaternionVisitor
"'q*v' (rotating 'v' by 'q'), "
"'q==q', 'q!=q', 'q[0..3]'.",
bp::no_init)
.def(QuaternionVisitor<Quaternion>());
.def(QuaternionVisitor<Quaternion>())
.def(IdVisitor<Quaternion>());

// Cast to Eigen::QuaternionBase and vice-versa
bp::implicitly_convertible<Quaternion, QuaternionBase>();
Expand Down
3 changes: 3 additions & 0 deletions include/eigenpy/solvers/BFGSPreconditioners.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright 2017 CNRS
* Copyright 2024 Inria
*/

#ifndef __eigenpy_bfgs_preconditioners_hpp__
Expand Down Expand Up @@ -37,6 +38,7 @@ struct BFGSPreconditionerBaseVisitor

static void expose(const std::string& name) {
bp::class_<Preconditioner>(name, bp::no_init)
.def(IdVisitor<Preconditioner>())
.def(BFGSPreconditionerBaseVisitor<Preconditioner>());
}
};
Expand All @@ -56,6 +58,7 @@ struct LimitedBFGSPreconditionerBaseVisitor

static void expose(const std::string& name) {
bp::class_<Preconditioner>(name.c_str(), bp::no_init)
.def(IdVisitor<Preconditioner>())
.def(LimitedBFGSPreconditionerBaseVisitor<Preconditioner>());
}
};
Expand Down
10 changes: 7 additions & 3 deletions include/eigenpy/solvers/BasicPreconditioners.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright 2017 CNRS
* Copyright 2024 Inria
*/

#ifndef __eigenpy_basic_preconditioners_hpp__
Expand Down Expand Up @@ -69,7 +70,8 @@ struct DiagonalPreconditionerVisitor
"A preconditioner based on the digonal entrie.\n"
"This class allows to approximately solve for A.x = b problems "
"assuming A is a diagonal matrix.",
bp::no_init);
bp::no_init)
.def(IdVisitor<Preconditioner>());
}
};

Expand All @@ -91,7 +93,8 @@ struct LeastSquareDiagonalPreconditionerVisitor
"his class allows to approximately solve for A' A x = A' b problems "
"assuming A' A is a diagonal matrix.",
bp::no_init)
.def(DiagonalPreconditionerVisitor<Scalar>());
.def(DiagonalPreconditionerVisitor<Scalar>())
.def(IdVisitor<Preconditioner>());
}
};
#endif
Expand All @@ -105,7 +108,8 @@ struct IdentityPreconditionerVisitor

static void expose() {
bp::class_<Preconditioner>("IdentityPreconditioner", bp::no_init)
.def(PreconditionerBaseVisitor<Preconditioner>());
.def(PreconditionerBaseVisitor<Preconditioner>())
.def(IdVisitor<Preconditioner>());
}
};

Expand Down
3 changes: 2 additions & 1 deletion include/eigenpy/solvers/ConjugateGradient.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ struct ConjugateGradientVisitor

static void expose(const std::string& name = "ConjugateGradient") {
bp::class_<ConjugateGradient, boost::noncopyable>(name.c_str(), bp::no_init)
.def(ConjugateGradientVisitor<ConjugateGradient>());
.def(ConjugateGradientVisitor<ConjugateGradient>())
.def(IdVisitor<ConjugateGradient>());
}
};

Expand Down
3 changes: 2 additions & 1 deletion include/eigenpy/solvers/LeastSquaresConjugateGradient.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ struct LeastSquaresConjugateGradientVisitor
"LeastSquaresConjugateGradient", bp::no_init)
.def(IterativeSolverVisitor<LeastSquaresConjugateGradient>())
.def(LeastSquaresConjugateGradientVisitor<
LeastSquaresConjugateGradient>());
LeastSquaresConjugateGradient>())
.def(IdVisitor<LeastSquaresConjugateGradient>());
}
};

Expand Down
1 change: 1 addition & 0 deletions include/eigenpy/std-array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ struct StdArrayPythonVisitor {
bp::class_<array_type> cl(class_name.c_str(), doc_string.c_str());
cl.def(bp::init<const array_type &>(bp::args("self", "other"),
"Copy constructor"));
cl.def(IdVisitor<array_type>());

array_indexing_suite<array_type, NoProxy, SliceAllocator> indexing_suite;
cl.def(indexing_suite)
Expand Down
1 change: 1 addition & 0 deletions include/eigenpy/std-vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ struct StdVectorPythonVisitor {
if (!register_symbolic_link_to_registered_type<vector_type>(
add_std_visitor)) {
bp::class_<vector_type> cl(class_name.c_str(), doc_string.c_str());
cl.def(IdVisitor<vector_type>());

// Standard vector indexing definition
boost::python::vector_indexing_suite<
Expand Down
2 changes: 2 additions & 0 deletions unittest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ add_python_eigenpy_lib_unit_test("py-LLT" "unittest/python/test_LLT.py")

add_python_eigenpy_lib_unit_test("py-LDLT" "unittest/python/test_LDLT.py")

add_python_eigenpy_lib_unit_test("py-id" "unittest/python/test_id.py")

if(NOT WIN32)
add_python_eigenpy_lib_unit_test("py-MINRES" "unittest/python/test_MINRES.py")
endif(NOT WIN32)
Expand Down
11 changes: 11 additions & 0 deletions unittest/python/test_id.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import eigenpy

ldlt1 = eigenpy.LDLT()
ldlt2 = eigenpy.LDLT()

id1 = ldlt1.id()
id2 = ldlt2.id()

assert id1 != id2
assert id1 == ldlt1.id()
assert id2 == ldlt2.id()

0 comments on commit e99f461

Please sign in to comment.