diff options
author | Kevin Ryde <user42@zip.com.au> | 2002-05-07 00:19:45 +0200 |
---|---|---|
committer | Kevin Ryde <user42@zip.com.au> | 2002-05-07 00:19:45 +0200 |
commit | edfd47b603a62ba43273060426ffaf44b8b8e858 (patch) | |
tree | 996ea422fb64ef0eaa9d3f5df7db51f159b54308 | |
parent | c6a240f01b25b9b4061c6e58c7c5c225f55f3480 (diff) | |
download | gmp-edfd47b603a62ba43273060426ffaf44b8b8e858.tar.gz |
* mpz/import.c, mpz/export.c: New files.
-rw-r--r-- | mpz/export.c | 191 | ||||
-rw-r--r-- | mpz/import.c | 164 |
2 files changed, 355 insertions, 0 deletions
diff --git a/mpz/export.c b/mpz/export.c new file mode 100644 index 000000000..1b736c77e --- /dev/null +++ b/mpz/export.c @@ -0,0 +1,191 @@ +/* mpz_export -- create word data from mpz. + +Copyright 2002 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include <stdio.h> /* for NULL */ +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + + +#if HAVE_LIMB_BIG_ENDIAN +#define HOST_ENDIAN 1 +#endif +#if HAVE_LIMB_LITTLE_ENDIAN +#define HOST_ENDIAN (-1) +#endif +#ifndef HOST_ENDIAN +static const mp_limb_t endian_test = (CNST_LIMB(1) << (GMP_LIMB_BITS-7)) - 1; +#define HOST_ENDIAN (* (signed char *) &endian_test) +#endif + + +#define MPN_SIZEINBASE_2EXP(result, ptr, size, base2exp) \ + do { \ + int __cnt; \ + unsigned long __totbits; \ + ASSERT ((size) > 0); \ + ASSERT ((ptr)[(size)-1] != 0); \ + count_leading_zeros (__cnt, (ptr)[(size)-1]); \ + __totbits = (size) * GMP_NUMB_BITS - (__cnt - GMP_NAIL_BITS); \ + (result) = (__totbits + (base2exp)-1) / (base2exp); \ + } while (0) + + +void * +mpz_export (void *data, size_t *countp, int order, + size_t size, int endian, size_t nail, mpz_srcptr z) +{ + mp_size_t zsize; + mp_srcptr zp; + size_t count; + unsigned long numb; + unsigned align; + + ASSERT (order == 1 || order == -1); + ASSERT (endian == 1 || endian == 0 || endian == -1); + ASSERT (nail <= 8*size); + ASSERT (8*size-nail > 0); + + zsize = SIZ(z); + if (zsize == 0) + { + *countp = 0; + return data; + } + + zsize = ABS (zsize); + zp = PTR(z); + numb = 8*size - nail; + MPN_SIZEINBASE_2EXP (count, zp, zsize, numb); + *countp = count; + + if (data == NULL) + data = (*__gmp_allocate_func) (count*size); + + if (endian == 0) + endian = HOST_ENDIAN; + + align = (unsigned) data % sizeof (mp_limb_t); + + if (nail == GMP_NAIL_BITS) + { + if (size == sizeof (mp_limb_t) && align == 0) + { + if (order == -1 && endian == HOST_ENDIAN) + { + MPN_COPY ((mp_ptr) data, zp, (mp_size_t) count); + return data; + } + if (order == 1 && endian == HOST_ENDIAN) + { + MPN_REVERSE ((mp_ptr) data, zp, (mp_size_t) count); + return data; + } + + if (order == -1 && endian == -HOST_ENDIAN) + { + MPN_BSWAP ((mp_ptr) data, zp, (mp_size_t) count); + return data; + } + if (order == 1 && endian == -HOST_ENDIAN) + { + MPN_BSWAP_REVERSE ((mp_ptr) data, zp, (mp_size_t) count); + return data; + } + } + } + + { + mp_limb_t limb, wbitsmask; + size_t i, numb; + mp_size_t j, wbytes, woffset; + unsigned char *dp; + int lbits, wbits; + mp_srcptr zend; + + numb = size * 8 - nail; + + /* whole bytes per word */ + wbytes = numb / 8; + + /* possible partial byte */ + wbits = numb % 8; + wbitsmask = (CNST_LIMB(1) << wbits) - 1; + + /* offset to get to the next word */ + woffset = (endian >= 0 ? size : - (mp_size_t) size) + + (order < 0 ? size : - (mp_size_t) size); + + /* least significant byte */ + dp = (unsigned char *) data + + (order >= 0 ? (count-1)*size : 0) + (endian >= 0 ? size-1 : 0); + +#define EXTRACT(N, MASK) \ + do { \ + if (lbits >= (N)) \ + { \ + *dp = limb MASK; \ + limb >>= (N); \ + lbits -= (N); \ + } \ + else \ + { \ + mp_limb_t newlimb; \ + newlimb = (zp == zend ? 0 : *zp++); \ + *dp = (limb | (newlimb << lbits)) MASK; \ + limb = newlimb >> ((N)-lbits); \ + lbits += GMP_NUMB_BITS - (N); \ + } \ + } while (0) + + zend = zp + zsize; + lbits = 0; + limb = 0; + for (i = 0; i < count; i++) + { + for (j = 0; j < wbytes; j++) + { + EXTRACT (8, + 0); + dp -= endian; + } + if (wbits != 0) + { + EXTRACT (wbits, & wbitsmask); + dp -= endian; + j++; + } + for ( ; j < size; j++) + { + *dp = '\0'; + dp -= endian; + } + dp += woffset; + } + + ASSERT (zp == PTR(z) + ABSIZ(z)); + + /* low byte of word after most significant */ + ASSERT (dp == (unsigned char *) data + + (order < 0 ? count*size : - (mp_size_t) size) + + (endian >= 0 ? (mp_size_t) size - 1 : 0)); + } + return data; +} diff --git a/mpz/import.c b/mpz/import.c new file mode 100644 index 000000000..e06afaab5 --- /dev/null +++ b/mpz/import.c @@ -0,0 +1,164 @@ +/* mpz_import -- set mpz from word data. + +Copyright 2002 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +MA 02111-1307, USA. */ + +#include "gmp.h" +#include "gmp-impl.h" + + + +#if HAVE_LIMB_BIG_ENDIAN +#define HOST_ENDIAN 1 +#endif +#if HAVE_LIMB_LITTLE_ENDIAN +#define HOST_ENDIAN (-1) +#endif +#ifndef HOST_ENDIAN +static const mp_limb_t endian_test = (CNST_LIMB(1) << (GMP_LIMB_BITS-7)) - 1; +#define HOST_ENDIAN (* (signed char *) &endian_test) +#endif + + +void +mpz_import (mpz_ptr z, size_t count, int order, + size_t size, int endian, size_t nail, const void *data) +{ + mp_size_t zsize; + mp_ptr zp; + + ASSERT (order == 1 || order == -1); + ASSERT (endian == 1 || endian == 0 || endian == -1); + ASSERT (nail <= 8*size); + + zsize = (count * (8*size - nail) + GMP_NUMB_BITS-1) / GMP_NUMB_BITS; + MPZ_REALLOC (z, zsize); + zp = PTR(z); + + if (endian == 0) + endian = HOST_ENDIAN; + + if (nail == GMP_NAIL_BITS) + { + unsigned align = (unsigned) data % sizeof (mp_limb_t); + + if (order == -1 + && size == sizeof (mp_limb_t) + && endian == HOST_ENDIAN + && align == 0) + { + MPN_COPY (zp, (mp_srcptr) data, (mp_size_t) count); + return; + } + + if (order == -1 + && size == sizeof (mp_limb_t) + && endian == - HOST_ENDIAN + && align == 0) + { + MPN_BSWAP (zp, (mp_srcptr) data, (mp_size_t) count); + return; + } + + if (order == 1 + && size == sizeof (mp_limb_t) + && endian == HOST_ENDIAN + && align == 0) + { + MPN_REVERSE (zp, (mp_srcptr) data, (mp_size_t) count); + return; + } + } + + { + mp_limb_t limb, byte, wbitsmask; + size_t i, j, numb, wbytes; + mp_size_t woffset; + unsigned char *dp; + int lbits, wbits; + + numb = size * 8 - nail; + + /* whole bytes to process */ + wbytes = numb / 8; + + /* partial byte to process */ + wbits = numb % 8; + wbitsmask = (CNST_LIMB(1) << wbits) - 1; + + /* offset to get to the next word after processing wbytes and wbits */ + woffset = (numb + 7) / 8; + woffset = (endian >= 0 ? woffset : -woffset) + + (order < 0 ? size : - (mp_size_t) size); + + /* least significant byte */ + dp = (unsigned char *) data + + (order >= 0 ? (count-1)*size : 0) + (endian >= 0 ? size-1 : 0); + +#define ACCUMULATE(N) \ + do { \ + limb |= (mp_limb_t) byte << lbits; \ + lbits += (N); \ + if (lbits >= GMP_NUMB_BITS) \ + { \ + *zp++ = limb & GMP_NUMB_MASK; \ + lbits -= GMP_NUMB_BITS; \ + ASSERT (lbits < 8); \ + limb = byte >> (8 - lbits); \ + } \ + } while (0) + + limb = 0; + lbits = 0; + for (i = 0; i < count; i++) + { + for (j = 0; j < wbytes; j++) + { + byte = *dp; + dp -= endian; + ACCUMULATE (8); + } + if (wbits != 0) + { + byte = *dp & wbitsmask; + dp -= endian; + ACCUMULATE (wbits); + } + dp += woffset; + } + + if (lbits != 0) + { + ASSERT (lbits <= GMP_NUMB_BITS); + ASSERT_LIMB (limb); + *zp++ = limb; + } + + ASSERT (zp == PTR(z) + zsize); + + /* low byte of word after most significant */ + ASSERT (dp == (unsigned char *) data + + (order < 0 ? count*size : - (mp_size_t) size) + + (endian >= 0 ? (mp_size_t) size - 1 : 0)); + + zp = PTR(z); + MPN_NORMALIZE (zp, zsize); + SIZ(z) = zsize; + } +} |