anchor.diff:  	true = <<(Num band AndOp):8>> == bs_and(Bin,<<AndOp:8>>),
   	%% Or
   	OrOp = random:uniform(255),
  -	io:fwrite("| ~8s ~8.2B ||  ~8.2B  ||  ~8s  |~n",["Or",OrOp,Num bor OrOp,bs_to_string( bs_and(Bin,<<OrOp:8>>))]),
  +	io:fwrite("| ~8s ~8.2B ||  ~8.2B  ||  ~8s  |~n",["Or",OrOp,Num bor OrOp,bs_to_string( bs_or(Bin,<<OrOp:8>>))]),
   	true = <<(Num bor OrOp):8>> == bs_or(Bin,<<OrOp:8>>),
   	%% Xor	
   	XorOp = random:uniform(255),
  -	io:fwrite("| ~8s ~8.2B ||  ~8.2B  ||  ~8s  |~n",["Xor",XorOp,Num bxor XorOp,bs_to_string( bs_and(Bin,<<XorOp:8>>))]),
  -	true = <<(Num bxor XorOp):8>> == bs_and(Bin,<<XorOp:8>>),
  +	io:fwrite("| ~8s ~8.2B ||  ~8.2B  ||  ~8s  |~n",["Xor",XorOp,Num bxor XorOp,bs_to_string( bs_xor(Bin,<<XorOp:8>>))]),
  +	true = <<(Num bxor XorOp):8>> == bs_xor(Bin,<<XorOp:8>>),
   
   	ok.
   
  -bs_oper_bigbits_test(Bin) ->
  -	io:fwrite("Bin : ~w ~n", [Bin]),
  -	io:fwrite("TODO : find an set of binary operations that we can easily test having only the input value~n",[]).
  -
  -
  -
  -
  -
  +bs_oper_boolsimplif_test(<<A/bits>>,<<B/bits>>,<<C/bits>>) ->
  +	%Idempotent A
  +	io:fwrite("Idempotent Laws :~n",[]),
  +	io:fwrite("~12s ~s~n",["A = ",bs_to_string(A)]),
  +	io:fwrite("~12s ~s~n",["A & A",bs_to_string(bs_and(A,A))]), 
  +	true = bs_and(A,A) == A,
  +	io:fwrite("~12s ~s~n",["A | A",bs_to_string(bs_or(A,A))]), 
  +	true = bs_or(A,A) == A,
  +
  +	%Idempotent B
  +	io:fwrite("~12s ~s~n",["B = ",bs_to_string(B)]),
  +	io:fwrite("~12s ~s~n",["B & B",bs_to_string(bs_and(B,B))]), 
  +	true = bs_and(B,B) == B,
  +	io:fwrite("~12s ~s~n",["B | B",bs_to_string(bs_or(B,B))]), 
  +	true = bs_or(B,B) == B,
  +
  +	%Idempotent C
  +	io:fwrite("~12s ~s~n",["C = ",bs_to_string(C)]),
  +	io:fwrite("~12s ~s~n",["C & C",bs_to_string(bs_and(C,C))]), 
  +	true = bs_and(C,C) == C,
  +	io:fwrite("~12s ~s~n",["C | C",bs_to_string(bs_or(C,C))]), 
  +	true = bs_or(C,C) == C,
  +
  +	%Associativity
  +	io:fwrite("Associative Laws :~n",[]),
  +	io:fwrite("~12s ~s~n",["(A&B)&C",bs_to_string(bs_and(bs_and(A,B),C))]),
  +	io:fwrite("~12s ~s~n",["A&(B&C)",bs_to_string(bs_and(A,bs_and(B,C)))]), 
  +	true = bs_and(bs_and(A,B),C) == bs_and(A,bs_and(B,C)),
  +	io:fwrite("~12s ~s~n",["(A|B)|C",bs_to_string(bs_or(bs_or(A,B),C))]),
  +	io:fwrite("~12s ~s~n",["A|(B|C)",bs_to_string(bs_or(A,bs_or(B,C)))]), 
  +	true = bs_or(bs_or(A,B),C) == bs_or(A,bs_or(B,C)),
  +	
  +	%Commutativity
  +	io:fwrite("Commutative Laws :~n",[]),
  +	io:fwrite("~12s ~s~n",[" A & B ",bs_to_string(bs_and(A,B))]),
  +	io:fwrite("~12s ~s~n",[" B & A ",bs_to_string(bs_and(B,A))]),
  +	true = bs_and(A,B) == bs_and(B,A),
  +	io:fwrite("~12s ~s~n",[" A | B ",bs_to_string(bs_or(A,B))]),
  +	io:fwrite("~12s ~s~n",[" B | A ",bs_to_string(bs_or(B,A))]),
  +	true = bs_or(A,B) == bs_or(B,A),
  +
  +
  +	%Distributivity
  +	io:fwrite("Distributive Laws :~n",[]),
  +	io:fwrite("~12s ~s~n",["A&(B|C)",bs_to_string(bs_and(A,bs_or(B,C)))]),
  +	io:fwrite("~12s ~s~n",["(A&B)|(A&C)",bs_to_string(bs_or(bs_and(A,B),bs_and(A,C)))]),
  +	true = bs_and(A,bs_or(B,C)) == bs_or(bs_and(A,B),bs_and(A,C)),
  +	io:fwrite("~12s ~s~n",["A|(B&C)",bs_to_string(bs_or(A,bs_and(B,C)))]),
  +	io:fwrite("~12s ~s~n",["(A|B)&(A|C)",bs_to_string(bs_and(bs_or(A,B),bs_or(A,C)))]),
  +	true = bs_or(A,bs_and(B,C)) == bs_and(bs_or(A,B),bs_or(A,C)),
  +	
  +	%Identity A
  +	io:fwrite("Identity Laws :~n",[]),
  +	io:fwrite("~12s ~s~n",["A = ",bs_to_string(A)]),
  +	io:fwrite("~12s ~s~n",["A & 1",bs_to_string(bs_and(A,bs_true(bit_size(A))))]),
  +	true = bs_and(A,bs_true(bit_size(A))) == A,
  +	io:fwrite("~12s ~s~n",["A | 0",bs_to_string(bs_or(A,bs_false(bit_size(A))))]),
  +	true = bs_or(A,bs_false(bit_size(A))) == A,
  +	io:fwrite("~12s ~s~n",["A | 1 = 1",bs_to_string(bs_or(A,bs_true(bit_size(A))))]),
  +	true = bs_or(A,bs_true(bit_size(A))) == bs_true(bit_size(A)),
  +	io:fwrite("~12s ~s~n",["A & 0 = 0",bs_to_string(bs_and(A,bs_false(bit_size(A))))]),
  +	true = bs_and(A,bs_false(bit_size(A))) == bs_false(bit_size(A)),
  +		
  +	%Complement Laws
  +	io:fwrite("Complement Laws :~n",[]),
  +	io:fwrite("~12s ~s~n",["A&-A=0",bs_to_string(bs_and(A,bs_not(A)))]),
  +	true = bs_and(A,bs_not(A)) == bs_false(bit_size(A)),
  +	io:fwrite("~12s ~s~n",["A|-A=1",bs_to_string(bs_or(A,bs_not(A)))]),
  +	true = bs_or(A,bs_not(A)) == bs_true(bit_size(A)),
  +	io:fwrite("~12s ~s~n",["-0 = 1", bs_to_string(bs_not(bs_false(bit_size(A))))]),
  +	true = bs_not(bs_false(bit_size(A))) == bs_true(bit_size(A)),
  +	io:fwrite("~12s ~s~n",["-1 = 0", bs_to_string(bs_not(bs_true(bit_size(A))))]),
  +	true = bs_not(bs_true(bit_size(A))) == bs_false(bit_size(A)),
  +
  +	%Involution
  +	io:fwrite("Involution Law :~n",[]),
  +	io:fwrite("~12s ~s~n",["-(-A) = A",bs_to_string(bs_not(bs_not(A)))]),
  +	true = bs_not(bs_not(A)) == A,
  +
  +	%De Morgan's Law
  +	io:fwrite("De Morgan's Law :~n",[]),
  +	io:fwrite("~12s ~s~n",["-(A&B)",bs_to_string(bs_not(bs_and(A,B)))]),
  +	io:fwrite("~12s ~s~n",["-A|-B",bs_to_string(bs_or(bs_not(A),bs_not(B)))]),
  +	true = bs_not(bs_and(A,B)) == bs_or(bs_not(A),bs_not(B)),
  +	io:fwrite("~12s ~s~n",["-(A|B)",bs_to_string(bs_not(bs_or(A,B)))]),
  +	io:fwrite("~12s ~s~n",["-A&-B",bs_to_string(bs_and(bs_not(A),bs_not(B)))]),
  +	true = bs_not(bs_or(A,B)) == bs_and(bs_not(A),bs_not(B)),
  +	
  +
  +
  +% Heavy simplification exercize
  +%#  Simplify: C + BC:
  +%Expression 	Rule(s) Used
  +%C + BC 	Original Expression
  +%C + (B + C) 	DeMorgan's Law.
  +%(C + C) + B 	Commutative, Associative Laws.
  +%T + B 	Complement Law.
  +%T 	Identity Law.
  +
  +%# Simplify: AB(A + B)(B + B):
  +%Expression 	Rule(s) Used
  +%AB(A + B)(B + B) 	Original Expression
  +%AB(A + B) 	Complement law, Identity law.
  +%(A + B)(A + B) 	DeMorgan's Law
  +%A + BB 	Distributive law. This step uses the fact that or distributes over and. It can look a bit strange since addition does not distribute over multiplication.
  +%A 	Complement, Identity.
  +
  +%# Simplify: (A + C)(AD + AD) + AC + C:
  +%Expression 	Rule(s) Used
  +%(A + C)(AD + AD) + AC + C 	Original Expression
  +%(A + C)A(D + D) + AC + C 	Distributive.
  +%(A + C)A + AC + C 	Complement, Identity.
  +%A((A + C) + C) + C 	Commutative, Distributive.
  +%A(A + C) + C 	Associative, Idempotent.
  +%AA + AC + C 	Distributive.
  +%A + (A + T)C 	Idempotent, Identity, Distributive.
  +%A + C 	Identity, twice.
  +%You can also use distribution of or over and starting from A(A+C)+C to reach the same result by another route.
  +
  +%# Simplify: A(A + B) + (B + AA)(A + B):
  +%Expression 	Rule(s) Used
  +%A(A + B) + (B + AA)(A + B) 	Original Expression
  +%AA + AB + (B + A)A + (B + A)B 	Idempotent (AA to A), then Distributive, used twice.
  +%AB + (B + A)A + (B + A)B 	Complement, then Identity. (Strictly speaking, we also used the Commutative Law for each of these applications.)
  +%AB + BA + AA + BB + AB 	Distributive, two places.
  +%AB + BA + A + AB 	Idempotent (for the A's), then Complement and Identity to remove BB.
  +%AB + AB + AT + AB 	Commutative, Identity; setting up for the next step.
  +%AB + A(B + T + B) 	Distributive.
  +%AB + A 	Identity, twice (depending how you count it).
  +%A + AB 	Commutative.
  +%(A + A)(A + B) 	Distributive.
  +%A + B 	Complement, Identity. 
  +%
  +	ok.
  +
  +
  +
  +
  
positive.code: 
  
  % bitshift right
  bs_sr(<<I:1/bits,B/bits>>,N) when N < (bit_size(B)+1) -> <<(bs_sr(B,N))/bits,I:1/bits>>;
  bs_sr(<<B/bits>>,N) when N >= (bit_size(B)) -> <<0:(bit_size(B))>>;
  
  bs_sr(<<B/bits>>,N) when N < 0 -> bs_sl(<<B/bits>>, -1 * N).
  
  
  
negative.code: bs_reverse(<<I:1,B/bits>> ) -> << ( bs_reverse(B))/bits,I:1 >>;
  bs_reverse(<<>>) -> <<>>.
  
  %TODO :improve performance and code design... same with bitwise comprehension if possible ? or more arithmetic ?
  % unary bitwise not
  bs_not(<<I:1/bits,B/bits>>) when I == <<0:1>> -> <<1:1,(bs_not(B))/bits >>;
  bs_not(<<I:1/bits,B/bits>>) when I == <<1:1>> -> <<0:1,(bs_not(B))/bits >>;
  