increase mini-gmp base support to 62

Austyn Krutsinger akrutsinger at gmail.com
Mon Jan 30 04:06:49 UTC 2017


In small steps to bring mini-gmp's implementation up to par with the main
GMP, here is a patch that will allow using up to base 62. I hope this could
be useful to some.

Cheers,

--Austyn



---
 README     |   3 +-
 mini-gmp.c | 101
++++++++++++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 75 insertions(+), 29 deletions(-)

diff --git a/README b/README
index f291489..84c6c94 100644
--- a/README
+++ b/README
@@ -42,8 +42,7 @@ The supported GMP subset is declared in mini-gmp.h. The
implemented
 functions are fully compatible with the corresponding GMP functions,
 as specified in the GMP manual, with a few exceptions:

-  mpz_set_str, mpz_init_set_str, mpz_get_str, mpz_out_str and
-  mpz_sizeinbase support only |base| <= 36;
+  mpz_set_str, mpz_init_set_str, mpz_get_str, and mpz_out_str;
   mpz_export and mpz_import support only NAILS = 0.

   The REALLOC_FUNC and FREE_FUNC registered with
diff --git a/mini-gmp.c b/mini-gmp.c
index 04bed3f..49343a7 100644
--- a/mini-gmp.c
+++ b/mini-gmp.c
@@ -4013,7 +4013,7 @@ mpz_sizeinbase (const mpz_t u, int base)
   size_t ndigits;

   assert (base >= 2);
-  assert (base <= 36);
+  assert (base <= 62);

   un = GMP_ABS (u->_mp_size);
   if (un == 0)
@@ -4066,16 +4066,24 @@ mpz_get_str (char *sp, int base, const mpz_t u)
   if (base >= 0)
     {
       digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+      if (base <= 1)
+        base = 10;
+      else if (base > 36)
+        {
+          digits =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+          if (base > 62)
+            return NULL;
+        }
     }
   else
     {
       base = -base;
+  if (base <= 1)
+        base = 10;
+      else if (base > 36)
+        return NULL;
       digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
     }
-  if (base <= 1)
-    base = 10;
-  if (base > 36)
-    return NULL;

   sn = 1 + mpz_sizeinbase (u, base);
   if (!sp)
@@ -4120,6 +4128,40 @@ mpz_get_str (char *sp, int base, const mpz_t u)
   return sp;
 }

+#define X 0xff
+const unsigned char digit_value_tab[] =
+{
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, X, X, X, X, X, X,
+  X,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
+  25,26,27,28,29,30,31,32,33,34,35,X, X, X, X, X,
+  X,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
+  25,26,27,28,29,30,31,32,33,34,35,X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, X, X, X, X, X, X,
+  X,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
+  25,26,27,28,29,30,31,32,33,34,35,X, X, X, X, X,
+  X,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,
+  51,52,53,54,55,56,57,58,59,60,61,X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X,
+  X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X
+};
+
 int
 mpz_set_str (mpz_t r, const char *sp, int base)
 {
@@ -4129,9 +4171,20 @@ mpz_set_str (mpz_t r, const char *sp, int base)
   size_t dn;
   int sign;
   unsigned char *dp;
+  const unsigned char *digit_value;

-  assert (base == 0 || (base >= 2 && base <= 36));
+  assert (base == 0 || (base >= 2 && base <= 62));

+  digit_value = digit_value_tab;
+  if (base > 36)
+    {
+      /* For bases > 36, use the collating sequence
+         0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz. */
+      digit_value += 208;
+      if (base > 62)
+        return -1; /* too large base */
+    }
+
   while (isspace( (unsigned char) *sp))
     sp++;

@@ -4168,27 +4221,21 @@ mpz_set_str (mpz_t r, const char *sp, int base)

   for (dn = 0; *sp; sp++)
     {
-      unsigned digit;
-
-      if (isspace ((unsigned char) *sp))
- continue;
-      else if (*sp >= '0' && *sp <= '9')
- digit = *sp - '0';
-      else if (*sp >= 'a' && *sp <= 'z')
- digit = *sp - 'a' + 10;
-      else if (*sp >= 'A' && *sp <= 'Z')
- digit = *sp - 'A' + 10;
-      else
- digit = base; /* fail */
-
-      if (digit >= (unsigned) base)
- {
-  gmp_free (dp);
-  r->_mp_size = 0;
-  return -1;
- }
-
-      dp[dn++] = digit;
+      if (!isspace (*sp))
+        {
+          /* Get digit value from lookup table */
+          unsigned digit;
+          digit = digit_value[(unsigned char) *sp];
+
+          if (digit >= (unsigned) base)
+            {
+              gmp_free (dp);
+              r->_mp_size = 0;
+              return -1;
+            }
+
+          dp[dn++] = digit;
+        }
     }

   if (!dn)
-- 
2.10.1.windows.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Increase-base-support-to-62-to-match-GMP.patch
Type: application/octet-stream
Size: 5223 bytes
Desc: not available
URL: <https://gmplib.org/list-archives/gmp-devel/attachments/20170129/c11df20b/attachment.obj>


More information about the gmp-devel mailing list