mirror of
https://github.com/CHN-beta/nixos.git
synced 2026-01-12 04:39:23 +08:00
packages.biu: 完成 eigen 转换
This commit is contained in:
@@ -162,7 +162,7 @@
|
||||
config = { archive = false; branch = "production"; };
|
||||
devShells.x86_64-linux = let inherit (inputs.self.packages.x86_64-linux) pkgs; in
|
||||
{
|
||||
biu = pkgs.mkShell
|
||||
biu = pkgs.mkShell.override { stdenv = pkgs.gcc14Stdenv; }
|
||||
{
|
||||
inputsFrom = [ pkgs.localPackages.biu ];
|
||||
packages = [ pkgs.clang-tools_18 ];
|
||||
|
||||
@@ -32,10 +32,12 @@ namespace biu
|
||||
// if size is specified as a number, convert to fixed-size Eigen::Vector if specified size equals the size of the
|
||||
// input, otherwise throw an error
|
||||
// return deduced size if the size is deducible in compile time, otherwise return Empty
|
||||
template <std::size_t ToSize, typename Container> constexpr auto deduce_eigen_size();
|
||||
template <std::size_t ToSize, typename Container> consteval auto deduce_eigen_size();
|
||||
|
||||
// helper operator| to specify the size of the destination container
|
||||
template <std::size_t Row, std::size_t Col> struct ToEigenHelper {};
|
||||
template <std::size_t Size> struct FromEigenVectorHelper {};
|
||||
template <std::size_t Row, std::size_t Col> struct FromEigenMatrixHelper {};
|
||||
|
||||
// convert 1D standard container to Eigen::Matrix, the second argument should always be unspecified
|
||||
template <typename From, std::size_t ToSize> auto operator|
|
||||
@@ -51,11 +53,23 @@ namespace biu
|
||||
&& detail_::StandardContainer<typename From::value_type, typename From::value_type::value_type>
|
||||
&& Arithmetic<typename From::value_type::value_type>
|
||||
);
|
||||
|
||||
// convert 1D Eigen matrix to std::vector or std::array
|
||||
template <typename Vector, std::size_t ToSize> auto operator|
|
||||
(const Vector&, const detail_::FromEigenVectorHelper<ToSize>&);
|
||||
|
||||
// convert 2D Eigen matrix to std::vector or std::array
|
||||
template <typename Matrix, std::size_t ToRow, std::size_t ToCol> auto operator|
|
||||
(const Matrix&, const detail_::FromEigenMatrixHelper<ToRow, ToCol>&);
|
||||
}
|
||||
|
||||
// usage: some_value | toEigen<Row, Col>
|
||||
template <std::size_t Row = detail_::unspecifiedSize, std::size_t Col = detail_::unspecifiedSize>
|
||||
inline constexpr detail_::ToEigenHelper<Row, Col> toEigen;
|
||||
template <std::size_t Size = detail_::unspecifiedSize>
|
||||
inline constexpr detail_::FromEigenVectorHelper<Size> fromEigenVector;
|
||||
template <std::size_t Row = detail_::unspecifiedSize, std::size_t Col = detail_::unspecifiedSize>
|
||||
inline constexpr detail_::FromEigenMatrixHelper<Row, Col> fromEigenMatrix;
|
||||
|
||||
// test if a class is an eigen matrix
|
||||
namespace detail_
|
||||
@@ -66,7 +80,7 @@ namespace biu
|
||||
}
|
||||
template <typename Matrix> concept EigenMatrix = detail_::EigenMatrix<Matrix>::value;
|
||||
}
|
||||
using eigen::toEigen, eigen::EigenMatrix;
|
||||
using eigen::toEigen, eigen::fromEigenVector, eigen::fromEigenMatrix, eigen::EigenMatrix;
|
||||
}
|
||||
|
||||
// archive a matrix
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# pragma once
|
||||
# include <utility>
|
||||
# include <biu/eigen.hpp>
|
||||
# include <biu/common.hpp>
|
||||
# include <range/v3/view.hpp>
|
||||
@@ -6,10 +7,10 @@
|
||||
|
||||
namespace biu::eigen
|
||||
{
|
||||
template <std::size_t ToSize, typename Container> constexpr auto detail_::deduce_eigen_size()
|
||||
template <std::size_t ToSize, typename Container> consteval auto detail_::deduce_eigen_size()
|
||||
{
|
||||
if constexpr (ToSize == detail_::dynamicSize) return Empty{};
|
||||
else if constexpr (ToSize == detail_::unspecifiedSize)
|
||||
if constexpr (ToSize == dynamicSize) return Empty{};
|
||||
else if constexpr (ToSize == unspecifiedSize)
|
||||
if constexpr (SpecializationOfArray<Container>) return Container{}.size();
|
||||
else return Empty{};
|
||||
else
|
||||
@@ -105,6 +106,150 @@ namespace biu::eigen
|
||||
return Matrix(Eigen::Map<const Matrix>(data.data()));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Vector, std::size_t ToSize> auto detail_::operator|
|
||||
(const Vector& vector, const detail_::FromEigenVectorHelper<ToSize>&)
|
||||
{
|
||||
// 尽量在编译时获得大小并检查大小是否匹配,第一个返回值为确定的大小,第二个返回值为用于在运行时检查大小的函数
|
||||
auto get_size = []<std::size_t to_size>(this auto&& self) consteval
|
||||
{
|
||||
// 如果没有指定
|
||||
if constexpr (to_size == unspecifiedSize)
|
||||
// 如果两个维度都是动态的,那么作为动态大小处理
|
||||
if constexpr
|
||||
(
|
||||
Vector::CompileTimeTraits::RowsAtCompileTime == Eigen::Dynamic
|
||||
&& Vector::CompileTimeTraits::ColsAtCompileTime == Eigen::Dynamic
|
||||
)
|
||||
return std::make_pair
|
||||
(dynamicSize, [](const Vector& vector) { return vector.nrows() <= 1 && vector.ncols() <= 1; });
|
||||
// 如果两个维度都是固定的
|
||||
else if constexpr
|
||||
(
|
||||
Vector::CompileTimeTraits::RowsAtCompileTime != Eigen::Dynamic
|
||||
&& Vector::CompileTimeTraits::ColsAtCompileTime != Eigen::Dynamic
|
||||
)
|
||||
// 如果两个维度都超过了 1
|
||||
if constexpr
|
||||
(Vector::CompileTimeTraits::RowsAtCompileTime > 1 && Vector::CompileTimeTraits::ColsAtCompileTime > 1)
|
||||
throw std::invalid_argument("The size of the destination Eigen container mismatches the input container");
|
||||
// 否则返回两个维度的乘积
|
||||
else return std::make_pair
|
||||
(
|
||||
Vector::CompileTimeTraits::RowsAtCompileTime * Vector::CompileTimeTraits::ColsAtCompileTime,
|
||||
[](const Vector&) consteval { return true; }
|
||||
);
|
||||
// 如果固定的那个维度等于 1,那么为动态大小(大小取决于另外一个没有固定的维度)
|
||||
// 否则,大小等于这个维度,另一个维度是否为 1 留作之后检查
|
||||
else if constexpr (Vector::CompileTimeTraits::RowsAtCompileTime != Eigen::Dynamic)
|
||||
if constexpr (Vector::CompileTimeTraits::RowsAtCompileTime == 1)
|
||||
return std::make_pair(dynamicSize, [](const Vector&) consteval { return true; });
|
||||
else
|
||||
return std::make_pair
|
||||
(
|
||||
Vector::CompileTimeTraits::RowsAtCompileTime,
|
||||
[](const Vector& vector) { return vector.ncols() <= 1; }
|
||||
);
|
||||
else if constexpr (Vector::CompileTimeTraits::ColsAtCompileTime != Eigen::Dynamic)
|
||||
if constexpr (Vector::CompileTimeTraits::ColsAtCompileTime == 1)
|
||||
return std::make_pair(dynamicSize, [](const Vector&) consteval { return true; });
|
||||
else
|
||||
return std::make_pair
|
||||
(
|
||||
Vector::CompileTimeTraits::ColsAtCompileTime,
|
||||
[](const Vector& vector) { return vector.nrows() <= 1; }
|
||||
);
|
||||
else
|
||||
std::unreachable();
|
||||
// 如果指定了为动态:同样按照上述检查,但返回动态大小
|
||||
else if constexpr (to_size == dynamicSize)
|
||||
return std::make_pair(dynamicSize, self->template operator()<unspecifiedSize>().second);
|
||||
// 如果指定了大小:按照上述检查,如果判断为静态大小且大小不一致则报错,如果判断为动态大小则额外判断大小
|
||||
else
|
||||
{
|
||||
auto result = self->template operator()<unspecifiedSize>();
|
||||
if constexpr (result.first != dynamicSize)
|
||||
if constexpr (result.first != to_size)
|
||||
throw std::invalid_argument("The size of the destination Eigen container mismatches the input container");
|
||||
else
|
||||
return result;
|
||||
else
|
||||
return std::make_pair
|
||||
(
|
||||
to_size,
|
||||
[size = to_size](const Vector& vector) { return vector.size() == size; }
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// decomposition declarations can't be constexpr
|
||||
constexpr auto size = get_size.template operator()<ToSize>();
|
||||
if (!size.second(vector))
|
||||
throw std::invalid_argument("The size of the destination Eigen container mismatches the input container");
|
||||
if constexpr (size.first == dynamicSize)
|
||||
return std::vector<typename Vector::Scalar>(vector.data(), vector.data() + vector.size());
|
||||
else
|
||||
return std::array<typename Vector::Scalar, size.first>(vector.data(), vector.data() + vector.size());
|
||||
}
|
||||
|
||||
template <typename Matrix, std::size_t ToRow, std::size_t ToCol> auto detail_::operator|
|
||||
(const Matrix& matrix, const detail_::FromEigenMatrixHelper<ToRow, ToCol>&)
|
||||
{
|
||||
auto get_size = [] consteval
|
||||
{
|
||||
auto get_one_size = []<std::size_t to_size, int eigen_size> consteval
|
||||
{
|
||||
// 如果没有指定
|
||||
if constexpr (to_size == unspecifiedSize)
|
||||
// 如果原大小是动态的,那么作为动态大小处理
|
||||
if constexpr (eigen_size == Eigen::Dynamic)
|
||||
return std::make_pair(dynamicSize, [](int) { return true; });
|
||||
// 否则返回原大小
|
||||
else return std::make_pair(eigen_size, [](int) { return true; });
|
||||
// 如果指定为动态大小:直接返回动态大小
|
||||
else if constexpr (to_size == dynamicSize)
|
||||
return std::make_pair(dynamicSize, [](int) { return true; });
|
||||
// 如果指定了大小:如果原大小是动态的则返回指定的大小,并在稍后检查;否则现在检查并返回
|
||||
else
|
||||
if constexpr (eigen_size == Eigen::Dynamic)
|
||||
return std::make_pair(to_size, [](int original_size) { return to_size == original_size; });
|
||||
else
|
||||
if constexpr (to_size == eigen_size)
|
||||
return std::make_pair(to_size, [](int) { return true; });
|
||||
else
|
||||
throw std::invalid_argument("The size of the destination Eigen container mismatches the input container");
|
||||
};
|
||||
constexpr auto row = get_one_size.template operator()<ToRow, Matrix::CompileTimeTraits::RowsAtCompileTime>();
|
||||
constexpr auto col = get_one_size.template operator()<ToCol, Matrix::CompileTimeTraits::ColsAtCompileTime>();
|
||||
return std::make_pair
|
||||
(
|
||||
std::make_pair(row.first, col.first),
|
||||
[row_check = row.second, col_check = col.second](const Matrix& matrix)
|
||||
{ return row_check(matrix.rows()) && col_check(matrix.cols()); }
|
||||
);
|
||||
};
|
||||
|
||||
// decomposition declarations can't be constexpr
|
||||
constexpr auto size = get_size();
|
||||
if (!size.second(matrix))
|
||||
throw std::invalid_argument("The size of the destination Eigen container mismatches the input container");
|
||||
|
||||
// 首先构造每一行
|
||||
using container_per_row = std::conditional_t<size.first.second == dynamicSize,
|
||||
std::vector<typename Matrix::Scalar>, std::array<typename Matrix::Scalar, size.first.second>>;
|
||||
using container = std::conditional_t<size.first.first == dynamicSize,
|
||||
std::vector<container_per_row>, std::array<container_per_row, size.first.first>>;
|
||||
container result;
|
||||
if constexpr (size.first.first == dynamicSize) result.resize(matrix.rows());
|
||||
if constexpr (size.first.second == dynamicSize) for (auto& row : result) row.resize(matrix.cols());
|
||||
for (int i = 0; i < matrix.rows(); i++)
|
||||
{
|
||||
using RowVector = Eigen::RowVector
|
||||
<typename Matrix::Scalar, size.first.second == dynamicSize ? Eigen::Dynamic : size.first.second>;
|
||||
Eigen::Map<RowVector>(result[i].data(), 1, matrix.cols()) = matrix.row(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
template <typename Matrix> constexpr auto Eigen::serialize(auto & archive, Matrix& matrix)
|
||||
requires biu::EigenMatrix<std::remove_cvref_t<Matrix>>
|
||||
|
||||
@@ -15,6 +15,11 @@ int main()
|
||||
auto d = std::array{std::array{1, 2}, std::array{3, 4}, std::array{5, 6}}
|
||||
| biu::eigen::toEigen<>;
|
||||
static_assert(std::same_as<decltype(d), Eigen::Matrix<int, 3, 2, Eigen::RowMajor | Eigen::AutoAlign>>);
|
||||
auto f = std::vector{1, 2, 3, 4, 5};
|
||||
assert(f == (f | biu::toEigen<> | biu::fromEigenVector<>));
|
||||
auto g = std::vector
|
||||
{std::array{1, 2}, std::array{3, 4}, std::array{5, 6}};
|
||||
assert(g == (g | biu::toEigen<> | biu::fromEigenMatrix<>));
|
||||
|
||||
auto e = biu::deserialize<decltype(c)>(biu::serialize(c));
|
||||
static_assert(std::same_as<decltype(e), decltype(c)>);
|
||||
|
||||
@@ -58,7 +58,7 @@ inputs: rec
|
||||
mumax = inputs.pkgs.callPackage ./mumax.nix { src = inputs.topInputs.mumax; };
|
||||
kylin-virtual-keyboard = inputs.pkgs.libsForQt5.callPackage ./kylin-virtual-keyboard.nix
|
||||
{ src = inputs.topInputs.kylin-virtual-keyboard; };
|
||||
biu = inputs.pkgs.callPackage ./biu { inherit nameof zpp-bits; };
|
||||
biu = inputs.pkgs.callPackage ./biu { inherit nameof zpp-bits; stdenv = inputs.pkgs.gcc14Stdenv; };
|
||||
zxorm = inputs.pkgs.callPackage ./zxorm.nix { src = inputs.topInputs.zxorm; };
|
||||
hpcstat = inputs.pkgs.callPackage ./hpcstat
|
||||
{ inherit sqlite-orm date biu openxlsx; stdenv = inputs.pkgs.gcc14Stdenv; };
|
||||
|
||||
Reference in New Issue
Block a user