version 1.1.1.2, 2000/09/09 14:12:55 |
version 1.1.1.3, 2003/08/25 16:06:33 |
|
|
/* mpz_out_raw -- Output a mpz_t in binary. Use an endianess and word size |
/* mpz_out_raw -- write an mpz_t in raw format. |
independent format. |
|
|
|
Copyright (C) 1995 Free Software Foundation, Inc. |
Copyright 2001, 2002 Free Software Foundation, Inc. |
|
|
This file is part of the GNU MP Library. |
This file is part of the GNU MP Library. |
|
|
Line 21 the Free Software Foundation, Inc., 59 Temple Place - |
|
Line 20 the Free Software Foundation, Inc., 59 Temple Place - |
|
MA 02111-1307, USA. */ |
MA 02111-1307, USA. */ |
|
|
#include <stdio.h> |
#include <stdio.h> |
|
|
#include "gmp.h" |
#include "gmp.h" |
#include "gmp-impl.h" |
#include "gmp-impl.h" |
|
#include "longlong.h" |
|
|
size_t |
|
#if __STDC__ |
/* HTON_LIMB_STORE takes a normal host byte order limb and stores it as |
mpz_out_raw (FILE *stream, mpz_srcptr x) |
network byte order (ie. big endian). */ |
#else |
|
mpz_out_raw (stream, x) |
#if HAVE_LIMB_BIG_ENDIAN |
FILE *stream; |
#define HTON_LIMB_STORE(dst, limb) do { *(dst) = (limb); } while (0) |
mpz_srcptr x; |
|
#endif |
#endif |
|
|
|
/* The generic implementations below very likely come out as lots of |
|
separate byte stores, so if we know the host is little endian then |
|
instead use a purely arithmetic BSWAP_LIMB and a single store. */ |
|
#if HAVE_LIMB_LITTLE_ENDIAN |
|
#define HTON_LIMB_STORE(dst, limb) BSWAP_LIMB_STORE (dst, limb) |
|
#endif |
|
|
|
#if ! defined (HTON_LIMB_STORE) |
|
#if BITS_PER_MP_LIMB == 8 |
|
#define HTON_LIMB_STORE(dst, limb) do { *(dst) = (limb); } while (0) |
|
#endif |
|
#if BITS_PER_MP_LIMB == 16 |
|
#define HTON_LIMB_STORE(dst, limb) \ |
|
do { \ |
|
mp_limb_t __limb = (limb); \ |
|
char *__p = (char *) (dst); \ |
|
__p[1] = (__limb); \ |
|
__p[0] = (__limb) >> 8; \ |
|
} while (0) |
|
#endif |
|
#if BITS_PER_MP_LIMB == 32 |
|
#define HTON_LIMB_STORE(dst, limb) \ |
|
do { \ |
|
mp_limb_t __limb = (limb); \ |
|
char *__p = (char *) (dst); \ |
|
__p[3] = (__limb); \ |
|
__p[2] = (__limb) >> 8; \ |
|
__p[1] = (__limb) >> 16; \ |
|
__p[0] = (__limb) >> 24; \ |
|
} while (0) |
|
#endif |
|
#if BITS_PER_MP_LIMB == 64 |
|
#define HTON_LIMB_STORE(dst, limb) \ |
|
do { \ |
|
mp_limb_t __limb = (limb); \ |
|
char *__p = (char *) (dst); \ |
|
__p[7] = (__limb); \ |
|
__p[6] = (__limb) >> 8; \ |
|
__p[5] = (__limb) >> 16; \ |
|
__p[4] = (__limb) >> 24; \ |
|
__p[3] = (__limb) >> 32; \ |
|
__p[2] = (__limb) >> 40; \ |
|
__p[1] = (__limb) >> 48; \ |
|
__p[0] = (__limb) >> 56; \ |
|
} while (0) |
|
#endif |
|
#endif |
|
|
|
|
|
size_t |
|
mpz_out_raw (FILE *fp, mpz_srcptr x) |
{ |
{ |
int i; |
mp_size_t xsize, abs_xsize, bytes, i; |
mp_size_t s; |
mp_srcptr xp; |
mp_size_t xsize = ABS (x->_mp_size); |
char *tp, *bp; |
mp_srcptr xp = x->_mp_d; |
mp_limb_t xlimb; |
mp_size_t out_bytesize; |
int zeros; |
mp_limb_t hi_limb; |
size_t tsize, ssize; |
int n_bytes_in_hi_limb; |
|
|
|
if (stream == 0) |
xsize = SIZ(x); |
stream = stdout; |
abs_xsize = ABS (xsize); |
|
bytes = (abs_xsize * GMP_NUMB_BITS + 7) / 8; |
|
tsize = ROUND_UP_MULTIPLE ((unsigned) 4, BYTES_PER_MP_LIMB) + bytes; |
|
|
if (xsize == 0) |
tp = __GMP_ALLOCATE_FUNC_TYPE (tsize, char); |
{ |
bp = tp + ROUND_UP_MULTIPLE ((unsigned) 4, BYTES_PER_MP_LIMB); |
for (i = 4 - 1; i >= 0; i--) |
|
fputc (0, stream); |
|
return ferror (stream) ? 0 : 4; |
|
} |
|
|
|
hi_limb = xp[xsize - 1]; |
if (bytes != 0) |
for (i = BYTES_PER_MP_LIMB - 1; i > 0; i--) |
|
{ |
{ |
if ((hi_limb >> i * BITS_PER_CHAR) != 0) |
bp += bytes; |
break; |
xp = PTR (x); |
} |
i = abs_xsize; |
n_bytes_in_hi_limb = i + 1; |
|
out_bytesize = BYTES_PER_MP_LIMB * (xsize - 1) + n_bytes_in_hi_limb; |
|
if (x->_mp_size < 0) |
|
out_bytesize = -out_bytesize; |
|
|
|
/* Make the size 4 bytes on all machines, to make the format portable. */ |
if (GMP_NAIL_BITS == 0) |
for (i = 4 - 1; i >= 0; i--) |
{ |
fputc ((out_bytesize >> (i * BITS_PER_CHAR)) % (1 << BITS_PER_CHAR), |
/* reverse limb order, and byte swap if necessary */ |
stream); |
#ifdef _CRAY |
|
_Pragma ("_CRI ivdep"); |
|
#endif |
|
do |
|
{ |
|
bp -= BYTES_PER_MP_LIMB; |
|
xlimb = *xp; |
|
HTON_LIMB_STORE ((mp_ptr) bp, xlimb); |
|
xp++; |
|
} |
|
while (--i > 0); |
|
|
/* Output from the most significant limb to the least significant limb, |
/* strip high zero bytes (without fetching from bp) */ |
with each limb also output in decreasing significance order. */ |
count_leading_zeros (zeros, xlimb); |
|
zeros /= 8; |
|
bp += zeros; |
|
bytes -= zeros; |
|
} |
|
else |
|
{ |
|
mp_limb_t new_xlimb; |
|
int bits; |
|
ASSERT_CODE (char *bp_orig = bp - bytes); |
|
|
/* Output the most significant limb separately, since we will only |
ASSERT_ALWAYS (GMP_NUMB_BITS >= 8); |
output some of its bytes. */ |
|
for (i = n_bytes_in_hi_limb - 1; i >= 0; i--) |
|
fputc ((hi_limb >> (i * BITS_PER_CHAR)) % (1 << BITS_PER_CHAR), stream); |
|
|
|
/* Output the remaining limbs. */ |
bits = 0; |
for (s = xsize - 2; s >= 0; s--) |
xlimb = 0; |
{ |
for (;;) |
mp_limb_t x_limb; |
{ |
|
while (bits >= 8) |
|
{ |
|
ASSERT (bp > bp_orig); |
|
*--bp = xlimb & 0xFF; |
|
xlimb >>= 8; |
|
bits -= 8; |
|
} |
|
|
x_limb = xp[s]; |
if (i == 0) |
for (i = BYTES_PER_MP_LIMB - 1; i >= 0; i--) |
break; |
fputc ((x_limb >> (i * BITS_PER_CHAR)) % (1 << BITS_PER_CHAR), stream); |
|
|
new_xlimb = *xp++; |
|
i--; |
|
ASSERT (bp > bp_orig); |
|
*--bp = (xlimb | (new_xlimb << bits)) & 0xFF; |
|
xlimb = new_xlimb >> (8 - bits); |
|
bits += GMP_NUMB_BITS - 8; |
|
} |
|
|
|
if (bits != 0) |
|
{ |
|
ASSERT (bp > bp_orig); |
|
*--bp = xlimb; |
|
} |
|
|
|
ASSERT (bp == bp_orig); |
|
while (*bp == 0) |
|
{ |
|
bp++; |
|
bytes--; |
|
} |
|
} |
} |
} |
return ferror (stream) ? 0 : ABS (out_bytesize) + 4; |
|
|
/* total bytes to be written */ |
|
ssize = 4 + bytes; |
|
|
|
/* twos complement negative for the size value */ |
|
bytes = (xsize >= 0 ? bytes : -bytes); |
|
|
|
/* so we don't rely on sign extension in ">>" */ |
|
ASSERT_ALWAYS (sizeof (bytes) >= 4); |
|
|
|
bp[-4] = bytes >> 24; |
|
bp[-3] = bytes >> 16; |
|
bp[-2] = bytes >> 8; |
|
bp[-1] = bytes; |
|
bp -= 4; |
|
|
|
if (fp == 0) |
|
fp = stdout; |
|
if (fwrite (bp, ssize, 1, fp) != 1) |
|
ssize = 0; |
|
|
|
(*__gmp_free_func) (tp, tsize); |
|
return ssize; |
} |
} |