eigen在QNX上的移植

对于EIgen数学计算库,官网介绍只需要包含头文件即可,无需编译成动态库,极大提高了多平台的可移植性。windows针对QNX系统有交叉编译工具链qcc,可以直接对c++文件进行编译。因此只需要将test.c文件放在eigen文件夹下直接进行编译即可。

以下内容可以解决移植过程中的报错。

‘abort’ was not declared in this scope · Issue #1 · captainigloo/spark-web-embd-rest-json

用户对问题"编译Eigen以在QNX 6上运行"的回答 - 问答 - 腾讯云开发者社区-腾讯云

#include <iostream>
#include <stdio.h> /* fopen, fputs, fclose, stderr */
#include <stdlib.h> /* abort, NULL */
#include <math.h>
using std::expf;
#include <Eigen/Dense>
using Eigen::MatrixXd;
using Eigen::VectorXd;
using Eigen::Vector3d;

int main()
{
    MatrixXd m = MatrixXd::Random(3,3);
    m = (m + MatrixXd::Constant(3,3,1.2)) * 50;
    std::cout << "m =" << std::endl << m << std::endl;
    // VectorXd v(3);
    // v << 1, 2, 3;
    // std::cout << "m * v =" << std::endl << m * v << std::endl;
    Vector3d v(1,2,3);

    std::cout << "m * v =" << std::endl << m * v << std::endl;
    while(1);
}

报错:unfinded reference to sqrtf;

编译指令:gcc -I. test.cc -o test_eigen -lm

#include <iostream>
#include <stdio.h> /* fopen, fputs, fclose, stderr */
#include <stdlib.h> /* abort, NULL */
#include <math.h>
using std::expf;
#include <Eigen/Dense>
using Eigen::MatrixXd;
using Eigen::VectorXd;
using Eigen::Vector3d;
template <typename T>
static void matrix_mul_matrix(T* p1, int iRow1, int iCol1, T* p2, int iRow2, int iCol2, T* p3)
{
    if (iRow1 != iRow2) return;

    //列优先
    //Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> > map1(p1, iRow1, iCol1);
    //Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> > map2(p2, iRow2, iCol2);
    //Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> > map3(p3, iCol1, iCol2);

    //行优先
    Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > map1(p1, iRow1, iCol1);
    Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > map2(p2, iRow2, iCol2);
    Eigen::Map< Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> > map3(p3, iCol1, iCol2);

    map3 = map1 * map2;
}

int main(int argc, char* argv[])
{
    //1. 矩阵的定义
    Eigen::MatrixXd m(2, 2);
    Eigen::Vector3d vec3d;
    Eigen::Vector4d vec4d(1.0, 2.0, 3.0, 4.0);

    //2. 动态矩阵、静态矩阵
    Eigen::MatrixXd matrixXd;
    Eigen::Matrix3d matrix3d;

    //3. 矩阵元素的访问
    m(0, 0) = 1;
    m(0, 1) = 2;
    m(1, 0) = m(0, 0) + 3; 
    m(1, 1) = m(0, 0) * m(0, 1);
    std::cout << m << std::endl << std::endl;

    //4. 设置矩阵的元素
    m << -1.5, 2.4,
        6.7, 2.0;
    std::cout << m << std::endl << std::endl;
    int row = 4;
    int col = 5;
    Eigen::MatrixXf matrixXf(row, col);
    matrixXf << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20;
    std::cout << matrixXf << std::endl << std::endl;
    matrixXf << Eigen::MatrixXf::Identity(row, col);
    std::cout << matrixXf << std::endl << std::endl;

    //5. 重置矩阵大小
    Eigen::MatrixXd matrixXd1(3, 3);
    m = matrixXd1;
    std::cout << m.rows() << "  " << m.cols() << std::endl << std::endl;

    //6. 矩阵运算
    m << 1, 2, 7,
        3, 4, 8,
        5, 6, 9;
    std::cout << m << std::endl;
    matrixXd1 = Eigen::Matrix3d::Random();
    m += matrixXd1;
    std::cout << m << std::endl << std::endl;
    m *= 2;
    std::cout << m << std::endl << std::endl;
    std::cout << -m << std::endl << std::endl;
    std::cout << m << std::endl << std::endl;

    //7. 求矩阵的转置、共轭矩阵、伴随矩阵
    std::cout << m.transpose() << std::endl << std::endl;
    std::cout << m.conjugate() << std::endl << std::endl;
    std::cout << m.adjoint() << std::endl << std::endl;
    std::cout << m << std::endl << std::endl;
    m.transposeInPlace();
    std::cout << m << std::endl << std::endl;

    //8. 矩阵相乘、矩阵向量相乘
    std::cout << m*m << std::endl << std::endl;
    vec3d = Eigen::Vector3d(1, 2, 3);
    std::cout << m * vec3d << std::endl << std::endl;
    std::cout << vec3d.transpose()*m << std::endl << std::endl;

    //9. 矩阵的块操作
    std::cout << m << std::endl << std::endl;
    std::cout << m.block(1, 1, 2, 2) << std::endl << std::endl;
    std::cout << m.block<1, 2>(0, 0) << std::endl << std::endl;
    std::cout << m.col(1) << std::endl << std::endl;
    std::cout << m.row(0) << std::endl << std::endl;

    //10. 向量的块操作
    Eigen::ArrayXf arrayXf(10);
    arrayXf << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
    std::cout << vec3d << std::endl << std::endl;
    std::cout << arrayXf << std::endl << std::endl;
    std::cout << arrayXf.head(5) << std::endl << std::endl;
    std::cout << arrayXf.tail(4) * 2 << std::endl << std::endl;

    //11. 求解矩阵的特征值和特征向量
    Eigen::Matrix2f matrix2f;
    matrix2f << 1, 2, 3, 4;
    Eigen::SelfAdjointEigenSolver<Eigen::Matrix2f> eigenSolver(matrix2f);
    if (eigenSolver.info() == Eigen::Success) {
        std::cout << eigenSolver.eigenvalues() << std::endl << std::endl;
        std::cout << eigenSolver.eigenvectors() << std::endl << std::endl;
    }

    //12. 类Map及动态矩阵的使用
    int array1[4] = { 1, 2, 3, 4 };
    int array2[4] = { 5, 6, 7, 8 };
    int array3[4] = { 0, 0, 0, 0};
    matrix_mul_matrix(array1, 2, 2, array2, 2, 2, array3);
    for (int i = 0; i < 4; i++)
        std::cout << array3[i] << std::endl;

while (1)
{
    /* code */
}
    return 0;
}

