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