% -----------------------------------------------------------------------------
%  (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.
% 
% =============================================================================


/*** SIMPLIFY(in X,out Y) -- simplify expression X to get Y ***/

/* Simplify expressions of the form 'not(A)' where possible */

/* NOT1 */   simplify(not(true),false) :- !.
/* NOT2 */   simplify(not(false),true) :- !.
/* NOT3 */   simplify(not(not(X)),A) :- simplify(X,A), !.
/* NOT4 */   simplify((not X),B) :-
                simplify(X,A),
                (
                   A=true,
                   B=false
                ;
                   A=false,
                   B=true
                ;
                   B=(not A)
                ), !.


/* Simplify expressions of the form 'A and B' where possible */

/* AND1 */   simplify(false and _X,false) :- !.
/* AND2 */   simplify(_X and false,false) :- !.
/* AND3 */   simplify(X and (not X),false) :- !.
/* AND4 */   simplify((not X) and X,false) :- !.
/* AND5 */   simplify(true and X,Y) :- simplify(X,Y), !.
/* AND6 */   simplify(X and true,Y) :- simplify(X,Y), !.
/* AND7 */   simplify(X and X,Y) :- simplify(X,Y), !.
/* AND8 */   simplify(X and Y,Z) :-
                simplify(X,A),
                (
                   A=true,
                   simplify(Y,Z)
                ;
                   A=false,
                   Z=A
                ;
                   simplify(Y,B),
                   (
                      (
                         B=true,
                         Z=A
                      ;
                         B=false,
                         Z=B
                      )
                   ;
                      (
                         A=(not B)
                      ;
                         A=(not Y)
                      ;
                         B=(not A)
                      ;
                         B=(not X)
                      ),
                      Z=false
                   ;
                      A=B,
                      Z=A
                   ;
                      Z=(A and B)
                   )
                ), !.


/* Simplify expressions of the form 'A or B' where possible. */

/* OR1 */    simplify(true or _X,true) :- !.
/* OR2 */    simplify(_X or true,true) :- !.
/* OR3 */    simplify(X or (not X),true) :- !.
/* OR4 */    simplify((not X) or X,true) :- !.
/* OR5 */    simplify(false or X,Y) :- simplify(X,Y), !.
/* OR6 */    simplify(X or false,Y) :- simplify(X,Y), !.
/* OR7 */    simplify(X or X,Y) :- simplify(X,Y), !.
/* OR8 */    simplify(X or Y,Z) :-
                simplify(X,A),
                (
                   A=true,
                   Z=A
                ;
                   A=false,
                   simplify(Y,Z)
                ;
                   simplify(Y,B),
                   (
                      B=true,
                      Z=B
                   ;
                      B=false,
                      Z=A
                   ;
                      (
                         A=(not B)
                      ;
                         A=(not Y)
                      ;
                         B=(not A)
                      ;
                         B=(not X)
                      ),
                      Z=true
                   ;
                      A=B,
                      Z=A
                   ;
                      Z=(A or B)
                   )
                ), !.


/* Simplify expressions of the form 'A -> B' where possible */

/* IMP1 */   simplify(false->_X,true) :- !.
/* IMP2 */   simplify(_X->true,true) :- !.
/* IMP3 */   simplify(X->X,true) :- !.
/* IMP4 */   simplify(true->X,Y) :- simplify(X,Y), !.
/* IMP5 */   simplify(X->false,A) :- simplify((not X),A), !.
/* IMP6 */   simplify(X->(not X),Y) :- simplify((not X),Y), !.
/* IMP7 */   simplify((not X)->X,Y) :- simplify(X,Y), !.
/* IMP8 */   simplify(X -> (Y -> Z),A) :- simplify((X and Y) -> Z,A), !.
/* IMP9 */   simplify(X->Y,Z) :-
                simplify(X,A),
                (
                   A=true,
                   simplify(Y,Z)
                ;
                   A=false,
                   Z=true
                ;
                   simplify(Y,B),
                   (
                      B=true,
                      Z=B
                   ;
                      B=false,
                      simplify((not X),Z)
                   ;
                      (
                         A=(not B)
                      ;
                         A=(not Y)
                      ;
                         B=(not A)
                      ;
                         B=(not X)
                      ),
                      Z=B
                   ;
                      A=B,
                      Z=true
                   ;
                      Z=(A->B)
                   )
                ), !.


/* Simplify expressions of the form 'A <-> B' where possible */

/* EQV1  */  simplify(X<->X,true) :- !.
/* EQV2  */  simplify(X<->(not X),false) :- !.
/* EQV3  */  simplify((not X)<->X,false) :- !.
/* EQV4  */  simplify(X<->true,Y) :- simplify(X,Y), !.
/* EQV5  */  simplify(true<->X,Y) :- simplify(X,Y), !.
/* EQV6  */  simplify(X<->false,Y) :- simplify((not X),Y), !.
/* EQV7  */  simplify(false<->X,Y) :- simplify((not X),Y), !.
/* EQV8  */  simplify(X <-> (Y <-> Z),B) :-
                simplify(X <-> Y,A),
                simplify(A <-> Z,B), !.
/* EQV9  */  simplify(X <-> Y <-> Z,B) :-
                simplify(Y <-> Z,A),
                (Y <-> Z)\=A,
                simplify(X <-> A,B), !.
/* EQV10 */  simplify(X <-> Y <-> Z,B) :-
                simplify(X <-> Z,A),
                (X <-> Z)\=A,
                simplify(A <-> Y,B), !.
/* EQV11 */  simplify(X<->Y,Z) :-
                simplify(X,A),
                (
                   A=true,
                   simplify(Y,Z)
                ;
                   A=false,
                   simplify((not Y),Z)
                ;
                   simplify(Y,B),
                   (
                      B=true,
                      Z=A
                   ;
                      B=false,
                      simplify((not X),Z)
                   ;
                      (
                         A=(not B)
                      ;
                         A=(not Y)
                      ;
                         B=(not A)
                      ;
                         B=(not X)
                      ),
                      Z=false
                   ;
                      A=B,
                      Z=true
                   ;
                      Z=(A<->B)
                   )
                ), !.


/* Simplify 'for_all( )' exprs. where possible */

/* ALL3 */   simplify(for_all(V:T,X),NEW) :-
                find_core_type(T, CT),
                (
                   var_const(V, CT, _),
                   STATE = dont_retract
                ;
                   asserta(var_const(V, CT, temp)),
                   STATE = retract
                ),
                simplify(X,Y),
                (
                   Y = true,
                   NEW = true
                ;
                   Y = false,
                   NEW = false
                ;
                   NEW = (for_all(V:T, Y))
                ),
                !,
                (
                   STATE = dont_retract
                ;
                   retract(var_const(V, CT, temp))
                ),
                !.

/* Simplify 'for_some( )' exprs. where possible */

/* EXI3 */   simplify(for_some(V:T,X),NEW) :-
                find_core_type(T, CT),
                (
                   var_const(V, CT, _),
                   STATE = dont_retract
                ;
                   asserta(var_const(V, CT, temp)),
                   STATE = retract
                ),
                simplify(X,Y),
                (
                   Y = true,
                   NEW = true
                ;
                   Y = false,
                   NEW = false
                ;
                   NEW = (for_some(V:T, Y))
                ),
                !,
                (
                   STATE = dont_retract
                ;
                   retract(var_const(V, CT, temp))
                ),
                !.


/* Simplify set-type expressions where possible */

/* SET1 */   simplify(A \/ B, S) :-
                !,
                set_simplify(A \/ B, S),
                !.
/* SET2 */   simplify(A \ B, S) :-
                !,
                set_simplify(A \ B, S),
                !.
/* SET3 */   simplify(A /\ B, S) :-
                !,
                set_simplify(A /\ B, S),
                !.
/* SET4 */   simplify((set A), S) :-
                !,
                set_simplify((set A), S),
                !.
/* SET5 */   simplify(A subset_of B, S) :-
                !,
                set_simplify(A subset_of B, S),
                !.
/* SET6 */   simplify(A strict_subset_of B, S) :-
                !,
                set_simplify(A strict_subset_of B, S),
                !.
/* SET7 */   simplify(A in B, S) :-
                !,
                set_simplify(A in B, S),
                !.
/* SET8 */   simplify(A not_in B, S) :-
                !,
                set_simplify(A not_in B, S),
                !.


/* Simplify atomic formulae where possible */

/* REL1 */   simplify(X=Y,Z) :-
                checktype(X,T),
                (
                   type(T, set(_)),
                   !,
                   set_simplify(X=Y,Z)
                ;
                   type(T,enumerated),
                   !,
                   enumerated_simplify(X=Y,Z)
                ;
                   simplify(X,A),
                   simplify(Y,B),
                   (
                      A=B,
                      Z=true
                   ;
                      signed_integer(A),
                      (                                         /* CFR050 */
                         signed_integer(B),                     /* CFR050 */
                         A\=B,                                  /* CFR050 */
                         Z=false                                /* CFR050 */
                      ;                                         /* CFR050 */
                         B=P+Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(A-P,R),                    /* CFR050 */
                            Z=(Q=R)                             /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(A-Q,R),                    /* CFR050 */
                            Z=(P=R)                             /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         B=P-Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(P-A,R),                    /* CFR050 */
                            Z=(Q=R)                             /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(A+Q,R),                    /* CFR050 */
                            Z=(P=R)                             /* CFR050 */
                         )                                      /* CFR050 */
                      )                                         /* CFR050 */
                   ;                                            /* CFR050 */
                      signed_integer(B),                        /* CFR050 */
                      (                                         /* CFR050 */
                         A=P+Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(B-P,R),                    /* CFR050 */
                            Z=(Q=R)                             /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(B-Q,R),                    /* CFR050 */
                            Z=(P=R)                             /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         A=P-Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(P-B,R),                    /* CFR050 */
                            Z=(Q=R)                             /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(B+Q,R),                    /* CFR050 */
                            Z=(P=R)                             /* CFR050 */
                         )                                      /* CFR050 */
                      )                                         /* CFR050 */
                   ;                                            /* CFR050 */
                      Z=(A=B)                                   /* CFR050 */
                   )                                            /* CFR050 */
                ), !.

