Fwd: mpx_set_str2(mpx_t, const char*, const char*, int) suggestion

Pierre Chatelier pierre at chachatelier.fr
Sat Dec 12 13:07:24 UTC 2015


Hello,

I don't see guidelines on gmplib.org to know how to submit a patch.
Here is a patch. I have never used mercurial before, please excuse if it is not the correct way.

# HG changeset patch
# User Pierre Chatelier <pierre at chachatelier.fr>
# Date 1449003901 -3600
#      Tue Dec 01 22:05:01 2015 +0100
# Node ID 89fd519f1bac6846bfa54319f416c6c75716ea71
# Parent  bb072477386f1a513937aec31cd6fa3e925f59f6
added mpz_set_str2
added mpq_set_str2
added mpf_set_str2

diff -r bb072477386f -r 89fd519f1bac gmp-h.in
--- a/gmp-h.in	Tue Nov 24 15:31:26 2015 +0100
+++ b/gmp-h.in	Tue Dec 01 22:05:01 2015 +0100
@@ -1032,6 +1032,9 @@
 #define mpz_set_str __gmpz_set_str
 __GMP_DECLSPEC int mpz_set_str (mpz_ptr, const char *, int);
 
+#define mpz_set_str2 __gmpz_set_str2
+__GMP_DECLSPEC int mpz_set_str2 (mpz_ptr, const char *, const char *, int);
+
 #define mpz_set_ui __gmpz_set_ui
 __GMP_DECLSPEC void mpz_set_ui (mpz_ptr, unsigned long int);
 
@@ -1233,6 +1236,9 @@
 #define mpq_set_str __gmpq_set_str
 __GMP_DECLSPEC int mpq_set_str (mpq_ptr, const char *, int);
 
+#define mpq_set_str2 __gmpq_set_str2
+__GMP_DECLSPEC int mpq_set_str2 (mpq_ptr, const char *, const char *, int);
+
 #define mpq_set_ui __gmpq_set_ui
 __GMP_DECLSPEC void mpq_set_ui (mpq_ptr, unsigned long int, unsigned long int);
 
@@ -1419,6 +1425,9 @@
 #define mpf_set_str __gmpf_set_str
 __GMP_DECLSPEC int mpf_set_str (mpf_ptr, const char *, int);
 
+#define mpf_set_str2 __gmpf_set_str2
+__GMP_DECLSPEC int mpf_set_str2 (mpf_ptr, const char *, const char *, int);
+
 #define mpf_set_ui __gmpf_set_ui
 __GMP_DECLSPEC void mpf_set_ui (mpf_ptr, unsigned long int);
 
