#############################################################################
##
#W  moufang_modifications.gi   Moufang modifications [loops]
##  
#H  @(#)$Id: moufang_modifications.gi, v 3.0.0 2015/06/15 gap Exp $
##  
#Y  Copyright (C)  2004,  G. P. Nagy (University of Szeged, Hungary),  
#Y                        P. Vojtechovsky (University of Denver, USA)
##

#############################################################################
##  LOOPS M(G,2)
##  -------------------------------------------------------------------------

#############################################################################
##  
#F  LoopMG2( G ) 
##    
##  Returns the Chein loop M(G,2) constructed from a group <G>.
##  See documentation for details.

InstallGlobalFunction( LoopMG2, function( G )

    local T, inv, n, L, i, j;

    T := MultiplicationTable( Elements( G ) );
    n := Size( G );
    inv := List( [1..n], i->Position( T[i], 1 ) );  #inverses
    L := List( [1..2*n], i->[]);
    
    for i in [1..n] do for j in [1..n] do
        L[ i ][ j ] := T[ i ][ j ];                 # g*h = gh
        L[ i ][ j+n ] := T[ j ][ i ] + n;           # g*hu = (hg)u
        L[ i+n ][ j ] := T[ i ][ inv[ j ] ] + n;    # gu*h = (gh^{-1})u
        L[ i+n ][ j+n ] := T[ inv[ j ] ][ i ];      # gu*hu = h^{-1}g
    od; od;
    
    return LoopByCayleyTable( L );
end);

#############################################################################
##  AUXILIARY FUNCTIONS FOR MOUFANG MODIFICATIONS
##  -------------------------------------------------------------------------

#############################################################################
##  
#F  LOOPS_PositionList( A, B ) 
##    
##  input: lists A, B
##  returns: list P, where P[i] is the position of B[i] in A

InstallGlobalFunction( LOOPS_PositionList,
function( A, B )
    local P, b;
    P := [];
    for b in B do Add( P, Position( A, b ) ); od;
    return P;
end);

#############################################################################
##  
#F  LOOPS_Modular( i, m ) 
##    
##  returns i modulo the set [-m+1..m]

InstallGlobalFunction( LOOPS_Modular,
function(i, m)
    while i>m do i:=i-2*m; od;
    while i<1-m do i:=i+2*m; od;
    return i;
end);

#############################################################################
##  
#F  LOOPS_DVSigma( i, m ) 
##
##  Calculates overflow of i modulo [-m+1..m].
##  See documentation for more details.
            
InstallGlobalFunction( LOOPS_DVSigma,
function( i, m )
    if i > m then return 1; fi;
    if i < 1 - m then return -1; fi;
    return 0;
end);

#############################################################################
##  CYCLIC MODIFICATION
##  -------------------------------------------------------------------------

#############################################################################
##  
#F  LoopByCyclicModification( L, S, a, h) 
##
##  Returns the cyclic modification of Moufang loop <L> with parameters
##  <S>, <a>, <h>, as described in the documentation.

# (MATH)
# L is a loop,
# S is a normal subloop of L, or a set generating a normal subloop of L,
# L/S is cyclic of order 2m, generated by aS,
# h is an element of Z(L) and S
# (PROG) 
# NOTHING IS CHECKED!!

