Re: mpn_set_str_bits

2020-09-30 Thread Niels Möller
Marco Bodrato  writes:

> static mp_size_t
> mpn_set_str_bits (mp_ptr rp, const unsigned char *sp, size_t sn,
> unsigned bits)
> {
>   mp_size_t rn;
>   mp_limb_t limb;
>   unsigned shift;
>
>   for (limb = 0, rn = 0, shift = 0; sn-- > 0; )
> {
>   limb |= (mp_limb_t) sp[sn] << shift;
>   shift += bits;
>   if (shift >= GMP_LIMB_BITS)
> {
>   shift -= GMP_LIMB_BITS;
>   rp[rn++] = limb;
>   /* Next line is correct also if shift == 0,
>  bits == 8, and mp_limb_t == unsigned char. */
>   limb = (unsigned int) sp[sn] >> (bits - shift);
> }
> }
>   if (limb != 0)
> rp[rn++] = limb;
>   else
> rn = mpn_normalized_size (rp, rn);
>   return rn;
> }
>
> It seems simple enough. Any further comment?

Looks nice!

Regards,
/Niels

-- 
Niels Möller. PGP-encrypted email is preferred. Keyid 368C6677.
Internet email is subject to wholesale government surveillance.
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpn_set_str_bits

2020-09-30 Thread Marco Bodrato

Ciao,

Il 2020-09-30 19:37 ni...@lysator.liu.se ha scritto:

Marco Bodrato  writes:


  limb = (unsigned int) sp[sn] >> (bits - shift);


That's easier to read than what I proposed.



Maybe worth a comment mentioning the problem case: mp_limb_t


Thanks Niels!

So, here is the current proposed rewrite:

static mp_size_t
mpn_set_str_bits (mp_ptr rp, const unsigned char *sp, size_t sn,
  unsigned bits)
{
  mp_size_t rn;
  mp_limb_t limb;
  unsigned shift;

  for (limb = 0, rn = 0, shift = 0; sn-- > 0; )
{
  limb |= (mp_limb_t) sp[sn] << shift;
  shift += bits;
  if (shift >= GMP_LIMB_BITS)
{
  shift -= GMP_LIMB_BITS;
  rp[rn++] = limb;
  /* Next line is correct also if shift == 0,
 bits == 8, and mp_limb_t == unsigned char. */
  limb = (unsigned int) sp[sn] >> (bits - shift);
}
}
  if (limb != 0)
rp[rn++] = limb;
  else
rn = mpn_normalized_size (rp, rn);
  return rn;
}

It seems simple enough. Any further comment?

Ĝis,
m
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpn_set_str_bits

2020-09-30 Thread Niels Möller
Marco Bodrato  writes:

>   limb = (unsigned int) sp[sn] >> (bits - shift);

That's easier to read than what I proposed.

> Maybe the cast is unnecessary, because the C standard says that the
> left operand of a shift operation is always promoted to (unsigned) int
> if it is smaller, correct?

I think so, but it's a bit subtle, so I'd prefer the explicit cast.
Maybe worth a comment mentioning the problem case: mp_limb_t
== unsigned char, bits == 8, shift == 0

Regards,
/Niels

-- 
Niels Möller. PGP-encrypted email is preferred. Keyid 368C6677.
Internet email is subject to wholesale government surveillance.
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpn_set_str_bits

2020-09-30 Thread Marco Bodrato

Ciao!

Il 2020-09-30 09:03 ni...@lysator.liu.se ha scritto:

Marco Bodrato  writes:

  limb = sp[sn];
  if (GMP_LIMB_BITS > CHAR_BIT || shift > 0)
limb >>= bits - shift;
  else
limb = 0;



Do we really need to support bits == GMP_LIMB_BITS here? If not, the


About mpn_set_str, the manual reads "base can vary from 2 to 256". 
Moreover we are fool enough to (unofficially) support "typedef unsigned 
char mp_limb_t;" in mini-gmp...



above 5 lines could be simplified to just



  limb = (sp[sn] >> 1) >> (bits - 1 - shift);

it should be safe in all cases.


I agree.

Anyway, there may be a problem only if we shift sp[sn] (unsigned char) 
or limb (possibly the same type) by 8 bits (if bits=8 and shift=0).


An even simpler solution could be to cast to unsigned int (at least 16 
bits, right?) so:


  limb = (unsigned int) sp[sn] >> (bits - shift);

Maybe the cast is unnecessary, because the C standard says that the left 
operand of a shift operation is always promoted to (unsigned) int if it 
is smaller, correct? But it shouldn't be dangerous.


Ĝis,
m
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpn_set_str_bits

2020-09-30 Thread Niels Möller
Marco Bodrato  writes:

> The loop in mpz_import uses another strategy, a temporary limb.
> This reduces the number of write operations into memory.

And it postpones writing the top limb. Another simplification I tried
failed because it sometimes wrote an extra zero limb.

> static mp_size_t
> mpn_set_str_bits (mp_ptr rp, const unsigned char *sp, size_t sn,
> unsigned bits)
> {
>   mp_size_t rn;
>   mp_limb_t limb;
>   unsigned shift;
>
>   for (limb = 0, rn = 0, shift = 0; sn-- > 0; )
> {
>   limb |= (mp_limb_t) sp[sn] << shift;
>   shift += bits;
>   if (shift >= GMP_LIMB_BITS)
>   {
> rp[rn++] = limb;
> shift -= GMP_LIMB_BITS;
> limb = sp[sn];
> if (GMP_LIMB_BITS > CHAR_BIT || shift > 0)
>   limb >>= bits - shift;
> else
>   limb = 0;

Do we really need to support bits == GMP_LIMB_BITS here? If not, the
above 5 lines could be simplified to just

  limb = sp[sn] >> (bits - shift);

Hmm, at this point, we always have shift < bits, right? So if we write
it as

  limb = (sp[sn] >> 1) >> (bits - 1 - shift);
  
it should be safe in all cases. 

Regards,
/Niels

-- 
Niels Möller. PGP-encrypted email is preferred. Keyid 368C6677.
Internet email is subject to wholesale government surveillance.
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel


Re: mpn_set_str_bits

2020-09-29 Thread Marco Bodrato

Ciao,

Il 2020-09-29 12:15 Raphael Rieu-Helft ha scritto:

The attached patch slightly improves the mini-gmp function
mpn_set_str_bits. The invariants are also a bit clearer (shift is the


The loop in mpz_import uses another strategy, a temporary limb.
This reduces the number of write operations into memory.

May I propose an alternative rewrite?
What do you think about it?

static mp_size_t
mpn_set_str_bits (mp_ptr rp, const unsigned char *sp, size_t sn,
  unsigned bits)
{
  mp_size_t rn;
  mp_limb_t limb;
  unsigned shift;

  for (limb = 0, rn = 0, shift = 0; sn-- > 0; )
{
  limb |= (mp_limb_t) sp[sn] << shift;
  shift += bits;
  if (shift >= GMP_LIMB_BITS)
{
  rp[rn++] = limb;
  shift -= GMP_LIMB_BITS;
  limb = sp[sn];
  if (GMP_LIMB_BITS > CHAR_BIT || shift > 0)
limb >>= bits - shift;
  else
limb = 0;
}
}
  if (limb != 0)
rp[rn++] = limb;
  else
rn = mpn_normalized_size (rp, rn);
  return rn;
}

Ĝis,
m
___
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel