Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More GMP work #1075

Merged
merged 21 commits into from
Jan 23, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
1898ea7
gmpints: introduce fake_mpz_t
fingolfin Jan 21, 2017
8c018e0
gmpints: merge GMPorINTOBJ_INT and ObjInt_Int
fingolfin Jan 21, 2017
e918054
gmpints: rewrite PrintInt using mpz_get_str
fingolfin Jan 21, 2017
1c6d8ee
gmpints: rewrite HexStringInt and STRING_INT using fake_mpz_t
fingolfin Jan 21, 2017
b591686
gmpints: remove GMP_INTOBJ
fingolfin Jan 21, 2017
9a3689f
gmpints: rewrite FuncIntHexString
fingolfin Jan 21, 2017
99418d3
gmpints: replace TypLimb -> mp_limb_t, TypGMPSize -> mp_size_t
fingolfin Jan 21, 2017
b700ea4
gmpints: replace INTEGER_ALLOCATION_SIZE by INTEGER_UNIT_SIZE
fingolfin Jan 21, 2017
af567b1
gmpints: cleanup gmpints.h
fingolfin Jan 21, 2017
6a5815f
gmpints: simplify ModInt
fingolfin Jan 21, 2017
b8a188c
gmpints: remove NEW_INTPOS
fingolfin Jan 21, 2017
8454a6f
gmpints: add IS_INT, IS_POSITIVE, REQUIRE_INT_ARG
fingolfin Jan 21, 2017
1c8ae24
gmpints: change REQUIRE_INT_ARG to use ErrorMayQuit
fingolfin Jan 21, 2017
cdba5d4
gmpints: use REQUIRE_INT_ARG in two more places
fingolfin Jan 21, 2017
3e44492
gmpints: fix RemInt error handling
fingolfin Jan 21, 2017
42c4845
gmpints: add JACOBI_INT and change Jacobi() to use it
fingolfin Jan 21, 2017
0950124
gmpints: add POWERMODINT and INVMODINT
fingolfin Jan 21, 2017
9561e9d
gmpints: add PVALUATION_INT
fingolfin Jan 21, 2017
fbf656a
tests: replace legal header in intarith.tst
fingolfin Jan 21, 2017
9bc7f34
gmpints: explain the buffer in PrintInt
fingolfin Jan 23, 2017
cad52ab
gmpints: improve initial documentation comment
fingolfin Jan 23, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
gmpints: rewrite FuncIntHexString
Added test to verify it does not destroy the input string anymore.
  • Loading branch information
