added some trust model stuff
[gnupg.git] / mpi / mpi-bit.c
1 /* mpi-bit.c  -  MPI bit level fucntions
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 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  * G10 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <assert.h>
25 #include "mpi-internal.h"
26 #include "longlong.h"
27
28
29 /****************
30  * Return the number of bits in A.
31  */
32 unsigned
33 mpi_get_nbits( MPI a )
34 {
35     unsigned n;
36
37     if( a->nlimbs ) {
38         mpi_limb_t alimb = a->d[a->nlimbs-1];
39         if( alimb )
40             count_leading_zeros( n, alimb );
41         else
42             n = BITS_PER_MPI_LIMB;
43         n = BITS_PER_MPI_LIMB - n + (a->nlimbs-1) * BITS_PER_MPI_LIMB;
44     }
45     else
46         n = 0;
47     return n;
48 }
49
50
51 /****************
52  * Test wether bit N is set.
53  */
54 int
55 mpi_test_bit( MPI a, unsigned n )
56 {
57     unsigned limbno, bitno;
58     mpi_limb_t limb;
59
60     limbno = n / BITS_PER_MPI_LIMB;
61     bitno  = n % BITS_PER_MPI_LIMB;
62
63     if( limbno >= a->nlimbs )
64         return 0; /* too far left: this is a 0 */
65     limb = a->d[limbno];
66     return (limb & (1 << bitno))? 1: 0;
67 }
68
69
70 /****************
71  * Set bit N of A.
72  */
73 void
74 mpi_set_bit( MPI a, unsigned n )
75 {
76     unsigned limbno, bitno;
77
78     limbno = n / BITS_PER_MPI_LIMB;
79     bitno  = n % BITS_PER_MPI_LIMB;
80
81     if( limbno >= a->nlimbs ) { /* resize */
82         if( a->alloced >= limbno )
83             mpi_resize(a, limbno+1 );
84         a->nlimbs = limbno+1;
85     }
86     a->d[limbno] |= (1<<bitno);
87 }
88
89 /****************
90  * Set bit N of A. and clear all bits above
91  */
92 void
93 mpi_set_highbit( MPI a, unsigned n )
94 {
95     unsigned limbno, bitno;
96
97     limbno = n / BITS_PER_MPI_LIMB;
98     bitno  = n % BITS_PER_MPI_LIMB;
99
100     if( limbno >= a->nlimbs ) { /* resize */
101         if( a->alloced >= limbno )
102             mpi_resize(a, limbno+1 );
103         a->nlimbs = limbno+1;
104     }
105     a->d[limbno] |= (1<<bitno);
106     for( bitno++; bitno < BITS_PER_MPI_LIMB; bitno++ )
107         a->d[limbno] &= ~(1 << bitno);
108     a->nlimbs = limbno+1;
109 }
110
111 /****************
112  * Clear bit N of A.
113  */
114 void
115 mpi_clear_bit( MPI a, unsigned n )
116 {
117     unsigned limbno, bitno;
118
119     limbno = n / BITS_PER_MPI_LIMB;
120     bitno  = n % BITS_PER_MPI_LIMB;
121
122     if( limbno >= a->nlimbs )
123         return; /* don't need to clear this bit, it's to far to left */
124     a->d[limbno] &= ~(1 << bitno);
125 }
126
127
128 void
129 mpi_set_bytes( MPI a, unsigned nbits, byte (*fnc)(int), int opaque )
130 {
131     byte *p;
132     unsigned nlimbs, nlimbs2, xbits, xbytes;
133     unsigned n;
134     int i;
135
136     nlimbs = nbits / BITS_PER_MPI_LIMB;
137     xbits = nbits % BITS_PER_MPI_LIMB;
138     nlimbs2 = xbits? (nlimbs+1):nlimbs;
139     xbytes = xbits / 8;
140     xbits = xbits % 8;
141     if( a->alloced < nlimbs2 )
142         mpi_resize(a, nlimbs2 );
143     a->nlimbs = nlimbs2;
144     for(n=0; n < nlimbs; n++ ) {
145         p = (byte*)(a->d+n);
146       #ifdef LITTLE_ENDIAN_HOST
147         for(i=0; i < BYTES_PER_MPI_LIMB; i++ )
148             p[i] = fnc(opaque);
149       #else
150         for(i=BYTES_PER_MPI_LIMB-1; i>=0; i-- )
151             p[i] = fnc(opaque);
152       #endif
153     }
154     if( xbytes ) {
155         p = (byte*)(a->d+n);
156       #ifdef LITTLE_ENDIAN_HOST
157         for(i=0; i < xbytes; i++ )
158             p[i] = fnc(opaque);
159       #else
160         for(i=xbytes-1; i>=0; i-- )
161             p[i] = fnc(opaque);
162       #endif
163     }
164   #if 0 /* fixme: set complete random byte and clear out the unwanted ones*/
165     if( xbits ) {
166         p = (byte*)(a->d+n);
167       #ifdef LITTLE_ENDIAN_HOST
168         for(i=0; i < xbytes; i++ )
169             p[i] = fnc(opaque);
170       #else
171         for(i=xbytes-1; i>=0; i-- )
172             p[i] = fnc(opaque);
173       #endif
174     }
175   #endif
176 }
177
178 /****************
179  * Shift A by N bits to the right
180  * FIXME: should use alloc_limb if X and A are same.
181  */
182 void
183 mpi_rshift( MPI x, MPI a, unsigned n )
184 {
185     mpi_ptr_t xp;
186     mpi_size_t xsize;
187
188     xsize = a->nlimbs;
189     x->sign = a->sign;
190     RESIZE_IF_NEEDED(x, xsize);
191     xp = x->d;
192
193     if( xsize ) {
194         mpihelp_rshift( xp, a->d, xsize, n);
195         MPN_NORMALIZE( xp, xsize);
196     }
197     x->nlimbs = xsize;
198 }
199