github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpz/export.c (about) 1 /* mpz_export -- create word data from mpz. 2 3 Copyright 2002, 2003, 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> /* for NULL */ 32 #include "gmp.h" 33 #include "gmp-impl.h" 34 #include "longlong.h" 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 void * 49 mpz_export (void *data, size_t *countp, int order, 50 size_t size, int endian, size_t nail, mpz_srcptr z) 51 { 52 mp_size_t zsize; 53 mp_srcptr zp; 54 size_t count, dummy; 55 unsigned long numb; 56 unsigned align; 57 58 ASSERT (order == 1 || order == -1); 59 ASSERT (endian == 1 || endian == 0 || endian == -1); 60 ASSERT (nail <= 8*size); 61 ASSERT (nail < 8*size || SIZ(z) == 0); /* nail < 8*size+(SIZ(z)==0) */ 62 63 if (countp == NULL) 64 countp = &dummy; 65 66 zsize = SIZ(z); 67 if (zsize == 0) 68 { 69 *countp = 0; 70 return data; 71 } 72 73 zsize = ABS (zsize); 74 zp = PTR(z); 75 numb = 8*size - nail; 76 MPN_SIZEINBASE_2EXP (count, zp, zsize, numb); 77 *countp = count; 78 79 if (data == NULL) 80 data = (*__gmp_allocate_func) (count*size); 81 82 if (endian == 0) 83 endian = HOST_ENDIAN; 84 85 align = ((char *) data - (char *) NULL) % sizeof (mp_limb_t); 86 87 if (nail == GMP_NAIL_BITS) 88 { 89 if (size == sizeof (mp_limb_t) && align == 0) 90 { 91 if (order == -1 && endian == HOST_ENDIAN) 92 { 93 MPN_COPY ((mp_ptr) data, zp, (mp_size_t) count); 94 return data; 95 } 96 if (order == 1 && endian == HOST_ENDIAN) 97 { 98 MPN_REVERSE ((mp_ptr) data, zp, (mp_size_t) count); 99 return data; 100 } 101 102 if (order == -1 && endian == -HOST_ENDIAN) 103 { 104 MPN_BSWAP ((mp_ptr) data, zp, (mp_size_t) count); 105 return data; 106 } 107 if (order == 1 && endian == -HOST_ENDIAN) 108 { 109 MPN_BSWAP_REVERSE ((mp_ptr) data, zp, (mp_size_t) count); 110 return data; 111 } 112 } 113 } 114 115 { 116 mp_limb_t limb, wbitsmask; 117 size_t i, numb; 118 mp_size_t j, wbytes, woffset; 119 unsigned char *dp; 120 int lbits, wbits; 121 mp_srcptr zend; 122 123 numb = size * 8 - nail; 124 125 /* whole bytes per word */ 126 wbytes = numb / 8; 127 128 /* possible partial byte */ 129 wbits = numb % 8; 130 wbitsmask = (CNST_LIMB(1) << wbits) - 1; 131 132 /* offset to get to the next word */ 133 woffset = (endian >= 0 ? size : - (mp_size_t) size) 134 + (order < 0 ? size : - (mp_size_t) size); 135 136 /* least significant byte */ 137 dp = (unsigned char *) data 138 + (order >= 0 ? (count-1)*size : 0) + (endian >= 0 ? size-1 : 0); 139 140 #define EXTRACT(N, MASK) \ 141 do { \ 142 if (lbits >= (N)) \ 143 { \ 144 *dp = limb MASK; \ 145 limb >>= (N); \ 146 lbits -= (N); \ 147 } \ 148 else \ 149 { \ 150 mp_limb_t newlimb; \ 151 newlimb = (zp == zend ? 0 : *zp++); \ 152 *dp = (limb | (newlimb << lbits)) MASK; \ 153 limb = newlimb >> ((N)-lbits); \ 154 lbits += GMP_NUMB_BITS - (N); \ 155 } \ 156 } while (0) 157 158 zend = zp + zsize; 159 lbits = 0; 160 limb = 0; 161 for (i = 0; i < count; i++) 162 { 163 for (j = 0; j < wbytes; j++) 164 { 165 EXTRACT (8, + 0); 166 dp -= endian; 167 } 168 if (wbits != 0) 169 { 170 EXTRACT (wbits, & wbitsmask); 171 dp -= endian; 172 j++; 173 } 174 for ( ; j < size; j++) 175 { 176 *dp = '\0'; 177 dp -= endian; 178 } 179 dp += woffset; 180 } 181 182 ASSERT (zp == PTR(z) + ABSIZ(z)); 183 184 /* low byte of word after most significant */ 185 ASSERT (dp == (unsigned char *) data 186 + (order < 0 ? count*size : - (mp_size_t) size) 187 + (endian >= 0 ? (mp_size_t) size - 1 : 0)); 188 } 189 return data; 190 }