[Gmp-commit] /var/hg/gmp-proj/mini-gmp: Implemented mpz_import and mpz_export...

mercurial at gmplib.org mercurial at gmplib.org
Sun Jan 15 13:22:53 CET 2012


details:   /var/hg/gmp-proj/mini-gmp/rev/202e6902f894
changeset: 84:202e6902f894
user:      Niels M?ller <nisse at lysator.liu.se>
date:      Sun Jan 15 13:22:48 2012 +0100
description:
Implemented mpz_import and mpz_export. Not tested.

diffstat:

 mini-gmp.c |  156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 mini-gmp.h |    3 +
 2 files changed, 157 insertions(+), 2 deletions(-)

diffs (183 lines):

diff -r 30830a74313f -r 202e6902f894 mini-gmp.c
--- a/mini-gmp.c	Sat Jan 14 14:26:13 2012 +0100
+++ b/mini-gmp.c	Sun Jan 15 13:22:48 2012 +0100
@@ -36,8 +36,6 @@
 
      mpz_divisible_p
      mpz_divisible_ui_p
-     mpz_export
-     mpz_import.
 */
 
 #include <assert.h>
@@ -3838,3 +3836,157 @@
   free (str);
   return len;
 }
+
+
+static int
+gmp_detect_endian (void)
+{
+  static const int i = 1;
+  const unsigned char *p = (const unsigned char *) &i;
+  if (*p == 1)
+    /* Little endian */
+    return -1;
+  else
+    /* Big endian */
+    return 1;
+}
+
+/* Import and export. Does not support nails. */
+void
+mpz_import (mpz_t r, size_t count, int order, size_t size, int endian,
+	    size_t nails, const void *src)
+{
+  const unsigned char *p;
+  ptrdiff_t word_step;
+  mp_ptr rp;
+  mp_size_t rn;
+
+  /* The current (partial) limb. */
+  mp_limb_t limb;
+  /* The number of bytes already copied to this limb (starting from
+     the low end). */
+  size_t bytes;
+  /* The index where the limb should be stored, when completed. */
+  mp_size_t i;
+
+  if (nails != 0)
+    gmp_die ("mpz_import: nails not supported.\n");
+
+  assert (order == 1 || order == -1);
+  assert (endian >= -1 && endian <= 1);
+
+  if (endian == 0)
+    endian = gmp_detect_endian ();
+
+  p = (unsigned char *) src;
+
+  /* Process bytes from the least significant end, so point p at the
+     least significant word. */
+  if (order == 1)
+    {
+      p += size * (count - 1);
+      word_step = -(ptrdiff_t) size;
+    }
+  else
+    word_step = size;
+
+  /* And at east significant byte of that word. */
+  if (endian == 1)
+    p += (size - 1);
+
+  rn = (size * count + sizeof(mp_limb_t) - 1) / sizeof(mp_limb_t);
+  rp = MPZ_REALLOC (r, rn);
+
+  for (limb = 0, bytes = 0, i = 0; count > 0; count--, p += word_step)
+    {
+      size_t j;
+      for (j = 0; j < size; j++, p -= (ptrdiff_t) endian)
+	{
+	  limb |= *p << (bytes++ * CHAR_BIT);
+	  if (bytes == sizeof(mp_limb_t))
+	    {
+	      rp[i++] = limb;
+	      bytes = 0;
+	    }
+	}
+    }
+  if (bytes > 0)
+    rp[i++] = limb;
+  assert (i == rn);
+
+  r->_mp_size = rn;
+}
+
+void *
+mpz_export (void *r, size_t *countp, int order, size_t size, int endian,
+	    size_t nails, const mpz_t u)
+{
+  unsigned char *p;
+  ptrdiff_t word_step;
+  size_t count, k;
+  mp_size_t un;
+
+  /* The current (partial) limb. */
+  mp_limb_t limb;
+  /* The number of bytes left to to in this limb. */
+  size_t bytes;
+  /* The index where the limb was read. */
+  mp_size_t i;
+
+  if (nails != 0)
+    gmp_die ("mpz_import: nails not supported.\n");
+
+  assert (order == 1 || order == -1);
+  assert (endian >= -1 && endian <= 1);
+
+  un = GMP_ABS (u->_mp_size);
+  if (!un)
+    return r;
+
+  count = (un * sizeof (mp_limb_t) + size - 1) / size;
+  if (!r)
+    r = gmp_xalloc (count * size);
+
+  if (endian == 0)
+    endian = gmp_detect_endian ();
+
+  p = (unsigned char *) r;
+
+  /* Process bytes from the least significant end, so point p at the
+     least significant word. */
+  if (order == 1)
+    {
+      p += size * (count - 1);
+      word_step = -(ptrdiff_t) size;
+    }
+  else
+    word_step = size;
+
+  /* And at east significant byte of that word. */
+  if (endian == 1)
+    p += (size - 1);
+
+  for (limb = 0, bytes = 0, i = 0, k = 0; i < un; k++, p += word_step)
+    {
+      size_t j;
+      for (j = 0; j < size; j++, p -= (ptrdiff_t) endian)
+	{
+	  if (bytes == 0)
+	    {
+	      if (i < un)
+		limb = u->_mp_d[i++];
+	      bytes = sizeof (mp_limb_t);
+	    }
+	  *p = limb;
+	  limb >>= CHAR_BIT;
+	  bytes--;
+	}
+    }
+  assert (i == un);
+  assert (k == count);
+
+  if (countp)
+    *countp = count;
+
+  return r;
+}
diff -r 30830a74313f -r 202e6902f894 mini-gmp.h
--- a/mini-gmp.h	Sat Jan 14 14:26:13 2012 +0100
+++ b/mini-gmp.h	Sun Jan 15 13:22:48 2012 +0100
@@ -217,6 +217,9 @@
 size_t mpz_out_str (FILE *, int, const mpz_t);
 #endif
 
+void mpz_import (mpz_t, size_t, int, size_t, int, size_t, const void *);
+void *mpz_export (void *, size_t *, int, size_t, int, size_t, const mpz_t);
+
 #if defined (__cplusplus)
 }
 #endif


More information about the gmp-commit mailing list