2013-06-04 32 views
5

Những gì tôi muốn làm thực chất là thực hiện chức năng này:Tạo một Eigen Matrix từ một mảng C

template<typename T> 
Matrix<T, Dynamic, Dynamic, ColMajor>* dataToEigen(T* const data, const int rows, const int cols); 

mà không sao chép bất kỳ dữ liệu. Tôi biết cách tiêu chuẩn để thực hiện một cái gì đó như thế này là với một bản đồ, nhưng tôi có một số vấn đề với cách tiếp cận này.

  1. Tôi không muốn viết lại phần còn lại của mã để chấp nhận Maps làm đầu vào (không sao chép Bản đồ thành ma trận tạm thời). Tôi biết tôi có thể làm điều này bằng cách khái quát các chức năng của mình để lấy các đối tượng MatrixBase làm đầu vào, nhưng tôi đã định nghĩa các mẫu Ma trận cụ thể trong các đầu vào của mình vì một lý do - nếu hàm của tôi mất Matrix<T, Dynamic, Dynamic, ColMajor>, thì đó là vì chỉ sử dụng ma trận loại đó làm đầu vào.

  2. Lý tưởng nhất, tôi muốn tạo Ma trận để sở hữu con trỏ dữ liệu, vì vậy tôi chỉ có thể quản lý Ma trận thông qua shared_ptr và không phải chạm vào con trỏ dữ liệu ban đầu nữa.

suy nghĩ ban đầu của tôi là tôi có thể làm một cái gì đó giống như tạo ra một đối tượng Matrix động có kích thước chưa được khởi tạo, và sau đó chỉ cần thiết lập kích thước và dữ liệu của đối tượng con trỏ, nhưng điều này dường như không thể trong API Eigen. Có ai biết về bất kỳ cách giải quyết?

Trả lời

3

Có rất ít khả năng Eigen :: Matrix sẽ được phép trực tiếp quấn bộ đệm ngoài và có nhiều lý do chính đáng cho việc bao gồm khả năng tương thích ABI, tính nhất quán API trên các ma trận động và được phân bổ tĩnh.

Một workaround xấu xí sẽ được xác định một cấu trúc với cách bố trí tương tự như MatrixX_:

template<typename T> struct Foo { 
    T* data; 
    DenseIndex rows, cols; 
    Matrix<T, Dynamic, Dynamic, ColMajor>& asMatrix() { 
    return reinterpret_cast<Matrix<T, Dynamic, Dynamic, ColMajor>&>(*this); 
    } 
}; 

Một giải pháp khác sẽ được di chuyển đến chi nhánh devel (khá ổn định), và sử dụng lớp mới Ref<> đó là được thiết kế để giải quyết vấn đề chính xác của bạn và hơn thế nữa. documentation của nó là đủ để sử dụng nó đúng cách. Khó khăn duy nhất là bạn có thể dễ dàng templatize loại vô hướng bởi vì Ref <> không phải là một lớp cơ sở của Ma trận hoặc Bản đồ, và do đó bạn sẽ phải gọi fonction của bạn bằng cách xác định loại vô hướng một cách rõ ràng, hoặc tạo Ref < > sao chép bản thân:

foo<T>(M); 
foo(Ref<MatrixXd>(M)); 
+1

Cách giải quyết xấu xí của bạn có vẻ là giải pháp đơn giản nhất, nhưng điều đó không nguy hiểm đến mức nào? Tôi không quá lo lắng vào lúc này về mã biên dịch thực tế đang được di chuyển, nhưng có bất kỳ Foo đảm bảo nào và một MatrixX có khuôn mẫu sẽ kết thúc với sự sắp xếp trong bộ nhớ giống nhau không? Đối với tùy chọn thứ hai, có vẻ như tôi có thể viết lại phương pháp của tôi để tìm một cái gì đó như: mẫu void Foo (const Ref >) và điều này sẽ cho phép họ chấp nhận cả hai đầu vào Matrix và Map >? – user2452966

+1

Bố cục bộ nhớ được đảm bảo (khả năng tương thích ABI trên các phiên bản Eigen). Đối với Ref <> có, đó là cách sử dụng nó.Vấn đề là nó ít thuận tiện hơn khi được định nghĩa một phần với tham số mẫu vì Ma trận hoặc Bản đồ không kế thừa Ref <> và do đó trình biên dịch sẽ không được phép ngầm khởi tạo các đối số mẫu phù hợp. Vì vậy, bạn hoặc phải cung cấp một cách rõ ràng, hoặc rõ ràng chuyển đổi sang Ref <>, hoặc nếu bạn chỉ quan tâm đến 2 hoặc 3 loại vô hướng, bạn cũng có thể thực hiện 2-3 quá tải gọi phiên bản chung (giải pháp sạch nhất). – ggael

-1

tôi nghĩ rằng giải pháp dễ dàng như sau:

float **data = new float[numRows][numCols]; 
MatrixXf M(numRows,numCols); 
M.data() = data; 

theo mặc định, dữ liệu trong một ma trận được tổ chức Cột Major, vì vậy nếu bạn muốn ma trận của bạn để truy cập dữ liệu float ** trong một hàng Thứ tự lớn, bạn có thể chuyển ma trận sau khi gán.

Các vấn đề liên quan