##############################################################################
##
#W  map3.gi                         XMOD Package                 Chris Wensley
##
##  Installation file for functions of the XMOD package.
##
#H  @(#)$Id: map3.gi,v 2.007 2006/07/04 gap Exp $
##
#Y  Copyright (C) 1999,2001 University of St. Andrews, North Haugh,
#Y                          St. Andrews, Fife KY16 9SS, Scotland
##
Revision.("xmod/gap/map3_gi") := 
   "@(#)$Id: map3.gi,v 2.007 2006/07/04 gap Exp $";

##############################################################################
##
#M  Make3dMapping( <src>, <rng>, <up>, <lt>, <down>, <rt> ) .... 3d-object map
##
InstallMethod( Make3dMapping,
    "for two 3d-objects and four 2d-morphisms", true, [ Is3dObject, 
    Is3dObject, Is2dMapping, Is2dMapping, Is2dMapping, Is2dMapping ], 0,
function( src, rng, upmor, leftmor, downmor, rightmor )

    local  filter, fam, mor;

    fam := FamilyObj( [ src, rng, upmor, leftmor, downmor, rightmor ] );
    filter := Is3dMappingRep;
    mor := rec();
    ObjectifyWithAttributes( mor, 
      NewType( fam, filter ),
      Source, src,
      Range, rng,
      Up2dMorphism, upmor,
      Left2dMorphism, leftmor,
      Down2dMorphism, downmor, 
      Right2dMorphism, rightmor );
    return mor;
end );


#############################################################################
##
#M  IsPreXSqMorphism                check the axioms for a pre-crossed square
##
InstallMethod( IsPreXSqMorphism,
    "generic method for pre-crossed module homomorphisms",
    true, [ Is3dMapping ], 0,
function( mor )

    local  PS, QS, upmor, leftmor, downmor, rightmor, ok;

    PS := Source( mor );
    QS := Range( mor );
    if not ( IsPreXSq( PS ) and IsPreXSq( QS ) ) then
        return false;
    fi;
    ### (1) check that the morphisms commute
    upmor := Up2dMorphism( mor );
    leftmor := Left2dMorphism( mor );
    rightmor := Right2dMorphism( mor );
    downmor := Down2dMorphism( mor );
    ok := ( ( SourceHom( upmor ) = SourceHom( leftmor ) ) and
            ( RangeHom( upmor ) = SourceHom( rightmor ) ) and
            ( RangeHom( leftmor ) = SourceHom( downmor ) ) and
            ( RangeHom( rightmor ) = RangeHom( downmor ) ) );
    if not ok then
        return false;
    fi;
    ### (2) check the remaining axioms
    Print( "\n#I  Warning: IsPreXSqMorphism not fully implemented!\n\n" );
    return true;
end );

#############################################################################
##
#M  IsXSqMorphism
##
InstallMethod( IsXSqMorphism,
    "generic method for pre-crossed square morphisms", true,
    [ IsPreXSqMorphism ], 0,
function( mor )
    return ( IsXSq( Source( mor ) ) and IsXSq(  Range( mor ) ) );
end );

InstallMethod( IsXSqMorphism, "generic method for 3d-mappings", true,
    [ Is3dMapping ], 0,
function( mor )
    local  ispre;
    ispre := IsPreXSqMorphism( mor );
    if not ispre then
        return false;
    else
        return ( IsXSq( Source( mor ) ) and IsXSq(  Range( mor ) ) );
    fi;
end );

##############################################################################
##
#M  \=( <mor>, <phi> ) . . . . . test if two morphisms of 3d-objects are equal
##
InstallMethod( \=,
    "generic method for two 3d-morphisms",
    IsIdenticalObj, [ Is3dMapping, Is3dMapping ], 0,
    function ( mor, phi )
    return (     ( Source( mor ) = Source( phi ) )
             and ( Range( mor ) = Range( phi ) )
             and ( Up2dMorphism( mor ) = Up2dMorphism( phi ) )
             and ( Left2dMorphism( mor ) = Left2dMorphism( phi ) )
             and ( Down2dMorphism( mor ) = Down2dMorphism( phi ) )
             and ( Right2dMorphism( mor ) = Right2dMorphism( phi ) ) );
end );