InstallGlobalFunction( LoopByCyclicModification, function( L, S, a, h )

    local n, ih, m, aP, aa, i, iL, T, x, y, z, exponent;

    # making sure that S is a subloop of L
    if not IsLoop( S ) then S := Subloop( L, S ); fi;
    
    # converting all into numbers for faster calculation
    n := Size( L );
    ih := Position( Elements( L ), h^(-1) ); #inverse of h
    h := Position( Elements( L ), h );
    a := Position( Elements( L ), a );
    S := LOOPS_PositionList( Elements( L ), Elements( S ) );
    L := CayleyTable( L );
    
    # setting parameter m of the construction
    m := n / ( 2 * Length( S ) );

    # calculating all cosets a^i, for i in M
    aP := []; aa := 1;
    for i in [ 0..2*m-1 ] do
        Add( aP, List( S, j -> L[ aa ][ j ] ) );
        aa := L[ aa ][ a ];
    od;

    # into which cosets belong elements of L
    iL := List( [ 1..n ], x -> LOOPS_Modular( LOOPS_SublistPosition(aP, x ) - 1, m ) );

    # setting up the multiplication table
    T := List( [ 1..n ], i->[] );
    for x in [ 1..n ] do for y in [ 1..n ] do
        z := L[ x ][ y ];
        exponent := LOOPS_DVSigma( iL[ x ] + iL[ y ], m );
        if exponent = 1 then z := L[ z ][ h ]; fi;
        if exponent = -1 then z := L[ z ][ ih ]; fi;
        T[ x ][ y ] := z;
    od; od;

    return LoopByCayleyTable( T );
end);

#############################################################################
##  DIHEDRAL MODIFICATION
##  -------------------------------------------------------------------------

#############################################################################
##  
#F  LoopByDihedralModification( L, S, e, f, h) 
##
##  Returns the dihedral modification of Moufang loop <L> with parameters
##  <S>, <e>, <f>, <h>, as described in the documentation.

# (MATH)
# L is a loop,
# S is a normal subloop of L, or a set generating a normal subloop of L,
# L/S is dihedral of order 4m, 
# eS, fS are involutions of L/S such that eS*fS is of order 2m,
# let G0 be the union of cosets of L/S generated by eS*fS,
# h is an element of N(L), S and Z(G0).
# (PROG) 
# NOTHING IS CHECKED!!

InstallGlobalFunction( LoopByDihedralModification, function( L, S, e, f, h )

    local a, G0, n, m, ih, aP, aa, i, eP, fP, eL, fL, T, x, y, z, exp;

    # making sure that S is a subloop of L
    if not IsLoop( S ) then S := Subloop( L, S ); fi;
    
    # obtaining a and G0
    a := e * f; 
    G0:= Subloop( L, a * Elements( S ) );

    # all in numbers
    n := Size( L );
    ih := Position( Elements( L ), h^(-1) ); #inverse of h
    h := Position( Elements( L ), h );
    a := Position( Elements( L ), a );
    e := Position( Elements( L ), e );
    f := Position( Elements( L ), f );
    S := LOOPS_PositionList( Elements( L ), Elements( S ) );
    G0 := LOOPS_PositionList( Elements( L ), Elements( G0 ) );
    L := CayleyTable( L );

    # setting parameter m
    m := n / ( 4 * Length( S ) );

    # powers of aS, eS and fS
    aP := []; aa := 1;
    for i in [ 0..2*m-1 ] do
        Add( aP, List( S, i -> L[ aa ][ i ] ) );
        aa := L[ aa ][ a ];
    od;
    eP := List( aP, x -> Union( List( x, y -> [ y, L[ e ][ y ] ] ) ) );
    fP := List( aP, x -> Union( List( x, y -> [ y, L[ y ][ f ] ] ) ) );
    
    # into which cosets belong elements of L
    eL := List( [ 1..n ], x -> LOOPS_Modular( LOOPS_SublistPosition(eP, x ) - 1, m ) );
    fL := List( [ 1..n ], x -> LOOPS_Modular( LOOPS_SublistPosition(fP, x ) - 1, m ) );

    # setting up multiplication table
    T := List( L, x->[] );
    for x in [ 1..n ] do for y in [ 1..n ] do
        if y in G0 then exp := LOOPS_DVSigma( eL[ x ] + fL[ y ], m );
        else exp := (-1)*LOOPS_DVSigma( eL[ x ] + fL[ y ], m ); fi;
        z := L[ x ][ y ];
        if exp = 1 then z := L[ z ][ h ]; fi;
        if exp = -1 then z := L[ z ][ ih ]; fi;
        T[ x ][ y ] := z;
    od; od;

    return LoopByCayleyTable(T);
end);
