| /* mpi-scan.c - MPI functions |
| * Copyright (C) 1998, 2001, 2002, 2003 Free Software Foundation, Inc. |
| * |
| * This file is part of Libgcrypt. |
| * |
| * Libgcrypt is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU Lesser General Public License as |
| * published by the Free Software Foundation; either version 2.1 of |
| * the License, or (at your option) any later version. |
| * |
| * Libgcrypt 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 Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser 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 <config.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #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 |
| _gcry_mpi_getbyte( gcry_mpi_t 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 |
| _gcry_mpi_putbyte( gcry_mpi_t 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; |
| } |
| } |
| abort(); /* index out of range */ |
| } |
| |
| |
| /**************** |
| * Count the number of zerobits at the low end of A |
| */ |
| unsigned |
| _gcry_mpi_trailing_zeros( gcry_mpi_t 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; |
| |
| } |
| |
| |