source: trunk/third/gmp/mpz/out_raw.c @ 18191

Revision 18191, 5.4 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18190, which included commits to RCS files with non-trunk default branches.
Line 
1/* mpz_out_raw -- write an mpz_t in raw format.
2
3Copyright 2001, 2002 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library.
6
7The GNU MP Library is free software; you can redistribute it and/or modify
8it under the terms of the GNU Lesser General Public License as published by
9the Free Software Foundation; either version 2.1 of the License, or (at your
10option) any later version.
11
12The GNU MP Library is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15License for more details.
16
17You should have received a copy of the GNU Lesser General Public License
18along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20MA 02111-1307, USA. */
21
22#include <stdio.h>
23#include "gmp.h"
24#include "gmp-impl.h"
25#include "longlong.h"
26
27
28/* HTON_LIMB_STORE takes a normal host byte order limb and stores it as
29   network byte order (ie. big endian). */
30
31#if HAVE_LIMB_BIG_ENDIAN
32#define HTON_LIMB_STORE(dst, limb)  do { *(dst) = (limb); } while (0)
33#endif
34
35/* The generic implementations below very likely come out as lots of
36   separate byte stores, so if we know the host is little endian then
37   instead use a purely arithmetic BSWAP_LIMB and a single store.  */
38#if HAVE_LIMB_LITTLE_ENDIAN
39#define HTON_LIMB_STORE(dst, limb)  BSWAP_LIMB_STORE (dst, limb)
40#endif
41
42#if ! defined (HTON_LIMB_STORE)
43#if BITS_PER_MP_LIMB == 8
44#define HTON_LIMB_STORE(dst, limb)  do { *(dst) = (limb); } while (0)
45#endif
46#if BITS_PER_MP_LIMB == 16
47#define HTON_LIMB_STORE(dst, limb)      \
48  do {                                  \
49    mp_limb_t  __limb = (limb);         \
50    char  *__p = (char *) (dst);        \
51    __p[1] = (__limb);                  \
52    __p[0] = (__limb) >> 8;             \
53  } while (0)
54#endif
55#if BITS_PER_MP_LIMB == 32
56#define HTON_LIMB_STORE(dst, limb)      \
57  do {                                  \
58    mp_limb_t  __limb = (limb);         \
59    char  *__p = (char *) (dst);        \
60    __p[3] = (__limb);                  \
61    __p[2] = (__limb) >> 8;             \
62    __p[1] = (__limb) >> 16;            \
63    __p[0] = (__limb) >> 24;            \
64  } while (0)
65#endif
66#if BITS_PER_MP_LIMB == 64
67#define HTON_LIMB_STORE(dst, limb)      \
68  do {                                  \
69    mp_limb_t  __limb = (limb);         \
70    char  *__p = (char *) (dst);        \
71    __p[7] = (__limb);                  \
72    __p[6] = (__limb) >> 8;             \
73    __p[5] = (__limb) >> 16;            \
74    __p[4] = (__limb) >> 24;            \
75    __p[3] = (__limb) >> 32;            \
76    __p[2] = (__limb) >> 40;            \
77    __p[1] = (__limb) >> 48;            \
78    __p[0] = (__limb) >> 56;            \
79  } while (0)
80#endif
81#endif
82
83
84size_t
85mpz_out_raw (FILE *fp, mpz_srcptr x)
86{
87  mp_size_t   xsize, abs_xsize, bytes, i;
88  mp_srcptr   xp;
89  char        *tp, *bp;
90  mp_limb_t   xlimb;
91  int         zeros;
92  size_t      tsize, ssize;
93
94  xsize = SIZ(x);
95  abs_xsize = ABS (xsize);
96  bytes = (abs_xsize * GMP_NUMB_BITS + 7) / 8;
97  tsize = ROUND_UP_MULTIPLE ((unsigned) 4, BYTES_PER_MP_LIMB) + bytes;
98
99  tp = __GMP_ALLOCATE_FUNC_TYPE (tsize, char);
100  bp = tp + ROUND_UP_MULTIPLE ((unsigned) 4, BYTES_PER_MP_LIMB);
101
102  if (bytes != 0)
103    {
104      bp += bytes;
105      xp = PTR (x);
106      i = abs_xsize;
107
108      if (GMP_NAIL_BITS == 0)
109        {
110          /* reverse limb order, and byte swap if necessary */
111#ifdef _CRAY
112          _Pragma ("_CRI ivdep");
113#endif
114          do
115            {
116              bp -= BYTES_PER_MP_LIMB;
117              xlimb = *xp;
118              HTON_LIMB_STORE ((mp_ptr) bp, xlimb);
119              xp++;
120            }
121          while (--i > 0);
122
123          /* strip high zero bytes (without fetching from bp) */
124          count_leading_zeros (zeros, xlimb);
125          zeros /= 8;
126          bp += zeros;
127          bytes -= zeros;
128        }
129      else
130        {
131          mp_limb_t  new_xlimb;
132          int        bits;
133          ASSERT_CODE (char *bp_orig = bp - bytes);
134
135          ASSERT_ALWAYS (GMP_NUMB_BITS >= 8);
136
137          bits = 0;
138          xlimb = 0;
139          for (;;)
140            {
141              while (bits >= 8)
142                {
143                  ASSERT (bp > bp_orig);
144                  *--bp = xlimb & 0xFF;
145                  xlimb >>= 8;
146                  bits -= 8;
147                }
148
149              if (i == 0)
150                break;
151
152              new_xlimb = *xp++;
153              i--;
154              ASSERT (bp > bp_orig);
155              *--bp = (xlimb | (new_xlimb << bits)) & 0xFF;
156              xlimb = new_xlimb >> (8 - bits);
157              bits += GMP_NUMB_BITS - 8;
158            }
159
160          if (bits != 0)
161            {
162              ASSERT (bp > bp_orig);
163              *--bp = xlimb;
164            }
165
166          ASSERT (bp == bp_orig);
167          while (*bp == 0)
168            {
169              bp++;
170              bytes--;
171            }
172        }
173    }
174
175  /* total bytes to be written */
176  ssize = 4 + bytes;
177
178  /* twos complement negative for the size value */
179  bytes = (xsize >= 0 ? bytes : -bytes);
180
181  /* so we don't rely on sign extension in ">>" */
182  ASSERT_ALWAYS (sizeof (bytes) >= 4);
183
184  bp[-4] = bytes >> 24;
185  bp[-3] = bytes >> 16;
186  bp[-2] = bytes >> 8;
187  bp[-1] = bytes;
188  bp -= 4;
189
190  if (fp == 0)
191    fp = stdout;
192  if (fwrite (bp, ssize, 1, fp) != 1)
193    ssize = 0;
194
195  (*__gmp_free_func) (tp, tsize);
196  return ssize;
197}
Note: See TracBrowser for help on using the repository browser.