% -----------------------------------------------------------------------------
%  (C) Altran Praxis Limited
% -----------------------------------------------------------------------------
% 
%  The SPARK toolset is free software; you can redistribute it and/or modify it
%  under terms of the GNU General Public License as published by the Free
%  Software Foundation; either version 3, or (at your option) any later
%  version. The SPARK toolset is distributed in the hope that it will be
%  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
%  Public License for more details. You should have received a copy of the GNU
%  General Public License distributed with the SPARK toolset; see file
%  COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
%  the license.
% 
% =============================================================================


%-------------------------------------------------------------------------------
% RULE FAMILIES CONTAINED HEREIN :-
% bitwise : bitwise logical operators for SPARK Modular Types
%-------------------------------------------------------------------------------
% MODEL DECLARATIONS FOR THIS FILE :-
%
% rule_family bitwise:
%      bit__and(I,J) requires [I : i, J : i] &
%      bit__or(I,J)  requires [I : i, J : i] &
%      bit__xor(I,J) requires [I : i, J : i] &
%      bit__and(I,J) = K requires [I : i, J : i, K : i] &
%      bit__or(I,J)  = K requires [I : i, J : i, K : i] &
%      bit__xor(I,J) = K requires [I : i, J : i, K : i] &
%      I < J         requires [I : i, J : i] &
%      I <= J        requires [I : i, J : i] &
%      I = J         requires [I : i, J : i].
%-------------------------------------------------------------------------------


/*** Simplification of bitwise operators ***/
bitwise(1):      bit__and(X,X)         may_be_replaced_by X if [ 0 <= X ].
bitwise(2):      bit__or(X,X)          may_be_replaced_by X if [ 0 <= X ].
bitwise(3):      bit__xor(X,X)         may_be_replaced_by 0 if [ 0 <= X ].
bitwise(4):      bit__and(X, 2**N - 1) may_be_replaced_by X if [ 0 <= X, 0 <= N, X <= 2**N - 1 ].

/*** Properties of zero ***/
bitwise(11):     bit__and(X,0)        may_be_replaced_by    0    if [ 0 <= X ].
bitwise(12):     bit__or(X,0)         may_be_replaced_by    X    if [ 0 <= X ].
bitwise(13):     bit__xor(X,0)        may_be_replaced_by    X    if [ 0 <= X ].

/*** Commutativity ***/
bitwise(21):     bit__and(X,Y)        may_be_replaced_by
                                           bit__and(Y,X) if [ 0 <= X, 0 <= Y ].
bitwise(22):     bit__or(X,Y)         may_be_replaced_by
                                           bit__or(Y,X)  if [ 0 <= X, 0 <= Y ].
bitwise(23):     bit__xor(X,Y)        may_be_replaced_by
                                           bit__xor(Y,X) if [ 0 <= X, 0 <= Y ].

/*** Associativity ***/
bitwise(31):     bit__and(bit__and(X,Y), Z) may_be_replaced_by
                              bit__and(bit__and(X,Z), Y) if [ 0 <= X, 0 <= Y ].
bitwise(32):     bit__or(bit__or(X,Y), Z)   may_be_replaced_by
                              bit__or(bit__or(X,Z), Y)   if [ 0 <= X, 0 <= Y ].
bitwise(33):     bit__xor(bit__xor(X,Y), Z) may_be_replaced_by
                              bit__xor(bit__xor(X,Z), Y) if [ 0 <= X, 0 <= Y ].

/*** Distributivity of bit__and and bit__or (bit__xor requires negation)***/
bitwise(41):    bit__or(bit__and(X,Y), Z) & bit__and(bit__or(X,Z), bit__or(Y,Z))
                             are_interchangeable if [ 0 <= X, 0 <= Y, 0 <= Z ].
bitwise(42):    bit__and(bit__or(X,Y), Z) & bit__or(bit__and(X,Z), bit__and(Y,Z))
                             are_interchangeable if [ 0 <= X, 0 <= Y, 0 <= Z ].