/* REL2 */   simplify(X>Y,Z) :-
                checktype(X,T),
                (
                   type(T,enumerated),
                   !,
                   enumerated_simplify(X>Y,Z)
                ;
                   simplify(X,A),
                   simplify(Y,B),
                   (
                      signed_integer(A),
                      (                                         /* CFR050 */
                         signed_integer(B),                     /* CFR050 */
                         (                                      /* CFR050 */
                            B less_than A,                      /* CFR050 */
                            Z=true                              /* CFR050 */
                         ;                                      /* CFR050 */
                            (                                   /* CFR050 */
                               A=B                              /* CFR050 */
                            ;                                   /* CFR050 */
                               A less_than B                    /* CFR050 */
                            ),                                  /* CFR050 */
                            Z=false                             /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         B=P+Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(A-P,R),                    /* CFR050 */
                            Z=(Q<R)                             /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(A-Q,R),                    /* CFR050 */
                            Z=(P<R)                             /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         B=P-Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(P-A,R),                    /* CFR050 */
                            Z=(Q>R)                             /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(A+Q,R),                    /* CFR050 */
                            Z=(P<R)                             /* CFR050 */
                         )                                      /* CFR050 */
                      )                                         /* CFR050 */
                   ;                                            /* CFR050 */
                      signed_integer(B),                        /* CFR050 */
                      (                                         /* CFR050 */
                         A=P+Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(B-P,R),                    /* CFR050 */
                            Z=(Q>R)                             /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(B-Q,R),                    /* CFR050 */
                            Z=(P>R)                             /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         A=P-Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(P-B,R),                    /* CFR050 */
                            Z=(Q<R)                             /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(B+Q,R),                    /* CFR050 */
                            Z=(P>R)                             /* CFR050 */
                         )                                      /* CFR050 */
                      )                                         /* CFR050 */
                   ;                                            /* CFR050 */
                      Z=(A>B)                                   /* CFR050 */
                   )                                            /* CFR050 */
                ), !.

