[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