/*** Lower bounds ***/
bitwise(51):    0 <= bit__and(X,Y)    may_be_deduced_from    [ 0 <= X, 0 <= Y ].
bitwise(52):    0 <= bit__or(X,Y)     may_be_deduced_from    [ 0 <= X, 0 <= Y ].
bitwise(53):    0 <= bit__xor(X,Y)    may_be_deduced_from    [ 0 <= X, 0 <= Y ].
bitwise(54):    X <= bit__or(X,Y)     may_be_deduced_from    [ 0 <= X, 0 <= Y ].
bitwise(55):    Y <= bit__or(X,Y)     may_be_deduced_from    [ 0 <= X, 0 <= Y ].
bitwise(56):    X - Y <= bit__xor(X, Y) may_be_deduced_from    [ 0 <= X, 0 <= Y ].
bitwise(57):    Y - X <= bit__xor(X, Y) may_be_deduced_from    [ 0 <= X, 0 <= Y ].

/*** Upper bounds ***/
bitwise(61):  bit__and(X,Y) <= X         may_be_deduced_from [ 0 <= X, 0 <= Y ].
bitwise(62):  bit__and(X,Y) <= Y         may_be_deduced_from [ 0 <= X, 0 <= Y ].
bitwise(63):  bit__or(X,Y)  <= X + Y     may_be_deduced_from [ 0 <= X, 0 <= Y ].
bitwise(64):  bit__xor(X,Y) <= X + Y     may_be_deduced_from [ 0 <= X, 0 <= Y ].
bitwise(65):  bit__and(X,Y) <= Z         may_be_deduced_from [ 0 <= X, 0 <= Y, X <= Z or Y <= Z ].
bitwise(66):  bit__or(X,Y)  <= 2**N - 1  may_be_deduced_from [ 0 <= X, 0 <= Y, 0 <= N,
                                                  X <= 2**N - 1, Y <= 2**N - 1].
bitwise(67):  bit__xor(X,Y) <= 2**N - 1  may_be_deduced_from [ 0 <= X, 0 <= Y, 0 <= N,
                                                  X <= 2**N - 1, Y <= 2**N - 1].

/*** Values ***/
bitwise(72):      bit__or(X,Y)  may_be_replaced_by X + Y - bit__and(X,Y)
                                                          if [ 0 <= X, 0 <= Y ].
bitwise(73):      bit__xor(X,Y) may_be_replaced_by X + Y - 2 * bit__and(X,Y)
                                                          if [ 0 <= X, 0 <= Y ].

/*** Comparison ***/
bitwise(81):     bit__and(X,Y) <= bit__or(X,Y) may_be_deduced_from
                                                      [ 0 <= X, 0 <= Y].
bitwise(82):     bit__xor(X,Y) <= bit__or(X,Y) may_be_deduced_from
                                                      [ 0 <= X, 0 <= Y].

/*** Combination of X with ~X ***/
bitwise(91):     bit__and(X, 2**N - X - 1) = 0        may_be_deduced_from
                                                      [ 0 <= X, 0 <= N, X <= 2**N - 1 ].
bitwise(92):     bit__or(X, 2**N - X - 1) = 2**N - 1  may_be_deduced_from
                                                      [ 0 <= X, 0 <= N, X <= 2**N - 1 ].
bitwise(93):     bit__xor(X, 2**N - X - 1) = 2**N - 1 may_be_deduced_from
                                                      [ 0 <= X, 0 <= N, X <= 2**N - 1 ].

/*** Maximum value argument ***/
bitwise(101):     bit__and(X, 2**N - 1) <= X            may_be_deduced_from
                                                      [ 0 <= X, 0 <= N, X <= 2**N - 1 ].
bitwise(102):     bit__or(X, 2**N - 1)  = 2**N - 1     may_be_deduced_from
                                                      [ 0 <= X, 0 <= N, X <= 2**N - 1 ].
bitwise(103):     bit__xor(X, 2**N - 1) = 2**N - X - 1 may_be_deduced_from
                                                      [ 0 <= X, 0 <= N, X <= 2**N - 1 ].
/*** Definition of bit__and ***/
bitwise(111):     bit__and(X, Y) may_be_replaced_by 2 * bit__and(X div 2, Y div 2) +
                                                    (X mod 2) * (Y mod 2) if [0 <= X, 0 <= Y].