/* REL3 */   simplify(X<Y,Z) :-
                checktype(X,T),
                (
                   type(T,enumerated),
                   !,
                   enumerated_simplify(X<Y,Z)
                ;
                   simplify(X,A),
                   simplify(Y,B),
                   (
                      signed_integer(A),
                      (                                         /* CFR050 */
                         signed_integer(B),                     /* CFR050 */
                         (                                      /* CFR050 */
                            A less_than B,                      /* CFR050 */
                            Z=true                              /* CFR050 */
                         ;                                      /* CFR050 */
                            (                                   /* CFR050 */
                               A=B                              /* CFR050 */
                            ;                                   /* CFR050 */
                               B less_than A                    /* CFR050 */
                            ),                                  /* CFR050 */
                            Z=false                             /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         B=P+Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(A-P,R),                    /* CFR050 */
                            Z=(Q>R)                             /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(A-Q,R),                    /* CFR050 */
                            Z=(P>R)                             /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         B=P-Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(P-A,R),                    /* CFR050 */
                            Z=(Q<R)                             /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(A+Q,R),                    /* CFR050 */
                            Z=(P>R)                             /* CFR050 */
                         )                                      /* CFR050 */
                      )                                         /* CFR050 */
                   ;                                            /* CFR050 */
                      signed_integer(B),                        /* CFR050 */
                      (                                         /* CFR050 */
                         A=P+Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(B-P,R),                    /* CFR050 */
                            Z=(Q<R)                             /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(B-Q,R),                    /* CFR050 */
                            Z=(P<R)                             /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         A=P-Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(P-B,R),                    /* CFR050 */
                            Z=(Q>R)                             /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(B+Q,R),                    /* CFR050 */
                            Z=(P<R)                             /* CFR050 */
                         )                                      /* CFR050 */
                      )                                         /* CFR050 */
                   ;                                            /* CFR050 */
                      Z=(A<B)                                   /* CFR050 */
                   )                                            /* CFR050 */
                ), !.

