Skip to content

Commit

Permalink
Add Flip/Set/ClearAllBitsBlist
Browse files Browse the repository at this point in the history
  • Loading branch information
james-d-mitchell authored and wilfwilson committed Apr 9, 2019
1 parent 3d6f4d7 commit 27c845b
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 1 deletion.
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 );

#############################################################################
##
#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);
> 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);

0 comments on commit 27c845b

Please sign in to comment.