Skip to content

Commit

Permalink
Change QuaternionAlgebra to use GET_FROM_SORTED_CACHE
Browse files Browse the repository at this point in the history
Also ensure that the exact same code is used to produce the
resulting algebra regardless of whether it is created freshly
or from the cache. This revealed a bug: `A.1` only worked
in the former case, not the latter, which could lead to subtly
broken code. Before this patch, the following happened:

    gap> A:= QuaternionAlgebra( [1], 2, 5 );
    <algebra-with-one of dimension 4 over Rationals>
    gap> A.1;
    e
    gap> B:= QuaternionAlgebra( [1], 2, 5 );
    <algebra-with-one of dimension 4 over Rationals>
    gap> B.1;
    Error, illegal access to record component `obj.1'

This is now fixed.

Resolves #2940
  • Loading branch information
fingolfin committed Apr 21, 2021
1 parent 68a8859 commit 85b5584
Showing 1 changed file with 8 additions and 36 deletions.
44 changes: 8 additions & 36 deletions lib/algsc.gi
Original file line number Diff line number Diff line change
Expand Up @@ -689,26 +689,9 @@ InstallAccessToGenerators( IsSCAlgebraObjCollection and IsFullSCAlgebra,
##
#V QuaternionAlgebraData
##
InstallFlushableValue( QuaternionAlgebraData, [] );
InstallFlushableValue( QuaternionAlgebraData, [ [], [] ] );
if IsHPCGAP then
ShareSpecialObj( QuaternionAlgebraData );

BindGlobal("StoreQuaternionAlgebraData", function( a, b, F, A )
local stored;
atomic readwrite QuaternionAlgebraData do
stored:= First( QuaternionAlgebraData,
t -> t[1] = a and t[2] = b and
IsIdenticalObj( t[3], FamilyObj( F ) ) );
if stored = fail then
# Store the data for the next call.
Add( QuaternionAlgebraData, MakeImmutable([ a, b, FamilyObj( F ), A ]) );
else
A:= AlgebraWithOne( F, GeneratorsOfAlgebra( stored[4] ), "basis" );
SetGeneratorsOfAlgebra( A, GeneratorsOfAlgebraWithOne( A ) );
fi;
od;
return A;
end);
fi;


Expand Down Expand Up @@ -744,16 +727,8 @@ InstallGlobalFunction( QuaternionAlgebra, function( arg )
fi;

# Generators in the right family may be already available.
atomic readonly QuaternionAlgebraData do
stored:= First( QuaternionAlgebraData,
t -> t[1] = a and t[2] = b
and IsIdenticalObj( t[3], FamilyObj( F ) ) );
od;
if stored <> fail then
A:= AlgebraWithOne( F, GeneratorsOfAlgebra( stored[4] ), "basis" );
SetGeneratorsOfAlgebra( A, GeneratorsOfAlgebraWithOne( A ) );
else

stored := GET_FROM_SORTED_CACHE( QuaternionAlgebraData, [ a, b, FamilyObj( F ) ],
function()
# Construct a filter describing element properties,
# which will be stored in the family.
filter:= IsSCAlgebraObj and IsQuaternion;
Expand All @@ -780,15 +755,12 @@ InstallGlobalFunction( QuaternionAlgebra, function( arg )
filter );
SetFilterObj( A, IsAlgebraWithOne );
#T better introduce AlgebraWithOneByStructureConstants?
return A;
end );

# Store the data for the next call.
if IsHPCGAP then
A := StoreQuaternionAlgebraData( a, b, F, A );
else
Add( QuaternionAlgebraData, [ a, b, FamilyObj( F ), A ] );
fi;

fi;
A:= AlgebraWithOne( F, GeneratorsOfAlgebra( stored ), "basis" );
SetGeneratorsOfAlgebra( A, GeneratorsOfAlgebraWithOne( A ) );
SetIsFullSCAlgebra( A, true );

# A quaternion algebra with negative parameters over a real field
# is a division ring.
Expand Down

0 comments on commit 85b5584

Please sign in to comment.