/* REL4 */   simplify(X<>Y,Z) :-
                checktype(X,T),
                (
                   type(T, set(_)),
                   !,
                   set_simplify(X<>Y,Z)
                ;
                   type(T,enumerated),
                   !,
                   enumerated_simplify(X<>Y,Z)
                ;
                   simplify(X,A),
                   simplify(Y,B),
                   (
                      A=B,
                      Z=false
                   ;
                      signed_integer(A),
                      (                                         /* CFR050 */
                         signed_integer(B),                     /* CFR050 */
                         (                                      /* CFR050 */
                            A\=B,                               /* CFR050 */
                            Z=true                              /* CFR050 */
                         ;                                      /* CFR050 */
                            A=B,                                /* CFR050 */
                            Z=true                              /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         B=P+Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(A-P,R),                    /* CFR050 */
                            Z=(Q<>R)                            /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(A-Q,R),                    /* CFR050 */
                            Z=(P<>R)                            /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         B=P-Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(P-A,R),                    /* CFR050 */
                            Z=(Q<>R)                            /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(A+Q,R),                    /* CFR050 */
                            Z=(P<>R)                            /* CFR050 */
                         )                                      /* CFR050 */
                      )                                         /* CFR050 */
                   ;                                            /* CFR050 */
                      signed_integer(B),                        /* CFR050 */
                      (                                         /* CFR050 */
                         A=P+Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(B-P,R),                    /* CFR050 */
                            Z=(Q<>R)                            /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(B-Q,R),                    /* CFR050 */
                            Z=(P<>R)                            /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         A=P-Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(P-B,R),                    /* CFR050 */
                            Z=(Q<>R)                            /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(B+Q,R),                    /* CFR050 */
                            Z=(P<>R)                            /* CFR050 */
                         )                                      /* CFR050 */
                      )                                         /* CFR050 */
                   ;                                            /* CFR050 */
                      Z=(A<>B)                                  /* CFR050 */
                   )                                            /* CFR050 */
                ), !.