#############################################################################
##
#F  MappingGeneratorsImages( <map> ) . . . . . . . . . . . .  for a 3dMapping
##
InstallOtherMethod( MappingGeneratorsImages, "for a 3dMapping", true,
    [ Is3dMapping ], 0,
    function( map )
    return [ MappingGeneratorsImages( Up2dMorphism( map ) ),
             MappingGeneratorsImages( Left2dMorphism( map ) ),
             MappingGeneratorsImages( Down2dMorphism( map ) ),
             MappingGeneratorsImages( Right2dMorphism( map ) ) ];
end );

#############################################################################
##
#M  Name                                                       for a pre-xsq
##
InstallMethod( Name, "method for a 3d-mapping", true, [ Is3dMapping ], 0,
function( mor )

    local  nsrc, nrng, name;

    if HasName( Source( mor ) ) then
        nsrc := Name( Source( mor ) );
    else
        nsrc := "[..]";
    fi;
    if HasName( Range( mor ) ) then
        nrng := Name( Range( mor ) );
    else
        nrng := "[..]";
    fi;
    name := Concatenation( "[", nsrc, " => ", nrng, "]" );
    SetName( mor, name );
    return name;
end );

#############################################################################
##
#F  Display( <mor> ) . . . . print details of a (pre-)crossed square morphism
##
InstallMethod( Display, "display a morphism of pre-crossed squares", true,
    [ IsPreXSqMorphism ], 0,
    function( mor )

    local  upmor, downmor, P, Q;

    P := Source( mor );
    Q := Range( mor );
    upmor := Up2dMorphism( mor );
    downmor := Down2dMorphism( mor );
    if IsXSqMorphism( mor ) then
        Print( "Morphism of crossed squares :- \n" );
    else
        Print( "Morphism of pre-crossed squares :- \n" );
    fi;
    if HasName( P ) then
        Print( ":    Source = ", Name( P ), "\n" );
    else
        Print( ":    Source = \n", P, "\n" );
    fi;
    if HasName( Q ) then
        Print( ":     Range = ", Name( Q ), "\n" );
    else
        Print( ":     Range = \n", Q, "\n" );
    fi;
    if HasOrder( mor ) then
        Print( ":     order = ", Order( mor ), "\n" );
    fi;
    Print( ":    up-left: ", MappingGeneratorsImages(SourceHom(upmor)),"\n");
    Print( ":   up-right: ", MappingGeneratorsImages(RangeHom(upmor)),"\n");
    Print( ":  down-left: ", MappingGeneratorsImages(SourceHom(downmor)),"\n");
    Print( ": down-right: ", MappingGeneratorsImages(RangeHom(downmor)),"\n");
end ); 

##############################################################################
##
#M  IdentityMapping( <obj> )
##
InstallOtherMethod( IdentityMapping, "for 3d-group object", true,
    [ Is3dObject ], 0,
function( obj )

    local  up, left, down, right;

    up := IdentityMapping( Up2dObject( obj ) );
    left := IdentityMapping( Left2dObject( obj ) );
    down := IdentityMapping( Down2dObject( obj ) );
    right := IdentityMapping( Right2dObject( obj ) );
    if IsPreXSq( obj ) then
        return PreXSqMorphismByMorphisms( obj, obj, up, left, down, right );
    elif IsPreCat2( obj ) then
        return PreCat2MorphismByMorphisms( obj, obj, up, left, down, right );
    else
        return fail;
    fi;
end );

##############################################################################
##
#M  InclusionMorphism3dObjects( <obj>, <sub> )
##
InstallMethod( InclusionMorphism3dObjects, "of one 3d-object in another", 
    true, [ Is3dObject, Is3dObject ], 0,
function( obj, sub )

    local  up, left, down, right;

    up := InclusionMorphism2dObjects( Up2dObject(obj), Up2dObject(sub) );
    left := InclusionMorphism2dObjects( Left2dObject(obj), Left2dObject(sub) );
    down := InclusionMorphism2dObjects( Down2dObject(obj), Down2dObject(sub) );
    right := InclusionMorphism2dObjects( Right2dObject(obj), 
                                         Right2dObject(sub) );
    if IsPreXSq( obj ) then
        return PreXSqMorphismByMorphisms( sub, obj, up, left, down, right );
    elif IsPreCat2( obj ) then
        return PreCat2MorphismByMorphisms( sub, obj, up, left, down, right );
    else
        return fail;
    fi;
end );