diff -r bb072477386f -r 89fd519f1bac mpf/set_str.c
--- a/mpf/set_str.c	Tue Nov 24 15:31:26 2015 +0100
+++ b/mpf/set_str.c	Tue Dec 01 22:05:01 2015 +0100
@@ -122,6 +122,12 @@
 int
 mpf_set_str (mpf_ptr x, const char *str, int base)
 {
+  return mpf_set_str2(x, str, str+strlen(str), base);
+}
+
+int
+mpf_set_str2 (mpf_ptr x, const char *start, const char *end, int base)
+{
   size_t str_size;
   char *s, *begs;
   size_t i, j;
@@ -133,16 +139,21 @@
   const char  *point = GMP_DECIMAL_POINT;
   size_t      pointlen = strlen (point);
   const unsigned char *digit_value;
+  const char* str = start;
   TMP_DECL;
+  
+  if (!start || (end <= start))
+    return -1;
 
-  c = (unsigned char) *str;
+  if (str<end)
+    c = (unsigned char) *str;
 
   /* Skip whitespace.  */
-  while (isspace (c))
+  while ((str<end) && isspace (c))
     c = (unsigned char) *++str;
 
   negative = 0;
-  if (c == '-')
+  if ((c == '-') && (str<end))
     {
       negative = 1;
       c = (unsigned char) *++str;
@@ -175,16 +186,16 @@
     {
       /* not a digit, must be a decimal point */
       for (i = 0; i < pointlen; i++)
-	if (str[i] != point[i])
+	if ((str+i >= end) || (str[i] != point[i]))
 	  return -1;
-      if (digit_value[(unsigned char) str[pointlen]] >= base)
+      if ((str+pointlen >= end) || (digit_value[(unsigned char) str[pointlen]] >= base))
 	return -1;
     }
 
   /* Locate exponent part of the input.  Look from the right of the string,
      since the exponent is usually a lot shorter than the mantissa.  */
   expptr = NULL;
-  str_size = strlen (str);
+  str_size = end-str;
   for (i = str_size - 1; i > 0; i--)
     {
       c = (unsigned char) str[i];
diff -r bb072477386f -r 89fd519f1bac mpq/set_str.c
--- a/mpq/set_str.c	Tue Nov 24 15:31:26 2015 +0100
+++ b/mpq/set_str.c	Tue Dec 01 22:05:01 2015 +0100
@@ -41,29 +41,32 @@
 int
 mpq_set_str (mpq_ptr q, const char *str, int base)
 {
+  return mpq_set_str2(q, str, str+strlen(str), base);
+}
+
+int
+mpq_set_str2 (mpq_ptr q, const char *start, const char *end, int base)
+{
   const char  *slash;
-  char        *num;
-  size_t      numlen;
   int         ret;
+  const char* str = start;
+  
+  if (!start || (end<=start))
+    return -1;
 
-  slash = strchr (str, '/');
+  slash = memchr (str, '/', end-str);
   if (slash == NULL)
     {
       SIZ(DEN(q)) = 1;
       PTR(DEN(q))[0] = 1;
 
-      return mpz_set_str (mpq_numref(q), str, base);
+      return mpz_set_str2 (mpq_numref(q), str, end, base);
     }
 
-  numlen = slash - str;
-  num = __GMP_ALLOCATE_FUNC_TYPE (numlen+1, char);
-  memcpy (num, str, numlen);
-  num[numlen] = '\0';
-  ret = mpz_set_str (mpq_numref(q), num, base);
-  (*__gmp_free_func) (num, numlen+1);
+  ret = mpz_set_str2 (mpq_numref(q), str, slash, base);
 
   if (ret != 0)
     return ret;
 
-  return mpz_set_str (mpq_denref(q), slash+1, base);
+  return mpz_set_str2 (mpq_denref(q), slash+1, end, base);
 }
diff -r bb072477386f -r 89fd519f1bac mpz/set_str.c
--- a/mpz/set_str.c	Tue Nov 24 15:31:26 2015 +0100
+++ b/mpz/set_str.c	Tue Dec 01 22:05:01 2015 +0100
@@ -44,6 +44,12 @@
 int
 mpz_set_str (mpz_ptr x, const char *str, int base)
 {
+  return (mpz_set_str2(x, str, str+strlen(str), base));
+}
+
+int
+mpz_set_str2 (mpz_ptr x, const char *start, const char* end, int base)
+{
   size_t str_size;
   char *s, *begs;
   size_t i;
@@ -51,7 +57,11 @@
   int c;
   int negative;
   const unsigned char *digit_value;
+  const char* str = start;
   TMP_DECL;
+  
+  if (!start || (end<=start))
+    return -1;
 
   digit_value = digit_value_tab;
   if (base > 36)
@@ -64,12 +74,15 @@
     }
 
   /* Skip whitespace.  */
-  do
-    c = (unsigned char) *str++;
-  while (isspace (c));
+  if (str<end)
+  {
+    do
+      c = (unsigned char) *str++;
+    while ((isspace (c)) && (str<end));
+  }
 
   negative = 0;
-  if (c == '-')
+  if ((c == '-') && (str<end))
     {
       negative = 1;
       c = (unsigned char) *str++;
@@ -80,19 +93,19 @@
 
   /* If BASE is 0, try to find out the base by looking at the initial
      characters.  */
-  if (base == 0)
+  if ((base == 0) && (str<end))
     {
       base = 10;
       if (c == '0')
 	{
 	  base = 8;
 	  c = (unsigned char) *str++;
-	  if (c == 'x' || c == 'X')
+	  if ((c == 'x' || c == 'X') && (str<end))
 	    {
 	      base = 16;
 	      c = (unsigned char) *str++;
 	    }
-	  else if (c == 'b' || c == 'B')
+	  else if ((c == 'b' || c == 'B') && (str<end))
 	    {
 	      base = 2;
 	      c = (unsigned char) *str++;
@@ -101,7 +114,7 @@
     }
 
   /* Skip leading zeros and white space.  */
-  while (c == '0' || isspace (c))
+  while ((str<end) && (c == '0' || isspace (c)))
     c = (unsigned char) *str++;
   /* Make sure the string does not become empty, mpn_set_str would fail.  */
   if (c == 0)
@@ -111,7 +124,7 @@
     }
 
   TMP_MARK;
-  str_size = strlen (str - 1);
+  str_size = end-str+1;
   s = begs = (char *) TMP_ALLOC (str_size + 1);
 
   /* Remove spaces from the string and convert the result from ASCII to a


Regards,

Pierre Chatelier


Le 29 nov. 2015 à 07:26, Marco Bodrato <bodrato at mail.dm.unipi.it> a écrit :

> Ciao,
> 
> Il Ven, 27 Novembre 2015 8:53 pm, Pierre Chatelier ha scritto:
>> Currently the various mpx structures (mpz_t, mpq_t, mpf_t) have an
> 
>> For the sake of performance, I suggest a new prototype
>> mpx_set_str2(mpx_t r, const char *start, const char* end, int base)
>> (where [start;end[ is the string to consider)
> 
> The prototype of the underlying mpn function is
> mp_size_t mpn_set_str (mp_limb_t *rp, const unsigned char *str, size_t
> strsize, int base)
> 
> If you use start:end, you need to explain: *end is included or not?
> 
>> For me, the interest is :
> 
>> 	-It saves a call to strlen() in the current implementation
>> 	-users of gmplib do not need to create intermediate strings with
>> 	'\0' terminator when parsing substring from complex input data
> 
> From mpq/set_str.c:
> /* FIXME: Would like an mpz_set_mem (or similar) accepting a pointer and
>  length so we wouldn't have to copy the numerator just to null-terminate
>  it.  */
> 
> Regards,
> m
> 
> -- 
> http://bodrato.it/papers/
> 




More information about the gmp-discuss mailing list