/* REL5 */   simplify(X<=Y,Z) :-
                checktype(X,T),
                (
                   type(T,enumerated),
                   !,
                   enumerated_simplify(X<=Y,Z)
                ;
                   simplify(X,A),
                   simplify(Y,B),
                   (
                      A=B,                                      /* CFR050 */
                      Z=true                                    /* CFR050 */
                   ;                                            /* CFR050 */
                      signed_integer(A),                        /* CFR050 */
                      (                                         /* CFR050 */
                         signed_integer(B),                     /* CFR050 */
                         (                                      /* CFR050 */
                            A less_than B,                      /* CFR050 */
                            Z=true                              /* CFR050 */
                         ;                                      /* CFR050 */
                            B less_than A,                      /* CFR050 */
                            Z=false                             /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         B=P+Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(A-P,R),                    /* CFR050 */
                            Z=(R<=Q)                            /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(A-Q,R),                    /* CFR050 */
                            Z=(R<=P)                            /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         B=P-Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(P-A,R),                    /* CFR050 */
                            Z=(Q<=R)                            /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(A+Q,R),                    /* CFR050 */
                            Z=(R<=P)                            /* CFR050 */
                         )                                      /* CFR050 */
                      )                                         /* CFR050 */
                   ;                                            /* CFR050 */
                      signed_integer(B),                        /* CFR050 */
                      (                                         /* CFR050 */
                         A=P+Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(B-P,R),                    /* CFR050 */
                            Z=(Q<=R)                            /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(B-Q,R),                    /* CFR050 */
                            Z=(P<=R)                            /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         A=P-Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(P-B,R),                    /* CFR050 */
                            Z=(R<=Q)                            /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(B+Q,R),                    /* CFR050 */
                            Z=(P<=R)                            /* CFR050 */
                         )                                      /* CFR050 */
                      )                                         /* CFR050 */
                   ;                                            /* CFR050 */
                      Z=(A<=B)                                  /* CFR050 */
                   )                                            /* CFR050 */
                ), !.

/* REL6 */   simplify(X>=Y,Z) :-
                checktype(X,T),
                (
                   type(T,enumerated),
                   !,
                   enumerated_simplify(X>=Y,Z)
                ;
                   simplify(X,A),
                   simplify(Y,B),
                   (
                      A=B,
                      Z=true
                   ;
                      signed_integer(A),
                      (                                         /* CFR050 */
                         signed_integer(B),                     /* CFR050 */
                         (                                      /* CFR050 */
                            B less_than A,                      /* CFR050 */
                            Z=true                              /* CFR050 */
                         ;                                      /* CFR050 */
                            A less_than B,                      /* CFR050 */
                            Z=false                             /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         B=P+Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(A-P,R),                    /* CFR050 */
                            Z=(Q<=R)                            /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(A-Q,R),                    /* CFR050 */
                            Z=(P<=R)                            /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         B=P-Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(P-A,R),                    /* CFR050 */
                            Z=(Q>=R)                            /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(A+Q,R),                    /* CFR050 */
                            Z=(P<=R)                            /* CFR050 */
                         )                                      /* CFR050 */
                      )                                         /* CFR050 */
                   ;                                            /* CFR050 */
                      signed_integer(B),                        /* CFR050 */
                      (                                         /* CFR050 */
                         A=P+Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(B-P,R),                    /* CFR050 */
                            Z=(Q>=R)                            /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(B-Q,R),                    /* CFR050 */
                            Z=(P>=R)                            /* CFR050 */
                         )                                      /* CFR050 */
                      ;                                         /* CFR050 */
                         A=P-Q,                                 /* CFR050 */
                         (                                      /* CFR050 */
                            signed_integer(P),                  /* CFR050 */
                            simplify(P-B,R),                    /* CFR050 */
                            Z=(Q<=R)                            /* CFR050 */
                         ;                                      /* CFR050 */
                            signed_integer(Q),                  /* CFR050 */
                            simplify(B+Q,R),                    /* CFR050 */
                            Z=(P>=R)                            /* CFR050 */
                         )                                      /* CFR050 */
                      )                                         /* CFR050 */
                   ;                                            /* CFR050 */
                      Z=(A>=B)                                  /* CFR050 */
                   )                                            /* CFR050 */
                ), !.


