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-impl.h" 33 1.1 mrg #include "longlong.h" 34 1.1 mrg 35 1.1 mrg 36 1.1 mrg /* HTON_LIMB_STORE takes a normal host byte order limb and stores it as 37 1.1 mrg network byte order (ie. big endian). */ 38 1.1 mrg 39 1.1 mrg #if HAVE_LIMB_BIG_ENDIAN 40 1.1 mrg #define HTON_LIMB_STORE(dst, limb) do { *(dst) = (limb); } while (0) 41 1.1 mrg #endif 42 1.1 mrg 43 1.1 mrg #if HAVE_LIMB_LITTLE_ENDIAN 44 1.1 mrg #define HTON_LIMB_STORE(dst, limb) BSWAP_LIMB_STORE (dst, limb) 45 1.1 mrg #endif 46 1.1 mrg 47 1.1 mrg #ifndef HTON_LIMB_STORE 48 1.1 mrg #define HTON_LIMB_STORE(dst, limb) \ 49 1.1 mrg do { \ 50 1.1 mrg mp_limb_t __limb = (limb); \ 51 1.1 mrg char *__p = (char *) (dst); \ 52 1.1 mrg int __i; \ 53 1.1.1.3 mrg for (__i = 0; __i < GMP_LIMB_BYTES; __i++) \ 54 1.1.1.3 mrg __p[__i] = (char) (__limb >> ((GMP_LIMB_BYTES-1 - __i) * 8)); \ 55 1.1 mrg } while (0) 56 1.1 mrg #endif 57 1.1 mrg 58 1.1 mrg 59 1.1 mrg size_t 60 1.1 mrg mpz_out_raw (FILE *fp, mpz_srcptr x) 61 1.1 mrg { 62 1.1 mrg mp_size_t xsize, abs_xsize, bytes, i; 63 1.1 mrg mp_srcptr xp; 64 1.1 mrg char *tp, *bp; 65 1.1 mrg mp_limb_t xlimb; 66 1.1 mrg int zeros; 67 1.1 mrg size_t tsize, ssize; 68 1.1 mrg 69 1.1 mrg xsize = SIZ(x); 70 1.1 mrg abs_xsize = ABS (xsize); 71 1.1 mrg bytes = (abs_xsize * GMP_NUMB_BITS + 7) / 8; 72 1.1.1.3 mrg tsize = ROUND_UP_MULTIPLE ((unsigned) 4, GMP_LIMB_BYTES) + bytes; 73 1.1 mrg 74 1.1 mrg tp = __GMP_ALLOCATE_FUNC_TYPE (tsize, char); 75 1.1.1.3 mrg bp = tp + ROUND_UP_MULTIPLE ((unsigned) 4, GMP_LIMB_BYTES); 76 1.1 mrg 77 1.1 mrg if (bytes != 0) 78 1.1 mrg { 79 1.1 mrg bp += bytes; 80 1.1 mrg xp = PTR (x); 81 1.1 mrg i = abs_xsize; 82 1.1 mrg 83 1.1 mrg if (GMP_NAIL_BITS == 0) 84 1.1.1.2 mrg { 85 1.1.1.2 mrg /* reverse limb order, and byte swap if necessary */ 86 1.1 mrg #ifdef _CRAY 87 1.1.1.2 mrg _Pragma ("_CRI ivdep"); 88 1.1 mrg #endif 89 1.1.1.2 mrg do 90 1.1.1.2 mrg { 91 1.1.1.3 mrg bp -= GMP_LIMB_BYTES; 92 1.1.1.2 mrg xlimb = *xp; 93 1.1.1.2 mrg HTON_LIMB_STORE ((mp_ptr) bp, xlimb); 94 1.1.1.2 mrg xp++; 95 1.1.1.2 mrg } 96 1.1.1.2 mrg while (--i > 0); 97 1.1.1.2 mrg 98 1.1.1.2 mrg /* strip high zero bytes (without fetching from bp) */ 99 1.1.1.2 mrg count_leading_zeros (zeros, xlimb); 100 1.1.1.2 mrg zeros /= 8; 101 1.1.1.2 mrg bp += zeros; 102 1.1.1.2 mrg bytes -= zeros; 103 1.1.1.2 mrg } 104 1.1 mrg else 105 1.1.1.2 mrg { 106 1.1.1.2 mrg mp_limb_t new_xlimb; 107 1.1.1.2 mrg int bits; 108 1.1.1.2 mrg ASSERT_CODE (char *bp_orig = bp - bytes); 109 1.1.1.2 mrg 110 1.1.1.2 mrg ASSERT_ALWAYS (GMP_NUMB_BITS >= 8); 111 1.1.1.2 mrg 112 1.1.1.2 mrg bits = 0; 113 1.1.1.2 mrg xlimb = 0; 114 1.1.1.2 mrg for (;;) 115 1.1.1.2 mrg { 116 1.1.1.2 mrg while (bits >= 8) 117 1.1.1.2 mrg { 118 1.1.1.2 mrg ASSERT (bp > bp_orig); 119 1.1.1.2 mrg *--bp = xlimb & 0xFF; 120 1.1.1.2 mrg xlimb >>= 8; 121 1.1.1.2 mrg bits -= 8; 122 1.1.1.2 mrg } 123 1.1.1.2 mrg 124 1.1.1.2 mrg if (i == 0) 125 1.1.1.2 mrg break; 126 1.1.1.2 mrg 127 1.1.1.2 mrg new_xlimb = *xp++; 128 1.1.1.2 mrg i--; 129 1.1.1.2 mrg ASSERT (bp > bp_orig); 130 1.1.1.2 mrg *--bp = (xlimb | (new_xlimb << bits)) & 0xFF; 131 1.1.1.2 mrg xlimb = new_xlimb >> (8 - bits); 132 1.1.1.2 mrg bits += GMP_NUMB_BITS - 8; 133 1.1.1.2 mrg } 134 1.1.1.2 mrg 135 1.1.1.2 mrg if (bits != 0) 136 1.1.1.2 mrg { 137 1.1.1.2 mrg ASSERT (bp > bp_orig); 138 1.1.1.2 mrg *--bp = xlimb; 139 1.1.1.2 mrg } 140 1.1.1.2 mrg 141 1.1.1.2 mrg ASSERT (bp == bp_orig); 142 1.1.1.2 mrg while (*bp == 0) 143 1.1.1.2 mrg { 144 1.1.1.2 mrg bp++; 145 1.1.1.2 mrg bytes--; 146 1.1.1.2 mrg } 147 1.1.1.2 mrg } 148 1.1 mrg } 149 1.1 mrg 150 1.1 mrg /* total bytes to be written */ 151 1.1 mrg ssize = 4 + bytes; 152 1.1 mrg 153 1.1 mrg /* twos complement negative for the size value */ 154 1.1 mrg bytes = (xsize >= 0 ? bytes : -bytes); 155 1.1 mrg 156 1.1 mrg /* so we don't rely on sign extension in ">>" */ 157 1.1 mrg ASSERT_ALWAYS (sizeof (bytes) >= 4); 158 1.1 mrg 159 1.1 mrg bp[-4] = bytes >> 24; 160 1.1 mrg bp[-3] = bytes >> 16; 161 1.1 mrg bp[-2] = bytes >> 8; 162 1.1 mrg bp[-1] = bytes; 163 1.1 mrg bp -= 4; 164 1.1 mrg 165 1.1 mrg if (fp == 0) 166 1.1 mrg fp = stdout; 167 1.1 mrg if (fwrite (bp, ssize, 1, fp) != 1) 168 1.1 mrg ssize = 0; 169 1.1 mrg 170 1.1 mrg (*__gmp_free_func) (tp, tsize); 171 1.1 mrg return ssize; 172 1.1 mrg } 173