This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

gh_scm2doubles and friends


Hi,

Sorry this is a bit long.  I'm proposing a change to the gh_ interface
to vectors.  If this bores you to tears, please skip this message.

I'm running a bit behind the times, but I've finally taken a look at
the new gh_ interface to uniform arrays.  Using the current gh_
interface, a gh_scm2doubles/gh_doubles2scm will create a second copy
of the vector.  With vectors (particularly large vectors) it's often
desirable to have only one copy of the vector under scheme.  I think
that an interface that implements copy in/copy out would be quite
useful.

Here's my suggestion:

----------------------------------------
#define GH_COPY          (0x01000000)
double *gh_scm2doubles(SCM vect, double *result, int flag);
#define GH_KEEP          (0x00000000)
#define GH_RELEASE       (0x01000000)
#define GH_MAKE_VECTOR   (0x02000000)
#define GH_VALUE_SIZE(v) (0x00ffffff & (v)) 
SCM gh_doubles2scm(SCM vect, double *result, int flag);
----------------------------------------

@defun gh_scm2doubles vector result flag
Take an @var{vector} of type SCM and convert it into an array of
doubles.  If @var{result} is @code{NULL}, provide memory for a new
one.  The @var{flag} controls the internal actions.  If @var{flag} is
positive then it gives the maximum number of values that can be
saved @var{result}.  If @var{flag} is @var{GH_COPY} then it is assumed
that @var{result} is NULL or points to memory that was allocated by a
previous call to @code{gh_scm2doubles} with a vector with the same
length as @var{vector}. 

This returns a pointer to the array of doubles containing the result.
@end defun

@defun gh_doubles2scm vector values flag
Take the array of doubles @var{values} and convert the result to an
SCM variable.  If @var{vector} is a uniform array or vector, then
copy the values into the existing vector; otherwise, create a new
uniform array or vector.  The @var{flag} is the bitwise or of the
values: 

@table @code

@item GH_RELEASE
The memory pointed to by @var{values} may be freed.

@item GH_KEEP
Do not free the memory pointed to by @var{values}.  

@item GH_MAKE_VECTOR
Create a vector instead of a uniform array.  This only affects the
result when @var{vector} is not a uniform array or vector.

@item A positive integer
The length of @var{values} array.  If a non-zero value is used and
@var{vector} is a vector or uniform array, then the value must match
the length of @var{vector}.  
@end table
@end defun

These routines can be used to implement copyin/copyout semantics in a
user routine.

SCM example(SCM myvect) {
    double newvect;
    double *mem = NULL;    
    mem = gh_scm2doubles(myvect,mem,GH_COPY);
    some_function(mem,gh_length(myvect));
    newvect = gh_doubles2scm(myvect,mem,GH_RELEASE);
    return newvect;
}

In this example, newvect and myvect will be equal and mem will be
allocated and then freed.

SCM example(SCM myvect) {
    double newvect;
    double *mem = NULL;    
    mem = gh_scm2doubles(myvect,mem,GH_COPY);
    some_function(mem,gh_length(myvect));
    newvect = gh_doubles2scm(SCM_EOL,mem,GH_RELEASE);
    return newvect;
}

In this example, newvect will not be equal to myvect.

Because of the way uniform arrays are implemented in GUILE it's also
possible to use the uniform array memory directly.  This removes the
need to copy the values in and out of the array.  To allow this, a new
gh_scm2doubles flag GH_AVOID_COPY can be defined, then if the scm
value is a scm_tc7_dvect (sorry for the reference to internals) the
address can be returned directly.  The gh_doubles2scm routine would
need to be modified to check that the location of the values is
different from SCM_CHARS(vector) before calling free.

I believe that this captures all of the functionality of the current
gh_scm2doubles, gh_doubles2scm, and gh_doubles2dvect interface.  It
also adds the ability to do copy in/copy out.  If the GH_AVOID_COPY
flag seems reasonable, it also allows the dvect memory to be directly
accessed in cases where that's possible and transparently falls back
to copy when it's not.

If this seems like a good change to the gh_ vector interface then I'd
be happy to write up an example implementation.  I may write it just
for my own edification.

Cheers,

Clark