##############################################################################
##
#F  XSqMorphism( <src>, <rng>, <up>, <lt>, <rt>, <dn> )      x-square morphism
##
##  (need to extend to other sets of parameters)
##
InstallGlobalFunction( XSqMorphism, function( arg )

    local  nargs;
    nargs := Length( arg );

    # two xsqs and two homomorphisms
    if ( ( nargs = 6 ) and IsXSq( arg[1] ) and IsXSq( arg[2])
             and IsXModMorphism( arg[3] ) and IsXModMorphism( arg[4] )
             and IsXModMorphism( arg[5] ) and IsXModMorphism( arg[6] ) ) then
        return  XSqMorphismByMorphisms( arg[1], arg[2], arg[3], 
                                        arg[4], arg[5], arg[6] );
    fi;
    # alternatives not allowed
    Info( InfoXMod, 2, "usage: XSqMorphism( src, rng, up, lt, rt, down );" );
    return fail;
end );

###############################################################################
##
#M  PreXSqMorphismByMorphisms( <src>, <rng>, <up>, <left>, <right>, <down> ) 
##
InstallMethod( PreXSqMorphismByMorphisms,
    "for two pre-crossed squares and four pre-xmod morphisms,", true,
    [ IsPreXSq, IsPreXSq, IsPreXModMorphism, IsPreXModMorphism, 
      IsPreXModMorphism, IsPreXModMorphism ], 0,
function( src, rng, up, left, down, right )

    local  filter, fam, mor, ok, nsrc, nrng, name;

    mor := Make3dMapping( src, rng, up, left, down, right );
    if not IsPreXSqMorphism( mor ) then
        Info( InfoXMod, 2, "not a morphism of pre-crossed squares.\n" );
        return fail;
    fi;
    ok := IsXSqMorphism( mor );
    return mor;
end );

##############################################################################
##
#M  XSqMorphismByMorphisms( <Xs>, <Xr>, <up>, <lt>, <rt>, <dn> )  make xsq map
##
InstallMethod( XSqMorphismByMorphisms, "for 2 xsqs and 4 morphisms", true,
    [ IsXSq, IsXSq, IsXModMorphism, IsXModMorphism, IsXModMorphism, 
      IsXModMorphism ], 0,
function( src, rng, up, left, down, right )

    local  mor, ok;
    mor := PreXSqMorphismByMorphisms( src, rng, up, left, down, right );
    ok := IsXSqMorphism( mor );
    if not ok then
        return fail;
    fi;
    return mor;
end );

##############################################################################
##
#M  CompositionMorphism  . . . . . . . . . . . . . . . . . for two 3d-mappings
##
InstallOtherMethod( CompositionMorphism, "generic method for 3d-mappings",
    IsIdenticalObj, [ Is3dMapping, Is3dMapping ], 0,
function( m2, m1 )

    local  up, left, down, right, comp, ok;

    if not ( Range( m1 ) = Source( m2 ) ) then
        Info( InfoXMod, 2, "Range(m1) <> Source(m2)" );
        return fail;
    fi;
    up := CompositionMapping( Up2dMorphism(m2), Up2dMorphism(m1) );
    left := CompositionMapping( Left2dMorphism(m2), Left2dMorphism(m1) );
    down := CompositionMapping( Down2dMorphism(m2), Down2dMorphism(m1) );
    right := CompositionMapping( Right2dMorphism(m2), Right2dMorphism(m1) );
    comp := Make3dMapping( Source( m1 ), Range( m2 ), up, left, down, right );
    if IsPreCat2( Source( m1 ) ) then
        if ( IsPreCat2Morphism( m1 ) and IsPreCat2Morphism( m2 ) ) then
            SetIsPreCat2Morphism( comp, true );
        fi;
        if ( IsCat2Morphism( m1 ) and IsCat2Morphism( m2 ) ) then
            SetIsCat2Morphism( comp, true );
        fi;
    else
        if ( IsPreXSqMorphism( m1 ) and IsPreXSqMorphism( m2 ) ) then
            SetIsPreXSqMorphism( comp, true );
        fi;
        if ( IsXSqMorphism( m1 ) and IsXSqMorphism( m2 ) ) then
            SetIsXSqMorphism( comp, true );
        fi;
    fi;
    return comp;
end );

