diff --git a/doc/ref/blist.xml b/doc/ref/blist.xml index ef8f9bf66d..8aa3e31a99 100644 --- a/doc/ref/blist.xml +++ b/doc/ref/blist.xml @@ -57,7 +57,9 @@ In function names we call boolean lists blists for brevity. <#Include Label="UniteBlistList"> <#Include Label="IntersectBlist"> <#Include Label="SubtractBlist"> - +<#Include Label="FlipBlist"> +<#Include Label="SetAllBlist"> +<#Include Label="ClearAllBlist"> diff --git a/lib/list.g b/lib/list.g index f464cfaa00..be15d8b917 100644 --- a/lib/list.g +++ b/lib/list.g @@ -875,3 +875,108 @@ DeclareSynonym( "IntersectBlist", INTER_BLIST ); ## <#/GAPDoc> ## DeclareSynonym( "SubtractBlist", SUBTR_BLIST ); + +############################################################################# +## +#F FlipBlist( ) +## +## <#GAPDoc Label="FlipBlist"> +## +## +## +## +## Changes every entry in blist that equals true to false +## and vice versa. If blist1 and blist2 are boolean lists with +## equal length and every value in blist2 is true, +## then FlipBlist( blist1 ) is equivalent to +## SubtractBlist( blist2, blist1 ); blist1 := blist2; +## but FlipBlist is faster, and simpler to type. +##

+## returns nothing, it is only called to change +## blist in-place. +##

+## 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 ] +## ]]> +## +## +## <#/GAPDoc> +## +DeclareSynonym( "FlipBlist", FLIP_BLIST ); + +############################################################################# +## +#F ClearAllBlist( ) +## +## <#GAPDoc Label="ClearAllBlist"> +## +## +## +## +## Changes every entry in blist to false. +## If blist1 and blist2 are boolean lists with +## equal length and every value in blist2 is false, +## then ClearAllBlist( blist1 ) is equivalent to +## IntersectBlist( blist1, blist2 ); but is faster, and simpler to +## type. +##

+## returns nothing, it is only called to change +## blist in-place. +##

+## 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 ] +## ]]> +## +## +## <#/GAPDoc> +## +DeclareSynonym( "ClearAllBlist", CLEAR_ALL_BLIST ); + +############################################################################# +## +#F SetAllBlist( ) +## +## <#GAPDoc Label="SetAllBlist"> +## +## +## +## +## Changes every entry in blist to true. +## If blist1 and blist2 are boolean lists with +## equal length and every value in blist2 is true, +## then SetAllBlist( blist1 ) is equivalent to +## UniteBlist( blist1, blist2 ); but is faster, and simpler to +## type. +##

+## returns nothing, it is only called to change +## blist in-place. +##

+## 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 ] +## ]]> +## +## +## <#/GAPDoc> +## +DeclareSynonym( "SetAllBlist", SET_ALL_BLIST ); diff --git a/src/blister.c b/src/blister.c index 1af0c47300..83381f7d32 100644 --- a/src/blister.c +++ b/src/blister.c @@ -1577,6 +1577,102 @@ static Obj FuncMEET_BLIST(Obj self, Obj list1, Obj list2) return False; } +/**************************************************************************** +** +*F FuncFLIP_BLIST( , ) . . . +** +** 'FuncFLIP_BLIST' implements the internal function 'FlipBlist'. +** +** 'FlipBlist( )' +** +** 'FlipBlist' changes every value in the blist 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( , ) . . . +** +** 'FuncCLEAR_ALL_BLIST' implements the internal function 'ClearAllBlist'. +** +** 'ClearAllBlist( )' +** +** 'ClearAllBlist' changes every value in the blist 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( , ) . . . +** +** 'FuncSET_ALL_BLIST' implements the internal function 'SetAllBlist'. +** +** 'SetAllBlist( )' +** +** 'SetAllBlist' changes every value in the blist 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; +} /**************************************************************************** ** @@ -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 } diff --git a/tst/testinstall/kernel/blister.tst b/tst/testinstall/kernel/blister.tst index 43b5a25203..5dd1b7487b 100644 --- a/tst/testinstall/kernel/blister.tst +++ b/tst/testinstall/kernel/blister.tst @@ -209,5 +209,59 @@ true gap> MEET_BLIST(x, [true,false,false,false]); false +# FuncFLIP_BLIST +gap> FLIP_BLIST(fail); +Error, FlipBlist: 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: 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: 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);