sexp: Improve argument checking of sexp parser.
[libgcrypt.git] / mpi / mpi-div.c
index e706c00..9ac99c3 100644 (file)
@@ -1,21 +1,21 @@
 /* mpi-div.c  -  MPI functions
- *     Copyright (C) 1998 Free Software Foundation, Inc.
- *     Copyright (C) 1994, 1996 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.
@@ -23,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>
 #include <stdlib.h>
 #include "mpi-internal.h"
 #include "longlong.h"
-
+#include "g10lib.h"
 
 
 void
-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
@@ -49,10 +47,10 @@ mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor )
        divisor = temp_divisor;
     }
 
-    mpi_tdiv_r( rem, dividend, divisor );
+    _gcry_mpi_tdiv_r( rem, dividend, divisor );
 
     if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs )
-       mpi_addrem, rem, divisor);
+       mpi_add (rem, rem, divisor);
 
     if( temp_divisor )
        mpi_free(temp_divisor);
@@ -67,11 +65,11 @@ mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor )
  */
 
 ulong
-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;
 
-    rlimb = mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor );
+    rlimb = _gcry_mpih_mod_1( dividend->d, dividend->nlimbs, divisor );
     if( rlimb && dividend->sign )
        rlimb = divisor - rlimb;
 
@@ -84,25 +82,25 @@ mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor )
 
 
 void
-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) );
-    mpi_fdiv_qr( quot, tmp, dividend, divisor);
+    gcry_mpi_t tmp = mpi_alloc( mpi_get_nlimbs(quot) );
+    _gcry_mpi_fdiv_qr( quot, tmp, dividend, divisor);
     mpi_free(tmp);
 }
 
 void
-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 );
        divisor = temp_divisor;
     }
 
-    mpi_tdiv_qr( quot, rem, dividend, divisor );
+    _gcry_mpi_tdiv_qr( quot, rem, dividend, divisor );
 
     if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) {
        mpi_sub_ui( quot, quot, 1 );
@@ -122,13 +120,13 @@ mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor )
  */
 
 void
-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)
 {
-    mpi_tdiv_qr(NULL, rem, num, den );
+    _gcry_mpi_tdiv_qr(NULL, rem, num, den );
 }
 
 void
-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;
@@ -140,6 +138,7 @@ 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.
@@ -177,13 +176,13 @@ mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
        mpi_limb_t rlimb;
        if( quot ) {
            qp = quot->d;
-           rlimb = mpihelp_divmod_1( qp, np, nsize, dp[0] );
+           rlimb = _gcry_mpih_divmod_1( qp, np, nsize, dp[0] );
            qsize -= qp[qsize - 1] == 0;
            quot->nlimbs = qsize;
            quot->sign = sign_quotient;
        }
        else
-           rlimb = mpihelp_mod_1( np, nsize, dp[0] );
+           rlimb = _gcry_mpih_mod_1( np, nsize, dp[0] );
        rp[0] = rlimb;
        rsize = rlimb != 0?1:0;
        rem->nlimbs = rsize;
@@ -197,6 +196,7 @@ 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);
@@ -218,14 +218,15 @@ 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));
-       mpihelp_lshift( tp, dp, dsize, normalization_steps );
+       _gcry_mpih_lshift( tp, dp, dsize, normalization_steps );
        dp = tp;
 
        /* Shift up the numerator, possibly introducing a new most
         * significant word.  Move the shifted numerator in the remainder
         * meanwhile.  */
-       nlimb = mpihelp_lshift(rp, np, nsize, normalization_steps);
+       nlimb = _gcry_mpih_lshift(rp, np, nsize, normalization_steps);
        if( nlimb ) {
            rp[nsize] = nlimb;
            rsize = nsize + 1;
@@ -239,7 +240,9 @@ 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;
        }
@@ -251,7 +254,7 @@ mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
        rsize = nsize;
     }
 
-    q_limb = mpihelp_divrem( qp, 0, rp, rsize, dp, dsize );
+    q_limb = _gcry_mpih_divrem( qp, 0, rp, rsize, dp, dsize );
 
     if( quot ) {
        qsize = rsize - dsize;
@@ -268,18 +271,21 @@ mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
     MPN_NORMALIZE (rp, rsize);
 
     if( normalization_steps && rsize ) {
-       mpihelp_rshift(rp, rp, rsize, normalization_steps);
+       _gcry_mpih_rshift(rp, rp, rsize, normalization_steps);
        rsize -= rp[rsize - 1] == 0?1:0;
     }
 
     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
-mpi_tdiv_q_2exp( MPI w, MPI u, unsigned 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;
@@ -299,7 +305,7 @@ mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count )
 
        count %= BITS_PER_MPI_LIMB;
        if( count ) {
-           mpihelp_rshift( wp, up + limb_cnt, wsize, count );
+           _gcry_mpih_rshift( wp, up + limb_cnt, wsize, count );
            wsize -= !wp[wsize - 1];
        }
        else {
@@ -315,8 +321,36 @@ mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count )
  * (note: divisor must fit into a limb)
  */
 int
-mpi_divisible_ui(MPI dividend, ulong divisor )
+_gcry_mpi_divisible_ui(gcry_mpi_t dividend, ulong divisor )
 {
-    return !mpihelp_mod_1( dividend->d, dividend->nlimbs, 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");
+}