Skip to content

Commit

Permalink
Add optimised SmallestMovedPoint
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisJefferson authored and fingolfin committed Nov 13, 2019
1 parent 22eebc7 commit 3cca408
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 7 deletions.
6 changes: 6 additions & 0 deletions lib/permutat.g
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,12 @@ InstallMethod( SmallestMovedPoint,
end );


InstallMethod( SmallestMovedPoint,
"for an internal permutation",
[ IsPerm and IsInternalRep ],
SMALLEST_MOVED_POINT_PERM );


#############################################################################
##
#m LargestMovedPoint( <perm> ) . . . . . . . . for internal permutation
Expand Down
50 changes: 50 additions & 0 deletions src/permutat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1125,6 +1125,40 @@ UInt LargestMovedPointPerm(Obj perm)
return LargestMovedPointPerm_<UInt4>(perm);
}

/****************************************************************************
**
*F SmallestMovedPointPerm( <perm> ) smallest point moved by perm
**
** 'SmallestMovedPointPerm' implements 'SmallestMovedPoint' for internal
** permutations.
*/

// Import 'Infinity', as a return value for the identity permutation
static Obj Infinity;

template <typename T>
static inline Obj SmallestMovedPointPerm_(Obj perm)
{
const T * ptPerm = CONST_ADDR_PERM<T>(perm);
UInt deg = DEG_PERM<T>(perm);

for (UInt i = 1; i <= deg; i++) {
if (ptPerm[i - 1] != i - 1)
return INTOBJ_INT(i);
}
return Infinity;
}

static Obj SmallestMovedPointPerm(Obj perm)
{
GAP_ASSERT(TNUM_OBJ(perm) == T_PERM2 || TNUM_OBJ(perm) == T_PERM4);

if (TNUM_OBJ(perm) == T_PERM2)
return SmallestMovedPointPerm_<UInt2>(perm);
else
return SmallestMovedPointPerm_<UInt4>(perm);
}


/****************************************************************************
**
Expand All @@ -1141,6 +1175,18 @@ static Obj FuncLARGEST_MOVED_POINT_PERM(Obj self, Obj perm)
return INTOBJ_INT(LargestMovedPointPerm(perm));
}

/****************************************************************************
**
*F FuncSMALLEST_MOVED_POINT_PERM( <self>, <perm> )
**
** GAP-level wrapper for 'SmallestMovedPointPerm'.
*/
static Obj FuncSMALLEST_MOVED_POINT_PERM(Obj self, Obj perm)
{
RequirePermutation("SmallestMovedPointPerm", perm);

return SmallestMovedPointPerm(perm);
}

/****************************************************************************
**
Expand Down Expand Up @@ -2736,6 +2782,7 @@ static StructGVarFunc GVarFuncs [] = {

GVAR_FUNC_1ARGS(PermList, list),
GVAR_FUNC_1ARGS(LARGEST_MOVED_POINT_PERM, perm),
GVAR_FUNC_1ARGS(SMALLEST_MOVED_POINT_PERM, perm),
GVAR_FUNC_2ARGS(CYCLE_LENGTH_PERM_INT, perm, point),
GVAR_FUNC_2ARGS(CYCLE_PERM_INT, perm, point),
GVAR_FUNC_1ARGS(CYCLE_STRUCT_PERM, perm),
Expand Down Expand Up @@ -2784,6 +2831,9 @@ static Int InitKernel (

ImportGVarFromLibrary("PERM_INVERSE_THRESHOLD", &PERM_INVERSE_THRESHOLD);

/* needed for SmallestMovedPoint */
ImportGVarFromLibrary("infinity", &Infinity);

/* install the type functions */
ImportGVarFromLibrary( "TYPE_PERM2", &TYPE_PERM2 );
ImportGVarFromLibrary( "TYPE_PERM4", &TYPE_PERM4 );
Expand Down
40 changes: 33 additions & 7 deletions tst/testinstall/perm.tst
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#@local checklens,n,permAll,permBig,permSml,x,y
#@local checklens,n,permAll,permBig,permSml,x,y, moved
gap> START_TEST("perm.tst");

# Permutations come in two flavors in GAP, with two TNUMs: T_PERM2 for
Expand Down Expand Up @@ -314,12 +314,38 @@ gap> PermList(Concatenation([1..70000],[70001,1,70003]));
fail

#
# LARGEST_MOVED_POINT_PERM
#
gap> LARGEST_MOVED_POINT_PERM((2,3));
3
gap> LARGEST_MOVED_POINT_PERM((2,70000));
70000
# SmallestMovedPoint, LargestMovedPoint, MovedPoints, NrMovedPoints
#
gap> moved := {p} -> [SmallestMovedPoint(p), LargestMovedPoint(p), MovedPoints(p), NrMovedPoints(p)];;
gap> moved((2,3));
[ 2, 3, [ 2, 3 ], 2 ]
gap> moved((2,70000));
[ 2, 70000, [ 2, 70000 ], 2 ]
gap> moved((70000, 70001));
[ 70000, 70001, [ 70000, 70001 ], 2 ]
gap> moved((1,2,3,4));
[ 1, 4, [ 1, 2, 3, 4 ], 4 ]
gap> moved(());
[ infinity, 0, [ ], 0 ]
gap> moved((1,2,3,4)^4);
[ infinity, 0, [ ], 0 ]
gap> moved([]);
[ infinity, 0, [ ], 0 ]
gap> moved([()]);
[ infinity, 0, [ ], 0 ]
gap> moved([(1,2),(5,6)]);
[ 1, 6, [ 1, 2, 5, 6 ], 4 ]
gap> moved(SymmetricGroup([5,7,9]));
[ 5, 9, [ 5, 7 .. 9 ], 3 ]
gap> moved(SymmetricGroup([5,7,9,70000]));
[ 5, 70000, [ 5, 7, 9, 70000 ], 4 ]
gap> moved(SymmetricGroup(1));
[ infinity, 0, [ ], 0 ]
gap> moved(Group((8,9,10),(13,15,19)));
[ 8, 19, [ 8, 9, 10, 13, 15, 19 ], 6 ]
gap> SMALLEST_MOVED_POINT_PERM(fail);
Error, SmallestMovedPointPerm: <perm> must be a permutation (not the value 'fa\
il')
gap> LARGEST_MOVED_POINT_PERM(fail);
Error, LargestMovedPointPerm: <perm> must be a permutation (not the value 'fai\
l')
Expand Down

0 comments on commit 3cca408

Please sign in to comment.