[racket] math/matrix <--> FFI/array

From: Neil Toronto (neil.toronto at gmail.com)
Date: Tue Jan 22 15:02:31 EST 2013

On 01/22/2013 12:33 PM, Tobias Hammer wrote:
> When you pass it directly to c-code, maybe you can completely bypass the
> array and convert
> matrix -> flarray -> flvector -> cpointer
> the last 3 conversions should be blazing fast but i guess that won't
> matter much for 16 elements.
> Neil, can you nevertheless tell me more about the expected performance
> of the first one?

That'll work when the foreign function expects a "double*" argument that 
points at the matrix elements in row-major order. It's about as fast as 
you can do it, so well-spotted.

Going from matrix to flarray quickly maps `real->double-flonum' (equiv. 
`fl' from `math/flonum') over the matrix entries. The flonums themselves 
should remain unboxed. Going from flarray to flvector is just a struct 
access. I think going from flvector to cpointer is just a struct access 
at the C level.

Neil ⊥

> Here is a sample code (it was surprisingly easy to integrate ffi into TR)
>
> Tobias
>
>
> ;; --------------------------
>
> #lang typed/racket/base
>
> (require math)
> (require/typed ffi/unsafe
>                 [#:opaque CPointer cpointer?]
>                 [flvector->cpointer (FlVector -> CPointer)]
>                 [#:opaque CType ctype?]
>                 [_double CType]
>                 [ptr-ref (CPointer CType Exact-Nonnegative-Integer ->
> Any)])
>
> (define dim 4)
> (define m (build-matrix dim dim
>                          (lambda: ([i : Integer]
>                                    [j : Integer])
>                            (->fl (+ (* i dim) j)))))
>
> (define flv (flarray-data (array->flarray m)))
> (define cp (flvector->cpointer flv))
>
> (for/list: : (Listof Any) ([i (flvector-length flv)])
>    (ptr-ref cp _double i))
>
>
>
>
>
> On Mon, 21 Jan 2013 20:42:51 +0100, Neil Toronto
> <neil.toronto at gmail.com> wrote:
>
>> On 01/21/2013 02:48 AM, Pierpaolo Bernardi wrote:
>>> Hello,
>>>
>>> what's the most convenient way to convert between math/matrices and
>>> FFI/arrays?
>>>
>>> To reduce the scope of the question, at the moment I'm only interested
>>> in conversions from and to the following FFI types:
>>>
>>>   (_array _double 3 3)
>>>   (_array _double 3)
>>>   (_array _double 2 3)
>>
>>  From the FFI docs, it looks like you need to construct either:
>>
>>   1. A vector of vectors for foreign functions that accept an
>>      (_array/vector type m n).
>>
>>   2. A flat vector with elements in row-major order for foreign functions
>>      that accept an (_array type m n) or (_array type m).
>>
>> For #1, use `matrix->vector*', and for #2, use `matrix->vector'. I
>> don't know whether you can pass the vectors returned from these
>> functions directly to foreign functions. I wouldn't be surprised.
>>
>> If you're working in Typed Racket and you need this to be fast, do the
>> conversions to and from vectors in Typed Racket. Currently, passing
>> matrices across the contract boundary makes element access very slow. :/
>>
>> Neil ⊥
>>
>> ____________________
>>   Racket Users list:
>>   http://lists.racket-lang.org/users


Posted on the users mailing list.