29 September 2005

Srfi-4 Vectors in Bigloo

I just thought I'd drop a quick note about srfi-4-like vectors in Bigloo. For those who don't know, srfi-4 specifies an interface for homogeneous numeric vector types. For those of us who do numerical computing, this is a big win---boxing a double, for example, every time you reference or store into a vector is just impossibly inefficient if you want to get anything numerical done. But, Bigloo doesn't have an implementation of srfi-4---so how is it that I'm such an enthusiastic user?

Here's how: Bigloo allows for the definition of typed vectors. Typed vectors are vectors that only hold one of the native Bigloo types. (Unfortunately, this cannot be done for user-created types like classes.) For example, the module clause

(module f64vector
   (type (tvector f64vector (double)))
   (eval (export-all)))
Creates homogeneous vectors of doubles labeled by the type ::f64vector and functions to access these vectors. Nearly the entire srfi-4 interface is created; the only warts are
  1. The make-f64vector procedure requires two arguments; the initializing value is not optional.
  2. The f64vector procedure is not created.
Note that the created ref and set! procedures are typed correctly, which helps immensely in the type analysis of the remainder of your program (I hardly ever end up putting in typing information except at procedure arguments).

In fact, the Bigloo source distribution contains an example of using tvectors, but it's not a widely known fact, so I thought I would mention it here for posterity's sake.

By the way, supposedly the type system in Bigloo can identify when vectors are used homogeneously, and automatically convert them to tvectors. That's nice in theory, but in practice it only works on vectors that are used in only a few procedures within the same module, and even then it has trouble if you use the vectors in some strange way or forget to explicitly initialize them in the creation statement. For things like numerical computing, where the f64vectors can get passed around through the entire program it's hopeless---just use a tvector.


TheHoffAgain said...

Hmmm, that's pretty cool. One thing, though, is that a tvector doesn't seem to coerce to its C type. I can pass a tvector of floats to a foreign function that wants a float*, for instance. Or can I? Am I missing something?

Will Farr said...

Unfortunately, no. You can't pass the tvector directly to a C function. However, you can if you are willing to have a crack at the internal representation of a tvector structure. You can do this using either the -cgen option to Bigloo (stops compilation after the C output phase) or the -rm option (leaves the C code around after the object file is produced). A tvector is a struct with a header, a length field, a descriptor, and then the elements; it should be easy to extract a pointer to the first element using a pragma form.