X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=gmp%2Fmpz%2Fout_raw.c;fp=gmp%2Fmpz%2Fout_raw.c;h=3eb9fab50ea58411f7e3cc07225c96403b48386e;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=0000000000000000000000000000000000000000;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/gmp/mpz/out_raw.c b/gmp/mpz/out_raw.c new file mode 100644 index 00000000..3eb9fab5 --- /dev/null +++ b/gmp/mpz/out_raw.c @@ -0,0 +1,162 @@ +/* mpz_out_raw -- write an mpz_t in raw format. + +Copyright 2001, 2002 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ + +#include +#include "gmp.h" +#include "gmp-impl.h" +#include "longlong.h" + + +/* HTON_LIMB_STORE takes a normal host byte order limb and stores it as + network byte order (ie. big endian). */ + +#if HAVE_LIMB_BIG_ENDIAN +#define HTON_LIMB_STORE(dst, limb) do { *(dst) = (limb); } while (0) +#endif + +#if HAVE_LIMB_LITTLE_ENDIAN +#define HTON_LIMB_STORE(dst, limb) BSWAP_LIMB_STORE (dst, limb) +#endif + +#ifndef HTON_LIMB_STORE +#define HTON_LIMB_STORE(dst, limb) \ + do { \ + mp_limb_t __limb = (limb); \ + char *__p = (char *) (dst); \ + int __i; \ + for (__i = 0; __i < BYTES_PER_MP_LIMB; __i++) \ + __p[__i] = (char) (__limb >> ((BYTES_PER_MP_LIMB-1 - __i) * 8)); \ + } while (0) +#endif + + +size_t +mpz_out_raw (FILE *fp, mpz_srcptr x) +{ + mp_size_t xsize, abs_xsize, bytes, i; + mp_srcptr xp; + char *tp, *bp; + mp_limb_t xlimb; + int zeros; + size_t tsize, ssize; + + xsize = SIZ(x); + abs_xsize = ABS (xsize); + bytes = (abs_xsize * GMP_NUMB_BITS + 7) / 8; + tsize = ROUND_UP_MULTIPLE ((unsigned) 4, BYTES_PER_MP_LIMB) + bytes; + + tp = __GMP_ALLOCATE_FUNC_TYPE (tsize, char); + bp = tp + ROUND_UP_MULTIPLE ((unsigned) 4, BYTES_PER_MP_LIMB); + + if (bytes != 0) + { + bp += bytes; + xp = PTR (x); + i = abs_xsize; + + if (GMP_NAIL_BITS == 0) + { + /* reverse limb order, and byte swap if necessary */ +#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); + + /* strip high zero bytes (without fetching from bp) */ + 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); + + ASSERT_ALWAYS (GMP_NUMB_BITS >= 8); + + bits = 0; + xlimb = 0; + for (;;) + { + while (bits >= 8) + { + ASSERT (bp > bp_orig); + *--bp = xlimb & 0xFF; + xlimb >>= 8; + bits -= 8; + } + + if (i == 0) + break; + + 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--; + } + } + } + + /* 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; +}