% -----------------------------------------------------------------------------
%  (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 :-
%
% abs          : properties of the absolute value function abs(_)
% sqr          : properties of the square function sqr(_)
% odd          : properties of predicate odd(_)
% exp          : properties of the exponentiation operator **
%-------------------------------------------------------------------------------
% MODEL DECLARATIONS FOR THIS FILE :-
%
% rule_family abs:
%         abs(X) requires [ X:ir         ] &
%         X >= Y requires [ X:ir,  Y:ir  ] &
%         X > Y  requires [ X:ir,  Y:ir  ] &
%         X or Y requires [ X:any, Y:any ] &
%         X * Y  requires [ X:ir,  Y:ir  ].
%
% rule_family sqr:
%         sqr(X) requires [ X:ir       ] &
%         X >= Y requires [ X:ir, Y:ir ] &
%         X > Y  requires [ X:ir, Y:ir ] &
%         X * Y  requires [ X:ir, Y:ir ] &
%         abs(X) requires [ X:ir       ].
%
% rule_family odd:
%         odd(X) requires [ X:i        ] &
%         not X  requires [ X:any      ] &
%         X <> Y requires [ X:i,   Y:i ] &
%         X = Y  requires [ X:i,   Y:i ].
%
% rule_family exp:
%         X ** Y requires [ X:ir, Y:i  ] &
%         X * Y  requires [ X:ir, Y:ir ] &
%         X >= Y requires [ X:ir, Y:ir ] &
%         X <= Y requires [ X:ir, Y:ir ] &
%         X > Y  requires [ X:ir, Y:ir ] &
%         X < Y  requires [ X:ir, Y:ir ].
%-------------------------------------------------------------------------------


/*** ABS:  absolute value function properties ***/

abs(1): abs(X)      may_be_replaced_by X if [ X>=0 ].
abs(2): abs(X)      may_be_replaced_by -X if [ X<=0 ].
abs(3): abs(X)>=0   may_be_deduced.
abs(4): abs(X)>0    may_be_deduced_from [ X<>0 ].
abs(5): abs(X)=X or abs(X)=(-X) may_be_deduced.
abs(6): abs(abs(X)) may_be_replaced_by abs(X).
abs(7): abs(X*Y) & abs(X)*abs(Y) are_interchangeable.


/*** SQR:  square function properties ***/

sqr(1): sqr(X)      may_be_replaced_by X*X.
sqr(2): sqr(X)>=0   may_be_deduced.
sqr(3): sqr(X)>0    may_be_deduced_from [ X<>0 ].
sqr(4): sqr(X*Y) & sqr(X)*sqr(Y) are_interchangeable.
sqr(5): abs(sqr(X)) may_be_replaced_by sqr(X).
sqr(6): sqr(abs(X)) may_be_replaced_by sqr(X).


/*** ODD:  odd function properties ***/

odd(1): odd(X)     & (X div 2) * 2 <> X are_interchangeable.
odd(2): not odd(X) & (X div 2) * 2 =  X are_interchangeable.

odd(3): odd(X)           may_be_deduced_from [ X=2*K+1 ].
odd(4): not odd(X)       may_be_deduced_from [ X=2*K ].

odd(5): odd(X)           may_be_deduced_from [ odd(-X) ].
odd(6): odd(-X)          may_be_deduced_from [ odd(X) ].
odd(7): not odd(X)       may_be_deduced_from [ not odd(-X) ].
odd(8): not odd(-X)      may_be_deduced_from [ not odd(X) ].

odd(9): odd(X+Y)         may_be_deduced_from [ odd(X), not odd(Y) ].
odd(10): odd(X+Y)        may_be_deduced_from [ not odd(X), odd(Y) ].
odd(11): not odd(X+Y)    may_be_deduced_from [ not odd(X), not odd(Y) ].
odd(12): not odd(X+Y)    may_be_deduced_from [ odd(X), odd(Y) ].

odd(13): odd(X-Y)        may_be_deduced_from [ odd(X), not odd(Y) ].
odd(14): odd(X-Y)        may_be_deduced_from [ not odd(X), odd(Y) ].
odd(15): not odd(X-Y)    may_be_deduced_from [ not odd(X), not odd(Y) ].
odd(16): not odd(X-Y)    may_be_deduced_from [ odd(X), odd(Y) ].

odd(17): odd(X*Y)        may_be_deduced_from [ odd(X), odd(Y) ].
odd(18): not odd(X*Y)    may_be_deduced_from [ not odd(X) ].
odd(19): not odd(X*Y)    may_be_deduced_from [ not odd(Y) ].

odd(20): odd(sqr(X))     may_be_deduced_from [ odd(X) ].
odd(21): odd(X)          may_be_deduced_from [ odd(sqr(X)) ].
odd(22): not odd(sqr(X)) may_be_deduced_from [ not odd(X) ].
odd(23): not odd(X)      may_be_deduced_from [ not odd(sqr(X)) ].

odd(24): odd(abs(X))     may_be_deduced_from [ odd(X) ].
odd(25): odd(X)          may_be_deduced_from [ odd(abs(X)) ].
odd(26): not odd(abs(X)) may_be_deduced_from [ not odd(X) ].
odd(27): not odd(X)      may_be_deduced_from [ not odd(abs(X)) ].


/*** EXP: exponentiation operator properties - for non-negative exponents ***/

exp(1):  X**0     may_be_replaced_by 1.
exp(2):  0**Y     may_be_replaced_by 0               if [ Y>=1 ].
exp(3):  1**Y     may_be_replaced_by 1               if [ Y>=0 ].

exp(4):  X**Y     & X*(X**(Y-1)) are_interchangeable if [ Y>0 ].
exp(5):  X**(Y+1) & X*(X**Y)     are_interchangeable if [ Y>=0 ].

exp(6):  (-X)**Y  may_be_replaced_by X**Y            if [ not odd(Y) ].
exp(7):  (-X)**Y  may_be_replaced_by -(X**Y)         if [ odd(Y) ].

exp(8):  X**1     may_be_replaced_by X.
exp(9):  X**2     may_be_replaced_by X*X.
exp(10): X**3     may_be_replaced_by X*X*X.
exp(11): X**4     may_be_replaced_by X*X*X*X.

exp(12): X**Y>=0  may_be_deduced_from [ X>=0, Y>=0 ].
exp(13): X**Y>=0  may_be_deduced_from [ not odd(Y) ].

exp(14): X**Y<=0  may_be_deduced_from [ X<=0, odd(Y) ].

exp(15): X**Y>0   may_be_deduced_from [ X>0 ].
exp(16): X**Y>0   may_be_deduced_from [ X<0, not odd(Y) ].

exp(17): X**Y<0   may_be_deduced_from [ X<0, odd(Y) ].
