[racket] math/matrix <--> FFI/array
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