sexp: Improve argument checking of sexp parser.
[libgcrypt.git] / mpi / mpi-div.c
index a439c46..9ac99c3 100644 (file)
@@ -1,20 +1,21 @@
 /* mpi-div.c  -  MPI functions
- *     Copyright (C) 1994, 1996, 1998, 2001 Free Software Foundation, Inc.
+ * Copyright (C) 1994, 1996, 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 General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * 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 General Public License for more details.
+ * GNU Lesser 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
+ * 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
  *
  * Note: This code is heavily based on the GNU MP Library.
@@ -22,8 +23,6 @@
  *      way the data is stored; this is to support the abstraction
  *      of an optional secure memory allocation which may be used
  *      to avoid revealing of sensitive data due to paging etc.
- *      The GNU MP Library itself is published under the LGPL;
- *      however I decided to publish this code under the plain GPL.
  */
 
 #include <config.h>
 
 
 void
-_gcry_mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor )
+_gcry_mpi_fdiv_r( gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor )
 {
     int divisor_sign = divisor->sign;
-    MPI temp_divisor = NULL;
+    gcry_mpi_t temp_divisor = NULL;
 
     /* We need the original value of the divisor after the remainder has been
      * preliminary calculated. We have to copy it to temporary space if it's
@@ -51,7 +50,7 @@ _gcry_mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor )
     _gcry_mpi_tdiv_r( rem, dividend, divisor );
 
     if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs )
-       gcry_mpi_add( rem, rem, divisor);
+       mpi_add (rem, rem, divisor);
 
     if( temp_divisor )
        mpi_free(temp_divisor);
@@ -66,7 +65,7 @@ _gcry_mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor )
  */
 
 ulong
-_gcry_mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor )
+_gcry_mpi_fdiv_r_ui( gcry_mpi_t rem, gcry_mpi_t dividend, ulong divisor )
 {
     mpi_limb_t rlimb;
 
@@ -83,18 +82,18 @@ _gcry_mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor )
 
 
 void
-_gcry_mpi_fdiv_q( MPI quot, MPI dividend, MPI divisor )
+_gcry_mpi_fdiv_q( gcry_mpi_t quot, gcry_mpi_t dividend, gcry_mpi_t divisor )
 {
-    MPI tmp = mpi_alloc( mpi_get_nlimbs(quot) );
+    gcry_mpi_t tmp = mpi_alloc( mpi_get_nlimbs(quot) );
     _gcry_mpi_fdiv_qr( quot, tmp, dividend, divisor);
     mpi_free(tmp);
 }
 
 void
-_gcry_mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor )
+_gcry_mpi_fdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor )
 {
     int divisor_sign = divisor->sign;
-    MPI temp_divisor = NULL;
+    gcry_mpi_t temp_divisor = NULL;
 
     if( quot == divisor || rem == divisor ) {
        temp_divisor = mpi_copy( divisor );
@@ -104,8 +103,8 @@ _gcry_mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor )
     _gcry_mpi_tdiv_qr( quot, rem, dividend, divisor );
 
     if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) {
-       gcry_mpi_sub_ui( quot, quot, 1 );
-       gcry_mpi_add( rem, rem, divisor);
+       mpi_sub_ui( quot, quot, 1 );
+       mpi_add( rem, rem, divisor);
     }
 
     if( temp_divisor )
@@ -121,13 +120,13 @@ _gcry_mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor )
  */
 
 void
-_gcry_mpi_tdiv_r( MPI rem, MPI num, MPI den)
+_gcry_mpi_tdiv_r( gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den)
 {
     _gcry_mpi_tdiv_qr(NULL, rem, num, den );
 }
 
 void
-_gcry_mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
+_gcry_mpi_tdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t num, gcry_mpi_t den)
 {
     mpi_ptr_t np, dp;
     mpi_ptr_t qp, rp;
@@ -139,6 +138,7 @@ _gcry_mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
     unsigned normalization_steps;
     mpi_limb_t q_limb;
     mpi_ptr_t marker[5];
+    unsigned int marker_nlimbs[5];
     int markidx=0;
 
     /* Ensure space is enough for quotient and remainder.
@@ -196,6 +196,7 @@ _gcry_mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
        /* Make sure QP and NP point to different objects.  Otherwise the
         * numerator would be gradually overwritten by the quotient limbs.  */
        if(qp == np) { /* Copy NP object to temporary space.  */
+            marker_nlimbs[markidx] = nsize;
            np = marker[markidx++] = mpi_alloc_limb_space(nsize,
                                                          mpi_is_secure(quot));
            MPN_COPY(np, qp, nsize);
@@ -217,6 +218,7 @@ _gcry_mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
        /* Shift up the denominator setting the most significant bit of
         * the most significant word.  Use temporary storage not to clobber
         * the original contents of the denominator.  */
+        marker_nlimbs[markidx] = dsize;
        tp = marker[markidx++] = mpi_alloc_limb_space(dsize,mpi_is_secure(den));
        _gcry_mpih_lshift( tp, dp, dsize, normalization_steps );
        dp = tp;
@@ -238,7 +240,9 @@ _gcry_mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
        if( dp == rp || (quot && (dp == qp))) {
            mpi_ptr_t tp;
 
-           tp = marker[markidx++] = mpi_alloc_limb_space(dsize, mpi_is_secure(den));
+            marker_nlimbs[markidx] = dsize;
+           tp = marker[markidx++] = mpi_alloc_limb_space(dsize,
+                                                          mpi_is_secure(den));
            MPN_COPY( tp, dp, dsize );
            dp = tp;
        }
@@ -274,11 +278,14 @@ _gcry_mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
     rem->nlimbs = rsize;
     rem->sign  = sign_remainder;
     while( markidx )
-       mpi_free_limb_space(marker[--markidx]);
+      {
+        markidx--;
+       _gcry_mpi_free_limb_space (marker[markidx], marker_nlimbs[markidx]);
+      }
 }
 
 void
-_gcry_mpi_tdiv_q_2exp( MPI w, MPI u, unsigned int count )
+_gcry_mpi_tdiv_q_2exp( gcry_mpi_t w, gcry_mpi_t u, unsigned int count )
 {
     mpi_size_t usize, wsize;
     mpi_size_t limb_cnt;
@@ -314,8 +321,36 @@ _gcry_mpi_tdiv_q_2exp( MPI w, MPI u, unsigned int count )
  * (note: divisor must fit into a limb)
  */
 int
-_gcry_mpi_divisible_ui(MPI dividend, ulong divisor )
+_gcry_mpi_divisible_ui(gcry_mpi_t dividend, ulong divisor )
 {
     return !_gcry_mpih_mod_1( dividend->d, dividend->nlimbs, divisor );
 }
 
+
+void
+_gcry_mpi_div (gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend,
+               gcry_mpi_t divisor, int round)
+{
+  if (!round)
+    {
+      if (!rem)
+        {
+          gcry_mpi_t tmp = mpi_alloc (mpi_get_nlimbs(quot));
+          _gcry_mpi_tdiv_qr (quot, tmp, dividend, divisor);
+          mpi_free (tmp);
+        }
+      else
+        _gcry_mpi_tdiv_qr (quot, rem, dividend, divisor);
+    }
+  else if (round < 0)
+    {
+      if (!rem)
+        _gcry_mpi_fdiv_q (quot, dividend, divisor);
+      else if (!quot)
+        _gcry_mpi_fdiv_r (rem, dividend, divisor);
+      else
+        _gcry_mpi_fdiv_qr (quot, rem, dividend, divisor);
+    }
+  else
+    log_bug ("mpi rounding to ceiling not yet implemented\n");
+}