GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#############################################################################
##
## ToolsForHomalg.gi ToolsForHomalg package
##
## Copyright 2007-2012, Mohamed Barakat, University of Kaiserslautern
## Sebastian Gutsche, RWTH-Aachen University
## Markus Lange-Hegermann, RWTH-Aachen University
##
## Implementations for ToolsForHomalg.
##
#############################################################################
####################################
#
# representations:
#
####################################
## <#GAPDoc Label="IsStructureObjectOrFinitelyPresentedObjectRep">
## <ManSection>
## <Filt Type="Representation" Arg="M" Name="IsStructureObjectOrFinitelyPresentedObjectRep"/>
## <Returns><C>true</C> or <C>false</C></Returns>
## <Description>
## The &GAP; representation of finitley generated &homalg; objects. <P/>
## It is a representation of the &GAP; category <Ref Filt="IsHomalgObject"/>.
## </Description>
## </ManSection>
## <#/GAPDoc>
##
DeclareRepresentation( "IsStructureObjectOrFinitelyPresentedObjectRep",
IsStructureObjectOrObject,
[ ] );
# a new representation for the GAP-category IsHomalgObject
# which is a subrepresentation of the representation IsStructureObjectOrFinitelyPresentedObjectRep and IsHomalgRingOrModule:
DeclareRepresentation( "IsHomalgRingOrFinitelyPresentedModuleRep",
IsStructureObjectOrFinitelyPresentedObjectRep and
IsHomalgRingOrModule,
[ ] );
# a new representation for the GAP-category IsContainerForWeakPointers:
DeclareRepresentation( "IsContainerForWeakPointersRep",
IsContainerForWeakPointers,
[ "weak_pointers", "active", "deleted", "counter", "cache_hits" ] );
# a new subrepresentation of IsContainerForWeakPointersRep:
DeclareRepresentation( "IsContainerForWeakPointersOnObjectsRep",
IsContainerForWeakPointersRep,
[ "weak_pointers", "active", "deleted", "counter", "accessed", "cache_misses", "cache_hits" ] );
# a new subrepresentation of IsContainerForWeakPointersOnObjectsRep:
DeclareRepresentation( "IsContainerForWeakPointersOnComputedValuesRep",
IsContainerForWeakPointersOnObjectsRep,
[ "weak_pointers", "weak_pointers_on_values", "active", "deleted", "counter", "accessed", "cache_misses", "cache_hits" ] );
# a new subrepresentation of IsContainerForWeakPointersOnObjectsRep:
DeclareRepresentation( "IsContainerForWeakPointersOnContainersRep",
IsContainerForWeakPointersOnObjectsRep,
[ "weak_pointers", "active", "deleted", "counter" ] );
####################################
#
# representations for pointer object
#
####################################
# a new representation for the GAP-category IsContainerForPointers:
DeclareRepresentation( "IsContainerForPointersRep",
IsContainerForPointers,
[ "pointers", "counter", "cache_hits", "cache_misses" ] );
# a new subrepresentation of IsContainerForPointersRep:
DeclareRepresentation( "IsContainerForPointersOnObjectsRep",
IsContainerForPointersRep,
[ "pointers", "counter", "accessed" ] );
# a new subrepresentation of IsContainerForPointersOnObjectsRep:
DeclareRepresentation( "IsContainerForPointersOnComputedValuesRep",
IsContainerForPointersOnObjectsRep,
[ "pointers", "pointers_on_values", "counter", "accessed" ] );
# a new subrepresentation of IsContainerForPointersOnObjectsRep:
DeclareRepresentation( "IsContainerForPointersOnContainersRep",
IsContainerForPointersOnObjectsRep,
[ "pointers", "counter" ] );
####################################
#
# families and types:
#
####################################
# a new family:
BindGlobal( "TheFamilyOfContainersForWeakPointers",
NewFamily( "TheFamilyOfContainersForWeakPointers" ) );
# a new type:
BindGlobal( "TheTypeContainerForWeakPointers",
NewType( TheFamilyOfContainersForWeakPointers,
IsContainerForWeakPointersRep ) );
# a new type:
BindGlobal( "TheTypeContainerForWeakPointersOnObjects",
NewType( TheFamilyOfContainersForWeakPointers,
IsContainerForWeakPointersOnObjectsRep ) );
# a new type:
BindGlobal( "TheTypeContainerForWeakPointersOnComputedValues",
NewType( TheFamilyOfContainersForWeakPointers,
IsContainerForWeakPointersOnComputedValuesRep ) );
# a new type:
BindGlobal( "TheTypeContainerForWeakPointersOnContainers",
NewType( TheFamilyOfContainersForWeakPointers,
IsContainerForWeakPointersOnContainersRep ) );
####################################
#
# global variables:
#
####################################
# a central place for configuration variables:
InstallValue( HOMALG_TOOLS,
rec(
TotalRuntimes := 0,
minus_infinity := -999999,
## ContainersForWeakPointers "will be added below",
)
);
## cannot move it to read.g
if IsBound( MakeThreadLocal ) then
MakeThreadLocal( "HOMALG_TOOLS" );
fi;
####################################
#
# global functions:
#
####################################
InfoOfObject :=
function( arg )
local o, depth, attr, cmpn, prop, tprp, all, i, r, a;
o := arg[1];
if Length( arg ) > 1 then
depth := arg[2];
else
depth := 1;
fi;
if depth = 0 then
return o;
elif IsAttributeStoringRep( o ) then
attr := KnownAttributesOfObject( o );
cmpn := Filtered( NamesOfComponents( o ), a -> not( a in attr ) );
prop := KnownPropertiesOfObject( o );
all := rec( object := o,
attributes := attr,
components := cmpn,
properties := prop );
elif IsComponentObjectRep( o ) then
all := rec( object := o, components := NamesOfComponents( o ) );
else
return o;
fi;
## below o is an AttributeStoringRep or at least a ComponentObjectRep:
for i in NamesOfComponents( all ) do
if i in [ "attributes" ] then
r := rec( );
for a in all.(i) do
r.(a) := InfoOfObject( ValueGlobal( a )( o ), depth-1 );
od;
all.(i) := r;
elif i in [ "components" ] then
r := rec( );
for a in all.(i) do
r.(a) := InfoOfObject( o!.(a), depth-1 );
od;
all.(i) := r;
elif i = "properties" then
r := rec( );
for a in all.(i) do
r.(a) := ValueGlobal( a )( o );
od;
all.(i) := r;
fi;
od;
return all;
end;
##
InstallGlobalFunction( ContainerForWeakPointers,
function( arg )
local nargs, container, component, type, containers;
nargs := Length( arg );
container := rec( weak_pointers := WeakPointerObj( [ ] ),
active := [ ],
deleted := [ ],
counter := 0,
accessed := 0,
cache_misses := 0,
cache_hits := 0 );
for component in arg{[ 2 .. nargs ]} do
container.( component[1] ) := component[2];
od;
type := arg[1];
## Objectify:
Objectify( type, container );
if IsBound( HOMALG_TOOLS.ContainersForWeakPointers ) then
_AddElmWPObj_ForHomalg( HOMALG_TOOLS.ContainersForWeakPointers, container );
fi;
if IsContainerForWeakPointersOnComputedValuesRep( container ) then
container!.weak_pointers_on_values := WeakPointerObj( [ ] );
fi;
return container;
end );
HOMALG_TOOLS.ContainersForWeakPointers := ContainerForWeakPointers( TheTypeContainerForWeakPointersOnContainers );
Unbind( HOMALG_TOOLS.ContainersForWeakPointers!.accessed );
Unbind( HOMALG_TOOLS.ContainersForWeakPointers!.cache_misses );
Unbind( HOMALG_TOOLS.ContainersForWeakPointers!.cache_hits );
##
InstallGlobalFunction( homalgTotalRuntimes,
function( arg )
local r, t;
r := Runtimes( );
HOMALG_TOOLS.TotalRuntimes := r.user_time;
if IsBound( r.system_time ) and r.system_time <> fail then
HOMALG_TOOLS.TotalRuntimes := HOMALG_TOOLS.TotalRuntimes + r.system_time;
fi;
if IsBound( r.user_time_children ) and r.user_time_children <> fail then
HOMALG_TOOLS.TotalRuntimes := HOMALG_TOOLS.TotalRuntimes + r.user_time_children;
fi;
if IsBound( r.system_time_children ) and r.system_time_children <> fail then
HOMALG_TOOLS.TotalRuntimes := HOMALG_TOOLS.TotalRuntimes + r.system_time_children;
fi;
if Length( arg ) = 0 then
return HOMALG_TOOLS.TotalRuntimes;
fi;
t := HOMALG_TOOLS.TotalRuntimes - arg[1];
if Length( arg ) > 1 then
return Concatenation( StringTime( t ), " h" );
fi;
return t;
end );
##
InstallGlobalFunction( AddLeftRightLogicalImplicationsForHomalg,
function( list, properties )
local prop, property, left_property, right_property, add;
for prop in properties do;
if IsList( prop ) and Length( prop ) = 2 and ForAll( prop, IsString ) then
property := ValueGlobal( Concatenation( prop[1], prop[2] ) );
left_property := ValueGlobal( Concatenation( prop[1], "Left", prop[2] ) );
right_property := ValueGlobal( Concatenation( prop[1], "Right", prop[2] ) );
add := [
[ left_property, "and", right_property,
"define", property ],
[ property,
"implies by definition", left_property ],
[ property,
"implies by definition", right_property ],
[ IsCommutative, "and", left_property,
"trivially imply", right_property ],
[ IsCommutative, "and", right_property,
"trivially imply", left_property ],
## we also need these two for their contra positions to get installed
[ IsCommutative, "and", left_property,
"trivially imply", property ],
[ IsCommutative, "and", right_property,
"trivially imply", property ],
];
elif IsList( prop ) and Length( prop ) = 3 and ForAll( prop, IsString ) then
property := ValueGlobal( Concatenation( prop[1], prop[2] ) );
left_property := ValueGlobal( Concatenation( prop[1], "Left", prop[2] ) );
right_property := ValueGlobal( Concatenation( prop[1], "Right", prop[2] ) );
add := [
[ IsCommutative, "and", left_property,
"trivally imply", right_property ],
[ IsCommutative, "and", left_property,
"trivally imply", property ],
[ IsCommutative, "and", right_property,
"trivally imply", left_property ],
[ IsCommutative, "and", right_property,
"trivally imply", property ],
[ IsCommutative, "and", property,
"trivally imply", left_property ],
[ IsCommutative, "and", property,
"trivally imply", right_property ]
];
elif IsList( prop ) and Length( prop ) = 3 and ForAll( prop{[ 1 .. 2 ]}, IsString ) and IsOperation( prop[3] ) then
property := ValueGlobal( Concatenation( prop[1], prop[2] ) );
left_property := ValueGlobal( Concatenation( prop[1], "Left", prop[2] ) );
right_property := ValueGlobal( Concatenation( prop[1], "Right", prop[2] ) );
add := [
[ left_property, "and", right_property,
"define", property ],
[ property,
"implies by definition", left_property ],
[ property,
"implies by definition", right_property ],
];
fi;
Append( list, add );
od;
end );
## a global function for logical implications:
InstallGlobalFunction( LogicalImplicationsForOneHomalgObject,
function( statement, filter )
local len, propA, propB, propC, prop;
len := Length( statement );
if len = 3 then
propA := statement[1];
prop := statement[3];
InstallTrueMethod( prop, filter and propA );
InstallImmediateMethod( propA,
filter and Tester( prop ), 0,
function( o )
if not prop( o ) then
return false;
fi;
TryNextMethod( );
end );
elif len = 5 then
propA := statement[1];
propB := statement[3];
prop := statement[5];
InstallTrueMethod( prop, filter and propA and propB );
InstallImmediateMethod( propA,
filter and Tester( propB ) and Tester( prop ), 0,
function( o )
if propB( o ) and not prop( o ) then
return false;
fi;
TryNextMethod( );
end );
InstallImmediateMethod( propB,
filter and Tester( propA ) and Tester( prop ), 0,
function( o )
if propA( o ) and not prop( o ) then
return false;
fi;
TryNextMethod( );
end );
elif len = 7 then
propA := statement[1];
propB := statement[3];
propC := statement[5];
prop := statement[7];
InstallTrueMethod( prop, filter and propA and propB and propC );
InstallImmediateMethod( propA,
filter and Tester( propB ) and Tester( propC ) and Tester( prop ), 0,
function( o )
if propB( o ) and propC( o ) and not prop( o ) then
return false;
fi;
TryNextMethod( );
end );
InstallImmediateMethod( propB,
filter and Tester( propA ) and Tester( propC ) and Tester( prop ), 0,
function( o )
if propA( o ) and propC( o ) and not prop( o ) then
return false;
fi;
TryNextMethod( );
end );
InstallImmediateMethod( propC,
filter and Tester( propA ) and Tester( propB ) and Tester( prop ), 0,
function( o )
if propA( o ) and propB( o ) and not prop( o ) then
return false;
fi;
TryNextMethod( );
end );
fi;
end );
##
InstallGlobalFunction( InstallLogicalImplicationsForHomalgBasicObjects,
function( arg )
local nargs, properties, filter, subobj_filter, statement;
nargs := Length( arg );
if nargs < 2 then
Error( "too few arguments\n" );
fi;
properties := arg[1];
filter := arg[2];
if nargs = 2 then
for statement in properties do;
LogicalImplicationsForOneHomalgObject( statement, filter );
od;
elif nargs = 3 then
subobj_filter := arg[3];
for statement in properties do;
LogicalImplicationsForTwoHomalgBasicObjects( statement, filter, subobj_filter );
od;
fi;
end );
## a global function for left/right attributes:
InstallGlobalFunction( LeftRightAttributesForHomalg,
function( attr, filter )
local attribute, left_attribute, right_attribute;
attribute := ValueGlobal( attr );
left_attribute := ValueGlobal( Concatenation( "Left", attr ) );
right_attribute := ValueGlobal( Concatenation( "Right", attr ) );
InstallImmediateMethod( left_attribute,
filter and Tester( attribute ), 0,
function( o )
return attribute( o );
end );
InstallImmediateMethod( right_attribute,
filter and Tester( attribute ), 0,
function( o )
return attribute( o );
end );
InstallImmediateMethod( attribute,
filter and Tester( left_attribute ) and Tester( right_attribute ), 0,
function( o )
local l;
l := left_attribute( o );
if l = right_attribute( o ) then
return l;
fi;
TryNextMethod( );
end );
## extra for homalg rings
if filter = IsStructureObject then
InstallImmediateMethod( left_attribute,
filter and Tester( right_attribute ) and IsCommutative, 0,
function( o )
return right_attribute( o );
end );
InstallImmediateMethod( right_attribute,
filter and Tester( left_attribute ) and IsCommutative, 0,
function( o )
return left_attribute( o );
end );
fi;
end );
##
InstallGlobalFunction( InstallLeftRightAttributesForHomalg,
function( attributes, filter )
local attribute;
for attribute in attributes do;
LeftRightAttributesForHomalg( attribute, filter );
od;
end );
##
InstallGlobalFunction( MatchPropertiesAndAttributes,
function( arg )
local S, T, properties, attributes, propertiesS, propertiesT,
attributesS, attributesT, p, a, components, c;
S := arg[1];
T := arg[2];
properties := arg[3];
attributes := arg[4];
propertiesS := Intersection2( KnownPropertiesOfObject( S ), properties );
propertiesT := Intersection2( KnownPropertiesOfObject( T ), properties );
attributesS := Intersection2( KnownAttributesOfObject( S ), attributes );
attributesT := Intersection2( KnownAttributesOfObject( T ), attributes );
## for properties:
for p in propertiesS do ## also check if properties already set for both objects coincide
Setter( ValueGlobal( p ) )( T, ValueGlobal( p )( S ) );
od;
## now backwards
for p in Difference( propertiesT, propertiesS ) do
Setter( ValueGlobal( p ) )( S, ValueGlobal( p )( T ) );
od;
## for attributes:
for a in Difference( attributesS, attributesT ) do
Setter( ValueGlobal( a ) )( T, ValueGlobal( a )( S ) );
od;
## now backwards
for a in Difference( attributesT, attributesS ) do
Setter( ValueGlobal( a ) )( S, ValueGlobal( a )( T ) );
od;
## also check if properties already set for both objects coincide
## by now, more attributes than the union might be konwn
attributesS := Intersection2( KnownAttributesOfObject( S ), attributes );
attributesT := Intersection2( KnownAttributesOfObject( T ), attributes );
for a in Intersection2( attributesS, attributesT ) do
if ValueGlobal( a )( S ) <> ValueGlobal( a )( T ) then
Error( "the attribute ", a, " has different values for source and target object\n" );
fi;
od;
if Length( arg ) > 4 then
components := arg[5];
for c in components do
if IsBound( S!.(c) ) and not IsBound( T!.(c) ) then
T!.(c) := S!.(c);
elif IsBound( T!.(c) ) and not IsBound( S!.(c) ) then
S!.(c) := T!.(c);
fi;
od;
fi;
end );
##
InstallGlobalFunction( InstallImmediateMethodToPullPropertyOrAttribute,
function( filter1, filter2, prop_attr, trigger, get_remote_object );
InstallImmediateMethod( prop_attr,
filter1 and Tester( trigger ), 0,
function( M )
local U;
U := get_remote_object( M );
if Tester( prop_attr )( U ) then
return prop_attr( U );
fi;
TryNextMethod();
end );
InstallMethod( prop_attr,
"for homalg objects with an underlying object (PullPropertyOrAttribute)",
[ filter2 ],
function( M )
return prop_attr( get_remote_object( M ) );
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToConditionallyPullPropertyOrAttribute,
function( filter1, filter2, prop_attr, condition, trigger, get_remote_object );
InstallImmediateMethod( prop_attr,
filter1 and Tester( trigger ) and condition, 0,
function( M )
local U;
U := get_remote_object( M );
if Tester( prop_attr )( U ) then
return prop_attr( U );
fi;
TryNextMethod();
end );
InstallMethod( prop_attr,
"for homalg objects with an underlying object (ConditionallyPullPropertyOrAttribute)",
[ filter2 ],
function( M )
return condition( M ) and prop_attr( get_remote_object( M ) );
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToPullPropertyOrAttributeWithDifferentName,
function( filter1, filter2, prop_attr, trigger, get_remote_object );
InstallImmediateMethod( prop_attr[1],
filter1 and Tester( trigger ), 0,
function( M )
local U;
U := get_remote_object( M );
if Tester( prop_attr[2] )( U ) then
return prop_attr[2]( U );
fi;
TryNextMethod();
end );
InstallMethod( prop_attr[1],
"for homalg objects with an underlying object (PullPropertyOrAttributeWithDifferentName)",
[ filter2 ],
function( M )
return prop_attr[2]( get_remote_object( M ) );
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToPullPropertiesOrAttributes,
function( filter1, filter2, PROP_ATTR, triggers, get_remote_object )
local trigger, prop_attr;
for trigger in triggers do
for prop_attr in PROP_ATTR do
if IsString( prop_attr ) then
if prop_attr <> trigger then
InstallImmediateMethodToPullPropertyOrAttribute(
filter1,
filter2,
ValueGlobal( prop_attr ),
ValueGlobal( trigger ),
get_remote_object
);
fi;
elif IsList( prop_attr ) and Length( prop_attr ) = 2 and
IsString( prop_attr[1] ) and IsList( prop_attr[2] ) and IsString( prop_attr[2][1] ) then
if prop_attr[1] <> trigger then
InstallImmediateMethodToConditionallyPullPropertyOrAttribute(
filter1,
filter2,
ValueGlobal( prop_attr[1] ),
ValueGlobal( prop_attr[2][1] ),
ValueGlobal( trigger ),
get_remote_object
);
fi;
elif IsList( prop_attr ) and Length( prop_attr ) = 2 and ForAll( prop_attr, IsString ) then
if prop_attr[1] <> trigger then
InstallImmediateMethodToPullPropertyOrAttributeWithDifferentName(
filter1,
filter2,
List( prop_attr, ValueGlobal ),
ValueGlobal( trigger ),
get_remote_object
);
fi;
fi;
od;
od;
end );
##
InstallGlobalFunction( InstallImmediateMethodToPullTrueProperty,
function( filter1, filter2, prop, trigger, get_remote_object );
InstallImmediateMethod( prop,
filter1 and Tester( trigger ), 0,
function( M )
local U;
U := get_remote_object( M );
if Tester( prop )( U ) and prop( U ) then
return true;
fi;
TryNextMethod();
end );
InstallMethod( prop,
"for homalg objects with an underlying object (MethodToPullTrueProperty)",
[ filter2 ],
function( M )
if prop( get_remote_object( M ) ) then
return true;
fi;
TryNextMethod();
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToConditionallyPullTrueProperty,
function( filter1, filter2, prop, condition, trigger, get_remote_object );
InstallImmediateMethod( prop,
filter1 and Tester( trigger ) and condition, 0,
function( M )
local U;
U := get_remote_object( M );
if Tester( prop )( U ) and prop( U ) then
return true;
fi;
TryNextMethod();
end );
InstallMethod( prop,
"for homalg objects with an underlying object (ConditionallyPullTrueProperty)",
[ filter2 ],
function( M )
if condition( M ) and prop( get_remote_object( M ) ) then
return true;
fi;
TryNextMethod();
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToPullTruePropertyWithDifferentName,
function( filter1, filter2, prop, trigger, get_remote_object );
InstallImmediateMethod( prop[1],
filter1 and Tester( trigger ), 0,
function( M )
local U;
U := get_remote_object( M );
if Tester( prop[2] )( U ) and prop[2]( U ) then
return true;
fi;
TryNextMethod();
end );
InstallMethod( prop[1],
"for homalg objects with an underlying object (PullTruePropertyWithDifferentName)",
[ filter2 ],
function( M )
if prop[2]( get_remote_object( M ) ) then
return true;
fi;
TryNextMethod();
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToPullTrueProperties,
function( filter1, filter2, PROP, triggers, get_remote_object )
local trigger, prop;
for trigger in triggers do
for prop in PROP do
if IsString( prop ) then
if prop <> trigger then
InstallImmediateMethodToPullTrueProperty(
filter1,
filter2,
ValueGlobal( prop ),
ValueGlobal( trigger ),
get_remote_object
);
fi;
elif IsList( prop ) and Length( prop ) = 2 and
IsString( prop[1] ) and IsList( prop[2] ) and IsString( prop[2][1] ) then
if prop[1] <> trigger then
InstallImmediateMethodToConditionallyPullTrueProperty(
filter1,
filter2,
ValueGlobal( prop[1] ),
ValueGlobal( prop[2][1] ),
ValueGlobal( trigger ),
get_remote_object
);
fi;
elif IsList( prop ) and Length( prop ) = 2 and ForAll( prop, IsString ) then
if prop[1] <> trigger then
InstallImmediateMethodToPullTruePropertyWithDifferentName(
filter1,
filter2,
List( prop, ValueGlobal ),
ValueGlobal( trigger ),
get_remote_object
);
fi;
fi;
od;
od;
end );
##
InstallGlobalFunction( InstallImmediateMethodToPullFalseProperty,
function( filter1, filter2, prop, trigger, get_remote_object );
InstallImmediateMethod( prop,
filter1 and Tester( trigger ), 0,
function( M )
local U;
U := get_remote_object( M );
if Tester( prop )( U ) and not prop( U ) then
return false;
fi;
TryNextMethod();
end );
InstallMethod( prop,
"for homalg objects with an underlying object (PullFalseProperty)",
[ filter2 ],
function( M )
if not prop( get_remote_object( M ) ) then
return false;
fi;
TryNextMethod();
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToConditionallyPullFalseProperty,
function( filter1, filter2, prop, condition, trigger, get_remote_object );
InstallImmediateMethod( prop,
filter1 and Tester( trigger ) and condition, 0,
function( M )
local U;
U := get_remote_object( M );
if Tester( prop )( U ) and not prop( U ) then
return false;
fi;
TryNextMethod();
end );
InstallMethod( prop,
"for homalg objects with an underlying object (ConditionallyPullFalseProperty)",
[ filter2 ],
function( M )
if condition( M ) and not prop( get_remote_object( M ) ) then
return false;
fi;
TryNextMethod();
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToPullFalsePropertyWithDifferentName,
function( filter1, filter2, prop, trigger, get_remote_object );
InstallImmediateMethod( prop[1],
filter1 and Tester( trigger ), 0,
function( M )
local U;
U := get_remote_object( M );
if Tester( prop[2] )( U ) and not prop[2]( U ) then
return false;
fi;
TryNextMethod();
end );
InstallMethod( prop[1],
"for homalg objects with an underlying object (PullFalsePropertyWithDifferentName)",
[ filter2 ],
function( M )
if not prop[2]( get_remote_object( M ) ) then
return false;
fi;
TryNextMethod();
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToPullFalseProperties,
function( filter1, filter2, PROP, triggers, get_remote_object )
local trigger, prop;
for trigger in triggers do
for prop in PROP do
if IsString( prop ) then
if prop <> trigger then
InstallImmediateMethodToPullFalseProperty(
filter1,
filter2,
ValueGlobal( prop ),
ValueGlobal( trigger ),
get_remote_object
);
fi;
elif IsList( prop ) and Length( prop ) = 2 and
IsString( prop[1] ) and IsList( prop[2] ) and IsString( prop[2][1] ) then
if prop[1] <> trigger then
InstallImmediateMethodToConditionallyPullFalseProperty(
filter1,
filter2,
ValueGlobal( prop[1] ),
ValueGlobal( prop[2][1] ),
ValueGlobal( trigger ),
get_remote_object
);
fi;
elif IsList( prop ) and Length( prop ) = 2 and ForAll( prop, IsString ) then
if prop[1] <> trigger then
InstallImmediateMethodToPullFalsePropertyWithDifferentName(
filter1,
filter2,
List( prop, ValueGlobal ),
ValueGlobal( trigger ),
get_remote_object
);
fi;
fi;
od;
od;
end );
##
InstallGlobalFunction( InstallImmediateMethodToPushPropertyOrAttribute,
function( twitter, filter, prop_attr, get_remote_object )
InstallImmediateMethod( twitter,
filter and Tester( prop_attr ), 0,
function( M )
Setter( prop_attr )( get_remote_object( M ), prop_attr( M ) );
TryNextMethod( );
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToConditionallyPushPropertyOrAttribute,
function( twitter, filter, prop_attr, condition, get_remote_object )
InstallImmediateMethod( twitter,
filter and Tester( prop_attr ) and condition, 0,
function( M )
Setter( prop_attr )( get_remote_object( M ), prop_attr( M ) );
TryNextMethod( );
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToPushPropertyOrAttributeWithDifferentName,
function( twitter, filter, prop_attr, get_remote_object )
InstallImmediateMethod( twitter,
filter and Tester( prop_attr[1] ), 0,
function( M )
Setter( prop_attr[2] )( get_remote_object( M ), prop_attr[1]( M ) );
TryNextMethod( );
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToPushPropertiesOrAttributes,
function( twitter, filter, PROP_ATTR, get_remote_object )
local prop_attr;
for prop_attr in PROP_ATTR do
if IsString( prop_attr ) then
InstallImmediateMethodToPushPropertyOrAttribute(
twitter,
filter,
ValueGlobal( prop_attr ),
get_remote_object
);
elif IsList( prop_attr ) and Length( prop_attr ) = 2 and
IsString( prop_attr[1] ) and IsList( prop_attr[2] ) and IsString( prop_attr[2][1] ) then
InstallImmediateMethodToConditionallyPushPropertyOrAttribute(
twitter,
filter,
ValueGlobal( prop_attr[1] ),
ValueGlobal( prop_attr[2][1] ),
get_remote_object
);
elif IsList( prop_attr ) and Length( prop_attr ) = 2 and ForAll( prop_attr, IsString ) then
InstallImmediateMethodToPushPropertyOrAttributeWithDifferentName(
twitter,
filter,
List( prop_attr, ValueGlobal ),
get_remote_object
);
fi;
od;
end );
##
InstallGlobalFunction( InstallImmediateMethodToPushTrueProperty,
function( twitter, filter, prop, get_remote_object )
InstallImmediateMethod( twitter,
filter and prop, 0,
function( M )
Setter( prop )( get_remote_object( M ), true );
TryNextMethod( );
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToPushTruePropertyWithDifferentName,
function( twitter, filter, prop, get_remote_object )
InstallImmediateMethod( twitter,
filter and prop[1], 0,
function( M )
Setter( prop[2] )( get_remote_object( M ), true );
TryNextMethod( );
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToPushTrueProperties,
function( twitter, filter, PROP, get_remote_object )
local prop;
for prop in PROP do
if IsString( prop ) then
InstallImmediateMethodToPushTrueProperty(
twitter, filter, ValueGlobal( prop ), get_remote_object
);
elif IsList( prop ) and Length( prop ) = 2 and ForAll( prop, IsString ) then
InstallImmediateMethodToPushTruePropertyWithDifferentName(
twitter, filter, List( prop, ValueGlobal ), get_remote_object
);
fi;
od;
end );
##
InstallGlobalFunction( InstallImmediateMethodToPushFalseProperty,
function( twitter, filter, prop, get_remote_object )
InstallImmediateMethod( twitter,
filter and Tester( prop ), 0,
function( M )
if not prop( M ) then
Setter( prop )( get_remote_object( M ), false );
fi;
TryNextMethod( );
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToPushFalsePropertyWithDifferentName,
function( twitter, filter, prop, get_remote_object )
InstallImmediateMethod( twitter,
filter and Tester( prop[1] ), 0,
function( M )
if not prop[1]( M ) then
Setter( prop[2] )( get_remote_object( M ), false );
fi;
TryNextMethod( );
end );
end );
##
InstallGlobalFunction( InstallImmediateMethodToPushFalseProperties,
function( twitter, filter, PROP, get_remote_object )
local prop;
for prop in PROP do
if IsString( prop ) then
InstallImmediateMethodToPushFalseProperty(
twitter, filter, ValueGlobal( prop ), get_remote_object
);
elif IsList( prop ) and Length( prop ) = 2 and ForAll( prop, IsString ) then
InstallImmediateMethodToPushFalsePropertyWithDifferentName(
twitter, filter, List( prop, ValueGlobal ), get_remote_object
);
fi;
od;
end );
# This function declares an attribute, but does not install the standard getter.
# instead, a getter given as third argument is installed.
# the primary use of this method is for morphism aids: we are able to set lazy
# morphism aids and compute them by the getter.
##
InstallGlobalFunction( DeclareAttributeWithCustomGetter,
function ( arg )
local attr, name, custom_getter, nname, gvar, pos, filter;
name := arg[1];
custom_getter := arg[3];
if IsBoundGlobal( name ) then
Error( "expected a name not bound" );
else
attr := CallFuncList( NewAttribute, arg );
BindGlobal( name, custom_getter );
nname := "Set";
Append( nname, name );
BindGlobal( nname, SETTER_FILTER( attr ) );
nname := "Has";
Append( nname, name );
BindGlobal( nname, TESTER_FILTER( attr ) );
fi;
return;
end );
##
InstallGlobalFunction( AppendToAhomalgTable,
function( RP, RP_addon )
local component;
for component in NamesOfComponents( RP_addon ) do
RP!.(component) := RP_addon.(component);
od;
end );
##
InstallGlobalFunction( homalgNamesOfComponentsToIntLists,
function( arg )
return Filtered(
List( NamesOfComponents( arg[1] ),
function( a )
local l;
l := SplitString( a, ",", "[ ]" );
if Length( l ) = 1 then
if Length( l[1] ) <= 24 then
return Int( l[1] );
else
return fail;
fi;
else
return List( l, Int );
fi;
end
),
b -> b <> fail );
end );
##
InstallGlobalFunction( IncreaseExistingCounterInObject,
function( o, component )
o!.(component) := o!.(component) + 1;
end );
InstallGlobalFunction( IncreaseExistingCounterInObjectWithTiming,
function( o, component, t )
o!.(component) := o!.(component) + [ 1, t ];
end );
##
InstallGlobalFunction( IncreaseCounterInObject,
function( o, component )
if IsBound( o!.(component) ) then
o!.(component) := o!.(component) + 1;
else
o!.(component) := 1;
fi;
end );
##
InstallGlobalFunction( MemoryToString,
function( memory )
local m;
m := memory;
if m < 1024 then
return Concatenation( String( m ), " Bytes" );
fi;
m := Float( m / 1024 );
if m < 1024 then
return Concatenation( String( m ), " KB" );
fi;
m := Float( m / 1024 );
if m < 1024 then
return Concatenation( String( m ), " MB" );
fi;
m := Float( m / 1024 );
if m < 1024 then
return Concatenation( String( m ), " GB" );
fi;
m := Float( m / 1024 );
return Concatenation( String( m ), " TB" );
end );
##
InstallGlobalFunction( PrimePowerExponent,
function( n, p )
local a;
if not IsPrime( p ) then
Error( "the second argument is not a prime\n" );
fi;
a := -1;
repeat
a := a + 1;
n := n / p;
until not IsInt( n );
return a;
end );
##
InstallMethod( ViewList,
[ "IsList" ],
function( L )
local l, i;
l := Length( L );
if l = 0 then
ViewObj( [ ] );
return;
fi;
Print( "[ " );
ViewObj( L[1] );
for i in [ 2 .. l ] do
Print( ",\n " );
ViewObj( L[i] );
od;
Print( " ]\n" );
end );
####################################
#
# methods for operations:
#
####################################
##
InstallMethod( ExamplesForHomalg,
[ ], 0,
function( )
if LoadPackage( "ExamplesForHomalg" ) = true then
ExamplesForHomalg( );
else
return fail;
fi;
end );
##
InstallMethod( ExamplesForHomalg,
[ IsInt ], 0,
function( d )
if LoadPackage( "ExamplesForHomalg" ) = true then
ExamplesForHomalg( d );
else
return fail;
fi;
end );
##
InstallMethod( UpdateContainerOfWeakPointers,
"for containers of weak pointer lists",
[ IsContainerForWeakPointersRep ],
function( container )
local weak_pointers, l, active, l_active, i;
weak_pointers := container!.weak_pointers;
l := LengthWPObj( weak_pointers );
active := Filtered( container!.active, i -> i <= l );
l_active := Length( active );
i := 1;
while i <= l_active do
if ElmWPObj( weak_pointers, active[i] ) <> fail then
i := i + 1;
else ## active[i] is no longer active
Remove( active, i );
l_active := l_active - 1;
fi;
od;
## UpdateContainerOfWeakPointers is only called
## from view and display methods, which we do not want
## to count as accesses:
# container!.accessed := container!.accessed + 1;
container!.active := active;
container!.deleted := Difference( [ 1 .. l ], active );
end );
##
InstallMethod( UpdateContainerOfWeakPointers,
"for containers of weak pointer lists",
[ IsContainerForWeakPointersOnComputedValuesRep ],
function( container )
local weak_pointers, weak_pointers_on_values, l, active, l_active, i;
weak_pointers := container!.weak_pointers;
weak_pointers_on_values := container!.weak_pointers_on_values;
l := Minimum( LengthWPObj( weak_pointers ), LengthWPObj( weak_pointers_on_values ) );
active := Filtered( container!.active, i -> i <= l );
l_active := Length( active );
i := 1;
while i <= l_active do
if ElmWPObj( weak_pointers, active[i] ) <> fail and
ElmWPObj( weak_pointers_on_values, active[i] ) <> fail then
i := i + 1;
else ## active[i] is no longer active
Remove( active, i );
l_active := l_active - 1;
fi;
od;
## UpdateContainerOfWeakPointers is only called
## from view and display methods, which we do not want
## to count as accesses:
# container!.accessed := container!.accessed + 1;
container!.active := active;
container!.deleted := Difference( [ 1 .. l ], active );
end );
##
InstallGlobalFunction( _AddElmWPObj_ForHomalg,
function( container, obj )
local weak_pointers, l, deleted, active, l_active, d;
weak_pointers := container!.weak_pointers;
l := LengthWPObj( weak_pointers );
deleted := Filtered( container!.deleted, i -> i <= l );
active := Filtered( container!.active, i -> i <= l );
## check assertion
Assert( 10,
Intersection2( deleted, active ) = [ ] and
Union2( deleted, active ) = [ 1 .. l ] );
l_active := Length( active );
if deleted = [ ] then
SetElmWPObj( weak_pointers, l_active + 1, obj );
Add( active, l_active + 1 );
l := l + 1;
else
d := deleted[1];
SetElmWPObj( weak_pointers, d, obj );
Remove( deleted, 1 );
Add( active, d, d );
fi;
container!.deleted := deleted;
container!.active := active;
## here we increase container!.counter instead of container!.accessed;
container!.counter := container!.counter + 1;
end );
##
InstallGlobalFunction( _AddTwoElmWPObj_ForHomalg,
function( container, ref, value )
local weak_pointers, weak_pointers_on_values, l, deleted, active, l_active, d;
weak_pointers := container!.weak_pointers;
weak_pointers_on_values := container!.weak_pointers_on_values;
l := Minimum( LengthWPObj( weak_pointers ), LengthWPObj( weak_pointers_on_values ) );
deleted := Filtered( container!.deleted, i -> i <= l );
active := Filtered( container!.active, i -> i <= l );
## check assertion
Assert( 10,
Intersection2( deleted, active ) = [ ] and
Union2( deleted, active ) = [ 1 .. l ] );
l_active := Length( active );
if deleted = [ ] then
SetElmWPObj( weak_pointers, l_active + 1, ref );
SetElmWPObj( weak_pointers_on_values, l_active + 1, value );
Add( active, l_active + 1 );
l := l + 1;
else
d := deleted[1];
SetElmWPObj( weak_pointers, d, ref );
SetElmWPObj( weak_pointers_on_values, d, value );
Remove( deleted, 1 );
Add( active, d, d );
fi;
container!.deleted := deleted;
container!.active := active;
## here we increase container!.counter instead of container!.accessed;
container!.counter := container!.counter + 1;
end );
##
InstallMethod( _ElmWPObj_ForHomalg,
"for a container of weak pointer lists and two objects (a reference and a return fail value)",
[ IsContainerForWeakPointersOnComputedValuesRep, IsObject, IsObject ], 0,
function( container, obj, FAIL )
local weak_pointers, weak_pointers_on_values, l, active, cache_hit, l_active, i, ref, value;
weak_pointers := container!.weak_pointers;
weak_pointers_on_values := container!.weak_pointers_on_values;
l := Minimum( LengthWPObj( weak_pointers ), LengthWPObj( weak_pointers_on_values ) );
active := Filtered( container!.active, i -> i <= l );
cache_hit := false;
l_active := Length( active );
i := 1;
while i <= l_active do
value := ElmWPObj( weak_pointers_on_values, active[i] );
if value <> fail then
ref := ElmWPObj( weak_pointers, active[i] );
if ref <> fail then
if IsIdenticalObj( ref, obj ) then
cache_hit := true;
break;
fi;
i := i + 1;
else ## active[i] is no longer active
Remove( active, i );
l_active := l_active - 1;
fi;
else ## active[i] is no longer active
Remove( active, i );
l_active := l_active - 1;
fi;
od;
container!.active := active;
container!.deleted := Difference( [ 1 .. l ], active );
container!.accessed := container!.accessed + 1;
container!.cache_misses := container!.cache_misses + i - 1;
if cache_hit then
container!.cache_hits := container!.cache_hits + 1;
return value;
fi;
return FAIL;
end );
####################################
#
# View, Print, and Display methods:
#
####################################
##
InstallMethod( ViewObj,
"for weak pointer containers of objects",
[ IsContainerForWeakPointersOnObjectsRep ],
function( o )
local a;
UpdateContainerOfWeakPointers( o );
a := Length( o!.active );
Print( "<A container for weak pointers " );
if IsBound( o!.operation ) then
Print( "on computed values of ", o!.operation );
else
Print( "on objects" );
fi;
Print( ": active = ", a, ", deleted = ", o!.counter - a, ", counter = ", o!.counter, ", accessed = ", o!.accessed, ", cache_misses = ", o!.cache_misses, ", cache_hits = ", o!.cache_hits, ">" );
end );
##
InstallMethod( ViewObj,
"for weak pointer containers of containers",
[ IsContainerForWeakPointersOnContainersRep ],
function( o )
local a;
UpdateContainerOfWeakPointers( o );
a := Length( o!.active );
Print( "<A container for weak pointers on containers: active = ", a, ", deleted = ", o!.counter - a, ", counter = ", o!.counter, ">" );
end );
##
InstallMethod( Display,
"for weak pointer containers of objects",
[ IsContainerForWeakPointersOnObjectsRep ],
function( o )
local weak_pointers;
weak_pointers := o!.weak_pointers;
Print( List( [ 1 .. LengthWPObj( weak_pointers ) ], function( i ) if IsBoundElmWPObj( weak_pointers, i ) then return i; else return 0; fi; end ), "\n" );
end );
##
InstallMethod( Display,
"for weak pointer containers of containers",
[ IsContainerForWeakPointersOnContainersRep ],
function( o )
local weak_pointers, a, obj;
UpdateContainerOfWeakPointers( o );
weak_pointers := o!.weak_pointers;
for a in o!.active do
obj := ElmWPObj( weak_pointers, a );
if obj <> fail and
( not IsBound( obj!.counter ) or obj!.counter <> 0 ) then
Print( a, ":\t" );
ViewObj( obj );
Print( "\n" );
fi;
od;
end );
##
InstallMethod( Display,
"for weak pointer containers of containers",
[ IsContainerForWeakPointersOnContainersRep, IsString ],
function( o, string )
local weak_pointers, a, obj;
string := LowercaseString( string );
if string = "a" or string = "all" then
UpdateContainerOfWeakPointers( o );
weak_pointers := o!.weak_pointers;
for a in o!.active do
obj := ElmWPObj( weak_pointers, a );
if obj <> fail then
Print( a, ":\t" );
ViewObj( obj );
Print( "\n" );
fi;
od;
else
Display( o );
fi;
end );
####################################
#
# ContainerForPointers
#
####################################
# a new family:
BindGlobal( "TheFamilyOfContainersForPointers",
NewFamily( "TheFamilyOfContainersForPointers" ) );
# a new type:
BindGlobal( "TheTypeContainerForPointers",
NewType( TheFamilyOfContainersForPointers,
IsContainerForPointersRep ) );
# a new type:
BindGlobal( "TheTypeContainerForPointersOnObjects",
NewType( TheFamilyOfContainersForPointers,
IsContainerForPointersOnObjectsRep ) );
# a new type:
BindGlobal( "TheTypeContainerForPointersOnComputedValues",
NewType( TheFamilyOfContainersForPointers,
IsContainerForPointersOnComputedValuesRep ) );
# a new type:
BindGlobal( "TheTypeContainerForPointersOnContainers",
NewType( TheFamilyOfContainersForPointers,
IsContainerForPointersOnContainersRep ) );
##
InstallGlobalFunction( ContainerForPointers,
function( arg )
local nargs, container, component, type, containers;
nargs := Length( arg );
container := rec( pointers := [ ],
counter := 0,
accessed := 0,
cache_hits := 0,
cache_misses := 0 );
for component in arg{[ 2 .. nargs ]} do
container.( component[1] ) := component[2];
od;
type := arg[1];
## Objectify:
Objectify( type, container );
if IsBound( HOMALG_TOOLS.ContainersForPointers ) then
_AddElmPObj_ForHomalg( HOMALG_TOOLS.ContainersForPointers, container );
fi;
if IsContainerForPointersOnComputedValuesRep( container ) then
container!.pointers_on_values := [ ];
fi;
return container;
end );
HOMALG_TOOLS.ContainersForPointers := ContainerForPointers( TheTypeContainerForPointersOnContainers );
Unbind( HOMALG_TOOLS.ContainersForPointers!.accessed );
##
InstallGlobalFunction( _AddElmPObj_ForHomalg,
function( container, obj )
Add( container!.pointers, obj );
## here we increase container!.counter instead of container!.accessed;
container!.counter := container!.counter + 1;
end );
##
InstallGlobalFunction( _AddTwoElmPObj_ForHomalg,
function( container, ref, value )
Add( container!.pointers, ref );
Add( container!.pointers_on_values, value );
## here we increase container!.counter instead of container!.accessed;
container!.counter := container!.counter + 1;
end );
##
InstallMethod( _ElmPObj_ForHomalg,
"for a container of weak pointer lists and two objects (a reference and a return fail value)",
[ IsContainerForPointersOnComputedValuesRep, IsObject, IsObject ], 0,
function( container, obj, FAIL )
local pointers, pointers_on_values, l, cache_hit, i;
pointers := container!.pointers;
pointers_on_values := container!.pointers_on_values;
l := Length( pointers );
i := 1;
cache_hit := false;
while i <= l do
if IsIdenticalObj( pointers[ i ], obj ) then
cache_hit := true;
break;
fi;
i := i + 1;
od;
container!.accessed := container!.accessed + 1;
container!.cache_misses := container!.cache_misses + i - 1;
if cache_hit then
container!.cache_hits := container!.cache_hits + 1;
return pointers_on_values[ i ];
fi;
return FAIL;
end );
####################################
#
# View, Print, and Display methods:
#
####################################
##
InstallMethod( ViewObj,
"for pointer containers of objects",
[ IsContainerForPointersOnObjectsRep ],
function( o )
local a;
a := Length( o!.pointers );
Print( "<A container for pointers " );
if IsBound( o!.operation ) then
Print( "on computed values of ", o!.operation );
else
Print( "on objects" );
fi;
Print( ": active = ", a, ", counter = ", o!.counter, ", accessed = ", o!.accessed, ", cache_misses = ", o!.cache_misses, ", cache_hits = ", o!.cache_hits, ">" );
end );
##
InstallMethod( ViewObj,
"for pointer containers of containers",
[ IsContainerForPointersOnContainersRep ],
function( o )
local a;
a := Length( o!.pointers );
Print( "<A container for weak pointers on containers: active = ", a, ", counter = ", o!.counter, ">" );
end );
##
InstallMethod( Display,
"for pointer containers of objects",
[ IsContainerForPointersOnObjectsRep ],
function( o )
Print( o!.pointers, "\n" );
end );
##
InstallMethod( Display,
"for pointer containers of containers",
[ IsContainerForPointersOnContainersRep ],
function( o )
local a, pointers;
pointers := o!.pointers;
for a in [ 1 .. Length( pointers ) ] do
Print( a, ":\t" );
ViewObj( pointers[ a ] );
Print( "\n" );
od;
end );
##
InstallMethod( Display,
"for pointer containers of containers",
[ IsContainerForPointersOnContainersRep, IsString ],
function( o, string )
Display( o );
end );