github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpz/import.c (about) 1 /* mpz_import -- set mpz from word data. 2 3 Copyright 2002, 2012 Free Software Foundation, Inc. 4 5 This file is part of the GNU MP Library. 6 7 The GNU MP Library is free software; you can redistribute it and/or modify 8 it under the terms of either: 9 10 * the GNU Lesser General Public License as published by the Free 11 Software Foundation; either version 3 of the License, or (at your 12 option) any later version. 13 14 or 15 16 * the GNU General Public License as published by the Free Software 17 Foundation; either version 2 of the License, or (at your option) any 18 later version. 19 20 or both in parallel, as here. 21 22 The GNU MP Library is distributed in the hope that it will be useful, but 23 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 24 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 25 for more details. 26 27 You should have received copies of the GNU General Public License and the 28 GNU Lesser General Public License along with the GNU MP Library. If not, 29 see https://www.gnu.org/licenses/. */ 30 31 #include <stdio.h> 32 #include "gmp.h" 33 #include "gmp-impl.h" 34 35 36 37 #if HAVE_LIMB_BIG_ENDIAN 38 #define HOST_ENDIAN 1 39 #endif 40 #if HAVE_LIMB_LITTLE_ENDIAN 41 #define HOST_ENDIAN (-1) 42 #endif 43 #ifndef HOST_ENDIAN 44 static const mp_limb_t endian_test = (CNST_LIMB(1) << (GMP_LIMB_BITS-7)) - 1; 45 #define HOST_ENDIAN (* (signed char *) &endian_test) 46 #endif 47 48 49 void 50 mpz_import (mpz_ptr z, size_t count, int order, 51 size_t size, int endian, size_t nail, const void *data) 52 { 53 mp_size_t zsize; 54 mp_ptr zp; 55 56 ASSERT (order == 1 || order == -1); 57 ASSERT (endian == 1 || endian == 0 || endian == -1); 58 ASSERT (nail <= 8*size); 59 60 zsize = BITS_TO_LIMBS (count * (8*size - nail)); 61 zp = MPZ_NEWALLOC (z, zsize); 62 63 if (endian == 0) 64 endian = HOST_ENDIAN; 65 66 /* Can't use these special cases with nails currently, since they don't 67 mask out the nail bits in the input data. */ 68 if (nail == 0 && GMP_NAIL_BITS == 0) 69 { 70 unsigned align = ((char *) data - (char *) NULL) % sizeof (mp_limb_t); 71 72 if (order == -1 73 && size == sizeof (mp_limb_t) 74 && endian == HOST_ENDIAN 75 && align == 0) 76 { 77 MPN_COPY (zp, (mp_srcptr) data, (mp_size_t) count); 78 goto done; 79 } 80 81 if (order == -1 82 && size == sizeof (mp_limb_t) 83 && endian == - HOST_ENDIAN 84 && align == 0) 85 { 86 MPN_BSWAP (zp, (mp_srcptr) data, (mp_size_t) count); 87 goto done; 88 } 89 90 if (order == 1 91 && size == sizeof (mp_limb_t) 92 && endian == HOST_ENDIAN 93 && align == 0) 94 { 95 MPN_REVERSE (zp, (mp_srcptr) data, (mp_size_t) count); 96 goto done; 97 } 98 } 99 100 { 101 mp_limb_t limb, byte, wbitsmask; 102 size_t i, j, numb, wbytes; 103 mp_size_t woffset; 104 unsigned char *dp; 105 int lbits, wbits; 106 107 numb = size * 8 - nail; 108 109 /* whole bytes to process */ 110 wbytes = numb / 8; 111 112 /* partial byte to process */ 113 wbits = numb % 8; 114 wbitsmask = (CNST_LIMB(1) << wbits) - 1; 115 116 /* offset to get to the next word after processing wbytes and wbits */ 117 woffset = (numb + 7) / 8; 118 woffset = (endian >= 0 ? woffset : -woffset) 119 + (order < 0 ? size : - (mp_size_t) size); 120 121 /* least significant byte */ 122 dp = (unsigned char *) data 123 + (order >= 0 ? (count-1)*size : 0) + (endian >= 0 ? size-1 : 0); 124 125 #define ACCUMULATE(N) \ 126 do { \ 127 ASSERT (lbits < GMP_NUMB_BITS); \ 128 ASSERT (limb <= (CNST_LIMB(1) << lbits) - 1); \ 129 \ 130 limb |= (mp_limb_t) byte << lbits; \ 131 lbits += (N); \ 132 if (lbits >= GMP_NUMB_BITS) \ 133 { \ 134 *zp++ = limb & GMP_NUMB_MASK; \ 135 lbits -= GMP_NUMB_BITS; \ 136 ASSERT (lbits < (N)); \ 137 limb = byte >> ((N) - lbits); \ 138 } \ 139 } while (0) 140 141 limb = 0; 142 lbits = 0; 143 for (i = 0; i < count; i++) 144 { 145 for (j = 0; j < wbytes; j++) 146 { 147 byte = *dp; 148 dp -= endian; 149 ACCUMULATE (8); 150 } 151 if (wbits != 0) 152 { 153 byte = *dp & wbitsmask; 154 dp -= endian; 155 ACCUMULATE (wbits); 156 } 157 dp += woffset; 158 } 159 160 if (lbits != 0) 161 { 162 ASSERT (lbits <= GMP_NUMB_BITS); 163 ASSERT_LIMB (limb); 164 *zp++ = limb; 165 } 166 167 ASSERT (zp == PTR(z) + zsize); 168 169 /* low byte of word after most significant */ 170 ASSERT (dp == (unsigned char *) data 171 + (order < 0 ? count*size : - (mp_size_t) size) 172 + (endian >= 0 ? (mp_size_t) size - 1 : 0)); 173 174 } 175 176 done: 177 zp = PTR(z); 178 MPN_NORMALIZE (zp, zsize); 179 SIZ(z) = zsize; 180 }