运行简单的Eigen示例,虚拟机中计算矩阵求逆所需时间为3ms,工控机上应该快很多。

#include <iostream>
#include <stdio.h> /* fopen, fputs, fclose, stderr */
#include <stdlib.h> /* abort, NULL */
#include <math.h>
using std::expf;
#include <Eigen/Dense>
#include <Eigen/Core>
using Eigen::MatrixXd;
using Eigen::VectorXd;
using Eigen::Vector3d;
#include <ctime>
// 
#include <stdio.h>
#include <sys/neutrino.h>
#include <inttypes.h>
#include <sys/syspage.h>
#include <unistd.h>

#define MATRIX_SIZE 50

int main(int,char**)
{
    uint64_t start_cyc,end_cyc;
    uint64_t cps = SYSPAGE_ENTRY(qtime)->cycles_per_sec;
    // Eigen中所有的向量和矩阵都是Eigen::Matrix,
    // 它是一个模板类。它是一个模板类。
    // 它的前三个参数为数据类型,行,列
    Eigen::Matrix<float,2,3> matrix_23;

    // 同时,Eigen通过 typedef 提供了许多内置类型,不过底层仍是Eigen::Matrix
    // 例如:Vector3d 实质上是Eigen::Matrix<double,3,1> 即三维向量

    Eigen::Vector3d v_3d;

    Eigen::Matrix<float,3,1> vd_3d;

    //Matrix3d 实质上时Eigen::Matrix<double,3,3>
    Eigen::Matrix3d matrix_33=Eigen::Matrix3d::Zero(); //初始化为零

    //如果不确定矩阵大小,可以使用动态大小的矩阵
    Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> matrix_dynamic;

    //更简单的
    Eigen::MatrixXd matrix_x;

    //对Eigen阵的操作
    //输入数据(初始化)
    matrix_23<<1,2,3,4,2,5;
    //输出
    std::cout<<"matrix 2x3 :\n"<<matrix_23<<std::endl;

    //使用()访问矩阵中的元素
    std::cout<<"print maxtrix 2x3:"<<std::endl;
    for(int i=0;i<2;i++){
        for(int j=0;j<3;j++){
            std::cout<<matrix_23(i,j)<<"\t";
        }
        std::cout<<std::endl;
    }


    //矩阵和向量相乘(实际上仍是矩阵和矩阵)
    v_3d<<3,2,1;
    vd_3d<<3,5,3;

    //注:在Eigen中不能混合两种不同类型的矩阵,如下:
//    Eigen::Matrix<double,2,1> result_wrong_type=matrix_23*v_3d;
    //应该进行显式类型转换
    Eigen::Matrix<double,2,1>result=matrix_23.cast<double>()*v_3d;
    std::cout<<"[1 2 3,4 2 5]*[3 2 1]:"<<result.transpose()<<std::endl;

    Eigen::Matrix<float,2,1>result2=matrix_23*vd_3d;
    std::cout<<"[1 2 3,4 2 5]*[3 5 3]:"<<result2.transpose()<<std::endl;

    // 不能搞错矩阵维度,可尝试取消注释,看一下Eigen会报什么错
//    Eigen::Matrix<float,2,3>result3=matrix_23*vd_3d;

    //四则运算,直接用=-*/
    matrix_33=Eigen::Matrix3d::Random();
    std::cout<<"random matrix: \n"<<matrix_33<<std::endl;

    std::cout<<"transpose: \n"<<matrix_33.transpose()<<std::endl;
    std::cout<<"sum: "<<matrix_33.sum()<<std::endl;
    std::cout<<"trace: "<<matrix_33.trace()<<std::endl;
    std::cout<<"times 10: "<<10*matrix_33<<std::endl;
    std::cout<<"inverse: "<<"\n"<<matrix_33.inverse()<<std::endl;
    std::cout<<"det: "<<matrix_33.determinant()<<std::endl;

    //特征值
    Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigen_solver(matrix_33.transpose()*matrix_33);
    std::cout<<"Eigen value: \n"<<eigen_solver.eigenvalues()<<std::endl;
    std::cout<<"Eigen Vector: \n"<<eigen_solver.eigenvectors()<<std::endl;

    //解方程
    //求解 matrix_NN * x=v_ND 方程
    // N 的大小 在前面的宏已定义,它由随机数产生
    //直接求逆自然是最直接的,但是运算量大
    Eigen::Matrix<double,MATRIX_SIZE,MATRIX_SIZE> matrix_NN=
            Eigen::MatrixXd::Random(MATRIX_SIZE,MATRIX_SIZE);
    matrix_NN=matrix_NN*matrix_NN.transpose();  //保证半正定
    Eigen::Matrix<double,MATRIX_SIZE,1> v_Nd=Eigen::MatrixXd::Random(MATRIX_SIZE,1);

    // clock_t time_stt = clock(); //计时
    start_cyc = ClockCycles();
    //直接求逆
    Eigen::Matrix<double,MATRIX_SIZE,1>x=matrix_NN.inverse()*v_Nd;
    end_cyc = ClockCycles();
    double tbs = (double) (end_cyc - start_cyc) / cps;
    std::cout<<"time of normal inverse is:"<<tbs<<"s"<<std::endl;
    std::cout<<"x= "<<x.transpose()<<std::endl;

    //通常使用矩阵分解来求解,例如:QR 分解,速度会快很多
    // time_stt=clock();
    start_cyc = ClockCycles();
    x = matrix_NN.colPivHouseholderQr().solve(v_Nd);
    end_cyc = ClockCycles();
    tbs = (double) (end_cyc - start_cyc) / cps;
    std::cout<<"time of Qr decomposition is : "<<tbs <<"ms"<<std::endl;
    std::cout<<"x= "<<x.transpose()<<std::endl;

    //对于正定矩阵,还可以用cholesky分解求解方程
    // time_stt=clock();
    start_cyc = ClockCycles();
    x=matrix_NN.ldlt().solve(v_Nd);
    end_cyc = ClockCycles();
    tbs = (double) (end_cyc - start_cyc) / cps;
    std::cout<<"time of ldlt decomposition is :"<<tbs <<"s"<<std::endl;
    std::cout<<"x= "<<x.transpose()<<std::endl;
    sleep(3);
    return 0;
}

