See ChangeLog: Mon Jan 24 22:24:38 CET 2000 Werner Koch
[gnupg.git] / mpi / mpi-bit.c
index 864dc02..b79505f 100644 (file)
@@ -1,14 +1,14 @@
 /* mpi-bit.c  -  MPI bit level fucntions
- *     Copyright (c) 1997 by Werner Koch (dd9jn)
+ *     Copyright (C) 1998, 1999 Free Software Foundation, Inc.
  *
- * This file is part of G10.
+ * This file is part of GnuPG.
  *
- * G10 is free software; you can redistribute it and/or modify
+ * 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.
  *
- * G10 is distributed in the hope that it will be useful,
+ * 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.
 #include "longlong.h"
 
 
+#ifdef MPI_INTERNAL_NEED_CLZ_TAB
+#ifdef __STDC__
+const
+#endif
+unsigned char
+__clz_tab[] =
+{
+  0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+};
+#endif
+
+
+#define A_LIMB_1 ((mpi_limb_t)1)
+
+
+/****************
+ * Sometimes we have MSL (most significant limbs) which are 0;
+ * this is for some reasons not good, so this function removes them.
+ */
+void
+mpi_normalize( MPI a )
+{
+    if( mpi_is_opaque(a) )
+       return;
+
+    for( ; a->nlimbs && !a->d[a->nlimbs-1]; a->nlimbs-- )
+       ;
+}
+
+
+
 /****************
  * Return the number of bits in A.
  */
-unsigned
+unsigned int
 mpi_get_nbits( MPI a )
 {
     unsigned n;
 
+    if( mpi_is_opaque(a) ) {
+       return a->sign; /* which holds the number of bits */
+    }
+
+    mpi_normalize( a );
     if( a->nlimbs ) {
        mpi_limb_t alimb = a->d[a->nlimbs-1];
        if( alimb )
@@ -47,9 +90,14 @@ mpi_get_nbits( MPI a )
     return n;
 }
 
+unsigned int
+gcry_mpi_get_nbits( MPI a )
+{
+    return mpi_get_nbits( a );
+}
 
 /****************
- * Test wether bit N is set.
+ * Test whether bit N is set.
  */
 int
 mpi_test_bit( MPI a, unsigned n )
@@ -63,7 +111,7 @@ mpi_test_bit( MPI a, unsigned n )
     if( limbno >= a->nlimbs )
        return 0; /* too far left: this is a 0 */
     limb = a->d[limbno];
-    return (limb & (1 << bitno))? 1: 0;
+    return (limb & (A_LIMB_1 << bitno))? 1: 0;
 }
 
 
@@ -83,7 +131,7 @@ mpi_set_bit( MPI a, unsigned n )
            mpi_resize(a, limbno+1 );
        a->nlimbs = limbno+1;
     }
-    a->d[limbno] |= (1<<bitno);
+    a->d[limbno] |= (A_LIMB_1<<bitno);
 }
 
 /****************
@@ -102,17 +150,17 @@ mpi_set_highbit( MPI a, unsigned n )
            mpi_resize(a, limbno+1 );
        a->nlimbs = limbno+1;
     }
-    a->d[limbno] |= (1<<bitno);
+    a->d[limbno] |= (A_LIMB_1<<bitno);
     for( bitno++; bitno < BITS_PER_MPI_LIMB; bitno++ )
-       a->d[limbno] &= ~(1 << bitno);
+       a->d[limbno] &= ~(A_LIMB_1 << bitno);
     a->nlimbs = limbno+1;
 }
 
 /****************
- * Clear bit N of A.
+ * clear bit N of A and all bits above
  */
 void
-mpi_clear_bit( MPI a, unsigned n )
+mpi_clear_highbit( MPI a, unsigned n )
 {
     unsigned limbno, bitno;
 
@@ -120,61 +168,30 @@ mpi_clear_bit( MPI a, unsigned n )
     bitno  = n % BITS_PER_MPI_LIMB;
 
     if( limbno >= a->nlimbs )
-       return; /* don't need to clear this bit, it's to far to left */
-    a->d[limbno] &= ~(1 << bitno);
-}
+       return; /* not allocated, so need to clear bits :-) */
 
