From 4108686545a62a3348b3b9a72da6a5d5b86e7ed2 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 5 Feb 2018 10:25:43 +0100 Subject: [PATCH] kernel: use LcmInt in order computations, fix GC bugs The order computation for permutations, partial permutations and transformations now uses LcmInt(). Also, fixed a garbage collection related bug in each: a GC could invalidate pointers to a temporary object --- src/integer.h | 9 +++++++++ src/permutat.c | 25 ++++++++++--------------- src/pperm.c | 24 +++++++----------------- src/trans.c | 38 +++++++++++++++----------------------- 4 files changed, 41 insertions(+), 55 deletions(-) diff --git a/src/integer.h b/src/integer.h index b8a78feb5a..1c6c5ca279 100644 --- a/src/integer.h +++ b/src/integer.h @@ -326,6 +326,15 @@ extern Obj RemInt( Obj opL, Obj opR ); extern Obj GcdInt( Obj opL, Obj opR ); +/**************************************************************************** +** +*F LcmInt( , ) . . . . . . . lcm of two integers +** +** 'LcmInt' returns the lcm of the two integers and . +*/ +extern Obj LcmInt( Obj opL, Obj opR ); + + /**************************************************************************** ** *F AInvInt( ) . . . . . . . . . . . . . additive inverse of an integer diff --git a/src/permutat.c b/src/permutat.c index 79d61623e4..53270a0602 100644 --- a/src/permutat.c +++ b/src/permutat.c @@ -2707,7 +2707,6 @@ Obj FuncOrderPerm ( UInt2 * ptKnown2; /* pointer to temporary bag */ UInt4 * ptKnown4; /* pointer to temporary bag */ UInt len; /* length of one cycle */ - UInt gcd, s, t; /* gcd( len, ord ), temporaries */ UInt p, q; /* loop variables */ /* check arguments and extract permutation */ @@ -2747,13 +2746,11 @@ Obj FuncOrderPerm ( len++; ptKnown2[q] = 1; } - /* compute the gcd with the previously order ord */ - /* Note that since len is single precision, ord % len is to*/ - gcd = len; s = INT_INTOBJ( ModInt( ord, INTOBJ_INT(len) ) ); - while ( s != 0 ) { - t = s; s = gcd % s; gcd = t; - } - ord = ProdInt( ord, INTOBJ_INT( len / gcd ) ); + ord = LcmInt( ord, INTOBJ_INT( len ) ); + + // update bag pointers, in case a garbage collection happened + ptPerm2 = CONST_ADDR_PERM2(perm); + ptKnown2 = ADDR_PERM2(TmpPerm); } @@ -2787,13 +2784,11 @@ Obj FuncOrderPerm ( len++; ptKnown4[q] = 1; } - /* compute the gcd with the previously order ord */ - /* Note that since len is single precision, ord % len is to*/ - gcd = len; s = INT_INTOBJ( ModInt( ord, INTOBJ_INT(len) ) ); - while ( s != 0 ) { - t = s; s = gcd % s; gcd = t; - } - ord = ProdInt( ord, INTOBJ_INT( len / gcd ) ); + ord = LcmInt( ord, INTOBJ_INT( len ) ); + + // update bag pointers, in case a garbage collection happened + ptPerm4 = CONST_ADDR_PERM4(perm); + ptKnown4 = ADDR_PERM4(TmpPerm); } diff --git a/src/pperm.c b/src/pperm.c index f03fc61ba4..8c7dd1b18f 100644 --- a/src/pperm.c +++ b/src/pperm.c @@ -617,7 +617,7 @@ Obj FuncPREIMAGE_PPERM_INT(Obj self, Obj f, Obj pt) // the least m, r such that f^m=f^m+r Obj FuncINDEX_PERIOD_PPERM(Obj self, Obj f) { - UInt i, len, j, pow, gcd, rank, k, deg, n; + UInt i, len, j, pow, rank, k, deg, n; UInt2 * ptf2; UInt4 * ptseen, *ptf4; Obj dom, img, ord, out; @@ -670,14 +670,9 @@ Obj FuncINDEX_PERIOD_PPERM(Obj self, Obj f) len++; ptseen[k - 1] = 0; } - gcd = len; - j = INT_INTOBJ(ModInt(ord, INTOBJ_INT(len))); - while (j != 0) { - k = j; - j = gcd % j; - gcd = k; - } - ord = ProdInt(ord, INTOBJ_INT(len / gcd)); + ord = LcmInt(ord, INTOBJ_INT(len)); + // update ptseen, in case a garbage collection happened + ptseen = (UInt4 *)(ADDR_OBJ(TmpPPerm)); } } } @@ -712,14 +707,9 @@ Obj FuncINDEX_PERIOD_PPERM(Obj self, Obj f) len++; ptseen[k - 1] = 0; } - gcd = len; - j = INT_INTOBJ(ModInt(ord, INTOBJ_INT(len))); - while (j != 0) { - k = j; - j = gcd % j; - gcd = k; - } - ord = ProdInt(ord, INTOBJ_INT(len / gcd)); + ord = LcmInt(ord, INTOBJ_INT(len)); + // update ptseen, in case a garbage collection happened + ptseen = (UInt4 *)(ADDR_OBJ(TmpPPerm)); } } } diff --git a/src/trans.c b/src/trans.c index 43cff15f0f..66a4fca325 100644 --- a/src/trans.c +++ b/src/trans.c @@ -1406,7 +1406,7 @@ Obj FuncIndexPeriodOfTransformation(Obj self, Obj f) UInt4 * seen; UInt deg, i, pt, dist, pow, len, last_pt; Obj ord, out; - Int s, t, gcd, cyc; + Int cyc; if (!IS_TRANS(f)) { ErrorQuit("IndexPeriodOfTransformation: the argument must be a " @@ -1464,18 +1464,14 @@ Obj FuncIndexPeriodOfTransformation(Obj self, Obj f) seen[pt] = 1; } - // compute the gcd of the cycle length with the previous - // order ord - gcd = cyc; - s = INT_INTOBJ(ModInt(ord, INTOBJ_INT(cyc))); - while (s != 0) { - t = s; - s = gcd % s; - gcd = t; - } - ord = ProdInt(ord, INTOBJ_INT(cyc / gcd)); - dist = len - cyc + 1; + ord = LcmInt(ord, INTOBJ_INT(cyc)); + // the distance of i from the cycle in its component + 1 + dist = len - cyc + 1; + + // update bag pointers, in case a garbage collection happened + ptf2 = CONST_ADDR_TRANS2(f); + seen = ADDR_TRANS4(TmpTrans); } if (dist > pow) { pow = dist; @@ -1513,18 +1509,14 @@ Obj FuncIndexPeriodOfTransformation(Obj self, Obj f) seen[pt] = 1; } - // compute the gcd of the cycle length with the previous - // order ord - gcd = cyc; - s = INT_INTOBJ(ModInt(ord, INTOBJ_INT(cyc))); - while (s != 0) { - t = s; - s = gcd % s; - gcd = t; - } - ord = ProdInt(ord, INTOBJ_INT(cyc / gcd)); - dist = len - cyc + 1; + ord = LcmInt(ord, INTOBJ_INT(cyc)); + // the distance of i from the cycle in its component + 1 + dist = len - cyc + 1; + + // update bag pointers, in case a garbage collection happened + ptf4 = CONST_ADDR_TRANS4(f); + seen = ADDR_TRANS4(TmpTrans); } if (dist > pow) { pow = dist;