| /* mpi-scan.c - MPI functions | |
| * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. | |
| * | |
| * This file is part of GnuPG. | |
| * | |
| * GnuPG is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU General Public License as published by | |
| * the Free Software Foundation; either version 2 of the License, or | |
| * (at your option) any later version. | |
| * | |
| * GnuPG is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU General Public License | |
| * along with this program; if not, write to the Free Software | |
| * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | |
| */ | |
| #include "mpi-internal.h" | |
| #include "longlong.h" | |
| /**************** | |
| * Scan through an mpi and return byte for byte. a -1 is returned to indicate | |
| * the end of the mpi. Scanning is done from the lsb to the msb, returned | |
| * values are in the range of 0 .. 255. | |
| * | |
| * FIXME: This code is VERY ugly! | |
| */ | |
| int mpi_getbyte(const MPI a, unsigned idx) | |
| { | |
| int i, j; | |
| unsigned n; | |
| mpi_ptr_t ap; | |
| mpi_limb_t limb; | |
| ap = a->d; | |
| for (n = 0, i = 0; i < a->nlimbs; i++) { | |
| limb = ap[i]; | |
| for (j = 0; j < BYTES_PER_MPI_LIMB; j++, n++) | |
| if (n == idx) | |
| return (limb >> j * 8) & 0xff; | |
| } | |
| return -1; | |
| } | |
| /**************** | |
| * Put a value at position IDX into A. idx counts from lsb to msb | |
| */ | |
| void mpi_putbyte(MPI a, unsigned idx, int xc) | |
| { | |
| int i, j; | |
| unsigned n; | |
| mpi_ptr_t ap; | |
| mpi_limb_t limb, c; | |
| c = xc & 0xff; | |
| ap = a->d; | |
| for (n = 0, i = 0; i < a->alloced; i++) { | |
| limb = ap[i]; | |
| for (j = 0; j < BYTES_PER_MPI_LIMB; j++, n++) | |
| if (n == idx) { | |
| #if BYTES_PER_MPI_LIMB == 4 | |
| if (j == 0) | |
| limb = (limb & 0xffffff00) | c; | |
| else if (j == 1) | |
| limb = (limb & 0xffff00ff) | (c << 8); | |
| else if (j == 2) | |
| limb = (limb & 0xff00ffff) | (c << 16); | |
| else | |
| limb = (limb & 0x00ffffff) | (c << 24); | |
| #elif BYTES_PER_MPI_LIMB == 8 | |
| if (j == 0) | |
| limb = (limb & 0xffffffffffffff00) | c; | |
| else if (j == 1) | |
| limb = | |
| (limb & 0xffffffffffff00ff) | (c << | |
| 8); | |
| else if (j == 2) | |
| limb = | |
| (limb & 0xffffffffff00ffff) | (c << | |
| 16); | |
| else if (j == 3) | |
| limb = | |
| (limb & 0xffffffff00ffffff) | (c << | |
| 24); | |
| else if (j == 4) | |
| limb = | |
| (limb & 0xffffff00ffffffff) | (c << | |
| 32); | |
| else if (j == 5) | |
| limb = | |
| (limb & 0xffff00ffffffffff) | (c << | |
| 40); | |
| else if (j == 6) | |
| limb = | |
| (limb & 0xff00ffffffffffff) | (c << | |
| 48); | |
| else | |
| limb = | |
| (limb & 0x00ffffffffffffff) | (c << | |
| 56); | |
| #else | |
| #error please enhance this function, its ugly - i know. | |
| #endif | |
| if (a->nlimbs <= i) | |
| a->nlimbs = i + 1; | |
| ap[i] = limb; | |
| return; | |
| } | |
| } | |
| log_bug("index out of range\n"); | |
| } | |
| /**************** | |
| * Count the number of zerobits at the low end of A | |
| */ | |
| unsigned mpi_trailing_zeros(const MPI a) | |
| { | |
| unsigned n, count = 0; | |
| for (n = 0; n < a->nlimbs; n++) { | |
| if (a->d[n]) { | |
| unsigned nn; | |
| mpi_limb_t alimb = a->d[n]; | |
| count_trailing_zeros(nn, alimb); | |
| count += nn; | |
| break; | |
| } | |
| count += BITS_PER_MPI_LIMB; | |
| } | |
| return count; | |
| } |