fingolfin committed Jan 21, 2017
commit 9a3689fd595f4f431681f657d57564c2e3146b15
116 changes: 64 additions & 52 deletions src/gmpints.c
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,7 @@ Obj StringIntBase( Obj gmp, int base )
**
** The function `FuncIntHexString' does the converse, but here the
** letters a..f are also allowed in <string> instead of A..F.
**
**
*/
Obj FuncHexStringInt( Obj self, Obj gmp )
{
Expand All @@ -670,14 +670,41 @@ Obj FuncHexStringInt( Obj self, Obj gmp )
}


/****************************************************************************
**
** This helper function for IntHexString reads <len> bytes in the string
** <p> and parses them as a hexadecimal. The resulting integer is returned.
** This function does not check for overflow, so make sure that len*4 does
** not exceed the number of bits in TypLimb.
**/
static TypLimb hexstr2int( const UInt1 *p, UInt len )
{
TypLimb n = 0;
UInt1 a;
while (len--) {
a = *p++;
if (a >= 'a')
a -= 'a' - 10;
else if ( a>= 'A')
a -= 'A' - 10;
else
a -= '0';
if (a > 15)
ErrorMayQuit("IntHexString: invalid character in hex-string", 0L, 0L);
n = (n << 4) + a;
}
return n;
}


Obj FuncIntHexString( Obj self, Obj str )
{
Obj res;
Int i, j, len, sign, nd;
UInt n;
UInt1 *p, a;
UChar c;
Int i, len, sign, nd;
TypLimb n;
UInt1 *p;
TypLimb *limbs;

if (! IsStringConv(str))
ErrorMayQuit("IntHexString: argument must be string (not a %s)",
(Int)TNAM_OBJ(str), 0L);
Expand All @@ -687,7 +714,8 @@ Obj FuncIntHexString( Obj self, Obj str )
res = INTOBJ_INT(0);
return res;
}
if (*(CHARS_STRING(str)) == '-') {
p = CHARS_STRING(str);
if (*p == '-') {
sign = -1;
i = 1;
}
Expand All @@ -696,60 +724,44 @@ Obj FuncIntHexString( Obj self, Obj str )
i = 0;
}

while ((CHARS_STRING(str))[i] == '0' && i < len)
while (p[i] == '0' && i < len)
i++;
len -= i;

if ((len-i)*4 <= NR_SMALL_INT_BITS) {
n = 0;
p = CHARS_STRING(str);
for (; i<len; i++) {
a = p[i];
if (a>='a')
a -= 'a' - 10;
else if (a>='A')
a -= 'A' - 10;
else
a -= '0';
if (a > 15)
ErrorMayQuit("IntHexString: non-valid character in hex-string",
0L, 0L);
n = (n << 4) + a;
}
if (len*4 <= NR_SMALL_INT_BITS) {
n = hexstr2int( p + i, len );
res = INTOBJ_INT(sign * n);
return res;
}

else {
nd = (len-i)/INTEGER_UNIT_SIZE;
if (nd * INTEGER_UNIT_SIZE < (len-i)) nd++;
/* nd += ((3*nd) % 4); */
if (sign == 1)
res = NewBag( T_INTPOS, nd*sizeof(TypLimb) );
else
res = NewBag( T_INTNEG, nd*sizeof(TypLimb) );

p = CHARS_STRING(str)+i;

/* findme */
/* the following destroys the supplied string - document this */
for (j=0;j<len-i;j++){
c=p[j];
if (IsDigit(c))
p[j] = c - '0';
else if (islower((unsigned int)c))
p[j] = c - 'a' + 10;
else if (isupper((unsigned int)c))
p[j] = c - 'A' + 10;
else
ErrorMayQuit("IntHexString: non-valid character in hex-string",
0L, 0L);
if (p[j] >= 16)
ErrorMayQuit("IntHexString: non-valid character in hex-string",
0L, 0L);
/* Each hex digit corresponds to to 4 bits, and each GMP limb has INTEGER_UNIT_SIZE
bytes, thus 2*INTEGER_UNIT_SIZE hex digits fit into one limb. We use this
to compute the number of limbs minus 1: */
nd = (len - 1) / (2*INTEGER_UNIT_SIZE);
res = NewBag( (sign == 1) ? T_INTPOS : T_INTNEG, (nd + 1) * sizeof(TypLimb) );

/* update pointer, in case a garbage collection happened */
p = CHARS_STRING(str) + i;
limbs = ADDR_INT(res);

/* if len is not divisible by 2*INTEGER_UNIT_SIZE, then take care of the extra bytes */
UInt diff = len - nd * (2*INTEGER_UNIT_SIZE);
if ( diff ) {
n = hexstr2int( p, diff );
p += diff;
len -= diff;
limbs[nd--] = n;
}

/* */
while ( len ) {
n = hexstr2int( p, 2*INTEGER_UNIT_SIZE );
p += 2*INTEGER_UNIT_SIZE;
len -= 2*INTEGER_UNIT_SIZE;
limbs[nd--] = n;
}

mpn_set_str(ADDR_INT(res),p,len-i,16);
res = GMP_NORMALIZE(res);
res = GMP_REDUCE(res);
return res;
Expand Down
9 changes: 6 additions & 3 deletions tst/testinstall/intarith.tst
Original file line number Diff line number Diff line change
Expand Up @@ -490,18 +490,21 @@ gap> HexStringInt("abc");
Error, HexStringInt: argument must be an integer (not a list (string))
gap> List(dataHex, IntHexString) = data;
true
gap> dataHex; # HexStringInt used to destroy its argument
[ "-56BC75E2D63100001", "-56BC75E2D63100000", "-2710", "-1", "0", "1",
"2710", "56BC75E2D63100000", "56BC75E2D63100001" ]
gap> IntHexString("");
0
gap> IntHexString("a");
10
gap> IntHexString("A");
10
gap> IntHexString("x");
Error, IntHexString: non-valid character in hex-string
Error, IntHexString: invalid character in hex-string
gap> IntHexString("56BC75E2D63100000x");
Error, IntHexString: non-valid character in hex-string
Error, IntHexString: invalid character in hex-string
gap> IntHexString("56BC75E2D63100000@");
Error, IntHexString: non-valid character in hex-string
Error, IntHexString: invalid character in hex-string
gap> IntHexString(0);
Error, IntHexString: argument must be string (not a integer)
gap> IntHexString("-1000000000000000");
Expand Down