How to read back c-values of int array to Kotlin


#1

I am trying to perform an LU-factorization in Kotlin/Native by using a LAPACK c-function. However, I don’t know how to read back the values to Kotlin that is modified by the c-function. dgetrf_ modifies the data that pivots points to. How do I get an IntArray in Kotlin with the values referenced by pivots?

fun luPivots(matrix : DoubleArray) : IntArray {
    val dim = sqrt(matrix.size.toDouble()).toInt()

    var cDim: CValuesRef<__CLPK_integerVar> = cValuesOf(dim)
    var inMatrix: CValuesRef<__CLPK_doublerealVar> = matrix.toCValues()
    var pivots: CValuesRef<__CLPK_integerVar> = Array(matrix.size) { 0 }.toIntArray().toCValues()
    var info: CValuesRef<__CLPK_integerVar> = cValuesOf(0)

    // Taken from iOS platform.Accelerate
    dgetrf_(cDim, cDim, inMatrix, cDim, pivots, info)

    return ???
}

#2

It seems that toCValues() and cValuesOf() creates a temporary copy of the data in memory (There is a hint here). Hence, if the data should be modified and read back it is necessary to manually allocate the memory, perform the operation, read it back and then free the memory. The function above was part of the inverse function I am writing. Can anyone confirm that the way I write below is best practice or are there improvements?

fun inverse(matrix : DoubleArray) : DoubleArray {
    val dim = sqrt(matrix.size.toDouble()).toInt()

    val inMatrixPtr = nativeHeap.allocArray<__CLPK_doublerealVar>(matrix.size)
    matrix.forEachIndexed { i, v -> inMatrixPtr[i] = v}

    val pivotsPtr = nativeHeap.allocArray<__CLPK_integerVar>(dim)

    dgetrf_(cValuesOf(dim), cValuesOf(dim), inMatrixPtr, cValuesOf(dim), pivotsPtr, cValuesOf(0))

    val workLength = dim * dim
    val workspacePtr = nativeHeap.allocArray<__CLPK_doublerealVar>(workLength)

    dgetri_(cValuesOf(dim), inMatrixPtr, cValuesOf(dim), pivotsPtr, workspacePtr, cValuesOf(workLength), cValuesOf(0))

    nativeHeap.free(pivotsPtr)
    nativeHeap.free(workspacePtr)

    val outMatrix: DoubleArray =
    memScoped {
        val ptr: CPointer<DoubleVarOf<__CLPK_doublereal>> = inMatrixPtr.getPointer(memScope)
        (0 until matrix.size).map { ptr[it] }.toDoubleArray()
    }

    nativeHeap.free(inMatrixPtr)

    return outMatrix
}