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