Add mpz_inp_str to mini-gmp

Austyn Krutsinger akrutsinger at gmail.com
Fri Jul 8 15:18:08 UTC 2016


On Fri, Jul 8, 2016 at 4:43 PM, Niels Möller <nisse at lysator.liu.se> wrote:

> nisse at lysator.liu.se (Niels Möller) writes:
>
> > tg at gmplib.org (Torbjörn Granlund) writes:
> >
> >> I haven't looked at mini-gmp's mpz_set_str, but I assume it is O(n^2),
> >> so not much is lost by using a trivial implementation like the one
> >> above.
> >
> > It tries to be O(n) when base is a power of two.
>
> And I should add that for non-powers-of-two, it's also a bit more
> sophisticated than what you sketch, for good or bad. If m is the largest
> integer for which bb = base^m fits in a limb, the inner loop collects m
> digits at a time, followed by an outerloop doing an mpn_mul_1 by bb and
> an mpn_add_1.
>
> So the O(n^2) constant is mostly independent of the base, and n is the
> limb size, not the size in digits.
>
> The interesting functions are mpn_set_str_bits and mpn_set_str_other.
>
> And to limit code-duplication between mpz_inp_str and mpz_set_str, one
> approach (which would work regardless of how the input termination
> question is solved) is to use a shared helper-function
> convert_to_digit_value, collect into a buffer, and then call mpn_set_str
> which is responsible for the above tricks.
>

As I have it now, the only code that is duplicated between my mpz_inp_str
and mpz_set_str is the removal of any leading white spaces between in the
string. Since mpz_set_str can be called from functions other than
mpz_inp_str that check is still going to have to remain. As you alluded to
earlier, with the ambiguity of the GMP documentation, we would still need
both mpz_inp_str and mpz_set_str to handle strings their own way until a
standard is described in documentation.

I have updated mini-gmp to support up to base 62 also. You can find the
attached patch for review. This patch also includes the below
implementation for mpz_inp_str. I'm really not sure of the optimal way to
allocate then realloc memory for the input buffer. I suppose some kind of
statistical analysis of the size of strings read in from file streams would
be ideal, but since I don't have such statistics, I have arbitrarily chosen
the sizes you see.

int
mpz_inp_str (mpz_t x, FILE *stream, int base)
{
  int c;
  size_t nread = 0;
  size_t size = 1000;

  if (stream == 0)
    stream = stdin;

  char *buf = (char *) gmp_xalloc (size);

  /* Skip leading whitespace */
  do
    {
      c = getc (stream);
    } while (isspace (c));

  /* Read input until end of file or a space character */
  while ((c != EOF) && (isspace (c) == 0))
    {
      if (nread >= size - 1)
        {
          /* Increase input buffer size */
          size_t old_size = size;
          size += 100;
          buf = (char *) gmp_xrealloc (buf, old_size, size);
        }

        buf[nread++] = c;

      c = getc (stream);
    }

  buf[nread] = '\0';  /* Ensure null terminated string */
  ungetc (c, stream);

  c = mpz_set_str(x, buf, base);
  gmp_free (buf);
  /* 0 on error else number of characters read excluding null-terminator */
  return (c == -1 ? 0 : nread);
}

--Austyn


> Regards,
> /Niels
>
> --
> Niels Möller. PGP-encrypted email is preferred. Keyid C0B98E26.
> Internet email is subject to wholesale government surveillance.
> _______________________________________________
> gmp-devel mailing list
> gmp-devel at gmplib.org
> https://gmplib.org/mailman/listinfo/gmp-devel
>



-- 

--Austyn
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Allow-up-to-base-62-and-added-mpz_inp_str.patch
Type: application/octet-stream
Size: 6388 bytes
Desc: not available
URL: <https://gmplib.org/list-archives/gmp-devel/attachments/20160708/a00ab67d/attachment.obj>


More information about the gmp-devel mailing list