beta-0.89.2
[luatex.git] / source / libs / gmp / gmp-src / mpz / export.c
blobbc4c4df976a5f3171122da6b68708cd3873fa599
1 /* mpz_export -- create word data from mpz.
3 Copyright 2002, 2003, 2012 Free Software Foundation, Inc.
5 This file is part of the GNU MP Library.
7 The GNU MP Library is free software; you can redistribute it and/or modify
8 it under the terms of either:
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.
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.
20 or both in parallel, as here.
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.
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/. */
31 #include <stdio.h> /* for NULL */
32 #include "gmp.h"
33 #include "gmp-impl.h"
34 #include "longlong.h"
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
48 void *
49 mpz_export (void *data, size_t *countp, int order,
50 size_t size, int endian, size_t nail, mpz_srcptr z)
52 mp_size_t zsize;
53 mp_srcptr zp;
54 size_t count, dummy;
55 unsigned long numb;
56 unsigned align;
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) */
63 if (countp == NULL)
64 countp = &dummy;
66 zsize = SIZ(z);
67 if (zsize == 0)
69 *countp = 0;
70 return data;
73 zsize = ABS (zsize);
74 zp = PTR(z);
75 numb = 8*size - nail;
76 MPN_SIZEINBASE_2EXP (count, zp, zsize, numb);
77 *countp = count;
79 if (data == NULL)
80 data = (*__gmp_allocate_func) (count*size);
82 if (endian == 0)
83 endian = HOST_ENDIAN;
85 align = ((char *) data - (char *) NULL) % sizeof (mp_limb_t);
87 if (nail == GMP_NAIL_BITS)
89 if (size == sizeof (mp_limb_t) && align == 0)
91 if (order == -1 && endian == HOST_ENDIAN)
93 MPN_COPY ((mp_ptr) data, zp, (mp_size_t) count);
94 return data;
96 if (order == 1 && endian == HOST_ENDIAN)
98 MPN_REVERSE ((mp_ptr) data, zp, (mp_size_t) count);
99 return data;
102 if (order == -1 && endian == -HOST_ENDIAN)
104 MPN_BSWAP ((mp_ptr) data, zp, (mp_size_t) count);
105 return data;
107 if (order == 1 && endian == -HOST_ENDIAN)
109 MPN_BSWAP_REVERSE ((mp_ptr) data, zp, (mp_size_t) count);
110 return data;
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;
123 numb = size * 8 - nail;
125 /* whole bytes per word */
126 wbytes = numb / 8;
128 /* possible partial byte */
129 wbits = numb % 8;
130 wbitsmask = (CNST_LIMB(1) << wbits) - 1;
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);
136 /* least significant byte */
137 dp = (unsigned char *) data
138 + (order >= 0 ? (count-1)*size : 0) + (endian >= 0 ? size-1 : 0);
140 #define EXTRACT(N, MASK) \
141 do { \
142 if (lbits >= (N)) \
144 *dp = limb MASK; \
145 limb >>= (N); \
146 lbits -= (N); \
148 else \
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); \
156 } while (0)
158 zend = zp + zsize;
159 lbits = 0;
160 limb = 0;
161 for (i = 0; i < count; i++)
163 for (j = 0; j < wbytes; j++)
165 EXTRACT (8, + 0);
166 dp -= endian;
168 if (wbits != 0)
170 EXTRACT (wbits, & wbitsmask);
171 dp -= endian;
172 j++;
174 for ( ; j < size; j++)
176 *dp = '\0';
177 dp -= endian;
179 dp += woffset;
182 ASSERT (zp == PTR(z) + ABSIZ(z));
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));
189 return data;