This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / crypto / mpi / mpi-scan.c
1 /* mpi-scan.c  -  MPI functions
2  * Copyright (C) 1998, 1999, 2000, 2001 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include "mpi-internal.h"
22 #include "longlong.h"
23
24 /****************
25  * Scan through an mpi and return byte for byte. a -1 is returned to indicate
26  * the end of the mpi. Scanning is done from the lsb to the msb, returned
27  * values are in the range of 0 .. 255.
28  *
29  * FIXME: This code is VERY ugly!
30  */
31 int
32 mpi_getbyte( const MPI a, unsigned idx )
33 {
34     int i, j;
35     unsigned n;
36     mpi_ptr_t ap;
37     mpi_limb_t limb;
38
39     ap = a->d;
40     for(n=0,i=0; i < a->nlimbs; i++ ) {
41         limb = ap[i];
42         for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ )
43             if( n == idx )
44                 return (limb >> j*8) & 0xff;
45     }
46     return -1;
47 }
48
49
50 /****************
51  * Put a value at position IDX into A. idx counts from lsb to msb
52  */
53 void
54 mpi_putbyte( MPI a, unsigned idx, int xc )
55 {
56     int i, j;
57     unsigned n;
58     mpi_ptr_t ap;
59     mpi_limb_t limb, c;
60
61     c = xc & 0xff;
62     ap = a->d;
63     for(n=0,i=0; i < a->alloced; i++ ) {
64         limb = ap[i];
65         for( j=0; j < BYTES_PER_MPI_LIMB; j++, n++ )
66             if( n == idx ) {
67               #if BYTES_PER_MPI_LIMB == 4
68                 if( j == 0 )
69                     limb = (limb & 0xffffff00) | c;
70                 else if( j == 1 )
71                     limb = (limb & 0xffff00ff) | (c<<8);
72                 else if( j == 2 )
73                     limb = (limb & 0xff00ffff) | (c<<16);
74                 else
75                     limb = (limb & 0x00ffffff) | (c<<24);
76               #elif BYTES_PER_MPI_LIMB == 8
77                 if( j == 0 )
78                     limb = (limb & 0xffffffffffffff00) | c;
79                 else if( j == 1 )
80                     limb = (limb & 0xffffffffffff00ff) | (c<<8);
81                 else if( j == 2 )
82                     limb = (limb & 0xffffffffff00ffff) | (c<<16);
83                 else if( j == 3 )
84                     limb = (limb & 0xffffffff00ffffff) | (c<<24);
85                 else if( j == 4 )
86                     limb = (limb & 0xffffff00ffffffff) | (c<<32);
87                 else if( j == 5 )
88                     limb = (limb & 0xffff00ffffffffff) | (c<<40);
89                 else if( j == 6 )
90                     limb = (limb & 0xff00ffffffffffff) | (c<<48);
91                 else
92                     limb = (limb & 0x00ffffffffffffff) | (c<<56);
93               #else
94                  #error please enhance this function, its ugly - i know.
95               #endif
96                 if( a->nlimbs <= i )
97                     a->nlimbs = i+1;
98                 ap[i] = limb;
99                 return;
100             }
101     }
102     log_bug("index out of range\n");
103 }
104
105
106 /****************
107  * Count the number of zerobits at the low end of A
108  */
109 unsigned
110 mpi_trailing_zeros( const MPI a )
111 {
112     unsigned n, count = 0;
113
114     for(n=0; n < a->nlimbs; n++ ) {
115         if( a->d[n] ) {
116             unsigned nn;
117             mpi_limb_t alimb = a->d[n];
118
119             count_trailing_zeros( nn, alimb );
120             count += nn;
121             break;
122         }
123         count += BITS_PER_MPI_LIMB;
124     }
125     return count;
126
127 }
128
129