Antwort: Re: Re: mini-gmp: mpz_init_set_str fails on leading zeroes
Axel Miller
axel.miller at ppi.de
Fri Jul 22 21:22:03 UTC 2016
Works for me.
Regards,
Axel
Von: Austyn Krutsinger <akrutsinger at gmail.com>
An: Axel Miller <axel.miller at ppi.de>
Kopie: gmp-bugs at gmplib.org, Torbjörn Granlund <tg at gmplib.org>
Datum: 22.07.2016 18:10
Betreff: Re: Re: mini-gmp: mpz_init_set_str fails on leading zeroes
I think I've got a workable solution for everybody's review. I added a 'z'
flag. If none of the calculated limbs are great than 0, then we know the
entire number is zero and we return zero. Otherwise, we treat the
calculated number as any other and return the size.
static mp_size_t
mpn_set_str_other (mp_ptr rp, const unsigned char *sp, size_t sn,
mp_limb_t b, const struct mpn_base_info *info)
{
mp_size_t rn;
mp_limb_t w;
unsigned k;
size_t j;
mp_size_t z;
k = 1 + (sn - 1) % info->exp;
j = 0;
w = sp[j++];
while (--k != 0)
w = w * b + sp[j++];
rp[0] = w;
z = (w > 0);
for (rn = 1; j < sn;)
{
mp_limb_t cy;
w = sp[j++];
for (k = 1; k < info->exp; k++)
w = w * b + sp[j++];
if (w > 0)
z = 1;
cy = mpn_mul_1 (rp, rp, rn, info->bb);
cy += mpn_add_1 (rp, rp, rn, w);
if (cy > 0)
rp[rn++] = cy;
}
assert (j == sn);
return z == 0 ? z : rn;
}
Regards,
Austyn
On Fri, Jul 22, 2016 at 12:02 AM, Austyn Krutsinger <akrutsinger at gmail.com
> wrote:
On Thu, Jul 21, 2016 at 5:46 PM, Axel Miller <axel.miller at ppi.de> wrote:
Wouldn't that break mpz_sgn(v)
if i use mpz_set_str(v, "00000000000000000000000000000000000000000000",
10) ?
?I'm not too sure about what will happen with mpz_sgn. mpz_sizeinbase has
a problem handling all ?zeros as you have above. I
presume mpn_get_str_bits? would also fail because it too
calls mpn_limb_size_in_base_2?(up[0]) in this specific case.??
3980 size_t
3981 mpz_sizeinbase (const mpz_t u, int base)
3982 {
/*snip*/
3996
3997 up = u->_mp_d;
3998
3999 bits = (un - 1) * GMP_LIMB_BITS + mpn_limb_size_in_base_2
(up[un-1]);
4000 switch (base)
4001 {
mpn_limb_size_in_base_2 fails because it expects u to be greater than
zero.
1147 static mp_bitcnt_t
1148 mpn_limb_size_in_base_2 (mp_limb_t u)
1149 {
1150 unsigned shift;
1151
1152 assert (u > 0);
1153 gmp_clz (shift, u);
1154 return GMP_LIMB_BITS - shift;
1155 }
I don't really have any ideas right now on a solution either.
Regards,
Austyn
mpn_set_str_other would then return a value greater than zero for v, even
if the value is zero.
Thus v->_mp_size would be greater than zero:
4179 rn = mpn_set_str_other (rp, dp, sn, base, &info);
4180 }
4181 assert (rn <= alloc);
4182 gmp_free (dp);
4183
4184 r->_mp_size = sign ? - rn : rn;
As a consequence, mpz_sgn(v) would return 1.
Kind regards
Axel
Von: Austyn Krutsinger <akrutsinger at gmail.com>
An: Torbjörn Granlund <tg at gmplib.org>
Kopie: Axel Miller <axel.miller at ppi.de>, gmp-bugs at gmplib.org
Datum: 21.07.2016 10:53
Betreff: Re: mini-gmp: mpz_init_set_str fails on leading zeroes
On Thu, Jul 21, 2016 at 1:43 AM, Torbjörn Granlund <tg at gmplib.org> wrote:
Austyn Krutsinger <akrutsinger at gmail.com> writes:
My initial though was to just skip the leading zero's in the mpz_set_str
function by something like this:
while (isspace( (unsigned char) *sp) || (*sp == '0'))
sp++;
Only problems is that this doesn't work for negative numbers that still
have a bunch of leading zeros;
I think we should not accept strings like 00000-0000017.
Absolutely agree with you, kind of a silly proposal in retrospect.
We can fix this in the mpn_set_str_other function by changing the
comparison in line 1321. If we accept that w can be > or = to 0, then
there is no issue if the number has leading zeros. So line 1321 in
mpn_set_str_other becomes:
1321 for (rn = (w >= 0); j < sn;)
1322 {
1323 mp_limb_t cy;
1324
1325 w = sp[j++];
1326 for (k = 1; k < info->exp; k++)
1327 w = w * b + sp[j++];
1328
1329 cy = mpn_mul_1 (rp, rp, rn, info->bb);
1330 cy += mpn_add_1 (rp, rp, rn, w);
1331 if (cy > 0)
1332 rp[rn++] = cy;
1333 }
1334 assert (j == sn);
1321 for (rn = (w > 0); j < sn;)
Regards,
Austyn
More information about the gmp-bugs
mailing list