Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Flip/SetAll/ClearAllBlist #3385

Merged
merged 1 commit into from
Apr 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion doc/ref/blist.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ In function names we call boolean lists <E>blists</E> for brevity.
<#Include Label="UniteBlistList">
<#Include Label="IntersectBlist">
<#Include Label="SubtractBlist">

<#Include Label="FlipBlist">
<#Include Label="SetAllBlist">
<#Include Label="ClearAllBlist">
</Section>


Expand Down
105 changes: 105 additions & 0 deletions lib/list.g
Original file line number Diff line number Diff line change
Expand Up @@ -875,3 +875,108 @@ DeclareSynonym( "IntersectBlist", INTER_BLIST );
## <#/GAPDoc>
##
DeclareSynonym( "SubtractBlist", SUBTR_BLIST );

#############################################################################
##
#F FlipBlist( <blist> )
##
## <#GAPDoc Label="FlipBlist">
## <ManSection>
## <Func Name="FlipBlist" Arg='blist'/>
##
## <Description>
## Changes every entry in <A>blist</A> that equals <K>true</K> to <K>false</K>
## and vice versa. If <C>blist1</C> and <C>blist2</C> are boolean lists with
## equal length and every value in <C>blist2</C> is <K>true</K>,
## then <C>FlipBlist( blist1 )</C> is equivalent to
## <C>SubtractBlist( blist2, blist1 ); blist1 := blist2;</C>
## but <C>FlipBlist</C> is faster, and simpler to type.
## <P/>
## <Ref Func="FlipBlist"/> returns nothing, it is only called to change
## <A>blist</A> in-place.
## <P/>
## <Example><![CDATA[
## gap> blist1 := [ true, true, true, true ];;
## gap> blist2 := [ true, false, true, false ];;
## gap> SubtractBlist( blist1, blist2 );
## gap> blist1;
## [ false, true, false, true ]
## gap> FlipBlist( blist2 );
## gap> blist2;
## [ false, true, false, true ]
## ]]></Example>
## </Description>
## </ManSection>
## <#/GAPDoc>
##
DeclareSynonym( "FlipBlist", FLIP_BLIST );

#############################################################################
##
#F ClearAllBlist( <blist> )
##
## <#GAPDoc Label="ClearAllBlist">
## <ManSection>
## <Func Name="ClearAllBlist" Arg='blist'/>
##
## <Description>
## Changes every entry in <A>blist</A> to <K>false</K>.
## If <C>blist1</C> and <C>blist2</C> are boolean lists with
## equal length and every value in <C>blist2</C> is <K>false</K>,
## then <C>ClearAllBlist( blist1 )</C> is equivalent to
## <C>IntersectBlist( blist1, blist2 );</C> but is faster, and simpler to
## type.
## <P/>
## <Ref Func="ClearAllBlist"/> returns nothing, it is only called to change
## <A>blist</A> in-place.
## <P/>
## <Example><![CDATA[
## gap> blist1 := [ true, true, true, true ];;
## gap> blist2 := [ true, false, true, false ];;
## gap> ClearAllBlist( blist1 );
## gap> blist1;
## [ false, false, false, false ]
## gap> ClearAllBlist(blist2);
## gap> blist2;
## [ false, false, false, false ]
## ]]></Example>
## </Description>
## </ManSection>
## <#/GAPDoc>
##
DeclareSynonym( "ClearAllBlist", CLEAR_ALL_BLIST );

#############################################################################
fingolfin marked this conversation as resolved.
Show resolved Hide resolved
##
#F SetAllBlist( <blist> )
##
## <#GAPDoc Label="SetAllBlist">
## <ManSection>
## <Func Name="SetAllBlist" Arg='blist'/>
##
## <Description>
## Changes every entry in <A>blist</A> to <K>true</K>.
## If <C>blist1</C> and <C>blist2</C> are boolean lists with
## equal length and every value in <C>blist2</C> is <K>true</K>,
## then <C>SetAllBlist( blist1 )</C> is equivalent to
## <C>UniteBlist( blist1, blist2 );</C> but is faster, and simpler to
## type.
## <P/>
## <Ref Func="SetAllBlist"/> returns nothing, it is only called to change
## <A>blist</A> in-place.
## <P/>
## <Example><![CDATA[
## gap> blist1 := [ true, true, true, true ];;
## gap> blist2 := [ true, false, true, false ];;
## gap> SetAllBlist( blist1 );
## gap> blist1;
## [ true, true, true, true ]
## gap> SetAllBlist(blist2);
## gap> blist2;
## [ true, true, true, true ]
## ]]></Example>
## </Description>
## </ManSection>
## <#/GAPDoc>
##
DeclareSynonym( "SetAllBlist", SET_ALL_BLIST );
99 changes: 99 additions & 0 deletions src/blister.c
Original file line number Diff line number Diff line change
Expand Up @@ -1577,6 +1577,102 @@ static Obj FuncMEET_BLIST(Obj self, Obj list1, Obj list2)
return False;
}

/****************************************************************************
**
*F FuncFLIP_BLIST( <self>, <list> ) . . .
**
** 'FuncFLIP_BLIST' implements the internal function 'FlipBlist'.
**
** 'FlipBlist( <list> )'
**
** 'FlipBlist' changes every value in the blist <list> from true to false, and
** vice versa.
*/

