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

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

1.1       maekawa     1: /* mpz_ior -- Logical inclusive or.
                      2:
                      3: Copyright (C) 1991, 1993, 1994, 1996 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 Library General Public License as published by
                      9: the Free Software Foundation; either version 2 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 Library General Public
                     15: License for more details.
                     16:
                     17: You should have received a copy of the GNU Library 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 "gmp.h"
                     23: #include "gmp-impl.h"
                     24:
                     25: void
                     26: #if __STDC__
                     27: mpz_ior (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2)
                     28: #else
                     29: mpz_ior (res, op1, op2)
                     30:      mpz_ptr res;
                     31:      mpz_srcptr op1;
                     32:      mpz_srcptr op2;
                     33: #endif
                     34: {
                     35:   mp_srcptr op1_ptr, op2_ptr;
                     36:   mp_size_t op1_size, op2_size;
                     37:   mp_ptr res_ptr;
                     38:   mp_size_t res_size;
                     39:   mp_size_t i;
                     40:   TMP_DECL (marker);
                     41:
                     42:   TMP_MARK (marker);
                     43:   op1_size = op1->_mp_size;
                     44:   op2_size = op2->_mp_size;
                     45:
                     46:   op1_ptr = op1->_mp_d;
                     47:   op2_ptr = op2->_mp_d;
                     48:   res_ptr = res->_mp_d;
                     49:
                     50:   if (op1_size >= 0)
                     51:     {
                     52:       if (op2_size >= 0)
                     53:        {
                     54:          if (op1_size >= op2_size)
                     55:            {
                     56:              if (res->_mp_alloc < op1_size)
                     57:                {
                     58:                  _mpz_realloc (res, op1_size);
                     59:                  op1_ptr = op1->_mp_d;
                     60:                  op2_ptr = op2->_mp_d;
                     61:                  res_ptr = res->_mp_d;
                     62:                }
                     63:
                     64:              if (res_ptr != op1_ptr)
                     65:                MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
                     66:                          op1_size - op2_size);
                     67:              for (i = op2_size - 1; i >= 0; i--)
                     68:                res_ptr[i] = op1_ptr[i] | op2_ptr[i];
                     69:              res_size = op1_size;
                     70:            }
                     71:          else
                     72:            {
                     73:              if (res->_mp_alloc < op2_size)
                     74:                {
                     75:                  _mpz_realloc (res, op2_size);
                     76:                  op1_ptr = op1->_mp_d;
                     77:                  op2_ptr = op2->_mp_d;
                     78:                  res_ptr = res->_mp_d;
                     79:                }
                     80:
                     81:              if (res_ptr != op2_ptr)
                     82:                MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size,
                     83:                          op2_size - op1_size);
                     84:              for (i = op1_size - 1; i >= 0; i--)
                     85:                res_ptr[i] = op1_ptr[i] | op2_ptr[i];
                     86:              res_size = op2_size;
                     87:            }
                     88:
                     89:          res->_mp_size = res_size;
                     90:          return;
                     91:        }
                     92:       else /* op2_size < 0 */
                     93:        {
                     94:          /* Fall through to the code at the end of the function.  */
                     95:        }
                     96:     }
                     97:   else
                     98:     {
                     99:       if (op2_size < 0)
                    100:        {
                    101:          mp_ptr opx;
                    102:          mp_limb_t cy;
                    103:
                    104:          /* Both operands are negative, so will be the result.
                    105:             -((-OP1) | (-OP2)) = -(~(OP1 - 1) | ~(OP2 - 1)) =
                    106:             = ~(~(OP1 - 1) | ~(OP2 - 1)) + 1 =
                    107:             = ((OP1 - 1) & (OP2 - 1)) + 1      */
                    108:
                    109:          op1_size = -op1_size;
                    110:          op2_size = -op2_size;
                    111:
                    112:          res_size = MIN (op1_size, op2_size);
                    113:
                    114:          /* Possible optimization: Decrease mpn_sub precision,
                    115:             as we won't use the entire res of both.  */
                    116:          opx = (mp_ptr) TMP_ALLOC (res_size * BYTES_PER_MP_LIMB);
                    117:          mpn_sub_1 (opx, op1_ptr, res_size, (mp_limb_t) 1);
                    118:          op1_ptr = opx;
                    119:
                    120:          opx = (mp_ptr) TMP_ALLOC (res_size * BYTES_PER_MP_LIMB);
                    121:          mpn_sub_1 (opx, op2_ptr, res_size, (mp_limb_t) 1);
                    122:          op2_ptr = opx;
                    123:
                    124:          if (res->_mp_alloc < res_size)
                    125:            {
                    126:              _mpz_realloc (res, res_size);
                    127:              res_ptr = res->_mp_d;
                    128:              /* Don't re-read OP1_PTR and OP2_PTR.  They point to
                    129:                 temporary space--never to the space RES->_mp_D used
                    130:                 to point to before reallocation.  */
                    131:            }
                    132:
                    133:          /* First loop finds the size of the result.  */
                    134:          for (i = res_size - 1; i >= 0; i--)
                    135:            if ((op1_ptr[i] & op2_ptr[i]) != 0)
                    136:              break;
                    137:          res_size = i + 1;
                    138:
                    139:          if (res_size != 0)
                    140:            {
                    141:              /* Second loop computes the real result.  */
                    142:              for (i = res_size - 1; i >= 0; i--)
                    143:                res_ptr[i] = op1_ptr[i] & op2_ptr[i];
                    144:
                    145:              cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
                    146:              if (cy)
                    147:                {
                    148:                  res_ptr[res_size] = cy;
                    149:                  res_size++;
                    150:                }
                    151:            }
                    152:          else
                    153:            {
                    154:              res_ptr[0] = 1;
                    155:              res_size = 1;
                    156:            }
                    157:
                    158:          res->_mp_size = -res_size;
                    159:          TMP_FREE (marker);
                    160:          return;
                    161:        }
                    162:       else
                    163:        {
                    164:          /* We should compute -OP1 | OP2.  Swap OP1 and OP2 and fall
                    165:             through to the code that handles OP1 | -OP2.  */
                    166:          {mpz_srcptr t = op1; op1 = op2; op2 = t;}
                    167:          {mp_srcptr t = op1_ptr; op1_ptr = op2_ptr; op2_ptr = t;}
                    168:          {mp_size_t t = op1_size; op1_size = op2_size; op2_size = t;}
                    169:        }
                    170:     }
                    171:
                    172:   {
                    173:     mp_ptr opx;
                    174:     mp_limb_t cy;
                    175:     mp_size_t res_alloc;
                    176:     mp_size_t count;
                    177:
                    178:     /* Operand 2 negative, so will be the result.
                    179:        -(OP1 | (-OP2)) = -(OP1 | ~(OP2 - 1)) =
                    180:        = ~(OP1 | ~(OP2 - 1)) + 1 =
                    181:        = (~OP1 & (OP2 - 1)) + 1      */
                    182:
                    183:     op2_size = -op2_size;
                    184:
                    185:     res_alloc = op2_size;
                    186:
                    187:     opx = (mp_ptr) TMP_ALLOC (op2_size * BYTES_PER_MP_LIMB);
                    188:     mpn_sub_1 (opx, op2_ptr, op2_size, (mp_limb_t) 1);
                    189:     op2_ptr = opx;
                    190:
                    191:     if (res->_mp_alloc < res_alloc)
                    192:       {
                    193:        _mpz_realloc (res, res_alloc);
                    194:        op1_ptr = op1->_mp_d;
                    195:        res_ptr = res->_mp_d;
                    196:        /* Don't re-read OP2_PTR.  It points to temporary space--never
                    197:           to the space RES->_mp_D used to point to before reallocation.  */
                    198:       }
                    199:
                    200:     if (op1_size >= op2_size)
                    201:       {
                    202:        /* We can just ignore the part of OP1 that stretches above OP2,
                    203:           because the result limbs are zero there.  */
                    204:
                    205:        /* First loop finds the size of the result.  */
                    206:        for (i = op2_size - 1; i >= 0; i--)
                    207:          if ((~op1_ptr[i] & op2_ptr[i]) != 0)
                    208:            break;
                    209:        res_size = i + 1;
                    210:        count = res_size;
                    211:       }
                    212:     else
                    213:       {
                    214:        res_size = op2_size;
                    215:
                    216:        /* Copy the part of OP2 that stretches above OP1, to RES.  */
                    217:        MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, op2_size - op1_size);
                    218:        count = op1_size;
                    219:       }
                    220:
                    221:     if (res_size != 0)
                    222:       {
                    223:        /* Second loop computes the real result.  */
                    224:        for (i = count - 1; i >= 0; i--)
                    225:          res_ptr[i] = ~op1_ptr[i] & op2_ptr[i];
                    226:
                    227:        cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
                    228:        if (cy)
                    229:          {
                    230:            res_ptr[res_size] = cy;
                    231:            res_size++;
                    232:          }
                    233:       }
                    234:     else
                    235:       {
                    236:        res_ptr[0] = 1;
                    237:        res_size = 1;
                    238:       }
                    239:
                    240:     res->_mp_size = -res_size;
                    241:   }
                    242:   TMP_FREE (marker);
                    243: }

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