在IDE下编译仍存在报错。

make[2]: Entering directory `C:/Users/ronaldo/Desktop/QNET/test_eigen/x86/o-g'
C:/QNX641/host/win32/x86/usr/bin/qcc -Vgcc_ntox86 -c -Wc,-Wall -Wc,-Wno-parentheses               -I. -IC:/Users/ronaldo/Desktop/QNET/test_eigen/x86/o -IC:/Users/ronaldo/Desktop/QNET/test_eigen/x86/o-g -IC:/Users/ronaldo/Desktop/QNET/test_eigen/x86 -IC:/Users/ronaldo/Desktop/QNET/test_eigen -IC:/QNX641/target/qnx6/usr/include    -g    -DVARIANT_g -DBUILDENV_qss  C:/Users/ronaldo/Desktop/QNET/test_eigen/test_eigen.cc 
C:/QNX641/host/win32/x86/usr/bin/rm -f  C:/Users/ronaldo/Desktop/QNET/test_eigen/x86/o-g/test_eigen_g
C:/QNX641/host/win32/x86/usr/bin/qcc -Vgcc_ntox86  -lang-c++ -lang-c++    -oC:/Users/ronaldo/Desktop/QNET/test_eigen/x86/o-g/test_eigen_g    test_eigen.o   -L . -L C:/QNX641/target/qnx6/x86/lib -L C:/QNX641/target/qnx6/x86/usr/lib  -Wl,--rpath-link . -Wl,--rpath-link C:/QNX641/target/qnx6/x86/lib -Wl,--rpath-link C:/QNX641/target/qnx6/x86/usr/lib    -l-lm   -g     
C:\QNX641\host\win32\x86\usr\bin\ntox86-ld: cannot find -l-lm
cc: C:/QNX641/host/win32/x86/usr/bin/ntox86-ld caught signal 1
make[2]: *** [C:/Users/ronaldo/Desktop/QNET/test_eigen/x86/o-g/test_eigen_g] Error 1
make[2]: Target `all' not remade because of errors.
make[2]: Leaving directory `C:/Users/ronaldo/Desktop/QNET/test_eigen/x86/o-g'
make[1]: [all] Error 2 (ignored)
make[1]: Leaving directory `C:/Users/ronaldo/Desktop/QNET/test_eigen/x86'

报错:cannot find -l-lm,需要在IDE中加上编译条件”-lm“,如下所示。

在图中的”socket“改成”m“,即可实现在IDE编译。