Skip to content

Commit

Permalink
kernel: use LcmInt in order computations, fix GC bugs
Browse files Browse the repository at this point in the history
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
  • Loading branch information
fingolfin committed Feb 5, 2018
1 parent 29f0678 commit 4108686
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 55 deletions.
9 changes: 9 additions & 0 deletions src/integer.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,15 @@ extern Obj RemInt( Obj opL, Obj opR );
extern Obj GcdInt( Obj opL, Obj opR );


/****************************************************************************
**
*F LcmInt( <opL>, <opR> ) . . . . . . . lcm of two integers
**
** 'LcmInt' returns the lcm of the two integers <opL> and <opR>.
*/
extern Obj LcmInt( Obj opL, Obj opR );


/****************************************************************************
**
*F AInvInt( <op> ) . . . . . . . . . . . . . additive inverse of an integer
Expand Down
25 changes: 10 additions & 15 deletions src/permutat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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);

}

Expand Down Expand Up @@ -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);

}

Expand Down
24 changes: 7 additions & 17 deletions src/pperm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
}
}
}
Expand Down Expand Up @@ -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));
}
}
}
Expand Down
38 changes: 15 additions & 23 deletions src/trans.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 4108686

Please sign in to comment.