@@ -323,24 +323,51 @@ true
323323```
324324"""
325325function perm (g:: PermGroup , L:: AbstractVector{<:IntegerUnion} )
326- x = GAPWrap . PermList ( GapObj (L;recursive = true ) )
326+ x = _make_gap_perm ( degree (g), L )
327327 @req x != = GAP. Globals. fail " the list does not describe a permutation"
328- @req ( length (L) <= degree (g) && x in GapObj (g) ) " the element does not embed in the group"
328+ @req x in GapObj (g) " the element does not embed in the group"
329329 return PermGroupElem (g, x)
330330end
331331
332332perm (g:: PermGroup , L:: AbstractVector{<:ZZRingElem} ) = perm (g, [Int (y) for y in L])
333333
334334function (g:: PermGroup )(L:: AbstractVector{<:IntegerUnion} )
335- x = GAPWrap . PermList ( GapObj (L;recursive = true ) )
336- @req ( length (L) <= degree (g) && x in GapObj (g) ) " the element does not embed in the group"
335+ x = _make_gap_perm ( degree (g), L )
336+ @req x in GapObj (g) " the element does not embed in the group"
337337 return PermGroupElem (g, x)
338338end
339339
340+ function _make_gap_perm (deg:: Int , L:: Vector{<:IntegerUnion} )
341+ @req 0 <= deg " degree is $deg , must be non-negative"
342+ @req deg < 2 ^ 32 " degree is $deg , must be less than 2^32"
343+ @req length (L) <= deg " length(L) = $(length (L)) exceeds degree bound $deg "
344+ if deg < 2 ^ 16
345+ x = _make_gap_perm (UInt16, deg, L)
346+ else
347+ x = _make_gap_perm (UInt32, deg, L)
348+ end
349+ return x
350+ end
351+
352+ function _make_gap_perm (:: Type{T} , deg:: Int , L:: Vector{<:IntegerUnion} ) where {T <: Union{UInt16, UInt32} }
353+ if T === UInt16
354+ perm = @ccall GAP. libgap. NEW_PERM2 (deg:: Cint ):: GapObj
355+ else
356+ perm = @ccall GAP. libgap. NEW_PERM4 (deg:: Cint ):: GapObj
357+ end
358+ addr = Ptr {T} (GAP. ADDR_OBJ (perm)+ 8 ) # skip 8 byte header
359+
360+ for i in 1 : length (L)
361+ unsafe_store! (addr, UInt64 (L[i]) - 1 , i)
362+ end
363+ for i in 1 + length (L): deg
364+ unsafe_store! (addr, i - 1 , i)
365+ end
366+ return perm
367+ end
368+
340369(g:: PermGroup )(L:: AbstractVector{<:ZZRingElem} ) = g ([Int (y) for y in L])
341370
342- # cperm stands for "cycle permutation", but we can change name if we want
343- # takes as input a list of vectors (not necessarily disjoint)
344371@doc raw """
345372 cperm(L::AbstractVector{<:T}...) where T <: IntegerUnion
346373 cperm(L::AbstractVector{<:AbstractVector{T}}) where T <: IntegerUnion
@@ -501,9 +528,24 @@ Base.Vector(x::PermGroupElem, n::Int = x.parent.deg) = Vector{Int}(x,n)
501528# evaluation function
502529(x:: PermGroupElem )(n:: IntegerUnion ) = n^ x
503530
504- ^ (n:: T , x:: PermGroupElem ) where T <: IntegerUnion = T (GAP. Obj (n)^ GapObj (x))
531+ function ^ (n:: T , g:: PermGroupElem ) where T <: IntegerUnion
532+ return fits (Int, n) ? T (Int (n)^ g) : n
533+ end
534+
535+ function ^ (n:: Int , g:: PermGroupElem )
536+ @req n > 0 " permutations only act on positive integers"
537+ large = (GAP. TNUM_OBJ (GapObj (g)) == GAP. T_PERM4)
538+ deg = GAP. SIZE_OBJ (GapObj (g)) - 8 # subtract 9 byte header
539+ deg >>= large ? 2 : 1
540+ n > deg && return n
505541
506- ^ (n:: Int , x:: PermGroupElem ) = (n^ GapObj (x)):: Int
542+ addr = GAP. ADDR_OBJ (GapObj (g))+ 8 # skip 8 byte header
543+ if large
544+ return Int (unsafe_load (Ptr {UInt32} (addr), n))+ 1
545+ else
546+ return Int (unsafe_load (Ptr {UInt16} (addr), n))+ 1
547+ end
548+ end
507549
508550
509551@doc raw """
0 commit comments