Tizen 2.1 base
[framework/security/gnupg.git] / mpi / mpi-bit.c
1 /* mpi-bit.c  -  MPI bit level fucntions
2  * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <assert.h>
26 #include "mpi-internal.h"
27 #include "longlong.h"
28
29
30 #ifdef MPI_INTERNAL_NEED_CLZ_TAB
31 #ifdef __STDC__
32 const
33 #endif
34 unsigned char
35 __clz_tab[] =
36 {
37   0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
38   6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
39   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
40   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
41   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
42   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
43   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
44   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
45 };
46 #endif
47
48
49 #define A_LIMB_1 ((mpi_limb_t)1)
50
51
52 /****************
53  * Sometimes we have MSL (most significant limbs) which are 0;
54  * this is for some reasons not good, so this function removes them.
55  */
56 void
57 mpi_normalize( MPI a )
58 {
59     if( mpi_is_opaque (a) )
60         return;
61
62     for( ; a->nlimbs && !a->d[a->nlimbs-1]; a->nlimbs-- )
63         ;
64 }
65
66
67
68 /****************
69  * Return the number of bits in A.
70  */
71 unsigned
72 mpi_get_nbits( MPI a )
73 {
74     unsigned n;
75
76     mpi_normalize( a );
77     if( a->nlimbs ) {
78         mpi_limb_t alimb = a->d[a->nlimbs-1];
79         if( alimb )
80             count_leading_zeros( n, alimb );
81         else
82             n = BITS_PER_MPI_LIMB;
83         n = BITS_PER_MPI_LIMB - n + (a->nlimbs-1) * BITS_PER_MPI_LIMB;
84     }
85     else
86         n = 0;
87     return n;
88 }
89
90
91 /****************
92  * Test whether bit N is set.
93  */
94 int
95 mpi_test_bit( MPI a, unsigned n )
96 {
97     unsigned limbno, bitno;
98     mpi_limb_t limb;
99
100     limbno = n / BITS_PER_MPI_LIMB;
101     bitno  = n % BITS_PER_MPI_LIMB;
102
103     if( limbno >= a->nlimbs )
104         return 0; /* too far left: this is a 0 */
105     limb = a->d[limbno];
106     return (limb & (A_LIMB_1 << bitno))? 1: 0;
107 }
108
109
110 /****************
111  * Set bit N of A.
112  */
113 void
114 mpi_set_bit( MPI a, unsigned n )
115 {
116     unsigned limbno, bitno;
117
118     limbno = n / BITS_PER_MPI_LIMB;
119     bitno  = n % BITS_PER_MPI_LIMB;
120
121     if( limbno >= a->nlimbs ) { /* resize */
122         if( a->alloced >= limbno )
123             mpi_resize(a, limbno+1 );
124         a->nlimbs = limbno+1;
125     }
126     a->d[limbno] |= (A_LIMB_1<<bitno);
127 }
128
129 /****************
130  * Set bit N of A. and clear all bits above
131  */
132 void
133 mpi_set_highbit( MPI a, unsigned n )
134 {
135     unsigned limbno, bitno;
136
137     limbno = n / BITS_PER_MPI_LIMB;
138     bitno  = n % BITS_PER_MPI_LIMB;
139
140     if( limbno >= a->nlimbs ) { /* resize */
141         if( a->alloced >= limbno )
142             mpi_resize(a, limbno+1 );
143         a->nlimbs = limbno+1;
144     }
145     a->d[limbno] |= (A_LIMB_1<<bitno);
146     for( bitno++; bitno < BITS_PER_MPI_LIMB; bitno++ )
147         a->d[limbno] &= ~(A_LIMB_1 << bitno);
148     a->nlimbs = limbno+1;
149 }
150
151 /****************
152  * clear bit N of A and all bits above
153  */
154 void
155 mpi_clear_highbit( MPI a, unsigned n )
156 {
157     unsigned limbno, bitno;
158
159     limbno = n / BITS_PER_MPI_LIMB;
160     bitno  = n % BITS_PER_MPI_LIMB;
161
162     if( limbno >= a->nlimbs )
163         return; /* not allocated, so need to clear bits :-) */
164
165     for( ; bitno < BITS_PER_MPI_LIMB; bitno++ )
166         a->d[limbno] &= ~(A_LIMB_1 << bitno);
167     a->nlimbs = limbno+1;
168 }
169
170 /****************
171  * Clear bit N of A.
172  */
173 void
174 mpi_clear_bit( MPI a, unsigned n )
175 {
176     unsigned limbno, bitno;
177
178     limbno = n / BITS_PER_MPI_LIMB;
179     bitno  = n % BITS_PER_MPI_LIMB;
180
181     if( limbno >= a->nlimbs )
182         return; /* don't need to clear this bit, it's to far to left */
183     a->d[limbno] &= ~(A_LIMB_1 << bitno);
184 }
185
186
187 /****************
188  * Shift A by N bits to the right
189  * FIXME: should use alloc_limb if X and A are same.
190  */
191 void
192 mpi_rshift( MPI x, MPI a, unsigned n )
193 {
194     mpi_ptr_t xp;
195     mpi_size_t xsize;
196
197     xsize = a->nlimbs;
198     x->sign = a->sign;
199     RESIZE_IF_NEEDED(x, xsize);
200     xp = x->d;
201
202     if( xsize ) {
203         mpihelp_rshift( xp, a->d, xsize, n);
204         MPN_NORMALIZE( xp, xsize);
205     }
206     x->nlimbs = xsize;
207 }
208
209
210 /****************
211  * Shift A by COUNT limbs to the left
212  * This is used only within the MPI library
213  */
214 void
215 mpi_lshift_limbs( MPI a, unsigned int count )
216 {
217     mpi_ptr_t ap = a->d;
218     int n = a->nlimbs;
219     int i;
220
221     if( !count || !n )
222         return;
223
224     RESIZE_IF_NEEDED( a, n+count );
225
226     for( i = n-1; i >= 0; i-- )
227         ap[i+count] = ap[i];
228     for(i=0; i < count; i++ )
229         ap[i] = 0;
230     a->nlimbs += count;
231 }
232
233
234 /****************
235  * Shift A by COUNT limbs to the right
236  * This is used only within the MPI library
237  */
238 void
239 mpi_rshift_limbs( MPI a, unsigned int count )
240 {
241     mpi_ptr_t ap = a->d;
242     mpi_size_t n = a->nlimbs;
243     unsigned int i;
244
245     if( count >= n ) {
246         a->nlimbs = 0;
247         return;
248     }
249
250     for( i = 0; i < n - count; i++ )
251         ap[i] = ap[i+count];
252     ap[i] = 0;
253     a->nlimbs -= count;
254 }
255
256