Skip to content

Commit

Permalink
Re-implement ListPerm as a kernel function
Browse files Browse the repository at this point in the history
  • Loading branch information
fingolfin committed Jan 9, 2024
1 parent e26b1eb commit 581989d
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 25 deletions.
18 changes: 0 additions & 18 deletions lib/permutat.g
Original file line number Diff line number Diff line change
Expand Up @@ -464,24 +464,6 @@ SetOne( PermutationsFamily, () );
## </ManSection>
## <#/GAPDoc>
##
BIND_GLOBAL( "ListPerm", function( perm, n... )
if not IsPerm(perm) then
Error("ListPerm: <perm> must be a permutation");
fi;
if Length(n)=1 then
n := n[1];
if not IsInt(n) then
Error("ListPerm: <n> must be an integer");
fi;
else
n := LargestMovedPoint(perm);
fi;
if IsOne(perm) then
return [1..n];
else
return OnTuples( [1..n], perm );
fi;
end );


#############################################################################
Expand Down
10 changes: 4 additions & 6 deletions src/listfunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1528,15 +1528,13 @@ static Int InitKernel (
StructInitInfo * module )
{
// init filters and functions
/* ADD_LIST needs special consideration because we want distinct kernel
handlers for 2 and 3 arguments */
InitHandlerFunc( FuncADD_LIST, "src/listfunc.c:FuncADD_LIST" );
InitHandlerFunc( FuncADD_LIST3, "src/listfunc.c:FuncADD_LIST3" );

InitHdlrOpersFromTable( GVarOpers );
InitHdlrFuncsFromTable( GVarFuncs );


// ADD_LIST needs special consideration because we want distinct kernel
// handlers for 2 and 3 arguments
InitHandlerFunc( FuncADD_LIST, "src/listfunc.c:FuncADD_LIST" );
InitHandlerFunc( FuncADD_LIST3, "src/listfunc.c:FuncADD_LIST3" );

return 0;
}
Expand Down
93 changes: 93 additions & 0 deletions src/permutat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,72 @@ static Obj FuncPermList(Obj self, Obj list)
}
}

template <typename T>
static inline Obj ListPerm_(Obj perm, UInt len)
{
Obj res; // handle of the image, result
Obj * ptRes; // pointer to the result
const T * ptPrm; // pointer to the permutation
UInt lmp; // largest moved point
UInt i; // loop variable

lmp = DEG_PERM<T>(perm);
if (len == 0)
len = lmp;
else if (len < lmp)
lmp = len;

if (len == 0)
return NewEmptyPlist();

// copy the list into a mutable plist, which we will then modify in place
res = NEW_PLIST(T_PLIST_CYC, len);
SET_LEN_PLIST(res, len);

// get the pointer
ptRes = ADDR_OBJ(res) + 1;
ptPrm = CONST_ADDR_PERM<T>(perm);

// loop over the entries of the permutation
for (i = 1; i <= lmp; i++, ptRes++) {
*ptRes = INTOBJ_INT(ptPrm[i - 1] + 1);
}
// add extras if requested
for (; i <= len; i++, ptRes++) {
*ptRes = INTOBJ_INT(i);
}

//CHANGED_BAG( res );

return res;
}

static Obj ListPermOper;

static Obj FuncListPerm1(Obj self, Obj perm)
{
RequirePermutation(SELF_NAME, perm);

if (TNUM_OBJ(perm) == T_PERM2)
return ListPerm_<UInt2>(perm, 0);
else
return ListPerm_<UInt4>(perm, 0);

Check warning on line 1150 in src/permutat.cc

View check run for this annotation

Codecov / codecov/patch

src/permutat.cc#L1150

Added line #L1150 was not covered by tests
}

static Obj FuncListPerm2(Obj self, Obj perm, Obj n)
{
RequirePermutation(SELF_NAME, perm);
Int nn = GetSmallInt(SELF_NAME, n);
if (nn <= 0) {
return NewEmptyPlist();
}

if (TNUM_OBJ(perm) == T_PERM2)
return ListPerm_<UInt2>(perm, nn);
else
return ListPerm_<UInt4>(perm, nn);
}

/****************************************************************************
**
*F LargestMovedPointPerm( <perm> ) largest point moved by perm
Expand Down Expand Up @@ -2744,6 +2810,22 @@ static StructGVarFilt GVarFilts[] = {
};



/****************************************************************************
**
*V GVarOpers . . . . . . . . . . . . . . . . . list of operations to export
*/
static StructGVarOper GVarOpers [] = {

// ListPerm can take 1 or 2 arguments; since NewOperation ignores the
// handler for variadic operations, use DoOperation0Args as a placeholder.
{ "ListPerm", -1, "perm[, n]", &ListPermOper,
(ObjFunc)DoOperation0Args, "src/permutat.cc:ListPerm" },

{ 0, 0, 0, 0, 0, 0 }

};

/****************************************************************************
**
*V GVarFuncs . . . . . . . . . . . . . . . . . . list of functions to export
Expand Down Expand Up @@ -2817,8 +2899,14 @@ static Int InitKernel (

// init filters and functions
InitHdlrFiltsFromTable( GVarFilts );
InitHdlrOpersFromTable( GVarOpers );
InitHdlrFuncsFromTable( GVarFuncs );

// ListPerm needs special consideration because we want distinct kernel
// handlers for 1 and 2 arguments
InitHandlerFunc( (ObjFunc)FuncListPerm1, "src/permutat.cc:FuncListPerm1" );
InitHandlerFunc( (ObjFunc)FuncListPerm2, "src/permutat.cc:FuncListPerm2" );

// make the buffer bag
#ifndef HPCGAP
InitGlobalBag( &TmpPerm, "src/permutat.cc:TmpPerm" );
Expand Down Expand Up @@ -2924,8 +3012,13 @@ static Int InitLibrary (
{
// init filters and functions
InitGVarFiltsFromTable( GVarFilts );
InitGVarOpersFromTable( GVarOpers );
InitGVarFuncsFromTable( GVarFuncs );

// make and install the 'ListPerm' operation
SET_HDLR_FUNC( ListPermOper, 1, (ObjFunc)FuncListPerm1);
SET_HDLR_FUNC( ListPermOper, 2, (ObjFunc)FuncListPerm2);

// make the identity permutation
IdentityPerm = NEW_PERM2(0);

Expand Down
2 changes: 1 addition & 1 deletion tst/testinstall/perm.tst
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ gap> ListPerm( (), 0 );
gap> ListPerm( (), 1 );
[ 1 ]
gap> ListPerm( (), 5 );
[ 1 .. 5 ]
[ 1, 2, 3, 4, 5 ]
gap> ListPerm( (1,2,3) );
[ 2, 3, 1 ]
gap> ListPerm( (1,2,3), -1 );
Expand Down

0 comments on commit 581989d

Please sign in to comment.