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