initially checkin
[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
27
28 /****************
29  * Return the number of bits in A.
30  * fixme: we should not count leading zero bits
31  */
32 unsigned
33 mpi_get_nbits( MPI a )
34 {
35     return a->nlimbs * BITS_PER_MPI_LIMB;
36 }
37
38
39 /****************
40  * Test wether bit N is set.
41  */
42 int
43 mpi_test_bit( MPI a, unsigned n )
44 {
45     unsigned limbno, bitno;
46     mpi_limb_t limb;
47
48     limbno = n / BITS_PER_MPI_LIMB;
49     bitno  = n % BITS_PER_MPI_LIMB;
50
51     if( limbno >= a->nlimbs )
52         return 0; /* too far left: this is a 0 */
53     limb = a->d[limbno];
54     return (limb & (1 << bitno))? 1: 0;
55 }
56
57
58 /****************
59  * Set bit N of A.
60  */
61 void
62 mpi_set_bit( MPI a, unsigned n )
63 {
64     unsigned limbno, bitno;
65
66     limbno = n / BITS_PER_MPI_LIMB;
67     bitno  = n % BITS_PER_MPI_LIMB;
68
69     if( limbno >= a->nlimbs ) { /* resize */
70         if( a->alloced >= limbno )
71             mpi_resize(a, limbno+1 );
72         a->nlimbs = limbno+1;
73     }
74     a->d[limbno] |= (1<<bitno);
75 }
76
77 /****************
78  * Clear bit N of A.
79  */
80 void
81 mpi_clear_bit( MPI a, unsigned n )
82 {
83     unsigned limbno, bitno;
84
85     limbno = n / BITS_PER_MPI_LIMB;
86     bitno  = n % BITS_PER_MPI_LIMB;
87
88     if( limbno >= a->nlimbs )
89         return; /* don't need to clear this bit, it's to far to left */
90     a->d[limbno] &= ~(1 << bitno);
91 }
92
93
94 void
95 mpi_set_bytes( MPI a, unsigned nbits, byte (*fnc)(int), int opaque )
96 {
97     byte *p;
98     unsigned nlimbs, nlimbs2, xbits, xbytes;
99     unsigned n;
100     int i;
101
102     nlimbs = nbits / BITS_PER_MPI_LIMB;
103     xbits = nbits % BITS_PER_MPI_LIMB;
104     nlimbs2 = xbits? (nlimbs+1):nlimbs;
105     xbytes = xbits / 8;
106     xbits = xbits % 8;
107     if( a->alloced < nlimbs2 )
108         mpi_resize(a, nlimbs2 );
109     a->nlimbs = nlimbs2;
110     for(n=0; n < nlimbs; n++ ) {
111         p = (byte*)(a->d+n);
112       #ifdef HAVE_LITTLE_ENDIAN
113         for(i=0; i < BYTES_PER_MPI_LIMB; i++ )
114             p[i] = fnc(opaque);
115       #else
116         for(i=BYTES_PER_MPI_LIMB-1; i>=0; i-- )
117             p[i] = fnc(opaque);
118       #endif
119     }
120     if( xbytes ) {
121         p = (byte*)(a->d+n);
122       #ifdef HAVE_LITTLE_ENDIAN
123         for(i=0; i < xbytes; i++ )
124             p[i] = fnc(opaque);
125       #else
126         for(i=xbytes-1; i>=0; i-- )
127             p[i] = fnc(opaque);
128       #endif
129     }
130     assert(!xbits);
131 }
132
133