/* ODD */    simplify(odd(X), ODD) :-
                simplify(X, NEWX),
                (
                   signed_integer(NEWX),
                   X1 iss NEWX*NEWX,
                   (
                      X2 iss (X1 div 2)*2,
                      X1 =:= X2,
                      ODD=false
                   ;
                      X2 iss (X1 div 2)*2,
                      X1 =\= X2,
                      ODD=true
                   )
                ;
                   NEWX=A*B,
                   simplify(odd(A), TFA),
                   simplify(odd(B), TFB),
                   (
                      (
                         TFA = false
                      ;
                         TFB = false
                      ),
                      ODD = false
                   ;
                      TFA = true,
                      ODD = TFB
                   ;
                      TFB = true,
                      ODD = TFA
                   )
                ;
                   (
                      NEWX=A+B
                   ;
                      NEWX=A-B
                   ),
                   simplify(odd(A), TFA),
                   simplify(odd(B), TFB),
                   (
                      TFA = true,
                      (
                         TFB = true,
                         ODD = false
                      ;
                         TFB = false,
                         ODD = true
                      ;
                         ODD = (not TFB)
                      )
                   ;
                      TFA = false,
                      ODD = TFB
                   ;
                      TFB = true,
                      ODD = (not TFA)
                   ;
                      TFB = false,
                      ODD = TFA
                   )
                ;
                   NEWX = (-A),
                   simplify(odd(A), ODD)
                ;
                   ODD = odd(NEWX)
                ), !.

/* SQR1*/    simplify(sqr(abs(X)), SQR) :- simplify(X*X, SQR), !.
/* SQR2*/    simplify(sqr(X), SQR) :- simplify(X*X, SQR), !.

/* ABS */    simplify(abs(X), ABS) :-
                simplify(X, NEWX),
                (
                   signed_integer(NEWX),
                   (
                      NEWX >= 0,
                      ABS = NEWX
                   ;
                      NEWX < 0,
                      ABS is -NEWX
                   )
                ;
                   NEWX = A*A,
                   ABS = NEWX
                ;
                   NEWX = A*B,
                   simplify(abs(A), ABSA),
                   simplify(abs(B), ABSB),
                   ABS = ABSA*ABSB
                ;
                   NEWX = abs(_EXPR),
                   ABS = NEWX
                ;
                   ABS = abs(NEWX)
                ), !.


/* Simplify array, record & sequence type objects if possible */

/* ARR */    simplify(X, Y) :- array_simplify(X, Y), !.
/* REC */    simplify(X, Y) :- record_simplify(X, Y), !.
/* SEQ */    simplify(X, Y) :- sequence_simplify(X, Y), !.
/* ENU1 */   simplify(succ(X), Y) :- enumerated_simplify(succ(X), Y), !.
/* ENU2 */   simplify(pred(X), Y) :- enumerated_simplify(pred(X), Y), !.

/* Final catch-all */

/* EVAL */   simplify(X,Y) :- evaluate(X,Y), !.


/*** EVALUATE(in X,out Y) -- evaluate (non-boolean) X to get Y ***/

/* EVAL_BASE1 */ evaluate(X,X) :-
                    (
                       signed_integer(X)
                    ;
                       X=true
                    ;
                       X=false
                    ), !.
/* EVAL_BASE2 */ evaluate(X,Y) :-
                    integer(X), X<0,
                    Y iss X, !.

/* UMIN1 */  evaluate(-(-X),A) :- simplify(X,A), !.
/* UMIN2 */  evaluate(-X,A) :-
                simplify(X,B),
                (
                   signed_integer(B),
                   A iss -B
                ;
                   A=(-B)
                ), !.

/* UPLUS */  evaluate(+X, A) :- simplify(X, A), !.              /* CFR039 */

/*SPECIAL*/  evaluate(X+N-N,Y) :- simplify(X,Y), !.
             evaluate(X-N+N,Y) :- simplify(X,Y), !.

/* PLUS  */  evaluate(X+Y,Z) :-
                simplify(X,A),
                simplify(Y,B),
                (
                   signed_integer(A),
                   signed_integer(B),
                   Z iss A+B
                ;
                   A=0,
                   Z=B
                ;
                   B=0,
                   Z=A
                ;
                   Z=A+B
                ), !.

/* MINUS */  evaluate(X-Y,Z) :-
                simplify(X,A),
                simplify(Y,B),
                (
                   signed_integer(A),
                   signed_integer(B),
                   Z iss A-B
                ;
                   B=0,
                   Z=A
                ;
                   A=0,
                   simplify(-Y,Z)
                ;
                   Z=A-B
                ), !.

