1#############################################################################
2##
3##  This file is part of GAP, a system for computational discrete algebra.
4##  This file's authors include Thomas Breuer, Martin Schönert, Frank Celler.
5##
6##  Copyright of GAP belongs to its developers, whose names are too numerous
7##  to list here. Please refer to the COPYRIGHT file for details.
8##
9##  SPDX-License-Identifier: GPL-2.0-or-later
10##
11##  This file contains (representation dependent)
12##
13##  1. methods for general mappings in 'IsDefaultMappingRep'
14##  2. methods for composition mappings,
15##  3. methods for mappings by function,
16##  4. methods for inverse mappings
17##  5. methods for identity mappings
18##  6. methods for zero mappings
19##
20
21
22#############################################################################
23##
24##  1. methods for general mappings in 'IsDefaultMappingRep'
25##
26
27#############################################################################
28##
29#R  IsDefaultGeneralMappingRep( <map> )
30##
31##  Source and range of such a general mapping are stored in its type, as
32##  'DataType( TypeObj( <map> ) )[1]' resp.
33##  'DataType( TypeObj( <map> ) )[2]'.
34##
35##  Note that this representation does *not* decide whether <map> is
36##  a positional or a component object.
37##
38DeclareRepresentation( "IsDefaultGeneralMappingRep",
39    IsGeneralMapping and HasSource and HasRange,
40    [] );
41#T methods to handle attributes 'One', 'Inverse', and 'InverseGeneralMapping',
42#T 'ImagesSource', 'PreImagesRange'?
43
44
45#############################################################################
46##
47#F  TypeOfDefaultGeneralMapping( <source>, <range>, <filter> )
48##
49InstallGlobalFunction( TypeOfDefaultGeneralMapping,
50    function( source, range, filter )
51    local Type;
52
53    # Do a cheap test whether the general mapping has equal source and range.
54    if IsIdenticalObj( source, range ) then
55      filter:= filter and IsEndoGeneralMapping;
56    fi;
57
58    # Construct the type.
59    Type:= NewType( GeneralMappingsFamily(
60                          ElementsFamily( FamilyObj( source ) ),
61                          ElementsFamily( FamilyObj( range  ) ) ),
62                    IsDefaultGeneralMappingRep and filter );
63
64    # Store source and range.
65    SetDataType( Type, [ source, range ] );
66
67    # Return the type.
68    return Type;
69end );
70
71
72#############################################################################
73##
74#M  Range( <map> )
75##
76InstallMethod( Range,
77    "for default general mapping",
78    true,
79    [ IsGeneralMapping and IsDefaultGeneralMappingRep ],
80    GETTER_FLAGS + 1,  # higher than the system getter!
81    map -> DataType( TypeObj( map ) )[2] );
82
83
84#############################################################################
85##
86#M  Source( <map> )
87##
88InstallMethod( Source,
89    "for default general mapping",
90    true,
91    [ IsGeneralMapping and IsDefaultGeneralMappingRep ],
92    GETTER_FLAGS + 1,  # higher than the system getter!
93    map -> DataType( TypeObj( map ) )[1] );
94
95
96#############################################################################
97##
98##  2. methods for composition mappings,
99##
100
101#############################################################################
102##
103#F  ConstituentsCompositionMapping( <map> )
104##
105InstallGlobalFunction(ConstituentsCompositionMapping,function(map)
106  if not IsCompositionMappingRep(map) then
107    Error("<map> must be `IsCompositionMappingRep'");
108  fi;
109  return [map!.map1,map!.map2];
110end);
111
112#############################################################################
113##
114#M  CompositionMapping2( <map2>, <map1> ) . . . . .  for two general mappings
115##
116InstallGlobalFunction(CompositionMapping2General,
117function( map2, map1 )
118local com;        # composition of <map1> and <map2>, result
119
120  # Make the general mapping.
121  if IsSPGeneralMapping( map1 ) and IsSPGeneralMapping( map2 ) then
122    com:= Objectify( TypeOfDefaultGeneralMapping( Source( map1 ),
123						  Range( map2 ),
124		      IsCompositionMappingRep and IsSPGeneralMapping ),
125		    rec() );
126  else
127    com:= Objectify( TypeOfDefaultGeneralMapping( Source( map1 ),
128						  Range( map2 ),
129		      IsCompositionMappingRep and IsNonSPGeneralMapping ),
130		    rec() );
131  fi;
132
133  # Enter the identifying information.
134  # (Maintenance of useful information is dealt with by the
135  # wrapper function `CompositionMapping'.)
136  com!.map1:= map1;
137  com!.map2:= map2;
138
139  # Return the composition.
140  return com;
141end );
142
143InstallMethod( CompositionMapping2,
144    "for two general mappings",
145    FamSource1EqFamRange2,
146    [ IsGeneralMapping, IsGeneralMapping ], 0,
147    CompositionMapping2General);
148
149#############################################################################
150##
151#M  IsInjective( <map> )  . . . . . . . . . . . . . . for composition mapping
152##
153InstallMethod( IsInjective,
154    "for a composition mapping",
155    true,
156    [ IsCompositionMappingRep ], 0,
157    function( com )
158    if IsInjective( com!.map1 ) and IsInjective( com!.map2 ) then
159      return true;
160    fi;
161    if not IsInjective( com!.map1 ) and IsTotal( com!.map2 ) then
162      return false;
163    fi;
164    if     IsSurjective( com!.map1 ) and IsSingleValued( com!.map1 )
165       and not IsInjective( com!.map2 ) then
166      return false;
167    fi;
168    TryNextMethod();
169    end );
170
171
172#############################################################################
173##
174#M  IsSingleValued( <map> )   . . . . . . . . . . . . for composition mapping
175##
176InstallMethod( IsSingleValued,
177    "for a composition mapping",
178    true,
179    [ IsCompositionMappingRep ], 0,
180    function( com )
181    if IsSingleValued( com!.map1 ) and IsSingleValued( com!.map2 ) then
182      return true;
183    fi;
184    if     not IsSingleValued( com!.map1 )
185       and IsInjective( com!.map2 ) and IsTotal( com!.map2 ) then
186      return false;
187    fi;
188    if IsSurjective( com!.map1 ) and not IsSingleValued( com!.map2 ) then
189      return false;
190    fi;
191    TryNextMethod();
192    end );
193
194
195#############################################################################
196##
197#M  IsSurjective( <map> ) . . . . . . . . . . . . . . for composition mapping
198##
199InstallMethod( IsSurjective,
200    "for a composition mapping",
201    true,
202    [ IsCompositionMappingRep ], 0,
203    function( com )
204    if   not IsSurjective( com!.map2 ) then
205      return false;
206    elif IsSurjective( com!.map1 ) and
207         IsSubset( Range( com!.map1 ), PreImagesRange( com!.map2 ) ) then
208      return true;
209    fi;
210    TryNextMethod();
211    end );
212
213
214#############################################################################
215##
216#M  IsTotal( <map> )  . . . . . . . . . . . . . . . . for composition mapping
217##
218InstallMethod( IsTotal,
219    "for a composition mapping",
220    true,
221    [ IsCompositionMappingRep ], 0,
222    function( com )
223    if not IsTotal( com!.map1 ) then
224      return false;
225    elif IsTotal( com!.map2 ) and
226         IsSubset( Source( com!.map2 ), ImagesSource( com!.map1 ) ) then
227      return true;
228    fi;
229    TryNextMethod();
230    end );
231
232
233#############################################################################
234##
235#M  ImagesElm( <map>, <elm> ) . . . . . . . . . . . . for composition mapping
236##
237InstallMethod( ImagesElm,
238    "for a composition mapping, and an element",
239    FamSourceEqFamElm,
240    [ IsCompositionMappingRep, IsObject ], 0,
241    function( com, elm )
242    local im;
243    im:= ImagesElm( com!.map1, elm );
244    if not IsEmpty( im ) then
245      return ImagesSet( com!.map2, im );
246    else
247      return [];
248    fi;
249    end );
250
251
252#############################################################################
253##
254#M  ImagesSet( <map>, <elms> )  . . . . . . . . . . . for composition mapping
255##
256InstallMethod( ImagesSet,
257    "for a composition mapping, and a collection",
258    CollFamSourceEqFamElms,
259    [ IsCompositionMappingRep, IsCollection ], 0,
260    function ( com, elms )
261    local im;
262    im:= ImagesSet( com!.map1, elms );
263    if not IsEmpty( im ) then
264      return ImagesSet( com!.map2, im );
265    else
266      return [];
267    fi;
268    end );
269
270
271#############################################################################
272##
273#M  ImagesRepresentative( <map>, <elm> )  . . . . . . for composition mapping
274##
275InstallMethod( ImagesRepresentative,
276    "for a composition mapping, and an element",
277    FamSourceEqFamElm,
278    [ IsCompositionMappingRep, IsObject ], 0,
279    function( com, elm )
280    local im, rep;
281    im:= ImagesRepresentative( com!.map1, elm );
282    if im = fail then
283      # 'elm' has no images under 'com!.map1', so it has none under 'com'.
284      return fail;
285    else
286      im:= ImagesRepresentative( com!.map2, im );
287      if im <> fail then
288        return im;
289      fi;
290
291      # It may happen that only the chosen representative has no images.
292      for im in Enumerator( ImagesElm( com!.map1, elm ) ) do
293        rep:= ImagesRepresentative( com!.map2, im );
294        if rep <> fail then
295          return rep;
296        fi;
297      od;
298      return fail;
299    fi;
300    end );
301
302
303#############################################################################
304##
305#M  PreImagesElm( <map>, <elm> )  . . . . . . . . . . for composition mapping
306##
307InstallMethod( PreImagesElm,
308    "for a composition mapping, and an element",
309    FamRangeEqFamElm,
310    [ IsCompositionMappingRep, IsObject ], 0,
311    function( com, elm )
312    local im;
313    im:= PreImagesElm( com!.map2, elm );
314    if not IsEmpty( im ) then
315      return PreImagesSet( com!.map1, im );
316    else
317      return [];
318    fi;
319    end );
320
321
322#############################################################################
323##
324#M  PreImagesSet( <map>, <elm> )  . . . . . . . . . . for composition mapping
325##
326InstallMethod( PreImagesSet,
327    "for a composition mapping, and a collection",
328    CollFamRangeEqFamElms,
329    [ IsCompositionMappingRep, IsCollection ], 0,
330    function( com, elms )
331    local im;
332    im:= PreImagesSet( com!.map2, elms );
333    if not IsEmpty( im ) then
334      return PreImagesSet( com!.map1, im );
335    else
336      return [];
337    fi;
338    end );
339
340
341#############################################################################
342##
343#M  PreImagesRepresentative( <map>, <elm> ) . . . . . for composition mapping
344##
345InstallMethod( PreImagesRepresentative,
346    "for a composition mapping, and an element",
347    FamRangeEqFamElm,
348    [ IsCompositionMappingRep, IsObject ], 0,
349    function( com, elm )
350    local im, rep;
351    im:= PreImagesRepresentative( com!.map2, elm );
352    if im = fail then
353      # 'elm' has no preimages under 'com!.map2', so it has none under 'com'.
354      return fail;
355    else
356      im:= PreImagesRepresentative( com!.map1, im );
357      if im <> fail then
358        return im;
359      fi;
360
361      # It may happen that only the chosen representative has no preimages.
362      for im in Enumerator( PreImagesElm( com!.map2, elm ) ) do
363        rep:= PreImagesRepresentative( com!.map1, im );
364        if rep <> fail then
365          return rep;
366        fi;
367      od;
368      return fail;
369    fi;
370    end );
371
372
373#############################################################################
374##
375#M  KernelOfAdditiveGeneralMapping( <map> ) . . . . . for composition mapping
376##
377InstallMethod( KernelOfAdditiveGeneralMapping,
378    "for a composition mapping that resp. add. and add.inv.",
379    true,
380    [ IsGeneralMapping and IsCompositionMappingRep
381      and RespectsAddition and RespectsAdditiveInverses ], 0,
382    function( com )
383    if IsInjective( com!.map2 ) then
384      return KernelOfAdditiveGeneralMapping( com!.map1 );
385    else
386      return PreImagesSet( com!.map1,
387                 KernelOfAdditiveGeneralMapping( com!.map2 ) );
388    fi;
389    end );
390
391
392#############################################################################
393##
394#M  CoKernelOfAdditiveGeneralMapping( <map> ) . . . . for composition mapping
395##
396InstallMethod( CoKernelOfAdditiveGeneralMapping,
397    "for a composition mapping that resp. add. and add.inv.",
398    true,
399    [ IsGeneralMapping and IsCompositionMappingRep
400      and RespectsAddition and RespectsAdditiveInverses ], 0,
401    function( com )
402    if IsSingleValued( com!.map1 ) then
403      return CoKernelOfAdditiveGeneralMapping( com!.map2 );
404    else
405      return ImagesSet( com!.map2,
406                 CoKernelOfAdditiveGeneralMapping( com!.map1 ) );
407    fi;
408    end );
409
410
411#############################################################################
412##
413#M  KernelOfMultiplicativeGeneralMapping( <map> ) . . for composition mapping
414##
415InstallMethod( KernelOfMultiplicativeGeneralMapping,
416    "for a composition mapping that resp. mult. and inv.",
417    true,
418    [ IsGeneralMapping and IsCompositionMappingRep
419      and RespectsMultiplication and RespectsInverses ], 0,
420    function( com )
421    if IsInjective( com!.map2 ) then
422      return KernelOfMultiplicativeGeneralMapping( com!.map1 );
423    else
424      return PreImagesSet( com!.map1,
425                 KernelOfMultiplicativeGeneralMapping( com!.map2 ) );
426    fi;
427    end );
428
429
430#############################################################################
431##
432#M  CoKernelOfMultiplicativeGeneralMapping( <map> ) . for composition mapping
433##
434InstallMethod( CoKernelOfMultiplicativeGeneralMapping,
435    "for a composition mapping that resp. mult. and inv.",
436    true,
437    [ IsGeneralMapping and IsCompositionMappingRep
438      and RespectsMultiplication and RespectsInverses ], 0,
439    function( com )
440    if IsSingleValued( com!.map1 ) then
441      return CoKernelOfMultiplicativeGeneralMapping( com!.map2 );
442    else
443      return ImagesSet( com!.map2,
444                 CoKernelOfMultiplicativeGeneralMapping( com!.map1 ) );
445    fi;
446    end );
447
448
449#############################################################################
450##
451#M  ViewObj( <map> )  . . . . . . . . . . . . . . . . for composition mapping
452#M  PrintObj( <map> ) . . . . . . . . . . . . . . . . for composition mapping
453##
454InstallMethod( ViewObj,
455    "for a composition mapping",
456    true,
457    [ IsCompositionMappingRep ], 100,
458    function( com )
459    Print( "CompositionMapping( ", BHINT );
460    View( com!.map2 );
461    Print( ",", BHINT, " " );
462    View( com!.map1 );
463    Print( " )", BHINT );
464    end );
465
466InstallMethod( PrintObj,
467    "for a composition mapping",
468    true,
469    [ IsCompositionMappingRep ], 100,
470    function( com )
471    Print( "CompositionMapping( ", com!.map2, ", ", com!.map1, " )" );
472    end );
473
474
475#############################################################################
476##
477##  3. methods for mappings by function,
478##
479
480#############################################################################
481##
482#R  IsMappingByFunctionRep( <map> )
483##
484DeclareRepresentation( "IsMappingByFunctionRep",
485    IsMapping and IsAttributeStoringRep,
486    [ "fun" ] );
487#T really attribute storing ??
488
489
490#############################################################################
491##
492#R  IsMappingByFunctionWithInverseRep( <map> )
493##
494DeclareRepresentation( "IsMappingByFunctionWithInverseRep",
495        IsMappingByFunctionRep
496    and IsBijective,
497#T 1996/10/10 fceller where to put non-reps, 4th position?
498    [ "fun", "invFun" ] );
499
500#############################################################################
501##
502#R  IsNonSPMappingByFunctionRep( <map> )
503##
504DeclareRepresentation( "IsNonSPMappingByFunctionRep",
505    IsNonSPGeneralMapping and IsMappingByFunctionRep, [] );
506
507#############################################################################
508##
509#R  IsNonSPMappingByFunctionWithInverseRep( <map> )
510##
511DeclareRepresentation( "IsNonSPMappingByFunctionWithInverseRep",
512        IsMappingByFunctionWithInverseRep and IsNonSPMappingByFunctionRep,
513    [ "fun", "invFun" ] );
514
515#############################################################################
516##
517#R  IsSPMappingByFunctionRep( <map> )
518##
519DeclareRepresentation( "IsSPMappingByFunctionRep",
520    IsSPGeneralMapping and IsMappingByFunctionRep, [] );
521
522#############################################################################
523##
524#R  IsSPMappingByFunctionWithInverseRep( <map> )
525##
526DeclareRepresentation( "IsSPMappingByFunctionWithInverseRep",
527        IsMappingByFunctionWithInverseRep and IsSPMappingByFunctionRep,
528    [ "fun", "invFun" ] );
529
530
531#############################################################################
532##
533#F  MappingByFunction( <D>, <E>, <fun> )  . . . . .  create map from function
534#F  MappingByFunction( <D>, <E>, <fun>, <invfun> )
535##
536InstallGlobalFunction( MappingByFunction, function ( arg )
537    local   map;        # mapping <map>, result
538
539
540    if not Length(arg) in [3,4,5] then
541      # signal an error
542      Error( "usage: MappingByFunction( <D>, <E>, <fun>[, <inv>] )" );
543    fi;
544
545    # ensure that the source and range are domains
546    if not (IsDomain(arg[1]) and IsDomain(arg[2])) then
547	    Error("MappingByFunction: Source and Range must be domains");
548    fi;
549
550    # no inverse function given
551    if Length(arg)<>4  then
552
553      # make the general mapping
554      map:= Objectify( TypeOfDefaultGeneralMapping( arg[1], arg[2],
555                               IsNonSPMappingByFunctionRep
556                           and IsSingleValued
557                           and IsTotal ),
558                       rec( fun:= arg[3] ) );
559      if Length(arg)=5 and IsFunction(arg[5]) then
560        map!.prefun:=arg[5];
561      fi;
562
563    # inverse function given
564    elif Length(arg) = 4  then
565
566      # make the mapping
567      map:= Objectify( TypeOfDefaultGeneralMapping( arg[1], arg[2],
568                               IsNonSPMappingByFunctionWithInverseRep
569                           and IsBijective ),
570                       rec( fun    := arg[3],
571                            invFun := arg[4],
572			    prefun := arg[4]) );
573
574    fi;
575
576    # return the mapping
577    return map;
578end );
579
580
581#############################################################################
582##
583#M  ImageElm( <map>, <elm> )  . . . . . . . . . . . . for mapping by function
584##
585InstallMethod( ImageElm,
586    "for mapping by function",
587    FamSourceEqFamElm,
588    [ IsMappingByFunctionRep, IsObject ], 0,
589    function ( map, elm )
590    return map!.fun( elm );
591    end );
592
593
594#############################################################################
595##
596#M  ImagesElm( <map>, <elm> ) . . . . . . . . . . . . for mapping by function
597##
598InstallMethod( ImagesElm,
599    "for mapping by function",
600    FamSourceEqFamElm,
601    [ IsMappingByFunctionRep, IsObject ], 0,
602    function ( map, elm )
603    return [ map!.fun( elm ) ];
604    end );
605
606
607#############################################################################
608##
609#M  ImagesRepresentative( <map>, <elm> )  . . . . . . for mapping by function
610##
611InstallMethod( ImagesRepresentative,
612    "for mapping by function",
613    FamSourceEqFamElm,
614    [ IsMappingByFunctionRep, IsObject ], 0,
615    function ( map, elm )
616    return map!.fun( elm );
617    end );
618
619#############################################################################
620##
621#M  KernelOfMultiplicativeGeneralMapping( <map> )   . for mapping by function
622##
623InstallMethod(KernelOfMultiplicativeGeneralMapping,"hom by function",true,
624    [ IsMappingByFunctionRep and IsGroupHomomorphism ],0,
625function ( map )
626  return
627  KernelOfMultiplicativeGeneralMapping(AsGroupGeneralMappingByImages(map));
628end );
629
630#############################################################################
631##
632#M  PreImagesRepresentative( <map>, <elm> ) . . . . . for mapping by function
633##
634InstallMethod( PreImagesRepresentative,
635    "for mapping by function",
636    FamRangeEqFamElm,
637    [ IsMappingByFunctionRep, IsObject ], 0,
638  function ( map, elm )
639    if not IsBound(map!.prefun) then
640      # no quick way known
641      TryNextMethod();
642    fi;
643    return map!.prefun( elm );
644  end );
645
646
647#############################################################################
648##
649#M  PreImageElm( <map>, <elm> ) . . . . . . . . . . . for mapping by function
650##
651InstallMethod( PreImageElm,
652    "for mapping by function",
653    FamRangeEqFamElm,
654    [ IsMappingByFunctionWithInverseRep, IsObject ], 0,
655    function ( map, elm )
656    return map!.invFun( elm );
657    end );
658
659
660#############################################################################
661##
662#M  PreImagesElm( <map>, <elm> )  . . . . . . . . . . for mapping by function
663##
664InstallMethod( PreImagesElm,
665    "for mapping by function",
666    FamRangeEqFamElm,
667    [ IsMappingByFunctionWithInverseRep, IsObject ], 0,
668    function ( map, elm )
669    return [ map!.invFun( elm ) ];
670    end );
671
672#############################################################################
673##
674#M  PreImagesRepresentative( <map>, <elm> ) . . . . . for mapping by function
675##
676InstallMethod( PreImagesRepresentative,
677    "for mapping by function with inverse",
678    FamRangeEqFamElm,
679    [ IsMappingByFunctionWithInverseRep, IsObject ], 0,
680    function ( map, elm )
681    return map!.invFun( elm );
682    end );
683
684
685
686#############################################################################
687##
688##  Transfer information about the mapping map to its associated inverse
689##  mapping inv. For example, if map is total than inv is surjective and
690##  vice versa.
691##
692BindGlobal( "TransferMappingPropertiesToInverse", function ( map, inv )
693    # If possible, enter preimage and image.
694    if HasImagesSource( map ) then
695      SetPreImagesRange( inv, ImagesSource( map ) );
696    fi;
697    if HasPreImagesRange( map )  then
698      SetImagesSource( inv, PreImagesRange( map ) );
699    fi;
700
701    # Maintain important properties.
702    if HasIsSingleValued( map ) then
703      SetIsInjective( inv, IsSingleValued( map ) );
704    fi;
705    if HasIsInjective( map ) then
706      SetIsSingleValued( inv, IsInjective( map ) );
707    fi;
708    if HasIsTotal( map ) then
709      SetIsSurjective( inv, IsTotal( map ) );
710    fi;
711    if HasIsSurjective( map ) then
712      SetIsTotal( inv, IsSurjective( map ) );
713    fi;
714    if HasIsEndoGeneralMapping( map ) then
715      SetIsEndoGeneralMapping( inv, IsEndoGeneralMapping( map ) );
716    fi;
717
718    # Maintain the maintainings w.r.t. multiplication.
719    if HasRespectsMultiplication( map ) then
720      SetRespectsMultiplication( inv, RespectsMultiplication( map ) );
721    fi;
722    if HasRespectsInverses( map ) then
723      SetRespectsInverses( inv, RespectsInverses( map ) );
724    elif HasRespectsOne( map ) then
725      SetRespectsOne( inv, RespectsOne( map ) );
726    fi;
727
728    # Maintain the maintainings w.r.t. addition.
729    if HasRespectsAddition( map ) then
730      SetRespectsAddition( inv, RespectsAddition( map ) );
731    fi;
732    if HasRespectsAdditiveInverses( map ) then
733      SetRespectsAdditiveInverses( inv, RespectsAdditiveInverses( map ) );
734    elif HasRespectsZero( map ) then
735      SetRespectsZero( inv, RespectsZero( map ) );
736    fi;
737
738    # Maintain respecting of scalar multiplication.
739    # (Note the slight asymmetry, depending on the coefficient domains.)
740    if     HasRespectsScalarMultiplication( map )
741       and   LeftActingDomain( Source( map ) )
742           = LeftActingDomain( Range( map ) ) then
743      SetRespectsScalarMultiplication( inv,
744          RespectsScalarMultiplication( map ) );
745    fi;
746
747    # We know the inverse general mapping of the inverse general mapping ;-).
748    SetInverseGeneralMapping( inv, map );
749end );
750
751#############################################################################
752##
753#M  InverseGeneralMapping( <map> )  . . . . . . . . . for mapping by function
754##
755InstallMethod( InverseGeneralMapping, "for mapping by function", true,
756    [ IsMappingByFunctionWithInverseRep ], 0,
757    function ( map )
758    local inv;
759    inv:= MappingByFunction( Range( map ), Source( map ),
760                             map!.invFun, map!.fun );
761    TransferMappingPropertiesToInverse( map, inv );
762    return inv;
763    end );
764
765InstallMethod( RestrictedInverseGeneralMapping, "for mapping by function", true,
766    [ IsMappingByFunctionWithInverseRep ], 0,
767    function ( map )
768    local inv;
769    inv:= MappingByFunction( Image( map ), Source( map ),
770                             map!.invFun, map!.fun );
771    TransferMappingPropertiesToInverse( map, inv );
772    return inv;
773    end );
774
775
776#############################################################################
777##
778#M  ViewObj( <map> )  . . . . . . . . . . . . . . . . for mapping by function
779#M  PrintObj( <map> ) . . . . . . . . . . . . . . . . for mapping by function
780##
781InstallMethod( ViewObj,
782    "for mapping by function",
783    true,
784    [ IsMappingByFunctionRep ], 0,
785    function ( map )
786    Print( "MappingByFunction( " );
787    View( Source( map ) );
788    Print( ", " );
789    View( Range( map ) );
790    Print( ", " );
791    View( map!.fun );
792    Print( " )" );
793    end );
794
795InstallMethod( PrintObj,
796    "for mapping by function",
797    true,
798    [ IsMappingByFunctionRep ], 0,
799    function ( map )
800    Print( "MappingByFunction( ",
801           Source( map ), ", ", Range( map ), ", ",
802           map!.fun, " )" );
803    end );
804
805
806#############################################################################
807##
808#M  ViewObj( <map> )  . . . . . . . . .  for mapping by function with inverse
809#M  PrintObj( <map> ) . . . . . . . . .  for mapping by function with inverse
810##
811InstallMethod( ViewObj,
812    "for mapping by function with inverse",
813    true,
814    [ IsMappingByFunctionWithInverseRep ], 0,
815    function ( map )
816    Print( "MappingByFunction( " );
817    View( Source( map ) );
818    Print( ", " );
819    View( Range( map ) );
820    Print( ", " );
821    View( map!.fun );
822    Print( ", " );
823    View( map!.invFun );
824    Print( " )" );
825    end );
826
827InstallMethod( PrintObj,
828    "for mapping by function with inverse",
829    true,
830    [ IsMappingByFunctionWithInverseRep ], 0,
831    function ( map )
832    Print( "MappingByFunction( ",
833           Source( map ), ", ", Range( map ), ", ",
834           map!.fun, ", ", map!.invFun, " )" );
835    end );
836
837
838#############################################################################
839##
840##  4. methods for inverse mappings
841##
842
843#############################################################################
844##
845#R  IsInverseGeneralMappingRep( <map> )
846##
847##  Note that if a mapping knows its inverse mapping then also the inverse
848##  mapping knows its inverse mapping.
849##  So we need this flag to avoid infinite recursion when a question is
850##  delegated to the inverse of a mapping.
851##
852DeclareRepresentation( "IsInverseGeneralMappingRep",
853    IsNonSPGeneralMapping,
854    [] );
855
856
857#############################################################################
858##
859#M  InverseGeneralMapping( <map> ) . for a general mapping with known inverse
860##
861InstallImmediateMethod( InverseGeneralMapping,
862    IsGeneralMapping and HasInverse and IsAttributeStoringRep, 0,
863    function( map )
864    if Inverse( map ) <> fail then
865      return Inverse( map );
866    else
867      TryNextMethod();
868    fi;
869    end );
870
871
872#############################################################################
873##
874#M  InverseGeneralMapping( <map> ) . . . . . . . . . .  for a general mapping
875##
876InstallMethod( InverseGeneralMapping,
877    "for a general mapping",
878    true,
879    [ IsGeneralMapping ], 0,
880    function ( map )
881    local   inv;
882
883    # Make the mapping.
884    inv:= Objectify( TypeOfDefaultGeneralMapping( Range( map ),
885                                                  Source( map ),
886                             IsInverseGeneralMappingRep
887                         and IsAttributeStoringRep ),
888                     rec() );
889
890    TransferMappingPropertiesToInverse( map, inv );
891
892    # Return the inverse general mapping.
893    return inv;
894    end );
895
896
897#############################################################################
898##
899#M  IsSingleValued( <map> ) . . . . . . . . . . . . .  for an inverse mapping
900##
901InstallMethod( IsSingleValued,
902    "for an inverse mapping",
903    true,
904    [ IsGeneralMapping and IsInverseGeneralMappingRep ], 0,
905    inv -> IsInjective( InverseGeneralMapping( inv ) ) );
906
907
908#############################################################################
909##
910#M  IsInjective( <map> )  . . . . . . . . . . . . . .  for an inverse mapping
911##
912InstallMethod( IsInjective,
913    "for an inverse mapping",
914    true,
915    [ IsGeneralMapping and IsInverseGeneralMappingRep ], 0,
916    inv -> IsSingleValued( InverseGeneralMapping( inv ) ) );
917
918
919#############################################################################
920##
921#M  IsSurjective( <map> ) . . . . . . . . . . . . . .  for an inverse mapping
922##
923InstallMethod( IsSurjective,
924    "for an inverse mapping",
925    true,
926    [ IsGeneralMapping and IsInverseGeneralMappingRep ], 0,
927    inv -> IsTotal( InverseGeneralMapping( inv ) ) );
928
929
930#############################################################################
931##
932#M  IsTotal( <map> )  . . . . . . . . . . . . . . . .  for an inverse mapping
933##
934InstallMethod( IsTotal,
935    "for an inverse mapping",
936    true,
937    [ IsGeneralMapping and IsInverseGeneralMappingRep ], 0,
938    inv -> IsSurjective( InverseGeneralMapping( inv ) ) );
939
940
941#############################################################################
942##
943#M  CoKernelOfAdditiveGeneralMapping( <invmap> )  . . . . for inverse mapping
944##
945InstallMethod( CoKernelOfAdditiveGeneralMapping,
946    "for an inverse mapping",
947    true,
948    [ IsGeneralMapping and IsInverseGeneralMappingRep ], 0,
949    inv -> KernelOfAdditiveGeneralMapping(
950               InverseGeneralMapping( inv ) ) );
951
952
953#############################################################################
954##
955#M  KernelOfAdditiveGeneralMapping( <invmap> )  . . . . . for inverse mapping
956##
957InstallMethod( KernelOfAdditiveGeneralMapping,
958    "for an inverse mapping",
959    true,
960    [ IsGeneralMapping and IsInverseGeneralMappingRep ], 0,
961    inv -> CoKernelOfAdditiveGeneralMapping(
962               InverseGeneralMapping( inv ) ) );
963
964
965#############################################################################
966##
967#M  CoKernelOfMultiplicativeGeneralMapping( <invmap> )  . for inverse mapping
968##
969InstallMethod( CoKernelOfMultiplicativeGeneralMapping,
970    "for an inverse mapping",
971    true,
972    [ IsGeneralMapping and IsInverseGeneralMappingRep ], 0,
973    inv -> KernelOfMultiplicativeGeneralMapping(
974               InverseGeneralMapping( inv ) ) );
975
976
977#############################################################################
978##
979#M  KernelOfMultiplicativeGeneralMapping( <invmap> )  . . for inverse mapping
980##
981InstallMethod( KernelOfMultiplicativeGeneralMapping,
982    "for an inverse mapping",
983    true,
984    [ IsGeneralMapping and IsInverseGeneralMappingRep ], 0,
985    inv -> CoKernelOfMultiplicativeGeneralMapping(
986               InverseGeneralMapping( inv ) ) );
987
988
989#############################################################################
990##
991#M  ImageElm( <invmap>, <map> ) . . . . . . . for inverse mapping and element
992##
993InstallMethod( ImageElm,
994    "for an inverse mapping and an element",
995    FamSourceEqFamElm,
996    [ IsMapping and IsInverseGeneralMappingRep, IsObject ], 0,
997    function ( inv, elm )
998    return PreImageElm( InverseGeneralMapping( inv ), elm );
999    end );
1000
1001
1002#############################################################################
1003##
1004#M  ImagesElm( <invmap>, <map> )  . . . . . . for inverse mapping and element
1005##
1006InstallMethod( ImagesElm,
1007    "for an inverse mapping and an element",
1008    FamSourceEqFamElm,
1009    [ IsGeneralMapping and IsInverseGeneralMappingRep, IsObject ], 0,
1010    function ( inv, elm )
1011    return PreImagesElm( InverseGeneralMapping( inv ), elm );
1012    end );
1013
1014
1015#############################################################################
1016##
1017#M  ImagesSet( <invmap>, <coll> ) . . . .  for inverse mapping and collection
1018##
1019InstallMethod( ImagesSet,
1020    "for an inverse mapping and a collection",
1021    CollFamSourceEqFamElms,
1022    [ IsGeneralMapping and IsInverseGeneralMappingRep, IsCollection ], 0,
1023    function ( inv, elms )
1024    return PreImagesSet( InverseGeneralMapping( inv ), elms );
1025    end );
1026
1027
1028#############################################################################
1029##
1030#M  ImagesSet( <invmap>, <coll> ) . . . .  for inverse mapping and collection
1031##
1032InstallMethod( ImagesRepresentative,
1033    "for an inverse mapping and an element",
1034    FamSourceEqFamElm,
1035    [ IsGeneralMapping and IsInverseGeneralMappingRep, IsObject ], 0,
1036    function ( inv, elm )
1037    return PreImagesRepresentative( InverseGeneralMapping( inv ), elm );
1038    end );
1039
1040
1041#############################################################################
1042##
1043#M  PreImageElm( <invmap>, <elm> )  . . . . . for inverse mapping and element
1044##
1045InstallMethod( PreImageElm,
1046    "for an inj. & surj. inverse mapping, and an element",
1047    FamRangeEqFamElm,
1048    [ IsGeneralMapping and IsInverseGeneralMappingRep
1049                       and IsInjective and IsSurjective, IsObject ], 0,
1050    function ( inv, elm )
1051    return ImageElm( InverseGeneralMapping( inv ), elm );
1052    end );
1053
1054
1055#############################################################################
1056##
1057#M  PreImagesElm( <invmap>, <elm> ) . . . . . for inverse mapping and element
1058##
1059InstallMethod( PreImagesElm,
1060    "for an inverse mapping and an element",
1061    FamRangeEqFamElm,
1062    [ IsGeneralMapping and IsInverseGeneralMappingRep, IsObject ], 0,
1063    function ( inv, elm )
1064    return ImagesElm( InverseGeneralMapping( inv ), elm );
1065    end );
1066
1067
1068#############################################################################
1069##
1070#M  PreImagesSet( <invmap>, <coll> )  . .  for inverse mapping and collection
1071##
1072InstallMethod( PreImagesSet,
1073    "for an inverse mapping and a collection",
1074    CollFamRangeEqFamElms,
1075    [ IsGeneralMapping and IsInverseGeneralMappingRep, IsCollection ], 0,
1076    function ( inv, elms )
1077    return ImagesSet( InverseGeneralMapping( inv ), elms );
1078    end );
1079
1080
1081#############################################################################
1082##
1083#M  PreImagesRepresentative( <invmap>, <elm> )  . . for inv. mapping and elm.
1084##
1085InstallMethod( PreImagesRepresentative,
1086    "for an inverse mapping and an element",
1087    FamRangeEqFamElm,
1088    [ IsInverseGeneralMappingRep, IsObject ], 0,
1089    function ( inv, elm )
1090    return ImagesRepresentative( InverseGeneralMapping( inv ), elm );
1091    end );
1092
1093
1094#############################################################################
1095##
1096#M  ViewObj( <invmap> ) . . . . . . . . . . . . . . . . . .  for inv. mapping
1097#M  PrintObj( <invmap> )  . . . . . . . . . . . . . . . . .  for inv. mapping
1098##
1099InstallMethod( ViewObj,
1100    "for an inverse mapping",
1101    true,
1102    [ IsGeneralMapping and IsInverseGeneralMappingRep ], 100,
1103    function ( inv )
1104    Print( "InverseGeneralMapping( " );
1105    View( InverseGeneralMapping( inv ) );
1106    Print( " )" );
1107    end );
1108
1109InstallMethod( PrintObj,
1110    "for an inverse mapping",
1111    true,
1112    [ IsGeneralMapping and IsInverseGeneralMappingRep ], 100,
1113    function ( inv )
1114    Print( "InverseGeneralMapping( ", InverseGeneralMapping( inv )," )" );
1115    end );
1116
1117
1118#############################################################################
1119##
1120##  5. methods for identity mappings
1121##
1122##  For each domain we need to construct only one identity mapping.
1123##  In order to allow this to interact with other mappings of this domain
1124##  (for example, with automorphisms of a field in a special representation),
1125##  one needs to install methods to compare these mappings with the identity
1126##  mapping via '\=' and '\<'.
1127##
1128##  Methods for identity mappings are all installed with rank 'SUM_FLAGS'.
1129##
1130
1131#############################################################################
1132##
1133##  An identity mapping whose source has a nice structure gets the properties
1134##  to respect this structure.
1135##
1136BindGlobal( "ImmediateImplicationsIdentityMapping", function( idmap )
1137
1138    local source;
1139
1140    source:= Source( idmap );
1141
1142    # multiplicative structure
1143    if IsMagma( source ) then
1144      SetRespectsMultiplication( idmap, true );
1145      if IsMagmaWithOne( source ) then
1146	SetRespectsOne( idmap, true );
1147	if IsMagmaWithInverses( source ) then
1148	  SetRespectsInverses( idmap, true );
1149	fi;
1150      fi;
1151    fi;
1152
1153    # additive structure
1154    if IsAdditiveMagma( source ) then
1155      SetRespectsAddition( idmap, true );
1156      if IsAdditiveMagmaWithZero( source ) then
1157	SetRespectsZero( idmap, true );
1158	if IsAdditiveGroup( source ) then
1159	  SetRespectsAdditiveInverses( idmap, true );
1160
1161          # linear structure
1162          if IsLeftModule( source ) then
1163            SetRespectsScalarMultiplication( idmap, true );
1164          fi;
1165
1166	fi;
1167      fi;
1168    fi;
1169end );
1170
1171
1172#############################################################################
1173##
1174#M  IdentityMapping( <D> )  . . . . . . . .  identity mapping of a collection
1175##
1176InstallMethod( IdentityMapping,
1177    "for a collection",
1178    true,
1179    [ IsCollection ], 0,
1180    function( D )
1181    local id;
1182
1183    # make the mapping
1184    id := Objectify( TypeOfDefaultGeneralMapping( D, D,
1185                                  IsSPGeneralMapping
1186                              and IsAdditiveElementWithInverse
1187                              and IsAttributeStoringRep
1188                              and IsOne ),
1189                     rec() );
1190
1191    # the identity mapping is self-inverse
1192    SetInverseGeneralMapping( id, id );
1193
1194    # set the respectings
1195    ImmediateImplicationsIdentityMapping( id );
1196
1197    # return the identity mapping
1198    return id;
1199    end );
1200
1201
1202#############################################################################
1203##
1204#M  \^( <idmap>, <n> )  . . . . . . . . . .  for identity mapping and integer
1205##
1206InstallMethod( \^,
1207    "for identity mapping and integer",
1208    true,
1209    [ IsGeneralMapping and IsOne, IsInt ],
1210    SUM_FLAGS, # can't do better
1211  function ( id, n )
1212    return id;
1213  end );
1214
1215
1216#############################################################################
1217##
1218#M  ImageElm( <idmap>, <elm> )  . . . . . .  for identity mapping and element
1219##
1220InstallMethod( ImageElm,
1221    "for identity mapping and object",
1222    FamSourceEqFamElm,
1223    [ IsGeneralMapping and IsOne, IsObject ],
1224    SUM_FLAGS, # can't do better
1225  function ( id, elm )
1226    return elm;
1227  end );
1228
1229
1230#############################################################################
1231##
1232#M  ImagesElm( <idmap>, <elm> )  . . . . . . for identity mapping and element
1233##
1234InstallMethod( ImagesElm,
1235    "for identity mapping and object",
1236    FamSourceEqFamElm,
1237    [ IsGeneralMapping and IsOne, IsObject ],
1238    SUM_FLAGS, # can't do better
1239  function ( id, elm )
1240    return [ elm ];
1241  end );
1242
1243
1244#############################################################################
1245##
1246#M  ImagesSet( <idmap>, <coll> ) . . . .  for identity mapping and collection
1247##
1248InstallMethod( ImagesSet,
1249    "for identity mapping and collection",
1250    CollFamSourceEqFamElms,
1251    [ IsGeneralMapping and IsOne, IsCollection ],
1252    SUM_FLAGS, # can't do better
1253  function ( id, elms )
1254    return elms;
1255  end );
1256
1257#############################################################################
1258##
1259#M  ImagesSource( <idmap> )
1260##
1261InstallMethod( ImagesSource,"for identity mapping",true,
1262    [ IsGeneralMapping and IsOne ], SUM_FLAGS, # can't do better
1263function ( id )
1264  return Source(id);
1265end );
1266
1267
1268#############################################################################
1269##
1270#M  ImagesRepresentative( <idmap>, <elm> )   for identity mapping and element
1271##
1272InstallMethod( ImagesRepresentative,
1273    "for identity mapping and object",
1274    FamSourceEqFamElm,
1275    [ IsGeneralMapping and IsOne, IsObject ],
1276    SUM_FLAGS, # can't do better
1277  function ( id, elm )
1278    return elm;
1279  end );
1280
1281
1282#############################################################################
1283##
1284#M  PreImageElm( <idmap>, <elm> )   . . . .  for identity mapping and element
1285##
1286InstallMethod( PreImageElm,
1287    "for identity mapping and object",
1288    FamRangeEqFamElm,
1289    [ IsGeneralMapping and IsOne, IsObject ],
1290    SUM_FLAGS, # can't do better
1291  function ( id, elm )
1292    return elm;
1293  end );
1294
1295
1296#############################################################################
1297##
1298#M  PreImagesElm( <idmap>, <elm> )  . . . .  for identity mapping and element
1299##
1300InstallMethod( PreImagesElm,
1301    "for identity mapping and object",
1302    FamRangeEqFamElm,
1303    [ IsGeneralMapping and IsOne, IsObject ],
1304    SUM_FLAGS, # can't do better
1305  function ( id, elm )
1306    return [ elm ];
1307  end );
1308
1309
1310#############################################################################
1311##
1312#M  PreImagesSet( <idmap>, <coll> ) . . . for identity mapping and collection
1313##
1314InstallMethod( PreImagesSet,
1315    "for identity mapping and collection",
1316    CollFamRangeEqFamElms,
1317    [ IsGeneralMapping and IsOne, IsCollection ],
1318    SUM_FLAGS, # can't do better
1319  function ( id, elms )
1320    return elms;
1321  end );
1322
1323
1324#############################################################################
1325##
1326#M  PreImagesRepresentative( <idmap>, <elm> )
1327##
1328InstallMethod( PreImagesRepresentative,
1329    "for identity mapping and object",
1330    FamRangeEqFamElm,
1331    [ IsGeneralMapping and IsOne, IsObject ],
1332    SUM_FLAGS, # can't do better
1333  function ( id, elm )
1334    return elm;
1335  end );
1336
1337
1338#############################################################################
1339##
1340#M  ViewObj( <idmap> )  . . . . . . . . . . . . . . . .  for identity mapping
1341#M  PrintObj( <idmap> ) . . . . . . . . . . . . . . . .  for identity mapping
1342##
1343InstallMethod( ViewObj,
1344    "for identity mapping",
1345    true,
1346    [ IsGeneralMapping and IsOne ],
1347    # rank up, but just to exactly SUM_FLAGS, so that mappings in a special
1348    # representation with a custom printing method still get that, even if
1349    # the rank of IsGeneralMapping and IsOne happens to be increased a lot
1350    {} -> SUM_FLAGS - RankFilter( IsGeneralMapping and IsOne ),
1351  function ( id )
1352    Print( "IdentityMapping( " );
1353    View( Source( id ) );
1354    Print( " )" );
1355  end );
1356
1357InstallMethod( PrintObj,
1358    "for identity mapping",
1359    true,
1360    [ IsGeneralMapping and IsOne ],
1361    # rank up, but just to exactly SUM_FLAGS, so that mappings in a special
1362    # representation with a custom printing method still get that, even if
1363    # the rank of IsGeneralMapping and IsOne happens to be increased a lot
1364    {} -> SUM_FLAGS - RankFilter( IsGeneralMapping and IsOne ),
1365    function ( id )
1366    Print( "IdentityMapping( ", Source( id ), " )" );
1367    end );
1368
1369
1370#############################################################################
1371##
1372#M  CompositionMapping2( <map>, <idmap> ) .  for gen. mapping and id. mapping
1373##
1374InstallMethod( CompositionMapping2,
1375  "for general mapping and identity mapping", FamSource1EqFamRange2,
1376  [ IsGeneralMapping, IsGeneralMapping and IsOne ],
1377  {} -> SUM_FLAGS + RankFilter( IsGeneralMapping and IsZero ),  # should be higher than the rank for a zero mapping
1378function ( map, id )
1379  if not IsSubset(Range(id),Source(map)) then
1380    # if the identity is defined on something smaller, we need to take a
1381    # true `CompositionMapping'.
1382    TryNextMethod();
1383  fi;
1384  return map;
1385end );
1386
1387
1388#############################################################################
1389##
1390#M  CompositionMapping2( <idmap>, <map> ) .  for id. mapping and gen. mapping
1391##
1392InstallMethod( CompositionMapping2,
1393  "for identity mapping and general mapping",FamSource1EqFamRange2,
1394  [ IsGeneralMapping and IsOne, IsGeneralMapping ],
1395  {} -> SUM_FLAGS + RankFilter( IsGeneralMapping and IsZero ),  # should be higher than the rank for a zero mapping
1396function( id, map )
1397  if not IsSubset(Source(id),Range(map)) then
1398    # if the identity is defined on something smaller, we need to take a
1399    # true `CompositionMapping'.
1400    TryNextMethod();
1401  fi;
1402  return map;
1403end );
1404
1405
1406#############################################################################
1407##
1408##  6. methods for zero mappings
1409##
1410##  methods for zero mappings are all installed with rank 'SUM_FLAGS'
1411##
1412#T (use 'IsZero' in '\+' method for mappings ...)
1413
1414
1415#############################################################################
1416##
1417##  A zero mapping whose source has a nice structure gets the properties
1418##  to respect this structure.
1419##
1420BindGlobal( "ImmediateImplicationsZeroMapping", function( zeromap )
1421
1422    local source;
1423
1424    source:= Source( zeromap );
1425
1426    # multiplicative structure
1427    if IsMagma( source ) then
1428      SetRespectsMultiplication( zeromap, true );
1429      if IsMagmaWithOne( source ) then
1430	SetRespectsOne( zeromap, false );
1431	if IsMagmaWithInverses( source ) then
1432	  SetRespectsInverses( zeromap, false );
1433	fi;
1434      fi;
1435    fi;
1436
1437    # additive structure
1438    if IsAdditiveMagma( source ) then
1439      SetRespectsAddition( zeromap, true );
1440      if IsAdditiveMagmaWithZero( source ) then
1441	SetRespectsZero( zeromap, true );
1442	if IsAdditiveGroup( source ) then
1443	  SetRespectsAdditiveInverses( zeromap, true );
1444	fi;
1445      fi;
1446    fi;
1447
1448    # linear structure
1449    if IsLeftModule( source ) then
1450      SetRespectsScalarMultiplication( zeromap, true );
1451    fi;
1452end );
1453
1454
1455#############################################################################
1456##
1457#F  ZeroMapping( <source>, <range> )
1458##
1459##  maps every element of <source> to 'Zero( <range> )'.
1460##  This is independent of the structure of <source> and <range>.
1461##
1462InstallMethod( ZeroMapping,
1463    "for collection and additive-magma-with-zero",
1464    true,
1465    [ IsCollection, IsAdditiveMagmaWithZero ], 0,
1466    function( S, R )
1467
1468    local zero;   # the zero mapping, result
1469
1470    # make the mapping
1471    zero := Objectify( TypeOfDefaultGeneralMapping( S, R,
1472                                  IsSPGeneralMapping
1473                              and IsAdditiveElementWithInverse
1474                              and IsAttributeStoringRep
1475                              and IsZero ),
1476                       rec() );
1477
1478    # set the respectings
1479    ImmediateImplicationsZeroMapping( zero );
1480
1481    # return the zero mapping
1482    return zero;
1483    end );
1484
1485
1486#############################################################################
1487##
1488#M  \^( <zeromap>, <n> )  . . . . . . . for zero mapping and positive integer
1489##
1490InstallMethod( \^,
1491    "for zero mapping and positive integer",
1492    true,
1493    [ IsGeneralMapping and IsZero, IsPosInt ], SUM_FLAGS,
1494    function( zero, n )
1495    if Zero( Source( zero ) ) in Range( zero ) then
1496      return zero;
1497    else
1498      Error( "source and range of <zero> do not match" );
1499    fi;
1500    end );
1501
1502
1503#############################################################################
1504##
1505#M  ImagesSource( <zeromap> ) . . . . . . . . . . . . . . .  for zero mapping
1506##
1507InstallMethod( ImagesSource,
1508    "for zero mapping",
1509    true,
1510    [ IsGeneralMapping and IsZero ], SUM_FLAGS,
1511    function( zero )
1512    if IsAdditiveMagmaWithZero( Range( zero ) ) then
1513      return TrivialSubadditiveMagmaWithZero( Range( zero ) );
1514    else
1515      return [ Zero( Range( zero ) ) ];
1516    fi;
1517    end );
1518
1519
1520#############################################################################
1521##
1522#M  ImageElm( <zeromap>, <elm> )  . . . . . . .  for zero mapping and element
1523##
1524InstallMethod( ImageElm,
1525    "for zero mapping and object",
1526    FamSourceEqFamElm,
1527    [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS,
1528    function( zero, elm )
1529    return Zero( Range( zero ) );
1530    end );
1531
1532
1533#############################################################################
1534##
1535#M  ImagesElm( <zeromap>, <elm> )  . . . . . . . for zero mapping and element
1536##
1537InstallMethod( ImagesElm,
1538    "for zero mapping and object",
1539    FamSourceEqFamElm,
1540    [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS,
1541    function( zero, elm )
1542    return [ Zero( Range( zero ) ) ];
1543    end );
1544
1545
1546#############################################################################
1547##
1548#M  ImagesSet( <zeromap>, <coll> ) . . . . .  for zero mapping and collection
1549##
1550InstallMethod( ImagesSet,
1551    "for zero mapping and collection",
1552    CollFamSourceEqFamElms,
1553    [ IsGeneralMapping and IsZero, IsCollection ], SUM_FLAGS,
1554    function( zero, elms )
1555    return TrivialSubadditiveMagmaWithZero( Range( zero ) );
1556    end );
1557
1558
1559#############################################################################
1560##
1561#M  ImagesRepresentative( <zeromap>, <elm> )  .  for zero mapping and element
1562##
1563InstallMethod( ImagesRepresentative,
1564    "for zero mapping and object",
1565    FamSourceEqFamElm,
1566    [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS,
1567    function( zero, elm )
1568    return Zero( Range( zero ) );
1569    end );
1570
1571
1572#############################################################################
1573##
1574#M  PreImagesElm( <zeromap>, <elm> )  . . . . .  for zero mapping and element
1575##
1576InstallMethod( PreImagesElm,
1577    "for zero mapping and object",
1578    FamRangeEqFamElm,
1579    [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS,
1580    function( zero, elm )
1581    if elm = Zero( Range( zero ) ) then
1582      return Source( zero );
1583    else
1584      return [];
1585    fi;
1586    end );
1587
1588
1589#############################################################################
1590##
1591#M  PreImagesSet( <zeromap>, <elms> ) . . . . for zero mapping and collection
1592##
1593InstallMethod( PreImagesSet,
1594    "for zero mapping and collection",
1595    CollFamRangeEqFamElms,
1596    [ IsGeneralMapping and IsZero, IsCollection ], SUM_FLAGS,
1597    function( zero, elms )
1598    if Zero( Range( zero ) ) in elms then
1599      return Source( zero );
1600    else
1601      return [];
1602    fi;
1603    end );
1604
1605
1606#############################################################################
1607##
1608#M  PreImagesRepresentative( <zeromap>, <elm> )
1609##
1610InstallMethod( PreImagesRepresentative,
1611    "for zero mapping and object",
1612    FamRangeEqFamElm,
1613    [ IsGeneralMapping and IsZero, IsObject ], SUM_FLAGS,
1614    function( zero, elm )
1615    if elm = Zero( Range( zero ) ) then
1616      return Zero( Source( zero ) );
1617    else
1618      return fail;
1619    fi;
1620    end );
1621
1622
1623#############################################################################
1624##
1625#M  ViewObj( <zeromap> )  . . . . . . . . . . . . . . . . .  for zero mapping
1626#M  PrintObj( <zeromap> ) . . . . . . . . . . . . . . . . .  for zero mapping
1627##
1628InstallMethod( ViewObj,
1629    "for zero mapping",
1630    true,
1631    [ IsGeneralMapping and IsZero ],
1632    # rank up, but just to exactly SUM_FLAGS, so that mappings in a special
1633    # representation with a custom printing method still get that, even if
1634    # the rank of IsGeneralMapping and IsZero happens to be increased a lot
1635    {} -> SUM_FLAGS - RankFilter( IsGeneralMapping and IsZero ),
1636    function( zero )
1637    Print( "ZeroMapping( " );
1638    View( Source( zero ) );
1639    Print( ", " );
1640    View( Range( zero ) );
1641    Print( " )" );
1642    end );
1643
1644InstallMethod( PrintObj,
1645    "for zero mapping",
1646    true,
1647    [ IsGeneralMapping and IsZero ],
1648    # rank up, but just to exactly SUM_FLAGS, so that mappings in a special
1649    # representation with a custom printing method still get that, even if
1650    # the rank of IsGeneralMapping and IsZero happens to be increased a lot
1651    {} -> SUM_FLAGS - RankFilter( IsGeneralMapping and IsZero ),
1652    function( zero )
1653    Print( "ZeroMapping( ", Source( zero ), ", ", Range( zero ), " )" );
1654    end );
1655
1656
1657#############################################################################
1658##
1659#M  CompositionMapping2( <map>, <zeromap> ) for gen. mapping and zero mapping
1660##
1661InstallMethod( CompositionMapping2,
1662    "for general mapping and zero mapping",
1663    FamSource1EqFamRange2,
1664    [ IsGeneralMapping, IsGeneralMapping and IsZero ], SUM_FLAGS,
1665    function( map, zero )
1666    return ZeroMapping( Source( map ), Range( zero ) );
1667    end );
1668
1669
1670#############################################################################
1671##
1672#M  CompositionMapping2( <zeromap>, <map> ) for zero mapping and gen. mapping
1673##
1674InstallMethod( CompositionMapping2,
1675    "for zero mapping and single-valued gen. mapping that resp. zero",
1676    FamSource1EqFamRange2,
1677    [ IsGeneralMapping and IsZero,
1678      IsGeneralMapping and IsSingleValued and RespectsZero ],
1679    SUM_FLAGS,
1680    function( zero, map )
1681    return ZeroMapping( Source( zero ), Range( map ) );
1682    end );
1683
1684
1685#############################################################################
1686##
1687#M  IsInjective( <zeromap> )  . . . . . . . . . . . . . . .  for zero mapping
1688##
1689InstallMethod( IsInjective,
1690    "for zero mapping",
1691    true,
1692    [ IsGeneralMapping and IsZero ], 0,
1693    zero -> Size( Source( zero ) ) = 1 );
1694
1695
1696#############################################################################
1697##
1698#M  IsSurjective( <zeromap> ) . . . . . . . . . . . . . . .  for zero mapping
1699##
1700InstallMethod( IsSurjective,
1701    "for zero mapping",
1702    true,
1703    [ IsGeneralMapping and IsZero ], 0,
1704    zero -> Size( Range( zero ) ) = 1 );
1705
1706#############################################################################
1707##
1708##  7. methods for general restricted mappings,
1709##
1710
1711#############################################################################
1712##
1713#M  GeneralRestrictedMapping( <map>, <source>,<range> )
1714##
1715InstallGlobalFunction(GeneralRestrictedMapping,
1716function( map, s,r )
1717local res, prop;
1718
1719  # Make the general mapping.
1720  if IsSPGeneralMapping( map )  then
1721    res:= Objectify( TypeOfDefaultGeneralMapping( s,r,
1722		      IsGeneralRestrictedMappingRep and IsSPGeneralMapping ),
1723		    rec() );
1724  else
1725    res:= Objectify( TypeOfDefaultGeneralMapping( s,r,
1726		      IsGeneralRestrictedMappingRep and IsNonSPGeneralMapping ),
1727		    rec() );
1728  fi;
1729
1730  # Enter the identifying information.
1731  res!.map:= map;
1732  SetSource(res,s);
1733  SetRange(res,r);
1734
1735  for prop in [IsSingleValued, IsTotal, IsInjective, RespectsMultiplication, , RespectsInverses,
1736	  RespectsAddition, RespectsAdditiveInverses, RespectsScalarMultiplication] do
1737	if Tester(prop)(map) and prop(map) then
1738		Setter(prop)(res, true);
1739	fi;
1740  od;
1741
1742  # Return the restriction.
1743  return res;
1744end );
1745
1746
1747#############################################################################
1748##
1749#M  ImagesElm( <map>, <elm> ) . . . . . . . . . . . . for restricted mapping
1750##
1751InstallMethod( ImagesElm,
1752    "for a restricted mapping, and an element",
1753    FamSourceEqFamElm,
1754    [ IsGeneralRestrictedMappingRep, IsObject ], 0,
1755    function( res, elm )
1756    local im;
1757    im:= ImagesElm( res!.map, elm );
1758    if not ( (HasIsSingleValued(res) and IsSingleValued(res)) or
1759	(HasIsSingleValued(res!.map) and IsSingleValued(res!.map)) ) then
1760      im:=Intersection(Range(res),im);
1761    fi;
1762    return im;
1763  end );
1764
1765
1766#############################################################################
1767##
1768#M  ImagesSet( <map>, <elms> )  . . . . . . . . . . . for restricted mapping
1769##
1770InstallMethod( ImagesSet,
1771    "for a restricted mapping, and a collection",
1772    CollFamSourceEqFamElms,
1773    [ IsGeneralRestrictedMappingRep, IsCollection ], 0,
1774    function ( res, elms )
1775    local im;
1776    im:= ImagesSet( res!.map, elms );
1777    if not ( (HasIsSingleValued(res) and IsSingleValued(res)) or
1778	(HasIsSingleValued(res!.map) and IsSingleValued(res!.map)) ) then
1779      im:=Intersection(Range(res),im);
1780    fi;
1781    return im;
1782  end );
1783
1784
1785#############################################################################
1786##
1787#M  ImagesRepresentative( <map>, <elm> )  . . . . . . for restricted mapping
1788##
1789InstallMethod( ImagesRepresentative,
1790    "for a restricted mapping, and an element",
1791    FamSourceEqFamElm,
1792    [ IsGeneralRestrictedMappingRep, IsObject ], 0,
1793    function( res, elm )
1794    local im;
1795    im:= ImagesRepresentative( res!.map, elm );
1796    if im = fail then
1797      # 'elm' has no images under 'res!.map', so it has none under 'res'.
1798      return fail;
1799    elif im in Range(res) then
1800      return im;
1801    elif HasIsSingleValued(res!.map) and IsSingleValued(res!.map) then
1802      return fail; # no other choice
1803    else
1804      # It may happen that only the chosen representative is not in im
1805      im:= ImagesElm( res!.map, elm );
1806      return First(im,i->i in Range(res));
1807    fi;
1808end );
1809
1810
1811#############################################################################
1812##
1813#M  PreImagesElm( <map>, <elm> )  . . . . . . . . . . for restricted mapping
1814##
1815InstallMethod( PreImagesElm,
1816    "for a restricted mapping, and an element",
1817    FamRangeEqFamElm,
1818    [ IsGeneralRestrictedMappingRep, IsObject ], 0,
1819    function( res, elm )
1820    local preim;
1821    preim:= PreImagesElm( res!.map, elm );
1822    if not ( (HasIsInjective(res) and IsInjective(res)) or
1823	(HasIsInjective(res!.map) and IsInjective(res!.map)) ) then
1824      preim:=Intersection(Source(res),preim);
1825    fi;
1826    return preim;
1827end );
1828
1829
1830#############################################################################
1831##
1832#M  PreImagesSet( <map>, <elm> )  . . . . . . . . . . for restricted mapping
1833##
1834InstallMethod( PreImagesSet,
1835    "for a restricted mapping, and a collection",
1836    CollFamRangeEqFamElms,
1837    [ IsGeneralRestrictedMappingRep, IsCollection ], 0,
1838    function( res, elms )
1839    local preim;
1840    preim:= PreImagesSet( res!.map, elms );
1841    if not ( (HasIsInjective(res) and IsInjective(res)) or
1842	(HasIsInjective(res!.map) and IsInjective(res!.map)) ) then
1843      preim:=Intersection(Source(res),preim);
1844    fi;
1845    return preim;
1846    end );
1847
1848
1849#############################################################################
1850##
1851#M  PreImagesRepresentative( <map>, <elm> ) . . . . . for restricted mapping
1852##
1853InstallMethod( PreImagesRepresentative,
1854    "for a restricted mapping, and an element",
1855    FamRangeEqFamElm,
1856    [ IsGeneralRestrictedMappingRep, IsObject ], 0,
1857    function( res, elm )
1858    local preim, rep;
1859    preim:= PreImagesRepresentative( res!.map, elm );
1860    if preim = fail then
1861      # 'elm' has no preimages under 'res!.map', so it has none under 'res'.
1862      return fail;
1863    elif preim in Source(res) then
1864      return preim;
1865    elif HasIsInjective(res!.map) and IsInjective(res!.map) then
1866      return fail; # no other choice
1867    else
1868      preim:= PreImages( res!.map, elm );
1869      return First(preim,x->x in Source(res));
1870    fi;
1871    end );
1872
1873
1874#############################################################################
1875##
1876#M  KernelOfAdditiveGeneralMapping( <map> ) . . . . . for restricted mapping
1877##
1878InstallMethod( KernelOfAdditiveGeneralMapping,
1879    "for a restricted mapping that resp. add. and add.inv.", true,
1880    [ IsGeneralMapping and IsGeneralRestrictedMappingRep
1881      and RespectsAddition and RespectsAdditiveInverses ], 0,
1882function( res )
1883  return Intersection(Source(res),KernelOfAdditiveGeneralMapping( res!.map ));
1884end );
1885
1886
1887#############################################################################
1888##
1889#M  CoKernelOfAdditiveGeneralMapping( <map> ) . . . . for restricted mapping
1890##
1891InstallMethod( CoKernelOfAdditiveGeneralMapping,
1892    "for a restricted mapping that resp. add. and add.inv.",
1893    true,
1894    [ IsGeneralMapping and IsGeneralRestrictedMappingRep
1895      and RespectsAddition and RespectsAdditiveInverses ], 0,
1896function( res )
1897  return Intersection(Range(res),CoKernelOfAdditiveGeneralMapping( res!.map ));
1898end );
1899
1900#############################################################################
1901##
1902#M  KernelOfMultiplicativeGeneralMapping( <map> ) . . for restricted mapping
1903##
1904InstallMethod( KernelOfMultiplicativeGeneralMapping,
1905    "for a restricted mapping that resp. mult. and inv.",
1906    true,
1907    [ IsGeneralMapping and IsGeneralRestrictedMappingRep
1908      and RespectsMultiplication and RespectsInverses ], 0,
1909function( res )
1910  return Intersection(Source(res),
1911                      KernelOfMultiplicativeGeneralMapping(res!.map));
1912end );
1913
1914#############################################################################
1915##
1916#M  CoKernelOfMultiplicativeGeneralMapping( <map> ) . for restricted mapping
1917##
1918InstallMethod( CoKernelOfMultiplicativeGeneralMapping,
1919    "for a restricted mapping that resp. mult. and inv.",
1920    true,
1921    [ IsGeneralMapping and IsGeneralRestrictedMappingRep
1922      and RespectsMultiplication and RespectsInverses ], 0,
1923function( res )
1924  return Intersection(Range(res),
1925                      CoKernelOfMultiplicativeGeneralMapping(res!.map));
1926end );
1927
1928#############################################################################
1929##
1930#M  ViewObj( <map> )  . . . . . . . . . . . . . . . . for restricted mapping
1931#M  PrintObj( <map> ) . . . . . . . . . . . . . . . . for restricted mapping
1932##
1933InstallMethod( ViewObj,
1934    "for a restricted mapping",
1935    true,
1936    [ IsGeneralRestrictedMappingRep ], 100,
1937    function( res )
1938    Print( "GeneralRestrictedMapping( " );
1939    View( res!.map );
1940    Print( ", " );
1941    View( Source(res) );
1942    Print( ", " );
1943    View( Range(res) );
1944    Print( " )" );
1945    end );
1946
1947InstallMethod( PrintObj,
1948    "for a restricted mapping",
1949    true,
1950    [ IsGeneralRestrictedMappingRep ], 100,
1951    function( res )
1952    Print( "GeneralRestrictedMapping( ", res!.map, ", ", Source(res),
1953           ",", Range(res)," )" );
1954    end );
1955
1956
1957#############################################################################
1958##
1959#M  RestrictedMapping(<hom>,<U>)
1960##
1961InstallMethod(RestrictedMapping,"for mapping that is already restricted",
1962  CollFamSourceEqFamElms,
1963  [IsGeneralMapping and IsGeneralRestrictedMappingRep, IsDomain],
1964  SUM_FLAGS,
1965function(hom, U)
1966  return GeneralRestrictedMapping (hom!.map, U, Range(hom!.map));
1967end);
1968
1969
1970#############################################################################
1971##
1972#M  RestrictedMapping(<hom>,<U>)
1973##
1974InstallMethod(RestrictedMapping,"use GeneralRestrictedMapping",
1975  CollFamSourceEqFamElms,[IsGeneralMapping,IsDomain],0,
1976function(hom, U)
1977  return GeneralRestrictedMapping (hom, U, Range(hom));
1978end);
1979