+    for( ; bitno < BITS_PER_MPI_LIMB; bitno++ )
+       a->d[limbno] &= ~(A_LIMB_1 << bitno);
+    a->nlimbs = limbno+1;
+}
 
+/****************
+ * Clear bit N of A.
+ */
 void
-mpi_set_bytes( MPI a, unsigned nbits, byte (*fnc)(int), int opaque )
+mpi_clear_bit( MPI a, unsigned n )
 {
-    byte *p;
-    unsigned nlimbs, nlimbs2, xbits, xbytes;
-    unsigned n;
-    int i;
+    unsigned limbno, bitno;
 
-    nlimbs = nbits / BITS_PER_MPI_LIMB;
-    xbits = nbits % BITS_PER_MPI_LIMB;
-    nlimbs2 = xbits? (nlimbs+1):nlimbs;
-    xbytes = xbits / 8;
-    xbits = xbits % 8;
-    if( a->alloced < nlimbs2 )
-       mpi_resize(a, nlimbs2 );
-    a->nlimbs = nlimbs2;
-    for(n=0; n < nlimbs; n++ ) {
-       p = (byte*)(a->d+n);
-      #ifdef LITTLE_ENDIAN_HOST
-       for(i=0; i < BYTES_PER_MPI_LIMB; i++ )
-           p[i] = fnc(opaque);
-      #else
-       for(i=BYTES_PER_MPI_LIMB-1; i>=0; i-- )
-           p[i] = fnc(opaque);
-      #endif
-    }
-    if( xbytes ) {
-       p = (byte*)(a->d+n);
-      #ifdef LITTLE_ENDIAN_HOST
-       for(i=0; i < xbytes; i++ )
-           p[i] = fnc(opaque);
-      #else
-       for(i=xbytes-1; i>=0; i-- )
-           p[i] = fnc(opaque);
-      #endif
-    }
-  #if 0 /* fixme: set complete random byte and clear out the unwanted ones*/
-    if( xbits ) {
-       p = (byte*)(a->d+n);
-      #ifdef LITTLE_ENDIAN_HOST
-       for(i=0; i < xbytes; i++ )
-           p[i] = fnc(opaque);
-      #else
-       for(i=xbytes-1; i>=0; i-- )
-           p[i] = fnc(opaque);
-      #endif
-    }
-  #endif
+    limbno = n / BITS_PER_MPI_LIMB;
+    bitno  = n % BITS_PER_MPI_LIMB;
+
+    if( limbno >= a->nlimbs )
+       return; /* don't need to clear this bit, it's to far to left */
+    a->d[limbno] &= ~(A_LIMB_1 << bitno);
 }
 
+
 /****************
  * Shift A by N bits to the right
  * FIXME: should use alloc_limb if X and A are same.
@@ -197,3 +214,51 @@ mpi_rshift( MPI x, MPI a, unsigned n )
     x->nlimbs = xsize;
 }
 
+
+/****************
+ * Shift A by COUNT limbs to the left
+ * This is used only within the MPI library
+ */
+void
+mpi_lshift_limbs( MPI a, unsigned int count )
+{
+    mpi_ptr_t ap = a->d;
+    int n = a->nlimbs;
+    int i;
+
+    if( !count || !n )
+       return;
+
+    RESIZE_IF_NEEDED( a, n+count );
+
+    for( i = n-1; i >= 0; i-- )
+       ap[i+count] = ap[i];
+    for(i=0; i < count; i++ )
+       ap[i] = 0;
+    a->nlimbs += count;
+}
+
+
+/****************
+ * Shift A by COUNT limbs to the right
+ * This is used only within the MPI library
+ */
+void
+mpi_rshift_limbs( MPI a, unsigned int count )
+{
+    mpi_ptr_t ap = a->d;
+    mpi_size_t n = a->nlimbs;
+    unsigned int i;
+
+    if( count >= n ) {
+       a->nlimbs = 0;
+       return;
+    }
+
+    for( i = 0; i < n - count; i++ )
+       ap[i] = ap[i+count];
+    ap[i] = 0;
+    a->nlimbs -= count;
+}
+
+