~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to gmp3/mpz/ior.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

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