Annotation of OpenXM_contrib/gmp/mpz/export.c, Revision 1.1
1.1 ! ohara 1: /* mpz_export -- create word data from mpz.
! 2:
! 3: Copyright 2002 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 the GNU Lesser General Public License as published by
! 9: the Free Software Foundation; either version 2.1 of the License, or (at your
! 10: option) any later version.
! 11:
! 12: The GNU MP Library is distributed in the hope that it will be useful, but
! 13: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 14: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
! 15: License for more details.
! 16:
! 17: You should have received a copy of the GNU Lesser General Public License
! 18: along with the GNU MP Library; see the file COPYING.LIB. If not, write to
! 19: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
! 20: MA 02111-1307, USA. */
! 21:
! 22: #include <stdio.h> /* for NULL */
! 23: #include "gmp.h"
! 24: #include "gmp-impl.h"
! 25: #include "longlong.h"
! 26:
! 27:
! 28: #if HAVE_LIMB_BIG_ENDIAN
! 29: #define HOST_ENDIAN 1
! 30: #endif
! 31: #if HAVE_LIMB_LITTLE_ENDIAN
! 32: #define HOST_ENDIAN (-1)
! 33: #endif
! 34: #ifndef HOST_ENDIAN
! 35: static const mp_limb_t endian_test = (CNST_LIMB(1) << (GMP_LIMB_BITS-7)) - 1;
! 36: #define HOST_ENDIAN (* (signed char *) &endian_test)
! 37: #endif
! 38:
! 39:
! 40: #define MPN_SIZEINBASE_2EXP(result, ptr, size, base2exp) \
! 41: do { \
! 42: int __cnt; \
! 43: unsigned long __totbits; \
! 44: ASSERT ((size) > 0); \
! 45: ASSERT ((ptr)[(size)-1] != 0); \
! 46: count_leading_zeros (__cnt, (ptr)[(size)-1]); \
! 47: __totbits = (size) * GMP_NUMB_BITS - (__cnt - GMP_NAIL_BITS); \
! 48: (result) = (__totbits + (base2exp)-1) / (base2exp); \
! 49: } while (0)
! 50:
! 51:
! 52: void *
! 53: mpz_export (void *data, size_t *countp, int order,
! 54: size_t size, int endian, size_t nail, mpz_srcptr z)
! 55: {
! 56: mp_size_t zsize;
! 57: mp_srcptr zp;
! 58: size_t count;
! 59: unsigned long numb;
! 60: unsigned align;
! 61:
! 62: ASSERT (order == 1 || order == -1);
! 63: ASSERT (endian == 1 || endian == 0 || endian == -1);
! 64: ASSERT (nail <= 8*size);
! 65: ASSERT (8*size-nail > 0);
! 66:
! 67: zsize = SIZ(z);
! 68: if (zsize == 0)
! 69: {
! 70: *countp = 0;
! 71: return data;
! 72: }
! 73:
! 74: zsize = ABS (zsize);
! 75: zp = PTR(z);
! 76: numb = 8*size - nail;
! 77: MPN_SIZEINBASE_2EXP (count, zp, zsize, numb);
! 78: *countp = count;
! 79:
! 80: if (data == NULL)
! 81: data = (*__gmp_allocate_func) (count*size);
! 82:
! 83: if (endian == 0)
! 84: endian = HOST_ENDIAN;
! 85:
! 86: align = ((char *) data - (char *) NULL) % sizeof (mp_limb_t);
! 87:
! 88: if (nail == GMP_NAIL_BITS)
! 89: {
! 90: if (size == sizeof (mp_limb_t) && align == 0)
! 91: {
! 92: if (order == -1 && endian == HOST_ENDIAN)
! 93: {
! 94: MPN_COPY ((mp_ptr) data, zp, (mp_size_t) count);
! 95: return data;
! 96: }
! 97: if (order == 1 && endian == HOST_ENDIAN)
! 98: {
! 99: MPN_REVERSE ((mp_ptr) data, zp, (mp_size_t) count);
! 100: return data;
! 101: }
! 102:
! 103: if (order == -1 && endian == -HOST_ENDIAN)
! 104: {
! 105: MPN_BSWAP ((mp_ptr) data, zp, (mp_size_t) count);
! 106: return data;
! 107: }
! 108: if (order == 1 && endian == -HOST_ENDIAN)
! 109: {
! 110: MPN_BSWAP_REVERSE ((mp_ptr) data, zp, (mp_size_t) count);
! 111: return data;
! 112: }
! 113: }
! 114: }
! 115:
! 116: {
! 117: mp_limb_t limb, wbitsmask;
! 118: size_t i, numb;
! 119: mp_size_t j, wbytes, woffset;
! 120: unsigned char *dp;
! 121: int lbits, wbits;
! 122: mp_srcptr zend;
! 123:
! 124: numb = size * 8 - nail;
! 125:
! 126: /* whole bytes per word */
! 127: wbytes = numb / 8;
! 128:
! 129: /* possible partial byte */
! 130: wbits = numb % 8;
! 131: wbitsmask = (CNST_LIMB(1) << wbits) - 1;
! 132:
! 133: /* offset to get to the next word */
! 134: woffset = (endian >= 0 ? size : - (mp_size_t) size)
! 135: + (order < 0 ? size : - (mp_size_t) size);
! 136:
! 137: /* least significant byte */
! 138: dp = (unsigned char *) data
! 139: + (order >= 0 ? (count-1)*size : 0) + (endian >= 0 ? size-1 : 0);
! 140:
! 141: #define EXTRACT(N, MASK) \
! 142: do { \
! 143: if (lbits >= (N)) \
! 144: { \
! 145: *dp = limb MASK; \
! 146: limb >>= (N); \
! 147: lbits -= (N); \
! 148: } \
! 149: else \
! 150: { \
! 151: mp_limb_t newlimb; \
! 152: newlimb = (zp == zend ? 0 : *zp++); \
! 153: *dp = (limb | (newlimb << lbits)) MASK; \
! 154: limb = newlimb >> ((N)-lbits); \
! 155: lbits += GMP_NUMB_BITS - (N); \
! 156: } \
! 157: } while (0)
! 158:
! 159: zend = zp + zsize;
! 160: lbits = 0;
! 161: limb = 0;
! 162: for (i = 0; i < count; i++)
! 163: {
! 164: for (j = 0; j < wbytes; j++)
! 165: {
! 166: EXTRACT (8, + 0);
! 167: dp -= endian;
! 168: }
! 169: if (wbits != 0)
! 170: {
! 171: EXTRACT (wbits, & wbitsmask);
! 172: dp -= endian;
! 173: j++;
! 174: }
! 175: for ( ; j < size; j++)
! 176: {
! 177: *dp = '\0';
! 178: dp -= endian;
! 179: }
! 180: dp += woffset;
! 181: }
! 182:
! 183: ASSERT (zp == PTR(z) + ABSIZ(z));
! 184:
! 185: /* low byte of word after most significant */
! 186: ASSERT (dp == (unsigned char *) data
! 187: + (order < 0 ? count*size : - (mp_size_t) size)
! 188: + (endian >= 0 ? (mp_size_t) size - 1 : 0));
! 189: }
! 190: return data;
! 191: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>