out_raw.c
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:4k
源码类别:

数学计算

开发平台:

Unix_Linux

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