(root)/
gmp-6.3.0/
mpz/
ior.c
       1  /* mpz_ior -- Logical inclusive or.
       2  
       3  Copyright 1991, 1993, 1994, 1996, 1997, 2000, 2001, 2005, 2012, 2013,
       4  2015-2018 Free Software Foundation, Inc.
       5  
       6  This file is part of the GNU MP Library.
       7  
       8  The GNU MP Library is free software; you can redistribute it and/or modify
       9  it under the terms of either:
      10  
      11    * the GNU Lesser General Public License as published by the Free
      12      Software Foundation; either version 3 of the License, or (at your
      13      option) any later version.
      14  
      15  or
      16  
      17    * the GNU General Public License as published by the Free Software
      18      Foundation; either version 2 of the License, or (at your option) any
      19      later version.
      20  
      21  or both in parallel, as here.
      22  
      23  The GNU MP Library is distributed in the hope that it will be useful, but
      24  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      25  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      26  for more details.
      27  
      28  You should have received copies of the GNU General Public License and the
      29  GNU Lesser General Public License along with the GNU MP Library.  If not,
      30  see https://www.gnu.org/licenses/.  */
      31  
      32  #include "gmp-impl.h"
      33  
      34  void
      35  mpz_ior (mpz_ptr res, mpz_srcptr op1, mpz_srcptr op2)
      36  {
      37    mp_srcptr op1_ptr, op2_ptr;
      38    mp_size_t op1_size, op2_size;
      39    mp_ptr res_ptr;
      40    mp_size_t res_size;
      41    mp_size_t i;
      42  
      43    op1_size = SIZ(op1);
      44    op2_size = SIZ(op2);
      45  
      46    if (op1_size < op2_size)
      47      {
      48        MPZ_SRCPTR_SWAP (op1, op2);
      49        MP_SIZE_T_SWAP (op1_size, op2_size);
      50      }
      51  
      52    op1_ptr = PTR(op1);
      53    res_ptr = PTR(res);
      54  
      55    if (op2_size >= 0)
      56      {
      57        if (res_ptr != op1_ptr)
      58  	{
      59  	  res_ptr = MPZ_REALLOC (res, op1_size);
      60  	  /* No overlapping possible: op1_ptr = PTR(op1); */
      61  	  MPN_COPY (res_ptr + op2_size, op1_ptr + op2_size,
      62  		    op1_size - op2_size);
      63  	}
      64        if (LIKELY (op2_size != 0))
      65  	mpn_ior_n (res_ptr, op1_ptr, PTR(op2), op2_size);
      66  
      67        SIZ(res) = op1_size;
      68      }
      69    else
      70      {
      71        mp_ptr opx;
      72        TMP_DECL;
      73  
      74        TMP_MARK;
      75        if (op1_size < 0)
      76  	{
      77  	  mp_ptr opy;
      78  
      79  	  /* Both operands are negative, so will be the result.
      80  	     -((-OP1) | (-OP2)) = -(~(OP1 - 1) | ~(OP2 - 1)) =
      81  	     = ~(~(OP1 - 1) | ~(OP2 - 1)) + 1 =
      82  	     = ((OP1 - 1) & (OP2 - 1)) + 1      */
      83  
      84  	  res_size = -op1_size;
      85  
      86  	  /* Possible optimization: Decrease mpn_sub precision,
      87  	     as we won't use the entire res of both.  */
      88  	  TMP_ALLOC_LIMBS_2 (opx, res_size, opy, res_size);
      89  	  mpn_sub_1 (opx, op1_ptr, res_size, (mp_limb_t) 1);
      90  	  op1_ptr = opx;
      91  
      92  	  mpn_sub_1 (opy, PTR(op2), res_size, (mp_limb_t) 1);
      93  	  op2_ptr = opy;
      94  
      95  	  /* First loop finds the size of the result.  */
      96  	  for (i = res_size; --i >= 0;)
      97  	    if ((op1_ptr[i] & op2_ptr[i]) != 0)
      98  	      break;
      99  	  res_size = i + 1;
     100  
     101  	  res_ptr = MPZ_NEWALLOC (res, res_size + 1);
     102  
     103  	  if (res_size != 0)
     104  	    {
     105  	      /* Second loop computes the real result.  */
     106  	      mpn_and_n (res_ptr, op1_ptr, op2_ptr, res_size);
     107  
     108  	      res_ptr[res_size] = 0;
     109  	      MPN_INCR_U (res_ptr, res_size + 1, 1);
     110  	      res_size += res_ptr[res_size];
     111  	    }
     112  	  else
     113  	    {
     114  	      res_ptr[0] = 1;
     115  	      res_size = 1;
     116  	    }
     117  
     118  	  SIZ(res) = -res_size;
     119  	}
     120        else
     121  	{
     122  	  mp_limb_t cy;
     123  	  mp_size_t count;
     124  
     125  	  /* Operand 2 negative, so will be the result.
     126  	     -(OP1 | (-OP2)) = -(OP1 | ~(OP2 - 1)) =
     127  	     = ~(OP1 | ~(OP2 - 1)) + 1 =
     128  	     = (~OP1 & (OP2 - 1)) + 1      */
     129  
     130  	  op2_size = -op2_size;
     131  
     132  	  res_ptr = MPZ_REALLOC (res, op2_size);
     133  	  op1_ptr = PTR(op1);
     134  
     135  	  opx = TMP_ALLOC_LIMBS (op2_size);
     136  	  mpn_sub_1 (opx, PTR(op2), op2_size, (mp_limb_t) 1);
     137  	  op2_ptr = opx;
     138  	  op2_size -= op2_ptr[op2_size - 1] == 0;
     139  
     140  	  if (op1_size >= op2_size)
     141  	    {
     142  	      /* We can just ignore the part of OP1 that stretches above OP2,
     143  		 because the result limbs are zero there.  */
     144  
     145  	      /* First loop finds the size of the result.  */
     146  	      for (i = op2_size; --i >= 0;)
     147  		if ((~op1_ptr[i] & op2_ptr[i]) != 0)
     148  		  break;
     149  	      res_size = i + 1;
     150  	      count = res_size;
     151  	    }
     152  	  else
     153  	    {
     154  	      res_size = op2_size;
     155  
     156  	      /* Copy the part of OP2 that stretches above OP1, to RES.  */
     157  	      MPN_COPY (res_ptr + op1_size, op2_ptr + op1_size, op2_size - op1_size);
     158  	      count = op1_size;
     159  	    }
     160  
     161  	  if (res_size != 0)
     162  	    {
     163  	      /* Second loop computes the real result.  */
     164  	      if (LIKELY (count != 0))
     165  		mpn_andn_n (res_ptr, op2_ptr, op1_ptr, count);
     166  
     167  	      cy = mpn_add_1 (res_ptr, res_ptr, res_size, (mp_limb_t) 1);
     168  	      if (cy)
     169  		{
     170  		  res_ptr[res_size] = cy;
     171  		  ++res_size;
     172  		}
     173  	    }
     174  	  else
     175  	    {
     176  	      res_ptr[0] = 1;
     177  	      res_size = 1;
     178  	    }
     179  
     180  	  SIZ(res) = -res_size;
     181  	}
     182        TMP_FREE;
     183      }
     184  }