guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: mpz_import


From: Andreas Vögele
Subject: Re: mpz_import
Date: Sun, 29 Aug 2004 17:33:45 +0200

Marius Vollmer writes:

Andreas Vögele <address@hidden> writes:

Marius Vollmer writes:

[...]  I was thinking whether we should export something like
mpz_import and mpz_export for our integers in general.  Such an
operation is obviously needed sometimes.

I think that's a good idea.  I could, for example, use such wrappers
to convert message digests into bigints. Currently, I use scm_ash and
scm_sum in a loop to convert MD5 hashes into numbers.

Yes, that sounds the prototypical application.  Maybe you have a
concrete suggestion of how Guile should offer these functions (i.e.,
documented function prototypes)?  That would be great.

I'd include <gmp.h> in libguile/numbers.h and provide two C functions:

void scm_to_mpz_t (SCM val, mpz_t result);
SCM scm_from_mpz_t (mpz_t val);

Here's an example that converts a digest buffer into a Scheme number:

  mpz_t z;
  mpz_init (z);
  mpz_import (z, digestlen, 1, 1, 0, 0, digest);
  SCM n = scm_from_mpz_t (z);
  mpz_clear (z);
  ...

Another example that converts a Scheme number into an mpz_t number:

  mpz_t z;
  mpz_init (z);
  SCM n = scm_from_int (0);
  scm_to_mpz_t (n, z);
  ...
  mpz_add_ui (z, z, 100);
  ...
  SCM res = scm_from_mpz_t (z);
  mpz_clear (z);
  return res;

Another option would be to initialize a new mpz_t variable in scm_to_mpz_t() and to return that value. But I don't like this approach very much since the initialisation happens in the library whereas the memory must be freed by the user:

mpz_t z = scm_to_mpz_t (n);
mpz_clear (z);

The first approach also allows users to reuse variables of type mpz_t. This might be useful in loops, for example:

mpz_t z;
mpz_init (z);
for (walk = list; SCM_CONSP (walk); walk = SCM_CDR (walk)) {
  elt = SCM_CAR (walk);
  scm_to_mpz_t (elt, z);
  ...
}
mpz_clear (z);

I'm not sure about the order of arguments in scm_to_mpz_t(). All the assignment functions provided by GNU MP expect the result parameter as the first argument, e.g. mpz_set_ui (result, 100) and mp_add_ui (result, op, 100). So maybe the arguments ought to be reversed in the following documentation and code.

Documentation for api-data.texi:

@deftypefn {C Function} void scm_to_mpz_t (SCM val, mpz_t rop)
Assign @var{val} to the multiple precision integer @var{rop}.
@var{val} must be an exact integer, otherwise a `wrong-type-arg' error
will be signalled.  @var{rop} must have been initialized with
@code{mpz_init} before this function is called.  When @var{rop} is
no longer needed the occupied space must be freed with @code{mpz_clear}.
@xref{Initializing Integers,,, gmp, GNU MP Manual}, for details.
@end deftypefn

@deftypefn {C Function} SCM scm_from_mpz_t (mpz_t val)
Return the @code{SCM} value that represents @var{val}.
@end deftypefn

Implementation:

void
scm_to_mpz_t (SCM val, mpz_t rop)
{
  if (SCM_I_INUMP (val))
    mpz_set_si (rop, SCM_I_INUM (val));
  else if (SCM_BIGP (val))
    mpz_set (rop, SCM_I_BIG_MPZ (val));
  else
    scm_wrong_type_arg (NULL, 0, val);
}

SCM
scm_from_mpz_t (mpz_t val)
{
  SCM z = scm_double_cell (scm_tc16_big, 0, 0, 0);
  mpz_init_set (SCM_I_BIG_MPZ (z), val);
  return scm_i_normbig (z);
}





reply via email to

[Prev in Thread] Current Thread [Next in Thread]