Best way to import without copy

Emmanuel Thomé emmanuel.thome at gmail.com
Fri May 5 10:36:21 CEST 2023


Hi,

Quoting the fine manual:

     'mpz_t' variables initialised with the 'mpz_roinit_n' function or
>      the 'MPZ_ROINIT_N' macro have '_mp_alloc = 0' but can have a
>      non-zero '_mp_size'.  They can only be used as read-only constants.
>      See *note Integer Special Functions:: for details.


For sure, it's a design decision to set _mp_alloc = 0, but it is also an
understandable one.

If you don't heed the usage warning and try to modify (e.g., increment) an
mpz_t that was created with roinit, here's what happens. gmp decides that
it needs more storage, reallocates (actually just allocates afresh since
alloc=0), and blindly accepts the data in the new area as containing
ABS(_mp_size) valid limbs. So, you're asking for trouble and you do get
into trouble. It's fair game.

Furthermore:

The fact that get_mpz_t() returns a const and the function is called ROINIT
> makes me think that it won't make it..


These seem to be two incorrect statements. get_mpz_t() definitely does not
return a const. It returns a (non-const) reference, and it's definitely ok
to modify it as you actually do in your code snippet.

And mpz_roinit_n vs MPZ_ROINIT_N are two subtly different things, as
documented in the manual.

I am surprised GMP doesn't have a no copy mechanism if we can guarantee
> that we have a properly made buffer on input, available for output as well.


Depending on what you are trying to achieve, you can either:
 - #1 work with the mpn interface
 - #2 discipline yourself and really only use roinit'ed objects as readonly

In my experience, this has never been a problem.

Best regards,

E.

On Thu, May 4, 2023 at 11:13 PM Julien D Arques <acc.gccquestions at gmail.com>
wrote:

> Actually, after trying, the mpz_roinit_n won't make it because doing
> something like this:
>
> mpz_class tmp;
> std::array <u64, 1> m{10};
>
> mpz_roinit_n( tmp.get_mpz_t(), &m[0], m.size());
>
>
> std::cout << tmp << std::endl;
> tmp += 1;
> std::cout << tmp << std::endl;
>
> will yield 10 for the first call but a garbage value (I guess) for the
> second.
>
> The fact that get_mpz_t() returns a const and the function is called ROINIT
> makes me think that it won't make it..
>
> I am surprised GMP doesn't have a no copy mechanism if we can guarantee
> that we have a properly made buffer on input, available for output as well.
>
> On Thu, 4 May 2023 at 08:03, Julien D Arques <acc.gccquestions at gmail.com>
> wrote:
>
> > thanks Marc
> >
> > On Thu, 4 May 2023 at 00:25, Marc Glisse <marc.glisse at inria.fr> wrote:
> >
> >> On Wed, 3 May 2023, Julien D Arques wrote:
> >>
> >> > I currently use mpz_import, but reading the source code, it appears
> that
> >> > gmp copies the already allocated buffer I give it.
> >> > That's double the work, and the said buffer is big.
> >>
> >> Depending on endianness and other criteria, this might not be a simple
> >> copy.
> >>
> >> > Is there a correct/reliable way to avoid that?
> >>
> >> If you are certain the format is right, you could try mpz_roinit_n.
> >>
> >> --
> >> Marc Glisse
> >>
> >
> _______________________________________________
> gmp-discuss mailing list
> gmp-discuss at gmplib.org
> https://gmplib.org/mailman/listinfo/gmp-discuss
>


More information about the gmp-discuss mailing list