Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • jcarpent/eigenpy
  • gsaurel/eigenpy
  • stack-of-tasks/eigenpy
3 results
Show changes
import user_type
import numpy as np import numpy as np
import user_type
# from packaging import version # from packaging import version
...@@ -8,8 +8,9 @@ cols = 20 ...@@ -8,8 +8,9 @@ cols = 20
def test(dtype): def test(dtype):
mat = np.array(np.ones((rows, cols)).astype(np.intc), dtype=dtype) rng = np.random.default_rng()
mat = np.random.rand(rows, cols).astype(dtype) mat = np.ones((rows, cols), dtype=dtype)
mat = rng.random((rows, cols)).astype(dtype)
mat_copy = mat.copy() mat_copy = mat.copy()
assert (mat == mat_copy).all() assert (mat == mat_copy).all()
assert not (mat != mat_copy).all() assert not (mat != mat_copy).all()
...@@ -43,6 +44,11 @@ def test(dtype): ...@@ -43,6 +44,11 @@ def test(dtype):
mat2 = np.matmul(mat, mat.T) mat2 = np.matmul(mat, mat.T)
assert np.isclose(mat2.astype(np.double), mat2_ref).all() assert np.isclose(mat2.astype(np.double), mat2_ref).all()
vec = np.ones((rows,), dtype=dtype)
norm = np.linalg.norm(vec)
norm_ref = np.linalg.norm(vec.astype(np.double))
assert norm == norm_ref
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)
...@@ -62,8 +68,17 @@ test_cast(np.int64, user_type.CustomDouble) ...@@ -62,8 +68,17 @@ test_cast(np.int64, user_type.CustomDouble)
test_cast(user_type.CustomDouble, np.int32) test_cast(user_type.CustomDouble, np.int32)
test_cast(np.int32, user_type.CustomDouble) test_cast(np.int32, user_type.CustomDouble)
test(user_type.CustomFloat)
v = user_type.CustomDouble(1) v = user_type.CustomDouble(1)
a = np.array(v) a = np.array(v)
assert type(v) == a.dtype.type assert type(v) is a.dtype.type
test(user_type.CustomFloat)
test_cast(user_type.CustomFloat, np.float32)
test_cast(np.double, user_type.CustomFloat)
test_cast(user_type.CustomFloat, np.int64)
test_cast(np.int64, user_type.CustomFloat)
test_cast(user_type.CustomFloat, np.int32)
test_cast(np.int32, user_type.CustomFloat)
import importlib
variant_module = importlib.import_module("@MODNAME@")
V1 = variant_module.V1
V2 = variant_module.V2
VariantHolder = variant_module.VariantHolder
VariantFullHolder = variant_module.VariantFullHolder
make_variant = variant_module.make_variant
make_variant_full_none = variant_module.make_variant_full_none
make_variant_full_float = variant_module.make_variant_full_float
make_variant_full_int = variant_module.make_variant_full_int
make_variant_full_bool = variant_module.make_variant_full_bool
make_variant_full_str = variant_module.make_variant_full_str
make_variant_full_complex = variant_module.make_variant_full_complex
variant = make_variant()
assert isinstance(variant, V1)
v1 = V1()
v1.v = 10
v2 = V2()
v2.v = "c"
variant_holder = VariantHolder()
# Test copy from variant alternative V1 to non initialized variant
variant_holder.variant = v1
assert isinstance(variant_holder.variant, V1)
assert variant_holder.variant.v == v1.v
# variant_holder.variant is a copy of v1
variant_holder.variant.v = 11
assert v1.v != variant_holder.variant.v
# Test variant_holder.variant return by reference
# v1 reference variant_holder.variant
v1 = variant_holder.variant
variant_holder.variant.v = 100
assert variant_holder.variant.v == 100
assert v1.v == 100
v1.v = 1000
assert variant_holder.variant.v == 1000
assert v1.v == 1000
# Test with the second alternative type
variant_holder.variant = v2
assert isinstance(variant_holder.variant, V2)
assert variant_holder.variant.v == v2.v
# Test variant that hold a None value
v_full = make_variant_full_none()
assert v_full is None
# Test variant that hold a float value
v_full = make_variant_full_float()
assert v_full == 3.14
assert isinstance(v_full, float)
# Test variant that hold a int value
v_full = make_variant_full_int()
assert v_full == 3
assert isinstance(v_full, int)
# Test variant that hold a bool value
v_full = make_variant_full_bool()
assert not v_full
assert isinstance(v_full, bool)
# Test variant that hold a str value
v_full = make_variant_full_str()
assert v_full == "str"
assert isinstance(v_full, str)
# Test variant that hold a complex value
v_full = make_variant_full_complex()
assert v_full == 1 + 0j
assert isinstance(v_full, complex)
variant_full_holder = VariantFullHolder()
# Test None
v_none = variant_full_holder.variant
assert v_none is None
variant_full_holder.variant = None
assert v_none is None
# Test V1
v1 = V1()
v1.v = 10
variant_full_holder.variant = v1
assert variant_full_holder.variant.v == 10
assert isinstance(variant_full_holder.variant, V1)
# Test V1 ref
v1 = variant_full_holder.variant
v1.v = 100
assert variant_full_holder.variant.v == 100
variant_full_holder.variant = None
# Test bool
variant_full_holder.variant = True
assert variant_full_holder.variant
assert isinstance(variant_full_holder.variant, bool)
# Test int
variant_full_holder.variant = 3
assert variant_full_holder.variant == 3
assert isinstance(variant_full_holder.variant, int)
# Test float
variant_full_holder.variant = 3.14
assert variant_full_holder.variant == 3.14
assert isinstance(variant_full_holder.variant, float)
# Test str
variant_full_holder.variant = "str"
assert variant_full_holder.variant == "str"
assert isinstance(variant_full_holder.variant, str)
# Test complex
variant_full_holder.variant = 1 + 0j
assert variant_full_holder.variant == 1 + 0j
assert isinstance(variant_full_holder.variant, complex)
from __future__ import print_function
import eigenpy import eigenpy
assert eigenpy.checkVersionAtLeast(0, 0, 0) assert eigenpy.checkVersionAtLeast(0, 0, 0)
......
/*
* Copyright 2024 CNRS INRIA
*/
#include <iostream>
#include "eigenpy/eigenpy.hpp"
template <typename Scalar, int Options>
Eigen::SparseMatrix<Scalar, Options> vector1x1(const Scalar& value) {
typedef Eigen::SparseMatrix<Scalar, Options> ReturnType;
ReturnType mat(1, 1);
mat.coeffRef(0, 0) = value;
mat.makeCompressed();
return mat;
}
template <typename Scalar, int Options>
Eigen::SparseMatrix<Scalar, Options> matrix1x1(const Scalar& value) {
typedef Eigen::SparseMatrix<Scalar, Options> ReturnType;
ReturnType mat(1, 1);
mat.coeffRef(0, 0) = value;
mat.makeCompressed();
return mat;
}
template <typename Scalar, int Options>
Eigen::SparseMatrix<Scalar, Options> diagonal(
const Eigen::Ref<const Eigen::Matrix<Scalar, Eigen::Dynamic, 1> >&
diag_values) {
typedef Eigen::SparseMatrix<Scalar, Options> ReturnType;
ReturnType mat(diag_values.size(), diag_values.size());
for (Eigen::Index k = 0; k < diag_values.size(); ++k)
mat.coeffRef(k, k) = diag_values[k];
mat.makeCompressed();
return mat;
}
template <typename Scalar, int Options>
Eigen::SparseMatrix<Scalar, Options> emptyVector() {
return Eigen::SparseMatrix<Scalar, Options>();
}
template <typename Scalar, int Options>
Eigen::SparseMatrix<Scalar, Options> emptyMatrix() {
return Eigen::SparseMatrix<Scalar, Options>();
}
template <typename Scalar, int Options>
void print(const Eigen::SparseMatrix<Scalar, Options>& mat) {
std::cout << mat << std::endl;
}
template <typename Scalar, int Options>
Eigen::SparseMatrix<Scalar, Options> copy(
const Eigen::SparseMatrix<Scalar, Options>& mat) {
return mat;
}
template <typename Scalar, int Options>
void expose_functions() {
namespace bp = boost::python;
bp::def("vector1x1", vector1x1<Scalar, Options>);
bp::def("matrix1x1", matrix1x1<Scalar, Options>);
bp::def("print", print<Scalar, Options>);
bp::def("copy", copy<Scalar, Options>);
bp::def("diagonal", diagonal<Scalar, Options>);
bp::def("emptyVector", emptyVector<Scalar, Options>);
bp::def("emptyMatrix", emptyMatrix<Scalar, Options>);
}
BOOST_PYTHON_MODULE(sparse_matrix) {
namespace bp = boost::python;
eigenpy::enableEigenPy();
expose_functions<double, Eigen::ColMajor>();
expose_functions<double, Eigen::RowMajor>();
}
/// @file
/// @copyright Copyright 2023 CNRS INRIA
#include "eigenpy/std-array.hpp"
using Eigen::VectorXd;
std::array<int, 3> get_arr_3_ints() { return {1, 2, 3}; }
std::array<VectorXd, 3> get_arr_3_vecs() {
std::array<VectorXd, 3> out;
out[0].setOnes(4);
out[1].setZero(2);
out[2].setRandom(10);
return out;
}
struct test_struct {
std::array<int, 3> integs;
std::array<VectorXd, 2> vecs;
test_struct() {
integs = {42, 3, -1};
vecs[0].setRandom(4); // 4 randoms between [-1,1]
vecs[1].setZero(11); // 11 zeroes
}
};
BOOST_PYTHON_MODULE(std_array) {
using namespace eigenpy;
enableEigenPy();
StdArrayPythonVisitor<std::array<int, 3>, true>::expose("StdArr3_int");
StdVectorPythonVisitor<std::vector<int>, true>::expose("StdVec_int");
exposeStdArrayEigenSpecificType<VectorXd, 2>("VectorXd");
exposeStdArrayEigenSpecificType<VectorXd, 3>("VectorXd");
exposeStdVectorEigenSpecificType<VectorXd>("VectorXd");
bp::def("get_arr_3_ints", get_arr_3_ints);
bp::def("get_arr_3_vecs", get_arr_3_vecs);
bp::class_<test_struct>("test_struct", bp::init<>(bp::args("self")))
.def_readwrite("integs", &test_struct::integs)
.def_readwrite("vecs", &test_struct::vecs);
}
/// @file
/// @copyright Copyright 2023 CNRS INRIA
#include <eigenpy/eigenpy.hpp>
#include <eigenpy/std-map.hpp>
#include <boost/unordered_map.hpp>
namespace bp = boost::python;
template <typename T1>
bp::dict std_map_to_dict(const std::map<std::string, T1>& map) {
bp::dict dictionnary;
for (auto const& x : map) {
dictionnary[x.first] = x.second;
}
return dictionnary;
}
template <typename T1>
std::map<std::string, T1> copy(const std::map<std::string, T1>& map) {
std::map<std::string, T1> out = map;
return out;
}
template <typename T1>
boost::unordered_map<std::string, T1> copy_boost(
const boost::unordered_map<std::string, T1>& obj) {
return obj;
}
struct X {
X() = delete;
X(int x) : val(x) {}
int val;
};
BOOST_PYTHON_MODULE(std_map) {
eigenpy::enableEigenPy();
eigenpy::StdMapPythonVisitor<
std::string, double, std::less<std::string>,
std::allocator<std::pair<const std::string, double> >,
true>::expose("StdMap_Double");
eigenpy::GenericMapVisitor<boost::unordered_map<std::string, int> >::expose(
"boost_map_int");
using StdMap_X = std::map<std::string, X>;
bp::class_<X>("X", bp::init<int>()).def_readwrite("val", &X::val);
// this just needs to compile
eigenpy::GenericMapVisitor<StdMap_X>::expose(
"StdMap_X", eigenpy::overload_base_get_item_for_map<StdMap_X>());
bp::def("std_map_to_dict", std_map_to_dict<double>);
bp::def("copy", copy<double>);
bp::def("copy_boost", copy_boost<int>);
bp::def("copy_X", +[](const StdMap_X& m) { return m; });
}
/// @file
/// @copyright Copyright 2023 CNRS INRIA
#include <eigenpy/eigenpy.hpp>
#include <eigenpy/std-pair.hpp>
namespace bp = boost::python;
template <typename T1, typename T2>
bp::tuple std_pair_to_tuple(const std::pair<T1, T2>& pair) {
return bp::make_tuple(pair.first, pair.second);
}
template <typename T1, typename T2>
std::pair<T1, T2> copy(const std::pair<T1, T2>& pair) {
return pair;
}
template <typename T1, typename T2>
const std::pair<T1, T2>& passthrough(const std::pair<T1, T2>& pair) {
return pair;
}
BOOST_PYTHON_MODULE(std_pair) {
eigenpy::enableEigenPy();
typedef std::pair<int, double> PairType;
eigenpy::StdPairConverter<PairType>::registration();
bp::def("std_pair_to_tuple", std_pair_to_tuple<int, double>);
bp::def("copy", copy<int, double>);
bp::def("passthrough", passthrough<int, double>,
bp::return_value_policy<bp::copy_const_reference>());
}
/// @file
/// @copyright Copyright 2023 CNRS INRIA
#include <eigenpy/eigenpy.hpp>
#include <eigenpy/std-unique-ptr.hpp>
#include <memory>
#include <string>
#include <complex>
namespace bp = boost::python;
struct V1 {
V1() = default;
V1(double p_v) : v(p_v) {}
double v = 100;
};
std::unique_ptr<int> make_unique_int() { return std::make_unique<int>(10); }
std::unique_ptr<V1> make_unique_v1() { return std::make_unique<V1>(10); }
std::unique_ptr<V1> make_unique_null() { return nullptr; }
std::unique_ptr<std::string> make_unique_str() {
return std::make_unique<std::string>("str");
}
std::unique_ptr<std::complex<double> > make_unique_complex() {
return std::make_unique<std::complex<double> >(1., 0.);
}
struct UniquePtrHolder {
UniquePtrHolder()
: int_ptr(std::make_unique<int>(20)),
v1_ptr(std::make_unique<V1>(200)),
str_ptr(std::make_unique<std::string>("str")),
complex_ptr(std::make_unique<std::complex<double> >(1., 0.)) {}
std::unique_ptr<int> int_ptr;
std::unique_ptr<V1> v1_ptr;
std::unique_ptr<V1> null_ptr;
std::unique_ptr<std::string> str_ptr;
std::unique_ptr<std::complex<double> > complex_ptr;
};
BOOST_PYTHON_MODULE(std_unique_ptr) {
eigenpy::enableEigenPy();
bp::class_<V1>("V1", bp::init<>()).def_readwrite("v", &V1::v);
bp::def("make_unique_int", make_unique_int);
bp::def("make_unique_v1", make_unique_v1);
bp::def("make_unique_null", make_unique_null,
eigenpy::StdUniquePtrCallPolicies());
bp::def("make_unique_str", make_unique_str);
bp::def("make_unique_complex", make_unique_complex);
boost::python::class_<UniquePtrHolder, boost::noncopyable>("UniquePtrHolder",
bp::init<>())
.add_property("int_ptr",
bp::make_getter(&UniquePtrHolder::int_ptr,
eigenpy::ReturnInternalStdUniquePtr()))
.add_property("v1_ptr",
bp::make_getter(&UniquePtrHolder::v1_ptr,
eigenpy::ReturnInternalStdUniquePtr()))
.add_property("null_ptr",
bp::make_getter(&UniquePtrHolder::null_ptr,
eigenpy::ReturnInternalStdUniquePtr()))
.add_property("str_ptr",
bp::make_getter(&UniquePtrHolder::str_ptr,
eigenpy::ReturnInternalStdUniquePtr()))
.add_property("complex_ptr",
bp::make_getter(&UniquePtrHolder::complex_ptr,
eigenpy::ReturnInternalStdUniquePtr()));
}
...@@ -30,6 +30,10 @@ void setZero(std::vector<MatType, Eigen::aligned_allocator<MatType> > &Ms) { ...@@ -30,6 +30,10 @@ void setZero(std::vector<MatType, Eigen::aligned_allocator<MatType> > &Ms) {
} }
} }
struct CustomTestStruct {
bool operator==(const CustomTestStruct &) const { return true; }
};
BOOST_PYTHON_MODULE(std_vector) { BOOST_PYTHON_MODULE(std_vector) {
namespace bp = boost::python; namespace bp = boost::python;
using namespace eigenpy; using namespace eigenpy;
...@@ -49,4 +53,19 @@ BOOST_PYTHON_MODULE(std_vector) { ...@@ -49,4 +53,19 @@ BOOST_PYTHON_MODULE(std_vector) {
typedef Eigen::Ref<Eigen::MatrixXd> RefXd; typedef Eigen::Ref<Eigen::MatrixXd> RefXd;
StdVectorPythonVisitor<std::vector<RefXd>, true>::expose("StdVec_MatRef"); StdVectorPythonVisitor<std::vector<RefXd>, true>::expose("StdVec_MatRef");
bp::def("setZero", setZero<Eigen::MatrixXd>, "Sets the coeffs to 0."); bp::def("setZero", setZero<Eigen::MatrixXd>, "Sets the coeffs to 0.");
// Test matrix modification
// Mat2d don't have tolist, reserve, mutable __getitem__ and from list
// conversion
// exposeStdVectorEigenSpecificType must add those methods to StdVec_Mat2d
bp::class_<std::vector<Eigen::Matrix2d> >("StdVec_Mat2d")
.def(boost::python::vector_indexing_suite<
std::vector<Eigen::Matrix2d> >());
exposeStdVectorEigenSpecificType<Eigen::Matrix2d>("Mat2d");
// Test API regression:
// Exposing a `std::vector` with documentation doesn't clash with
// exposing a `std::vector` with a visitor
StdVectorPythonVisitor<std::vector<CustomTestStruct> >::expose(
"StdVec_CustomTestStruct", "some documentation");
} }
...@@ -122,7 +122,7 @@ template <typename Scalar, int Rank> ...@@ -122,7 +122,7 @@ template <typename Scalar, int Rank>
struct TensorContainer { struct TensorContainer {
typedef Eigen::Tensor<Scalar, Rank> Tensor; typedef Eigen::Tensor<Scalar, Rank> Tensor;
typedef Eigen::TensorRef<Tensor> TensorRef; typedef Eigen::TensorRef<Tensor> TensorRef;
typedef Eigen::Matrix<Scalar, Rank, 1> Dimensions; typedef Eigen::Matrix<typename Tensor::Index, Rank, 1> Dimensions;
Tensor m_tensor; Tensor m_tensor;
TensorContainer(const Dimensions& dims) { TensorContainer(const Dimensions& dims) {
......
/*
* Copyright 2024 INRIA
*/
#include <iostream>
#include "eigenpy/eigenpy.hpp"
#include "eigenpy/type_info.hpp"
struct Dummy {};
BOOST_PYTHON_MODULE(type_info) {
using namespace Eigen;
namespace bp = boost::python;
eigenpy::enableEigenPy();
eigenpy::expose_boost_type_info<int>();
eigenpy::expose_boost_type_info<std::string>();
bp::class_<Dummy>("Dummy").def(eigenpy::TypeInfoVisitor<Dummy>());
}
...@@ -54,6 +54,9 @@ struct NumTraits<CustomType<Scalar> > { ...@@ -54,6 +54,9 @@ struct NumTraits<CustomType<Scalar> > {
} }
static int digits10() { return std::numeric_limits<Scalar>::digits10; } static int digits10() { return std::numeric_limits<Scalar>::digits10; }
static int max_digits10() {
return std::numeric_limits<Scalar>::max_digits10;
}
}; };
} // namespace Eigen } // namespace Eigen
...@@ -198,14 +201,19 @@ BOOST_PYTHON_MODULE(user_type) { ...@@ -198,14 +201,19 @@ BOOST_PYTHON_MODULE(user_type) {
eigenpy::registerCast<DoubleType, double>(true); eigenpy::registerCast<DoubleType, double>(true);
eigenpy::registerCast<double, DoubleType>(true); eigenpy::registerCast<double, DoubleType>(true);
eigenpy::registerCast<DoubleType, float>(false);
eigenpy::registerCast<float, DoubleType>(true);
eigenpy::registerCast<DoubleType, int>(false); eigenpy::registerCast<DoubleType, int>(false);
eigenpy::registerCast<int, DoubleType>(true); eigenpy::registerCast<int, DoubleType>(true);
eigenpy::registerCast<DoubleType, long long>(false); eigenpy::registerCast<DoubleType, long long>(false);
eigenpy::registerCast<long long, DoubleType>(true); eigenpy::registerCast<long long, DoubleType>(true);
eigenpy::registerCast<DoubleType, long>(false); eigenpy::registerCast<DoubleType, long>(false);
eigenpy::registerCast<long, DoubleType>(true); eigenpy::registerCast<long, DoubleType>(true);
eigenpy::registerCast<FloatType, double>(true); eigenpy::registerCast<FloatType, double>(true);
eigenpy::registerCast<double, FloatType>(false); eigenpy::registerCast<double, FloatType>(false);
eigenpy::registerCast<FloatType, float>(true);
eigenpy::registerCast<float, FloatType>(true);
eigenpy::registerCast<FloatType, long long>(false); eigenpy::registerCast<FloatType, long long>(false);
eigenpy::registerCast<long long, FloatType>(true); eigenpy::registerCast<long long, FloatType>(true);
eigenpy::registerCast<FloatType, int>(false); eigenpy::registerCast<FloatType, int>(false);
......
/// @file
/// @copyright Copyright 2024 CNRS INRIA
#include <eigenpy/eigenpy.hpp>
#include <eigenpy/variant.hpp>
#include <string>
#include <complex>
#cmakedefine TEST_TYPE @TEST_TYPE@
#define VARIANT TEST_TYPE
namespace bp = boost::python;
struct V1 {
int v;
};
struct V2 {
char v;
};
typedef VARIANT<V1, V2> MyVariant;
template <typename Variant>
struct MyVariantNoneHelper {};
template <typename... Alternatives>
struct MyVariantNoneHelper<boost::variant<Alternatives...> > {
typedef VARIANT<boost::blank, Alternatives...> type;
};
#ifdef EIGENPY_WITH_CXX17_SUPPORT
template <typename... Alternatives>
struct MyVariantNoneHelper<std::variant<Alternatives...> > {
typedef VARIANT<std::monostate, Alternatives...> type;
};
#endif
typedef typename MyVariantNoneHelper<
VARIANT<V1, bool, int, double, std::string, std::complex<double> > >::type
MyVariantFull;
MyVariant make_variant() { return V1(); }
MyVariantFull make_variant_full_none() { return MyVariantFull(); }
MyVariantFull make_variant_full_float() { return 3.14; }
MyVariantFull make_variant_full_int() { return 3; }
MyVariantFull make_variant_full_bool() { return false; }
MyVariantFull make_variant_full_str() { return std::string("str"); }
MyVariantFull make_variant_full_complex() { return std::complex<double>(1., 0.); }
struct VariantHolder {
MyVariant variant;
};
struct VariantFullHolder {
MyVariantFull variant;
};
BOOST_PYTHON_MODULE(@MODNAME@) {
using namespace eigenpy;
enableEigenPy();
bp::class_<V1>("V1", bp::init<>()).def_readwrite("v", &V1::v);
bp::class_<V2>("V2", bp::init<>()).def_readwrite("v", &V2::v);
typedef eigenpy::VariantConverter<MyVariant> Converter;
Converter::registration();
bp::def("make_variant", make_variant);
boost::python::class_<VariantHolder>("VariantHolder", bp::init<>())
.add_property("variant",
bp::make_getter(&VariantHolder::variant,
Converter::return_internal_reference()),
bp::make_setter(&VariantHolder::variant));
typedef eigenpy::VariantConverter<MyVariantFull> ConverterFull;
ConverterFull::registration();
bp::def("make_variant_full_none", make_variant_full_none);
bp::def("make_variant_full_float", make_variant_full_float);
bp::def("make_variant_full_int", make_variant_full_int);
bp::def("make_variant_full_bool", make_variant_full_bool);
bp::def("make_variant_full_str", make_variant_full_str);
bp::def("make_variant_full_complex", make_variant_full_complex);
boost::python::class_<VariantFullHolder>("VariantFullHolder", bp::init<>())
.add_property("variant",
bp::make_getter(&VariantFullHolder::variant,
ConverterFull::return_internal_reference()),
bp::make_setter(&VariantFullHolder::variant));
}