Проблем с рамката Accelerate в Swift

Използвам алгоритъма dgeev от LAPACK в рамката Accelerate за изчисляване на собствени стойности и собствени вектори на матрица. Ето моят код:

    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)")

Все пак отпечатва нули.


person Youssef Moawad    schedule 11.01.2015    source източник


Отговори (1)


Проблемът е във вашата променлива 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)")
person Airspeed Velocity    schedule 11.01.2015
comment
Е, каква трябва да бъде стойността на lwork при второто повикване? - person Youssef Moawad; 11.01.2015
comment
@YoussefSami: Мисля, че трябва да е действителният размер на работното пространство: lwork = __CLPK_integer(workspace.count). Намерих този пример на C код, който също демонстрира употребата: software.intel.com/sites/products/documentation/doclib/mkl_sa/ - person Martin R; 11.01.2015
comment
Да, това е грешка в моя примерен код, трябва да го настроя също, както и да оразмеря работното пространство. Ще редактирам. - person Airspeed Velocity; 11.01.2015
comment
Много благодаря и на двама ви! - person Youssef Moawad; 11.01.2015
comment
Малка забележка: За заявката за работно пространство нямате нужда от масив, var workspaceQuery : Double = 0.0 би бил достатъчен. - person Martin R; 11.01.2015
comment
Добра гледна точка, имах го така, защото първоначално използвах повторно workspace, след което се замислих, но не взех докрай това разсъждение... - person Airspeed Velocity; 11.01.2015