out_raw.c revision 1.1.1.2 1 1.1 mrg /* mpz_out_raw -- write an mpz_t in raw format.
2 1.1 mrg
3 1.1 mrg Copyright 2001, 2002 Free Software Foundation, Inc.
4 1.1 mrg
5 1.1 mrg This file is part of the GNU MP Library.
6 1.1 mrg
7 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify
8 1.1 mrg it under the terms of the GNU Lesser General Public License as published by
9 1.1 mrg the Free Software Foundation; either version 3 of the License, or (at your
10 1.1 mrg option) any later version.
11 1.1 mrg
12 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
13 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 1.1 mrg License for more details.
16 1.1 mrg
17 1.1 mrg You should have received a copy of the GNU Lesser General Public License
18 1.1 mrg along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
19 1.1 mrg
20 1.1 mrg #include <stdio.h>
21 1.1 mrg #include "gmp.h"
22 1.1 mrg #include "gmp-impl.h"
23 1.1 mrg #include "longlong.h"
24 1.1 mrg
25 1.1 mrg
26 1.1 mrg /* HTON_LIMB_STORE takes a normal host byte order limb and stores it as
27 1.1 mrg network byte order (ie. big endian). */
28 1.1 mrg
29 1.1 mrg #if HAVE_LIMB_BIG_ENDIAN
30 1.1 mrg #define HTON_LIMB_STORE(dst, limb) do { *(dst) = (limb); } while (0)
31 1.1 mrg #endif
32 1.1 mrg
33 1.1 mrg #if HAVE_LIMB_LITTLE_ENDIAN
34 1.1 mrg #define HTON_LIMB_STORE(dst, limb) BSWAP_LIMB_STORE (dst, limb)
35 1.1 mrg #endif
36 1.1 mrg
37 1.1 mrg #ifndef HTON_LIMB_STORE
38 1.1 mrg #define HTON_LIMB_STORE(dst, limb) \
39 1.1 mrg do { \
40 1.1 mrg mp_limb_t __limb = (limb); \
41 1.1 mrg char *__p = (char *) (dst); \
42 1.1 mrg int __i; \
43 1.1 mrg for (__i = 0; __i < BYTES_PER_MP_LIMB; __i++) \
44 1.1 mrg __p[__i] = (char) (__limb >> ((BYTES_PER_MP_LIMB-1 - __i) * 8)); \
45 1.1 mrg } while (0)
46 1.1 mrg #endif
47 1.1 mrg
48 1.1 mrg
49 1.1 mrg size_t
50 1.1 mrg mpz_out_raw (FILE *fp, mpz_srcptr x)
51 1.1 mrg {
52 1.1 mrg mp_size_t xsize, abs_xsize, bytes, i;
53 1.1 mrg mp_srcptr xp;
54 1.1 mrg char *tp, *bp;
55 1.1 mrg mp_limb_t xlimb;
56 1.1 mrg int zeros;
57 1.1 mrg size_t tsize, ssize;
58 1.1 mrg
59 1.1 mrg xsize = SIZ(x);
60 1.1 mrg abs_xsize = ABS (xsize);
61 1.1 mrg bytes = (abs_xsize * GMP_NUMB_BITS + 7) / 8;
62 1.1 mrg tsize = ROUND_UP_MULTIPLE ((unsigned) 4, BYTES_PER_MP_LIMB) + bytes;
63 1.1 mrg
64 1.1 mrg tp = __GMP_ALLOCATE_FUNC_TYPE (tsize, char);
65 1.1 mrg bp = tp + ROUND_UP_MULTIPLE ((unsigned) 4, BYTES_PER_MP_LIMB);
66 1.1 mrg
67 1.1 mrg if (bytes != 0)
68 1.1 mrg {
69 1.1 mrg bp += bytes;
70 1.1 mrg xp = PTR (x);
71 1.1 mrg i = abs_xsize;
72 1.1 mrg
73 1.1 mrg if (GMP_NAIL_BITS == 0)
74 1.1.1.2 mrg {
75 1.1.1.2 mrg /* reverse limb order, and byte swap if necessary */
76 1.1 mrg #ifdef _CRAY
77 1.1.1.2 mrg _Pragma ("_CRI ivdep");
78 1.1 mrg #endif
79 1.1.1.2 mrg do
80 1.1.1.2 mrg {
81 1.1.1.2 mrg bp -= BYTES_PER_MP_LIMB;
82 1.1.1.2 mrg xlimb = *xp;
83 1.1.1.2 mrg HTON_LIMB_STORE ((mp_ptr) bp, xlimb);
84 1.1.1.2 mrg xp++;
85 1.1.1.2 mrg }
86 1.1.1.2 mrg while (--i > 0);
87 1.1.1.2 mrg
88 1.1.1.2 mrg /* strip high zero bytes (without fetching from bp) */
89 1.1.1.2 mrg count_leading_zeros (zeros, xlimb);
90 1.1.1.2 mrg zeros /= 8;
91 1.1.1.2 mrg bp += zeros;
92 1.1.1.2 mrg bytes -= zeros;
93 1.1.1.2 mrg }
94 1.1 mrg else
95 1.1.1.2 mrg {
96 1.1.1.2 mrg mp_limb_t new_xlimb;
97 1.1.1.2 mrg int bits;
98 1.1.1.2 mrg ASSERT_CODE (char *bp_orig = bp - bytes);
99 1.1.1.2 mrg
100 1.1.1.2 mrg ASSERT_ALWAYS (GMP_NUMB_BITS >= 8);
101 1.1.1.2 mrg
102 1.1.1.2 mrg bits = 0;
103 1.1.1.2 mrg xlimb = 0;
104 1.1.1.2 mrg for (;;)
105 1.1.1.2 mrg {
106 1.1.1.2 mrg while (bits >= 8)
107 1.1.1.2 mrg {
108 1.1.1.2 mrg ASSERT (bp > bp_orig);
109 1.1.1.2 mrg *--bp = xlimb & 0xFF;
110 1.1.1.2 mrg xlimb >>= 8;
111 1.1.1.2 mrg bits -= 8;
112 1.1.1.2 mrg }
113 1.1.1.2 mrg
114 1.1.1.2 mrg if (i == 0)
115 1.1.1.2 mrg break;
116 1.1.1.2 mrg
117 1.1.1.2 mrg new_xlimb = *xp++;
118 1.1.1.2 mrg i--;
119 1.1.1.2 mrg ASSERT (bp > bp_orig);
120 1.1.1.2 mrg *--bp = (xlimb | (new_xlimb << bits)) & 0xFF;
121 1.1.1.2 mrg xlimb = new_xlimb >> (8 - bits);
122 1.1.1.2 mrg bits += GMP_NUMB_BITS - 8;
123 1.1.1.2 mrg }
124 1.1.1.2 mrg
125 1.1.1.2 mrg if (bits != 0)
126 1.1.1.2 mrg {
127 1.1.1.2 mrg ASSERT (bp > bp_orig);
128 1.1.1.2 mrg *--bp = xlimb;
129 1.1.1.2 mrg }
130 1.1.1.2 mrg
131 1.1.1.2 mrg ASSERT (bp == bp_orig);
132 1.1.1.2 mrg while (*bp == 0)
133 1.1.1.2 mrg {
134 1.1.1.2 mrg bp++;
135 1.1.1.2 mrg bytes--;
136 1.1.1.2 mrg }
137 1.1.1.2 mrg }
138 1.1 mrg }
139 1.1 mrg
140 1.1 mrg /* total bytes to be written */
141 1.1 mrg ssize = 4 + bytes;
142 1.1 mrg
143 1.1 mrg /* twos complement negative for the size value */
144 1.1 mrg bytes = (xsize >= 0 ? bytes : -bytes);
145 1.1 mrg
146 1.1 mrg /* so we don't rely on sign extension in ">>" */
147 1.1 mrg ASSERT_ALWAYS (sizeof (bytes) >= 4);
148 1.1 mrg
149 1.1 mrg bp[-4] = bytes >> 24;
150 1.1 mrg bp[-3] = bytes >> 16;
151 1.1 mrg bp[-2] = bytes >> 8;
152 1.1 mrg bp[-1] = bytes;
153 1.1 mrg bp -= 4;
154 1.1 mrg
155 1.1 mrg if (fp == 0)
156 1.1 mrg fp = stdout;
157 1.1 mrg if (fwrite (bp, ssize, 1, fp) != 1)
158 1.1 mrg ssize = 0;
159 1.1 mrg
160 1.1 mrg (*__gmp_free_func) (tp, tsize);
161 1.1 mrg return ssize;
162 1.1 mrg }
163