解决Swift中的Accelerate框架问题

时间:2015-01-11 12:47:11

标签: swift matrix lapack eigenvector accelerate-framework

我在Accelerate框架中使用LAPACK中的dgeev算法来计算矩阵的特征值和特征向量。这是我的代码:

    var matrix:[__CLPK_doublereal] = [1,2,3,4,5,6,7,8,9]

    var N = __CLPK_integer(sqrt(Double(matrix.count)))
    var pivots = [__CLPK_integer](count: Int(N), repeatedValue: 0)
    var workspace = [Double](count: Int(N), repeatedValue: 0.0)
    var error : __CLPK_integer = 0
    var lwork = __CLPK_integer(-1)
    // Real parts of eigenvalues
    var wr = [Double](count: Int(N), repeatedValue: 0)
    // Imaginary parts of eigenvalues
    var wi = [Double](count: Int(N), repeatedValue: 0)
    // Left eigenvectors
    var vl = [__CLPK_doublereal](count: Int(N*N), repeatedValue: 0)
    // Right eigenvectors
    var vr = [__CLPK_doublereal](count: Int(N*N), repeatedValue: 0)

    dgeev_(UnsafeMutablePointer(("V" as NSString).UTF8String), UnsafeMutablePointer(("V" as NSString).UTF8String), &N, &matrix, &N, &wr, &wi, &vl, &N, &vr, &N, &workspace, &lwork, &error)

    println("\(wr), \(vl), \(vr)")

这仅打印包含零的数组,这意味着它们不被该函数修改。我做错了什么?

更新1

我现在有了这个:

    var matrix:[__CLPK_doublereal] = [1,2,3,4,5,6,7,8,9]

    var N = __CLPK_integer(sqrt(Double(matrix.count)))
    var pivots = [__CLPK_integer](count: Int(N), repeatedValue: 0)
    var workspaceQuery = [Double](count: 1, repeatedValue: 0.0)
    var error : __CLPK_integer = 0
    var lwork = __CLPK_integer(-1)
    // Real parts of eigenvalues
    var wr = [Double](count: Int(N), repeatedValue: 0)
    // Imaginary parts of eigenvalues
    var wi = [Double](count: Int(N), repeatedValue: 0)
    // Left eigenvectors
    var vl = [__CLPK_doublereal](count: Int(N*N), repeatedValue: 0)
    // Right eigenvectors
    var vr = [__CLPK_doublereal](count: Int(N*N), repeatedValue: 0)

    dgeev_(UnsafeMutablePointer(("V" as NSString).UTF8String), UnsafeMutablePointer(("V" as NSString).UTF8String), &N, &matrix, &N, &wr, &wi, &vl, &N, &vr, &N, &workspaceQuery, &lwork, &error)
    var workspace = [Double](count: Int(workspaceQuery[0]), repeatedValue: 0.0)

    dgeev_(UnsafeMutablePointer(("V" as NSString).UTF8String), UnsafeMutablePointer(("V" as NSString).UTF8String), &N, &matrix, &N, &wr, &wi, &vl, &N, &vr, &N, &workspace, &lwork, &error)

    println("\(wr), \(vl), \(vr)")

仍然打印零。

1 个答案:

答案 0 :(得分:3)

问题与您的lwork变量有关。这应该是您提供的工作空间的大小,-1表示您正在执行“工作区查询”:

 LWORK   (input) INTEGER   
        The dimension of the array WORK.  LWORK >= max(1,3*N), and   
        if JOBVL = 'V' or JOBVR = 'V', LWORK >= 4*N.  For good   
        performance, LWORK must generally be larger.   

        If LWORK = -1, then a workspace query is assumed; the routine   
        only calculates the optimal size of the WORK array, returns   
        this value as the first entry of the WORK array, and no error   
        message related to LWORK is issued by XERBLA.

所以你可能想要这样的东西:

var workspaceQuery: Double = 0.0
dgeev_(UnsafeMutablePointer(("V" as NSString).UTF8String), UnsafeMutablePointer(("V" as NSString).UTF8String), &N, &matrix, &N, &wr, &wi, &vl, &N, &vr, &N, &workspaceQuery, &lwork, &error)

// prints "102.0"
println("\(workspaceQuery)")

// size workspace per the results of the query:
var workspace = [Double](count: Int(workspaceQuery), repeatedValue: 0.0)
lwork = __CLPK_integer(workspaceQuery)

dgeev_(UnsafeMutablePointer(("V" as NSString).UTF8String), UnsafeMutablePointer(("V" as NSString).UTF8String), &N, &matrix, &N, &wr, &wi, &vl, &N, &vr, &N, &workspace, &lwork, &error)

// this now prints non-zero values
println("\(wr), \(vl), \(vr)")