| /* 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; |
| |
| } |