github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpz/export.c (about)

     1  /* mpz_export -- create word data from mpz.
     2  
     3  Copyright 2002, 2003, 2012 Free Software Foundation, Inc.
     4  
     5  This file is part of the GNU MP Library.
     6  
     7  The GNU MP Library is free software; you can redistribute it and/or modify
     8  it under the terms of either:
     9  
    10    * the GNU Lesser General Public License as published by the Free
    11      Software Foundation; either version 3 of the License, or (at your
    12      option) any later version.
    13  
    14  or
    15  
    16    * the GNU General Public License as published by the Free Software
    17      Foundation; either version 2 of the License, or (at your option) any
    18      later version.
    19  
    20  or both in parallel, as here.
    21  
    22  The GNU MP Library is distributed in the hope that it will be useful, but
    23  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    24  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    25  for more details.
    26  
    27  You should have received copies of the GNU General Public License and the
    28  GNU Lesser General Public License along with the GNU MP Library.  If not,
    29  see https://www.gnu.org/licenses/.  */
    30  
    31  #include <stdio.h>  /* for NULL */
    32  #include "gmp.h"
    33  #include "gmp-impl.h"
    34  #include "longlong.h"
    35  
    36  
    37  #if HAVE_LIMB_BIG_ENDIAN
    38  #define HOST_ENDIAN     1
    39  #endif
    40  #if HAVE_LIMB_LITTLE_ENDIAN
    41  #define HOST_ENDIAN     (-1)
    42  #endif
    43  #ifndef HOST_ENDIAN
    44  static const mp_limb_t  endian_test = (CNST_LIMB(1) << (GMP_LIMB_BITS-7)) - 1;
    45  #define HOST_ENDIAN     (* (signed char *) &endian_test)
    46  #endif
    47  
    48  void *
    49  mpz_export (void *data, size_t *countp, int order,
    50  	    size_t size, int endian, size_t nail, mpz_srcptr z)
    51  {
    52    mp_size_t      zsize;
    53    mp_srcptr      zp;
    54    size_t         count, dummy;
    55    unsigned long  numb;
    56    unsigned       align;
    57  
    58    ASSERT (order == 1 || order == -1);
    59    ASSERT (endian == 1 || endian == 0 || endian == -1);
    60    ASSERT (nail <= 8*size);
    61    ASSERT (nail <  8*size || SIZ(z) == 0); /* nail < 8*size+(SIZ(z)==0) */
    62  
    63    if (countp == NULL)
    64      countp = &dummy;
    65  
    66    zsize = SIZ(z);
    67    if (zsize == 0)
    68      {
    69        *countp = 0;
    70        return data;
    71      }
    72  
    73    zsize = ABS (zsize);
    74    zp = PTR(z);
    75    numb = 8*size - nail;
    76    MPN_SIZEINBASE_2EXP (count, zp, zsize, numb);
    77    *countp = count;
    78  
    79    if (data == NULL)
    80      data = (*__gmp_allocate_func) (count*size);
    81  
    82    if (endian == 0)
    83      endian = HOST_ENDIAN;
    84  
    85    align = ((char *) data - (char *) NULL) % sizeof (mp_limb_t);
    86  
    87    if (nail == GMP_NAIL_BITS)
    88      {
    89        if (size == sizeof (mp_limb_t) && align == 0)
    90  	{
    91  	  if (order == -1 && endian == HOST_ENDIAN)
    92  	    {
    93  	      MPN_COPY ((mp_ptr) data, zp, (mp_size_t) count);
    94  	      return data;
    95  	    }
    96  	  if (order == 1 && endian == HOST_ENDIAN)
    97  	    {
    98  	      MPN_REVERSE ((mp_ptr) data, zp, (mp_size_t) count);
    99  	      return data;
   100  	    }
   101  
   102  	  if (order == -1 && endian == -HOST_ENDIAN)
   103  	    {
   104  	      MPN_BSWAP ((mp_ptr) data, zp, (mp_size_t) count);
   105  	      return data;
   106  	    }
   107  	  if (order == 1 && endian == -HOST_ENDIAN)
   108  	    {
   109  	      MPN_BSWAP_REVERSE ((mp_ptr) data, zp, (mp_size_t) count);
   110  	      return data;
   111  	    }
   112  	}
   113      }
   114  
   115    {
   116      mp_limb_t      limb, wbitsmask;
   117      size_t         i, numb;
   118      mp_size_t      j, wbytes, woffset;
   119      unsigned char  *dp;
   120      int            lbits, wbits;
   121      mp_srcptr      zend;
   122  
   123      numb = size * 8 - nail;
   124  
   125      /* whole bytes per word */
   126      wbytes = numb / 8;
   127  
   128      /* possible partial byte */
   129      wbits = numb % 8;
   130      wbitsmask = (CNST_LIMB(1) << wbits) - 1;
   131  
   132      /* offset to get to the next word */
   133      woffset = (endian >= 0 ? size : - (mp_size_t) size)
   134        + (order < 0 ? size : - (mp_size_t) size);
   135  
   136      /* least significant byte */
   137      dp = (unsigned char *) data
   138        + (order >= 0 ? (count-1)*size : 0) + (endian >= 0 ? size-1 : 0);
   139  
   140  #define EXTRACT(N, MASK)                                \
   141      do {                                                \
   142        if (lbits >= (N))                                 \
   143          {                                               \
   144            *dp = limb MASK;                              \
   145            limb >>= (N);                                 \
   146            lbits -= (N);                                 \
   147          }                                               \
   148        else                                              \
   149          {                                               \
   150            mp_limb_t  newlimb;                           \
   151            newlimb = (zp == zend ? 0 : *zp++);           \
   152            *dp = (limb | (newlimb << lbits)) MASK;       \
   153            limb = newlimb >> ((N)-lbits);                \
   154            lbits += GMP_NUMB_BITS - (N);                 \
   155          }                                               \
   156      } while (0)
   157  
   158      zend = zp + zsize;
   159      lbits = 0;
   160      limb = 0;
   161      for (i = 0; i < count; i++)
   162        {
   163  	for (j = 0; j < wbytes; j++)
   164  	  {
   165  	    EXTRACT (8, + 0);
   166  	    dp -= endian;
   167  	  }
   168  	if (wbits != 0)
   169  	  {
   170  	    EXTRACT (wbits, & wbitsmask);
   171  	    dp -= endian;
   172  	    j++;
   173  	  }
   174  	for ( ; j < size; j++)
   175  	  {
   176  	    *dp = '\0';
   177  	    dp -= endian;
   178  	  }
   179  	dp += woffset;
   180        }
   181  
   182      ASSERT (zp == PTR(z) + ABSIZ(z));
   183  
   184      /* low byte of word after most significant */
   185      ASSERT (dp == (unsigned char *) data
   186  	    + (order < 0 ? count*size : - (mp_size_t) size)
   187  	    + (endian >= 0 ? (mp_size_t) size - 1 : 0));
   188    }
   189    return data;
   190  }