From 11da511c784eca003deb90c23570f0873954e0de Mon Sep 17 00:00:00 2001 From: Duncan Wilkie Date: Sat, 18 Nov 2023 06:11:09 -0600 Subject: Initial commit. --- gmp-6.3.0/mpz/import.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 gmp-6.3.0/mpz/import.c (limited to 'gmp-6.3.0/mpz/import.c') diff --git a/gmp-6.3.0/mpz/import.c b/gmp-6.3.0/mpz/import.c new file mode 100644 index 0000000..9ff0670 --- /dev/null +++ b/gmp-6.3.0/mpz/import.c @@ -0,0 +1,166 @@ +/* mpz_import -- set mpz from word data. + +Copyright 2002, 2012, 2021, 2022 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 either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + +or + + * the GNU General Public License as published by the Free Software + Foundation; either version 2 of the License, or (at your option) any + later version. + +or both in parallel, as here. + +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 General Public License +for more details. + +You should have received copies of the GNU General Public License and the +GNU Lesser General Public License along with the GNU MP Library. If not, +see https://www.gnu.org/licenses/. */ + +#include +#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 = BITS_TO_LIMBS (count * (8*size - nail)); + zp = MPZ_NEWALLOC (z, zsize); + + if (endian == 0) + endian = HOST_ENDIAN; + + /* Can't use these special cases with nails currently, since they don't + mask out the nail bits in the input data. */ + if (nail == 0 && GMP_NAIL_BITS == 0 + && size == sizeof (mp_limb_t) + && (((char *) data - (char *) NULL) % sizeof (mp_limb_t)) == 0 /* align */) + { + if (order == -1) + { + if (endian == HOST_ENDIAN) + MPN_COPY (zp, (mp_srcptr) data, (mp_size_t) count); + else /* if (endian == - HOST_ENDIAN) */ + MPN_BSWAP (zp, (mp_srcptr) data, (mp_size_t) count); + } + else /* if (order == 1) */ + { + if (endian == HOST_ENDIAN) + MPN_REVERSE (zp, (mp_srcptr) data, (mp_size_t) count); + else /* if (endian == - HOST_ENDIAN) */ + MPN_BSWAP_REVERSE (zp, (mp_srcptr) data, (mp_size_t) count); + } + } + else + { + 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 { \ + ASSERT (lbits < GMP_NUMB_BITS); \ + ASSERT (limb <= (CNST_LIMB(1) << lbits) - 1); \ + \ + limb |= (mp_limb_t) byte << lbits; \ + lbits += (N); \ + if (lbits >= GMP_NUMB_BITS) \ + { \ + *zp++ = limb & GMP_NUMB_MASK; \ + lbits -= GMP_NUMB_BITS; \ + ASSERT (lbits < (N)); \ + limb = byte >> ((N) - 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; +} -- cgit v1.2.3