static Obj FuncFLIP_BLIST(Obj self, Obj list)
{
// get and check the arguments
RequireBlist("FlipBlist", list, "blist");

if (LEN_BLIST(list) == 0) {
return 0;
}

UInt * ptr = BLOCKS_BLIST(list);
for (UInt i = NUMBER_BLOCKS_BLIST(list); 0 < i; i--) {
*ptr = ~(*ptr);
ptr++;
}
// If the logical length of the boolean list is not a multiple of BIPEB the
// last block will contain unused bits, which are then zero.
UInt mask =
~(UInt)0 >> ((BIPEB * NUMBER_BLOCKS_BLIST(list)) - LEN_BLIST(list));
ptr = BLOCK_ELM_BLIST_PTR(list, LEN_BLIST(list));
*ptr &= mask;
return 0;
}

/****************************************************************************
**
*F FuncCLEAR_ALL_BLIST( <self>, <list> ) . . .
**
** 'FuncCLEAR_ALL_BLIST' implements the internal function 'ClearAllBlist'.
**
** 'ClearAllBlist( <list> )'
**
** 'ClearAllBlist' changes every value in the blist <list> to false.
*/

static Obj FuncCLEAR_ALL_BLIST(Obj self, Obj list)
{
// get and check the arguments
RequireBlist("ClearAllBitsBlist", list, "blist");

if (LEN_BLIST(list) == 0) {
return 0;
}

UInt * ptr = BLOCKS_BLIST(list);
for (UInt i = NUMBER_BLOCKS_BLIST(list); 0 < i; i--) {
*ptr++ = 0;
}

return 0;
}

/****************************************************************************
**
*F FuncSET_ALL_BLIST( <self>, <list> ) . . .
**
** 'FuncSET_ALL_BLIST' implements the internal function 'SetAllBlist'.
**
** 'SetAllBlist( <list> )'
**
** 'SetAllBlist' changes every value in the blist <list> to true.
*/

static Obj FuncSET_ALL_BLIST(Obj self, Obj list)
{
// get and check the arguments
RequireBlist("SetAllBitsBlist", list, "blist");

if (LEN_BLIST(list) == 0) {
return 0;
}

UInt * ptr = BLOCKS_BLIST(list);
for (UInt i = NUMBER_BLOCKS_BLIST(list); 0 < i; i--) {
*ptr++ = ~(UInt)0;
}
// If the logical length of the boolean list is not a multiple of BIPEB the
// last block will contain unused bits, which are then zero.
UInt mask =
~(UInt)0 >> ((BIPEB * NUMBER_BLOCKS_BLIST(list)) - LEN_BLIST(list));
ptr = BLOCK_ELM_BLIST_PTR(list, LEN_BLIST(list));
*ptr &= mask;

return 0;
}

/****************************************************************************
**
Expand Down Expand Up @@ -1765,6 +1861,9 @@ static StructGVarFunc GVarFuncs [] = {
GVAR_FUNC(INTER_BLIST, 2, "blist1, blist2"),
GVAR_FUNC(SUBTR_BLIST, 2, "blist1, blist2"),
GVAR_FUNC(MEET_BLIST, 2, "blist1, blist2"),
GVAR_FUNC(FLIP_BLIST, 1, "blist"),
GVAR_FUNC(CLEAR_ALL_BLIST, 1, "blist"),
GVAR_FUNC(SET_ALL_BLIST, 1, "blist"),
GVAR_FUNC(PositionNthTrueBlist, 2, "blist, nth"),
{ 0, 0, 0, 0, 0 }

Expand Down
54 changes: 54 additions & 0 deletions tst/testinstall/kernel/blister.tst
Original file line number Diff line number Diff line change
Expand Up @@ -209,5 +209,59 @@ true
gap> MEET_BLIST(x, [true,false,false,false]);
false

# FuncFLIP_BLIST
gap> FLIP_BLIST(fail);
Error, FlipBlist: <blist> must be a boolean list (not the value 'fail')
gap> x:= [false,true,true,false];;
gap> FLIP_BLIST(x);
gap> x;
[ true, false, false, true ]
gap> FLIP_BLIST(x);
gap> x;
[ false, true, true, false ]
gap> for i in [0..200] do
> f1 := List([1..i], x -> false);
> f2 := List([1..i], x -> false);
> t1 := List([1..i], x -> true);
> t2 := List([1..i], x -> true);
fingolfin marked this conversation as resolved.
Show resolved Hide resolved
> FLIP_BLIST(f1); FLIP_BLIST(t1);
> if f1 <> t2 or t1 <> f2 then Print("Broken FLIP_BLIST", i, "\n"); fi;
> od;

# FuncSET_ALL_BLIST
gap> SET_ALL_BLIST(fail);
Error, SetAllBitsBlist: <blist> must be a boolean list (not the value 'fail')
gap> x:= [false,true,true,false];;
gap> SET_ALL_BLIST(x);
gap> x;
[ true, true, true, true ]
gap> SET_ALL_BLIST(x);
gap> x;
[ true, true, true, true ]
gap> for i in [0..200] do
> f1 := List([1..i], x -> false);
> t1 := List([1..i], x -> true);
> SET_ALL_BLIST(f1);
> if f1 <> t1 then Print("Broken SET_ALL_BLIST\n"); fi;
> od;

# FuncCLEAR_ALL_BLIST
gap> CLEAR_ALL_BLIST(fail);
Error, ClearAllBitsBlist: <blist> must be a boolean list (not the value 'fail'\
)
gap> x:= [false,true,true,false];;
gap> CLEAR_ALL_BLIST(x);
gap> x;
[ false, false, false, false ]
gap> CLEAR_ALL_BLIST(x);
gap> x;
[ false, false, false, false ]
gap> for i in [0..200] do
> f1 := List([1..i], x -> false);
> t1 := List([1..i], x -> true);
> CLEAR_ALL_BLIST(t1);
> if f1 <> t1 then Print("Broken CLEAR_ALL_BLIST\n"); fi;
> od;

#
gap> STOP_TEST("kernel/blister.tst", 1);