[BACK]Return to import.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gmp / mpz

Annotation of OpenXM_contrib/gmp/mpz/import.c, Revision 1.1.1.1

1.1       ohara       1: /* mpz_import -- set mpz from word data.
                      2:
                      3: Copyright 2002 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 the GNU Lesser General Public License as published by
                      9: the Free Software Foundation; either version 2.1 of the License, or (at your
                     10: option) any later version.
                     11:
                     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.
                     16:
                     17: You should have received a copy of the GNU Lesser General Public License
                     18: along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
                     19: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
                     20: MA 02111-1307, USA. */
                     21:
                     22: #include <stdio.h>  /* for NULL */
                     23: #include "gmp.h"
                     24: #include "gmp-impl.h"
                     25:
                     26:
                     27:
                     28: #if HAVE_LIMB_BIG_ENDIAN
                     29: #define HOST_ENDIAN     1
                     30: #endif
                     31: #if HAVE_LIMB_LITTLE_ENDIAN
                     32: #define HOST_ENDIAN     (-1)
                     33: #endif
                     34: #ifndef HOST_ENDIAN
                     35: static const mp_limb_t  endian_test = (CNST_LIMB(1) << (GMP_LIMB_BITS-7)) - 1;
                     36: #define HOST_ENDIAN     (* (signed char *) &endian_test)
                     37: #endif
                     38:
                     39:
                     40: void
                     41: mpz_import (mpz_ptr z, size_t count, int order,
                     42:             size_t size, int endian, size_t nail, const void *data)
                     43: {
                     44:   mp_size_t  zsize;
                     45:   mp_ptr     zp;
                     46:
                     47:   ASSERT (order == 1 || order == -1);
                     48:   ASSERT (endian == 1 || endian == 0 || endian == -1);
                     49:   ASSERT (nail <= 8*size);
                     50:
                     51:   zsize = (count * (8*size - nail) + GMP_NUMB_BITS-1) / GMP_NUMB_BITS;
                     52:   MPZ_REALLOC (z, zsize);
                     53:   zp = PTR(z);
                     54:
                     55:   if (endian == 0)
                     56:     endian = HOST_ENDIAN;
                     57:
                     58:   /* Can't use these special cases with nails currently, since they don't
                     59:      mask out the nail bits in the input data.  */
                     60:   if (nail == 0 && GMP_NAIL_BITS == 0)
                     61:     {
                     62:       unsigned  align = ((char *) data - (char *) NULL) % sizeof (mp_limb_t);
                     63:
                     64:       if (order == -1
                     65:           && size == sizeof (mp_limb_t)
                     66:           && endian == HOST_ENDIAN
                     67:           && align == 0)
                     68:         {
                     69:           MPN_COPY (zp, (mp_srcptr) data, (mp_size_t) count);
                     70:           goto done;
                     71:         }
                     72:
                     73:       if (order == -1
                     74:           && size == sizeof (mp_limb_t)
                     75:           && endian == - HOST_ENDIAN
                     76:           && align == 0)
                     77:         {
                     78:           MPN_BSWAP (zp, (mp_srcptr) data, (mp_size_t) count);
                     79:           goto done;
                     80:         }
                     81:
                     82:       if (order == 1
                     83:           && size == sizeof (mp_limb_t)
                     84:           && endian == HOST_ENDIAN
                     85:           && align == 0)
                     86:         {
                     87:           MPN_REVERSE (zp, (mp_srcptr) data, (mp_size_t) count);
                     88:           goto done;
                     89:         }
                     90:     }
                     91:
                     92:   {
                     93:     mp_limb_t      limb, byte, wbitsmask;
                     94:     size_t         i, j, numb, wbytes;
                     95:     mp_size_t      woffset;
                     96:     unsigned char  *dp;
                     97:     int            lbits, wbits;
                     98:
                     99:     numb = size * 8 - nail;
                    100:
                    101:     /* whole bytes to process */
                    102:     wbytes = numb / 8;
                    103:
                    104:     /* partial byte to process */
                    105:     wbits = numb % 8;
                    106:     wbitsmask = (CNST_LIMB(1) << wbits) - 1;
                    107:
                    108:     /* offset to get to the next word after processing wbytes and wbits */
                    109:     woffset = (numb + 7) / 8;
                    110:     woffset = (endian >= 0 ? woffset : -woffset)
                    111:       + (order < 0 ? size : - (mp_size_t) size);
                    112:
                    113:     /* least significant byte */
                    114:     dp = (unsigned char *) data
                    115:       + (order >= 0 ? (count-1)*size : 0) + (endian >= 0 ? size-1 : 0);
                    116:
                    117: #define ACCUMULATE(N)                                   \
                    118:     do {                                                \
                    119:       ASSERT (lbits < GMP_NUMB_BITS);                   \
                    120:       ASSERT (limb <= (CNST_LIMB(1) << lbits) - 1);     \
                    121:                                                         \
                    122:       limb |= (mp_limb_t) byte << lbits;                \
                    123:       lbits += (N);                                     \
                    124:       if (lbits >= GMP_NUMB_BITS)                       \
                    125:         {                                               \
                    126:           *zp++ = limb & GMP_NUMB_MASK;                 \
                    127:           lbits -= GMP_NUMB_BITS;                       \
                    128:           ASSERT (lbits < (N));                         \
                    129:           limb = byte >> ((N) - lbits);                 \
                    130:         }                                               \
                    131:     } while (0)
                    132:
                    133:     limb = 0;
                    134:     lbits = 0;
                    135:     for (i = 0; i < count; i++)
                    136:       {
                    137:         for (j = 0; j < wbytes; j++)
                    138:           {
                    139:             byte = *dp;
                    140:             dp -= endian;
                    141:             ACCUMULATE (8);
                    142:           }
                    143:         if (wbits != 0)
                    144:           {
                    145:             byte = *dp & wbitsmask;
                    146:             dp -= endian;
                    147:             ACCUMULATE (wbits);
                    148:           }
                    149:         dp += woffset;
                    150:       }
                    151:
                    152:     if (lbits != 0)
                    153:       {
                    154:         ASSERT (lbits <= GMP_NUMB_BITS);
                    155:         ASSERT_LIMB (limb);
                    156:         *zp++ = limb;
                    157:       }
                    158:
                    159:     ASSERT (zp == PTR(z) + zsize);
                    160:
                    161:     /* low byte of word after most significant */
                    162:     ASSERT (dp == (unsigned char *) data
                    163:             + (order < 0 ? count*size : - (mp_size_t) size)
                    164:             + (endian >= 0 ? (mp_size_t) size - 1 : 0));
                    165:
                    166:   }
                    167:
                    168:  done:
                    169:   zp = PTR(z);
                    170:   MPN_NORMALIZE (zp, zsize);
                    171:   SIZ(z) = zsize;
                    172: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>