##############################################################################
##
#M  Order . . . . . . . . . . . . . . . . . . . . . . . . . . for a 3d-mapping
##
InstallOtherMethod( Order, "generic method for 3d-mapping",
    true, [ Is3dMapping ], 0,
function( mor )

    local  XS, up, left, down, right, Xsrc, Xrng;

    if not ( IsEndomorphism3dObject( mor ) and IsBijective( mor ) ) then
       Info( InfoXMod, 2, "Parameter is not an automorphism" );
       return fail;
    fi;
    return Lcm( Order( Up2dMorphism(mor) ), Order( Left2dMorphism(mor) ),  
             Order( Down2dMorphism(mor) ), Order( Right2dMorphism(mor) ) );
end );

##############################################################################
##
#M  IsInjective( map ) . . . . . . . . . . . . . . . . . . .  for a 3d-mapping
##
InstallOtherMethod( IsInjective,
    "method for a 3d-mapping", true, [ Is3dMapping ], 0,
    map -> ( IsInjective( Up2dMorphism( map ) ) and 
             IsInjective( Left2dMorphism( map ) ) and
             IsInjective( Down2dMorphism( map ) ) and 
             IsInjective( Right2dMorphism( map ) ) ) );

##############################################################################
##
#M  IsSurjective( map ) . . . . . . . . . . . . . . . . . . . for a 3d-mapping
##
InstallOtherMethod( IsSurjective,
    "method for a 3d-mapping", true, [ Is3dMapping ], 0,
    map -> ( IsSurjective( Up2dMorphism( map ) ) and 
             IsSurjective( Left2dMorphism( map ) ) and
             IsSurjective( Down2dMorphism( map ) ) and 
             IsSurjective( Right2dMorphism( map ) ) ) );


##############################################################################
##
#M  IsSingleValued( map ) . . . . . . . . . . . . . . . . . . for a 3d-mapping
##
InstallOtherMethod( IsSingleValued,
    "method for a 3d-mapping", true, [ Is3dMapping ], 0,
    map -> ( IsSingleValued( Up2dMorphism( map ) ) and 
             IsSingleValued( Left2dMorphism( map ) ) and
             IsSingleValued( Down2dMorphism( map ) ) and 
             IsSingleValued( Right2dMorphism( map ) ) ) );

##############################################################################
##
#M  IsTotal( map ) . . . . . . . . . . . . . . . . . . . . .  for a 3d-mapping
##
InstallOtherMethod( IsTotal,
    "method for a 3d-mapping", true, [ Is3dMapping ], 0,
    map -> ( IsTotal( Up2dMorphism( map ) ) and 
             IsTotal( Left2dMorphism( map ) ) and
             IsTotal( Down2dMorphism( map ) ) and 
             IsTotal( Right2dMorphism( map ) ) ) );

##############################################################################
##
#M  IsBijective( map ) . . . . . . . . . . . . . . . . . . .  for a 3d-mapping
##
InstallOtherMethod( IsBijective,
    "method for a 3d-mapping", true, [ Is3dMapping ], 0,
    map -> ( IsBijective( Up2dMorphism( map ) ) and 
             IsBijective( Left2dMorphism( map ) ) and
             IsBijective( Down2dMorphism( map ) ) and 
             IsBijective( Right2dMorphism( map ) ) ) );

##############################################################################
##
#M  IsEndomorphism3dObject( map ) . . . . . . . . . . . . . . for a 3d-mapping
##  temporary fix 08/01/04  ---  need to check correctness
#M  IsAutomorphism3dObject( map ) . . . . . . . . . . . . . . for a 3d-mapping
##
InstallMethod( IsEndomorphism3dObject, 
    "method for a 3d-mapping", true, [ Is3dMapping ], 0,
    map -> IsEndomorphism2dObject( Up2dMorphism( map ) ) and
           IsEndomorphism2dObject( Left2dMorphism( map ) ) and
           IsEndomorphism2dObject( Down2dMorphism( map ) ) and
           IsEndomorphism2dObject( Right2dMorphism( map ) ) );

InstallMethod( IsAutomorphism3dObject, 
    "method for a 3d-mapping", true, [ Is3dMapping ], 0,
    map -> IsEndomorphism3dObject( map ) and IsBijective( map ) );

##############################################################################
##
#E  map3.gi . . . . . . . . . . . . . . . . . . . . . . . . . . . .  ends here
