3 Copyright (C) 2013 Niels Möller
4 Copyright (C) 2013 Red Hat
6 This file is part of GNU Nettle.
8 GNU Nettle is free software: you can redistribute it and/or
9 modify it under the terms of either:
11 * the GNU Lesser General Public License as published by the Free
12 Software Foundation; either version 3 of the License, or (at your
13 option) any later version.
17 * the GNU General Public License as published by the Free
18 Software Foundation; either version 2 of the License, or (at your
19 option) any later version.
21 or both in parallel, as here.
23 GNU Nettle is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 General Public License for more details.
28 You should have received copies of the GNU General Public License and
29 the GNU Lesser General Public License along with this program. If
30 not, see http://www.gnu.org/licenses/.
42 #if !GMP_HAVE_mpz_limbs_read
44 /* This implementation tries to make a minimal use of GMP internals.
45 We access and _mp_size and _mp_d, but not _mp_alloc. */
47 /* Use macros compatible with gmp-impl.h. */
48 #define ABS(x) ((x) >= 0 ? (x) : -(x))
49 #define PTR(x) ((x)->_mp_d)
50 #define SIZ(x) ((x)->_mp_size)
51 #define ABSIZ(x) ABS (SIZ (x))
53 #define MPN_NORMALIZE(xp, xn) do { \
54 while ( (xn) > 0 && (xp)[xn-1] == 0) \
58 /* NOTE: Makes an unnecessary realloc if allocation is already large
59 enough, but looking at _mp_alloc may break in future GMP
61 #define MPZ_REALLOC(x, n) \
62 (ABSIZ(x) >= (n) ? PTR(x) : (_mpz_realloc ((x),(n)), PTR (x)))
64 #define MPZ_NEWALLOC MPZ_REALLOC
66 /* Read access to mpz numbers. */
68 /* Return limb pointer, for read-only operations. Use mpz_size to get
69 the number of limbs. */
71 mpz_limbs_read (mpz_srcptr x)
76 /* Write access to mpz numbers. */
78 /* Get a limb pointer for writing, previous contents may be
81 mpz_limbs_write (mpz_ptr x, mp_size_t n)
84 return MPZ_NEWALLOC (x, n);
87 /* Get a limb pointer for writing, previous contents is intact. */
89 mpz_limbs_modify (mpz_ptr x, mp_size_t n)
92 return MPZ_REALLOC (x, n);
96 mpz_limbs_finish (mpz_ptr x, mp_size_t n)
99 MPN_NORMALIZE (PTR(x), n);
104 /* Needs some ugly casts. */
106 mpz_roinit_n (mpz_ptr x, const mp_limb_t *xp, mp_size_t xs)
108 mp_size_t xn = ABS (xs);
110 MPN_NORMALIZE (xp, xn);
112 x->_mp_size = xs < 0 ? -xn : xn;
114 x->_mp_d = (mp_limb_t *) xp;
117 #endif /* !GMP_HAVE_mpz_limbs_read */
119 #if !GMP_HAVE_mpn_copyd
121 mpn_copyd (mp_ptr dst, mp_srcptr src, mp_size_t n)
124 for (i = n - 1; i >= 0; i--)
129 mpn_copyi (mp_ptr dst, mp_srcptr src, mp_size_t n)
132 for (i = 0; i < n; i++)
137 mpn_zero (mp_ptr ptr, mp_size_t n)
140 for (i = 0; i < n; i++)
143 #endif /* !GMP_HAVE_mpn_copyd */
145 /* Additional convenience functions. */
148 mpz_limbs_cmp (mpz_srcptr a, const mp_limb_t *bp, mp_size_t bn)
150 mp_size_t an = mpz_size (a);
151 assert (mpz_sgn (a) >= 0);
161 return mpn_cmp (mpz_limbs_read(a), bp, an);
164 /* Get a pointer to an n limb area, for read-only operation. n must be
165 greater or equal to the current size, and the mpz is zero-padded if
168 mpz_limbs_read_n (mpz_ptr x, mp_size_t n)
170 mp_size_t xn = mpz_size (x);
175 xp = mpz_limbs_modify (x, n);
178 mpn_zero (xp + xn, n - xn);
184 mpz_limbs_copy (mp_limb_t *xp, mpz_srcptr x, mp_size_t n)
186 mp_size_t xn = mpz_size (x);
189 mpn_copyi (xp, mpz_limbs_read (x), xn);
191 mpn_zero (xp + xn, n - xn);
195 mpz_set_n (mpz_t r, const mp_limb_t *xp, mp_size_t xn)
197 mpn_copyi (mpz_limbs_write (r, xn), xp, xn);
198 mpz_limbs_finish (r, xn);
202 mpn_set_base256 (mp_limb_t *rp, mp_size_t rn,
203 const uint8_t *xp, size_t xn)
208 for (xi = xn, out = bits = 0; xi > 0 && rn > 0; )
210 mp_limb_t in = xp[--xi];
211 out |= (in << bits) & GMP_NUMB_MASK;
213 if (bits >= GMP_NUMB_BITS)
218 bits -= GMP_NUMB_BITS;
219 out = in >> (8 - bits);
231 mpn_set_base256_le (mp_limb_t *rp, mp_size_t rn,
232 const uint8_t *xp, size_t xn)
237 for (xi = 0, out = bits = 0; xi < xn && rn > 0; )
239 mp_limb_t in = xp[xi++];
240 out |= (in << bits) & GMP_NUMB_MASK;
242 if (bits >= GMP_NUMB_BITS)
247 bits -= GMP_NUMB_BITS;
248 out = in >> (8 - bits);
260 mpn_get_base256_le (uint8_t *rp, size_t rn,
261 const mp_limb_t *xp, mp_size_t xn)
265 for (bits = in = 0; xn > 0 && rn > 0; )
279 *rp++ = old | (in << bits);
281 bits += GMP_NUMB_BITS - 8;
293 gmp_alloc_limbs (mp_size_t n)
296 void *(*alloc_func)(size_t);
300 mp_get_memory_functions (&alloc_func, NULL, NULL);
301 return (mp_limb_t *) alloc_func ( (size_t) n * sizeof(mp_limb_t));
305 gmp_free_limbs (mp_limb_t *p, mp_size_t n)
307 void (*free_func)(void *, size_t);
310 mp_get_memory_functions (NULL, NULL, &free_func);
312 free_func (p, (size_t) n * sizeof(mp_limb_t));
318 void *(*alloc_func)(size_t);
321 mp_get_memory_functions(&alloc_func, NULL, NULL);
323 return alloc_func (n);
327 gmp_free(void *p, size_t n)
329 void (*free_func)(void *, size_t);
332 mp_get_memory_functions (NULL, NULL, &free_func);
334 free_func (p, (size_t) n);