/* MULT  */  evaluate(X*Y,Z) :-
                simplify(X,A),
                simplify(Y,B),
                (
                   signed_integer(A),
                   signed_integer(B),
                   Z iss A*B
                ;
                   (
                      A=0
                   ;
                      B=0
                   ),
                   Z=0
                ;
                   A=1,
                   Z=B
                ;
                   B=1,
                   Z=A
                ;
                   Z=A*B
                ), !.

/* DIV   */  evaluate(X div Y,Z) :-
                simplify(X,A),
                simplify(Y,B),
                (
                   signed_integer(A),
                   signed_integer(B),
                   B\=0,
                   Z iss A div B
                ;
                   B=1,
                   Z=A
                ;
                   Z=A div B
                ), !.

/*  /    */  evaluate(X / Y,Z) :-                               /*1.4*/
                simplify(X,A),                                  /*1.4*/
                simplify(Y,B),                                  /*1.4*/
                (                                               /*1.4*/
                   signed_integer(A),                           /*1.4*/
                   signed_integer(B),                           /*1.4*/
                   B\=0,                                        /*1.4*/
                   Z iss A div B,                               /*1.4*/
                   A =:= Z * B                                  /*1.4*/
                ;                                               /*1.4*/
                   B=1,                                         /*1.4*/
                   Z=A                                          /*1.4*/
                ;                                               /*1.4*/
                   Z=A / B                                      /*1.4*/
                ), !.                                           /*1.4*/

/* MOD   */  evaluate(X mod Y,A mod B) :-
                simplify(X,A),
                simplify(Y,B),
                !.   /* TEMPORARILY */
/* OLD MOD STUFF:
                (
                   signed_integer(A),
                   signed_integer(B),
                   B\=0,
                   Z iss A mod B
                ;
                   B=1,
                   Z=0
                ;
                   Z=(A mod B)
                ), !.   DELETED */

/*  EXP  */  evaluate(X**Y,Z) :-                                /* CFR038 */
                simplify(X,A),                                  /* CFR038 */
                simplify(Y,B),                                  /* CFR038 */
                (                                               /* CFR038 */
                   signed_integer(A),                           /* CFR038 */
                   signed_integer(B),                           /* CFR038 */
                   Z iss A**B                                   /* CFR038 */
                ;                                               /* CFR038 */
                   B=0,                                         /* CFR038 */
                   Z=1                                          /* CFR038 */
                ;                                               /* CFR038 */
                   B=1,                                         /* CFR038 */
                   Z=A                                          /* CFR038 */
                ;                                               /* CFR038 */
                   B=2,                                         /* CFR038 */
                   Z=A*A                                        /* CFR038 */
                ;                                               /* CFR038 */
                   Z=A**B                                       /* CFR038 */
                ), !.                                           /* CFR038 */

/* EVAL_VAL */     evaluate(X,Y) :- val(X,Y), !.

/* FUNC_SPLIT */   evaluate(X,Z) :-
                      (\+ atomic(X)),
                      X=..[H|T],
                      eval_list(T,U),
                      Z=..[H|U],
                      !.


/*** EVAL_LIST(in XL,out YL) -- simplify/evaluate each element
        of XL to get YL ***/

/* EVL1 */   eval_list([],[]) :- !.
/* EVL2 */   eval_list([H1|T1],[H2|T2]) :-
                simplify(H1,H2),
                eval_list(T1,T2),
                !.


/*** VAL(in X,out Y) -- additional simplification rules slot in here ***/

val(X,X) :- atomic(X), !.


/*** SIGNED_INTEGER(I) -- is I an integer (with an optional -)? ***/

signed_integer(I) :-
        (
           integer(I), I>=0
        ;
           I=(-I1), integer(I1), I1>0
        ).


/*** X LESS_THAN Y -- compare two signed_integers ***/

-X less_than -Y :- integer(X), X>0, integer(Y), Y>0, Y less_than X.
-X less_than Y :- integer(X), X>0, integer(Y), Y>=0.
X less_than Y :- integer(X), X>=0, integer(Y), Y>X.
%###############################################################################
%END-OF-FILE
